diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-08-14 11:38:45 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-08-14 17:16:47 +0000 |
commit | 3a97ca8dd9b96b599ae2d33e40df0dd2f7ea5859 (patch) | |
tree | 43cc572ba067417c7341db81f71ae7cc6e0fcc3e /chromium/cc | |
parent | f61ab1ac7f855cd281809255c0aedbb1895e1823 (diff) | |
download | qtwebengine-chromium-3a97ca8dd9b96b599ae2d33e40df0dd2f7ea5859.tar.gz |
BASELINE: Update chromium to 45.0.2454.40
Change-Id: Id2121d9f11a8fc633677236c65a3e41feef589e4
Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'chromium/cc')
515 files changed, 24652 insertions, 27473 deletions
diff --git a/chromium/cc/BUILD.gn b/chromium/cc/BUILD.gn index 7001440e61a..5cd45c2749c 100644 --- a/chromium/cc/BUILD.gn +++ b/chromium/cc/BUILD.gn @@ -13,10 +13,18 @@ component("cc") { "animation/animation_delegate.h", "animation/animation_events.cc", "animation/animation_events.h", + "animation/animation_host.cc", + "animation/animation_host.h", "animation/animation_id_provider.cc", "animation/animation_id_provider.h", + "animation/animation_player.cc", + "animation/animation_player.h", "animation/animation_registrar.cc", "animation/animation_registrar.h", + "animation/animation_timeline.cc", + "animation/animation_timeline.h", + "animation/element_animations.cc", + "animation/element_animations.h", "animation/keyframed_animation_curve.cc", "animation/keyframed_animation_curve.h", "animation/layer_animation_controller.cc", @@ -82,6 +90,8 @@ component("cc") { "debug/rendering_stats_instrumentation.cc", "debug/rendering_stats_instrumentation.h", "debug/ring_buffer.h", + "debug/traced_display_item_list.cc", + "debug/traced_display_item_list.h", "debug/traced_picture.cc", "debug/traced_picture.h", "debug/traced_value.cc", @@ -104,11 +114,7 @@ component("cc") { "input/top_controls_manager.h", "input/top_controls_manager_client.h", "layers/append_quads_data.h", - "layers/content_layer.cc", - "layers/content_layer.h", "layers/content_layer_client.h", - "layers/contents_scaling_layer.cc", - "layers/contents_scaling_layer.h", "layers/delegated_frame_provider.cc", "layers/delegated_frame_provider.h", "layers/delegated_frame_resource_collection.cc", @@ -122,8 +128,6 @@ component("cc") { "layers/heads_up_display_layer.h", "layers/heads_up_display_layer_impl.cc", "layers/heads_up_display_layer_impl.h", - "layers/image_layer.cc", - "layers/image_layer.h", "layers/io_surface_layer.cc", "layers/io_surface_layer.h", "layers/io_surface_layer_impl.cc", @@ -182,10 +186,6 @@ component("cc") { "layers/texture_layer_client.h", "layers/texture_layer_impl.cc", "layers/texture_layer_impl.h", - "layers/tiled_layer.cc", - "layers/tiled_layer.h", - "layers/tiled_layer_impl.cc", - "layers/tiled_layer_impl.h", "layers/ui_resource_layer.cc", "layers/ui_resource_layer.h", "layers/ui_resource_layer_impl.cc", @@ -282,7 +282,6 @@ component("cc") { "output/texture_mailbox_deleter.h", "output/viewport_selection_bound.cc", "output/viewport_selection_bound.h", - "output/vsync_parameter_observer.h", "playback/clip_display_item.cc", "playback/clip_display_item.h", "playback/clip_path_display_item.cc", @@ -293,6 +292,8 @@ component("cc") { "playback/display_item.h", "playback/display_item_list.cc", "playback/display_item_list.h", + "playback/display_item_list_settings.cc", + "playback/display_item_list_settings.h", "playback/display_list_raster_source.cc", "playback/display_list_raster_source.h", "playback/display_list_recording_source.cc", @@ -332,8 +333,6 @@ component("cc") { "quads/io_surface_draw_quad.h", "quads/largest_draw_quad.cc", "quads/largest_draw_quad.h", - "quads/list_container.cc", - "quads/list_container.h", "quads/picture_draw_quad.cc", "quads/picture_draw_quad.h", "quads/render_pass.cc", @@ -382,28 +381,10 @@ component("cc") { "raster/tile_task_worker_pool.h", "raster/zero_copy_tile_task_worker_pool.cc", "raster/zero_copy_tile_task_worker_pool.h", - "resources/bitmap_content_layer_updater.cc", - "resources/bitmap_content_layer_updater.h", - "resources/bitmap_skpicture_content_layer_updater.cc", - "resources/bitmap_skpicture_content_layer_updater.h", - "resources/content_layer_updater.cc", - "resources/content_layer_updater.h", - "resources/image_layer_updater.cc", - "resources/image_layer_updater.h", - "resources/layer_painter.h", - "resources/layer_updater.cc", - "resources/layer_updater.h", "resources/memory_history.cc", "resources/memory_history.h", "resources/platform_color.h", - "resources/prioritized_resource.cc", - "resources/prioritized_resource.h", - "resources/prioritized_resource_manager.cc", - "resources/prioritized_resource_manager.h", - "resources/priority_calculator.cc", - "resources/priority_calculator.h", "resources/release_callback.h", - "resources/resource.cc", "resources/resource.h", "resources/resource_format.cc", "resources/resource_format.h", @@ -411,12 +392,6 @@ component("cc") { "resources/resource_pool.h", "resources/resource_provider.cc", "resources/resource_provider.h", - "resources/resource_update.cc", - "resources/resource_update.h", - "resources/resource_update_controller.cc", - "resources/resource_update_controller.h", - "resources/resource_update_queue.cc", - "resources/resource_update_queue.h", "resources/returned_resource.h", "resources/scoped_resource.cc", "resources/scoped_resource.h", @@ -429,12 +404,8 @@ component("cc") { "resources/single_release_callback.h", "resources/single_release_callback_impl.cc", "resources/single_release_callback_impl.h", - "resources/skpicture_content_layer_updater.cc", - "resources/skpicture_content_layer_updater.h", "resources/texture_mailbox.cc", "resources/texture_mailbox.h", - "resources/texture_uploader.cc", - "resources/texture_uploader.h", "resources/transferable_resource.cc", "resources/transferable_resource.h", "resources/ui_resource_bitmap.cc", @@ -446,7 +417,11 @@ component("cc") { "resources/video_resource_updater.h", "scheduler/begin_frame_source.cc", "scheduler/begin_frame_source.h", + "scheduler/begin_frame_tracker.cc", + "scheduler/begin_frame_tracker.h", "scheduler/commit_earlyout_reason.h", + "scheduler/compositor_timing_history.cc", + "scheduler/compositor_timing_history.h", "scheduler/delay_based_time_source.cc", "scheduler/delay_based_time_source.h", "scheduler/draw_result.h", @@ -459,8 +434,6 @@ component("cc") { "scheduler/video_frame_controller.h", "tiles/eviction_tile_priority_queue.cc", "tiles/eviction_tile_priority_queue.h", - "tiles/layer_tiling_data.cc", - "tiles/layer_tiling_data.h", "tiles/picture_layer_tiling.cc", "tiles/picture_layer_tiling.h", "tiles/picture_layer_tiling_set.cc", @@ -507,6 +480,7 @@ component("cc") { "trees/layer_tree_impl.h", "trees/layer_tree_settings.cc", "trees/layer_tree_settings.h", + "trees/mutator_host_client.h", "trees/occlusion.cc", "trees/occlusion.h", "trees/occlusion_tracker.cc", @@ -517,8 +491,6 @@ component("cc") { "trees/property_tree_builder.h", "trees/proxy.cc", "trees/proxy.h", - "trees/proxy_timing_history.cc", - "trees/proxy_timing_history.h", "trees/scoped_abort_remaining_swap_promises.h", "trees/single_thread_proxy.cc", "trees/single_thread_proxy.h", @@ -530,8 +502,12 @@ component("cc") { "trees/tree_synchronizer.h", ] - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + if (target_cpu == "x86" || target_cpu == "x64") { + sources += [ + "raster/texture_compressor_etc1_sse.cc", + "raster/texture_compressor_etc1_sse.h", + ] + } public_deps = [ "//cc/base", @@ -540,7 +516,6 @@ component("cc") { deps = [ "//base", "//base/third_party/dynamic_annotations", - "//cc:cc_opts", "//cc/surfaces:surface_id", "//gpu", "//gpu/command_buffer/client:gles2_interface", @@ -558,51 +533,19 @@ component("cc") { } } -source_set("cc_opts") { - public_deps = [ - "//cc:cc_opts_sse", - ] -} - -source_set("cc_opts_sse") { - if (target_cpu == "x86" || target_cpu == "x64") { - deps = [ - "//base", - ] - - defines = [ "CC_IMPLEMENTATION=1" ] - - if (!is_debug && (is_win || is_android)) { - configs -= [ "//build/config/compiler:optimize" ] - configs += [ "//build/config/compiler:optimize_max" ] - } - - sources = [ - "raster/texture_compressor.h", - "raster/texture_compressor_etc1.h", - "raster/texture_compressor_etc1_sse.cc", - "raster/texture_compressor_etc1_sse.h", - ] - - cflags = [ "-msse2" ] - } -} - source_set("test_support") { testonly = true sources = [ "test/animation_test_common.cc", "test/animation_test_common.h", + "test/animation_timelines_test_common.cc", + "test/animation_timelines_test_common.h", "test/begin_frame_args_test.cc", "test/begin_frame_args_test.h", "test/failure_output_surface.cc", "test/failure_output_surface.h", - "test/fake_content_layer.cc", - "test/fake_content_layer.h", "test/fake_content_layer_client.cc", "test/fake_content_layer_client.h", - "test/fake_content_layer_impl.cc", - "test/fake_content_layer_impl.h", "test/fake_delegated_renderer_layer.cc", "test/fake_delegated_renderer_layer.h", "test/fake_delegated_renderer_layer_impl.cc", @@ -640,6 +583,7 @@ source_set("test_support") { "test/fake_renderer_client.cc", "test/fake_renderer_client.h", "test/fake_rendering_stats_instrumentation.h", + "test/fake_resource_provider.h", "test/fake_scoped_ui_resource.cc", "test/fake_scoped_ui_resource.h", "test/fake_scrollbar.cc", @@ -654,7 +598,6 @@ source_set("test_support") { "test/fake_video_frame_provider.h", "test/geometry_test_utils.cc", "test/geometry_test_utils.h", - "test/impl_side_painting_settings.h", "test/layer_test_common.cc", "test/layer_test_common.h", "test/layer_tree_host_common_test.cc", @@ -706,8 +649,6 @@ source_set("test_support") { "test/test_image_factory.h", "test/test_in_process_context_provider.cc", "test/test_in_process_context_provider.h", - "test/test_now_source.cc", - "test/test_now_source.h", "test/test_occlusion_tracker.h", "test/test_shared_bitmap_manager.cc", "test/test_shared_bitmap_manager.h", @@ -719,12 +660,8 @@ source_set("test_support") { "test/test_tile_priorities.h", "test/test_web_graphics_context_3d.cc", "test/test_web_graphics_context_3d.h", - "test/tiled_layer_test_common.cc", - "test/tiled_layer_test_common.h", ] - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - include_dirs = [ ".", "test", @@ -760,7 +697,11 @@ source_set("test_support") { test("cc_unittests") { sources = [ + "animation/animation_host_unittest.cc", + "animation/animation_player_unittest.cc", + "animation/animation_timeline_unittest.cc", "animation/animation_unittest.cc", + "animation/element_animations_unittest.cc", "animation/keyframed_animation_curve_unittest.cc", "animation/layer_animation_controller_unittest.cc", "animation/scroll_offset_animation_curve_unittest.cc", @@ -768,17 +709,18 @@ test("cc_unittests") { "animation/scrollbar_animation_controller_thinning_unittest.cc", "animation/transform_operations_unittest.cc", "base/float_quad_unittest.cc", + "base/histograms_unittest.cc", + "base/list_container_unittest.cc", "base/math_util_unittest.cc", "base/region_unittest.cc", "base/rolling_time_delta_history_unittest.cc", "base/scoped_ptr_vector_unittest.cc", + "base/sidecar_list_container_unittest.cc", "base/simple_enclosed_region_unittest.cc", "base/tiling_data_unittest.cc", - "base/util_unittest.cc", "debug/frame_timing_tracker_unittest.cc", "debug/micro_benchmark_controller_unittest.cc", "input/top_controls_manager_unittest.cc", - "layers/contents_scaling_layer_unittest.cc", "layers/delegated_frame_provider_unittest.cc", "layers/delegated_frame_resource_collection_unittest.cc", "layers/delegated_renderer_layer_impl_unittest.cc", @@ -807,10 +749,9 @@ test("cc_unittests") { "layers/surface_layer_unittest.cc", "layers/texture_layer_impl_unittest.cc", "layers/texture_layer_unittest.cc", - "layers/tiled_layer_impl_unittest.cc", - "layers/tiled_layer_unittest.cc", "layers/ui_resource_layer_impl_unittest.cc", "layers/ui_resource_layer_unittest.cc", + "layers/video_frame_provider_client_impl_unittest.cc", "layers/video_layer_impl_unittest.cc", "output/begin_frame_args_unittest.cc", "output/delegating_renderer_unittest.cc", @@ -825,6 +766,7 @@ test("cc_unittests") { "output/software_renderer_unittest.cc", "output/texture_mailbox_deleter_unittest.cc", "playback/display_item_list_unittest.cc", + "playback/display_list_raster_source_unittest.cc", "playback/display_list_recording_source_unittest.cc", "playback/picture_pile_impl_unittest.cc", "playback/picture_pile_unittest.cc", @@ -832,20 +774,18 @@ test("cc_unittests") { "playback/pixel_ref_map_unittest.cc", "playback/recording_source_unittest.cc", "quads/draw_quad_unittest.cc", - "quads/list_container_unittest.cc", "quads/render_pass_unittest.cc", "raster/scoped_gpu_raster_unittest.cc", "raster/task_graph_runner_unittest.cc", "raster/texture_compressor_etc1_unittest.cc", "raster/tile_task_worker_pool_unittest.cc", "resources/platform_color_unittest.cc", - "resources/prioritized_resource_unittest.cc", + "resources/resource_pool_unittest.cc", "resources/resource_provider_unittest.cc", - "resources/resource_update_controller_unittest.cc", "resources/scoped_resource_unittest.cc", - "resources/texture_uploader_unittest.cc", "resources/video_resource_updater_unittest.cc", "scheduler/begin_frame_source_unittest.cc", + "scheduler/compositor_timing_history_unittest.cc", "scheduler/delay_based_time_source_unittest.cc", "scheduler/scheduler_state_machine_unittest.cc", "scheduler/scheduler_unittest.cc", @@ -864,13 +804,14 @@ test("cc_unittests") { "trees/layer_tree_host_pixeltest_masks.cc", "trees/layer_tree_host_pixeltest_readback.cc", "trees/layer_tree_host_pixeltest_synchronous.cc", + "trees/layer_tree_host_pixeltest_tiles.cc", "trees/layer_tree_host_unittest.cc", "trees/layer_tree_host_unittest_animation.cc", + "trees/layer_tree_host_unittest_animation_timelines.cc", "trees/layer_tree_host_unittest_context.cc", "trees/layer_tree_host_unittest_copyrequest.cc", "trees/layer_tree_host_unittest_damage.cc", "trees/layer_tree_host_unittest_delegated.cc", - "trees/layer_tree_host_unittest_no_message_loop.cc", "trees/layer_tree_host_unittest_occlusion.cc", "trees/layer_tree_host_unittest_picture.cc", "trees/layer_tree_host_unittest_proxy.cc", @@ -894,8 +835,6 @@ test("cc_unittests") { "test/run_all_unittests.cc", ] - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - deps = [ ":cc", ":test_support", @@ -922,6 +861,7 @@ test("cc_perftests") { "layers/layer_perftest.cc", "layers/picture_layer_impl_perftest.cc", "playback/picture_pile_impl_perftest.cc", + "quads/draw_quad_perftest.cc", "raster/task_graph_runner_perftest.cc", "raster/texture_compressor_perftest.cc", "raster/tile_task_worker_pool_perftest.cc", @@ -935,8 +875,6 @@ test("cc_perftests") { "trees/occlusion_tracker_perftest.cc", ] - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - deps = [ ":cc", ":test_support", @@ -956,6 +894,10 @@ test("cc_perftests") { "//ui/gfx/geometry", "//ui/gl", ] + + if (is_android) { + isolate_file = "cc_perftests.isolate" + } } # When adding support for isolates, please have a look at run-time dependencies # in the cc_unittests_run target in cc_tests.gyp. diff --git a/chromium/cc/OWNERS b/chromium/cc/OWNERS index b0bce1de929..6cc39e71a21 100644 --- a/chromium/cc/OWNERS +++ b/chromium/cc/OWNERS @@ -47,5 +47,6 @@ vollick@chromium.org vollick@chromium.org ajuma@chromium.org -per-file *.isolate=csharp@chromium.org per-file *.isolate=maruel@chromium.org +per-file *.isolate=tandrii@chromium.org +per-file *.isolate=vadimsh@chromium.org diff --git a/chromium/cc/PRESUBMIT.py b/chromium/cc/PRESUBMIT.py index fa15632fd45..c8506182da1 100644 --- a/chromium/cc/PRESUBMIT.py +++ b/chromium/cc/PRESUBMIT.py @@ -333,3 +333,31 @@ def GetPreferredTryMasters(project, change): 'linux_blink_rel': set(['defaulttests']), }, } + +def PostUploadHook(cl, change, output_api): + """git cl upload will call this hook after the issue is created/modified. + + This hook adds extra try bots list to the CL description in order to run + Blink tests in addition to CQ try bots. + """ + rietveld_obj = cl.RpcServer() + issue = cl.issue + description = rietveld_obj.get_description(issue) + if re.search(r'^CQ_INCLUDE_TRYBOTS=.*', description, re.M | re.I): + return [] + + bots = GetPreferredTryMasters(None, change) + bots_string_bits = [] + for master in bots.keys(): + bots_string_bits.append("%s:%s" % (master, ','.join(bots[master].keys()))) + + results = [] + new_description = description + new_description += '\nCQ_INCLUDE_TRYBOTS=%s' % ';'.join(bots_string_bits) + results.append(output_api.PresubmitNotifyResult( + 'Automatically added Perf trybots to run Blink tests on CQ.')) + + if new_description != description: + rietveld_obj.update_description(issue, new_description) + + return results diff --git a/chromium/cc/animation/animation.h b/chromium/cc/animation/animation.h index 2677fdeff58..153e4ef7752 100644 --- a/chromium/cc/animation/animation.h +++ b/chromium/cc/animation/animation.h @@ -151,6 +151,9 @@ class CC_EXPORT Animation { scoped_ptr<Animation> CloneAndInitialize(RunState initial_run_state) const; + void set_is_controlling_instance_for_test(bool is_controlling_instance) { + is_controlling_instance_ = is_controlling_instance; + } bool is_controlling_instance() const { return is_controlling_instance_; } void PushPropertiesTo(Animation* other) const; diff --git a/chromium/cc/animation/animation_host.cc b/chromium/cc/animation/animation_host.cc new file mode 100644 index 00000000000..e7f289fad9a --- /dev/null +++ b/chromium/cc/animation/animation_host.cc @@ -0,0 +1,511 @@ +// Copyright 2015 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/animation/animation_host.h" + +#include <algorithm> + +#include "cc/animation/animation_delegate.h" +#include "cc/animation/animation_id_provider.h" +#include "cc/animation/animation_player.h" +#include "cc/animation/animation_registrar.h" +#include "cc/animation/animation_timeline.h" +#include "cc/animation/element_animations.h" +#include "cc/animation/scroll_offset_animation_curve.h" +#include "cc/animation/timing_function.h" +#include "ui/gfx/geometry/box_f.h" +#include "ui/gfx/geometry/scroll_offset.h" + +namespace cc { + +class AnimationHost::ScrollOffsetAnimations : public AnimationDelegate { + public: + explicit ScrollOffsetAnimations(AnimationHost* animation_host) + : animation_host_(animation_host), + scroll_offset_timeline_( + AnimationTimeline::Create(AnimationIdProvider::NextTimelineId())), + scroll_offset_animation_player_( + AnimationPlayer::Create(AnimationIdProvider::NextPlayerId())) { + scroll_offset_timeline_->set_is_impl_only(true); + scroll_offset_animation_player_->set_layer_animation_delegate(this); + + animation_host_->AddAnimationTimeline(scroll_offset_timeline_.get()); + scroll_offset_timeline_->AttachPlayer( + scroll_offset_animation_player_.get()); + } + + ~ScrollOffsetAnimations() override { + scroll_offset_timeline_->DetachPlayer( + scroll_offset_animation_player_.get()); + animation_host_->RemoveAnimationTimeline(scroll_offset_timeline_.get()); + } + + void ScrollAnimationCreate(int layer_id, + const gfx::ScrollOffset& target_offset, + const gfx::ScrollOffset& current_offset) { + scoped_ptr<ScrollOffsetAnimationCurve> curve = + ScrollOffsetAnimationCurve::Create(target_offset, + EaseInOutTimingFunction::Create()); + curve->SetInitialValue(current_offset); + + scoped_ptr<Animation> animation = Animation::Create( + curve.Pass(), AnimationIdProvider::NextAnimationId(), + AnimationIdProvider::NextGroupId(), Animation::SCROLL_OFFSET); + animation->set_is_impl_only(true); + + DCHECK(scroll_offset_animation_player_); + DCHECK(scroll_offset_animation_player_->animation_timeline()); + + if (scroll_offset_animation_player_->layer_id() != layer_id) { + if (scroll_offset_animation_player_->layer_id()) + scroll_offset_animation_player_->DetachLayer(); + scroll_offset_animation_player_->AttachLayer(layer_id); + } + + scroll_offset_animation_player_->AddAnimation(animation.Pass()); + } + + bool ScrollAnimationUpdateTarget(int layer_id, + const gfx::Vector2dF& scroll_delta, + const gfx::ScrollOffset& max_scroll_offset, + base::TimeTicks frame_monotonic_time) { + DCHECK(scroll_offset_animation_player_); + DCHECK_EQ(layer_id, scroll_offset_animation_player_->layer_id()); + + Animation* animation = scroll_offset_animation_player_->element_animations() + ->layer_animation_controller() + ->GetAnimation(Animation::SCROLL_OFFSET); + if (!animation) { + scroll_offset_animation_player_->DetachLayer(); + return false; + } + + ScrollOffsetAnimationCurve* curve = + animation->curve()->ToScrollOffsetAnimationCurve(); + + gfx::ScrollOffset new_target = + gfx::ScrollOffsetWithDelta(curve->target_value(), scroll_delta); + new_target.SetToMax(gfx::ScrollOffset()); + new_target.SetToMin(max_scroll_offset); + + curve->UpdateTarget(animation->TrimTimeToCurrentIteration( + frame_monotonic_time).InSecondsF(), + new_target); + + return true; + } + + // AnimationDelegate implementation. + void NotifyAnimationStarted(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override {} + void NotifyAnimationFinished(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + DCHECK_EQ(target_property, Animation::SCROLL_OFFSET); + DCHECK(animation_host_->mutator_host_client()); + animation_host_->mutator_host_client()->ScrollOffsetAnimationFinished(); + } + + private: + AnimationHost* animation_host_; + scoped_refptr<AnimationTimeline> scroll_offset_timeline_; + + // We have just one player for impl-only scroll offset animations. + // I.e. only one layer can have an impl-only scroll offset animation at + // any given time. + scoped_refptr<AnimationPlayer> scroll_offset_animation_player_; + + DISALLOW_COPY_AND_ASSIGN(ScrollOffsetAnimations); +}; + +scoped_ptr<AnimationHost> AnimationHost::Create( + ThreadInstance thread_instance) { + return make_scoped_ptr(new AnimationHost(thread_instance)); +} + +AnimationHost::AnimationHost(ThreadInstance thread_instance) + : animation_registrar_(AnimationRegistrar::Create()), + mutator_host_client_(nullptr), + thread_instance_(thread_instance) { + if (thread_instance_ == ThreadInstance::IMPL) + scroll_offset_animations_ = + make_scoped_ptr(new ScrollOffsetAnimations(this)); +} + +AnimationHost::~AnimationHost() { + scroll_offset_animations_ = nullptr; + + ClearTimelines(); + DCHECK(!mutator_host_client()); + DCHECK(layer_to_element_animations_map_.empty()); +} + +AnimationTimeline* AnimationHost::GetTimelineById(int timeline_id) const { + for (auto& timeline : timelines_) + if (timeline->id() == timeline_id) + return timeline.get(); + return nullptr; +} + +void AnimationHost::ClearTimelines() { + EraseTimelines(timelines_.begin(), timelines_.end()); +} + +void AnimationHost::EraseTimelines(AnimationTimelineList::iterator begin, + AnimationTimelineList::iterator end) { + for (auto i = begin; i != end; ++i) { + auto& timeline = *i; + timeline->ClearPlayers(); + timeline->SetAnimationHost(nullptr); + } + + timelines_.erase(begin, end); +} + +void AnimationHost::AddAnimationTimeline( + scoped_refptr<AnimationTimeline> timeline) { + timeline->SetAnimationHost(this); + timelines_.push_back(timeline); +} + +void AnimationHost::RemoveAnimationTimeline( + scoped_refptr<AnimationTimeline> timeline) { + for (auto iter = timelines_.begin(); iter != timelines_.end(); ++iter) { + if (iter->get() != timeline) + continue; + + EraseTimelines(iter, iter + 1); + break; + } +} + +void AnimationHost::RegisterLayer(int layer_id, LayerTreeType tree_type) { + ElementAnimations* element_animations = + GetElementAnimationsForLayerId(layer_id); + if (element_animations) + element_animations->LayerRegistered(layer_id, tree_type); +} + +void AnimationHost::UnregisterLayer(int layer_id, LayerTreeType tree_type) { + ElementAnimations* element_animations = + GetElementAnimationsForLayerId(layer_id); + if (element_animations) + element_animations->LayerUnregistered(layer_id, tree_type); +} + +void AnimationHost::RegisterPlayerForLayer(int layer_id, + AnimationPlayer* player) { + DCHECK(layer_id); + DCHECK(player); + + ElementAnimations* element_animations = + GetElementAnimationsForLayerId(layer_id); + if (!element_animations) { + auto new_element_animations = ElementAnimations::Create(this); + element_animations = new_element_animations.get(); + + layer_to_element_animations_map_.add(layer_id, + new_element_animations.Pass()); + element_animations->CreateLayerAnimationController(layer_id); + } + + DCHECK(element_animations); + element_animations->AddPlayer(player); +} + +void AnimationHost::UnregisterPlayerForLayer(int layer_id, + AnimationPlayer* player) { + DCHECK(layer_id); + DCHECK(player); + + ElementAnimations* element_animations = + GetElementAnimationsForLayerId(layer_id); + DCHECK(element_animations); + element_animations->RemovePlayer(player); + + if (element_animations->IsEmpty()) { + element_animations->DestroyLayerAnimationController(); + layer_to_element_animations_map_.erase(layer_id); + element_animations = nullptr; + } +} + +void AnimationHost::SetMutatorHostClient(MutatorHostClient* client) { + if (mutator_host_client_ == client) + return; + + mutator_host_client_ = client; +} + +void AnimationHost::SetNeedsCommit() { + DCHECK(mutator_host_client_); + mutator_host_client_->SetMutatorsNeedCommit(); +} + +void AnimationHost::PushPropertiesTo(AnimationHost* host_impl) { + PushTimelinesToImplThread(host_impl); + RemoveTimelinesFromImplThread(host_impl); + PushPropertiesToImplThread(host_impl); +} + +void AnimationHost::PushTimelinesToImplThread(AnimationHost* host_impl) const { + for (auto& timeline : timelines_) { + AnimationTimeline* timeline_impl = + host_impl->GetTimelineById(timeline->id()); + if (timeline_impl) + continue; + + scoped_refptr<AnimationTimeline> to_add = timeline->CreateImplInstance(); + host_impl->AddAnimationTimeline(to_add.get()); + } +} + +void AnimationHost::RemoveTimelinesFromImplThread( + AnimationHost* host_impl) const { + AnimationTimelineList& timelines_impl = host_impl->timelines_; + + auto to_erase = + std::partition(timelines_impl.begin(), timelines_impl.end(), + [this](AnimationTimelineList::value_type timeline_impl) { + return timeline_impl->is_impl_only() || + GetTimelineById(timeline_impl->id()); + }); + + host_impl->EraseTimelines(to_erase, timelines_impl.end()); +} + +void AnimationHost::PushPropertiesToImplThread(AnimationHost* host_impl) { + // Firstly, sync all players with impl thread to create ElementAnimations and + // layer animation controllers. + for (auto& timeline : timelines_) { + AnimationTimeline* timeline_impl = + host_impl->GetTimelineById(timeline->id()); + if (timeline_impl) + timeline->PushPropertiesTo(timeline_impl); + } + + // Secondly, sync properties for created layer animation controllers. + for (auto& kv : layer_to_element_animations_map_) { + ElementAnimations* element_animations = kv.second; + ElementAnimations* element_animations_impl = + host_impl->GetElementAnimationsForLayerId(kv.first); + if (element_animations_impl) + element_animations->PushPropertiesTo(element_animations_impl); + } +} + +LayerAnimationController* AnimationHost::GetControllerForLayerId( + int layer_id) const { + const ElementAnimations* element_animations = + GetElementAnimationsForLayerId(layer_id); + if (!element_animations) + return nullptr; + + return element_animations->layer_animation_controller(); +} + +ElementAnimations* AnimationHost::GetElementAnimationsForLayerId( + int layer_id) const { + DCHECK(layer_id); + auto iter = layer_to_element_animations_map_.find(layer_id); + return iter == layer_to_element_animations_map_.end() ? nullptr + : iter->second; +} + +void AnimationHost::SetSupportsScrollAnimations( + bool supports_scroll_animations) { + animation_registrar_->set_supports_scroll_animations( + supports_scroll_animations); +} + +bool AnimationHost::SupportsScrollAnimations() const { + return animation_registrar_->supports_scroll_animations(); +} + +bool AnimationHost::NeedsAnimateLayers() const { + return animation_registrar_->needs_animate_layers(); +} + +bool AnimationHost::ActivateAnimations() { + return animation_registrar_->ActivateAnimations(); +} + +bool AnimationHost::AnimateLayers(base::TimeTicks monotonic_time) { + return animation_registrar_->AnimateLayers(monotonic_time); +} + +bool AnimationHost::UpdateAnimationState(bool start_ready_animations, + AnimationEventsVector* events) { + return animation_registrar_->UpdateAnimationState(start_ready_animations, + events); +} + +scoped_ptr<AnimationEventsVector> AnimationHost::CreateEvents() { + return animation_registrar_->CreateEvents(); +} + +void AnimationHost::SetAnimationEvents( + scoped_ptr<AnimationEventsVector> events) { + return animation_registrar_->SetAnimationEvents(events.Pass()); +} + +bool AnimationHost::ScrollOffsetAnimationWasInterrupted(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->scroll_offset_animation_was_interrupted() + : false; +} + +bool AnimationHost::IsAnimatingFilterProperty(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->IsAnimatingProperty(Animation::FILTER) + : false; +} + +bool AnimationHost::IsAnimatingOpacityProperty(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->IsAnimatingProperty(Animation::OPACITY) + : false; +} + +bool AnimationHost::IsAnimatingTransformProperty(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->IsAnimatingProperty(Animation::TRANSFORM) + : false; +} + +bool AnimationHost::HasPotentiallyRunningOpacityAnimation(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + if (!controller) + return false; + + Animation* animation = controller->GetAnimation(Animation::OPACITY); + return animation && !animation->is_finished(); +} + +bool AnimationHost::HasPotentiallyRunningTransformAnimation( + int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + if (!controller) + return false; + + Animation* animation = controller->GetAnimation(Animation::TRANSFORM); + return animation && !animation->is_finished(); +} + +bool AnimationHost::FilterIsAnimatingOnImplOnly(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + if (!controller) + return false; + + Animation* animation = controller->GetAnimation(Animation::FILTER); + return animation && animation->is_impl_only(); +} + +bool AnimationHost::OpacityIsAnimatingOnImplOnly(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + if (!controller) + return false; + + Animation* animation = controller->GetAnimation(Animation::OPACITY); + return animation && animation->is_impl_only(); +} + +bool AnimationHost::TransformIsAnimatingOnImplOnly(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + if (!controller) + return false; + + Animation* animation = controller->GetAnimation(Animation::TRANSFORM); + return animation && animation->is_impl_only(); +} + +bool AnimationHost::HasFilterAnimationThatInflatesBounds(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->HasFilterAnimationThatInflatesBounds() + : false; +} + +bool AnimationHost::HasTransformAnimationThatInflatesBounds( + int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->HasTransformAnimationThatInflatesBounds() + : false; +} + +bool AnimationHost::HasAnimationThatInflatesBounds(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->HasAnimationThatInflatesBounds() : false; +} + +bool AnimationHost::FilterAnimationBoundsForBox(int layer_id, + const gfx::BoxF& box, + gfx::BoxF* bounds) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->FilterAnimationBoundsForBox(box, bounds) + : false; +} + +bool AnimationHost::TransformAnimationBoundsForBox(int layer_id, + const gfx::BoxF& box, + gfx::BoxF* bounds) const { + *bounds = gfx::BoxF(); + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->TransformAnimationBoundsForBox(box, bounds) + : true; +} + +bool AnimationHost::HasOnlyTranslationTransforms(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->HasOnlyTranslationTransforms() : true; +} + +bool AnimationHost::AnimationsPreserveAxisAlignment(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->AnimationsPreserveAxisAlignment() : true; +} + +bool AnimationHost::MaximumTargetScale(int layer_id, float* max_scale) const { + *max_scale = 0.f; + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->MaximumTargetScale(max_scale) : true; +} + +bool AnimationHost::AnimationStartScale(int layer_id, + float* start_scale) const { + *start_scale = 0.f; + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->AnimationStartScale(start_scale) : true; +} + +bool AnimationHost::HasAnyAnimation(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->has_any_animation() : false; +} + +bool AnimationHost::HasActiveAnimation(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + return controller ? controller->HasActiveAnimation() : false; +} + +void AnimationHost::ImplOnlyScrollAnimationCreate( + int layer_id, + const gfx::ScrollOffset& target_offset, + const gfx::ScrollOffset& current_offset) { + DCHECK(scroll_offset_animations_); + scroll_offset_animations_->ScrollAnimationCreate(layer_id, target_offset, + current_offset); +} + +bool AnimationHost::ImplOnlyScrollAnimationUpdateTarget( + int layer_id, + const gfx::Vector2dF& scroll_delta, + const gfx::ScrollOffset& max_scroll_offset, + base::TimeTicks frame_monotonic_time) { + DCHECK(scroll_offset_animations_); + return scroll_offset_animations_->ScrollAnimationUpdateTarget( + layer_id, scroll_delta, max_scroll_offset, frame_monotonic_time); +} + +} // namespace cc diff --git a/chromium/cc/animation/animation_host.h b/chromium/cc/animation/animation_host.h new file mode 100644 index 00000000000..3f69a023379 --- /dev/null +++ b/chromium/cc/animation/animation_host.h @@ -0,0 +1,167 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_ANIMATION_ANIMATION_HOST_H_ +#define CC_ANIMATION_ANIMATION_HOST_H_ + +#include <vector> + +#include "base/containers/scoped_ptr_hash_map.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "cc/animation/animation_events.h" +#include "cc/base/cc_export.h" +#include "cc/trees/mutator_host_client.h" + +namespace gfx { +class ScrollOffset; +} + +namespace cc { + +class AnimationPlayer; +class AnimationRegistrar; +class AnimationTimeline; +class ElementAnimations; +class LayerAnimationController; +class LayerTreeHost; + +enum class ThreadInstance { MAIN, IMPL }; + +typedef std::vector<scoped_refptr<AnimationTimeline>> AnimationTimelineList; + +// An AnimationHost contains all the state required to play animations. +// Specifically, it owns all the AnimationTimelines objects. +// There is just one AnimationHost for LayerTreeHost on main renderer thread +// and just one AnimationHost for LayerTreeHostImpl on impl thread. +// We synchronize them during the commit process in a one-way data flow process +// (PushPropertiesTo). +// An AnimationHost talks to its correspondent LayerTreeHost via +// LayerTreeMutatorsClient interface. +// AnimationHost has it's own instance of AnimationRegistrar, +// we want to merge AnimationRegistrar into AnimationHost. +class CC_EXPORT AnimationHost { + public: + static scoped_ptr<AnimationHost> Create(ThreadInstance thread_instance); + virtual ~AnimationHost(); + + void AddAnimationTimeline(scoped_refptr<AnimationTimeline> timeline); + void RemoveAnimationTimeline(scoped_refptr<AnimationTimeline> timeline); + AnimationTimeline* GetTimelineById(int timeline_id) const; + + void ClearTimelines(); + + void RegisterLayer(int layer_id, LayerTreeType tree_type); + void UnregisterLayer(int layer_id, LayerTreeType tree_type); + + void RegisterPlayerForLayer(int layer_id, AnimationPlayer* player); + void UnregisterPlayerForLayer(int layer_id, AnimationPlayer* player); + + ElementAnimations* GetElementAnimationsForLayerId(int layer_id) const; + + // TODO(loyso): Get rid of LayerAnimationController. + LayerAnimationController* GetControllerForLayerId(int layer_id) const; + + // Parent LayerTreeHost or LayerTreeHostImpl. + MutatorHostClient* mutator_host_client() { return mutator_host_client_; } + const MutatorHostClient* mutator_host_client() const { + return mutator_host_client_; + } + void SetMutatorHostClient(MutatorHostClient* client); + + void SetNeedsCommit(); + + void PushPropertiesTo(AnimationHost* host_impl); + + AnimationRegistrar* animation_registrar() const { + return animation_registrar_.get(); + } + + void SetSupportsScrollAnimations(bool supports_scroll_animations); + bool SupportsScrollAnimations() const; + bool NeedsAnimateLayers() const; + + bool ActivateAnimations(); + bool AnimateLayers(base::TimeTicks monotonic_time); + bool UpdateAnimationState(bool start_ready_animations, + AnimationEventsVector* events); + + scoped_ptr<AnimationEventsVector> CreateEvents(); + void SetAnimationEvents(scoped_ptr<AnimationEventsVector> events); + + bool ScrollOffsetAnimationWasInterrupted(int layer_id) const; + + bool IsAnimatingFilterProperty(int layer_id) const; + bool IsAnimatingOpacityProperty(int layer_id) const; + bool IsAnimatingTransformProperty(int layer_id) const; + + bool HasPotentiallyRunningOpacityAnimation(int layer_id) const; + bool HasPotentiallyRunningTransformAnimation(int layer_id) const; + + bool FilterIsAnimatingOnImplOnly(int layer_id) const; + bool OpacityIsAnimatingOnImplOnly(int layer_id) const; + bool TransformIsAnimatingOnImplOnly(int layer_id) const; + + bool HasFilterAnimationThatInflatesBounds(int layer_id) const; + bool HasTransformAnimationThatInflatesBounds(int layer_id) const; + bool HasAnimationThatInflatesBounds(int layer_id) const; + + bool FilterAnimationBoundsForBox(int layer_id, + const gfx::BoxF& box, + gfx::BoxF* bounds) const; + bool TransformAnimationBoundsForBox(int layer_id, + const gfx::BoxF& box, + gfx::BoxF* bounds) const; + + bool HasOnlyTranslationTransforms(int layer_id) const; + bool AnimationsPreserveAxisAlignment(int layer_id) const; + + bool MaximumTargetScale(int layer_id, float* max_scale) const; + bool AnimationStartScale(int layer_id, float* start_scale) const; + + bool HasAnyAnimation(int layer_id) const; + bool HasActiveAnimation(int layer_id) const; + + void ImplOnlyScrollAnimationCreate(int layer_id, + const gfx::ScrollOffset& target_offset, + const gfx::ScrollOffset& current_offset); + bool ImplOnlyScrollAnimationUpdateTarget( + int layer_id, + const gfx::Vector2dF& scroll_delta, + const gfx::ScrollOffset& max_scroll_offset, + base::TimeTicks frame_monotonic_time); + + private: + explicit AnimationHost(ThreadInstance thread_instance); + + void PushTimelinesToImplThread(AnimationHost* host_impl) const; + void RemoveTimelinesFromImplThread(AnimationHost* host_impl) const; + void PushPropertiesToImplThread(AnimationHost* host_impl); + + void EraseTimelines(AnimationTimelineList::iterator begin, + AnimationTimelineList::iterator end); + + // TODO(loyso): For now AnimationPlayers share LayerAnimationController object + // if they are attached to the same element(layer). Note that Element can + // contain many Layers. + typedef base::ScopedPtrHashMap<int, scoped_ptr<ElementAnimations>> + LayerToElementAnimationsMap; + LayerToElementAnimationsMap layer_to_element_animations_map_; + + AnimationTimelineList timelines_; + scoped_ptr<AnimationRegistrar> animation_registrar_; + MutatorHostClient* mutator_host_client_; + + class ScrollOffsetAnimations; + scoped_ptr<ScrollOffsetAnimations> scroll_offset_animations_; + + const ThreadInstance thread_instance_; + + DISALLOW_COPY_AND_ASSIGN(AnimationHost); +}; + +} // namespace cc + +#endif // CC_ANIMATION_ANIMATION_HOST_H_ diff --git a/chromium/cc/animation/animation_host_unittest.cc b/chromium/cc/animation/animation_host_unittest.cc new file mode 100644 index 00000000000..18d6c9f66f5 --- /dev/null +++ b/chromium/cc/animation/animation_host_unittest.cc @@ -0,0 +1,75 @@ +// Copyright 2015 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/animation/animation_host.h" + +#include "cc/animation/animation_id_provider.h" +#include "cc/animation/animation_timeline.h" +#include "cc/test/animation_test_common.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +// See AnimationPlayer tests on layer registration/unregistration in +// animation_player_unittest.cc. + +TEST(AnimationHostTest, SyncTimelinesAddRemove) { + scoped_ptr<AnimationHost> host(AnimationHost::Create(ThreadInstance::MAIN)); + scoped_ptr<AnimationHost> host_impl( + AnimationHost::Create(ThreadInstance::IMPL)); + + const int timeline_id = AnimationIdProvider::NextTimelineId(); + scoped_refptr<AnimationTimeline> timeline( + AnimationTimeline::Create(timeline_id)); + host->AddAnimationTimeline(timeline.get()); + EXPECT_TRUE(timeline->animation_host()); + + EXPECT_FALSE(host_impl->GetTimelineById(timeline_id)); + + host->PushPropertiesTo(host_impl.get()); + + scoped_refptr<AnimationTimeline> timeline_impl = + host_impl->GetTimelineById(timeline_id); + EXPECT_TRUE(timeline_impl); + EXPECT_EQ(timeline_impl->id(), timeline_id); + + host->PushPropertiesTo(host_impl.get()); + EXPECT_EQ(timeline_impl, host_impl->GetTimelineById(timeline_id)); + + host->RemoveAnimationTimeline(timeline.get()); + EXPECT_FALSE(timeline->animation_host()); + + host->PushPropertiesTo(host_impl.get()); + EXPECT_FALSE(host_impl->GetTimelineById(timeline_id)); + + EXPECT_FALSE(timeline_impl->animation_host()); +} + +TEST(AnimationHostTest, ImplOnlyTimeline) { + scoped_ptr<AnimationHost> host(AnimationHost::Create(ThreadInstance::MAIN)); + scoped_ptr<AnimationHost> host_impl( + AnimationHost::Create(ThreadInstance::IMPL)); + + const int timeline_id1 = AnimationIdProvider::NextTimelineId(); + const int timeline_id2 = AnimationIdProvider::NextTimelineId(); + + scoped_refptr<AnimationTimeline> timeline( + AnimationTimeline::Create(timeline_id1)); + scoped_refptr<AnimationTimeline> timeline_impl( + AnimationTimeline::Create(timeline_id2)); + timeline_impl->set_is_impl_only(true); + + host->AddAnimationTimeline(timeline.get()); + host_impl->AddAnimationTimeline(timeline_impl.get()); + + host->PushPropertiesTo(host_impl.get()); + + EXPECT_TRUE(host->GetTimelineById(timeline_id1)); + EXPECT_TRUE(host_impl->GetTimelineById(timeline_id2)); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/animation/animation_id_provider.cc b/chromium/cc/animation/animation_id_provider.cc index caefdb8fee5..9c87d2049f4 100644 --- a/chromium/cc/animation/animation_id_provider.cc +++ b/chromium/cc/animation/animation_id_provider.cc @@ -9,6 +9,8 @@ namespace cc { base::StaticAtomicSequenceNumber g_next_animation_id; base::StaticAtomicSequenceNumber g_next_group_id; +base::StaticAtomicSequenceNumber g_next_timeline_id; +base::StaticAtomicSequenceNumber g_next_player_id; int AnimationIdProvider::NextAnimationId() { // Animation IDs start from 1. @@ -20,4 +22,12 @@ int AnimationIdProvider::NextGroupId() { return g_next_group_id.GetNext() + 1; } +int AnimationIdProvider::NextTimelineId() { + return g_next_timeline_id.GetNext() + 1; +} + +int AnimationIdProvider::NextPlayerId() { + return g_next_player_id.GetNext() + 1; +} + } // namespace cc diff --git a/chromium/cc/animation/animation_id_provider.h b/chromium/cc/animation/animation_id_provider.h index b403841315b..3b14801e7d3 100644 --- a/chromium/cc/animation/animation_id_provider.h +++ b/chromium/cc/animation/animation_id_provider.h @@ -15,6 +15,8 @@ class CC_EXPORT AnimationIdProvider { // These functions each return monotonically increasing values. static int NextAnimationId(); static int NextGroupId(); + static int NextTimelineId(); + static int NextPlayerId(); private: DISALLOW_IMPLICIT_CONSTRUCTORS(AnimationIdProvider); diff --git a/chromium/cc/animation/animation_player.cc b/chromium/cc/animation/animation_player.cc new file mode 100644 index 00000000000..e4febeb242a --- /dev/null +++ b/chromium/cc/animation/animation_player.cc @@ -0,0 +1,189 @@ +// Copyright 2015 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/animation/animation_player.h" + +#include "cc/animation/animation_delegate.h" +#include "cc/animation/animation_host.h" +#include "cc/animation/animation_timeline.h" +#include "cc/animation/element_animations.h" +#include "cc/animation/layer_animation_controller.h" + +namespace cc { + +scoped_refptr<AnimationPlayer> AnimationPlayer::Create(int id) { + return make_scoped_refptr(new AnimationPlayer(id)); +} + +AnimationPlayer::AnimationPlayer(int id) + : animation_host_(), + animation_timeline_(), + element_animations_(), + layer_animation_delegate_(), + id_(id), + layer_id_(0) { + DCHECK(id_); +} + +AnimationPlayer::~AnimationPlayer() { + DCHECK(!animation_timeline_); + DCHECK(!element_animations_); + DCHECK(!layer_id_); +} + +scoped_refptr<AnimationPlayer> AnimationPlayer::CreateImplInstance() const { + scoped_refptr<AnimationPlayer> player = AnimationPlayer::Create(id()); + return player; +} + +void AnimationPlayer::SetAnimationHost(AnimationHost* animation_host) { + animation_host_ = animation_host; +} + +void AnimationPlayer::SetAnimationTimeline(AnimationTimeline* timeline) { + if (animation_timeline_ == timeline) + return; + + // We need to unregister player to manage ElementAnimations and observers + // properly. + if (layer_id_ && element_animations_) + UnregisterPlayer(); + + animation_timeline_ = timeline; + + // Register player only if layer AND host attached. + if (layer_id_ && animation_host_) + RegisterPlayer(); +} + +void AnimationPlayer::AttachLayer(int layer_id) { + DCHECK_EQ(layer_id_, 0); + DCHECK(layer_id); + + layer_id_ = layer_id; + + // Register player only if layer AND host attached. + if (animation_host_) + RegisterPlayer(); +} + +void AnimationPlayer::DetachLayer() { + DCHECK(layer_id_); + + if (animation_host_) + UnregisterPlayer(); + + layer_id_ = 0; +} + +void AnimationPlayer::RegisterPlayer() { + DCHECK(layer_id_); + DCHECK(animation_host_); + DCHECK(!element_animations_); + + // Create LAC or re-use existing. + animation_host_->RegisterPlayerForLayer(layer_id_, this); + // Get local reference to shared LAC. + BindElementAnimations(); +} + +void AnimationPlayer::UnregisterPlayer() { + DCHECK(layer_id_); + DCHECK(animation_host_); + DCHECK(element_animations_); + + UnbindElementAnimations(); + // Destroy LAC or release it if it's still needed. + animation_host_->UnregisterPlayerForLayer(layer_id_, this); +} + +void AnimationPlayer::BindElementAnimations() { + DCHECK(!element_animations_); + element_animations_ = + animation_host_->GetElementAnimationsForLayerId(layer_id_); + DCHECK(element_animations_); + + // Pass all accumulated animations to LAC. + for (auto it = animations_.begin(); it != animations_.end(); ++it) + element_animations_->layer_animation_controller()->AddAnimation( + animations_.take(it)); + if (!animations_.empty()) + SetNeedsCommit(); + animations_.clear(); +} + +void AnimationPlayer::UnbindElementAnimations() { + element_animations_ = nullptr; + DCHECK(animations_.empty()); +} + +void AnimationPlayer::AddAnimation(scoped_ptr<Animation> animation) { + DCHECK_IMPLIES( + animation->target_property() == Animation::SCROLL_OFFSET, + animation_host_ && animation_host_->SupportsScrollAnimations()); + + if (element_animations_) { + element_animations_->layer_animation_controller()->AddAnimation( + animation.Pass()); + SetNeedsCommit(); + } else { + animations_.push_back(animation.Pass()); + } +} + +void AnimationPlayer::PauseAnimation(int animation_id, double time_offset) { + DCHECK(element_animations_); + element_animations_->layer_animation_controller()->PauseAnimation( + animation_id, base::TimeDelta::FromSecondsD(time_offset)); + SetNeedsCommit(); +} + +void AnimationPlayer::RemoveAnimation(int animation_id) { + if (element_animations_) { + element_animations_->layer_animation_controller()->RemoveAnimation( + animation_id); + SetNeedsCommit(); + } else { + auto animations_to_remove = animations_.remove_if([animation_id]( + Animation* animation) { return animation->id() == animation_id; }); + animations_.erase(animations_to_remove, animations_.end()); + } +} + +void AnimationPlayer::PushPropertiesTo(AnimationPlayer* player_impl) { + if (!element_animations_) { + if (player_impl->element_animations()) + player_impl->DetachLayer(); + return; + } + + DCHECK(layer_id_); + if (!player_impl->element_animations()) + player_impl->AttachLayer(layer_id_); +} + +void AnimationPlayer::NotifyAnimationStarted( + base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) { + if (layer_animation_delegate_) + layer_animation_delegate_->NotifyAnimationStarted(monotonic_time, + target_property, group); +} + +void AnimationPlayer::NotifyAnimationFinished( + base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) { + if (layer_animation_delegate_) + layer_animation_delegate_->NotifyAnimationFinished(monotonic_time, + target_property, group); +} + +void AnimationPlayer::SetNeedsCommit() { + DCHECK(animation_host_); + animation_host_->SetNeedsCommit(); +} + +} // namespace cc diff --git a/chromium/cc/animation/animation_player.h b/chromium/cc/animation/animation_player.h new file mode 100644 index 00000000000..afb819d5c5e --- /dev/null +++ b/chromium/cc/animation/animation_player.h @@ -0,0 +1,114 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_ANIMATION_ANIMATION_PLAYER_H_ +#define CC_ANIMATION_ANIMATION_PLAYER_H_ + +#include "base/containers/linked_list.h" +#include "base/memory/ref_counted.h" +#include "base/time/time.h" +#include "cc/animation/animation.h" +#include "cc/base/cc_export.h" +#include "cc/base/scoped_ptr_vector.h" + +namespace cc { + +class AnimationDelegate; +class AnimationHost; +class AnimationTimeline; +class ElementAnimations; +class LayerAnimationController; +enum class LayerTreeType; + +// An AnimationPlayer owns all animations to be run on particular CC Layer. +// Multiple AnimationPlayers can be attached to one layer. In this case, +// they share common LayerAnimationController (temp solution) so the +// LayerAnimationController-to-Layer relationship stays the same (1:1, LACs +// have same IDs as their respective Layers). +// For now, the blink logic is responsible for handling of conflicting +// same-property animations. +// Each AnimationPlayer has its copy on the impl thread. +// This is a CC counterpart for blink::AnimationPlayer (in 1:1 relationship). +class CC_EXPORT AnimationPlayer : public base::RefCounted<AnimationPlayer>, + public base::LinkNode<AnimationPlayer> { + public: + static scoped_refptr<AnimationPlayer> Create(int id); + scoped_refptr<AnimationPlayer> CreateImplInstance() const; + + int id() const { return id_; } + int layer_id() const { return layer_id_; } + + // Parent AnimationHost. AnimationPlayer can be detached from + // AnimationTimeline. + AnimationHost* animation_host() { return animation_host_; } + const AnimationHost* animation_host() const { return animation_host_; } + void SetAnimationHost(AnimationHost* animation_host); + + // Parent AnimationTimeline. + AnimationTimeline* animation_timeline() { return animation_timeline_; } + const AnimationTimeline* animation_timeline() const { + return animation_timeline_; + } + void SetAnimationTimeline(AnimationTimeline* timeline); + + // ElementAnimations object where this player is listed. + // ElementAnimations has a reference to shared LayerAnimationController. + ElementAnimations* element_animations() const { return element_animations_; } + + void set_layer_animation_delegate(AnimationDelegate* delegate) { + layer_animation_delegate_ = delegate; + } + + void AttachLayer(int layer_id); + void DetachLayer(); + + void AddAnimation(scoped_ptr<Animation> animation); + void PauseAnimation(int animation_id, double time_offset); + void RemoveAnimation(int animation_id); + + void PushPropertiesTo(AnimationPlayer* player_impl); + + // AnimationDelegate routing. + void NotifyAnimationStarted(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group); + void NotifyAnimationFinished(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group); + + private: + friend class base::RefCounted<AnimationPlayer>; + + explicit AnimationPlayer(int id); + ~AnimationPlayer(); + + void SetNeedsCommit(); + + void RegisterPlayer(); + void UnregisterPlayer(); + + void BindElementAnimations(); + void UnbindElementAnimations(); + + // We accumulate added animations in animations_ container + // if element_animations_ is a nullptr. It allows us to add/remove animations + // to non-attached AnimationPlayers. + typedef ScopedPtrVector<Animation> AnimationList; + AnimationList animations_; + + AnimationHost* animation_host_; + AnimationTimeline* animation_timeline_; + // element_animations isn't null if player attached to an element (layer). + ElementAnimations* element_animations_; + AnimationDelegate* layer_animation_delegate_; + + int id_; + int layer_id_; + + DISALLOW_COPY_AND_ASSIGN(AnimationPlayer); +}; + +} // namespace cc + +#endif // CC_ANIMATION_ANIMATION_PLAYER_H_ diff --git a/chromium/cc/animation/animation_player_unittest.cc b/chromium/cc/animation/animation_player_unittest.cc new file mode 100644 index 00000000000..466964f6d77 --- /dev/null +++ b/chromium/cc/animation/animation_player_unittest.cc @@ -0,0 +1,336 @@ +// Copyright 2015 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/animation/animation_player.h" + +#include "cc/animation/animation_delegate.h" +#include "cc/animation/animation_host.h" +#include "cc/animation/animation_id_provider.h" +#include "cc/animation/animation_registrar.h" +#include "cc/animation/animation_timeline.h" +#include "cc/animation/element_animations.h" +#include "cc/test/animation_test_common.h" +#include "cc/test/animation_timelines_test_common.h" + +namespace cc { +namespace { + +class AnimationPlayerTest : public AnimationTimelinesTest { + public: + AnimationPlayerTest() {} + ~AnimationPlayerTest() override {} +}; + +// See element_animations_unittest.cc for active/pending observers tests. + +TEST_F(AnimationPlayerTest, AttachDetachLayerIfTimelineAttached) { + host_->AddAnimationTimeline(timeline_); + timeline_->AttachPlayer(player_); + EXPECT_FALSE(player_->element_animations()); + EXPECT_FALSE(player_->layer_id()); + + host_->PushPropertiesTo(host_impl_); + + EXPECT_FALSE(GetImplPlayerForLayerId(layer_id_)); + + GetImplTimelineAndPlayerByID(); + + EXPECT_FALSE(player_impl_->element_animations()); + EXPECT_FALSE(player_impl_->layer_id()); + + player_->AttachLayer(layer_id_); + EXPECT_EQ(player_, GetPlayerForLayerId(layer_id_)); + EXPECT_TRUE(player_->element_animations()); + EXPECT_EQ(player_->layer_id(), layer_id_); + + host_->PushPropertiesTo(host_impl_); + + EXPECT_EQ(player_impl_, GetImplPlayerForLayerId(layer_id_)); + EXPECT_TRUE(player_impl_->element_animations()); + EXPECT_EQ(player_impl_->layer_id(), layer_id_); + + player_->DetachLayer(); + EXPECT_FALSE(GetPlayerForLayerId(layer_id_)); + EXPECT_FALSE(player_->element_animations()); + EXPECT_FALSE(player_->layer_id()); + + host_->PushPropertiesTo(host_impl_); + + EXPECT_FALSE(GetImplPlayerForLayerId(layer_id_)); + EXPECT_FALSE(player_impl_->element_animations()); + EXPECT_FALSE(player_impl_->layer_id()); + + timeline_->DetachPlayer(player_); + EXPECT_FALSE(player_->animation_timeline()); + EXPECT_FALSE(player_->element_animations()); + EXPECT_FALSE(player_->layer_id()); +} + +TEST_F(AnimationPlayerTest, AttachDetachTimelineIfLayerAttached) { + host_->AddAnimationTimeline(timeline_); + + EXPECT_FALSE(player_->element_animations()); + EXPECT_FALSE(player_->layer_id()); + + player_->AttachLayer(layer_id_); + EXPECT_FALSE(player_->animation_timeline()); + EXPECT_FALSE(GetPlayerForLayerId(layer_id_)); + EXPECT_FALSE(player_->element_animations()); + EXPECT_EQ(player_->layer_id(), layer_id_); + + timeline_->AttachPlayer(player_); + EXPECT_EQ(timeline_, player_->animation_timeline()); + EXPECT_EQ(player_, GetPlayerForLayerId(layer_id_)); + EXPECT_TRUE(player_->element_animations()); + EXPECT_EQ(player_->layer_id(), layer_id_); + + // Removing player from timeline detaches layer. + timeline_->DetachPlayer(player_); + EXPECT_FALSE(player_->animation_timeline()); + EXPECT_FALSE(GetPlayerForLayerId(layer_id_)); + EXPECT_FALSE(player_->element_animations()); + EXPECT_FALSE(player_->layer_id()); +} + +TEST_F(AnimationPlayerTest, PropertiesMutate) { + client_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + client_impl_.RegisterLayer(layer_id_, LayerTreeType::PENDING); + client_impl_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + + host_->AddAnimationTimeline(timeline_); + timeline_->AttachPlayer(player_); + player_->AttachLayer(layer_id_); + + const float start_opacity = .7f; + const float end_opacity = .3f; + + const float start_brightness = .6f; + const float end_brightness = .4f; + + const int transform_x = 10; + const int transform_y = 20; + + const double duration = 1.; + + AddOpacityTransitionToPlayer(player_.get(), duration, start_opacity, + end_opacity, false); + AddAnimatedTransformToPlayer(player_.get(), duration, transform_x, + transform_y); + AddAnimatedFilterToPlayer(player_.get(), duration, start_brightness, + end_brightness); + + host_->PushPropertiesTo(host_impl_); + + EXPECT_FALSE(client_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::OPACITY)); + EXPECT_FALSE(client_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::TRANSFORM)); + EXPECT_FALSE(client_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::FILTER)); + + EXPECT_FALSE(client_impl_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::OPACITY)); + EXPECT_FALSE(client_impl_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::TRANSFORM)); + EXPECT_FALSE(client_impl_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::FILTER)); + + host_impl_->animation_registrar()->ActivateAnimations(); + + base::TimeTicks time; + time += base::TimeDelta::FromSecondsD(0.1); + AnimateLayersTransferEvents(time, 3u); + + time += base::TimeDelta::FromSecondsD(duration); + AnimateLayersTransferEvents(time, 3u); + + client_.ExpectOpacityPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + end_opacity); + client_.ExpectTransformPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + transform_x, transform_y); + client_.ExpectFilterPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + end_brightness); + + client_impl_.ExpectOpacityPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + end_opacity); + client_impl_.ExpectTransformPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + transform_x, transform_y); + client_impl_.ExpectFilterPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + end_brightness); + + client_impl_.ExpectOpacityPropertyMutated(layer_id_, LayerTreeType::PENDING, + end_opacity); + client_impl_.ExpectTransformPropertyMutated(layer_id_, LayerTreeType::PENDING, + transform_x, transform_y); + client_impl_.ExpectFilterPropertyMutated(layer_id_, LayerTreeType::PENDING, + end_brightness); +} + +TEST_F(AnimationPlayerTest, AttachTwoPlayersToOneLayer) { + TestAnimationDelegate delegate1; + TestAnimationDelegate delegate2; + + client_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + client_impl_.RegisterLayer(layer_id_, LayerTreeType::PENDING); + client_impl_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + + scoped_refptr<AnimationPlayer> player1 = + AnimationPlayer::Create(AnimationIdProvider::NextPlayerId()); + scoped_refptr<AnimationPlayer> player2 = + AnimationPlayer::Create(AnimationIdProvider::NextPlayerId()); + + host_->AddAnimationTimeline(timeline_); + timeline_->AttachPlayer(player1); + timeline_->AttachPlayer(player2); + + player1->set_layer_animation_delegate(&delegate1); + player2->set_layer_animation_delegate(&delegate2); + + // Attach players to the same layer. + player1->AttachLayer(layer_id_); + player2->AttachLayer(layer_id_); + + const float start_opacity = .7f; + const float end_opacity = .3f; + + const int transform_x = 10; + const int transform_y = 20; + + const double duration = 1.; + + AddOpacityTransitionToPlayer(player1.get(), duration, start_opacity, + end_opacity, false); + AddAnimatedTransformToPlayer(player2.get(), duration, transform_x, + transform_y); + + host_->PushPropertiesTo(host_impl_); + host_impl_->animation_registrar()->ActivateAnimations(); + + EXPECT_FALSE(delegate1.started_); + EXPECT_FALSE(delegate1.finished_); + + EXPECT_FALSE(delegate2.started_); + EXPECT_FALSE(delegate2.finished_); + + base::TimeTicks time; + time += base::TimeDelta::FromSecondsD(0.1); + AnimateLayersTransferEvents(time, 2u); + + EXPECT_TRUE(delegate1.started_); + EXPECT_FALSE(delegate1.finished_); + + EXPECT_TRUE(delegate2.started_); + EXPECT_FALSE(delegate2.finished_); + + time += base::TimeDelta::FromSecondsD(duration); + AnimateLayersTransferEvents(time, 2u); + + EXPECT_TRUE(delegate1.finished_); + EXPECT_TRUE(delegate2.finished_); + + client_.ExpectOpacityPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + end_opacity); + client_.ExpectTransformPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + transform_x, transform_y); + + client_impl_.ExpectOpacityPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + end_opacity); + client_impl_.ExpectTransformPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + transform_x, transform_y); + + client_impl_.ExpectOpacityPropertyMutated(layer_id_, LayerTreeType::PENDING, + end_opacity); + client_impl_.ExpectTransformPropertyMutated(layer_id_, LayerTreeType::PENDING, + transform_x, transform_y); +} + +TEST_F(AnimationPlayerTest, AddRemoveAnimationToNonAttachedPlayer) { + client_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + client_impl_.RegisterLayer(layer_id_, LayerTreeType::PENDING); + client_impl_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + + const double duration = 1.; + const float start_opacity = .7f; + const float end_opacity = .3f; + + const int filter_id = + AddAnimatedFilterToPlayer(player_.get(), duration, 0.1f, 0.9f); + const int opacity_id = AddOpacityTransitionToPlayer( + player_.get(), duration, start_opacity, end_opacity, false); + + host_->AddAnimationTimeline(timeline_); + timeline_->AttachPlayer(player_); + + EXPECT_FALSE(player_->element_animations()); + player_->RemoveAnimation(filter_id); + + player_->AttachLayer(layer_id_); + + EXPECT_TRUE(player_->element_animations()); + EXPECT_FALSE(player_->element_animations() + ->layer_animation_controller() + ->GetAnimationById(filter_id)); + EXPECT_TRUE(player_->element_animations() + ->layer_animation_controller() + ->GetAnimationById(opacity_id)); + + host_->PushPropertiesTo(host_impl_); + + EXPECT_FALSE(client_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::OPACITY)); + EXPECT_FALSE(client_impl_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::OPACITY)); + + EXPECT_FALSE(client_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::FILTER)); + EXPECT_FALSE(client_impl_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::FILTER)); + + host_impl_->animation_registrar()->ActivateAnimations(); + + base::TimeTicks time; + time += base::TimeDelta::FromSecondsD(0.1); + AnimateLayersTransferEvents(time, 1u); + + time += base::TimeDelta::FromSecondsD(duration); + AnimateLayersTransferEvents(time, 1u); + + client_.ExpectOpacityPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + end_opacity); + client_impl_.ExpectOpacityPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + end_opacity); + client_impl_.ExpectOpacityPropertyMutated(layer_id_, LayerTreeType::PENDING, + end_opacity); + + EXPECT_FALSE(client_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::FILTER)); + EXPECT_FALSE(client_impl_.IsPropertyMutated(layer_id_, LayerTreeType::ACTIVE, + Animation::FILTER)); +} + +TEST_F(AnimationPlayerTest, AddRemoveAnimationCausesSetNeedsCommit) { + client_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + host_->AddAnimationTimeline(timeline_); + timeline_->AttachPlayer(player_); + player_->AttachLayer(layer_id_); + + EXPECT_FALSE(client_.mutators_need_commit()); + + const int animation_id = + AddOpacityTransitionToPlayer(player_.get(), 1., .7f, .3f, false); + + EXPECT_TRUE(client_.mutators_need_commit()); + client_.set_mutators_need_commit(false); + + player_->PauseAnimation(animation_id, 1.); + EXPECT_TRUE(client_.mutators_need_commit()); + client_.set_mutators_need_commit(false); + + player_->RemoveAnimation(animation_id); + EXPECT_TRUE(client_.mutators_need_commit()); + client_.set_mutators_need_commit(false); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/animation/animation_timeline.cc b/chromium/cc/animation/animation_timeline.cc new file mode 100644 index 00000000000..9d19f8fbe0b --- /dev/null +++ b/chromium/cc/animation/animation_timeline.cc @@ -0,0 +1,120 @@ +// Copyright 2015 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/animation/animation_timeline.h" + +#include <algorithm> + +#include "cc/animation/animation_player.h" + +namespace cc { + +scoped_refptr<AnimationTimeline> AnimationTimeline::Create(int id) { + return make_scoped_refptr(new AnimationTimeline(id)); +} + +AnimationTimeline::AnimationTimeline(int id) + : id_(id), animation_host_(), is_impl_only_(false) { +} + +AnimationTimeline::~AnimationTimeline() { + for (auto& player : players_) + player->SetAnimationTimeline(nullptr); +} + +scoped_refptr<AnimationTimeline> AnimationTimeline::CreateImplInstance() const { + scoped_refptr<AnimationTimeline> timeline = AnimationTimeline::Create(id()); + return timeline; +} + +void AnimationTimeline::SetAnimationHost(AnimationHost* animation_host) { + animation_host_ = animation_host; + for (auto& player : players_) + player->SetAnimationHost(animation_host); +} + +void AnimationTimeline::AttachPlayer(scoped_refptr<AnimationPlayer> player) { + DCHECK(animation_host_); + player->SetAnimationHost(animation_host_); + player->SetAnimationTimeline(this); + players_.push_back(player); +} + +void AnimationTimeline::DetachPlayer(scoped_refptr<AnimationPlayer> player) { + for (AnimationPlayerList::iterator iter = players_.begin(); + iter != players_.end(); ++iter) { + if (iter->get() != player) + continue; + + ErasePlayers(iter, iter + 1); + break; + } + + player->SetAnimationHost(nullptr); +} + +AnimationPlayer* AnimationTimeline::GetPlayerById(int player_id) const { + for (auto& player : players_) + if (player->id() == player_id) + return player.get(); + return nullptr; +} + +void AnimationTimeline::ClearPlayers() { + ErasePlayers(players_.begin(), players_.end()); +} + +void AnimationTimeline::PushPropertiesTo(AnimationTimeline* timeline_impl) { + PushAttachedPlayersToImplThread(timeline_impl); + RemoveDetachedPlayersFromImplThread(timeline_impl); + PushPropertiesToImplThread(timeline_impl); +} + +void AnimationTimeline::PushAttachedPlayersToImplThread( + AnimationTimeline* timeline_impl) const { + for (auto& player : players_) { + AnimationPlayer* player_impl = timeline_impl->GetPlayerById(player->id()); + if (player_impl) + continue; + + scoped_refptr<AnimationPlayer> to_add = player->CreateImplInstance(); + timeline_impl->AttachPlayer(to_add.get()); + } +} + +void AnimationTimeline::RemoveDetachedPlayersFromImplThread( + AnimationTimeline* timeline_impl) const { + AnimationPlayerList& players_impl = timeline_impl->players_; + + auto to_erase = + std::partition(players_impl.begin(), players_impl.end(), + [this](AnimationPlayerList::value_type player_impl) { + return GetPlayerById(player_impl->id()); + }); + + timeline_impl->ErasePlayers(to_erase, players_impl.end()); +} + +void AnimationTimeline::ErasePlayers(AnimationPlayerList::iterator begin, + AnimationPlayerList::iterator end) { + for (auto i = begin; i != end; ++i) { + auto& player = *i; + if (player->element_animations()) + player->DetachLayer(); + player->SetAnimationTimeline(nullptr); + } + + players_.erase(begin, end); +} + +void AnimationTimeline::PushPropertiesToImplThread( + AnimationTimeline* timeline_impl) { + for (auto& player : players_) { + AnimationPlayer* player_impl = timeline_impl->GetPlayerById(player->id()); + if (player_impl) + player->PushPropertiesTo(player_impl); + } +} + +} // namespace cc diff --git a/chromium/cc/animation/animation_timeline.h b/chromium/cc/animation/animation_timeline.h new file mode 100644 index 00000000000..4cb31f5c076 --- /dev/null +++ b/chromium/cc/animation/animation_timeline.h @@ -0,0 +1,77 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_ANIMATION_ANIMATION_TIMELINE_H_ +#define CC_ANIMATION_ANIMATION_TIMELINE_H_ + +#include <vector> + +#include "base/containers/hash_tables.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" + +namespace cc { + +class AnimationHost; +class AnimationPlayer; + +typedef std::vector<scoped_refptr<AnimationPlayer>> AnimationPlayerList; + +// An AnimationTimeline owns a group of AnimationPlayers. +// This is a cc counterpart for blink::AnimationTimeline (in 1:1 relationship). +// Each AnimationTimeline and its AnimationPlayers have their copies on +// the impl thread. We synchronize main thread and impl thread instances +// using integer IDs. +class CC_EXPORT AnimationTimeline : public base::RefCounted<AnimationTimeline> { + public: + static scoped_refptr<AnimationTimeline> Create(int id); + scoped_refptr<AnimationTimeline> CreateImplInstance() const; + + int id() const { return id_; } + + // Parent AnimationHost. + AnimationHost* animation_host() { return animation_host_; } + const AnimationHost* animation_host() const { return animation_host_; } + void SetAnimationHost(AnimationHost* animation_host); + + void set_is_impl_only(bool is_impl_only) { is_impl_only_ = is_impl_only; } + bool is_impl_only() const { return is_impl_only_; } + + void AttachPlayer(scoped_refptr<AnimationPlayer> player); + void DetachPlayer(scoped_refptr<AnimationPlayer> player); + + void ClearPlayers(); + + void PushPropertiesTo(AnimationTimeline* timeline_impl); + + AnimationPlayer* GetPlayerById(int player_id) const; + + private: + friend class base::RefCounted<AnimationTimeline>; + + explicit AnimationTimeline(int id); + virtual ~AnimationTimeline(); + + void PushAttachedPlayersToImplThread(AnimationTimeline* timeline) const; + void RemoveDetachedPlayersFromImplThread(AnimationTimeline* timeline) const; + void PushPropertiesToImplThread(AnimationTimeline* timeline); + + void ErasePlayers(AnimationPlayerList::iterator begin, + AnimationPlayerList::iterator end); + + AnimationPlayerList players_; + int id_; + AnimationHost* animation_host_; + + // Impl-only AnimationTimeline has no main thread instance and lives on + // it's own. + bool is_impl_only_; + + DISALLOW_COPY_AND_ASSIGN(AnimationTimeline); +}; + +} // namespace cc + +#endif // CC_ANIMATION_ANIMATION_TIMELINE_H_ diff --git a/chromium/cc/animation/animation_timeline_unittest.cc b/chromium/cc/animation/animation_timeline_unittest.cc new file mode 100644 index 00000000000..3b0bc5ab730 --- /dev/null +++ b/chromium/cc/animation/animation_timeline_unittest.cc @@ -0,0 +1,99 @@ +// Copyright 2015 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/animation/animation_timeline.h" + +#include "cc/animation/animation_host.h" +#include "cc/animation/animation_id_provider.h" +#include "cc/animation/animation_player.h" +#include "cc/test/animation_test_common.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +TEST(AnimationTimelineTest, SyncPlayersAttachDetach) { + scoped_ptr<AnimationHost> host(AnimationHost::Create(ThreadInstance::MAIN)); + scoped_ptr<AnimationHost> host_impl( + AnimationHost::Create(ThreadInstance::IMPL)); + + const int timeline_id = AnimationIdProvider::NextTimelineId(); + const int player_id = AnimationIdProvider::NextPlayerId(); + + scoped_refptr<AnimationTimeline> timeline_impl( + AnimationTimeline::Create(timeline_id)); + scoped_refptr<AnimationTimeline> timeline( + AnimationTimeline::Create(timeline_id)); + + host->AddAnimationTimeline(timeline.get()); + EXPECT_TRUE(timeline->animation_host()); + + host_impl->AddAnimationTimeline(timeline_impl.get()); + EXPECT_TRUE(timeline_impl->animation_host()); + + scoped_refptr<AnimationPlayer> player(AnimationPlayer::Create(player_id)); + timeline->AttachPlayer(player.get()); + EXPECT_TRUE(player->animation_timeline()); + + EXPECT_FALSE(timeline_impl->GetPlayerById(player_id)); + + timeline->PushPropertiesTo(timeline_impl.get()); + + scoped_refptr<AnimationPlayer> player_impl = + timeline_impl->GetPlayerById(player_id); + EXPECT_TRUE(player_impl); + EXPECT_EQ(player_impl->id(), player_id); + EXPECT_TRUE(player_impl->animation_timeline()); + + timeline->PushPropertiesTo(timeline_impl.get()); + EXPECT_EQ(player_impl, timeline_impl->GetPlayerById(player_id)); + + timeline->DetachPlayer(player.get()); + EXPECT_FALSE(player->animation_timeline()); + + timeline->PushPropertiesTo(timeline_impl.get()); + EXPECT_FALSE(timeline_impl->GetPlayerById(player_id)); + + EXPECT_FALSE(player_impl->animation_timeline()); +} + +TEST(AnimationTimelineTest, ClearPlayers) { + scoped_ptr<AnimationHost> host(AnimationHost::Create(ThreadInstance::MAIN)); + scoped_ptr<AnimationHost> host_impl( + AnimationHost::Create(ThreadInstance::IMPL)); + + const int timeline_id = AnimationIdProvider::NextTimelineId(); + const int player_id1 = AnimationIdProvider::NextPlayerId(); + const int player_id2 = AnimationIdProvider::NextPlayerId(); + + scoped_refptr<AnimationTimeline> timeline_impl( + AnimationTimeline::Create(timeline_id)); + scoped_refptr<AnimationTimeline> timeline( + AnimationTimeline::Create(timeline_id)); + + host->AddAnimationTimeline(timeline.get()); + host_impl->AddAnimationTimeline(timeline_impl.get()); + + scoped_refptr<AnimationPlayer> player1(AnimationPlayer::Create(player_id1)); + timeline->AttachPlayer(player1.get()); + scoped_refptr<AnimationPlayer> player2(AnimationPlayer::Create(player_id2)); + timeline->AttachPlayer(player2.get()); + + timeline->PushPropertiesTo(timeline_impl.get()); + + EXPECT_TRUE(timeline_impl->GetPlayerById(player_id1)); + EXPECT_TRUE(timeline_impl->GetPlayerById(player_id2)); + + timeline->ClearPlayers(); + EXPECT_FALSE(timeline->GetPlayerById(player_id1)); + EXPECT_FALSE(timeline->GetPlayerById(player_id2)); + + timeline_impl->ClearPlayers(); + EXPECT_FALSE(timeline_impl->GetPlayerById(player_id1)); + EXPECT_FALSE(timeline_impl->GetPlayerById(player_id2)); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/animation/element_animations.cc b/chromium/cc/animation/element_animations.cc new file mode 100644 index 00000000000..2974bff91a2 --- /dev/null +++ b/chromium/cc/animation/element_animations.cc @@ -0,0 +1,250 @@ +// Copyright 2015 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/animation/element_animations.h" + +#include "cc/animation/animation_host.h" +#include "cc/animation/animation_player.h" +#include "cc/animation/animation_registrar.h" +#include "cc/animation/layer_animation_value_observer.h" +#include "cc/trees/mutator_host_client.h" + +namespace cc { + +class ElementAnimations::ValueObserver : public LayerAnimationValueObserver { + public: + ValueObserver(ElementAnimations* element_animation, LayerTreeType tree_type) + : element_animations_(element_animation), tree_type_(tree_type) { + DCHECK(element_animations_); + } + + // LayerAnimationValueObserver implementation. + void OnFilterAnimated(const FilterOperations& filters) override { + element_animations_->SetFilterMutated(tree_type_, filters); + } + + void OnOpacityAnimated(float opacity) override { + element_animations_->SetOpacityMutated(tree_type_, opacity); + } + + void OnTransformAnimated(const gfx::Transform& transform) override { + element_animations_->SetTransformMutated(tree_type_, transform); + } + + void OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) override { + element_animations_->SetScrollOffsetMutated(tree_type_, scroll_offset); + } + + void OnAnimationWaitingForDeletion() override { + // TODO(loyso): See Layer::OnAnimationWaitingForDeletion. But we always do + // PushProperties for AnimationTimelines for now. + } + + bool IsActive() const override { return tree_type_ == LayerTreeType::ACTIVE; } + + private: + ElementAnimations* element_animations_; + const LayerTreeType tree_type_; + + DISALLOW_COPY_AND_ASSIGN(ValueObserver); +}; + +scoped_ptr<ElementAnimations> ElementAnimations::Create(AnimationHost* host) { + return make_scoped_ptr(new ElementAnimations(host)); +} + +ElementAnimations::ElementAnimations(AnimationHost* host) + : players_list_(make_scoped_ptr(new PlayersList())), animation_host_(host) { + DCHECK(animation_host_); +} + +ElementAnimations::~ElementAnimations() { + DCHECK(!layer_animation_controller_); +} + +void ElementAnimations::CreateLayerAnimationController(int layer_id) { + DCHECK(layer_id); + DCHECK(!layer_animation_controller_); + DCHECK(animation_host_); + + AnimationRegistrar* registrar = animation_host_->animation_registrar(); + DCHECK(registrar); + + layer_animation_controller_ = + registrar->GetAnimationControllerForId(layer_id); + layer_animation_controller_->SetAnimationRegistrar(registrar); + layer_animation_controller_->set_layer_animation_delegate(this); + layer_animation_controller_->set_value_provider(this); + + DCHECK(animation_host_->mutator_host_client()); + if (animation_host_->mutator_host_client()->IsLayerInTree( + layer_id, LayerTreeType::ACTIVE)) + CreateActiveValueObserver(); + if (animation_host_->mutator_host_client()->IsLayerInTree( + layer_id, LayerTreeType::PENDING)) + CreatePendingValueObserver(); +} + +void ElementAnimations::DestroyLayerAnimationController() { + DCHECK(animation_host_); + + DestroyPendingValueObserver(); + DestroyActiveValueObserver(); + + if (layer_animation_controller_) { + layer_animation_controller_->remove_value_provider(this); + layer_animation_controller_->remove_layer_animation_delegate(this); + layer_animation_controller_->SetAnimationRegistrar(nullptr); + layer_animation_controller_ = nullptr; + } +} + +void ElementAnimations::LayerRegistered(int layer_id, LayerTreeType tree_type) { + DCHECK(layer_animation_controller_); + DCHECK_EQ(layer_animation_controller_->id(), layer_id); + + if (tree_type == LayerTreeType::ACTIVE) { + if (!active_value_observer_) + CreateActiveValueObserver(); + } else { + if (!pending_value_observer_) + CreatePendingValueObserver(); + } +} + +void ElementAnimations::LayerUnregistered(int layer_id, + LayerTreeType tree_type) { + DCHECK_EQ(this->layer_id(), layer_id); + tree_type == LayerTreeType::ACTIVE ? DestroyActiveValueObserver() + : DestroyPendingValueObserver(); +} + +void ElementAnimations::AddPlayer(AnimationPlayer* player) { + players_list_->Append(player); +} + +void ElementAnimations::RemovePlayer(AnimationPlayer* player) { + for (PlayersListNode* node = players_list_->head(); + node != players_list_->end(); node = node->next()) { + if (node->value() == player) { + node->RemoveFromList(); + return; + } + } +} + +bool ElementAnimations::IsEmpty() const { + return players_list_->empty(); +} + +void ElementAnimations::PushPropertiesTo( + ElementAnimations* element_animations_impl) { + DCHECK(layer_animation_controller_); + DCHECK(element_animations_impl->layer_animation_controller()); + + layer_animation_controller_->PushAnimationUpdatesTo( + element_animations_impl->layer_animation_controller()); +} + +void ElementAnimations::SetFilterMutated(LayerTreeType tree_type, + const FilterOperations& filters) { + DCHECK(layer_id()); + DCHECK(animation_host()); + DCHECK(animation_host()->mutator_host_client()); + animation_host()->mutator_host_client()->SetLayerFilterMutated( + layer_id(), tree_type, filters); +} + +void ElementAnimations::SetOpacityMutated(LayerTreeType tree_type, + float opacity) { + DCHECK(layer_id()); + DCHECK(animation_host()); + DCHECK(animation_host()->mutator_host_client()); + animation_host()->mutator_host_client()->SetLayerOpacityMutated( + layer_id(), tree_type, opacity); +} + +void ElementAnimations::SetTransformMutated(LayerTreeType tree_type, + const gfx::Transform& transform) { + DCHECK(layer_id()); + DCHECK(animation_host()); + DCHECK(animation_host()->mutator_host_client()); + animation_host()->mutator_host_client()->SetLayerTransformMutated( + layer_id(), tree_type, transform); +} + +void ElementAnimations::SetScrollOffsetMutated( + LayerTreeType tree_type, + const gfx::ScrollOffset& scroll_offset) { + DCHECK(layer_id()); + DCHECK(animation_host()); + DCHECK(animation_host()->mutator_host_client()); + animation_host()->mutator_host_client()->SetLayerScrollOffsetMutated( + layer_id(), tree_type, scroll_offset); +} + +void ElementAnimations::CreateActiveValueObserver() { + DCHECK(layer_animation_controller_); + DCHECK(!active_value_observer_); + active_value_observer_ = + make_scoped_ptr(new ValueObserver(this, LayerTreeType::ACTIVE)); + layer_animation_controller_->AddValueObserver(active_value_observer_.get()); +} + +void ElementAnimations::DestroyActiveValueObserver() { + if (layer_animation_controller_ && active_value_observer_) + layer_animation_controller_->RemoveValueObserver( + active_value_observer_.get()); + active_value_observer_ = nullptr; +} + +void ElementAnimations::CreatePendingValueObserver() { + DCHECK(layer_animation_controller_); + DCHECK(!pending_value_observer_); + pending_value_observer_ = + make_scoped_ptr(new ValueObserver(this, LayerTreeType::PENDING)); + layer_animation_controller_->AddValueObserver(pending_value_observer_.get()); +} + +void ElementAnimations::DestroyPendingValueObserver() { + if (layer_animation_controller_ && pending_value_observer_) + layer_animation_controller_->RemoveValueObserver( + pending_value_observer_.get()); + pending_value_observer_ = nullptr; +} + +void ElementAnimations::NotifyAnimationStarted( + base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) { + for (PlayersListNode* node = players_list_->head(); + node != players_list_->end(); node = node->next()) { + AnimationPlayer* player = node->value(); + player->NotifyAnimationStarted(monotonic_time, target_property, group); + } +} + +void ElementAnimations::NotifyAnimationFinished( + base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) { + for (PlayersListNode* node = players_list_->head(); + node != players_list_->end(); node = node->next()) { + AnimationPlayer* player = node->value(); + player->NotifyAnimationFinished(monotonic_time, target_property, group); + } +} + +gfx::ScrollOffset ElementAnimations::ScrollOffsetForAnimation() const { + DCHECK(layer_animation_controller_); + if (animation_host()) { + DCHECK(animation_host()->mutator_host_client()); + return animation_host()->mutator_host_client()->GetScrollOffsetForAnimation( + layer_id()); + } + + return gfx::ScrollOffset(); +} + +} // namespace cc diff --git a/chromium/cc/animation/element_animations.h b/chromium/cc/animation/element_animations.h new file mode 100644 index 00000000000..6fb2a429d4a --- /dev/null +++ b/chromium/cc/animation/element_animations.h @@ -0,0 +1,119 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_ANIMATION_ELEMENT_ANIMATIONS_H_ +#define CC_ANIMATION_ELEMENT_ANIMATIONS_H_ + +#include "base/containers/linked_list.h" +#include "base/memory/ref_counted.h" +#include "cc/animation/animation_delegate.h" +#include "cc/animation/layer_animation_controller.h" +#include "cc/animation/layer_animation_value_provider.h" +#include "cc/base/cc_export.h" + +namespace gfx { +class ScrollOffset; +class Transform; +} + +namespace cc { + +class AnimationHost; +class AnimationPlayer; +class FilterOperations; +class LayerAnimationController; +enum class LayerTreeType; + +// An ElementAnimations owns a list of all AnimationPlayers, attached to +// the layer. Also, it owns LayerAnimationController instance (1:1 +// relationship) +// ElementAnimations object redirects all events from LAC to the list +// of animation layers. +// This is a CC counterpart for blink::ElementAnimations (in 1:1 relationship). +// No pointer to/from respective blink::ElementAnimations object for now. +class CC_EXPORT ElementAnimations : public AnimationDelegate, + public LayerAnimationValueProvider { + public: + static scoped_ptr<ElementAnimations> Create(AnimationHost* host); + ~ElementAnimations() override; + + int layer_id() const { + return layer_animation_controller_ ? layer_animation_controller_->id() : 0; + } + + // Parent AnimationHost. + AnimationHost* animation_host() { return animation_host_; } + const AnimationHost* animation_host() const { return animation_host_; } + + LayerAnimationController* layer_animation_controller() const { + return layer_animation_controller_.get(); + } + + void CreateLayerAnimationController(int layer_id); + void DestroyLayerAnimationController(); + + void LayerRegistered(int layer_id, LayerTreeType tree_type); + void LayerUnregistered(int layer_id, LayerTreeType tree_type); + + bool has_active_value_observer_for_testing() const { + return active_value_observer_; + } + bool has_pending_value_observer_for_testing() const { + return pending_value_observer_; + } + + void AddPlayer(AnimationPlayer* player); + void RemovePlayer(AnimationPlayer* player); + bool IsEmpty() const; + + typedef base::LinkedList<AnimationPlayer> PlayersList; + typedef base::LinkNode<AnimationPlayer> PlayersListNode; + const PlayersList& players_list() const { return *players_list_.get(); } + + void PushPropertiesTo(ElementAnimations* element_animations_impl); + + private: + explicit ElementAnimations(AnimationHost* host); + + void SetFilterMutated(LayerTreeType tree_type, + const FilterOperations& filters); + void SetOpacityMutated(LayerTreeType tree_type, float opacity); + void SetTransformMutated(LayerTreeType tree_type, + const gfx::Transform& transform); + void SetScrollOffsetMutated(LayerTreeType tree_type, + const gfx::ScrollOffset& scroll_offset); + + void CreateActiveValueObserver(); + void DestroyActiveValueObserver(); + + void CreatePendingValueObserver(); + void DestroyPendingValueObserver(); + + // AnimationDelegate implementation + void NotifyAnimationStarted(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override; + void NotifyAnimationFinished(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override; + + // LayerAnimationValueProvider implementation. + gfx::ScrollOffset ScrollOffsetForAnimation() const override; + + scoped_ptr<PlayersList> players_list_; + + class ValueObserver; + scoped_ptr<ValueObserver> active_value_observer_; + scoped_ptr<ValueObserver> pending_value_observer_; + + // LAC is owned by ElementAnimations (1:1 relationship). + scoped_refptr<LayerAnimationController> layer_animation_controller_; + AnimationHost* animation_host_; + + DISALLOW_COPY_AND_ASSIGN(ElementAnimations); +}; + +} // namespace cc + +#endif // CC_ANIMATION_ELEMENT_ANIMATIONS_H_ diff --git a/chromium/cc/animation/element_animations_unittest.cc b/chromium/cc/animation/element_animations_unittest.cc new file mode 100644 index 00000000000..b676906c3c8 --- /dev/null +++ b/chromium/cc/animation/element_animations_unittest.cc @@ -0,0 +1,218 @@ +// Copyright 2015 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/animation/element_animations.h" + +#include "cc/animation/animation_delegate.h" +#include "cc/animation/animation_host.h" +#include "cc/animation/animation_id_provider.h" +#include "cc/animation/animation_player.h" +#include "cc/animation/animation_registrar.h" +#include "cc/animation/animation_timeline.h" +#include "cc/test/animation_test_common.h" +#include "cc/test/animation_timelines_test_common.h" + +namespace cc { +namespace { + +class ElementAnimationsTest : public AnimationTimelinesTest { + public: + ElementAnimationsTest() {} + ~ElementAnimationsTest() override {} +}; + +// See animation_player_unittest.cc for integration with AnimationPlayer. + +TEST_F(ElementAnimationsTest, AttachToLayerInActiveTree) { + // Set up the layer which is in active tree for main thread and not + // yet passed onto the impl thread. + client_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + client_impl_.RegisterLayer(layer_id_, LayerTreeType::PENDING); + + EXPECT_TRUE(client_.IsLayerInTree(layer_id_, LayerTreeType::ACTIVE)); + EXPECT_FALSE(client_.IsLayerInTree(layer_id_, LayerTreeType::PENDING)); + + host_->AddAnimationTimeline(timeline_); + + timeline_->AttachPlayer(player_); + player_->AttachLayer(layer_id_); + + ElementAnimations* element_animations = player_->element_animations(); + EXPECT_TRUE(element_animations); + + EXPECT_TRUE(element_animations->has_active_value_observer_for_testing()); + EXPECT_FALSE(element_animations->has_pending_value_observer_for_testing()); + + host_->PushPropertiesTo(host_impl_); + + GetImplTimelineAndPlayerByID(); + + ElementAnimations* element_animations_impl = + player_impl_->element_animations(); + EXPECT_TRUE(element_animations_impl); + + EXPECT_FALSE( + element_animations_impl->has_active_value_observer_for_testing()); + EXPECT_TRUE( + element_animations_impl->has_pending_value_observer_for_testing()); + + // Create the layer in the impl active tree. + client_impl_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + EXPECT_TRUE(element_animations_impl->has_active_value_observer_for_testing()); + EXPECT_TRUE( + element_animations_impl->has_pending_value_observer_for_testing()); + + EXPECT_TRUE(client_impl_.IsLayerInTree(layer_id_, LayerTreeType::ACTIVE)); + EXPECT_TRUE(client_impl_.IsLayerInTree(layer_id_, LayerTreeType::PENDING)); + + // kill layer on main thread. + client_.UnregisterLayer(layer_id_, LayerTreeType::ACTIVE); + EXPECT_EQ(element_animations, player_->element_animations()); + EXPECT_FALSE(element_animations->has_active_value_observer_for_testing()); + EXPECT_FALSE(element_animations->has_pending_value_observer_for_testing()); + + // Sync doesn't detach LayerImpl. + host_->PushPropertiesTo(host_impl_); + EXPECT_EQ(element_animations_impl, player_impl_->element_animations()); + EXPECT_TRUE(element_animations_impl->has_active_value_observer_for_testing()); + EXPECT_TRUE( + element_animations_impl->has_pending_value_observer_for_testing()); + + // Kill layer on impl thread in pending tree. + client_impl_.UnregisterLayer(layer_id_, LayerTreeType::PENDING); + EXPECT_EQ(element_animations_impl, player_impl_->element_animations()); + EXPECT_TRUE(element_animations_impl->has_active_value_observer_for_testing()); + EXPECT_FALSE( + element_animations_impl->has_pending_value_observer_for_testing()); + + // Kill layer on impl thread in active tree. + client_impl_.UnregisterLayer(layer_id_, LayerTreeType::ACTIVE); + EXPECT_EQ(element_animations_impl, player_impl_->element_animations()); + EXPECT_FALSE( + element_animations_impl->has_active_value_observer_for_testing()); + EXPECT_FALSE( + element_animations_impl->has_pending_value_observer_for_testing()); + + // Sync doesn't change anything. + host_->PushPropertiesTo(host_impl_); + EXPECT_EQ(element_animations_impl, player_impl_->element_animations()); + EXPECT_FALSE( + element_animations_impl->has_active_value_observer_for_testing()); + EXPECT_FALSE( + element_animations_impl->has_pending_value_observer_for_testing()); + + player_->DetachLayer(); + EXPECT_FALSE(player_->element_animations()); + + // Release ptrs now to test the order of destruction. + ReleaseRefPtrs(); +} + +TEST_F(ElementAnimationsTest, AttachToNotYetCreatedLayer) { + host_->AddAnimationTimeline(timeline_); + timeline_->AttachPlayer(player_); + + host_->PushPropertiesTo(host_impl_); + + GetImplTimelineAndPlayerByID(); + + player_->AttachLayer(layer_id_); + + ElementAnimations* element_animations = player_->element_animations(); + EXPECT_TRUE(element_animations); + + EXPECT_FALSE(element_animations->has_active_value_observer_for_testing()); + EXPECT_FALSE(element_animations->has_pending_value_observer_for_testing()); + + host_->PushPropertiesTo(host_impl_); + + ElementAnimations* element_animations_impl = + player_impl_->element_animations(); + EXPECT_TRUE(element_animations_impl); + + EXPECT_FALSE( + element_animations_impl->has_active_value_observer_for_testing()); + EXPECT_FALSE( + element_animations_impl->has_pending_value_observer_for_testing()); + + // Create layer. + client_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + EXPECT_TRUE(element_animations->has_active_value_observer_for_testing()); + EXPECT_FALSE(element_animations->has_pending_value_observer_for_testing()); + + client_impl_.RegisterLayer(layer_id_, LayerTreeType::PENDING); + EXPECT_FALSE( + element_animations_impl->has_active_value_observer_for_testing()); + EXPECT_TRUE( + element_animations_impl->has_pending_value_observer_for_testing()); + + client_impl_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE); + EXPECT_TRUE(element_animations_impl->has_active_value_observer_for_testing()); + EXPECT_TRUE( + element_animations_impl->has_pending_value_observer_for_testing()); +} + +TEST_F(ElementAnimationsTest, AddRemovePlayers) { + host_->AddAnimationTimeline(timeline_); + timeline_->AttachPlayer(player_); + player_->AttachLayer(layer_id_); + + ElementAnimations* element_animations = player_->element_animations(); + EXPECT_TRUE(element_animations); + + scoped_refptr<AnimationPlayer> player1 = + AnimationPlayer::Create(AnimationIdProvider::NextPlayerId()); + scoped_refptr<AnimationPlayer> player2 = + AnimationPlayer::Create(AnimationIdProvider::NextPlayerId()); + + timeline_->AttachPlayer(player1); + timeline_->AttachPlayer(player2); + + // Attach players to the same layer. + player1->AttachLayer(layer_id_); + player2->AttachLayer(layer_id_); + + EXPECT_EQ(element_animations, player1->element_animations()); + EXPECT_EQ(element_animations, player2->element_animations()); + + host_->PushPropertiesTo(host_impl_); + GetImplTimelineAndPlayerByID(); + + ElementAnimations* element_animations_impl = + player_impl_->element_animations(); + EXPECT_TRUE(element_animations_impl); + + int list_size_before = 0; + for (const ElementAnimations::PlayersListNode* node = + element_animations_impl->players_list().head(); + node != element_animations_impl->players_list().end(); + node = node->next()) { + const AnimationPlayer* player_impl = node->value(); + EXPECT_TRUE(timeline_->GetPlayerById(player_impl->id())); + ++list_size_before; + } + EXPECT_EQ(3, list_size_before); + + player2->DetachLayer(); + EXPECT_FALSE(player2->element_animations()); + EXPECT_EQ(element_animations, player_->element_animations()); + EXPECT_EQ(element_animations, player1->element_animations()); + + host_->PushPropertiesTo(host_impl_); + EXPECT_EQ(element_animations_impl, player_impl_->element_animations()); + + int list_size_after = 0; + for (const ElementAnimations::PlayersListNode* node = + element_animations_impl->players_list().head(); + node != element_animations_impl->players_list().end(); + node = node->next()) { + const AnimationPlayer* player_impl = node->value(); + EXPECT_TRUE(timeline_->GetPlayerById(player_impl->id())); + ++list_size_after; + } + EXPECT_EQ(2, list_size_after); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/animation/layer_animation_controller.cc b/chromium/cc/animation/layer_animation_controller.cc index 91bfe54e159..54b1a717f78 100644 --- a/chromium/cc/animation/layer_animation_controller.cc +++ b/chromium/cc/animation/layer_animation_controller.cc @@ -584,15 +584,6 @@ void LayerAnimationController::PushNewAnimationsToImplThread( if (controller_impl->GetAnimationById(animations_[i]->id())) continue; - // If the animation is not running on the impl thread, it does not - // necessarily mean that it needs to be copied over and started; it may - // have already finished. In this case, the impl thread animation will - // have already notified that it has started and the main thread animation - // will no longer need - // a synchronized start time. - if (!animations_[i]->needs_synchronized_start_time()) - continue; - // Scroll animations always start at the current scroll offset. if (animations_[i]->target_property() == Animation::SCROLL_OFFSET) { gfx::ScrollOffset current_scroll_offset; @@ -764,9 +755,14 @@ void LayerAnimationController::PromoteStartedAnimations( !animations_[i]->needs_synchronized_start_time()) animations_[i]->set_start_time(monotonic_time); if (events) { + base::TimeTicks start_time; + if (animations_[i]->has_set_start_time()) + start_time = animations_[i]->start_time(); + else + start_time = monotonic_time; AnimationEvent started_event( AnimationEvent::STARTED, id_, animations_[i]->group(), - animations_[i]->target_property(), monotonic_time); + animations_[i]->target_property(), start_time); started_event.is_impl_only = animations_[i]->is_impl_only(); if (started_event.is_impl_only) NotifyAnimationStarted(started_event); @@ -819,7 +815,9 @@ void LayerAnimationController::MarkAnimationsForDeletion( // on the impl thread, we only mark a FINISHED main thread animation for // deletion once it has received a FINISHED event from the impl thread. bool animation_i_will_send_or_has_received_finish_event = - events || animations_[i]->received_finished_event(); + animations_[i]->is_controlling_instance() || + animations_[i]->is_impl_only() || + animations_[i]->received_finished_event(); // If an animation is finished, and not already marked for deletion, // find out if all other animations in the same group are also finished. if (animations_[i]->run_state() == Animation::FINISHED && @@ -831,7 +829,9 @@ void LayerAnimationController::MarkAnimationsForDeletion( all_anims_with_same_id_are_finished = true; for (size_t j = 0; j < animations_.size(); ++j) { bool animation_j_will_send_or_has_received_finish_event = - events || animations_[j]->received_finished_event(); + animations_[j]->is_controlling_instance() || + animations_[j]->is_impl_only() || + animations_[j]->received_finished_event(); if (group_id == animations_[j]->group()) { if (!animations_[j]->is_finished() || (animations_[j]->run_state() == Animation::FINISHED && @@ -984,7 +984,7 @@ void LayerAnimationController::NotifyObserversOpacityAnimated( bool notify_active_observers, bool notify_pending_observers) { if (value_observers_.might_have_observers()) { - ObserverListBase<LayerAnimationValueObserver>::Iterator it( + base::ObserverListBase<LayerAnimationValueObserver>::Iterator it( &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) { @@ -1001,7 +1001,7 @@ void LayerAnimationController::NotifyObserversTransformAnimated( bool notify_active_observers, bool notify_pending_observers) { if (value_observers_.might_have_observers()) { - ObserverListBase<LayerAnimationValueObserver>::Iterator it( + base::ObserverListBase<LayerAnimationValueObserver>::Iterator it( &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) { @@ -1018,7 +1018,7 @@ void LayerAnimationController::NotifyObserversFilterAnimated( bool notify_active_observers, bool notify_pending_observers) { if (value_observers_.might_have_observers()) { - ObserverListBase<LayerAnimationValueObserver>::Iterator it( + base::ObserverListBase<LayerAnimationValueObserver>::Iterator it( &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) { @@ -1035,7 +1035,7 @@ void LayerAnimationController::NotifyObserversScrollOffsetAnimated( bool notify_active_observers, bool notify_pending_observers) { if (value_observers_.might_have_observers()) { - ObserverListBase<LayerAnimationValueObserver>::Iterator it( + base::ObserverListBase<LayerAnimationValueObserver>::Iterator it( &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) { @@ -1055,7 +1055,7 @@ void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() { bool LayerAnimationController::HasValueObserver() { if (value_observers_.might_have_observers()) { - ObserverListBase<LayerAnimationValueObserver>::Iterator it( + base::ObserverListBase<LayerAnimationValueObserver>::Iterator it( &value_observers_); return it.GetNext() != nullptr; } @@ -1064,7 +1064,7 @@ bool LayerAnimationController::HasValueObserver() { bool LayerAnimationController::HasActiveValueObserver() { if (value_observers_.might_have_observers()) { - ObserverListBase<LayerAnimationValueObserver>::Iterator it( + base::ObserverListBase<LayerAnimationValueObserver>::Iterator it( &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) diff --git a/chromium/cc/animation/layer_animation_controller.h b/chromium/cc/animation/layer_animation_controller.h index 1ac76fa393e..4b37ad44930 100644 --- a/chromium/cc/animation/layer_animation_controller.h +++ b/chromium/cc/animation/layer_animation_controller.h @@ -215,8 +215,8 @@ class CC_EXPORT LayerAnimationController base::TimeTicks last_tick_time_; - ObserverList<LayerAnimationValueObserver> value_observers_; - ObserverList<LayerAnimationEventObserver> event_observers_; + base::ObserverList<LayerAnimationValueObserver> value_observers_; + base::ObserverList<LayerAnimationEventObserver> event_observers_; LayerAnimationValueProvider* value_provider_; diff --git a/chromium/cc/animation/layer_animation_controller_unittest.cc b/chromium/cc/animation/layer_animation_controller_unittest.cc index ad1d4c9eece..e267eea1288 100644 --- a/chromium/cc/animation/layer_animation_controller_unittest.cc +++ b/chromium/cc/animation/layer_animation_controller_unittest.cc @@ -298,12 +298,13 @@ TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) { scoped_refptr<LayerAnimationController> controller( LayerAnimationController::Create(0)); controller->AddValueObserver(&dummy); + scoped_ptr<AnimationEventsVector> events( + make_scoped_ptr(new AnimationEventsVector)); EXPECT_FALSE(controller_impl->GetAnimation(Animation::OPACITY)); int animation_id = AddOpacityTransitionToController(controller.get(), 1, 0, 1, false); - int group_id = controller->GetAnimationById(animation_id)->group(); controller->PushAnimationUpdatesTo(controller_impl.get()); controller_impl->ActivateAnimations(); @@ -312,21 +313,30 @@ TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) { EXPECT_EQ(Animation::WAITING_FOR_TARGET_AVAILABILITY, controller_impl->GetAnimationById(animation_id)->run_state()); + events.reset(new AnimationEventsVector); + controller_impl->Animate(kInitialTickTime); + controller_impl->UpdateState(true, events.get()); + EXPECT_EQ(1u, events->size()); + EXPECT_EQ(AnimationEvent::STARTED, (*events)[0].type); + // Notify main thread controller that the animation has started. - AnimationEvent animation_started_event(AnimationEvent::STARTED, 0, group_id, - Animation::OPACITY, kInitialTickTime); - controller->NotifyAnimationStarted(animation_started_event); + controller->NotifyAnimationStarted((*events)[0]); - // Force animation to complete on impl thread. - controller_impl->RemoveAnimation(animation_id); + // Complete animation on impl thread. + events.reset(new AnimationEventsVector); + controller_impl->Animate(kInitialTickTime + TimeDelta::FromSeconds(1)); + controller_impl->UpdateState(true, events.get()); + EXPECT_EQ(1u, events->size()); + EXPECT_EQ(AnimationEvent::FINISHED, (*events)[0].type); - EXPECT_FALSE(controller_impl->GetAnimationById(animation_id)); + controller->NotifyAnimationFinished((*events)[0]); + + controller->Animate(kInitialTickTime + TimeDelta::FromSeconds(2)); + controller->UpdateState(true, nullptr); controller->PushAnimationUpdatesTo(controller_impl.get()); controller_impl->ActivateAnimations(); - - // Even though the main thread has a 'new' animation, it should not be pushed - // because the animation has already completed on the impl thread. + EXPECT_FALSE(controller->GetAnimationById(animation_id)); EXPECT_FALSE(controller_impl->GetAnimationById(animation_id)); } @@ -936,13 +946,13 @@ TEST(LayerAnimationControllerTest, ScrollOffsetRemovalClearsScrollDelta) { class FakeAnimationDelegate : public AnimationDelegate { public: FakeAnimationDelegate() - : started_(false), - finished_(false) {} + : started_(false), finished_(false), start_time_(base::TimeTicks()) {} void NotifyAnimationStarted(TimeTicks monotonic_time, Animation::TargetProperty target_property, int group) override { started_ = true; + start_time_ = monotonic_time; } void NotifyAnimationFinished(TimeTicks monotonic_time, @@ -955,9 +965,12 @@ class FakeAnimationDelegate : public AnimationDelegate { bool finished() { return finished_; } + TimeTicks start_time() { return start_time_; } + private: bool started_; bool finished_; + TimeTicks start_time_; }; // Tests that impl-only animations lead to start and finished notifications @@ -997,6 +1010,97 @@ TEST(LayerAnimationControllerTest, EXPECT_TRUE(delegate.finished()); } +// Tests that specified start times are sent to the main thread delegate +TEST(LayerAnimationControllerTest, + SpecifiedStartTimesAreSentToMainThreadDelegate) { + FakeLayerAnimationValueObserver dummy_impl; + scoped_refptr<LayerAnimationController> controller_impl( + LayerAnimationController::Create(0)); + controller_impl->AddValueObserver(&dummy_impl); + FakeLayerAnimationValueObserver dummy; + scoped_refptr<LayerAnimationController> controller( + LayerAnimationController::Create(0)); + controller->AddValueObserver(&dummy); + FakeAnimationDelegate delegate; + controller->set_layer_animation_delegate(&delegate); + + int animation_id = + AddOpacityTransitionToController(controller.get(), 1, 0, 1, false); + + const TimeTicks start_time = TicksFromSecondsF(123); + controller->GetAnimation(Animation::OPACITY)->set_start_time(start_time); + + controller->PushAnimationUpdatesTo(controller_impl.get()); + controller_impl->ActivateAnimations(); + + EXPECT_TRUE(controller_impl->GetAnimationById(animation_id)); + EXPECT_EQ(Animation::WAITING_FOR_TARGET_AVAILABILITY, + controller_impl->GetAnimationById(animation_id)->run_state()); + + AnimationEventsVector events; + controller_impl->Animate(kInitialTickTime); + controller_impl->UpdateState(true, &events); + + // Synchronize the start times. + EXPECT_EQ(1u, events.size()); + controller->NotifyAnimationStarted(events[0]); + + // Validate start time on the main thread delegate. + EXPECT_EQ(start_time, delegate.start_time()); +} + +class FakeLayerAnimationEventObserver : public LayerAnimationEventObserver { + public: + FakeLayerAnimationEventObserver() : start_time_(base::TimeTicks()) {} + + void OnAnimationStarted(const AnimationEvent& event) override { + start_time_ = event.monotonic_time; + } + + TimeTicks start_time() { return start_time_; } + + private: + TimeTicks start_time_; +}; + +// Tests that specified start times are sent to the event observers +TEST(LayerAnimationControllerTest, SpecifiedStartTimesAreSentToEventObservers) { + FakeLayerAnimationValueObserver dummy_impl; + scoped_refptr<LayerAnimationController> controller_impl( + LayerAnimationController::Create(0)); + controller_impl->AddValueObserver(&dummy_impl); + FakeLayerAnimationValueObserver dummy; + scoped_refptr<LayerAnimationController> controller( + LayerAnimationController::Create(0)); + controller->AddValueObserver(&dummy); + FakeLayerAnimationEventObserver observer; + controller->AddEventObserver(&observer); + + int animation_id = + AddOpacityTransitionToController(controller.get(), 1, 0, 1, false); + + const TimeTicks start_time = TicksFromSecondsF(123); + controller->GetAnimation(Animation::OPACITY)->set_start_time(start_time); + + controller->PushAnimationUpdatesTo(controller_impl.get()); + controller_impl->ActivateAnimations(); + + EXPECT_TRUE(controller_impl->GetAnimationById(animation_id)); + EXPECT_EQ(Animation::WAITING_FOR_TARGET_AVAILABILITY, + controller_impl->GetAnimationById(animation_id)->run_state()); + + AnimationEventsVector events; + controller_impl->Animate(kInitialTickTime); + controller_impl->UpdateState(true, &events); + + // Synchronize the start times. + EXPECT_EQ(1u, events.size()); + controller->NotifyAnimationStarted(events[0]); + + // Validate start time on the event observer. + EXPECT_EQ(start_time, observer.start_time()); +} + // Tests animations that are waiting for a synchronized start time do not // finish. TEST(LayerAnimationControllerTest, @@ -1423,16 +1527,20 @@ TEST(LayerAnimationControllerTest, SkipUpdateState) { LayerAnimationController::Create(0)); controller->AddValueObserver(&dummy); - controller->AddAnimation(CreateAnimation( + scoped_ptr<Animation> first_animation(CreateAnimation( scoped_ptr<AnimationCurve>(new FakeTransformTransition(1)).Pass(), 1, Animation::TRANSFORM)); + first_animation->set_is_controlling_instance_for_test(true); + controller->AddAnimation(first_animation.Pass()); controller->Animate(kInitialTickTime); controller->UpdateState(true, events.get()); - controller->AddAnimation(CreateAnimation( + scoped_ptr<Animation> second_animation(CreateAnimation( scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), 2, Animation::OPACITY)); + second_animation->set_is_controlling_instance_for_test(true); + controller->AddAnimation(second_animation.Pass()); // Animate but don't UpdateState. controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000)); @@ -1734,12 +1842,17 @@ TEST(LayerAnimationControllerTest, FinishedEventsForGroup) { const int group_id = 1; // Add two animations with the same group id but different durations. - controller_impl->AddAnimation(Animation::Create( + scoped_ptr<Animation> first_animation(Animation::Create( scoped_ptr<AnimationCurve>(new FakeTransformTransition(2.0)).Pass(), 1, group_id, Animation::TRANSFORM)); - controller_impl->AddAnimation(Animation::Create( + first_animation->set_is_controlling_instance_for_test(true); + controller_impl->AddAnimation(first_animation.Pass()); + + scoped_ptr<Animation> second_animation(Animation::Create( scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), 2, group_id, Animation::OPACITY)); + second_animation->set_is_controlling_instance_for_test(true); + controller_impl->AddAnimation(second_animation.Pass()); controller_impl->Animate(kInitialTickTime); controller_impl->UpdateState(true, events.get()); @@ -1784,12 +1897,17 @@ TEST(LayerAnimationControllerTest, FinishedAndAbortedEventsForGroup) { controller_impl->AddValueObserver(&dummy_impl); // Add two animations with the same group id. - controller_impl->AddAnimation(CreateAnimation( + scoped_ptr<Animation> first_animation(CreateAnimation( scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(), 1, Animation::TRANSFORM)); - controller_impl->AddAnimation(CreateAnimation( + first_animation->set_is_controlling_instance_for_test(true); + controller_impl->AddAnimation(first_animation.Pass()); + + scoped_ptr<Animation> second_animation(CreateAnimation( scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), 1, Animation::OPACITY)); + second_animation->set_is_controlling_instance_for_test(true); + controller_impl->AddAnimation(second_animation.Pass()); controller_impl->Animate(kInitialTickTime); controller_impl->UpdateState(true, events.get()); diff --git a/chromium/cc/animation/scroll_offset_animation_curve.cc b/chromium/cc/animation/scroll_offset_animation_curve.cc index 68761fbf8d1..17dff26b9ce 100644 --- a/chromium/cc/animation/scroll_offset_animation_curve.cc +++ b/chromium/cc/animation/scroll_offset_animation_curve.cc @@ -35,11 +35,18 @@ static base::TimeDelta DurationFromDelta(const gfx::Vector2dF& delta) { static scoped_ptr<TimingFunction> EaseOutWithInitialVelocity(double velocity) { // Based on EaseInOutTimingFunction::Create with first control point rotated. - const double r2 = 0.42 * 0.42; - const double v2 = velocity * velocity; - const double x1 = std::sqrt(r2 / (v2 + 1)); - const double y1 = std::sqrt(r2 * v2 / (v2 + 1)); - return CubicBezierTimingFunction::Create(x1, y1, 0.58, 1); + if (std::abs(velocity) < 1000.0) { + const double r2 = 0.42 * 0.42; + const double v2 = velocity * velocity; + const double x1 = std::sqrt(r2 / (v2 + 1)); + const double y1 = std::sqrt(r2 * v2 / (v2 + 1)); + return CubicBezierTimingFunction::Create(x1, y1, 0.58, 1); + } + + // For large |velocity|, x1 approaches 0 and y1 approaches 0.42. To avoid the + // risk of floating point arithmetic involving infinity and NaN, use those + // values directly rather than computing them above. + return CubicBezierTimingFunction::Create(0, 0.42, 0.58, 1); } } // namespace diff --git a/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc b/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc index 8aea905dfc2..58875136406 100644 --- a/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc +++ b/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc @@ -154,5 +154,28 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTarget) { EXPECT_EQ(7200.0, curve->GetValue(base::TimeDelta::FromSecondsD(1.674)).y()); } +TEST(ScrollOffsetAnimationCurveTest, UpdateTargetWithLargeVelocity) { + gfx::ScrollOffset initial_value(0.f, 0.f); + gfx::ScrollOffset target_value(0.f, 900.f); + scoped_ptr<ScrollOffsetAnimationCurve> curve( + ScrollOffsetAnimationCurve::Create( + target_value, EaseInOutTimingFunction::Create().Pass())); + curve->SetInitialValue(initial_value); + EXPECT_EQ(0.5, curve->Duration().InSecondsF()); + + EXPECT_EQ(450.0, curve->GetValue(base::TimeDelta::FromSecondsD(0.25)).y()); + + // This leads to a new computed velocity larger than 5000. + curve->UpdateTarget(0.25, gfx::ScrollOffset(0.0, 450.0001)); + + EXPECT_NEAR(0.25015, curve->Duration().InSecondsF(), 0.0001); + EXPECT_NEAR(450.0, + curve->GetValue(base::TimeDelta::FromSecondsD(0.22501)).y(), + 0.001); + EXPECT_NEAR(450.0, + curve->GetValue(base::TimeDelta::FromSecondsD(0.225015)).y(), + 0.001); +} + } // namespace } // namespace cc diff --git a/chromium/cc/animation/transform_operation.cc b/chromium/cc/animation/transform_operation.cc index 7421924aedc..e487921cdb4 100644 --- a/chromium/cc/animation/transform_operation.cc +++ b/chromium/cc/animation/transform_operation.cc @@ -41,7 +41,7 @@ static bool ShareSameAxis(const TransformOperation* from, if (IsOperationIdentity(from) && IsOperationIdentity(to)) return false; - if (IsOperationIdentity(from) && !IsOperationIdentity(to)) { + if (!from && !IsOperationIdentity(to)) { *axis_x = to->rotate.axis.x; *axis_y = to->rotate.axis.y; *axis_z = to->rotate.axis.z; @@ -49,7 +49,7 @@ static bool ShareSameAxis(const TransformOperation* from, return true; } - if (!IsOperationIdentity(from) && IsOperationIdentity(to)) { + if (!IsOperationIdentity(from) && !to) { *axis_x = from->rotate.axis.x; *axis_y = from->rotate.axis.y; *axis_z = from->rotate.axis.z; diff --git a/chromium/cc/animation/transform_operations.cc b/chromium/cc/animation/transform_operations.cc index 20e8c6a6587..6631a2a980b 100644 --- a/chromium/cc/animation/transform_operations.cc +++ b/chromium/cc/animation/transform_operations.cc @@ -58,25 +58,24 @@ bool TransformOperations::BlendedBoundsForBox(const gfx::BoxF& box, if (!MatchesTypes(from)) return false; - size_t num_operations = - std::max(from_identity ? 0 : from.operations_.size(), - to_identity ? 0 : operations_.size()); + size_t num_operations = std::max(from_identity ? 0 : from.operations_.size(), + to_identity ? 0 : operations_.size()); // Because we are squashing all of the matrices together when applying // them to the animation, we must apply them in reverse order when // not squashing them. - for (int i = num_operations - 1; i >= 0; --i) { + for (size_t i = 0; i < num_operations; ++i) { + size_t operation_index = num_operations - 1 - i; gfx::BoxF bounds_for_operation; const TransformOperation* from_op = - from_identity ? nullptr : &from.operations_[i]; - const TransformOperation* to_op = to_identity ? nullptr : &operations_[i]; - if (!TransformOperation::BlendedBoundsForBox(*bounds, - from_op, - to_op, - min_progress, - max_progress, - &bounds_for_operation)) + from_identity ? nullptr : &from.operations_[operation_index]; + const TransformOperation* to_op = + to_identity ? nullptr : &operations_[operation_index]; + if (!TransformOperation::BlendedBoundsForBox(*bounds, from_op, to_op, + min_progress, max_progress, + &bounds_for_operation)) { return false; + } *bounds = bounds_for_operation; } @@ -164,16 +163,14 @@ bool TransformOperations::ScaleComponent(gfx::Vector3dF* scale) const { } bool TransformOperations::MatchesTypes(const TransformOperations& other) const { - if (IsIdentity() || other.IsIdentity()) + if (operations_.size() == 0 || other.operations_.size() == 0) return true; if (operations_.size() != other.operations_.size()) return false; for (size_t i = 0; i < operations_.size(); ++i) { - if (operations_[i].type != other.operations_[i].type - && !operations_[i].IsIdentity() - && !other.operations_[i].IsIdentity()) + if (operations_[i].type != other.operations_[i].type) return false; } @@ -280,10 +277,9 @@ bool TransformOperations::BlendInternal(const TransformOperations& from, for (size_t i = 0; i < num_operations; ++i) { gfx::Transform blended; if (!TransformOperation::BlendTransformOperations( - from_identity ? 0 : &from.operations_[i], - to_identity ? 0 : &operations_[i], - progress, - &blended)) + from.operations_.size() <= i ? 0 : &from.operations_[i], + operations_.size() <= i ? 0 : &operations_[i], progress, + &blended)) return false; result->PreconcatTransform(blended); } diff --git a/chromium/cc/animation/transform_operations_unittest.cc b/chromium/cc/animation/transform_operations_unittest.cc index 7aae696db4c..a5cf7ec9619 100644 --- a/chromium/cc/animation/transform_operations_unittest.cc +++ b/chromium/cc/animation/transform_operations_unittest.cc @@ -139,14 +139,34 @@ void GetIdentityOperations(ScopedVector<TransformOperations>* operations) { operations->push_back(to_add); } -TEST(TransformOperationTest, IdentityAlwaysMatches) { +TEST(TransformOperationTest, MatchTypesOrder) { + TransformOperations mix_order_identity; + mix_order_identity.AppendTranslate(0, 0, 0); + mix_order_identity.AppendScale(1, 1, 1); + mix_order_identity.AppendTranslate(0, 0, 0); + + TransformOperations mix_order_one; + mix_order_one.AppendTranslate(0, 1, 0); + mix_order_one.AppendScale(2, 1, 3); + mix_order_one.AppendTranslate(1, 0, 0); + + TransformOperations mix_order_two; + mix_order_two.AppendTranslate(0, 1, 0); + mix_order_two.AppendTranslate(1, 0, 0); + mix_order_two.AppendScale(2, 1, 3); + + EXPECT_TRUE(mix_order_identity.MatchesTypes(mix_order_one)); + EXPECT_FALSE(mix_order_identity.MatchesTypes(mix_order_two)); + EXPECT_FALSE(mix_order_one.MatchesTypes(mix_order_two)); +} + +TEST(TransformOperationTest, NoneAlwaysMatches) { ScopedVector<TransformOperations> operations; GetIdentityOperations(&operations); - for (size_t i = 0; i < operations.size(); ++i) { - for (size_t j = 0; j < operations.size(); ++j) - EXPECT_TRUE(operations[i]->MatchesTypes(*operations[j])); - } + TransformOperations none_operation; + for (size_t i = 0; i < operations.size(); ++i) + EXPECT_TRUE(operations[i]->MatchesTypes(none_operation)); } TEST(TransformOperationTest, ApplyTranslate) { @@ -421,18 +441,54 @@ TEST(TransformOperationTest, LargeRotationsWithDifferentAxes) { expected, operations_to.Blend(operations_from, progress)); } +TEST(TransformOperationTest, RotationWithSlerpFromZeroDeg) { + TransformOperations operations_from; + operations_from.AppendRotate(0, 0, 1, 0); + + TransformOperations operations_to; + operations_to.AppendRotate(0, 1, 0, 450); + + SkMScalar progress = 0.5f; + gfx::Transform matrix_from; + matrix_from.RotateAbout(gfx::Vector3dF(0, 0, 1), 0); + + gfx::Transform matrix_to; + matrix_to.RotateAbout(gfx::Vector3dF(0, 1, 0), 90); + + gfx::Transform expected = matrix_to; + expected.Blend(matrix_from, progress); + + EXPECT_TRANSFORMATION_MATRIX_EQ( + expected, operations_to.Blend(operations_from, progress)); +} + +TEST(TransformOperationTest, RotationWithoutSlerpFromZeroDeg) { + TransformOperations operations_from; + operations_from.AppendRotate(0, 0, 1, 0); + + TransformOperations operations_to; + operations_to.AppendRotate(0, 0, 1, 450); + + SkMScalar progress = 0.5f; + gfx::Transform expected; + expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 225); + + EXPECT_TRANSFORMATION_MATRIX_EQ( + expected, operations_to.Blend(operations_from, progress)); +} + TEST(TransformOperationTest, BlendRotationFromIdentity) { ScopedVector<TransformOperations> identity_operations; GetIdentityOperations(&identity_operations); for (size_t i = 0; i < identity_operations.size(); ++i) { TransformOperations operations; - operations.AppendRotate(0, 0, 1, 360); + operations.AppendRotate(0, 0, 1, 90); SkMScalar progress = 0.5f; gfx::Transform expected; - expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180); + expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 45); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, operations.Blend(*identity_operations[i], progress)); @@ -440,7 +496,7 @@ TEST(TransformOperationTest, BlendRotationFromIdentity) { progress = -0.5f; expected.MakeIdentity(); - expected.RotateAbout(gfx::Vector3dF(0, 0, 1), -180); + expected.RotateAbout(gfx::Vector3dF(0, 0, 1), -45); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, operations.Blend(*identity_operations[i], progress)); @@ -448,7 +504,7 @@ TEST(TransformOperationTest, BlendRotationFromIdentity) { progress = 1.5f; expected.MakeIdentity(); - expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 540); + expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 135); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, operations.Blend(*identity_operations[i], progress)); @@ -523,41 +579,38 @@ TEST(TransformOperationTest, BlendScaleFromIdentity) { } } -TEST(TransformOperationTest, BlendSkewFromIdentity) { - ScopedVector<TransformOperations> identity_operations; - GetIdentityOperations(&identity_operations); +TEST(TransformOperationTest, BlendSkewFromEmpty) { + TransformOperations empty_operation; - for (size_t i = 0; i < identity_operations.size(); ++i) { - TransformOperations operations; - operations.AppendSkew(2, 2); + TransformOperations operations; + operations.AppendSkew(2, 2); - SkMScalar progress = 0.5f; + SkMScalar progress = 0.5f; - gfx::Transform expected; - expected.SkewX(1); - expected.SkewY(1); + gfx::Transform expected; + expected.SkewX(1); + expected.SkewY(1); - EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, operations.Blend(*identity_operations[i], progress)); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected, + operations.Blend(empty_operation, progress)); - progress = -0.5f; + progress = -0.5f; - expected.MakeIdentity(); - expected.SkewX(-1); - expected.SkewY(-1); + expected.MakeIdentity(); + expected.SkewX(-1); + expected.SkewY(-1); - EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, operations.Blend(*identity_operations[i], progress)); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected, + operations.Blend(empty_operation, progress)); - progress = 1.5f; + progress = 1.5f; - expected.MakeIdentity(); - expected.SkewX(3); - expected.SkewY(3); + expected.MakeIdentity(); + expected.SkewX(3); + expected.SkewY(3); - EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, operations.Blend(*identity_operations[i], progress)); - } + EXPECT_TRANSFORMATION_MATRIX_EQ(expected, + operations.Blend(empty_operation, progress)); } TEST(TransformOperationTest, BlendPerspectiveFromIdentity) { @@ -584,12 +637,12 @@ TEST(TransformOperationTest, BlendRotationToIdentity) { for (size_t i = 0; i < identity_operations.size(); ++i) { TransformOperations operations; - operations.AppendRotate(0, 0, 1, 360); + operations.AppendRotate(0, 0, 1, 90); SkMScalar progress = 0.5f; gfx::Transform expected; - expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180); + expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 45); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, identity_operations[i]->Blend(operations, progress)); @@ -632,23 +685,20 @@ TEST(TransformOperationTest, BlendScaleToIdentity) { } } -TEST(TransformOperationTest, BlendSkewToIdentity) { - ScopedVector<TransformOperations> identity_operations; - GetIdentityOperations(&identity_operations); +TEST(TransformOperationTest, BlendSkewToEmpty) { + TransformOperations empty_operation; - for (size_t i = 0; i < identity_operations.size(); ++i) { - TransformOperations operations; - operations.AppendSkew(2, 2); + TransformOperations operations; + operations.AppendSkew(2, 2); - SkMScalar progress = 0.5f; + SkMScalar progress = 0.5f; - gfx::Transform expected; - expected.SkewX(1); - expected.SkewY(1); + gfx::Transform expected; + expected.SkewX(1); + expected.SkewY(1); - EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, identity_operations[i]->Blend(operations, progress)); - } + EXPECT_TRANSFORMATION_MATRIX_EQ(expected, + empty_operation.Blend(operations, progress)); } TEST(TransformOperationTest, BlendPerspectiveToIdentity) { diff --git a/chromium/cc/base/BUILD.gn b/chromium/cc/base/BUILD.gn index e41c74f1586..98a5d4ad1e6 100644 --- a/chromium/cc/base/BUILD.gn +++ b/chromium/cc/base/BUILD.gn @@ -9,17 +9,23 @@ source_set("base") { "completion_event.h", "delayed_unique_notifier.cc", "delayed_unique_notifier.h", + "histograms.cc", + "histograms.h", "invalidation_region.cc", "invalidation_region.h", + "list_container.cc", + "list_container.h", "math_util.cc", "math_util.h", "region.cc", "region.h", + "resource_id.h", "rolling_time_delta_history.cc", "rolling_time_delta_history.h", "scoped_ptr_algorithm.h", "scoped_ptr_deque.h", "scoped_ptr_vector.h", + "sidecar_list_container.h", "simple_enclosed_region.cc", "simple_enclosed_region.h", "switches.cc", @@ -30,7 +36,6 @@ source_set("base") { "time_util.h", "unique_notifier.cc", "unique_notifier.h", - "util.h", ] deps = [ diff --git a/chromium/cc/base/histograms.cc b/chromium/cc/base/histograms.cc new file mode 100644 index 00000000000..9fe1515bc2a --- /dev/null +++ b/chromium/cc/base/histograms.cc @@ -0,0 +1,50 @@ +// Copyright 2015 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/base/histograms.h" + +#include <algorithm> +#include <cmath> +#include <limits> + +#include "base/numerics/safe_conversions.h" + +namespace cc { + +// Minimum elapsed time of 1us to limit weighting of fast calls. +static const int64 kMinimumTimeMicroseconds = 1; + +ScopedUMAHistogramAreaTimerBase::ScopedUMAHistogramAreaTimerBase() : area_(0) { +} + +ScopedUMAHistogramAreaTimerBase::~ScopedUMAHistogramAreaTimerBase() { +} + +bool ScopedUMAHistogramAreaTimerBase::GetHistogramValues( + Sample* time_microseconds, + Sample* pixels_per_ms) const { + return GetHistogramValues( + timer_.Elapsed(), area_.ValueOrDefault(std::numeric_limits<int>::max()), + time_microseconds, pixels_per_ms); +} + +// static +bool ScopedUMAHistogramAreaTimerBase::GetHistogramValues( + base::TimeDelta elapsed, + int area, + Sample* time_microseconds, + Sample* pixels_per_ms) { + elapsed = std::max( + elapsed, base::TimeDelta::FromMicroseconds(kMinimumTimeMicroseconds)); + double area_per_time = area / elapsed.InMillisecondsF(); + // It is not clear how NaN can get here, but we've gotten crashes from + // saturated_cast. http://crbug.com/486214 + if (std::isnan(area_per_time)) + return false; + *time_microseconds = base::saturated_cast<Sample>(elapsed.InMicroseconds()); + *pixels_per_ms = base::saturated_cast<Sample>(area_per_time); + return true; +} + +} // namespace cc diff --git a/chromium/cc/base/histograms.h b/chromium/cc/base/histograms.h new file mode 100644 index 00000000000..0c8a2bc8532 --- /dev/null +++ b/chromium/cc/base/histograms.h @@ -0,0 +1,76 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_BASE_HISTOGRAMS_H_ +#define CC_BASE_HISTOGRAMS_H_ + +#include "base/compiler_specific.h" +#include "base/metrics/histogram_base.h" +#include "base/metrics/histogram_macros.h" +#include "base/numerics/safe_math.h" +#include "base/time/time.h" +#include "base/timer/elapsed_timer.h" +#include "cc/base/cc_export.h" + +namespace cc { + +// Emits UMA histogram trackers for time spent as well as area (in pixels) +// processed per unit time. Time is measured in microseconds, and work in +// pixels per millisecond. +// +// Usage: +// // Outside of a method, perhaps in a namespace. +// DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(ScopedReticulateSplinesTimer, +// "ReticulateSplinesUs", +// "ReticulateSplinesPixelsPerMs"); +// +// // Inside a method. +// ScopedReticulateSplinesTimer timer; +// timer.AddArea(some_rect.size().GetArea()); +#define DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(class_name, time_histogram, \ + area_histogram) \ + class class_name : public ::cc::ScopedUMAHistogramAreaTimerBase { \ + public: \ + ~class_name(); \ + }; \ + class_name::~class_name() { \ + Sample time_sample; \ + Sample area_sample; \ + if (GetHistogramValues(&time_sample, &area_sample)) { \ + UMA_HISTOGRAM_COUNTS(time_histogram, time_sample); \ + UMA_HISTOGRAM_COUNTS(area_histogram, area_sample); \ + } \ + } + +class CC_EXPORT ScopedUMAHistogramAreaTimerBase { + public: + void AddArea(int area) { area_ += area; } + void SetArea(int area) { area_ = area; } + + protected: + using Sample = base::HistogramBase::Sample; + + ScopedUMAHistogramAreaTimerBase(); + ~ScopedUMAHistogramAreaTimerBase(); + + // Returns true if histograms should be recorded (i.e. values are valid). + bool GetHistogramValues(Sample* time_microseconds, + Sample* pixels_per_ms) const; + + private: + static bool GetHistogramValues(base::TimeDelta elapsed, + int area, + Sample* time_microseconds, + Sample* pixels_per_ms); + + base::ElapsedTimer timer_; + base::CheckedNumeric<int> area_; + + friend class ScopedUMAHistogramAreaTimerBaseTest; + DISALLOW_COPY_AND_ASSIGN(ScopedUMAHistogramAreaTimerBase); +}; + +} // namespace cc + +#endif // CC_BASE_HISTOGRAMS_H_ diff --git a/chromium/cc/base/histograms_unittest.cc b/chromium/cc/base/histograms_unittest.cc new file mode 100644 index 00000000000..19bdb09bd7b --- /dev/null +++ b/chromium/cc/base/histograms_unittest.cc @@ -0,0 +1,65 @@ +// Copyright 2015 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/base/histograms.h" + +#include <limits> + +#include "testing/gtest/include/gtest/gtest.h" + +using base::TimeDelta; +using Sample = base::HistogramBase::Sample; + +namespace cc { + +class ScopedUMAHistogramAreaTimerBaseTest : public ::testing::Test { + protected: + void ExpectValidHistogramValues(base::TimeDelta elapsed, + int area, + Sample expected_time_microseconds, + Sample expected_pixels_per_ms) { + Sample time_microseconds; + Sample pixels_per_ms; + ScopedUMAHistogramAreaTimerBase::GetHistogramValues( + elapsed, area, &time_microseconds, &pixels_per_ms); + EXPECT_EQ(expected_time_microseconds, time_microseconds); + EXPECT_EQ(expected_pixels_per_ms, pixels_per_ms); + } +}; + +namespace { + +TEST_F(ScopedUMAHistogramAreaTimerBaseTest, CommonCase) { + ExpectValidHistogramValues(TimeDelta::FromMicroseconds(500), 1000, 500, 2000); + ExpectValidHistogramValues(TimeDelta::FromMicroseconds(300), 1000, 300, 3333); +} + +TEST_F(ScopedUMAHistogramAreaTimerBaseTest, ZeroArea) { + ExpectValidHistogramValues(TimeDelta::FromMicroseconds(500), 0, 500, 0); +} + +TEST_F(ScopedUMAHistogramAreaTimerBaseTest, ZeroTime) { + // 1M pixels/ms, since the time is limited to at least 1us. + ExpectValidHistogramValues(TimeDelta(), 1000, 1, 1000000); +} + +TEST_F(ScopedUMAHistogramAreaTimerBaseTest, ZeroTimeAndArea) { + ExpectValidHistogramValues(TimeDelta(), 0, 1, 0); +} + +TEST_F(ScopedUMAHistogramAreaTimerBaseTest, VeryLargeTime) { + ExpectValidHistogramValues(TimeDelta::FromHours(24), 1000, + std::numeric_limits<Sample>::max(), 0); +} + +TEST_F(ScopedUMAHistogramAreaTimerBaseTest, VeryLargeArea) { + ExpectValidHistogramValues(TimeDelta::FromMicroseconds(500), 1000000000, 500, + 2000000000); + ExpectValidHistogramValues(TimeDelta::FromMicroseconds(1000), + std::numeric_limits<int>::max(), 1000, + std::numeric_limits<Sample>::max()); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/base/list_container.cc b/chromium/cc/base/list_container.cc new file mode 100644 index 00000000000..d5cb4f03260 --- /dev/null +++ b/chromium/cc/base/list_container.cc @@ -0,0 +1,520 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/base/list_container.h" + +#include <algorithm> +#include <vector> + +#include "cc/base/scoped_ptr_vector.h" + +namespace { +const size_t kDefaultNumElementTypesToReserve = 32; +} // namespace + +namespace cc { + +// ListContainerCharAllocator +//////////////////////////////////////////////////// +// This class deals only with char* and void*. It does allocation and passing +// out raw pointers, as well as memory deallocation when being destroyed. +class ListContainerBase::ListContainerCharAllocator { + public: + // ListContainerCharAllocator::InnerList + ///////////////////////////////////////////// + // This class holds the raw memory chunk, as well as information about its + // size and availability. + struct InnerList { + scoped_ptr<char[]> data; + // The number of elements in total the memory can hold. The difference + // between capacity and size is the how many more elements this list can + // hold. + size_t capacity; + // The number of elements have been put into this list. + size_t size; + // The size of each element is in bytes. This is used to move from between + // elements' memory locations. + size_t step; + + InnerList() : capacity(0), size(0), step(0) {} + + void Erase(char* position) { + // Confident that destructor is called by caller of this function. Since + // ListContainerCharAllocator does not handle construction after + // allocation, it doesn't handle desctrution before deallocation. + DCHECK_LE(position, LastElement()); + DCHECK_GE(position, Begin()); + char* start = position + step; + std::copy(start, End(), position); + + --size; + // Decrease capacity to avoid creating not full not last InnerList. + --capacity; + } + + bool IsEmpty() const { return !size; } + bool IsFull() { return capacity == size; } + size_t NumElementsAvailable() const { return capacity - size; } + + void* AddElement() { + DCHECK_LT(size, capacity); + ++size; + return LastElement(); + } + + void RemoveLast() { + DCHECK(!IsEmpty()); + --size; + } + + char* Begin() const { return data.get(); } + char* End() const { return data.get() + size * step; } + char* LastElement() const { return data.get() + (size - 1) * step; } + char* ElementAt(size_t index) const { return data.get() + index * step; } + + private: + DISALLOW_COPY_AND_ASSIGN(InnerList); + }; + + explicit ListContainerCharAllocator(size_t element_size) + : element_size_(element_size), + size_(0), + last_list_index_(0), + last_list_(NULL) { + AllocateNewList(kDefaultNumElementTypesToReserve); + last_list_ = storage_[last_list_index_]; + } + + ListContainerCharAllocator(size_t element_size, size_t element_count) + : element_size_(element_size), + size_(0), + last_list_index_(0), + last_list_(NULL) { + AllocateNewList(element_count > 0 ? element_count + : kDefaultNumElementTypesToReserve); + last_list_ = storage_[last_list_index_]; + } + + ~ListContainerCharAllocator() {} + + void* Allocate() { + if (last_list_->IsFull()) { + // Only allocate a new list if there isn't a spare one still there from + // previous usage. + if (last_list_index_ + 1 >= storage_.size()) + AllocateNewList(last_list_->capacity * 2); + + ++last_list_index_; + last_list_ = storage_[last_list_index_]; + } + + ++size_; + return last_list_->AddElement(); + } + + size_t element_size() const { return element_size_; } + size_t list_count() const { return storage_.size(); } + size_t size() const { return size_; } + bool IsEmpty() const { return size() == 0; } + + size_t Capacity() const { + size_t capacity_sum = 0; + for (const auto& inner_list : storage_) + capacity_sum += inner_list->capacity; + return capacity_sum; + } + + void Clear() { + // Remove all except for the first InnerList. + DCHECK(!storage_.empty()); + storage_.erase(storage_.begin() + 1, storage_.end()); + last_list_index_ = 0; + last_list_ = storage_[0]; + last_list_->size = 0; + size_ = 0; + } + + void RemoveLast() { + DCHECK(!IsEmpty()); + last_list_->RemoveLast(); + if (last_list_->IsEmpty() && last_list_index_ > 0) { + --last_list_index_; + last_list_ = storage_[last_list_index_]; + + // If there are now two empty inner lists, free one of them. + if (last_list_index_ + 2 < storage_.size()) + storage_.pop_back(); + } + --size_; + } + + void Erase(PositionInListContainerCharAllocator position) { + DCHECK_EQ(this, position.ptr_to_container); + storage_[position.vector_index]->Erase(position.item_iterator); + // TODO(weiliangc): Free the InnerList if it is empty. + --size_; + } + + InnerList* InnerListById(size_t id) const { + DCHECK_LT(id, storage_.size()); + return storage_[id]; + } + + size_t FirstInnerListId() const { + // |size_| > 0 means that at least one vector in |storage_| will be + // non-empty. + DCHECK_GT(size_, 0u); + size_t id = 0; + while (storage_[id]->size == 0) + ++id; + return id; + } + + size_t LastInnerListId() const { + // |size_| > 0 means that at least one vector in |storage_| will be + // non-empty. + DCHECK_GT(size_, 0u); + size_t id = storage_.size() - 1; + while (storage_[id]->size == 0) + --id; + return id; + } + + size_t NumAvailableElementsInLastList() const { + return last_list_->NumElementsAvailable(); + } + + private: + void AllocateNewList(size_t list_size) { + scoped_ptr<InnerList> new_list(new InnerList); + new_list->capacity = list_size; + new_list->size = 0; + new_list->step = element_size_; + new_list->data.reset(new char[list_size * element_size_]); + storage_.push_back(new_list.Pass()); + } + + ScopedPtrVector<InnerList> storage_; + const size_t element_size_; + + // The number of elements in the list. + size_t size_; + + // The index of the last list to have had elements added to it, or the only + // list if the container has not had elements added since being cleared. + size_t last_list_index_; + + // This is equivalent to |storage_[last_list_index_]|. + InnerList* last_list_; + + DISALLOW_COPY_AND_ASSIGN(ListContainerCharAllocator); +}; + +// PositionInListContainerCharAllocator +////////////////////////////////////////////////////// +ListContainerBase::PositionInListContainerCharAllocator:: + PositionInListContainerCharAllocator( + const ListContainerBase::PositionInListContainerCharAllocator& other) + : ptr_to_container(other.ptr_to_container), + vector_index(other.vector_index), + item_iterator(other.item_iterator) { +} + +ListContainerBase::PositionInListContainerCharAllocator:: + PositionInListContainerCharAllocator( + ListContainerBase::ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter) + : ptr_to_container(container), + vector_index(vector_ind), + item_iterator(item_iter) { +} + +bool ListContainerBase::PositionInListContainerCharAllocator::operator==( + const ListContainerBase::PositionInListContainerCharAllocator& other) + const { + DCHECK_EQ(ptr_to_container, other.ptr_to_container); + return vector_index == other.vector_index && + item_iterator == other.item_iterator; +} + +bool ListContainerBase::PositionInListContainerCharAllocator::operator!=( + const ListContainerBase::PositionInListContainerCharAllocator& other) + const { + return !(*this == other); +} + +ListContainerBase::PositionInListContainerCharAllocator +ListContainerBase::PositionInListContainerCharAllocator::Increment() { + ListContainerCharAllocator::InnerList* list = + ptr_to_container->InnerListById(vector_index); + if (item_iterator == list->LastElement()) { + ++vector_index; + while (vector_index < ptr_to_container->list_count()) { + if (ptr_to_container->InnerListById(vector_index)->size != 0) + break; + ++vector_index; + } + if (vector_index < ptr_to_container->list_count()) + item_iterator = ptr_to_container->InnerListById(vector_index)->Begin(); + else + item_iterator = NULL; + } else { + item_iterator += list->step; + } + return *this; +} + +ListContainerBase::PositionInListContainerCharAllocator +ListContainerBase::PositionInListContainerCharAllocator::ReverseIncrement() { + ListContainerCharAllocator::InnerList* list = + ptr_to_container->InnerListById(vector_index); + if (item_iterator == list->Begin()) { + --vector_index; + // Since |vector_index| is unsigned, we compare < list_count() instead of + // comparing >= 0, as the variable will wrap around when it goes out of + // range (below 0). + while (vector_index < ptr_to_container->list_count()) { + if (ptr_to_container->InnerListById(vector_index)->size != 0) + break; + --vector_index; + } + if (vector_index < ptr_to_container->list_count()) { + item_iterator = + ptr_to_container->InnerListById(vector_index)->LastElement(); + } else { + item_iterator = NULL; + } + } else { + item_iterator -= list->step; + } + return *this; +} + +// ListContainerBase +//////////////////////////////////////////// +ListContainerBase::ListContainerBase(size_t max_size_for_derived_class) + : data_(new ListContainerCharAllocator(max_size_for_derived_class)) { +} + +ListContainerBase::ListContainerBase(size_t max_size_for_derived_class, + size_t num_of_elements_to_reserve_for) + : data_(new ListContainerCharAllocator(max_size_for_derived_class, + num_of_elements_to_reserve_for)) { +} + +ListContainerBase::~ListContainerBase() { +} + +void ListContainerBase::RemoveLast() { + data_->RemoveLast(); +} + +void ListContainerBase::EraseAndInvalidateAllPointers( + ListContainerBase::Iterator position) { + data_->Erase(position); +} + +ListContainerBase::ConstReverseIterator ListContainerBase::crbegin() const { + if (data_->IsEmpty()) + return crend(); + + size_t id = data_->LastInnerListId(); + return ConstReverseIterator(data_.get(), id, + data_->InnerListById(id)->LastElement(), 0); +} + +ListContainerBase::ConstReverseIterator ListContainerBase::crend() const { + return ConstReverseIterator(data_.get(), static_cast<size_t>(-1), NULL, + size()); +} + +ListContainerBase::ReverseIterator ListContainerBase::rbegin() { + if (data_->IsEmpty()) + return rend(); + + size_t id = data_->LastInnerListId(); + return ReverseIterator(data_.get(), id, + data_->InnerListById(id)->LastElement(), 0); +} + +ListContainerBase::ReverseIterator ListContainerBase::rend() { + return ReverseIterator(data_.get(), static_cast<size_t>(-1), NULL, size()); +} + +ListContainerBase::ConstIterator ListContainerBase::cbegin() const { + if (data_->IsEmpty()) + return cend(); + + size_t id = data_->FirstInnerListId(); + return ConstIterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0); +} + +ListContainerBase::ConstIterator ListContainerBase::cend() const { + if (data_->IsEmpty()) + return ConstIterator(data_.get(), 0, NULL, size()); + + size_t id = data_->list_count(); + return ConstIterator(data_.get(), id, NULL, size()); +} + +ListContainerBase::Iterator ListContainerBase::begin() { + if (data_->IsEmpty()) + return end(); + + size_t id = data_->FirstInnerListId(); + return Iterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0); +} + +ListContainerBase::Iterator ListContainerBase::end() { + if (data_->IsEmpty()) + return Iterator(data_.get(), 0, NULL, size()); + + size_t id = data_->list_count(); + return Iterator(data_.get(), id, NULL, size()); +} + +ListContainerBase::ConstIterator ListContainerBase::IteratorAt( + size_t index) const { + DCHECK_LT(index, size()); + size_t original_index = index; + size_t list_index; + for (list_index = 0; list_index < data_->list_count(); ++list_index) { + size_t current_size = data_->InnerListById(list_index)->size; + if (index < current_size) + break; + index -= current_size; + } + return ConstIterator(data_.get(), list_index, + data_->InnerListById(list_index)->ElementAt(index), + original_index); +} + +ListContainerBase::Iterator ListContainerBase::IteratorAt(size_t index) { + DCHECK_LT(index, size()); + size_t original_index = index; + size_t list_index; + for (list_index = 0; list_index < data_->list_count(); ++list_index) { + size_t current_size = data_->InnerListById(list_index)->size; + if (index < current_size) + break; + index -= current_size; + } + return Iterator(data_.get(), list_index, + data_->InnerListById(list_index)->ElementAt(index), + original_index); +} + +void* ListContainerBase::Allocate(size_t size_of_actual_element_in_bytes) { + DCHECK_LE(size_of_actual_element_in_bytes, data_->element_size()); + return data_->Allocate(); +} + +size_t ListContainerBase::size() const { + return data_->size(); +} + +bool ListContainerBase::empty() const { + return data_->IsEmpty(); +} + +size_t ListContainerBase::MaxSizeForDerivedClass() const { + return data_->element_size(); +} + +size_t ListContainerBase::GetCapacityInBytes() const { + return data_->Capacity() * data_->element_size(); +} + +void ListContainerBase::clear() { + data_->Clear(); +} + +size_t ListContainerBase::AvailableSizeWithoutAnotherAllocationForTesting() + const { + return data_->NumAvailableElementsInLastList(); +} + +// ListContainerBase::Iterator +///////////////////////////////////////////////// +ListContainerBase::Iterator::Iterator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index) + : PositionInListContainerCharAllocator(container, vector_ind, item_iter), + index_(index) { +} + +ListContainerBase::Iterator::~Iterator() { +} + +size_t ListContainerBase::Iterator::index() const { + return index_; +} + +// ListContainerBase::ConstIterator +///////////////////////////////////////////////// +ListContainerBase::ConstIterator::ConstIterator( + const ListContainerBase::Iterator& other) + : PositionInListContainerCharAllocator(other), index_(other.index()) { +} + +ListContainerBase::ConstIterator::ConstIterator( + ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index) + : PositionInListContainerCharAllocator(container, vector_ind, item_iter), + index_(index) { +} + +ListContainerBase::ConstIterator::~ConstIterator() { +} + +size_t ListContainerBase::ConstIterator::index() const { + return index_; +} + +// ListContainerBase::ReverseIterator +///////////////////////////////////////////////// +ListContainerBase::ReverseIterator::ReverseIterator( + ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index) + : PositionInListContainerCharAllocator(container, vector_ind, item_iter), + index_(index) { +} + +ListContainerBase::ReverseIterator::~ReverseIterator() { +} + +size_t ListContainerBase::ReverseIterator::index() const { + return index_; +} + +// ListContainerBase::ConstReverseIterator +///////////////////////////////////////////////// +ListContainerBase::ConstReverseIterator::ConstReverseIterator( + const ListContainerBase::ReverseIterator& other) + : PositionInListContainerCharAllocator(other), index_(other.index()) { +} + +ListContainerBase::ConstReverseIterator::ConstReverseIterator( + ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index) + : PositionInListContainerCharAllocator(container, vector_ind, item_iter), + index_(index) { +} + +ListContainerBase::ConstReverseIterator::~ConstReverseIterator() { +} + +size_t ListContainerBase::ConstReverseIterator::index() const { + return index_; +} + +} // namespace cc diff --git a/chromium/cc/base/list_container.h b/chromium/cc/base/list_container.h new file mode 100644 index 00000000000..ae7afa92e5b --- /dev/null +++ b/chromium/cc/base/list_container.h @@ -0,0 +1,483 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_BASE_LIST_CONTAINER_H_ +#define CC_BASE_LIST_CONTAINER_H_ + +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" + +namespace cc { + +// ListContainer is a container type that handles allocating contiguous memory +// for new elements and traversing through elements with either iterator or +// reverse iterator. Since this container hands out raw pointers of its +// elements, it is very important that this container never reallocate its +// memory so those raw pointer will continue to be valid. This class is used to +// contain SharedQuadState or DrawQuad. Since the size of each DrawQuad varies, +// to hold DrawQuads, the allocations size of each element in this class is +// LargestDrawQuadSize while BaseElementType is DrawQuad. + +// Base class for non-templated logic. All methods are protected, and only +// exposed by ListContainer<BaseElementType>. +// For usage, see comments in ListContainer. +class CC_EXPORT ListContainerBase { + protected: + explicit ListContainerBase(size_t max_size_for_derived_class); + ListContainerBase(size_t max_size_for_derived_class, + size_t num_of_elements_to_reserve_for); + ~ListContainerBase(); + + // This class deals only with char* and void*. It does allocation and passing + // out raw pointers, as well as memory deallocation when being destroyed. + class ListContainerCharAllocator; + + // This class points to a certain position inside memory of + // ListContainerCharAllocator. It is a base class for ListContainer iterators. + struct CC_EXPORT PositionInListContainerCharAllocator { + ListContainerCharAllocator* ptr_to_container; + size_t vector_index; + char* item_iterator; + + PositionInListContainerCharAllocator( + const PositionInListContainerCharAllocator& other); + + PositionInListContainerCharAllocator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter); + + bool operator==(const PositionInListContainerCharAllocator& other) const; + bool operator!=(const PositionInListContainerCharAllocator& other) const; + + PositionInListContainerCharAllocator Increment(); + PositionInListContainerCharAllocator ReverseIncrement(); + }; + + // Iterator classes that can be used to access data. + ///////////////////////////////////////////////////////////////// + class CC_EXPORT Iterator : public PositionInListContainerCharAllocator { + // This class is only defined to forward iterate through + // ListContainerCharAllocator. + public: + Iterator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index); + ~Iterator(); + + size_t index() const; + + protected: + // This is used to track how many increment has happened since begin(). It + // is used to avoid double increment at places an index reference is + // needed. For iterator this means begin() corresponds to index 0 and end() + // corresponds to index |size|. + size_t index_; + }; + + class CC_EXPORT ConstIterator : public PositionInListContainerCharAllocator { + // This class is only defined to forward iterate through + // ListContainerCharAllocator. + public: + ConstIterator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index); + ConstIterator(const Iterator& other); // NOLINT + ~ConstIterator(); + + size_t index() const; + + protected: + // This is used to track how many increment has happened since begin(). It + // is used to avoid double increment at places an index reference is + // needed. For iterator this means begin() corresponds to index 0 and end() + // corresponds to index |size|. + size_t index_; + }; + + class CC_EXPORT ReverseIterator + : public PositionInListContainerCharAllocator { + // This class is only defined to reverse iterate through + // ListContainerCharAllocator. + public: + ReverseIterator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index); + ~ReverseIterator(); + + size_t index() const; + + protected: + // This is used to track how many increment has happened since rbegin(). It + // is used to avoid double increment at places an index reference is + // needed. For reverse iterator this means rbegin() corresponds to index 0 + // and rend() corresponds to index |size|. + size_t index_; + }; + + class CC_EXPORT ConstReverseIterator + : public PositionInListContainerCharAllocator { + // This class is only defined to reverse iterate through + // ListContainerCharAllocator. + public: + ConstReverseIterator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index); + ConstReverseIterator(const ReverseIterator& other); // NOLINT + ~ConstReverseIterator(); + + size_t index() const; + + protected: + // This is used to track how many increment has happened since rbegin(). It + // is used to avoid double increment at places an index reference is + // needed. For reverse iterator this means rbegin() corresponds to index 0 + // and rend() corresponds to index |size|. + size_t index_; + }; + + // Unlike the ListContainer methods, these do not invoke element destructors. + void RemoveLast(); + void EraseAndInvalidateAllPointers(Iterator position); + + ConstReverseIterator crbegin() const; + ConstReverseIterator crend() const; + ReverseIterator rbegin(); + ReverseIterator rend(); + ConstIterator cbegin() const; + ConstIterator cend() const; + Iterator begin(); + Iterator end(); + + Iterator IteratorAt(size_t index); + ConstIterator IteratorAt(size_t index) const; + + size_t size() const; + bool empty() const; + + size_t MaxSizeForDerivedClass() const; + + size_t GetCapacityInBytes() const; + + // Unlike the ListContainer method, this one does not invoke element + // destructors. + void clear(); + + size_t AvailableSizeWithoutAnotherAllocationForTesting() const; + + // Hands out memory location for an element at the end of data structure. + void* Allocate(size_t size_of_actual_element_in_bytes); + + scoped_ptr<ListContainerCharAllocator> data_; + + private: + DISALLOW_COPY_AND_ASSIGN(ListContainerBase); +}; + +template <class BaseElementType> +class ListContainer : public ListContainerBase { + public: + // BaseElementType is the type of raw pointers this class hands out; however, + // its derived classes might require different memory sizes. + // max_size_for_derived_class the largest memory size required for all the + // derived classes to use for allocation. + explicit ListContainer(size_t max_size_for_derived_class) + : ListContainerBase(max_size_for_derived_class) {} + + // This constructor omits input variable for max_size_for_derived_class. This + // is used when there is no derived classes from BaseElementType we need to + // worry about, and allocation size is just sizeof(BaseElementType). + ListContainer() : ListContainerBase(sizeof(BaseElementType)) {} + + // This constructor reserves the requested memory up front so only single + // allocation is needed. When num_of_elements_to_reserve_for is zero, use the + // default size. + ListContainer(size_t max_size_for_derived_class, + size_t num_of_elements_to_reserve_for) + : ListContainerBase(max_size_for_derived_class, + num_of_elements_to_reserve_for) {} + + ~ListContainer() { + for (Iterator i = begin(); i != end(); ++i) { + i->~BaseElementType(); + } + } + + class Iterator; + class ConstIterator; + class ReverseIterator; + class ConstReverseIterator; + + // Removes the last element of the list and makes its space available for + // allocation. + void RemoveLast() { + DCHECK(!empty()); + back()->~BaseElementType(); + ListContainerBase::RemoveLast(); + } + + // When called, all raw pointers that have been handed out are no longer + // valid. Use with caution. + // This function does not deallocate memory. + void EraseAndInvalidateAllPointers(Iterator position) { + BaseElementType* item = *position; + item->~BaseElementType(); + ListContainerBase::EraseAndInvalidateAllPointers(position); + } + + ConstReverseIterator crbegin() const { + return ConstReverseIterator(ListContainerBase::crbegin()); + } + ConstReverseIterator crend() const { + return ConstReverseIterator(ListContainerBase::crend()); + } + ConstReverseIterator rbegin() const { return crbegin(); } + ConstReverseIterator rend() const { return crend(); } + ReverseIterator rbegin() { + return ReverseIterator(ListContainerBase::rbegin()); + } + ReverseIterator rend() { return ReverseIterator(ListContainerBase::rend()); } + ConstIterator cbegin() const { + return ConstIterator(ListContainerBase::cbegin()); + } + ConstIterator cend() const { + return ConstIterator(ListContainerBase::cend()); + } + ConstIterator begin() const { return cbegin(); } + ConstIterator end() const { return cend(); } + Iterator begin() { return Iterator(ListContainerBase::begin()); } + Iterator end() { return Iterator(ListContainerBase::end()); } + + // TODO(weiliangc): front(), back() and ElementAt() function should return + // reference, consistent with container-of-object. + BaseElementType* front() { return *begin(); } + BaseElementType* back() { return *rbegin(); } + const BaseElementType* front() const { return *begin(); } + const BaseElementType* back() const { return *rbegin(); } + + BaseElementType* ElementAt(size_t index) { + return *Iterator(IteratorAt(index)); + } + const BaseElementType* ElementAt(size_t index) const { + return *ConstIterator(IteratorAt(index)); + } + + // Take in derived element type and construct it at location generated by + // Allocate(). + template <typename DerivedElementType> + DerivedElementType* AllocateAndConstruct() { + return new (Allocate(sizeof(DerivedElementType))) DerivedElementType; + } + + // Take in derived element type and copy construct it at location generated by + // Allocate(). + template <typename DerivedElementType> + DerivedElementType* AllocateAndCopyFrom(const DerivedElementType* source) { + return new (Allocate(sizeof(DerivedElementType))) + DerivedElementType(*source); + } + + // Construct a new element on top of an existing one. + template <typename DerivedElementType> + DerivedElementType* ReplaceExistingElement(Iterator at) { + at->~BaseElementType(); + return new (*at) DerivedElementType(); + } + + template <typename DerivedElementType> + void swap(ListContainer<DerivedElementType>& other) { + data_.swap(other.data_); + } + + // Appends a new item without copying. The original item will not be + // destructed and will be replaced with a new DerivedElementType. The + // DerivedElementType does not have to match the moved type as a full block + // of memory will be moved (up to MaxSizeForDerivedClass()). A pointer to + // the moved element is returned. + template <typename DerivedElementType> + DerivedElementType* AppendByMoving(DerivedElementType* item) { + size_t max_size_for_derived_class = MaxSizeForDerivedClass(); + void* new_item = Allocate(max_size_for_derived_class); + memcpy(new_item, static_cast<void*>(item), max_size_for_derived_class); + // Construct a new element in-place so it can be destructed safely. + new (item) DerivedElementType; + return static_cast<DerivedElementType*>(new_item); + } + + using ListContainerBase::size; + using ListContainerBase::empty; + using ListContainerBase::GetCapacityInBytes; + + void clear() { + for (Iterator i = begin(); i != end(); ++i) { + i->~BaseElementType(); + } + ListContainerBase::clear(); + } + + using ListContainerBase::AvailableSizeWithoutAnotherAllocationForTesting; + + // Iterator classes that can be used to access data. + ///////////////////////////////////////////////////////////////// + class Iterator : public ListContainerBase::Iterator { + // This class is only defined to forward iterate through + // ListContainerCharAllocator. + public: + Iterator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index) + : ListContainerBase::Iterator(container, vector_ind, item_iter, index) { + } + BaseElementType* operator->() const { + return reinterpret_cast<BaseElementType*>(item_iterator); + } + BaseElementType* operator*() const { + return reinterpret_cast<BaseElementType*>(item_iterator); + } + Iterator operator++(int unused_post_increment) { + Iterator tmp = *this; + operator++(); + return tmp; + } + Iterator& operator++() { + Increment(); + ++index_; + return *this; + } + + private: + explicit Iterator(const ListContainerBase::Iterator& base_iterator) + : ListContainerBase::Iterator(base_iterator) {} + friend Iterator ListContainer<BaseElementType>::begin(); + friend Iterator ListContainer<BaseElementType>::end(); + friend BaseElementType* ListContainer<BaseElementType>::ElementAt( + size_t index); + }; + + class ConstIterator : public ListContainerBase::ConstIterator { + // This class is only defined to forward iterate through + // ListContainerCharAllocator. + public: + ConstIterator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index) + : ListContainerBase::ConstIterator(container, + vector_ind, + item_iter, + index) {} + ConstIterator(const Iterator& other) // NOLINT + : ListContainerBase::ConstIterator(other) {} + const BaseElementType* operator->() const { + return reinterpret_cast<const BaseElementType*>(item_iterator); + } + const BaseElementType* operator*() const { + return reinterpret_cast<const BaseElementType*>(item_iterator); + } + ConstIterator operator++(int unused_post_increment) { + ConstIterator tmp = *this; + operator++(); + return tmp; + } + ConstIterator& operator++() { + Increment(); + ++index_; + return *this; + } + + private: + explicit ConstIterator( + const ListContainerBase::ConstIterator& base_iterator) + : ListContainerBase::ConstIterator(base_iterator) {} + friend ConstIterator ListContainer<BaseElementType>::cbegin() const; + friend ConstIterator ListContainer<BaseElementType>::cend() const; + friend const BaseElementType* ListContainer<BaseElementType>::ElementAt( + size_t index) const; + }; + + class ReverseIterator : public ListContainerBase::ReverseIterator { + // This class is only defined to reverse iterate through + // ListContainerCharAllocator. + public: + ReverseIterator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index) + : ListContainerBase::ReverseIterator(container, + vector_ind, + item_iter, + index) {} + BaseElementType* operator->() const { + return reinterpret_cast<BaseElementType*>(item_iterator); + } + BaseElementType* operator*() const { + return reinterpret_cast<BaseElementType*>(item_iterator); + } + ReverseIterator operator++(int unused_post_increment) { + ReverseIterator tmp = *this; + operator++(); + return tmp; + } + ReverseIterator& operator++() { + ReverseIncrement(); + ++index_; + return *this; + } + + private: + explicit ReverseIterator(ListContainerBase::ReverseIterator base_iterator) + : ListContainerBase::ReverseIterator(base_iterator) {} + friend ReverseIterator ListContainer<BaseElementType>::rbegin(); + friend ReverseIterator ListContainer<BaseElementType>::rend(); + }; + + class ConstReverseIterator : public ListContainerBase::ConstReverseIterator { + // This class is only defined to reverse iterate through + // ListContainerCharAllocator. + public: + ConstReverseIterator(ListContainerCharAllocator* container, + size_t vector_ind, + char* item_iter, + size_t index) + : ListContainerBase::ConstReverseIterator(container, + vector_ind, + item_iter, + index) {} + ConstReverseIterator(const ReverseIterator& other) // NOLINT + : ListContainerBase::ConstReverseIterator(other) {} + const BaseElementType* operator->() const { + return reinterpret_cast<const BaseElementType*>(item_iterator); + } + const BaseElementType* operator*() const { + return reinterpret_cast<const BaseElementType*>(item_iterator); + } + ConstReverseIterator operator++(int unused_post_increment) { + ConstReverseIterator tmp = *this; + operator++(); + return tmp; + } + ConstReverseIterator& operator++() { + ReverseIncrement(); + ++index_; + return *this; + } + + private: + explicit ConstReverseIterator( + ListContainerBase::ConstReverseIterator base_iterator) + : ListContainerBase::ConstReverseIterator(base_iterator) {} + friend ConstReverseIterator ListContainer<BaseElementType>::crbegin() const; + friend ConstReverseIterator ListContainer<BaseElementType>::crend() const; + }; +}; + +} // namespace cc + +#endif // CC_BASE_LIST_CONTAINER_H_ diff --git a/chromium/cc/base/list_container_unittest.cc b/chromium/cc/base/list_container_unittest.cc new file mode 100644 index 00000000000..d1fb3fb9490 --- /dev/null +++ b/chromium/cc/base/list_container_unittest.cc @@ -0,0 +1,1081 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/base/list_container.h" + +#include <algorithm> +#include <vector> +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +// Element class having derived classes. +class DerivedElement { + public: + virtual ~DerivedElement() {} + + protected: + bool bool_values[1]; + char char_values[1]; + int int_values[1]; + long long_values[1]; +}; + +class DerivedElement1 : public DerivedElement { + protected: + bool bool_values1[1]; + char char_values1[1]; + int int_values1[1]; + long long_values1[1]; +}; + +class DerivedElement2 : public DerivedElement { + protected: + bool bool_values2[2]; + char char_values2[2]; + int int_values2[2]; + long long_values2[2]; +}; + +class DerivedElement3 : public DerivedElement { + protected: + bool bool_values3[3]; + char char_values3[3]; + int int_values3[3]; + long long_values3[3]; +}; + +const size_t kLargestDerivedElementSize = sizeof(DerivedElement3); + +size_t LargestDerivedElementSize() { + static_assert(sizeof(DerivedElement1) <= kLargestDerivedElementSize, + "Largest Derived Element size needs update. DerivedElement1 is " + "currently largest."); + static_assert(sizeof(DerivedElement2) <= kLargestDerivedElementSize, + "Largest Derived Element size needs update. DerivedElement2 is " + "currently largest."); + + return kLargestDerivedElementSize; +} + +// Element class having no derived classes. +class NonDerivedElement { + public: + NonDerivedElement() {} + ~NonDerivedElement() {} + + int int_values[1]; +}; + +bool isConstNonDerivedElementPointer(const NonDerivedElement* ptr) { + return true; +} + +bool isConstNonDerivedElementPointer(NonDerivedElement* ptr) { + return false; +} + +const int kMagicNumberToUseForSimpleDerivedElementOne = 42; +const int kMagicNumberToUseForSimpleDerivedElementTwo = 314; +const int kMagicNumberToUseForSimpleDerivedElementThree = 1618; + +class SimpleDerivedElement : public DerivedElement { + public: + ~SimpleDerivedElement() override {} + void set_value(int val) { value = val; } + int get_value() { return value; } + + private: + int value; +}; + +class SimpleDerivedElementConstructMagicNumberOne + : public SimpleDerivedElement { + public: + SimpleDerivedElementConstructMagicNumberOne() { + set_value(kMagicNumberToUseForSimpleDerivedElementOne); + } +}; + +class SimpleDerivedElementConstructMagicNumberTwo + : public SimpleDerivedElement { + public: + SimpleDerivedElementConstructMagicNumberTwo() { + set_value(kMagicNumberToUseForSimpleDerivedElementTwo); + } +}; + +class SimpleDerivedElementConstructMagicNumberThree + : public SimpleDerivedElement { + public: + SimpleDerivedElementConstructMagicNumberThree() { + set_value(kMagicNumberToUseForSimpleDerivedElementThree); + } +}; + +class MockDerivedElement : public SimpleDerivedElementConstructMagicNumberOne { + public: + ~MockDerivedElement() override { Destruct(); } + MOCK_METHOD0(Destruct, void()); +}; + +class MockDerivedElementSubclass : public MockDerivedElement { + public: + MockDerivedElementSubclass() { + set_value(kMagicNumberToUseForSimpleDerivedElementTwo); + } +}; + +const size_t kCurrentLargestDerivedElementSize = + std::max(LargestDerivedElementSize(), sizeof(MockDerivedElementSubclass)); + +TEST(ListContainerTest, ConstructorCalledInAllocateAndConstruct) { + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize); + + size_t size = 2; + SimpleDerivedElementConstructMagicNumberOne* de_1 = + list.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberOne>(); + SimpleDerivedElementConstructMagicNumberTwo* de_2 = + list.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberTwo>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(de_1, list.front()); + EXPECT_EQ(de_2, list.back()); + + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, de_1->get_value()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, de_2->get_value()); +} + +TEST(ListContainerTest, DestructorCalled) { + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize); + + size_t size = 1; + MockDerivedElement* de_1 = list.AllocateAndConstruct<MockDerivedElement>(); + + EXPECT_CALL(*de_1, Destruct()); + EXPECT_EQ(size, list.size()); + EXPECT_EQ(de_1, list.front()); +} + +TEST(ListContainerTest, DestructorCalledOnceWhenClear) { + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize); + size_t size = 1; + MockDerivedElement* de_1 = list.AllocateAndConstruct<MockDerivedElement>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(de_1, list.front()); + + // Make sure destructor is called once during clear, and won't be called + // again. + testing::MockFunction<void()> separator; + { + testing::InSequence s; + EXPECT_CALL(*de_1, Destruct()); + EXPECT_CALL(separator, Call()); + EXPECT_CALL(*de_1, Destruct()).Times(0); + } + + list.clear(); + separator.Call(); +} + +TEST(ListContainerTest, ClearDoesNotMalloc) { + const size_t reserve = 10; + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize, + reserve); + + // Memory from the initial inner list that should be re-used after clear(). + std::vector<DerivedElement*> reserved_element_pointers; + for (size_t i = 0; i < reserve; i++) { + DerivedElement* element = list.AllocateAndConstruct<DerivedElement>(); + reserved_element_pointers.push_back(element); + } + EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + + // Allocate more than the reserve count, forcing new capacity to be added. + list.AllocateAndConstruct<DerivedElement>(); + EXPECT_NE(0u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + + // Clear should free all memory except the first |reserve| elements. + list.clear(); + EXPECT_EQ(reserve, list.AvailableSizeWithoutAnotherAllocationForTesting()); + + // Verify the first |reserve| elements are re-used after clear(). + for (size_t i = 0; i < reserve; i++) { + DerivedElement* element = list.AllocateAndConstruct<DerivedElement>(); + EXPECT_EQ(element, reserved_element_pointers[i]); + } + EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + + // Verify that capacity can still grow properly. + list.AllocateAndConstruct<DerivedElement>(); + EXPECT_NE(0u, list.AvailableSizeWithoutAnotherAllocationForTesting()); +} + +TEST(ListContainerTest, ReplaceExistingElement) { + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize); + size_t size = 1; + MockDerivedElement* de_1 = list.AllocateAndConstruct<MockDerivedElement>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(de_1, list.front()); + + // Make sure destructor is called once during clear, and won't be called + // again. + testing::MockFunction<void()> separator; + { + testing::InSequence s; + EXPECT_CALL(*de_1, Destruct()); + EXPECT_CALL(separator, Call()); + EXPECT_CALL(*de_1, Destruct()).Times(0); + } + + list.ReplaceExistingElement<MockDerivedElementSubclass>(list.begin()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, de_1->get_value()); + separator.Call(); + + EXPECT_CALL(*de_1, Destruct()); + list.clear(); +} + +TEST(ListContainerTest, DestructorCalledOnceWhenErase) { + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize); + size_t size = 1; + MockDerivedElement* de_1 = list.AllocateAndConstruct<MockDerivedElement>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(de_1, list.front()); + + // Make sure destructor is called once during clear, and won't be called + // again. + testing::MockFunction<void()> separator; + { + testing::InSequence s; + EXPECT_CALL(*de_1, Destruct()); + EXPECT_CALL(separator, Call()); + EXPECT_CALL(*de_1, Destruct()).Times(0); + } + + list.EraseAndInvalidateAllPointers(list.begin()); + separator.Call(); +} + +TEST(ListContainerTest, SimpleIndexAccessNonDerivedElement) { + ListContainer<NonDerivedElement> list; + + size_t size = 3; + NonDerivedElement* nde_1 = list.AllocateAndConstruct<NonDerivedElement>(); + NonDerivedElement* nde_2 = list.AllocateAndConstruct<NonDerivedElement>(); + NonDerivedElement* nde_3 = list.AllocateAndConstruct<NonDerivedElement>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(nde_1, list.front()); + EXPECT_EQ(nde_3, list.back()); + EXPECT_EQ(list.front(), list.ElementAt(0)); + EXPECT_EQ(nde_2, list.ElementAt(1)); + EXPECT_EQ(list.back(), list.ElementAt(2)); +} + +TEST(ListContainerTest, SimpleInsertionNonDerivedElement) { + ListContainer<NonDerivedElement> list; + + size_t size = 3; + NonDerivedElement* nde_1 = list.AllocateAndConstruct<NonDerivedElement>(); + list.AllocateAndConstruct<NonDerivedElement>(); + NonDerivedElement* nde_3 = list.AllocateAndConstruct<NonDerivedElement>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(nde_1, list.front()); + EXPECT_EQ(nde_3, list.back()); +} + +TEST(ListContainerTest, SimpleInsertionAndClearNonDerivedElement) { + ListContainer<NonDerivedElement> list; + EXPECT_TRUE(list.empty()); + EXPECT_EQ(0u, list.size()); + + size_t size = 3; + NonDerivedElement* nde_1 = list.AllocateAndConstruct<NonDerivedElement>(); + list.AllocateAndConstruct<NonDerivedElement>(); + NonDerivedElement* nde_3 = list.AllocateAndConstruct<NonDerivedElement>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(nde_1, list.front()); + EXPECT_EQ(nde_3, list.back()); + EXPECT_FALSE(list.empty()); + + list.clear(); + EXPECT_TRUE(list.empty()); + EXPECT_EQ(0u, list.size()); +} + +TEST(ListContainerTest, SimpleInsertionClearAndInsertAgainNonDerivedElement) { + ListContainer<NonDerivedElement> list; + EXPECT_TRUE(list.empty()); + EXPECT_EQ(0u, list.size()); + + size_t size = 2; + NonDerivedElement* nde_front = list.AllocateAndConstruct<NonDerivedElement>(); + NonDerivedElement* nde_back = list.AllocateAndConstruct<NonDerivedElement>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(nde_front, list.front()); + EXPECT_EQ(nde_back, list.back()); + EXPECT_FALSE(list.empty()); + + list.clear(); + EXPECT_TRUE(list.empty()); + EXPECT_EQ(0u, list.size()); + + size = 3; + nde_front = list.AllocateAndConstruct<NonDerivedElement>(); + list.AllocateAndConstruct<NonDerivedElement>(); + nde_back = list.AllocateAndConstruct<NonDerivedElement>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(nde_front, list.front()); + EXPECT_EQ(nde_back, list.back()); + EXPECT_FALSE(list.empty()); +} + +// This test is used to test when there is more than one allocation needed +// for, ListContainer can still perform like normal vector. +TEST(ListContainerTest, + SimpleInsertionTriggerMoreThanOneAllocationNonDerivedElement) { + ListContainer<NonDerivedElement> list(sizeof(NonDerivedElement), 2); + std::vector<NonDerivedElement*> nde_list; + size_t size = 10; + for (size_t i = 0; i < size; ++i) { + nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>()); + } + EXPECT_EQ(size, list.size()); + + ListContainer<NonDerivedElement>::Iterator iter = list.begin(); + for (std::vector<NonDerivedElement*>::const_iterator nde_iter = + nde_list.begin(); + nde_iter != nde_list.end(); ++nde_iter) { + EXPECT_EQ(*nde_iter, *iter); + ++iter; + } +} + +TEST(ListContainerTest, + CorrectAllocationSizeForMoreThanOneAllocationNonDerivedElement) { + // Constructor sets the allocation size to 2. Every time ListContainer needs + // to allocate again, it doubles allocation size. In this test, 10 elements is + // needed, thus ListContainerShould allocate spaces 2, 4 and 8 elements. + ListContainer<NonDerivedElement> list(sizeof(NonDerivedElement), 2); + std::vector<NonDerivedElement*> nde_list; + size_t size = 10; + for (size_t i = 0; i < size; ++i) { + // Before asking for a new element, space available without another + // allocation follows. + switch (i) { + case 2: + case 6: + EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 1: + case 5: + EXPECT_EQ(1u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 0: + case 4: + EXPECT_EQ(2u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 3: + EXPECT_EQ(3u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 9: + EXPECT_EQ(5u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 8: + EXPECT_EQ(6u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 7: + EXPECT_EQ(7u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + default: + break; + } + nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>()); + // After asking for a new element, space available without another + // allocation follows. + switch (i) { + case 1: + case 5: + EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 0: + case 4: + EXPECT_EQ(1u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 3: + EXPECT_EQ(2u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 2: + EXPECT_EQ(3u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 9: + EXPECT_EQ(4u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 8: + EXPECT_EQ(5u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 7: + EXPECT_EQ(6u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + case 6: + EXPECT_EQ(7u, list.AvailableSizeWithoutAnotherAllocationForTesting()); + break; + default: + break; + } + } + EXPECT_EQ(size, list.size()); + + ListContainer<NonDerivedElement>::Iterator iter = list.begin(); + for (std::vector<NonDerivedElement*>::const_iterator nde_iter = + nde_list.begin(); + nde_iter != nde_list.end(); ++nde_iter) { + EXPECT_EQ(*nde_iter, *iter); + ++iter; + } +} + +TEST(ListContainerTest, SimpleIterationNonDerivedElement) { + ListContainer<NonDerivedElement> list; + std::vector<NonDerivedElement*> nde_list; + size_t size = 10; + for (size_t i = 0; i < size; ++i) { + nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>()); + } + EXPECT_EQ(size, list.size()); + + size_t num_iters_in_list = 0; + { + std::vector<NonDerivedElement*>::const_iterator nde_iter = nde_list.begin(); + for (ListContainer<NonDerivedElement>::Iterator iter = list.begin(); + iter != list.end(); ++iter) { + EXPECT_EQ(*nde_iter, *iter); + ++num_iters_in_list; + ++nde_iter; + } + } + + size_t num_iters_in_vector = 0; + { + ListContainer<NonDerivedElement>::Iterator iter = list.begin(); + for (std::vector<NonDerivedElement*>::const_iterator nde_iter = + nde_list.begin(); + nde_iter != nde_list.end(); ++nde_iter) { + EXPECT_EQ(*nde_iter, *iter); + ++num_iters_in_vector; + ++iter; + } + } + + EXPECT_EQ(num_iters_in_vector, num_iters_in_list); +} + +TEST(ListContainerTest, SimpleConstIteratorIterationNonDerivedElement) { + ListContainer<NonDerivedElement> list; + std::vector<const NonDerivedElement*> nde_list; + size_t size = 10; + for (size_t i = 0; i < size; ++i) { + nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>()); + } + EXPECT_EQ(size, list.size()); + + { + std::vector<const NonDerivedElement*>::const_iterator nde_iter = + nde_list.begin(); + for (ListContainer<NonDerivedElement>::ConstIterator iter = list.begin(); + iter != list.end(); ++iter) { + EXPECT_TRUE(isConstNonDerivedElementPointer(*iter)); + EXPECT_EQ(*nde_iter, *iter); + ++nde_iter; + } + } + + { + std::vector<const NonDerivedElement*>::const_iterator nde_iter = + nde_list.begin(); + for (ListContainer<NonDerivedElement>::Iterator iter = list.begin(); + iter != list.end(); ++iter) { + EXPECT_FALSE(isConstNonDerivedElementPointer(*iter)); + EXPECT_EQ(*nde_iter, *iter); + ++nde_iter; + } + } + + { + ListContainer<NonDerivedElement>::ConstIterator iter = list.begin(); + for (std::vector<const NonDerivedElement*>::const_iterator nde_iter = + nde_list.begin(); + nde_iter != nde_list.end(); ++nde_iter) { + EXPECT_EQ(*nde_iter, *iter); + ++iter; + } + } +} + +TEST(ListContainerTest, SimpleReverseInsertionNonDerivedElement) { + ListContainer<NonDerivedElement> list; + std::vector<NonDerivedElement*> nde_list; + size_t size = 10; + for (size_t i = 0; i < size; ++i) { + nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>()); + } + EXPECT_EQ(size, list.size()); + + { + std::vector<NonDerivedElement*>::const_reverse_iterator nde_iter = + nde_list.rbegin(); + for (ListContainer<NonDerivedElement>::ReverseIterator iter = list.rbegin(); + iter != list.rend(); ++iter) { + EXPECT_EQ(*nde_iter, *iter); + ++nde_iter; + } + } + + { + ListContainer<NonDerivedElement>::ReverseIterator iter = list.rbegin(); + for (std::vector<NonDerivedElement*>::reverse_iterator nde_iter = + nde_list.rbegin(); + nde_iter != nde_list.rend(); ++nde_iter) { + EXPECT_EQ(*nde_iter, *iter); + ++iter; + } + } +} + +TEST(ListContainerTest, SimpleDeletion) { + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize); + std::vector<SimpleDerivedElement*> sde_list; + int size = 10; + for (int i = 0; i < size; ++i) { + sde_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>()); + sde_list.back()->set_value(i); + } + EXPECT_EQ(static_cast<size_t>(size), list.size()); + + list.EraseAndInvalidateAllPointers(list.begin()); + --size; + EXPECT_EQ(static_cast<size_t>(size), list.size()); + int i = 1; + for (ListContainer<DerivedElement>::Iterator iter = list.begin(); + iter != list.end(); ++iter) { + EXPECT_EQ(i, static_cast<SimpleDerivedElement*>(*iter)->get_value()); + ++i; + } +} + +TEST(ListContainerTest, DeletionAllInAllocation) { + const size_t kReserve = 10; + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize, + kReserve); + std::vector<SimpleDerivedElement*> sde_list; + // Add enough elements to cause another allocation. + for (size_t i = 0; i < kReserve + 1; ++i) { + sde_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>()); + sde_list.back()->set_value(static_cast<int>(i)); + } + EXPECT_EQ(kReserve + 1, list.size()); + + // Remove everything in the first allocation. + for (size_t i = 0; i < kReserve; ++i) + list.EraseAndInvalidateAllPointers(list.begin()); + EXPECT_EQ(1u, list.size()); + + // The last element is left. + SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*list.begin()); + EXPECT_EQ(static_cast<int>(kReserve), de->get_value()); + + // Remove the element from the 2nd allocation. + list.EraseAndInvalidateAllPointers(list.begin()); + EXPECT_EQ(0u, list.size()); +} + +TEST(ListContainerTest, DeletionAllInAllocationReversed) { + const size_t kReserve = 10; + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize, + kReserve); + std::vector<SimpleDerivedElement*> sde_list; + // Add enough elements to cause another allocation. + for (size_t i = 0; i < kReserve + 1; ++i) { + sde_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>()); + sde_list.back()->set_value(static_cast<int>(i)); + } + EXPECT_EQ(kReserve + 1, list.size()); + + // Remove everything in the 2nd allocation. + auto it = list.begin(); + for (size_t i = 0; i < kReserve; ++i) + ++it; + list.EraseAndInvalidateAllPointers(it); + + // The 2nd-last element is next, and the rest of the elements exist. + size_t i = kReserve - 1; + for (auto it = list.rbegin(); it != list.rend(); ++it) { + SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*it); + EXPECT_EQ(static_cast<int>(i), de->get_value()); + --i; + } + + // Can forward iterate too. + i = 0; + for (auto it = list.begin(); it != list.end(); ++it) { + SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*it); + EXPECT_EQ(static_cast<int>(i), de->get_value()); + ++i; + } + + // Remove the last thing from the 1st allocation. + it = list.begin(); + for (size_t i = 0; i < kReserve - 1; ++i) + ++it; + list.EraseAndInvalidateAllPointers(it); + + // The 2nd-last element is next, and the rest of the elements exist. + i = kReserve - 2; + for (auto it = list.rbegin(); it != list.rend(); ++it) { + SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*it); + EXPECT_EQ(static_cast<int>(i), de->get_value()); + --i; + } + + // Can forward iterate too. + i = 0; + for (auto it = list.begin(); it != list.end(); ++it) { + SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*it); + EXPECT_EQ(static_cast<int>(i), de->get_value()); + ++i; + } +} + +TEST(ListContainerTest, SimpleIterationAndManipulation) { + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize); + std::vector<SimpleDerivedElement*> sde_list; + size_t size = 10; + for (size_t i = 0; i < size; ++i) { + SimpleDerivedElement* simple_dq = + list.AllocateAndConstruct<SimpleDerivedElement>(); + sde_list.push_back(simple_dq); + } + EXPECT_EQ(size, list.size()); + + ListContainer<DerivedElement>::Iterator iter = list.begin(); + for (int i = 0; i < 10; ++i) { + static_cast<SimpleDerivedElement*>(*iter)->set_value(i); + ++iter; + } + + int i = 0; + for (std::vector<SimpleDerivedElement*>::const_iterator sde_iter = + sde_list.begin(); + sde_iter < sde_list.end(); ++sde_iter) { + EXPECT_EQ(i, (*sde_iter)->get_value()); + ++i; + } +} + +TEST(ListContainerTest, SimpleManipulationWithIndexSimpleDerivedElement) { + ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize); + std::vector<SimpleDerivedElement*> de_list; + int size = 10; + for (int i = 0; i < size; ++i) { + de_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>()); + } + EXPECT_EQ(static_cast<size_t>(size), list.size()); + + for (int i = 0; i < size; ++i) { + static_cast<SimpleDerivedElement*>(list.ElementAt(i))->set_value(i); + } + + int i = 0; + for (std::vector<SimpleDerivedElement*>::const_iterator + de_iter = de_list.begin(); + de_iter != de_list.end(); ++de_iter, ++i) { + EXPECT_EQ(i, (*de_iter)->get_value()); + } +} + +TEST(ListContainerTest, + SimpleManipulationWithIndexMoreThanOneAllocationSimpleDerivedElement) { + ListContainer<DerivedElement> list(LargestDerivedElementSize(), 2); + std::vector<SimpleDerivedElement*> de_list; + int size = 10; + for (int i = 0; i < size; ++i) { + de_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>()); + } + EXPECT_EQ(static_cast<size_t>(size), list.size()); + + for (int i = 0; i < size; ++i) { + static_cast<SimpleDerivedElement*>(list.ElementAt(i))->set_value(i); + } + + int i = 0; + for (std::vector<SimpleDerivedElement*>::const_iterator + de_iter = de_list.begin(); + de_iter != de_list.end(); ++de_iter, ++i) { + EXPECT_EQ(i, (*de_iter)->get_value()); + } +} + +TEST(ListContainerTest, + SimpleIterationAndReverseIterationWithIndexNonDerivedElement) { + ListContainer<NonDerivedElement> list; + std::vector<NonDerivedElement*> nde_list; + size_t size = 10; + for (size_t i = 0; i < size; ++i) { + nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>()); + } + EXPECT_EQ(size, list.size()); + + size_t i = 0; + for (ListContainer<NonDerivedElement>::Iterator iter = list.begin(); + iter != list.end(); ++iter) { + EXPECT_EQ(i, iter.index()); + ++i; + } + + i = 0; + for (ListContainer<NonDerivedElement>::ReverseIterator iter = list.rbegin(); + iter != list.rend(); ++iter) { + EXPECT_EQ(i, iter.index()); + ++i; + } +} + +// Increments an int when constructed (or the counter pointer is supplied) and +// decrements when destructed. +class InstanceCounter { + public: + InstanceCounter() : counter_(nullptr) {} + explicit InstanceCounter(int* counter) { SetCounter(counter); } + ~InstanceCounter() { + if (counter_) + --*counter_; + } + void SetCounter(int* counter) { + counter_ = counter; + ++*counter_; + } + + private: + int* counter_; +}; + +TEST(ListContainerTest, RemoveLastDestruction) { + // We keep an explicit instance count to make sure that the destructors are + // indeed getting called. + int counter = 0; + ListContainer<InstanceCounter> list(sizeof(InstanceCounter), 1); + EXPECT_EQ(0, counter); + EXPECT_EQ(0u, list.size()); + + // We should be okay to add one and then go back to zero. + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); + EXPECT_EQ(1, counter); + EXPECT_EQ(1u, list.size()); + list.RemoveLast(); + EXPECT_EQ(0, counter); + EXPECT_EQ(0u, list.size()); + + // We should also be okay to remove the last multiple times, as long as there + // are enough elements in the first place. + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); + list.RemoveLast(); + list.RemoveLast(); + EXPECT_EQ(4, counter); // Leaves one in the last list. + EXPECT_EQ(4u, list.size()); + list.RemoveLast(); + EXPECT_EQ(3, counter); // Removes an inner list from before. + EXPECT_EQ(3u, list.size()); +} + +// TODO(jbroman): std::equal would work if ListContainer iterators satisfied the +// usual STL iterator constraints. We should fix that. +template <typename It1, typename It2> +bool Equal(It1 it1, const It1& end1, It2 it2) { + for (; it1 != end1; ++it1, ++it2) { + if (!(*it1 == *it2)) + return false; + } + return true; +} + +TEST(ListContainerTest, RemoveLastIteration) { + struct SmallStruct { + char dummy[16]; + }; + ListContainer<SmallStruct> list(sizeof(SmallStruct), 1); + std::vector<SmallStruct*> pointers; + + // Utilities which keep these two lists in sync and check that their iteration + // order matches. + auto push = [&list, &pointers]() { + pointers.push_back(list.AllocateAndConstruct<SmallStruct>()); + }; + auto pop = [&list, &pointers]() { + pointers.pop_back(); + list.RemoveLast(); + }; + auto check_equal = [&list, &pointers]() { + // They should be of the same size, and compare equal with all four kinds of + // iteration. + // Apparently Mac doesn't have vector::cbegin and vector::crbegin? + const auto& const_pointers = pointers; + ASSERT_EQ(list.size(), pointers.size()); + ASSERT_TRUE(Equal(list.begin(), list.end(), pointers.begin())); + ASSERT_TRUE(Equal(list.cbegin(), list.cend(), const_pointers.begin())); + ASSERT_TRUE(Equal(list.rbegin(), list.rend(), pointers.rbegin())); + ASSERT_TRUE(Equal(list.crbegin(), list.crend(), const_pointers.rbegin())); + }; + + check_equal(); // Initially empty. + push(); + check_equal(); // One full inner list. + push(); + check_equal(); // One full, one partially full. + push(); + push(); + check_equal(); // Two full, one partially full. + pop(); + check_equal(); // Two full, one empty. + pop(); + check_equal(); // One full, one partially full, one empty. + pop(); + check_equal(); // One full, one empty. + push(); + pop(); + pop(); + ASSERT_TRUE(list.empty()); + check_equal(); // Empty. +} + +TEST(ListContainerTest, AppendByMovingSameList) { + ListContainer<SimpleDerivedElement> list(kCurrentLargestDerivedElementSize); + list.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberOne>(); + + list.AppendByMoving(list.front()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + list.back()->get_value()); + EXPECT_EQ(2u, list.size()); + + list.front()->set_value(kMagicNumberToUseForSimpleDerivedElementTwo); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, + list.front()->get_value()); + list.AppendByMoving(list.front()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, + list.back()->get_value()); + EXPECT_EQ(3u, list.size()); +} + +TEST(ListContainerTest, AppendByMovingDoesNotDestruct) { + ListContainer<DerivedElement> list_1(kCurrentLargestDerivedElementSize); + ListContainer<DerivedElement> list_2(kCurrentLargestDerivedElementSize); + MockDerivedElement* mde_1 = list_1.AllocateAndConstruct<MockDerivedElement>(); + + // Make sure destructor isn't called during AppendByMoving. + list_2.AppendByMoving(mde_1); + EXPECT_CALL(*mde_1, Destruct()).Times(0); + testing::Mock::VerifyAndClearExpectations(mde_1); + mde_1 = static_cast<MockDerivedElement*>(list_2.back()); + EXPECT_CALL(*mde_1, Destruct()); +} + +TEST(ListContainerTest, AppendByMovingReturnsMovedPointer) { + ListContainer<SimpleDerivedElement> list_1(kCurrentLargestDerivedElementSize); + ListContainer<SimpleDerivedElement> list_2(kCurrentLargestDerivedElementSize); + SimpleDerivedElement* simple_element = + list_1.AllocateAndConstruct<SimpleDerivedElement>(); + + SimpleDerivedElement* moved_1 = list_2.AppendByMoving(simple_element); + EXPECT_EQ(list_2.back(), moved_1); + + SimpleDerivedElement* moved_2 = list_1.AppendByMoving(moved_1); + EXPECT_EQ(list_1.back(), moved_2); + EXPECT_NE(moved_1, moved_2); +} + +TEST(ListContainerTest, AppendByMovingReplacesSourceWithNewDerivedElement) { + ListContainer<SimpleDerivedElementConstructMagicNumberOne> list_1( + kCurrentLargestDerivedElementSize); + ListContainer<SimpleDerivedElementConstructMagicNumberTwo> list_2( + kCurrentLargestDerivedElementSize); + + list_1.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberOne>(); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + list_1.front()->get_value()); + + list_2.AppendByMoving(list_1.front()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + list_1.front()->get_value()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + list_2.front()->get_value()); + + // Change the value of list_2.front() to ensure the value is actually moved. + list_2.back()->set_value(kMagicNumberToUseForSimpleDerivedElementThree); + + list_1.AppendByMoving(list_2.back()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + list_1.front()->get_value()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementThree, + list_1.back()->get_value()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, + list_2.back()->get_value()); + + // AppendByMoving replaces the source element with a new derived element so + // we do not expect sizes to shrink after AppendByMoving is called. + EXPECT_EQ(2u, list_1.size()); // One direct allocation, one AppendByMoving. + EXPECT_EQ(1u, list_2.size()); // One AppendByMoving. +} + +const size_t kLongCountForLongSimpleDerivedElement = 5; + +class LongSimpleDerivedElement : public SimpleDerivedElement { + public: + ~LongSimpleDerivedElement() override {} + void SetAllValues(unsigned long value) { + for (size_t i = 0; i < kLongCountForLongSimpleDerivedElement; i++) + values[i] = value; + } + bool AreAllValuesEqualTo(size_t value) const { + for (size_t i = 1; i < kLongCountForLongSimpleDerivedElement; i++) { + if (values[i] != values[0]) + return false; + } + return true; + } + + private: + unsigned long values[kLongCountForLongSimpleDerivedElement]; +}; + +const unsigned long kMagicNumberToUseForLongSimpleDerivedElement = 2718ul; + +class LongSimpleDerivedElementConstructMagicNumber + : public LongSimpleDerivedElement { + public: + LongSimpleDerivedElementConstructMagicNumber() { + SetAllValues(kMagicNumberToUseForLongSimpleDerivedElement); + } +}; + +TEST(ListContainerTest, AppendByMovingLongAndSimpleDerivedElements) { + static_assert(sizeof(LongSimpleDerivedElement) > sizeof(SimpleDerivedElement), + "LongSimpleDerivedElement should be larger than " + "SimpleDerivedElement's size."); + static_assert(sizeof(LongSimpleDerivedElement) <= kLargestDerivedElementSize, + "LongSimpleDerivedElement should be smaller than the maximum " + "DerivedElement size."); + + ListContainer<SimpleDerivedElement> list(kCurrentLargestDerivedElementSize); + list.AllocateAndConstruct<LongSimpleDerivedElementConstructMagicNumber>(); + list.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberOne>(); + + EXPECT_TRUE( + static_cast<LongSimpleDerivedElement*>(list.front()) + ->AreAllValuesEqualTo(kMagicNumberToUseForLongSimpleDerivedElement)); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + list.back()->get_value()); + + // Test that moving a simple derived element actually moves enough data so + // that the LongSimpleDerivedElement at this location is entirely moved. + SimpleDerivedElement* simple_element = list.back(); + list.AppendByMoving(list.front()); + EXPECT_TRUE( + static_cast<LongSimpleDerivedElement*>(list.back()) + ->AreAllValuesEqualTo(kMagicNumberToUseForLongSimpleDerivedElement)); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + simple_element->get_value()); + + LongSimpleDerivedElement* long_element = + static_cast<LongSimpleDerivedElement*>(list.back()); + list.AppendByMoving(simple_element); + EXPECT_TRUE(long_element->AreAllValuesEqualTo( + kMagicNumberToUseForLongSimpleDerivedElement)); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + list.back()->get_value()); +} + +TEST(ListContainerTest, Swap) { + ListContainer<SimpleDerivedElement> list_1(kCurrentLargestDerivedElementSize); + list_1.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberOne>(); + ListContainer<SimpleDerivedElement> list_2(kCurrentLargestDerivedElementSize); + list_2.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberTwo>(); + list_2.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberThree>(); + + SimpleDerivedElement* pre_swap_list_1_front = list_1.front(); + + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + list_1.front()->get_value()); + EXPECT_EQ(1u, list_1.size()); + + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, + list_2.front()->get_value()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementThree, + list_2.back()->get_value()); + EXPECT_EQ(2u, list_2.size()); + + list_2.swap(list_1); + + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, + list_1.front()->get_value()); + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementThree, + list_1.back()->get_value()); + EXPECT_EQ(2u, list_1.size()); + + EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, + list_2.front()->get_value()); + EXPECT_EQ(1u, list_2.size()); + + // Ensure pointers are still valid after swapping. + EXPECT_EQ(pre_swap_list_1_front, list_2.front()); +} + +TEST(ListContainerTest, GetCapacityInBytes) { + const int iterations = 500; + const size_t initial_capacity = 10; + const size_t upper_bound_on_min_capacity = initial_capacity; + + // At time of writing, removing elements from the end can cause up to 7x the + // memory required to be consumed, in the worst case, since we can have up to + // two trailing inner lists that are empty (for 2*size + 4*size in unused + // memory, due to the exponential growth strategy). + const size_t max_waste_factor = 8; + + ListContainer<DerivedElement> list(LargestDerivedElementSize(), + initial_capacity); + + // The capacity should grow with the list. + for (int i = 0; i < iterations; i++) { + size_t capacity = list.GetCapacityInBytes(); + ASSERT_GE(capacity, list.size() * LargestDerivedElementSize()); + ASSERT_LE(capacity, std::max(list.size(), upper_bound_on_min_capacity) * + max_waste_factor * LargestDerivedElementSize()); + list.AllocateAndConstruct<DerivedElement1>(); + } + + // The capacity should shrink with the list. + for (int i = 0; i < iterations; i++) { + size_t capacity = list.GetCapacityInBytes(); + ASSERT_GE(capacity, list.size() * LargestDerivedElementSize()); + ASSERT_LE(capacity, std::max(list.size(), upper_bound_on_min_capacity) * + max_waste_factor * LargestDerivedElementSize()); + list.RemoveLast(); + } +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/base/math_util.h b/chromium/cc/base/math_util.h index 749b9bdbae1..4c40e8ef9a4 100644 --- a/chromium/cc/base/math_util.h +++ b/chromium/cc/base/math_util.h @@ -96,6 +96,29 @@ class CC_EXPORT MathUtil { return (d > 0.0) ? std::floor(d + 0.5) : std::ceil(d - 0.5); } + // RoundUp rounds up a given |n| to be a multiple of |mul|. + // Examples: + // - RoundUp(123, 50) returns 150. + // - RoundUp(-123, 50) returns -100. + template <typename T> + static T RoundUp(T n, T mul) { + static_assert(std::numeric_limits<T>::is_integer, + "T must be an integer type"); + return (n > 0) ? ((n + mul - 1) / mul) * mul : (n / mul) * mul; + } + + // RoundDown rounds down a given |n| to be a multiple of |mul|. + // Examples: + // - RoundDown(123, 50) returns 100. + // - RoundDown(-123, 50) returns -150. + template <typename T> + static T RoundDown(T n, T mul) { + static_assert(std::numeric_limits<T>::is_integer, + "T must be an integer type"); + return (n > 0) ? (n / mul) * mul : (n == 0) ? 0 + : ((n - mul + 1) / mul) * mul; + } + template <typename T> static T ClampToRange(T value, T min, T max) { return std::min(std::max(value, min), max); } diff --git a/chromium/cc/base/math_util_unittest.cc b/chromium/cc/base/math_util_unittest.cc index 325870dc1f6..1d43e0f2129 100644 --- a/chromium/cc/base/math_util_unittest.cc +++ b/chromium/cc/base/math_util_unittest.cc @@ -193,5 +193,59 @@ TEST(MathUtilTest, MapEnclosedRectWith2dAxisAlignedTransform) { EXPECT_EQ(gfx::Rect(2, 4, 6, 8), output); } +TEST(MathUtilTest, RoundUp) { + for (int multiplier = 1; multiplier <= 10; ++multiplier) { + // Try attempts in descending order, so that we can + // determine the correct value before it's needed. + int correct; + for (int attempt = 5 * multiplier; attempt >= -5 * multiplier; --attempt) { + if ((attempt % multiplier) == 0) + correct = attempt; + EXPECT_EQ(correct, MathUtil::RoundUp(attempt, multiplier)) + << "attempt=" << attempt << " multiplier=" << multiplier; + } + } + + for (unsigned multiplier = 1; multiplier <= 10; ++multiplier) { + // Try attempts in descending order, so that we can + // determine the correct value before it's needed. + unsigned correct; + for (unsigned attempt = 5 * multiplier; attempt > 0; --attempt) { + if ((attempt % multiplier) == 0) + correct = attempt; + EXPECT_EQ(correct, MathUtil::RoundUp(attempt, multiplier)) + << "attempt=" << attempt << " multiplier=" << multiplier; + } + EXPECT_EQ(0u, MathUtil::RoundUp(0u, multiplier)) + << "attempt=0 multiplier=" << multiplier; + } +} + +TEST(MathUtilTest, RoundDown) { + for (int multiplier = 1; multiplier <= 10; ++multiplier) { + // Try attempts in ascending order, so that we can + // determine the correct value before it's needed. + int correct; + for (int attempt = -5 * multiplier; attempt <= 5 * multiplier; ++attempt) { + if ((attempt % multiplier) == 0) + correct = attempt; + EXPECT_EQ(correct, MathUtil::RoundDown(attempt, multiplier)) + << "attempt=" << attempt << " multiplier=" << multiplier; + } + } + + for (unsigned multiplier = 1; multiplier <= 10; ++multiplier) { + // Try attempts in ascending order, so that we can + // determine the correct value before it's needed. + unsigned correct; + for (unsigned attempt = 0; attempt <= 5 * multiplier; ++attempt) { + if ((attempt % multiplier) == 0) + correct = attempt; + EXPECT_EQ(correct, MathUtil::RoundDown(attempt, multiplier)) + << "attempt=" << attempt << " multiplier=" << multiplier; + } + } +} + } // namespace } // namespace cc diff --git a/chromium/cc/base/resource_id.h b/chromium/cc/base/resource_id.h new file mode 100644 index 00000000000..84d00ad8e59 --- /dev/null +++ b/chromium/cc/base/resource_id.h @@ -0,0 +1,16 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_BASE_RESOURCE_ID_H_ +#define CC_BASE_RESOURCE_ID_H_ + +#include <stdint.h> + +namespace cc { + +using ResourceId = uint32_t; + +} // namespace cc + +#endif // CC_BASE_RESOURCE_ID_H_ diff --git a/chromium/cc/base/sidecar_list_container.h b/chromium/cc/base/sidecar_list_container.h new file mode 100644 index 00000000000..5135ab1d7d2 --- /dev/null +++ b/chromium/cc/base/sidecar_list_container.h @@ -0,0 +1,97 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_BASE_SIDECAR_LIST_CONTAINER_H_ +#define CC_BASE_SIDECAR_LIST_CONTAINER_H_ + +#include "base/logging.h" +#include "cc/base/list_container.h" + +namespace cc { + +// This is a container, based on ListContainer, which allocates space in a +// contiguous block for objects subclassing BaseElementType, as well as an +// additional "sidecar" of opaque type. +// +// It takes a pointer to a function for tearing down sidecar objects, which must +// free any resources held by it as its memory will be deallocated by the +// container afterwards. When an element is constructed, callers are expected to +// immediately construct the sidecar as well (such that the sidecar destroyer +// will run safely and successfully). +// +// TODO(jbroman): It would be nice to be clear about the memory alignment +// constraints here, but that probably requires closer inspection of +// ListContainer first. +template <class BaseElementType> +class SidecarListContainer { + public: + using SidecarDestroyer = void (*)(void* sidecar); + using Iterator = typename ListContainer<BaseElementType>::Iterator; + using ConstIterator = typename ListContainer<BaseElementType>::ConstIterator; + using ReverseIterator = + typename ListContainer<BaseElementType>::ReverseIterator; + using ConstReverseIterator = + typename ListContainer<BaseElementType>::ConstReverseIterator; + + explicit SidecarListContainer(size_t max_size_for_derived_class, + size_t max_size_for_sidecar, + size_t num_of_elements_to_reserve_for, + SidecarDestroyer destroyer) + : list_(max_size_for_derived_class + max_size_for_sidecar, + num_of_elements_to_reserve_for), + destroyer_(destroyer), + sidecar_offset_(max_size_for_derived_class) {} + ~SidecarListContainer() { DestroyAllSidecars(); } + + // Forward most of the reading logic to ListContainer. + bool empty() const { return list_.empty(); } + size_t size() const { return list_.size(); } + size_t GetCapacityInBytes() const { return list_.GetCapacityInBytes(); } + ConstIterator begin() const { return list_.begin(); } + ConstIterator end() const { return list_.end(); } + + template <typename DerivedElementType> + DerivedElementType* AllocateAndConstruct() { + return list_.template AllocateAndConstruct<DerivedElementType>(); + } + template <typename DerivedElementType> + DerivedElementType* AllocateAndCopyFrom(const DerivedElementType* source) { + return list_.template AllocateAndCopyFrom<DerivedElementType>(source); + } + + void clear() { + DestroyAllSidecars(); + list_.clear(); + } + + void RemoveLast() { + destroyer_(GetSidecar(*list_.rbegin())); + list_.RemoveLast(); + } + + // This permits a client to exchange a pointer to an element to a pointer to + // its corresponding sidecar. + void* GetSidecar(BaseElementType* element) { + DCHECK_GT(sidecar_offset_, 0u); + return reinterpret_cast<char*>(element) + sidecar_offset_; + } + const void* GetSidecar(const BaseElementType* element) { + DCHECK_GT(sidecar_offset_, 0u); + return reinterpret_cast<const char*>(element) + sidecar_offset_; + } + + private: + void DestroyAllSidecars() { + for (auto* element : list_) + destroyer_(GetSidecar(element)); + } + + ListContainer<BaseElementType> list_; + SidecarDestroyer destroyer_; + size_t sidecar_offset_; +}; + +} // namespace cc + +#endif // CC_BASE_SIDECAR_LIST_CONTAINER_H_ diff --git a/chromium/cc/base/sidecar_list_container_unittest.cc b/chromium/cc/base/sidecar_list_container_unittest.cc new file mode 100644 index 00000000000..0012014df8f --- /dev/null +++ b/chromium/cc/base/sidecar_list_container_unittest.cc @@ -0,0 +1,198 @@ +// Copyright 2015 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/base/sidecar_list_container.h" + +#include <algorithm> + +#include "base/logging.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +const size_t kNumInitiallyReservedElements = 2; +const size_t kNumElementsForTest = 100; + +class DestructionNotifier { + public: + DestructionNotifier() : flag_(nullptr) {} + explicit DestructionNotifier(bool* flag) { set_flag(flag); } + ~DestructionNotifier() { + if (flag_) + *flag_ = true; + } + void set_flag(bool* flag) { + if (flag) + DCHECK(!*flag); + flag_ = flag; + } + + private: + bool* flag_; +}; + +class TestElement { + public: + TestElement() {} + virtual ~TestElement() {} + void set_destruction_flag(bool* flag) { notifier_.set_flag(flag); } + + private: + DestructionNotifier notifier_; +}; + +class DerivedTestElement : public TestElement { + public: + int additional_field = 0; +}; + +class TestSidecar { + public: + TestSidecar() {} + explicit TestSidecar(bool* destruction_flag) : notifier_(destruction_flag) {} + + static void Destroy(void* sidecar) { + static_cast<TestSidecar*>(sidecar)->~TestSidecar(); + } + + protected: + virtual ~TestSidecar() {} + + private: + DestructionNotifier notifier_; +}; + +class DerivedTestSidecar : public TestSidecar { + public: + DerivedTestSidecar() {} + explicit DerivedTestSidecar(bool* destruction_flag) + : TestSidecar(destruction_flag) {} + int additional_field = 0; + + private: + ~DerivedTestSidecar() override {} +}; + +class TestContainer : public SidecarListContainer<TestElement> { + public: + TestContainer() + : SidecarListContainer( + std::max(sizeof(TestElement), sizeof(DerivedTestElement)), + std::max(sizeof(TestSidecar), sizeof(DerivedTestSidecar)), + kNumInitiallyReservedElements, + &TestSidecar::Destroy) {} +}; + +TEST(SidecarListContainerTest, Destructor) { + bool element_destroyed = false; + bool sidecar_destroyed = false; + + { + TestContainer container; + + TestElement* element = container.AllocateAndConstruct<TestElement>(); + TestSidecar* sidecar = + new (container.GetSidecar(element)) TestSidecar(&sidecar_destroyed); + element->set_destruction_flag(&element_destroyed); + + // They shouldn't be destroyed yet. And they shouldn't overlap in memory. + ASSERT_FALSE(element_destroyed); + ASSERT_FALSE(sidecar_destroyed); + ASSERT_GE(reinterpret_cast<char*>(sidecar), + reinterpret_cast<char*>(element) + sizeof(TestElement)); + } + + // They should, however, be destroyed when going out of scope. + ASSERT_TRUE(element_destroyed); + ASSERT_TRUE(sidecar_destroyed); +} + +TEST(SidecarListContainerTest, Clear) { + bool element_destroyed = false; + bool sidecar_destroyed = false; + + TestContainer container; + + TestElement* element = container.AllocateAndConstruct<TestElement>(); + new (container.GetSidecar(element)) TestSidecar(&sidecar_destroyed); + element->set_destruction_flag(&element_destroyed); + + // They shouldn't be destroyed yet. + ASSERT_FALSE(element_destroyed); + ASSERT_FALSE(sidecar_destroyed); + + // They should, however, be destroyed after clearing. + container.clear(); + EXPECT_TRUE(element_destroyed); + EXPECT_TRUE(sidecar_destroyed); +} + +TEST(SidecarListContainerTest, DerivedTypes) { + bool element_destroyed = false; + bool sidecar_destroyed = false; + + { + TestContainer container; + + DerivedTestElement* element = + container.AllocateAndConstruct<DerivedTestElement>(); + DerivedTestSidecar* sidecar = new (container.GetSidecar(element)) + DerivedTestSidecar(&sidecar_destroyed); + element->set_destruction_flag(&element_destroyed); + element->additional_field = 12; + sidecar->additional_field = 13; + + // They shouldn't be destroyed yet. + ASSERT_FALSE(element_destroyed); + ASSERT_FALSE(sidecar_destroyed); + } + + // They should, however, be destroyed when going out of scope. + EXPECT_TRUE(element_destroyed); + EXPECT_TRUE(sidecar_destroyed); +} + +TEST(SidecarListContainerTest, AddingAndRemovingElements) { + TestContainer container; + EXPECT_TRUE(container.empty()); + EXPECT_EQ(0u, container.size()); + EXPECT_EQ(container.end(), container.begin()); + + for (size_t i = 1; i <= kNumElementsForTest; i++) { + TestElement* element = container.AllocateAndConstruct<TestElement>(); + new (container.GetSidecar(element)) TestSidecar(); + + ASSERT_FALSE(container.empty()); + ASSERT_EQ(i, container.size()); + ASSERT_NE(container.end(), container.begin()); + } + + size_t num_elements = 0; + for (const auto* element : container) { + (void)element; + num_elements++; + } + EXPECT_EQ(kNumElementsForTest, num_elements); + + container.clear(); + EXPECT_TRUE(container.empty()); + EXPECT_EQ(0u, container.size()); + EXPECT_EQ(container.end(), container.begin()); +} + +TEST(SidecarListContainerTest, RemoveLast) { + // We need only ensure that the sidecar is also destroyed on RemoveLast. + // The rest is logic already present in ListContainer. + bool sidecar_destroyed = false; + TestContainer container; + TestElement* element = container.AllocateAndConstruct<TestElement>(); + new (container.GetSidecar(element)) TestSidecar(&sidecar_destroyed); + ASSERT_FALSE(sidecar_destroyed); + container.RemoveLast(); + ASSERT_TRUE(sidecar_destroyed); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/base/switches.cc b/chromium/cc/base/switches.cc index ae424824611..0a27205d9d3 100644 --- a/chromium/cc/base/switches.cc +++ b/chromium/cc/base/switches.cc @@ -51,10 +51,6 @@ const char kCompositeToMailbox[] = "composite-to-mailbox"; const char kStrictLayerPropertyChangeChecking[] = "strict-layer-property-change-checking"; -// Virtual viewport for fixed-position elements, scrollbars during pinch. -const char kEnablePinchVirtualViewport[] = "enable-pinch-virtual-viewport"; -const char kDisablePinchVirtualViewport[] = "disable-pinch-virtual-viewport"; - // Ensures that the draw properties computed via the property trees match those // computed by CalcDrawProperties. const char kEnablePropertyTreeVerification[] = @@ -63,6 +59,9 @@ const char kEnablePropertyTreeVerification[] = // Disable partial swap which is needed for some OpenGL drivers / emulators. const char kUIDisablePartialSwap[] = "ui-disable-partial-swap"; +// Use a BeginFrame signal from browser to renderer to schedule rendering. +const char kEnableBeginFrameScheduling[] = "enable-begin-frame-scheduling"; + // Enables the GPU benchmarking extension const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking"; diff --git a/chromium/cc/base/switches.h b/chromium/cc/base/switches.h index 46fe922ea7e..cd5e3678824 100644 --- a/chromium/cc/base/switches.h +++ b/chromium/cc/base/switches.h @@ -27,13 +27,12 @@ CC_EXPORT extern const char kSlowDownRasterScaleFactor[]; CC_EXPORT extern const char kCompositeToMailbox[]; CC_EXPORT extern const char kMaxTilesForInterestArea[]; CC_EXPORT extern const char kMaxUnusedResourceMemoryUsagePercentage[]; -CC_EXPORT extern const char kEnablePinchVirtualViewport[]; -CC_EXPORT extern const char kDisablePinchVirtualViewport[]; CC_EXPORT extern const char kStrictLayerPropertyChangeChecking[]; CC_EXPORT extern const char kEnablePropertyTreeVerification[]; // Switches for both the renderer and ui compositors. CC_EXPORT extern const char kUIDisablePartialSwap[]; +CC_EXPORT extern const char kEnableBeginFrameScheduling[]; CC_EXPORT extern const char kEnableGpuBenchmarking[]; // Debug visualizations. diff --git a/chromium/cc/base/unique_notifier.cc b/chromium/cc/base/unique_notifier.cc index 0656c6d747b..eb0b09af36e 100644 --- a/chromium/cc/base/unique_notifier.cc +++ b/chromium/cc/base/unique_notifier.cc @@ -22,6 +22,10 @@ UniqueNotifier::UniqueNotifier(base::SequencedTaskRunner* task_runner, UniqueNotifier::~UniqueNotifier() { } +void UniqueNotifier::Cancel() { + notification_pending_ = false; +} + void UniqueNotifier::Schedule() { if (notification_pending_) return; @@ -33,6 +37,9 @@ void UniqueNotifier::Schedule() { } void UniqueNotifier::Notify() { + if (!notification_pending_) + return; + // Note that the order here is important in case closure schedules another // run. notification_pending_ = false; diff --git a/chromium/cc/base/unique_notifier.h b/chromium/cc/base/unique_notifier.h index 9a4a02cd62c..3cbc22a0a79 100644 --- a/chromium/cc/base/unique_notifier.h +++ b/chromium/cc/base/unique_notifier.h @@ -29,6 +29,9 @@ class CC_EXPORT UniqueNotifier { // pending, then only one notification will take place. void Schedule(); + // Cancel a pending notification, if one was scheduled. + void Cancel(); + private: void Notify(); diff --git a/chromium/cc/base/unique_notifier_unittest.cc b/chromium/cc/base/unique_notifier_unittest.cc index 7b52512d6c7..b53b52a76fd 100644 --- a/chromium/cc/base/unique_notifier_unittest.cc +++ b/chromium/cc/base/unique_notifier_unittest.cc @@ -50,12 +50,26 @@ TEST_F(UniqueNotifierTest, Schedule) { base::RunLoop().RunUntilIdle(); EXPECT_EQ(2, NotificationCount()); + // Schedule and cancel. + notifier.Schedule(); + notifier.Cancel(); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(2, NotificationCount()); + + notifier.Schedule(); + notifier.Cancel(); + notifier.Schedule(); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(3, NotificationCount()); + notifier.Schedule(); } // Notifier went out of scope, so we don't expect to get a notification. base::RunLoop().RunUntilIdle(); - EXPECT_EQ(2, NotificationCount()); + EXPECT_EQ(3, NotificationCount()); } } // namespace diff --git a/chromium/cc/base/util.h b/chromium/cc/base/util.h deleted file mode 100644 index a16d4855283..00000000000 --- a/chromium/cc/base/util.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_BASE_UTIL_H_ -#define CC_BASE_UTIL_H_ - -#include <limits> - -#include "base/basictypes.h" - -namespace cc { - -template <typename T> T RoundUp(T n, T mul) { - static_assert(std::numeric_limits<T>::is_integer, - "T must be an integer type"); - return (n > 0) ? ((n + mul - 1) / mul) * mul - : (n / mul) * mul; -} - -template <typename T> T RoundDown(T n, T mul) { - static_assert(std::numeric_limits<T>::is_integer, - "T must be an integer type"); - return (n > 0) ? (n / mul) * mul - : (n == 0) ? 0 - : ((n - mul + 1) / mul) * mul; -} - -} // namespace cc - -#endif // CC_BASE_UTIL_H_ diff --git a/chromium/cc/base/util_unittest.cc b/chromium/cc/base/util_unittest.cc deleted file mode 100644 index 6665a6a458d..00000000000 --- a/chromium/cc/base/util_unittest.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2013 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/base/util.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace cc { -namespace { - -TEST(UtilTest, RoundUp) { - for (int multiplier = 1; multiplier <= 10; ++multiplier) { - // Try attempts in descending order, so that we can - // determine the correct value before it's needed. - int correct; - for (int attempt = 5 * multiplier; attempt >= -5 * multiplier; --attempt) { - if ((attempt % multiplier) == 0) - correct = attempt; - EXPECT_EQ(correct, RoundUp(attempt, multiplier)) - << "attempt=" << attempt << " multiplier=" << multiplier; - } - } - - for (unsigned multiplier = 1; multiplier <= 10; ++multiplier) { - // Try attempts in descending order, so that we can - // determine the correct value before it's needed. - unsigned correct; - for (unsigned attempt = 5 * multiplier; attempt > 0; --attempt) { - if ((attempt % multiplier) == 0) - correct = attempt; - EXPECT_EQ(correct, RoundUp(attempt, multiplier)) - << "attempt=" << attempt << " multiplier=" << multiplier; - } - EXPECT_EQ(0u, RoundUp(0u, multiplier)) - << "attempt=0 multiplier=" << multiplier; - } -} - -TEST(UtilTest, RoundDown) { - for (int multiplier = 1; multiplier <= 10; ++multiplier) { - // Try attempts in ascending order, so that we can - // determine the correct value before it's needed. - int correct; - for (int attempt = -5 * multiplier; attempt <= 5 * multiplier; ++attempt) { - if ((attempt % multiplier) == 0) - correct = attempt; - EXPECT_EQ(correct, RoundDown(attempt, multiplier)) - << "attempt=" << attempt << " multiplier=" << multiplier; - } - } - - for (unsigned multiplier = 1; multiplier <= 10; ++multiplier) { - // Try attempts in ascending order, so that we can - // determine the correct value before it's needed. - unsigned correct; - for (unsigned attempt = 0; attempt <= 5 * multiplier; ++attempt) { - if ((attempt % multiplier) == 0) - correct = attempt; - EXPECT_EQ(correct, RoundDown(attempt, multiplier)) - << "attempt=" << attempt << " multiplier=" << multiplier; - } - } -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/blink/BUILD.gn b/chromium/cc/blink/BUILD.gn index 4854ead1ce8..c39498fe73a 100644 --- a/chromium/cc/blink/BUILD.gn +++ b/chromium/cc/blink/BUILD.gn @@ -17,6 +17,10 @@ component("blink") { "web_animation_curve_common.h", "web_animation_impl.cc", "web_animation_impl.h", + "web_compositor_animation_player_impl.cc", + "web_compositor_animation_player_impl.h", + "web_compositor_animation_timeline_impl.cc", + "web_compositor_animation_timeline_impl.h", "web_compositor_support_impl.cc", "web_compositor_support_impl.h", "web_content_layer_impl.cc", @@ -90,6 +94,7 @@ if (!is_mac) { "//base/third_party/dynamic_annotations", "//skia", "//testing/gtest", + "//third_party/WebKit/public:blink", "//ui/gfx/geometry", "//ui/gfx:test_support", "//cc", diff --git a/chromium/cc/blink/cc_blink.gyp b/chromium/cc/blink/cc_blink.gyp index e9934bf9653..c55213c5444 100644 --- a/chromium/cc/blink/cc_blink.gyp +++ b/chromium/cc/blink/cc_blink.gyp @@ -33,6 +33,10 @@ 'web_animation_curve_common.h', 'web_animation_impl.cc', 'web_animation_impl.h', + 'web_compositor_animation_player_impl.cc', + 'web_compositor_animation_player_impl.h', + 'web_compositor_animation_timeline_impl.cc', + 'web_compositor_animation_timeline_impl.h', 'web_compositor_support_impl.cc', 'web_compositor_support_impl.h', 'web_content_layer_impl.cc', diff --git a/chromium/cc/blink/web_compositor_animation_player_impl.cc b/chromium/cc/blink/web_compositor_animation_player_impl.cc new file mode 100644 index 00000000000..fd146de856f --- /dev/null +++ b/chromium/cc/blink/web_compositor_animation_player_impl.cc @@ -0,0 +1,66 @@ +// Copyright 2015 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/blink/web_compositor_animation_player_impl.h" + +#include "cc/animation/animation_id_provider.h" +#include "cc/animation/animation_player.h" +#include "cc/blink/web_animation_impl.h" +#include "cc/blink/web_to_cc_animation_delegate_adapter.h" +#include "third_party/WebKit/public/platform/WebLayer.h" + +using cc::AnimationPlayer; + +namespace cc_blink { + +WebCompositorAnimationPlayerImpl::WebCompositorAnimationPlayerImpl() + : animation_player_( + AnimationPlayer::Create(cc::AnimationIdProvider::NextPlayerId())) { +} + +WebCompositorAnimationPlayerImpl::~WebCompositorAnimationPlayerImpl() { +} + +CC_BLINK_EXPORT cc::AnimationPlayer* +WebCompositorAnimationPlayerImpl::animation_player() const { + return animation_player_.get(); +} + +void WebCompositorAnimationPlayerImpl::setAnimationDelegate( + blink::WebCompositorAnimationDelegate* delegate) { + animation_delegate_adapter_.reset( + new WebToCCAnimationDelegateAdapter(delegate)); + animation_player_->set_layer_animation_delegate( + animation_delegate_adapter_.get()); +} + +void WebCompositorAnimationPlayerImpl::attachLayer(blink::WebLayer* web_layer) { + animation_player_->AttachLayer(web_layer->id()); +} + +void WebCompositorAnimationPlayerImpl::detachLayer() { + animation_player_->DetachLayer(); +} + +bool WebCompositorAnimationPlayerImpl::isLayerAttached() const { + return animation_player_->layer_id() != 0; +} + +void WebCompositorAnimationPlayerImpl::addAnimation( + blink::WebCompositorAnimation* animation) { + animation_player_->AddAnimation( + static_cast<WebCompositorAnimationImpl*>(animation)->PassAnimation()); + delete animation; +} + +void WebCompositorAnimationPlayerImpl::removeAnimation(int animation_id) { + animation_player_->RemoveAnimation(animation_id); +} + +void WebCompositorAnimationPlayerImpl::pauseAnimation(int animation_id, + double time_offset) { + animation_player_->PauseAnimation(animation_id, time_offset); +} + +} // namespace cc_blink diff --git a/chromium/cc/blink/web_compositor_animation_player_impl.h b/chromium/cc/blink/web_compositor_animation_player_impl.h new file mode 100644 index 00000000000..9b5ea4475e7 --- /dev/null +++ b/chromium/cc/blink/web_compositor_animation_player_impl.h @@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_BLINK_WEB_COMPOSITOR_ANIMATION_PLAYER_IMPL_H_ +#define CC_BLINK_WEB_COMPOSITOR_ANIMATION_PLAYER_IMPL_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "cc/blink/cc_blink_export.h" +#include "third_party/WebKit/public/platform/WebCompositorAnimationPlayer.h" + +namespace cc { +class AnimationPlayer; +} + +namespace cc_blink { + +class WebToCCAnimationDelegateAdapter; + +class WebCompositorAnimationPlayerImpl + : public blink::WebCompositorAnimationPlayer { + public: + CC_BLINK_EXPORT WebCompositorAnimationPlayerImpl(); + virtual ~WebCompositorAnimationPlayerImpl(); + + CC_BLINK_EXPORT cc::AnimationPlayer* animation_player() const; + + // blink::WebCompositorAnimationPlayer implementation + virtual void setAnimationDelegate( + blink::WebCompositorAnimationDelegate* delegate); + virtual void attachLayer(blink::WebLayer* web_layer); + virtual void detachLayer(); + virtual bool isLayerAttached() const; + virtual void addAnimation(blink::WebCompositorAnimation* animation); + virtual void removeAnimation(int animation_id); + virtual void pauseAnimation(int animation_id, double time_offset); + + private: + scoped_refptr<cc::AnimationPlayer> animation_player_; + scoped_ptr<WebToCCAnimationDelegateAdapter> animation_delegate_adapter_; + + DISALLOW_COPY_AND_ASSIGN(WebCompositorAnimationPlayerImpl); +}; + +} // namespace cc_blink + +#endif // CC_BLINK_WEB_COMPOSITOR_ANIMATION_PLAYER_IMPL_H_ diff --git a/chromium/cc/blink/web_compositor_animation_timeline_impl.cc b/chromium/cc/blink/web_compositor_animation_timeline_impl.cc new file mode 100644 index 00000000000..a87778331bb --- /dev/null +++ b/chromium/cc/blink/web_compositor_animation_timeline_impl.cc @@ -0,0 +1,46 @@ +// Copyright 2015 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/blink/web_compositor_animation_timeline_impl.h" + +#include "cc/animation/animation_id_provider.h" +#include "cc/animation/animation_player.h" +#include "cc/animation/animation_timeline.h" +#include "cc/blink/web_compositor_animation_player_impl.h" +#include "third_party/WebKit/public/platform/WebCompositorAnimationPlayerClient.h" + +using cc::AnimationTimeline; + +namespace cc_blink { + +WebCompositorAnimationTimelineImpl::WebCompositorAnimationTimelineImpl() + : animation_timeline_(AnimationTimeline::Create( + cc::AnimationIdProvider::NextTimelineId())) { +} + +WebCompositorAnimationTimelineImpl::~WebCompositorAnimationTimelineImpl() { +} + +cc::AnimationTimeline* WebCompositorAnimationTimelineImpl::animation_timeline() + const { + return animation_timeline_.get(); +} + +void WebCompositorAnimationTimelineImpl::playerAttached( + const blink::WebCompositorAnimationPlayerClient& client) { + if (client.compositorPlayer()) + animation_timeline_->AttachPlayer( + static_cast<WebCompositorAnimationPlayerImpl*>( + client.compositorPlayer())->animation_player()); +} + +void WebCompositorAnimationTimelineImpl::playerDestroyed( + const blink::WebCompositorAnimationPlayerClient& client) { + if (client.compositorPlayer()) + animation_timeline_->DetachPlayer( + static_cast<WebCompositorAnimationPlayerImpl*>( + client.compositorPlayer())->animation_player()); +} + +} // namespace cc_blink diff --git a/chromium/cc/blink/web_compositor_animation_timeline_impl.h b/chromium/cc/blink/web_compositor_animation_timeline_impl.h new file mode 100644 index 00000000000..65d05d83157 --- /dev/null +++ b/chromium/cc/blink/web_compositor_animation_timeline_impl.h @@ -0,0 +1,45 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_BLINK_WEB_COMPOSITOR_ANIMATION_TIMELINE_IMPL_H_ +#define CC_BLINK_WEB_COMPOSITOR_ANIMATION_TIMELINE_IMPL_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "cc/blink/cc_blink_export.h" +#include "third_party/WebKit/public/platform/WebCompositorAnimationTimeline.h" + +namespace blink { +class WebCompositorAnimationPlayerClient; +} + +namespace cc { +class AnimationTimeline; +} + +namespace cc_blink { + +class WebCompositorAnimationTimelineImpl + : public blink::WebCompositorAnimationTimeline { + public: + CC_BLINK_EXPORT explicit WebCompositorAnimationTimelineImpl(); + virtual ~WebCompositorAnimationTimelineImpl(); + + CC_BLINK_EXPORT cc::AnimationTimeline* animation_timeline() const; + + // blink::WebCompositorAnimationTimeline implementation + virtual void playerAttached( + const blink::WebCompositorAnimationPlayerClient& client); + virtual void playerDestroyed( + const blink::WebCompositorAnimationPlayerClient& client); + + private: + scoped_refptr<cc::AnimationTimeline> animation_timeline_; + + DISALLOW_COPY_AND_ASSIGN(WebCompositorAnimationTimelineImpl); +}; + +} // namespace cc_blink + +#endif // CC_BLINK_WEB_COMPOSITOR_ANIMATION_TIMELINE_IMPL_H_ diff --git a/chromium/cc/blink/web_compositor_support_impl.cc b/chromium/cc/blink/web_compositor_support_impl.cc index e69abf69239..13a868d7ebf 100644 --- a/chromium/cc/blink/web_compositor_support_impl.cc +++ b/chromium/cc/blink/web_compositor_support_impl.cc @@ -5,9 +5,10 @@ #include "cc/blink/web_compositor_support_impl.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop_proxy.h" #include "cc/animation/transform_operations.h" #include "cc/blink/web_animation_impl.h" +#include "cc/blink/web_compositor_animation_player_impl.h" +#include "cc/blink/web_compositor_animation_timeline_impl.h" #include "cc/blink/web_content_layer_impl.h" #include "cc/blink/web_display_item_list_impl.h" #include "cc/blink/web_external_texture_layer_impl.h" @@ -26,6 +27,8 @@ using blink::WebCompositorAnimation; using blink::WebCompositorAnimationCurve; +using blink::WebCompositorAnimationPlayer; +using blink::WebCompositorAnimationTimeline; using blink::WebContentLayer; using blink::WebContentLayerClient; using blink::WebDisplayItemList; @@ -96,15 +99,9 @@ WebScrollbarLayer* WebCompositorSupportImpl::createSolidColorScrollbarLayer( WebCompositorAnimation* WebCompositorSupportImpl::createAnimation( const blink::WebCompositorAnimationCurve& curve, blink::WebCompositorAnimation::TargetProperty target, -#ifdef WEB_COMPOSITOR_SUPPORT_CREATE_ANIMATION_SUPPORTS_GROUP int group_id, -#endif int animation_id) { -#ifdef WEB_COMPOSITOR_SUPPORT_CREATE_ANIMATION_SUPPORTS_GROUP return new WebCompositorAnimationImpl(curve, target, animation_id, group_id); -#else - return new WebCompositorAnimationImpl(curve, target, animation_id, 0); -#endif } WebFilterAnimationCurve* @@ -136,4 +133,18 @@ WebFilterOperations* WebCompositorSupportImpl::createFilterOperations() { return new WebFilterOperationsImpl(); } +WebDisplayItemList* WebCompositorSupportImpl::createDisplayItemList() { + return new WebDisplayItemListImpl(); +} + +WebCompositorAnimationPlayer* +WebCompositorSupportImpl::createAnimationPlayer() { + return new WebCompositorAnimationPlayerImpl(); +} + +WebCompositorAnimationTimeline* +WebCompositorSupportImpl::createAnimationTimeline() { + return new WebCompositorAnimationTimelineImpl(); +} + } // namespace cc_blink diff --git a/chromium/cc/blink/web_compositor_support_impl.h b/chromium/cc/blink/web_compositor_support_impl.h index b924be9cc09..989966989e6 100644 --- a/chromium/cc/blink/web_compositor_support_impl.h +++ b/chromium/cc/blink/web_compositor_support_impl.h @@ -6,7 +6,6 @@ #define CC_BLINK_WEB_COMPOSITOR_SUPPORT_IMPL_H_ #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop_proxy.h" #include "cc/blink/cc_blink_export.h" #include "third_party/WebKit/public/platform/WebCompositorAnimationCurve.h" #include "third_party/WebKit/public/platform/WebCompositorSupport.h" @@ -45,9 +44,7 @@ class CC_BLINK_EXPORT WebCompositorSupportImpl virtual blink::WebCompositorAnimation* createAnimation( const blink::WebCompositorAnimationCurve& curve, blink::WebCompositorAnimation::TargetProperty target, -#ifdef WEB_COMPOSITOR_SUPPORT_CREATE_ANIMATION_SUPPORTS_GROUP int group_id, -#endif int animation_id); virtual blink::WebFilterAnimationCurve* createFilterAnimationCurve(); virtual blink::WebFloatAnimationCurve* createFloatAnimationCurve(); @@ -59,6 +56,10 @@ class CC_BLINK_EXPORT WebCompositorSupportImpl virtual blink::WebTransformAnimationCurve* createTransformAnimationCurve(); virtual blink::WebTransformOperations* createTransformOperations(); virtual blink::WebFilterOperations* createFilterOperations(); + virtual blink::WebDisplayItemList* createDisplayItemList(); + + virtual blink::WebCompositorAnimationPlayer* createAnimationPlayer(); + virtual blink::WebCompositorAnimationTimeline* createAnimationTimeline(); private: DISALLOW_COPY_AND_ASSIGN(WebCompositorSupportImpl); diff --git a/chromium/cc/blink/web_content_layer_impl.cc b/chromium/cc/blink/web_content_layer_impl.cc index a480a06614c..c9ca473cf8e 100644 --- a/chromium/cc/blink/web_content_layer_impl.cc +++ b/chromium/cc/blink/web_content_layer_impl.cc @@ -5,8 +5,8 @@ #include "cc/blink/web_content_layer_impl.h" #include "cc/blink/web_display_item_list_impl.h" -#include "cc/layers/content_layer.h" #include "cc/layers/picture_layer.h" +#include "cc/playback/display_item_list_settings.h" #include "third_party/WebKit/public/platform/WebContentLayerClient.h" #include "third_party/WebKit/public/platform/WebFloatPoint.h" #include "third_party/WebKit/public/platform/WebFloatRect.h" @@ -14,7 +14,6 @@ #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/skia/include/utils/SkMatrix44.h" -using cc::ContentLayer; using cc::PictureLayer; namespace cc_blink { @@ -38,18 +37,13 @@ PaintingControlToWeb( WebContentLayerImpl::WebContentLayerImpl(blink::WebContentLayerClient* client) : client_(client) { - if (WebLayerImpl::UsingPictureLayer()) - layer_ = make_scoped_ptr(new WebLayerImpl(PictureLayer::Create(this))); - else - layer_ = make_scoped_ptr(new WebLayerImpl(ContentLayer::Create(this))); + layer_ = make_scoped_ptr(new WebLayerImpl( + PictureLayer::Create(WebLayerImpl::LayerSettings(), this))); layer_->layer()->SetIsDrawable(true); } WebContentLayerImpl::~WebContentLayerImpl() { - if (WebLayerImpl::UsingPictureLayer()) - static_cast<PictureLayer*>(layer_->layer())->ClearClient(); - else - static_cast<ContentLayer*>(layer_->layer())->ClearClient(); + static_cast<PictureLayer*>(layer_->layer())->ClearClient(); } blink::WebLayer* WebContentLayerImpl::layer() { @@ -74,15 +68,21 @@ void WebContentLayerImpl::PaintContents( client_->paintContents(canvas, clip, PaintingControlToWeb(painting_control)); } -void WebContentLayerImpl::PaintContentsToDisplayList( - cc::DisplayItemList* display_list, +scoped_refptr<cc::DisplayItemList> +WebContentLayerImpl::PaintContentsToDisplayList( const gfx::Rect& clip, cc::ContentLayerClient::PaintingControlSetting painting_control) { - if (!client_) - return; - - WebDisplayItemListImpl list(display_list); - client_->paintContents(&list, clip, PaintingControlToWeb(painting_control)); + cc::DisplayItemListSettings settings; + settings.use_cached_picture = true; + + scoped_refptr<cc::DisplayItemList> display_list = + cc::DisplayItemList::Create(clip, settings); + if (client_) { + WebDisplayItemListImpl list(display_list.get()); + client_->paintContents(&list, clip, PaintingControlToWeb(painting_control)); + } + display_list->Finalize(); + return display_list; } bool WebContentLayerImpl::FillsBoundsCompletely() const { diff --git a/chromium/cc/blink/web_content_layer_impl.h b/chromium/cc/blink/web_content_layer_impl.h index e7b04b02abc..3e7b55c59a4 100644 --- a/chromium/cc/blink/web_content_layer_impl.h +++ b/chromium/cc/blink/web_content_layer_impl.h @@ -39,8 +39,7 @@ class WebContentLayerImpl : public blink::WebContentLayer, void PaintContents(SkCanvas* canvas, const gfx::Rect& clip, PaintingControlSetting painting_control) override; - void PaintContentsToDisplayList( - cc::DisplayItemList* display_list, + scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting painting_control) override; bool FillsBoundsCompletely() const override; diff --git a/chromium/cc/blink/web_display_item_list_impl.cc b/chromium/cc/blink/web_display_item_list_impl.cc index 3782358da33..ffcd5e35df7 100644 --- a/chromium/cc/blink/web_display_item_list_impl.cc +++ b/chromium/cc/blink/web_display_item_list_impl.cc @@ -10,6 +10,7 @@ #include "cc/playback/clip_display_item.h" #include "cc/playback/clip_path_display_item.h" #include "cc/playback/compositing_display_item.h" +#include "cc/playback/display_item_list_settings.h" #include "cc/playback/drawing_display_item.h" #include "cc/playback/filter_display_item.h" #include "cc/playback/float_clip_display_item.h" @@ -25,15 +26,35 @@ namespace cc_blink { +namespace { + +scoped_refptr<cc::DisplayItemList> CreateUncachedDisplayItemListForBlink() { + cc::DisplayItemListSettings settings; + settings.use_cached_picture = false; + return cc::DisplayItemList::CreateWithoutCachedPicture(settings); +} + +} // namespace + +WebDisplayItemListImpl::WebDisplayItemListImpl() + : display_item_list_(CreateUncachedDisplayItemListForBlink()) { +} + WebDisplayItemListImpl::WebDisplayItemListImpl( cc::DisplayItemList* display_list) : display_item_list_(display_list) { } void WebDisplayItemListImpl::appendDrawingItem(const SkPicture* picture) { - auto* item = - display_item_list_->CreateAndAppendItem<cc::DrawingDisplayItem>(); - item->SetNew(skia::SharePtr(const_cast<SkPicture*>(picture))); + if (display_item_list_->RetainsIndividualDisplayItems()) { + auto* item = + display_item_list_->CreateAndAppendItem<cc::DrawingDisplayItem>(); + item->SetNew(skia::SharePtr(const_cast<SkPicture*>(picture))); + } else { + cc::DrawingDisplayItem item; + item.SetNew(skia::SharePtr(const_cast<SkPicture*>(picture))); + display_item_list_->RasterIntoCanvas(item); + } } void WebDisplayItemListImpl::appendClipItem( @@ -43,47 +64,88 @@ void WebDisplayItemListImpl::appendClipItem( for (size_t i = 0; i < rounded_clip_rects.size(); ++i) { rounded_rects.push_back(rounded_clip_rects[i]); } - auto* item = display_item_list_->CreateAndAppendItem<cc::ClipDisplayItem>(); - item->SetNew(clip_rect, rounded_rects); + if (display_item_list_->RetainsIndividualDisplayItems()) { + auto* item = display_item_list_->CreateAndAppendItem<cc::ClipDisplayItem>(); + item->SetNew(clip_rect, rounded_rects); + } else { + cc::ClipDisplayItem item; + item.SetNew(clip_rect, rounded_rects); + display_item_list_->RasterIntoCanvas(item); + } } void WebDisplayItemListImpl::appendEndClipItem() { - display_item_list_->CreateAndAppendItem<cc::EndClipDisplayItem>(); + if (display_item_list_->RetainsIndividualDisplayItems()) { + display_item_list_->CreateAndAppendItem<cc::EndClipDisplayItem>(); + } else { + display_item_list_->RasterIntoCanvas(cc::EndClipDisplayItem()); + } } void WebDisplayItemListImpl::appendClipPathItem(const SkPath& clip_path, SkRegion::Op clip_op, bool antialias) { - auto* item = - display_item_list_->CreateAndAppendItem<cc::ClipPathDisplayItem>(); - item->SetNew(clip_path, clip_op, antialias); + if (display_item_list_->RetainsIndividualDisplayItems()) { + auto* item = + display_item_list_->CreateAndAppendItem<cc::ClipPathDisplayItem>(); + item->SetNew(clip_path, clip_op, antialias); + } else { + cc::ClipPathDisplayItem item; + item.SetNew(clip_path, clip_op, antialias); + display_item_list_->RasterIntoCanvas(item); + } } void WebDisplayItemListImpl::appendEndClipPathItem() { - display_item_list_->CreateAndAppendItem<cc::EndClipPathDisplayItem>(); + if (display_item_list_->RetainsIndividualDisplayItems()) { + display_item_list_->CreateAndAppendItem<cc::EndClipPathDisplayItem>(); + } else { + display_item_list_->RasterIntoCanvas(cc::EndClipPathDisplayItem()); + } } void WebDisplayItemListImpl::appendFloatClipItem( const blink::WebFloatRect& clip_rect) { - auto* item = - display_item_list_->CreateAndAppendItem<cc::FloatClipDisplayItem>(); - item->SetNew(clip_rect); + if (display_item_list_->RetainsIndividualDisplayItems()) { + auto* item = + display_item_list_->CreateAndAppendItem<cc::FloatClipDisplayItem>(); + item->SetNew(clip_rect); + } else { + cc::FloatClipDisplayItem item; + item.SetNew(clip_rect); + display_item_list_->RasterIntoCanvas(item); + } } void WebDisplayItemListImpl::appendEndFloatClipItem() { - display_item_list_->CreateAndAppendItem<cc::EndFloatClipDisplayItem>(); + if (display_item_list_->RetainsIndividualDisplayItems()) { + display_item_list_->CreateAndAppendItem<cc::EndFloatClipDisplayItem>(); + } else { + display_item_list_->RasterIntoCanvas(cc::EndFloatClipDisplayItem()); + } } void WebDisplayItemListImpl::appendTransformItem(const SkMatrix44& matrix) { gfx::Transform transform; transform.matrix() = matrix; - auto* item = - display_item_list_->CreateAndAppendItem<cc::TransformDisplayItem>(); - item->SetNew(transform); + + if (display_item_list_->RetainsIndividualDisplayItems()) { + auto* item = + display_item_list_->CreateAndAppendItem<cc::TransformDisplayItem>(); + item->SetNew(transform); + } else { + cc::TransformDisplayItem item; + item.SetNew(transform); + display_item_list_->RasterIntoCanvas(item); + } } void WebDisplayItemListImpl::appendEndTransformItem() { - display_item_list_->CreateAndAppendItem<cc::EndTransformDisplayItem>(); + if (display_item_list_->RetainsIndividualDisplayItems()) { + display_item_list_->CreateAndAppendItem<cc::EndTransformDisplayItem>(); + } else { + display_item_list_->RasterIntoCanvas(cc::EndTransformDisplayItem()); + } } void WebDisplayItemListImpl::appendCompositingItem( @@ -95,14 +157,26 @@ void WebDisplayItemListImpl::appendCompositingItem( DCHECK_LE(opacity, 1.f); // TODO(ajuma): This should really be rounding instead of flooring the alpha // value, but that breaks slimming paint reftests. - auto* item = - display_item_list_->CreateAndAppendItem<cc::CompositingDisplayItem>(); - item->SetNew(static_cast<uint8_t>(gfx::ToFlooredInt(255 * opacity)), xfermode, - bounds, skia::SharePtr(color_filter)); + + if (display_item_list_->RetainsIndividualDisplayItems()) { + auto* item = + display_item_list_->CreateAndAppendItem<cc::CompositingDisplayItem>(); + item->SetNew(static_cast<uint8_t>(gfx::ToFlooredInt(255 * opacity)), + xfermode, bounds, skia::SharePtr(color_filter)); + } else { + cc::CompositingDisplayItem item; + item.SetNew(static_cast<uint8_t>(gfx::ToFlooredInt(255 * opacity)), + xfermode, bounds, skia::SharePtr(color_filter)); + display_item_list_->RasterIntoCanvas(item); + } } void WebDisplayItemListImpl::appendEndCompositingItem() { - display_item_list_->CreateAndAppendItem<cc::EndCompositingDisplayItem>(); + if (display_item_list_->RetainsIndividualDisplayItems()) { + display_item_list_->CreateAndAppendItem<cc::EndCompositingDisplayItem>(); + } else { + display_item_list_->RasterIntoCanvas(cc::EndCompositingDisplayItem()); + } } void WebDisplayItemListImpl::appendFilterItem( @@ -110,12 +184,24 @@ void WebDisplayItemListImpl::appendFilterItem( const blink::WebFloatRect& bounds) { const WebFilterOperationsImpl& filters_impl = static_cast<const WebFilterOperationsImpl&>(filters); - auto* item = display_item_list_->CreateAndAppendItem<cc::FilterDisplayItem>(); - item->SetNew(filters_impl.AsFilterOperations(), bounds); + + if (display_item_list_->RetainsIndividualDisplayItems()) { + auto* item = + display_item_list_->CreateAndAppendItem<cc::FilterDisplayItem>(); + item->SetNew(filters_impl.AsFilterOperations(), bounds); + } else { + cc::FilterDisplayItem item; + item.SetNew(filters_impl.AsFilterOperations(), bounds); + display_item_list_->RasterIntoCanvas(item); + } } void WebDisplayItemListImpl::appendEndFilterItem() { - display_item_list_->CreateAndAppendItem<cc::EndFilterDisplayItem>(); + if (display_item_list_->RetainsIndividualDisplayItems()) { + display_item_list_->CreateAndAppendItem<cc::EndFilterDisplayItem>(); + } else { + display_item_list_->RasterIntoCanvas(cc::EndFilterDisplayItem()); + } } void WebDisplayItemListImpl::appendScrollItem( diff --git a/chromium/cc/blink/web_display_item_list_impl.h b/chromium/cc/blink/web_display_item_list_impl.h index 6b5d147b5d1..d45d7d36d48 100644 --- a/chromium/cc/blink/web_display_item_list_impl.h +++ b/chromium/cc/blink/web_display_item_list_impl.h @@ -27,11 +27,17 @@ struct WebFloatRect; struct WebRect; } +namespace cc { +class DisplayItemListSettings; +} + namespace cc_blink { class WebDisplayItemListImpl : public blink::WebDisplayItemList { public: - CC_BLINK_EXPORT WebDisplayItemListImpl(cc::DisplayItemList* display_list); + CC_BLINK_EXPORT WebDisplayItemListImpl(); + CC_BLINK_EXPORT explicit WebDisplayItemListImpl( + cc::DisplayItemList* display_list); virtual ~WebDisplayItemListImpl(); // blink::WebDisplayItemList implementation. @@ -61,7 +67,7 @@ class WebDisplayItemListImpl : public blink::WebDisplayItemList { virtual void appendEndScrollItem(); private: - cc::DisplayItemList* display_item_list_; + scoped_refptr<cc::DisplayItemList> display_item_list_; DISALLOW_COPY_AND_ASSIGN(WebDisplayItemListImpl); }; diff --git a/chromium/cc/blink/web_external_texture_layer_impl.cc b/chromium/cc/blink/web_external_texture_layer_impl.cc index 8d29aa172dd..e9700c6c6d9 100644 --- a/chromium/cc/blink/web_external_texture_layer_impl.cc +++ b/chromium/cc/blink/web_external_texture_layer_impl.cc @@ -7,7 +7,6 @@ #include "cc/blink/web_external_bitmap_impl.h" #include "cc/blink/web_layer_impl.h" #include "cc/layers/texture_layer.h" -#include "cc/resources/resource_update_queue.h" #include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "third_party/WebKit/public/platform/WebExternalTextureLayerClient.h" @@ -18,7 +17,6 @@ #include "third_party/khronos/GLES2/gl2.h" using cc::TextureLayer; -using cc::ResourceUpdateQueue; namespace cc_blink { @@ -26,7 +24,8 @@ WebExternalTextureLayerImpl::WebExternalTextureLayerImpl( blink::WebExternalTextureLayerClient* client) : client_(client) { cc::TextureLayerClient* cc_client = client_ ? this : nullptr; - scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(cc_client); + scoped_refptr<TextureLayer> layer = + TextureLayer::CreateForMailbox(WebLayerImpl::LayerSettings(), cc_client); layer->SetIsDrawable(true); layer_.reset(new WebLayerImpl(layer)); } @@ -86,10 +85,10 @@ bool WebExternalTextureLayerImpl::PrepareTextureMailbox( if (bitmap) { *mailbox = cc::TextureMailbox(bitmap->shared_bitmap(), bitmap->size()); } else { - *mailbox = - cc::TextureMailbox(name, GL_TEXTURE_2D, client_mailbox.syncPoint); + // TODO(achaulk): pass a valid size here if allowOverlay is set. + *mailbox = cc::TextureMailbox(name, GL_TEXTURE_2D, client_mailbox.syncPoint, + gfx::Size(), client_mailbox.allowOverlay); } - mailbox->set_allow_overlay(client_mailbox.allowOverlay); mailbox->set_nearest_neighbor(client_mailbox.nearestNeighbor); if (mailbox->IsValid()) { diff --git a/chromium/cc/blink/web_filter_operations_impl.cc b/chromium/cc/blink/web_filter_operations_impl.cc index acabe0f7a15..e896c6adede 100644 --- a/chromium/cc/blink/web_filter_operations_impl.cc +++ b/chromium/cc/blink/web_filter_operations_impl.cc @@ -92,4 +92,8 @@ void WebFilterOperationsImpl::clear() { filter_operations_.Clear(); } +bool WebFilterOperationsImpl::isEmpty() const { + return filter_operations_.IsEmpty(); +} + } // namespace cc_blink diff --git a/chromium/cc/blink/web_filter_operations_impl.h b/chromium/cc/blink/web_filter_operations_impl.h index 7a9dcf33c88..36c3b4565cf 100644 --- a/chromium/cc/blink/web_filter_operations_impl.h +++ b/chromium/cc/blink/web_filter_operations_impl.h @@ -37,6 +37,7 @@ class WebFilterOperationsImpl : public blink::WebFilterOperations { virtual void appendReferenceFilter(SkImageFilter* image_filter); virtual void clear(); + virtual bool isEmpty() const; private: cc::FilterOperations filter_operations_; diff --git a/chromium/cc/blink/web_image_layer_impl.cc b/chromium/cc/blink/web_image_layer_impl.cc index afd551a3102..55e28ef8152 100644 --- a/chromium/cc/blink/web_image_layer_impl.cc +++ b/chromium/cc/blink/web_image_layer_impl.cc @@ -6,16 +6,13 @@ #include "cc/blink/web_layer_impl.h" #include "cc/blink/web_layer_impl_fixed_bounds.h" -#include "cc/layers/image_layer.h" #include "cc/layers/picture_image_layer.h" namespace cc_blink { WebImageLayerImpl::WebImageLayerImpl() { - if (WebLayerImpl::UsingPictureLayer()) - layer_.reset(new WebLayerImplFixedBounds(cc::PictureImageLayer::Create())); - else - layer_.reset(new WebLayerImpl(cc::ImageLayer::Create())); + layer_.reset(new WebLayerImplFixedBounds( + cc::PictureImageLayer::Create(WebLayerImpl::LayerSettings()))); } WebImageLayerImpl::~WebImageLayerImpl() { @@ -26,20 +23,14 @@ blink::WebLayer* WebImageLayerImpl::layer() { } void WebImageLayerImpl::setImageBitmap(const SkBitmap& bitmap) { - if (WebLayerImpl::UsingPictureLayer()) { - static_cast<cc::PictureImageLayer*>(layer_->layer())->SetBitmap(bitmap); - static_cast<WebLayerImplFixedBounds*>(layer_.get()) - ->SetFixedBounds(gfx::Size(bitmap.width(), bitmap.height())); - } else { - static_cast<cc::ImageLayer*>(layer_->layer())->SetBitmap(bitmap); - } + static_cast<cc::PictureImageLayer*>(layer_->layer())->SetBitmap(bitmap); + static_cast<WebLayerImplFixedBounds*>(layer_.get()) + ->SetFixedBounds(gfx::Size(bitmap.width(), bitmap.height())); } void WebImageLayerImpl::setNearestNeighbor(bool nearest_neighbor) { - if (WebLayerImpl::UsingPictureLayer()) { - static_cast<cc::PictureImageLayer*>(layer_->layer()) - ->SetNearestNeighbor(nearest_neighbor); - } + static_cast<cc::PictureImageLayer*>(layer_->layer()) + ->SetNearestNeighbor(nearest_neighbor); } } // namespace cc_blink diff --git a/chromium/cc/blink/web_layer_impl.cc b/chromium/cc/blink/web_layer_impl.cc index 8bad92a002e..3ba9431171d 100644 --- a/chromium/cc/blink/web_layer_impl.cc +++ b/chromium/cc/blink/web_layer_impl.cc @@ -46,11 +46,12 @@ using blink::WebFilterOperations; namespace cc_blink { namespace { -bool g_impl_side_painting_enabled = false; +base::LazyInstance<cc::LayerSettings> g_layer_settings = + LAZY_INSTANCE_INITIALIZER; } // namespace -WebLayerImpl::WebLayerImpl() : layer_(Layer::Create()) { +WebLayerImpl::WebLayerImpl() : layer_(Layer::Create(LayerSettings())) { web_layer_client_ = nullptr; layer_->SetLayerClient(this); } @@ -62,18 +63,19 @@ WebLayerImpl::WebLayerImpl(scoped_refptr<Layer> layer) : layer_(layer) { WebLayerImpl::~WebLayerImpl() { layer_->ClearRenderSurface(); - layer_->set_layer_animation_delegate(nullptr); + if (animation_delegate_adapter_.get()) + layer_->set_layer_animation_delegate(nullptr); web_layer_client_ = nullptr; } // static -bool WebLayerImpl::UsingPictureLayer() { - return g_impl_side_painting_enabled; +void WebLayerImpl::SetLayerSettings(const cc::LayerSettings& settings) { + g_layer_settings.Get() = settings; } // static -void WebLayerImpl::SetImplSidePaintingEnabled(bool enabled) { - g_impl_side_painting_enabled = enabled; +const cc::LayerSettings& WebLayerImpl::LayerSettings() { + return g_layer_settings.Get(); } int WebLayerImpl::id() const { diff --git a/chromium/cc/blink/web_layer_impl.h b/chromium/cc/blink/web_layer_impl.h index beaf3b51679..eb049b8e711 100644 --- a/chromium/cc/blink/web_layer_impl.h +++ b/chromium/cc/blink/web_layer_impl.h @@ -39,6 +39,7 @@ class ConvertableToTraceFormat; namespace cc { class Layer; +class LayerSettings; } namespace cc_blink { @@ -51,8 +52,9 @@ class WebLayerImpl : public blink::WebLayer, public cc::LayerClient { CC_BLINK_EXPORT explicit WebLayerImpl(scoped_refptr<cc::Layer>); virtual ~WebLayerImpl(); - static bool UsingPictureLayer(); - CC_BLINK_EXPORT static void SetImplSidePaintingEnabled(bool enabled); + CC_BLINK_EXPORT static void SetLayerSettings( + const cc::LayerSettings& settings); + CC_BLINK_EXPORT static const cc::LayerSettings& LayerSettings(); CC_BLINK_EXPORT cc::Layer* layer() const; diff --git a/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc b/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc index c9fd4fad6dc..26f445ae072 100644 --- a/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc +++ b/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc @@ -7,6 +7,7 @@ #include "cc/layers/picture_image_layer.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/geometry_test_utils.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host_common.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebFloatPoint.h" @@ -67,10 +68,10 @@ TEST(WebLayerImplFixedBoundsTest, BoundsScaleSimple) { } void ExpectEqualLayerRectsInTarget(cc::Layer* layer1, cc::Layer* layer2) { - gfx::RectF layer1_rect_in_target(layer1->content_bounds()); + gfx::RectF layer1_rect_in_target(layer1->bounds()); layer1->draw_transform().TransformRect(&layer1_rect_in_target); - gfx::RectF layer2_rect_in_target(layer2->content_bounds()); + gfx::RectF layer2_rect_in_target(layer2->bounds()); layer2->draw_transform().TransformRect(&layer2_rect_in_target); EXPECT_FLOAT_RECT_EQ(layer1_rect_in_target, layer2_rect_in_target); @@ -88,15 +89,16 @@ void CompareFixedBoundsLayerAndNormalLayer(const WebFloatPoint& anchor_point, scoped_ptr<WebLayerImplFixedBounds> root_layer(new WebLayerImplFixedBounds()); - WebLayerImplFixedBounds* fixed_bounds_layer = - new WebLayerImplFixedBounds(cc::PictureImageLayer::Create()); + WebLayerImplFixedBounds* fixed_bounds_layer = new WebLayerImplFixedBounds( + cc::PictureImageLayer::Create(WebLayerImpl::LayerSettings())); fixed_bounds_layer->setBounds(bounds); fixed_bounds_layer->SetFixedBounds(fixed_bounds); fixed_bounds_layer->setTransform(transform.matrix()); fixed_bounds_layer->setPosition(position); root_layer->addChild(fixed_bounds_layer); - WebLayerImpl* normal_layer(new WebLayerImpl(cc::PictureImageLayer::Create())); + WebLayerImpl* normal_layer( + new WebLayerImpl(cc::PictureImageLayer::Create(cc::LayerSettings()))); normal_layer->setBounds(bounds); normal_layer->setTransform(transform.matrix()); @@ -104,8 +106,9 @@ void CompareFixedBoundsLayerAndNormalLayer(const WebFloatPoint& anchor_point, root_layer->addChild(normal_layer); cc::FakeLayerTreeHostClient client(cc::FakeLayerTreeHostClient::DIRECT_3D); + cc::TestTaskGraphRunner task_graph_runner; scoped_ptr<cc::FakeLayerTreeHost> host = - cc::FakeLayerTreeHost::Create(&client); + cc::FakeLayerTreeHost::Create(&client, &task_graph_runner); host->SetRootLayer(root_layer->layer()); { @@ -114,7 +117,7 @@ void CompareFixedBoundsLayerAndNormalLayer(const WebFloatPoint& anchor_point, root_layer->layer(), kDeviceViewportSize, &render_surface_layer_list); inputs.device_scale_factor = kDeviceScaleFactor; inputs.page_scale_factor = kPageScaleFactor; - inputs.page_scale_application_layer = root_layer->layer(), + inputs.page_scale_layer = root_layer->layer(), cc::LayerTreeHostCommon::CalculateDrawProperties(&inputs); ExpectEqualLayerRectsInTarget(normal_layer->layer(), @@ -131,7 +134,7 @@ void CompareFixedBoundsLayerAndNormalLayer(const WebFloatPoint& anchor_point, root_layer->layer(), kDeviceViewportSize, &render_surface_layer_list); inputs.device_scale_factor = kDeviceScaleFactor; inputs.page_scale_factor = kPageScaleFactor; - inputs.page_scale_application_layer = root_layer->layer(), + inputs.page_scale_layer = root_layer->layer(), cc::LayerTreeHostCommon::CalculateDrawProperties(&inputs); ExpectEqualLayerRectsInTarget(normal_layer->layer(), diff --git a/chromium/cc/blink/web_nine_patch_layer_impl.cc b/chromium/cc/blink/web_nine_patch_layer_impl.cc index 094349182fa..8dd9980f331 100644 --- a/chromium/cc/blink/web_nine_patch_layer_impl.cc +++ b/chromium/cc/blink/web_nine_patch_layer_impl.cc @@ -14,7 +14,8 @@ namespace cc_blink { WebNinePatchLayerImpl::WebNinePatchLayerImpl() { - layer_.reset(new WebLayerImpl(cc::NinePatchLayer::Create())); + layer_.reset(new WebLayerImpl( + cc::NinePatchLayer::Create(WebLayerImpl::LayerSettings()))); } WebNinePatchLayerImpl::~WebNinePatchLayerImpl() { diff --git a/chromium/cc/blink/web_scrollbar_layer_impl.cc b/chromium/cc/blink/web_scrollbar_layer_impl.cc index c94f2c5a9cc..a6813cb98e2 100644 --- a/chromium/cc/blink/web_scrollbar_layer_impl.cc +++ b/chromium/cc/blink/web_scrollbar_layer_impl.cc @@ -31,6 +31,7 @@ WebScrollbarLayerImpl::WebScrollbarLayerImpl( blink::WebScrollbarThemePainter painter, blink::WebScrollbarThemeGeometry* geometry) : layer_(new WebLayerImpl(PaintedScrollbarLayer::Create( + WebLayerImpl::LayerSettings(), scoped_ptr<cc::Scrollbar>( new ScrollbarImpl(make_scoped_ptr(scrollbar), painter, @@ -44,7 +45,8 @@ WebScrollbarLayerImpl::WebScrollbarLayerImpl( int track_start, bool is_left_side_vertical_scrollbar) : layer_(new WebLayerImpl( - SolidColorScrollbarLayer::Create(ConvertOrientation(orientation), + SolidColorScrollbarLayer::Create(WebLayerImpl::LayerSettings(), + ConvertOrientation(orientation), thumb_thickness, track_start, is_left_side_vertical_scrollbar, diff --git a/chromium/cc/cc.gyp b/chromium/cc/cc.gyp index 2a4d66a267e..d4a2ea02fe7 100644 --- a/chromium/cc/cc.gyp +++ b/chromium/cc/cc.gyp @@ -20,7 +20,6 @@ '<(DEPTH)/ui/events/events.gyp:events_base', '<(DEPTH)/ui/gfx/gfx.gyp:gfx', '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry', - 'cc_opts', ], 'variables': { 'optimize': 'max', @@ -40,10 +39,18 @@ 'animation/animation_delegate.h', 'animation/animation_events.cc', 'animation/animation_events.h', + 'animation/animation_host.cc', + 'animation/animation_host.h', 'animation/animation_id_provider.cc', 'animation/animation_id_provider.h', + 'animation/animation_player.cc', + 'animation/animation_player.h', 'animation/animation_registrar.cc', 'animation/animation_registrar.h', + 'animation/animation_timeline.cc', + 'animation/animation_timeline.h', + 'animation/element_animations.cc', + 'animation/element_animations.h', 'animation/keyframed_animation_curve.cc', 'animation/keyframed_animation_curve.h', 'animation/layer_animation_controller.cc', @@ -68,17 +75,23 @@ 'base/completion_event.h', 'base/delayed_unique_notifier.cc', 'base/delayed_unique_notifier.h', + 'base/histograms.cc', + 'base/histograms.h', 'base/invalidation_region.cc', 'base/invalidation_region.h', + 'base/list_container.cc', + 'base/list_container.h', 'base/math_util.cc', 'base/math_util.h', 'base/region.cc', 'base/region.h', + 'base/resource_id.h', 'base/rolling_time_delta_history.cc', 'base/rolling_time_delta_history.h', 'base/scoped_ptr_algorithm.h', 'base/scoped_ptr_deque.h', 'base/scoped_ptr_vector.h', + 'base/sidecar_list_container.h', 'base/simple_enclosed_region.cc', 'base/simple_enclosed_region.h', 'base/switches.cc', @@ -89,7 +102,6 @@ 'base/time_util.h', 'base/unique_notifier.cc', 'base/unique_notifier.h', - 'base/util.h', 'debug/benchmark_instrumentation.cc', 'debug/benchmark_instrumentation.h', 'debug/debug_colors.cc', @@ -134,6 +146,8 @@ 'debug/rendering_stats_instrumentation.cc', 'debug/rendering_stats_instrumentation.h', 'debug/ring_buffer.h', + 'debug/traced_display_item_list.cc', + 'debug/traced_display_item_list.h', 'debug/traced_picture.cc', 'debug/traced_picture.h', 'debug/traced_value.cc', @@ -156,11 +170,7 @@ 'input/top_controls_manager.h', 'input/top_controls_manager_client.h', 'layers/append_quads_data.h', - 'layers/content_layer.cc', - 'layers/content_layer.h', 'layers/content_layer_client.h', - 'layers/contents_scaling_layer.cc', - 'layers/contents_scaling_layer.h', 'layers/delegated_frame_provider.cc', 'layers/delegated_frame_provider.h', 'layers/delegated_frame_resource_collection.cc', @@ -174,8 +184,6 @@ 'layers/heads_up_display_layer.h', 'layers/heads_up_display_layer_impl.cc', 'layers/heads_up_display_layer_impl.h', - 'layers/image_layer.cc', - 'layers/image_layer.h', 'layers/io_surface_layer.cc', 'layers/io_surface_layer.h', 'layers/io_surface_layer_impl.cc', @@ -234,10 +242,6 @@ 'layers/texture_layer_client.h', 'layers/texture_layer_impl.cc', 'layers/texture_layer_impl.h', - 'layers/tiled_layer.cc', - 'layers/tiled_layer.h', - 'layers/tiled_layer_impl.cc', - 'layers/tiled_layer_impl.h', 'layers/ui_resource_layer.cc', 'layers/ui_resource_layer.h', 'layers/ui_resource_layer_impl.cc', @@ -334,7 +338,6 @@ 'output/texture_mailbox_deleter.h', 'output/viewport_selection_bound.cc', 'output/viewport_selection_bound.h', - 'output/vsync_parameter_observer.h', 'playback/clip_display_item.cc', 'playback/clip_display_item.h', 'playback/clip_path_display_item.cc', @@ -345,6 +348,8 @@ 'playback/display_item.h', 'playback/display_item_list.cc', 'playback/display_item_list.h', + 'playback/display_item_list_settings.cc', + 'playback/display_item_list_settings.h', 'playback/display_list_raster_source.cc', 'playback/display_list_raster_source.h', 'playback/display_list_recording_source.cc', @@ -385,8 +390,6 @@ 'quads/io_surface_draw_quad.h', 'quads/largest_draw_quad.cc', 'quads/largest_draw_quad.h', - 'quads/list_container.cc', - 'quads/list_container.h', 'quads/picture_draw_quad.cc', 'quads/picture_draw_quad.h', 'quads/render_pass.cc', @@ -435,28 +438,10 @@ 'raster/tile_task_worker_pool.h', 'raster/zero_copy_tile_task_worker_pool.cc', 'raster/zero_copy_tile_task_worker_pool.h', - 'resources/bitmap_content_layer_updater.cc', - 'resources/bitmap_content_layer_updater.h', - 'resources/bitmap_skpicture_content_layer_updater.cc', - 'resources/bitmap_skpicture_content_layer_updater.h', - 'resources/content_layer_updater.cc', - 'resources/content_layer_updater.h', - 'resources/image_layer_updater.cc', - 'resources/image_layer_updater.h', - 'resources/layer_painter.h', - 'resources/layer_updater.cc', - 'resources/layer_updater.h', 'resources/memory_history.cc', 'resources/memory_history.h', 'resources/platform_color.h', - 'resources/prioritized_resource.cc', - 'resources/prioritized_resource.h', - 'resources/prioritized_resource_manager.cc', - 'resources/prioritized_resource_manager.h', - 'resources/priority_calculator.cc', - 'resources/priority_calculator.h', 'resources/release_callback.h', - 'resources/resource.cc', 'resources/resource.h', 'resources/resource_format.cc', 'resources/resource_format.h', @@ -464,12 +449,6 @@ 'resources/resource_pool.h', 'resources/resource_provider.cc', 'resources/resource_provider.h', - 'resources/resource_update.cc', - 'resources/resource_update.h', - 'resources/resource_update_controller.cc', - 'resources/resource_update_controller.h', - 'resources/resource_update_queue.cc', - 'resources/resource_update_queue.h', 'resources/returned_resource.h', 'resources/scoped_resource.cc', 'resources/scoped_resource.h', @@ -482,12 +461,8 @@ 'resources/single_release_callback.h', 'resources/single_release_callback_impl.cc', 'resources/single_release_callback_impl.h', - 'resources/skpicture_content_layer_updater.cc', - 'resources/skpicture_content_layer_updater.h', 'resources/texture_mailbox.cc', 'resources/texture_mailbox.h', - 'resources/texture_uploader.cc', - 'resources/texture_uploader.h', 'resources/transferable_resource.cc', 'resources/transferable_resource.h', 'resources/ui_resource_bitmap.cc', @@ -499,7 +474,11 @@ 'resources/video_resource_updater.h', 'scheduler/begin_frame_source.cc', 'scheduler/begin_frame_source.h', + 'scheduler/begin_frame_tracker.cc', + 'scheduler/begin_frame_tracker.h', 'scheduler/commit_earlyout_reason.h', + 'scheduler/compositor_timing_history.cc', + 'scheduler/compositor_timing_history.h', 'scheduler/delay_based_time_source.cc', 'scheduler/delay_based_time_source.h', 'scheduler/draw_result.h', @@ -512,8 +491,6 @@ 'scheduler/video_frame_controller.h', 'tiles/eviction_tile_priority_queue.cc', 'tiles/eviction_tile_priority_queue.h', - 'tiles/layer_tiling_data.cc', - 'tiles/layer_tiling_data.h', 'tiles/picture_layer_tiling.cc', 'tiles/picture_layer_tiling.h', 'tiles/picture_layer_tiling_set.cc', @@ -560,6 +537,7 @@ 'trees/layer_tree_impl.h', 'trees/layer_tree_settings.cc', 'trees/layer_tree_settings.h', + 'trees/mutator_host_client.h', 'trees/occlusion.cc', 'trees/occlusion.h', 'trees/occlusion_tracker.cc', @@ -570,8 +548,6 @@ 'trees/property_tree_builder.h', 'trees/proxy.cc', 'trees/proxy.h', - 'trees/proxy_timing_history.cc', - 'trees/proxy_timing_history.h', 'trees/scoped_abort_remaining_swap_promises.h', 'trees/single_thread_proxy.cc', 'trees/single_thread_proxy.h', @@ -585,8 +561,14 @@ 'includes': [ '../build/android/increase_size_for_speed.gypi', ], - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 'msvs_disabled_warnings': [ 4267, ], + 'conditions': [ + ['target_arch == "ia32" or target_arch == "x64"', { + 'sources': [ + 'raster/texture_compressor_etc1_sse.cc', + 'raster/texture_compressor_etc1_sse.h', + ], + }], + ], }, { # GN version: //cc/surfaces @@ -596,6 +578,7 @@ 'cc', '<(DEPTH)/base/base.gyp:base', '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', + '<(DEPTH)/gpu/gpu.gyp:gpu', '<(DEPTH)/skia/skia.gyp:skia', '<(DEPTH)/ui/events/events.gyp:events_base', '<(DEPTH)/ui/gfx/gfx.gyp:gfx', @@ -609,6 +592,8 @@ 'surfaces/display.cc', 'surfaces/display.h', 'surfaces/display_client.h', + 'surfaces/display_scheduler.cc', + 'surfaces/display_scheduler.h', 'surfaces/onscreen_display_client.cc', 'surfaces/onscreen_display_client.h', 'surfaces/surface.cc', @@ -633,41 +618,5 @@ '../build/android/increase_size_for_speed.gypi', ], }, - { - 'target_name': 'cc_opts', - 'type': 'static_library', - 'conditions': [ - ['target_arch == "ia32" or target_arch == "x64"', { - 'defines': [ - 'CC_IMPLEMENTATION=1', - ], - 'dependencies': [ - 'cc_opts_sse', - ] - }], - ], - }, - { - 'target_name': 'cc_opts_sse', - 'type': 'static_library', - 'dependencies': [ - '<(DEPTH)/base/base.gyp:base', - ], - 'conditions': [ - ['target_arch == "ia32" or target_arch == "x64"', { - 'defines': [ - 'CC_IMPLEMENTATION=1', - ], - 'sources': [ - # Conditional compilation for SSE2 code on x86 and x64 machines - 'raster/texture_compressor_etc1_sse.cc', - 'raster/texture_compressor_etc1_sse.h', - ], - 'cflags': [ - '-msse2', - ], - }], - ], - }, ], } diff --git a/chromium/cc/cc_tests.gyp b/chromium/cc/cc_tests.gyp index 5ded2b81fc5..5f5f4e418aa 100644 --- a/chromium/cc/cc_tests.gyp +++ b/chromium/cc/cc_tests.gyp @@ -6,7 +6,11 @@ 'variables': { 'chromium_code': 1, 'cc_unit_tests_source_files': [ + 'animation/animation_host_unittest.cc', + 'animation/animation_player_unittest.cc', + 'animation/animation_timeline_unittest.cc', 'animation/animation_unittest.cc', + 'animation/element_animations_unittest.cc', 'animation/keyframed_animation_curve_unittest.cc', 'animation/layer_animation_controller_unittest.cc', 'animation/scroll_offset_animation_curve_unittest.cc', @@ -15,19 +19,20 @@ 'animation/transform_operations_unittest.cc', 'base/delayed_unique_notifier_unittest.cc', 'base/float_quad_unittest.cc', + 'base/histograms_unittest.cc', + 'base/list_container_unittest.cc', 'base/math_util_unittest.cc', 'base/region_unittest.cc', 'base/rolling_time_delta_history_unittest.cc', 'base/scoped_ptr_vector_unittest.cc', + 'base/sidecar_list_container_unittest.cc', 'base/simple_enclosed_region_unittest.cc', 'base/tiling_data_unittest.cc', 'base/unique_notifier_unittest.cc', - 'base/util_unittest.cc', 'debug/frame_timing_tracker_unittest.cc', 'debug/micro_benchmark_controller_unittest.cc', 'debug/rendering_stats_unittest.cc', 'input/top_controls_manager_unittest.cc', - 'layers/contents_scaling_layer_unittest.cc', 'layers/delegated_frame_provider_unittest.cc', 'layers/delegated_frame_resource_collection_unittest.cc', 'layers/delegated_renderer_layer_impl_unittest.cc', @@ -56,10 +61,9 @@ 'layers/surface_layer_unittest.cc', 'layers/texture_layer_impl_unittest.cc', 'layers/texture_layer_unittest.cc', - 'layers/tiled_layer_impl_unittest.cc', - 'layers/tiled_layer_unittest.cc', 'layers/ui_resource_layer_impl_unittest.cc', 'layers/ui_resource_layer_unittest.cc', + 'layers/video_frame_provider_client_impl_unittest.cc', 'layers/video_layer_impl_unittest.cc', 'output/begin_frame_args_unittest.cc', 'output/bsp_tree_unittest.cc', @@ -75,6 +79,7 @@ 'output/software_renderer_unittest.cc', 'output/texture_mailbox_deleter_unittest.cc', 'playback/display_item_list_unittest.cc', + 'playback/display_list_raster_source_unittest.cc', 'playback/display_list_recording_source_unittest.cc', 'playback/picture_pile_impl_unittest.cc', 'playback/picture_pile_unittest.cc', @@ -83,20 +88,18 @@ 'playback/recording_source_unittest.cc', 'quads/draw_polygon_unittest.cc', 'quads/draw_quad_unittest.cc', - 'quads/list_container_unittest.cc', 'quads/render_pass_unittest.cc', 'raster/scoped_gpu_raster_unittest.cc', 'raster/task_graph_runner_unittest.cc', 'raster/texture_compressor_etc1_unittest.cc', 'raster/tile_task_worker_pool_unittest.cc', 'resources/platform_color_unittest.cc', - 'resources/prioritized_resource_unittest.cc', + 'resources/resource_pool_unittest.cc', 'resources/resource_provider_unittest.cc', - 'resources/resource_update_controller_unittest.cc', 'resources/scoped_resource_unittest.cc', - 'resources/texture_uploader_unittest.cc', 'resources/video_resource_updater_unittest.cc', 'scheduler/begin_frame_source_unittest.cc', + 'scheduler/compositor_timing_history_unittest.cc', 'scheduler/delay_based_time_source_unittest.cc', 'scheduler/scheduler_state_machine_unittest.cc', 'scheduler/scheduler_unittest.cc', @@ -116,13 +119,14 @@ 'trees/layer_tree_host_pixeltest_masks.cc', 'trees/layer_tree_host_pixeltest_readback.cc', 'trees/layer_tree_host_pixeltest_synchronous.cc', + 'trees/layer_tree_host_pixeltest_tiles.cc', 'trees/layer_tree_host_unittest.cc', 'trees/layer_tree_host_unittest_animation.cc', + 'trees/layer_tree_host_unittest_animation_timelines.cc', 'trees/layer_tree_host_unittest_context.cc', 'trees/layer_tree_host_unittest_copyrequest.cc', 'trees/layer_tree_host_unittest_damage.cc', 'trees/layer_tree_host_unittest_delegated.cc', - 'trees/layer_tree_host_unittest_no_message_loop.cc', 'trees/layer_tree_host_unittest_occlusion.cc', 'trees/layer_tree_host_unittest_picture.cc', 'trees/layer_tree_host_unittest_proxy.cc', @@ -136,6 +140,7 @@ ], 'cc_surfaces_unit_tests_source_files': [ 'surfaces/display_unittest.cc', + 'surfaces/display_scheduler_unittest.cc', 'surfaces/surface_aggregator_test_helpers.cc', 'surfaces/surface_aggregator_test_helpers.h', 'surfaces/surface_aggregator_unittest.cc', @@ -147,16 +152,14 @@ 'cc_tests_support_files': [ 'test/animation_test_common.cc', 'test/animation_test_common.h', + 'test/animation_timelines_test_common.cc', + 'test/animation_timelines_test_common.h', 'test/begin_frame_args_test.cc', 'test/begin_frame_args_test.h', 'test/failure_output_surface.cc', 'test/failure_output_surface.h', - 'test/fake_content_layer.cc', - 'test/fake_content_layer.h', 'test/fake_content_layer_client.cc', 'test/fake_content_layer_client.h', - 'test/fake_content_layer_impl.cc', - 'test/fake_content_layer_impl.h', 'test/fake_delegated_renderer_layer.cc', 'test/fake_delegated_renderer_layer.h', 'test/fake_delegated_renderer_layer_impl.cc', @@ -194,6 +197,7 @@ 'test/fake_renderer_client.cc', 'test/fake_renderer_client.h', 'test/fake_rendering_stats_instrumentation.h', + 'test/fake_resource_provider.h', 'test/fake_scoped_ui_resource.cc', 'test/fake_scoped_ui_resource.h', 'test/fake_scrollbar.cc', @@ -208,7 +212,6 @@ 'test/fake_video_frame_provider.h', 'test/geometry_test_utils.cc', 'test/geometry_test_utils.h', - 'test/impl_side_painting_settings.h', 'test/layer_test_common.cc', 'test/layer_test_common.h', 'test/layer_tree_host_common_test.cc', @@ -260,8 +263,6 @@ 'test/test_image_factory.h', 'test/test_in_process_context_provider.cc', 'test/test_in_process_context_provider.h', - 'test/test_now_source.cc', - 'test/test_now_source.h', 'test/test_occlusion_tracker.h', 'test/test_shared_bitmap_manager.cc', 'test/test_shared_bitmap_manager.h', @@ -273,8 +274,6 @@ 'test/test_tile_priorities.h', 'test/test_web_graphics_context_3d.cc', 'test/test_web_graphics_context_3d.h', - 'test/tiled_layer_test_common.cc', - 'test/tiled_layer_test_common.h', ], }, 'targets': [ @@ -329,8 +328,6 @@ } ], ], - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 'msvs_disabled_warnings': [ 4267, ], }, { # GN version: //cc/cc_perftests @@ -357,6 +354,7 @@ 'layers/layer_perftest.cc', 'layers/picture_layer_impl_perftest.cc', 'playback/picture_pile_impl_perftest.cc', + 'quads/draw_quad_perftest.cc', 'raster/task_graph_runner_perftest.cc', 'raster/texture_compressor_perftest.cc', 'raster/tile_task_worker_pool_perftest.cc', @@ -390,8 +388,6 @@ } ], ], - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 'msvs_disabled_warnings': [ 4267, ], }, { 'target_name': 'cc_test_support', @@ -423,8 +419,6 @@ 'sources': [ '<@(cc_tests_support_files)', ], - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 'msvs_disabled_warnings': [ 4267, ], }, ], 'conditions': [ diff --git a/chromium/cc/debug/debug_rect_history.cc b/chromium/cc/debug/debug_rect_history.cc index c257c60c5cf..9fa90a5bd36 100644 --- a/chromium/cc/debug/debug_rect_history.cc +++ b/chromium/cc/debug/debug_rect_history.cc @@ -70,18 +70,10 @@ void DebugRectHistory::SavePaintRects(LayerImpl* layer) { Region invalidation_region = layer->GetInvalidationRegion(); if (!invalidation_region.IsEmpty() && layer->DrawsContent()) { - float width_scale = layer->content_bounds().width() / - static_cast<float>(layer->bounds().width()); - float height_scale = layer->content_bounds().height() / - static_cast<float>(layer->bounds().height()); - for (Region::Iterator it(invalidation_region); it.has_rect(); it.next()) { - gfx::Rect update_content_rect = - gfx::ScaleToEnclosingRect(it.rect(), width_scale, height_scale); - debug_rects_.push_back( - DebugRect(PAINT_RECT_TYPE, - MathUtil::MapEnclosingClippedRect( - layer->screen_space_transform(), update_content_rect))); + debug_rects_.push_back(DebugRect( + PAINT_RECT_TYPE, MathUtil::MapEnclosingClippedRect( + layer->screen_space_transform(), it.rect()))); } } @@ -92,9 +84,8 @@ void DebugRectHistory::SavePaintRects(LayerImpl* layer) { void DebugRectHistory::SavePropertyChangedRects( const LayerImplList& render_surface_layer_list, LayerImpl* hud_layer) { - for (int surface_index = render_surface_layer_list.size() - 1; - surface_index >= 0; - --surface_index) { + for (size_t i = 0; i < render_surface_layer_list.size(); ++i) { + size_t surface_index = render_surface_layer_list.size() - 1 - i; LayerImpl* render_surface_layer = render_surface_layer_list[surface_index]; RenderSurfaceImpl* render_surface = render_surface_layer->render_surface(); DCHECK(render_surface); @@ -115,20 +106,18 @@ void DebugRectHistory::SavePropertyChangedRects( if (!layer->LayerPropertyChanged()) continue; - debug_rects_.push_back( - DebugRect(PROPERTY_CHANGED_RECT_TYPE, - MathUtil::MapEnclosingClippedRect( - layer->screen_space_transform(), - gfx::Rect(layer->content_bounds())))); + debug_rects_.push_back(DebugRect( + PROPERTY_CHANGED_RECT_TYPE, + MathUtil::MapEnclosingClippedRect(layer->screen_space_transform(), + gfx::Rect(layer->bounds())))); } } } void DebugRectHistory::SaveSurfaceDamageRects( const LayerImplList& render_surface_layer_list) { - for (int surface_index = render_surface_layer_list.size() - 1; - surface_index >= 0; - --surface_index) { + for (size_t i = 0; i < render_surface_layer_list.size(); ++i) { + size_t surface_index = render_surface_layer_list.size() - 1 - i; LayerImpl* render_surface_layer = render_surface_layer_list[surface_index]; RenderSurfaceImpl* render_surface = render_surface_layer->render_surface(); DCHECK(render_surface); @@ -143,9 +132,8 @@ void DebugRectHistory::SaveSurfaceDamageRects( void DebugRectHistory::SaveScreenSpaceRects( const LayerImplList& render_surface_layer_list) { - for (int surface_index = render_surface_layer_list.size() - 1; - surface_index >= 0; - --surface_index) { + for (size_t i = 0; i < render_surface_layer_list.size(); ++i) { + size_t surface_index = render_surface_layer_list.size() - 1 - i; LayerImpl* render_surface_layer = render_surface_layer_list[surface_index]; RenderSurfaceImpl* render_surface = render_surface_layer->render_surface(); DCHECK(render_surface); @@ -176,12 +164,10 @@ void DebugRectHistory::SaveTouchEventHandlerRectsCallback(LayerImpl* layer) { for (Region::Iterator iter(layer->touch_event_handler_region()); iter.has_rect(); iter.next()) { - gfx::Rect touch_rect = gfx::ScaleToEnclosingRect( - iter.rect(), layer->contents_scale_x(), layer->contents_scale_y()); debug_rects_.push_back( DebugRect(TOUCH_EVENT_HANDLER_RECT_TYPE, MathUtil::MapEnclosingClippedRect( - layer->screen_space_transform(), touch_rect))); + layer->screen_space_transform(), iter.rect()))); } } @@ -195,14 +181,10 @@ void DebugRectHistory::SaveWheelEventHandlerRectsCallback(LayerImpl* layer) { if (!layer->have_wheel_event_handlers()) return; - gfx::Rect wheel_rect = - gfx::ScaleToEnclosingRect(gfx::Rect(layer->content_bounds()), - layer->contents_scale_x(), - layer->contents_scale_y()); - debug_rects_.push_back( - DebugRect(WHEEL_EVENT_HANDLER_RECT_TYPE, - MathUtil::MapEnclosingClippedRect( - layer->screen_space_transform(), wheel_rect))); + debug_rects_.push_back(DebugRect( + WHEEL_EVENT_HANDLER_RECT_TYPE, + MathUtil::MapEnclosingClippedRect(layer->screen_space_transform(), + gfx::Rect(layer->bounds())))); } void DebugRectHistory::SaveScrollEventHandlerRects(LayerImpl* layer) { @@ -215,14 +197,10 @@ void DebugRectHistory::SaveScrollEventHandlerRectsCallback(LayerImpl* layer) { if (!layer->have_scroll_event_handlers()) return; - gfx::Rect scroll_rect = - gfx::ScaleToEnclosingRect(gfx::Rect(layer->content_bounds()), - layer->contents_scale_x(), - layer->contents_scale_y()); - debug_rects_.push_back( - DebugRect(SCROLL_EVENT_HANDLER_RECT_TYPE, - MathUtil::MapEnclosingClippedRect( - layer->screen_space_transform(), scroll_rect))); + debug_rects_.push_back(DebugRect( + SCROLL_EVENT_HANDLER_RECT_TYPE, + MathUtil::MapEnclosingClippedRect(layer->screen_space_transform(), + gfx::Rect(layer->bounds())))); } void DebugRectHistory::SaveNonFastScrollableRects(LayerImpl* layer) { @@ -235,21 +213,17 @@ void DebugRectHistory::SaveNonFastScrollableRectsCallback(LayerImpl* layer) { for (Region::Iterator iter(layer->non_fast_scrollable_region()); iter.has_rect(); iter.next()) { - gfx::Rect scroll_rect = gfx::ScaleToEnclosingRect( - iter.rect(), layer->contents_scale_x(), layer->contents_scale_y()); debug_rects_.push_back( DebugRect(NON_FAST_SCROLLABLE_RECT_TYPE, MathUtil::MapEnclosingClippedRect( - layer->screen_space_transform(), scroll_rect))); + layer->screen_space_transform(), iter.rect()))); } } void DebugRectHistory::SaveLayerAnimationBoundsRects( const LayerImplList& render_surface_layer_list) { - typedef LayerIterator<LayerImpl> LayerIteratorType; - LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list); - for (LayerIteratorType it = - LayerIteratorType::Begin(&render_surface_layer_list); + LayerIterator end = LayerIterator::End(&render_surface_layer_list); + for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list); it != end; ++it) { if (!it.represents_itself()) continue; diff --git a/chromium/cc/debug/devtools_instrumentation.h b/chromium/cc/debug/devtools_instrumentation.h index f1faf6ff424..8f03f8c76fc 100644 --- a/chromium/cc/debug/devtools_instrumentation.h +++ b/chromium/cc/debug/devtools_instrumentation.h @@ -23,6 +23,7 @@ const char kPixelRefId[] = "pixelRefId"; const char kImageDecodeTask[] = "ImageDecodeTask"; const char kBeginFrame[] = "BeginFrame"; +const char kNeedsBeginFrameChanged[] = "NeedsBeginFrameChanged"; const char kActivateLayerTree[] = "ActivateLayerTree"; const char kRequestMainThreadFrame[] = "RequestMainThreadFrame"; const char kBeginMainThreadFrame[] = "BeginMainThreadFrame"; @@ -157,6 +158,21 @@ inline void WillBeginMainThreadFrame(int layer_tree_host_id, int frame_id) { internal::kData, BeginMainThreadFrameData(frame_id)); } +inline scoped_refptr<base::trace_event::ConvertableToTraceFormat> +NeedsBeginFrameData(bool needs_begin_frame) { + scoped_refptr<base::trace_event::TracedValue> value = + new base::trace_event::TracedValue(); + value->SetInteger("needsBeginFrame", needs_begin_frame); + return value; +} + +inline void NeedsBeginFrameChanged(int layer_tree_host_id, bool new_value) { + TRACE_EVENT_INSTANT2( + internal::kCategoryFrame, internal::kNeedsBeginFrameChanged, + TRACE_EVENT_SCOPE_THREAD, internal::kLayerTreeId, layer_tree_host_id, + internal::kData, NeedsBeginFrameData(new_value)); +} + } // namespace devtools_instrumentation } // namespace cc diff --git a/chromium/cc/debug/frame_rate_counter.h b/chromium/cc/debug/frame_rate_counter.h index 0b69b29aea5..c50d7e22237 100644 --- a/chromium/cc/debug/frame_rate_counter.h +++ b/chromium/cc/debug/frame_rate_counter.h @@ -18,7 +18,7 @@ class FrameRateCounter { public: static scoped_ptr<FrameRateCounter> Create(bool has_impl_thread); - int current_frame_number() const { return ring_buffer_.CurrentIndex(); } + size_t current_frame_number() const { return ring_buffer_.CurrentIndex(); } int dropped_frame_count() const { return dropped_frame_count_; } size_t time_stamp_history_size() const { return ring_buffer_.BufferSize(); } diff --git a/chromium/cc/debug/frame_timing_request.h b/chromium/cc/debug/frame_timing_request.h index 09379980fa0..aedd7205298 100644 --- a/chromium/cc/debug/frame_timing_request.h +++ b/chromium/cc/debug/frame_timing_request.h @@ -25,6 +25,10 @@ class CC_EXPORT FrameTimingRequest { // Return the layer space rect for this request. const gfx::Rect& rect() const { return rect_; } + bool operator==(const FrameTimingRequest& other) const { + return (id_ == other.id_) && (rect_ == other.rect_); + } + private: int64_t id_; gfx::Rect rect_; diff --git a/chromium/cc/debug/frame_timing_tracker.cc b/chromium/cc/debug/frame_timing_tracker.cc index 50aa92be5aa..38977ee6f32 100644 --- a/chromium/cc/debug/frame_timing_tracker.cc +++ b/chromium/cc/debug/frame_timing_tracker.cc @@ -8,9 +8,13 @@ #include <limits> #include "base/metrics/histogram.h" +#include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/proxy.h" namespace cc { +namespace { +int kSendTimingIntervalMS = 200; +} FrameTimingTracker::CompositeTimingEvent::CompositeTimingEvent( int _frame_id, @@ -32,11 +36,19 @@ FrameTimingTracker::MainFrameTimingEvent::~MainFrameTimingEvent() { } // static -scoped_ptr<FrameTimingTracker> FrameTimingTracker::Create() { - return make_scoped_ptr(new FrameTimingTracker); +scoped_ptr<FrameTimingTracker> FrameTimingTracker::Create( + LayerTreeHostImpl* layer_tree_host_impl) { + return make_scoped_ptr(new FrameTimingTracker(layer_tree_host_impl)); } -FrameTimingTracker::FrameTimingTracker() { +FrameTimingTracker::FrameTimingTracker(LayerTreeHostImpl* layer_tree_host_impl) + : layer_tree_host_impl_(layer_tree_host_impl), + post_events_notifier_( + layer_tree_host_impl_->proxy()->HasImplThread() + ? layer_tree_host_impl_->proxy()->ImplThreadTaskRunner() + : layer_tree_host_impl_->proxy()->MainThreadTaskRunner(), + base::Bind(&FrameTimingTracker::PostEvents, base::Unretained(this)), + base::TimeDelta::FromMilliseconds(kSendTimingIntervalMS)) { } FrameTimingTracker::~FrameTimingTracker() { @@ -51,6 +63,8 @@ void FrameTimingTracker::SaveTimeStamps( (*composite_events_)[pair.second].push_back( CompositeTimingEvent(pair.first, timestamp)); } + if (!post_events_notifier_.HasPendingNotification()) + post_events_notifier_.Schedule(); } void FrameTimingTracker::SaveMainFrameTimeStamps( @@ -65,6 +79,8 @@ void FrameTimingTracker::SaveMainFrameTimeStamps( events.push_back( MainFrameTimingEvent(source_frame_number, main_frame_time, end_time)); } + if (!post_events_notifier_.HasPendingNotification()) + post_events_notifier_.Schedule(); } scoped_ptr<FrameTimingTracker::CompositeTimingSet> @@ -95,4 +111,9 @@ FrameTimingTracker::GroupMainFrameCountsByRectId() { return main_frame_events_.Pass(); } +void FrameTimingTracker::PostEvents() { + layer_tree_host_impl_->PostFrameTimingEvents(GroupCompositeCountsByRectId(), + GroupMainFrameCountsByRectId()); +} + } // namespace cc diff --git a/chromium/cc/debug/frame_timing_tracker.h b/chromium/cc/debug/frame_timing_tracker.h index 33649931973..7b638d7f8ac 100644 --- a/chromium/cc/debug/frame_timing_tracker.h +++ b/chromium/cc/debug/frame_timing_tracker.h @@ -13,9 +13,12 @@ #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "cc/base/cc_export.h" +#include "cc/base/delayed_unique_notifier.h" namespace cc { +class LayerTreeHostImpl; + // This class maintains a history of timestamps and rect IDs to communicate // frame events back to Blink // TODO(mpb): Start using this. crbug.com/442554 @@ -30,7 +33,7 @@ class CC_EXPORT FrameTimingTracker { }; using CompositeTimingSet = - base::hash_map<int, std::vector<CompositeTimingEvent>>; + base::hash_map<int64_t, std::vector<CompositeTimingEvent>>; struct CC_EXPORT MainFrameTimingEvent { MainFrameTimingEvent(int frame_id, @@ -44,9 +47,10 @@ class CC_EXPORT FrameTimingTracker { }; using MainFrameTimingSet = - base::hash_map<int, std::vector<MainFrameTimingEvent>>; + base::hash_map<int64_t, std::vector<MainFrameTimingEvent>>; - static scoped_ptr<FrameTimingTracker> Create(); + static scoped_ptr<FrameTimingTracker> Create( + LayerTreeHostImpl* layer_tree_host_impl); ~FrameTimingTracker(); @@ -74,11 +78,16 @@ class CC_EXPORT FrameTimingTracker { int source_frame_number); private: - FrameTimingTracker(); + explicit FrameTimingTracker(LayerTreeHostImpl* layer_tree_host_impl); + + void PostEvents(); scoped_ptr<CompositeTimingSet> composite_events_; scoped_ptr<MainFrameTimingSet> main_frame_events_; + LayerTreeHostImpl* layer_tree_host_impl_; + DelayedUniqueNotifier post_events_notifier_; + DISALLOW_COPY_AND_ASSIGN(FrameTimingTracker); }; diff --git a/chromium/cc/debug/frame_timing_tracker_unittest.cc b/chromium/cc/debug/frame_timing_tracker_unittest.cc index b5574435fbc..218927cf26a 100644 --- a/chromium/cc/debug/frame_timing_tracker_unittest.cc +++ b/chromium/cc/debug/frame_timing_tracker_unittest.cc @@ -9,6 +9,10 @@ #include "base/trace_event/trace_event_argument.h" #include "base/values.h" #include "cc/debug/frame_timing_tracker.h" +#include "cc/test/fake_impl_proxy.h" +#include "cc/test/fake_layer_tree_host_impl.h" +#include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -70,7 +74,14 @@ std::string MainFrameToString( } TEST(FrameTimingTrackerTest, DefaultTrackerIsEmpty) { - scoped_ptr<FrameTimingTracker> tracker(FrameTimingTracker::Create()); + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); + + scoped_ptr<FrameTimingTracker> tracker( + FrameTimingTracker::Create(&host_impl)); EXPECT_EQ("{\"values\":[]}", CompositeToString(tracker->GroupCompositeCountsByRectId())); EXPECT_EQ("{\"values\":[]}", @@ -78,7 +89,14 @@ TEST(FrameTimingTrackerTest, DefaultTrackerIsEmpty) { } TEST(FrameTimingTrackerTest, NoFrameIdsIsEmpty) { - scoped_ptr<FrameTimingTracker> tracker(FrameTimingTracker::Create()); + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); + + scoped_ptr<FrameTimingTracker> tracker( + FrameTimingTracker::Create(&host_impl)); std::vector<std::pair<int, int64_t>> ids; tracker->SaveTimeStamps(base::TimeTicks::FromInternalValue(100), ids); EXPECT_EQ("{\"values\":[]}", @@ -86,7 +104,14 @@ TEST(FrameTimingTrackerTest, NoFrameIdsIsEmpty) { } TEST(FrameTimingTrackerTest, NoRectIdsYieldsNoMainFrameEvents) { - scoped_ptr<FrameTimingTracker> tracker(FrameTimingTracker::Create()); + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); + + scoped_ptr<FrameTimingTracker> tracker( + FrameTimingTracker::Create(&host_impl)); tracker->SaveMainFrameTimeStamps(std::vector<int64_t>(), base::TimeTicks::FromInternalValue(100), base::TimeTicks::FromInternalValue(110), 1); @@ -95,7 +120,14 @@ TEST(FrameTimingTrackerTest, NoRectIdsYieldsNoMainFrameEvents) { } TEST(FrameTimingTrackerTest, OneFrameId) { - scoped_ptr<FrameTimingTracker> tracker(FrameTimingTracker::Create()); + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); + + scoped_ptr<FrameTimingTracker> tracker( + FrameTimingTracker::Create(&host_impl)); std::vector<std::pair<int, int64_t>> ids; ids.push_back(std::make_pair(1, 2)); tracker->SaveTimeStamps(base::TimeTicks::FromInternalValue(100), ids); @@ -106,7 +138,14 @@ TEST(FrameTimingTrackerTest, OneFrameId) { } TEST(FrameTimingTrackerTest, OneMainFrameRect) { - scoped_ptr<FrameTimingTracker> tracker(FrameTimingTracker::Create()); + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); + + scoped_ptr<FrameTimingTracker> tracker( + FrameTimingTracker::Create(&host_impl)); std::vector<int64_t> rect_ids; rect_ids.push_back(1); tracker->SaveMainFrameTimeStamps(rect_ids, @@ -119,7 +158,14 @@ TEST(FrameTimingTrackerTest, OneMainFrameRect) { } TEST(FrameTimingTrackerTest, UnsortedTimestampsIds) { - scoped_ptr<FrameTimingTracker> tracker(FrameTimingTracker::Create()); + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); + + scoped_ptr<FrameTimingTracker> tracker( + FrameTimingTracker::Create(&host_impl)); std::vector<std::pair<int, int64_t>> ids; ids.push_back(std::make_pair(1, 2)); tracker->SaveTimeStamps(base::TimeTicks::FromInternalValue(200), ids); @@ -134,7 +180,14 @@ TEST(FrameTimingTrackerTest, UnsortedTimestampsIds) { } TEST(FrameTimingTrackerTest, MainFrameUnsortedTimestamps) { - scoped_ptr<FrameTimingTracker> tracker(FrameTimingTracker::Create()); + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); + + scoped_ptr<FrameTimingTracker> tracker( + FrameTimingTracker::Create(&host_impl)); std::vector<int64_t> rect_ids; rect_ids.push_back(2); tracker->SaveMainFrameTimeStamps(rect_ids, @@ -155,7 +208,14 @@ TEST(FrameTimingTrackerTest, MainFrameUnsortedTimestamps) { } TEST(FrameTimingTrackerTest, MultipleFrameIds) { - scoped_ptr<FrameTimingTracker> tracker(FrameTimingTracker::Create()); + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); + + scoped_ptr<FrameTimingTracker> tracker( + FrameTimingTracker::Create(&host_impl)); std::vector<std::pair<int, int64_t>> ids200; ids200.push_back(std::make_pair(1, 2)); @@ -187,7 +247,14 @@ TEST(FrameTimingTrackerTest, MultipleFrameIds) { } TEST(FrameTimingTrackerTest, MultipleMainFrameEvents) { - scoped_ptr<FrameTimingTracker> tracker(FrameTimingTracker::Create()); + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); + + scoped_ptr<FrameTimingTracker> tracker( + FrameTimingTracker::Create(&host_impl)); std::vector<int64_t> rect_ids200; rect_ids200.push_back(2); diff --git a/chromium/cc/debug/invalidation_benchmark.cc b/chromium/cc/debug/invalidation_benchmark.cc index 6fd3d3e2fb6..8a9fc883224 100644 --- a/chromium/cc/debug/invalidation_benchmark.cc +++ b/chromium/cc/debug/invalidation_benchmark.cc @@ -71,9 +71,9 @@ void InvalidationBenchmark::RunOnLayer(PictureLayer* layer) { switch (mode_) { case FIXED_SIZE: { // Invalidation with a random position and fixed size. - gfx::Rect visible_content_rect = layer->visible_content_rect(); - int x = LCGRandom() * (visible_content_rect.width() - width_); - int y = LCGRandom() * (visible_content_rect.height() - height_); + gfx::Rect visible_layer_rect = layer->visible_layer_rect(); + int x = LCGRandom() * (visible_layer_rect.width() - width_); + int y = LCGRandom() * (visible_layer_rect.height() - height_); gfx::Rect invalidation_rect(x, y, width_, height_); layer->SetNeedsDisplayRect(invalidation_rect); break; @@ -85,11 +85,11 @@ void InvalidationBenchmark::RunOnLayer(PictureLayer* layer) { } case RANDOM: { // Random invalidation inside the viewport. - gfx::Rect visible_content_rect = layer->visible_content_rect(); - int x_min = LCGRandom() * visible_content_rect.width(); - int x_max = LCGRandom() * visible_content_rect.width(); - int y_min = LCGRandom() * visible_content_rect.height(); - int y_max = LCGRandom() * visible_content_rect.height(); + gfx::Rect visible_layer_rect = layer->visible_layer_rect(); + int x_min = LCGRandom() * visible_layer_rect.width(); + int x_max = LCGRandom() * visible_layer_rect.width(); + int y_min = LCGRandom() * visible_layer_rect.height(); + int y_max = LCGRandom() * visible_layer_rect.height(); if (x_min > x_max) std::swap(x_min, x_max); if (y_min > y_max) @@ -100,7 +100,7 @@ void InvalidationBenchmark::RunOnLayer(PictureLayer* layer) { } case VIEWPORT: { // Invalidate entire viewport. - layer->SetNeedsDisplayRect(layer->visible_content_rect()); + layer->SetNeedsDisplayRect(layer->visible_layer_rect()); break; } } diff --git a/chromium/cc/debug/lap_timer.cc b/chromium/cc/debug/lap_timer.cc index 17bca3d313f..eb6900c460a 100644 --- a/chromium/cc/debug/lap_timer.cc +++ b/chromium/cc/debug/lap_timer.cc @@ -10,9 +10,13 @@ namespace cc { namespace { -base::TimeTicks Now() { - return base::TimeTicks::IsThreadNowSupported() ? base::TimeTicks::ThreadNow() - : base::TimeTicks::Now(); +// Returns the offset from the origin from the ThreadTicks time source. +// TimeTicks is used as a fallback if ThreadTicks is not available on the +// current platform. +base::TimeDelta Now() { + return base::ThreadTicks::IsSupported() + ? base::ThreadTicks::Now() - base::ThreadTicks() + : base::TimeTicks::Now() - base::TimeTicks(); } // Default values. @@ -65,7 +69,7 @@ void LapTimer::NextLap() { ++num_laps_; --remaining_no_check_laps_; if (!remaining_no_check_laps_) { - base::TimeTicks now = Now(); + base::TimeDelta now = Now(); accumulator_ += now - start_time_; start_time_ = now; remaining_no_check_laps_ = check_interval_; diff --git a/chromium/cc/debug/lap_timer.h b/chromium/cc/debug/lap_timer.h index 7662e2adb5f..48f99172040 100644 --- a/chromium/cc/debug/lap_timer.h +++ b/chromium/cc/debug/lap_timer.h @@ -49,7 +49,7 @@ class CC_EXPORT LapTimer { int NumLaps(); private: - base::TimeTicks start_time_; + base::TimeDelta start_time_; base::TimeDelta accumulator_; int num_laps_; int warmup_laps_; diff --git a/chromium/cc/debug/micro_benchmark_controller_unittest.cc b/chromium/cc/debug/micro_benchmark_controller_unittest.cc index 2a8dce45246..61f34f4b77e 100644 --- a/chromium/cc/debug/micro_benchmark_controller_unittest.cc +++ b/chromium/cc/debug/micro_benchmark_controller_unittest.cc @@ -7,10 +7,10 @@ #include "cc/debug/micro_benchmark.h" #include "cc/debug/micro_benchmark_controller.h" #include "cc/layers/layer.h" -#include "cc/resources/resource_update_queue.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/fake_proxy.h" +#include "cc/test/test_task_graph_runner.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -23,12 +23,12 @@ class MicroBenchmarkControllerTest : public testing::Test { void SetUp() override { impl_proxy_ = make_scoped_ptr(new FakeImplProxy); - shared_bitmap_manager_.reset(new TestSharedBitmapManager()); layer_tree_host_impl_ = make_scoped_ptr(new FakeLayerTreeHostImpl( - impl_proxy_.get(), shared_bitmap_manager_.get(), nullptr)); + impl_proxy_.get(), &shared_bitmap_manager_, &task_graph_runner_)); - layer_tree_host_ = FakeLayerTreeHost::Create(&layer_tree_host_client_); - layer_tree_host_->SetRootLayer(Layer::Create()); + layer_tree_host_ = FakeLayerTreeHost::Create(&layer_tree_host_client_, + &task_graph_runner_); + layer_tree_host_->SetRootLayer(Layer::Create(LayerSettings())); layer_tree_host_->InitializeForTesting(scoped_ptr<Proxy>(new FakeProxy)); } @@ -39,8 +39,9 @@ class MicroBenchmarkControllerTest : public testing::Test { } FakeLayerTreeHostClient layer_tree_host_client_; + TestTaskGraphRunner task_graph_runner_; + TestSharedBitmapManager shared_bitmap_manager_; scoped_ptr<FakeLayerTreeHost> layer_tree_host_; - scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; scoped_ptr<FakeLayerTreeHostImpl> layer_tree_host_impl_; scoped_ptr<FakeImplProxy> impl_proxy_; }; @@ -74,9 +75,8 @@ TEST_F(MicroBenchmarkControllerTest, BenchmarkRan) { base::Bind(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); - scoped_ptr<ResourceUpdateQueue> queue(new ResourceUpdateQueue); layer_tree_host_->SetOutputSurfaceLostForTesting(false); - layer_tree_host_->UpdateLayers(queue.get()); + layer_tree_host_->UpdateLayers(); EXPECT_EQ(1, run_count); } @@ -94,9 +94,8 @@ TEST_F(MicroBenchmarkControllerTest, MultipleBenchmarkRan) { base::Bind(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); - scoped_ptr<ResourceUpdateQueue> queue(new ResourceUpdateQueue); layer_tree_host_->SetOutputSurfaceLostForTesting(false); - layer_tree_host_->UpdateLayers(queue.get()); + layer_tree_host_->UpdateLayers(); EXPECT_EQ(2, run_count); @@ -111,10 +110,10 @@ TEST_F(MicroBenchmarkControllerTest, MultipleBenchmarkRan) { base::Bind(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); - layer_tree_host_->UpdateLayers(queue.get()); + layer_tree_host_->UpdateLayers(); EXPECT_EQ(4, run_count); - layer_tree_host_->UpdateLayers(queue.get()); + layer_tree_host_->UpdateLayers(); EXPECT_EQ(4, run_count); } diff --git a/chromium/cc/debug/picture_debug_util.cc b/chromium/cc/debug/picture_debug_util.cc index e653b78e235..2b1f7734b9e 100644 --- a/chromium/cc/debug/picture_debug_util.cc +++ b/chromium/cc/debug/picture_debug_util.cc @@ -7,6 +7,7 @@ #include <vector> #include "base/base64.h" +#include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkData.h" @@ -33,10 +34,12 @@ class BitmapSerializer : public SkPixelSerializer { // Otherwise encode as PNG. bool encoding_succeeded = false; if (info.isOpaque()) { - encoding_succeeded = - gfx::JPEGCodec::Encode(reinterpret_cast<const unsigned char*>(pixels), - gfx::JPEGCodec::FORMAT_SkBitmap, info.width(), - info.height(), row_bytes, kJpegQuality, &data); + DCHECK_LE(row_bytes, + static_cast<size_t>(std::numeric_limits<int>::max())); + encoding_succeeded = gfx::JPEGCodec::Encode( + reinterpret_cast<const unsigned char*>(pixels), + gfx::JPEGCodec::FORMAT_SkBitmap, info.width(), info.height(), + static_cast<int>(row_bytes), kJpegQuality, &data); } else { SkBitmap bm; // The cast is ok, since we only read the bm. diff --git a/chromium/cc/debug/picture_record_benchmark.cc b/chromium/cc/debug/picture_record_benchmark.cc index d8608c538ff..0f093ce1ecc 100644 --- a/chromium/cc/debug/picture_record_benchmark.cc +++ b/chromium/cc/debug/picture_record_benchmark.cc @@ -85,7 +85,7 @@ void PictureRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) { void PictureRecordBenchmark::RunOnLayer(PictureLayer* layer) { ContentLayerClient* painter = layer->client(); - gfx::Size content_bounds = layer->content_bounds(); + gfx::Size bounds = layer->bounds(); gfx::Size tile_grid_size(kTileGridSize, kTileGridSize); @@ -94,8 +94,8 @@ void PictureRecordBenchmark::RunOnLayer(PictureLayer* layer) { int width = dimensions.first; int height = dimensions.second; - int y_limit = std::max(1, content_bounds.height() - height); - int x_limit = std::max(1, content_bounds.width() - width); + int y_limit = std::max(1, bounds.height() - height); + int x_limit = std::max(1, bounds.width() - width); for (int y = 0; y < y_limit; y += kPositionIncrement) { for (int x = 0; x < x_limit; x += kPositionIncrement) { gfx::Rect rect = gfx::Rect(x, y, width, height); diff --git a/chromium/cc/debug/rasterize_and_record_benchmark.cc b/chromium/cc/debug/rasterize_and_record_benchmark.cc index c8439856043..b474e431fd2 100644 --- a/chromium/cc/debug/rasterize_and_record_benchmark.cc +++ b/chromium/cc/debug/rasterize_and_record_benchmark.cc @@ -74,7 +74,8 @@ void RasterizeAndRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) { DCHECK(!results_.get()); results_ = make_scoped_ptr(new base::DictionaryValue); results_->SetInteger("pixels_recorded", record_results_.pixels_recorded); - results_->SetInteger("picture_memory_usage", record_results_.bytes_used); + results_->SetInteger("picture_memory_usage", + static_cast<int>(record_results_.bytes_used)); for (int i = 0; i < RecordingSource::RECORDING_MODE_COUNT; i++) { std::string name = base::StringPrintf("record_time%s_ms", kModeSuffixes[i]); @@ -108,8 +109,7 @@ scoped_ptr<MicroBenchmarkImpl> RasterizeAndRecordBenchmark::CreateBenchmarkImpl( void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) { DCHECK(host_); - gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect( - layer->visible_content_rect(), 1.f / layer->contents_scale_x()); + gfx::Rect visible_layer_rect = layer->visible_layer_rect(); if (visible_layer_rect.IsEmpty()) return; @@ -218,18 +218,14 @@ void RasterizeAndRecordBenchmark::RunOnDisplayListLayer( kTimeCheckInterval); do { - const bool use_cached_picture = true; - display_list = - DisplayItemList::Create(visible_layer_rect, use_cached_picture); - painter->PaintContentsToDisplayList( - display_list.get(), visible_layer_rect, painting_control); - display_list->CreateAndCacheSkPicture(); + display_list = painter->PaintContentsToDisplayList(visible_layer_rect, + painting_control); if (memory_used) { // Verify we are recording the same thing each time. - DCHECK(memory_used == display_list->PictureMemoryUsage()); + DCHECK_EQ(memory_used, display_list->ApproximateMemoryUsage()); } else { - memory_used = display_list->PictureMemoryUsage(); + memory_used = display_list->ApproximateMemoryUsage(); } timer.NextLap(); diff --git a/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc b/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc index 1f9a36b871f..1dc110b4fac 100644 --- a/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc +++ b/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc @@ -51,7 +51,8 @@ void RunBenchmark(RasterSource* raster_source, raster_source->PerformSolidColorAnalysis(content_rect, contents_scale, &analysis); - raster_source->PlaybackToCanvas(&canvas, content_rect, contents_scale); + raster_source->PlaybackToCanvas(&canvas, content_rect, content_rect, + contents_scale); *is_solid_color = analysis.is_solid_color; @@ -90,8 +91,8 @@ class FixedInvalidationPictureLayerTilingClient return base_client_->GetPendingOrActiveTwinTiling(tiling); } - TilePriority::PriorityBin GetMaxTilePriorityBin() const override { - return base_client_->GetMaxTilePriorityBin(); + bool HasValidTilePriorities() const override { + return base_client_->HasValidTilePriorities(); } bool RequiresHighResToDraw() const override { @@ -134,7 +135,7 @@ void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit( result->SetDouble("rasterize_time_ms", rasterize_results_.total_best_time.InMillisecondsF()); result->SetDouble("total_pictures_in_pile_size", - rasterize_results_.total_memory_usage); + static_cast<int>(rasterize_results_.total_memory_usage)); result->SetInteger("pixels_rasterized", rasterize_results_.pixels_rasterized); result->SetInteger("pixels_rasterized_with_non_solid_color", rasterize_results_.pixels_rasterized_with_non_solid_color); @@ -157,13 +158,13 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) { rasterize_results_.total_picture_layers_with_no_content++; return; } - if (layer->visible_content_rect().IsEmpty()) { + if (layer->visible_layer_rect().IsEmpty()) { rasterize_results_.total_picture_layers_off_screen++; return; } - FixedInvalidationPictureLayerTilingClient client( - layer, gfx::Rect(layer->content_bounds())); + FixedInvalidationPictureLayerTilingClient client(layer, + gfx::Rect(layer->bounds())); // In this benchmark, we will create a local tiling set and measure how long // it takes to rasterize content. As such, the actual settings used here don't @@ -174,14 +175,13 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) { settings.skewport_target_time_in_seconds, settings.skewport_extrapolation_limit_in_content_pixels); - PictureLayerTiling* tiling = tiling_set->AddTiling(layer->contents_scale_x(), - layer->GetRasterSource()); + PictureLayerTiling* tiling = + tiling_set->AddTiling(1.f, layer->GetRasterSource()); tiling->CreateAllTilesForTesting(); RasterSource* raster_source = tiling->raster_source(); - for (PictureLayerTiling::CoverageIterator it( - tiling, layer->contents_scale_x(), layer->visible_content_rect()); - it; - ++it) { + for (PictureLayerTiling::CoverageIterator it(tiling, 1.f, + layer->visible_layer_rect()); + it; ++it) { DCHECK(*it); gfx::Rect content_rect = (*it)->content_rect(); diff --git a/chromium/cc/debug/rasterize_and_record_benchmark_impl.h b/chromium/cc/debug/rasterize_and_record_benchmark_impl.h index 0ab95438256..99b22f154e7 100644 --- a/chromium/cc/debug/rasterize_and_record_benchmark_impl.h +++ b/chromium/cc/debug/rasterize_and_record_benchmark_impl.h @@ -40,7 +40,7 @@ class RasterizeAndRecordBenchmarkImpl : public MicroBenchmarkImpl { int pixels_rasterized_with_non_solid_color; int pixels_rasterized_as_opaque; base::TimeDelta total_best_time; - int total_memory_usage; + size_t total_memory_usage; int total_layers; int total_picture_layers; int total_picture_layers_with_no_content; diff --git a/chromium/cc/debug/rendering_stats_instrumentation.cc b/chromium/cc/debug/rendering_stats_instrumentation.cc index 7497c628ed1..315743b8ffc 100644 --- a/chromium/cc/debug/rendering_stats_instrumentation.cc +++ b/chromium/cc/debug/rendering_stats_instrumentation.cc @@ -37,21 +37,21 @@ void RenderingStatsInstrumentation::AccumulateAndClearImplThreadStats() { impl_thread_rendering_stats_ = RenderingStats(); } -base::TimeTicks RenderingStatsInstrumentation::StartRecording() const { +base::TimeDelta RenderingStatsInstrumentation::StartRecording() const { if (record_rendering_stats_) { - if (base::TimeTicks::IsThreadNowSupported()) - return base::TimeTicks::ThreadNow(); - return base::TimeTicks::Now(); + if (base::ThreadTicks::IsSupported()) + return base::ThreadTicks::Now() - base::ThreadTicks(); + return base::TimeTicks::Now() - base::TimeTicks(); } - return base::TimeTicks(); + return base::TimeDelta(); } base::TimeDelta RenderingStatsInstrumentation::EndRecording( - base::TimeTicks start_time) const { - if (!start_time.is_null()) { - if (base::TimeTicks::IsThreadNowSupported()) - return base::TimeTicks::ThreadNow() - start_time; - return base::TimeTicks::Now() - start_time; + base::TimeDelta start_time) const { + if (start_time != base::TimeDelta()) { + if (base::ThreadTicks::IsSupported()) + return (base::ThreadTicks::Now() - base::ThreadTicks()) - start_time; + return (base::TimeTicks::Now() - base::TimeTicks()) - start_time; } return base::TimeDelta(); } diff --git a/chromium/cc/debug/rendering_stats_instrumentation.h b/chromium/cc/debug/rendering_stats_instrumentation.h index 2a6e3b7eb6e..47796887788 100644 --- a/chromium/cc/debug/rendering_stats_instrumentation.h +++ b/chromium/cc/debug/rendering_stats_instrumentation.h @@ -37,8 +37,8 @@ class CC_EXPORT RenderingStatsInstrumentation { record_rendering_stats_ = record_rendering_stats; } - base::TimeTicks StartRecording() const; - base::TimeDelta EndRecording(base::TimeTicks start_time) const; + base::TimeDelta StartRecording() const; + base::TimeDelta EndRecording(base::TimeDelta start_time) const; void IncrementFrameCount(int64 count); void AddVisibleContentArea(int64 area); diff --git a/chromium/cc/debug/traced_display_item_list.cc b/chromium/cc/debug/traced_display_item_list.cc new file mode 100644 index 00000000000..1b45a593f2a --- /dev/null +++ b/chromium/cc/debug/traced_display_item_list.cc @@ -0,0 +1,27 @@ +// Copyright 2015 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/debug/traced_display_item_list.h" + +#include "base/json/json_writer.h" +#include "cc/debug/traced_value.h" +#include "cc/playback/display_item_list.h" + +namespace cc { + +TracedDisplayItemList::TracedDisplayItemList( + scoped_refptr<const DisplayItemList> list, + bool include_items) + : display_item_list_(list), include_items_(include_items) { +} + +TracedDisplayItemList::~TracedDisplayItemList() { +} + +void TracedDisplayItemList::AppendAsTraceFormat(std::string* out) const { + scoped_refptr<base::trace_event::ConvertableToTraceFormat> convertable = + display_item_list_->AsValue(include_items_); + convertable->AppendAsTraceFormat(out); +} + +} // namespace cc diff --git a/chromium/cc/debug/traced_display_item_list.h b/chromium/cc/debug/traced_display_item_list.h new file mode 100644 index 00000000000..f7caa04b49e --- /dev/null +++ b/chromium/cc/debug/traced_display_item_list.h @@ -0,0 +1,42 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_DEBUG_TRACED_DISPLAY_ITEM_LIST_H_ +#define CC_DEBUG_TRACED_DISPLAY_ITEM_LIST_H_ + +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/trace_event/trace_event.h" +#include "cc/debug/traced_value.h" + +namespace cc { + +class DisplayItemList; + +class TracedDisplayItemList + : public base::trace_event::ConvertableToTraceFormat { + public: + static scoped_refptr<ConvertableToTraceFormat> AsTraceableDisplayItemList( + scoped_refptr<const DisplayItemList> list, + bool include_items) { + return scoped_refptr<ConvertableToTraceFormat>( + new TracedDisplayItemList(list, include_items)); + } + void AppendAsTraceFormat(std::string* out) const override; + + private: + explicit TracedDisplayItemList(scoped_refptr<const DisplayItemList> list, + bool include_items); + ~TracedDisplayItemList() override; + + scoped_refptr<const DisplayItemList> display_item_list_; + bool include_items_; + + DISALLOW_COPY_AND_ASSIGN(TracedDisplayItemList); +}; + +} // namespace cc + +#endif // CC_DEBUG_TRACED_DISPLAY_ITEM_LIST_H_ diff --git a/chromium/cc/debug/traced_picture.cc b/chromium/cc/debug/traced_picture.cc index 2c7622b66d5..3241871d8ee 100644 --- a/chromium/cc/debug/traced_picture.cc +++ b/chromium/cc/debug/traced_picture.cc @@ -40,18 +40,16 @@ void TracedPicture::AppendPictureAlias(std::string* out) const { scoped_ptr<base::DictionaryValue> alias(new base::DictionaryValue()); alias->SetString("id_ref", base::StringPrintf("%p", picture_.get())); - scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue()); - res->Set("alias", alias.release()); - + base::DictionaryValue res; + res.Set("alias", alias.release()); std::string tmp; - base::JSONWriter::Write(res.get(), &tmp); + base::JSONWriter::Write(res, &tmp); out->append(tmp); } void TracedPicture::AppendPicture(std::string* out) const { - scoped_ptr<base::Value> value = picture_->AsValue(); std::string tmp; - base::JSONWriter::Write(value.get(), &tmp); + base::JSONWriter::Write(*picture_->AsValue(), &tmp); out->append(tmp); } diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h index 81d91b87143..3401eceb553 100644 --- a/chromium/cc/input/input_handler.h +++ b/chromium/cc/input/input_handler.h @@ -88,6 +88,9 @@ class CC_EXPORT InputHandler { virtual ScrollStatus ScrollBegin(const gfx::Point& viewport_point, ScrollInputType type) = 0; + // Similar to ScrollBegin, except the hit test is skipped and scroll always + // targets at the root layer. + virtual ScrollStatus RootScrollBegin(ScrollInputType type) = 0; virtual ScrollStatus ScrollAnimated(const gfx::Point& viewport_point, const gfx::Vector2dF& scroll_delta) = 0; @@ -136,7 +139,7 @@ class CC_EXPORT InputHandler { virtual void PinchGestureEnd() = 0; // Request another callback to InputHandlerClient::Animate(). - virtual void SetNeedsAnimate() = 0; + virtual void SetNeedsAnimateInput() = 0; // Whether the layer under |viewport_point| is the currently scrolling layer. virtual bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point, diff --git a/chromium/cc/input/layer_scroll_offset_delegate.h b/chromium/cc/input/layer_scroll_offset_delegate.h index 02ba011118d..0afc4db89e3 100644 --- a/chromium/cc/input/layer_scroll_offset_delegate.h +++ b/chromium/cc/input/layer_scroll_offset_delegate.h @@ -6,6 +6,8 @@ #define CC_INPUT_LAYER_SCROLL_OFFSET_DELEGATE_H_ #include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/time/time.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/size_f.h" @@ -44,7 +46,14 @@ class LayerScrollOffsetDelegate { // This is called by the compositor to check whether a delegate-managed fling // is active or not. - virtual bool IsExternalFlingActive() const = 0; + // TODO(hush): Remove after WebView's smooth scrolling path is unified with + // Chrome's. + virtual bool IsExternalScrollActive() const = 0; + + // This is called by the compositor when a fling hitting the root layer + // requires a scheduled animation update. + typedef base::Callback<void(base::TimeTicks)> AnimationCallback; + virtual void SetNeedsAnimate(const AnimationCallback& animation) = 0; protected: LayerScrollOffsetDelegate() {} diff --git a/chromium/cc/input/top_controls_manager.cc b/chromium/cc/input/top_controls_manager.cc index c8bd5348721..1a961b50e93 100644 --- a/chromium/cc/input/top_controls_manager.cc +++ b/chromium/cc/input/top_controls_manager.cc @@ -12,7 +12,6 @@ #include "cc/input/top_controls_manager_client.h" #include "cc/output/begin_frame_args.h" #include "cc/trees/layer_tree_impl.h" -#include "ui/gfx/frame_time.h" #include "ui/gfx/geometry/vector2d_f.h" #include "ui/gfx/transform.h" @@ -190,7 +189,7 @@ void TopControlsManager::SetupAnimation(AnimationDirection direction) { } top_controls_animation_ = KeyframedFloatAnimationCurve::Create(); - base::TimeDelta start_time = gfx::FrameTime::Now() - base::TimeTicks(); + base::TimeDelta start_time = base::TimeTicks::Now() - base::TimeTicks(); top_controls_animation_->AddKeyframe( FloatKeyframe::Create(start_time, TopControlsShownRatio(), nullptr)); float max_ending_ratio = (direction == SHOWING_CONTROLS ? 1 : -1); diff --git a/chromium/cc/input/top_controls_manager_unittest.cc b/chromium/cc/input/top_controls_manager_unittest.cc index 52e46e674ed..788acbb9ea0 100644 --- a/chromium/cc/input/top_controls_manager_unittest.cc +++ b/chromium/cc/input/top_controls_manager_unittest.cc @@ -18,7 +18,6 @@ #include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_impl.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/frame_time.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { @@ -159,7 +158,7 @@ TEST(TopControlsManagerTest, PartialShownHideAnimation) { EXPECT_TRUE(manager->animation()); - base::TimeTicks time = gfx::FrameTime::Now(); + base::TimeTicks time = base::TimeTicks::Now(); float previous; while (manager->animation()) { previous = manager->TopControlsShownRatio(); @@ -189,7 +188,7 @@ TEST(TopControlsManagerTest, PartialShownShowAnimation) { EXPECT_TRUE(manager->animation()); - base::TimeTicks time = gfx::FrameTime::Now(); + base::TimeTicks time = base::TimeTicks::Now(); float previous; while (manager->animation()) { previous = manager->TopControlsShownRatio(); @@ -215,7 +214,7 @@ TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdShows) { manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); - base::TimeTicks time = gfx::FrameTime::Now(); + base::TimeTicks time = base::TimeTicks::Now(); float previous; while (manager->animation()) { previous = manager->TopControlsShownRatio(); @@ -241,7 +240,7 @@ TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdHides) { manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); - base::TimeTicks time = gfx::FrameTime::Now(); + base::TimeTicks time = base::TimeTicks::Now(); float previous; while (manager->animation()) { previous = manager->TopControlsShownRatio(); @@ -271,7 +270,7 @@ TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdHides) { manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); - base::TimeTicks time = gfx::FrameTime::Now(); + base::TimeTicks time = base::TimeTicks::Now(); float previous; while (manager->animation()) { previous = manager->TopControlsShownRatio(); @@ -301,7 +300,7 @@ TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdShows) { manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); - base::TimeTicks time = gfx::FrameTime::Now(); + base::TimeTicks time = base::TimeTicks::Now(); float previous; while (manager->animation()) { previous = manager->TopControlsShownRatio(); diff --git a/chromium/cc/layers/append_quads_data.h b/chromium/cc/layers/append_quads_data.h index 50f58775d48..45b0c17b20f 100644 --- a/chromium/cc/layers/append_quads_data.h +++ b/chromium/cc/layers/append_quads_data.h @@ -14,7 +14,7 @@ struct AppendQuadsData { AppendQuadsData() : num_incomplete_tiles(0), num_missing_tiles(0), - visible_content_area(0), + visible_layer_area(0), approximated_visible_content_area(0), checkerboarded_visible_content_area(0) {} @@ -23,7 +23,7 @@ struct AppendQuadsData { // Set by the layer appending quads. int64 num_missing_tiles; // Set by the layer appending quads. - int64 visible_content_area; + int64 visible_layer_area; // Set by the layer appending quads. int64 approximated_visible_content_area; // Set by the layer appending quads. diff --git a/chromium/cc/layers/content_layer.cc b/chromium/cc/layers/content_layer.cc deleted file mode 100644 index 7efa1c20b00..00000000000 --- a/chromium/cc/layers/content_layer.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2010 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/layers/content_layer.h" - -#include "base/auto_reset.h" -#include "base/metrics/histogram.h" -#include "base/time/time.h" -#include "cc/layers/content_layer_client.h" -#include "cc/resources/bitmap_content_layer_updater.h" -#include "cc/resources/bitmap_skpicture_content_layer_updater.h" -#include "cc/resources/layer_painter.h" -#include "cc/trees/layer_tree_host.h" -#include "third_party/skia/include/core/SkPictureRecorder.h" - -namespace cc { - -ContentLayerPainter::ContentLayerPainter(ContentLayerClient* client) - : client_(client) {} - -scoped_ptr<ContentLayerPainter> ContentLayerPainter::Create( - ContentLayerClient* client) { - return make_scoped_ptr(new ContentLayerPainter(client)); -} - -void ContentLayerPainter::Paint(SkCanvas* canvas, - const gfx::Rect& content_rect) { - client_->PaintContents(canvas, content_rect, - ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); -} - -scoped_refptr<ContentLayer> ContentLayer::Create(ContentLayerClient* client) { - return make_scoped_refptr(new ContentLayer(client)); -} - -ContentLayer::ContentLayer(ContentLayerClient* client) - : TiledLayer(), client_(client) { -} - -ContentLayer::~ContentLayer() {} - -void ContentLayer::ClearClient() { - client_ = nullptr; - UpdateDrawsContent(HasDrawableContent()); -} - -bool ContentLayer::HasDrawableContent() const { - return client_ && TiledLayer::HasDrawableContent(); -} - -void ContentLayer::SetLayerTreeHost(LayerTreeHost* host) { - TiledLayer::SetLayerTreeHost(host); - - if (!updater_.get()) - return; -} - -void ContentLayer::SetTexturePriorities( - const PriorityCalculator& priority_calc) { - // Update the tile data before creating all the layer's tiles. - UpdateTileSizeAndTilingOption(); - - TiledLayer::SetTexturePriorities(priority_calc); -} - -bool ContentLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - { - base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, - true); - - CreateUpdaterIfNeeded(); - } - - bool updated = TiledLayer::Update(queue, occlusion); - return updated; -} - -bool ContentLayer::NeedMoreUpdates() { - return NeedsIdlePaint(); -} - -LayerUpdater* ContentLayer::Updater() const { - return updater_.get(); -} - -void ContentLayer::CreateUpdaterIfNeeded() { - if (updater_.get()) - return; - scoped_ptr<LayerPainter> painter = ContentLayerPainter::Create(client_); - if (layer_tree_host()->settings().per_tile_painting_enabled) { - updater_ = BitmapSkPictureContentLayerUpdater::Create( - painter.Pass(), - rendering_stats_instrumentation(), - id()); - } else { - updater_ = BitmapContentLayerUpdater::Create( - painter.Pass(), - id()); - } - updater_->SetOpaque(contents_opaque()); - if (client_) - updater_->SetFillsBoundsCompletely(client_->FillsBoundsCompletely()); - updater_->SetBackgroundColor(background_color()); - - SetTextureFormat( - layer_tree_host()->GetRendererCapabilities().best_texture_format); -} - -void ContentLayer::SetContentsOpaque(bool opaque) { - Layer::SetContentsOpaque(opaque); - if (updater_.get()) - updater_->SetOpaque(opaque); -} - -skia::RefPtr<SkPicture> ContentLayer::GetPicture() const { - if (!DrawsContent()) - return skia::RefPtr<SkPicture>(); - - int width = bounds().width(); - int height = bounds().height(); - - SkPictureRecorder recorder; - SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0); - client_->PaintContents(canvas, gfx::Rect(width, height), - ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); - skia::RefPtr<SkPicture> picture = - skia::AdoptRef(recorder.endRecordingAsPicture()); - return picture; -} - -void ContentLayer::OnOutputSurfaceCreated() { - SetTextureFormat( - layer_tree_host()->GetRendererCapabilities().best_texture_format); - TiledLayer::OnOutputSurfaceCreated(); -} - -} // namespace cc diff --git a/chromium/cc/layers/content_layer.h b/chromium/cc/layers/content_layer.h deleted file mode 100644 index 5d6ac15a801..00000000000 --- a/chromium/cc/layers/content_layer.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_LAYERS_CONTENT_LAYER_H_ -#define CC_LAYERS_CONTENT_LAYER_H_ - -#include "base/basictypes.h" -#include "cc/base/cc_export.h" -#include "cc/layers/tiled_layer.h" -#include "cc/resources/layer_painter.h" - -class SkCanvas; - -namespace cc { - -class ContentLayerClient; -class ContentLayerUpdater; - -class CC_EXPORT ContentLayerPainter : public LayerPainter { - public: - static scoped_ptr<ContentLayerPainter> Create(ContentLayerClient* client); - - void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) override; - - private: - explicit ContentLayerPainter(ContentLayerClient* client); - - ContentLayerClient* client_; - - DISALLOW_COPY_AND_ASSIGN(ContentLayerPainter); -}; - -// A layer that renders its contents into an SkCanvas. -class CC_EXPORT ContentLayer : public TiledLayer { - public: - static scoped_refptr<ContentLayer> Create(ContentLayerClient* client); - - void ClearClient(); - - void SetLayerTreeHost(LayerTreeHost* layer_tree_host) override; - void SetTexturePriorities(const PriorityCalculator& priority_calc) override; - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; - bool NeedMoreUpdates() override; - - void SetContentsOpaque(bool contents_opaque) override; - - skia::RefPtr<SkPicture> GetPicture() const override; - - void OnOutputSurfaceCreated() override; - - protected: - explicit ContentLayer(ContentLayerClient* client); - ~ContentLayer() override; - - bool HasDrawableContent() const override; - - // TiledLayer implementation. - LayerUpdater* Updater() const override; - - private: - // TiledLayer implementation. - void CreateUpdaterIfNeeded() override; - - ContentLayerClient* client_; - scoped_refptr<ContentLayerUpdater> updater_; - - DISALLOW_COPY_AND_ASSIGN(ContentLayer); -}; - -} // namespace cc -#endif // CC_LAYERS_CONTENT_LAYER_H_ diff --git a/chromium/cc/layers/content_layer_client.h b/chromium/cc/layers/content_layer_client.h index 9125b9722b5..3a56263248d 100644 --- a/chromium/cc/layers/content_layer_client.h +++ b/chromium/cc/layers/content_layer_client.h @@ -12,7 +12,6 @@ class SkCanvas; namespace gfx { class Rect; -class RectF; } namespace cc { @@ -30,8 +29,7 @@ class CC_EXPORT ContentLayerClient { const gfx::Rect& clip, PaintingControlSetting painting_status) = 0; - virtual void PaintContentsToDisplayList( - DisplayItemList* display_list, + virtual scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting painting_status) = 0; diff --git a/chromium/cc/layers/contents_scaling_layer.cc b/chromium/cc/layers/contents_scaling_layer.cc deleted file mode 100644 index b44830f5fa7..00000000000 --- a/chromium/cc/layers/contents_scaling_layer.cc +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2012 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/layers/contents_scaling_layer.h" -#include "cc/trees/layer_tree_host.h" -#include "ui/gfx/geometry/size_conversions.h" - -namespace cc { - -gfx::Size ContentsScalingLayer::ComputeContentBoundsForScale( - float scale_x, - float scale_y) const { - return gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale_x, scale_y)); -} - -ContentsScalingLayer::ContentsScalingLayer() - : last_update_contents_scale_x_(0.f), - last_update_contents_scale_y_(0.f) {} - -ContentsScalingLayer::~ContentsScalingLayer() { -} - -void ContentsScalingLayer::CalculateContentsScale( - float ideal_contents_scale, - float* contents_scale_x, - float* contents_scale_y, - gfx::Size* content_bounds) { - float old_contents_scale_x = *contents_scale_x; - float old_contents_scale_y = *contents_scale_y; - gfx::Size old_content_bounds = *content_bounds; - *contents_scale_x = ideal_contents_scale; - *contents_scale_y = ideal_contents_scale; - *content_bounds = ComputeContentBoundsForScale( - ideal_contents_scale, - ideal_contents_scale); - - if (!layer_tree_host()) - return; - - if (old_contents_scale_x != *contents_scale_x || - old_contents_scale_y != *contents_scale_y || - old_content_bounds != *content_bounds) { - layer_tree_host()->property_trees()->needs_rebuild = true; - } -} - -bool ContentsScalingLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - bool updated = Layer::Update(queue, occlusion); - - if (draw_properties().contents_scale_x == last_update_contents_scale_x_ && - draw_properties().contents_scale_y == last_update_contents_scale_y_) - return updated; - - last_update_contents_scale_x_ = draw_properties().contents_scale_x; - last_update_contents_scale_y_ = draw_properties().contents_scale_y; - // Invalidate the whole layer if scale changed. - SetNeedsDisplayRect(gfx::Rect(paint_properties().bounds)); - return updated; -} - -} // namespace cc diff --git a/chromium/cc/layers/contents_scaling_layer.h b/chromium/cc/layers/contents_scaling_layer.h deleted file mode 100644 index 15faa005dfc..00000000000 --- a/chromium/cc/layers/contents_scaling_layer.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_LAYERS_CONTENTS_SCALING_LAYER_H_ -#define CC_LAYERS_CONTENTS_SCALING_LAYER_H_ - -#include "cc/base/cc_export.h" -#include "cc/layers/layer.h" - -namespace cc { - -// Base class for layers that need contents scale. -// The content bounds are determined by bounds and scale of the contents. -class CC_EXPORT ContentsScalingLayer : public Layer { - public: - void CalculateContentsScale(float ideal_contents_scale, - float* contents_scale_x, - float* contents_scale_y, - gfx::Size* content_bounds) override; - - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; - - protected: - ContentsScalingLayer(); - ~ContentsScalingLayer() override; - - gfx::Size ComputeContentBoundsForScale(float scale_x, float scale_y) const; - - private: - float last_update_contents_scale_x_; - float last_update_contents_scale_y_; - - DISALLOW_COPY_AND_ASSIGN(ContentsScalingLayer); -}; - -} // namespace cc - -#endif // CC_LAYERS_CONTENTS_SCALING_LAYER_H__ diff --git a/chromium/cc/layers/contents_scaling_layer_unittest.cc b/chromium/cc/layers/contents_scaling_layer_unittest.cc deleted file mode 100644 index 38385a06ad1..00000000000 --- a/chromium/cc/layers/contents_scaling_layer_unittest.cc +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2012 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/layers/contents_scaling_layer.h" - -#include <vector> - -#include "cc/test/fake_layer_tree_host.h" -#include "cc/test/geometry_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace cc { -namespace { - -class MockContentsScalingLayer : public ContentsScalingLayer { - public: - MockContentsScalingLayer() - : ContentsScalingLayer() {} - - void SetNeedsDisplayRect(const gfx::Rect& dirty_rect) override { - last_needs_display_rect_ = dirty_rect; - ContentsScalingLayer::SetNeedsDisplayRect(dirty_rect); - } - - const gfx::Rect& LastNeedsDisplayRect() const { - return last_needs_display_rect_; - } - - private: - ~MockContentsScalingLayer() override {} - - gfx::Rect last_needs_display_rect_; -}; - -static void CalcDrawProps(FakeLayerTreeHost* host, float device_scale_factor) { - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - host->root_layer(), gfx::Size(500, 500), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); -} - -TEST(ContentsScalingLayerTest, CheckContentsBounds) { - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client); - - scoped_refptr<MockContentsScalingLayer> test_layer = - make_scoped_refptr(new MockContentsScalingLayer()); - - scoped_refptr<Layer> root = Layer::Create(); - root->AddChild(test_layer); - host->SetRootLayer(root); - - test_layer->SetBounds(gfx::Size(320, 240)); - - CalcDrawProps(host.get(), 1.f); - EXPECT_FLOAT_EQ(1.f, test_layer->contents_scale_x()); - EXPECT_FLOAT_EQ(1.f, test_layer->contents_scale_y()); - EXPECT_EQ(320, test_layer->content_bounds().width()); - EXPECT_EQ(240, test_layer->content_bounds().height()); - - CalcDrawProps(host.get(), 2.f); - EXPECT_EQ(640, test_layer->content_bounds().width()); - EXPECT_EQ(480, test_layer->content_bounds().height()); - - test_layer->SetBounds(gfx::Size(10, 20)); - CalcDrawProps(host.get(), 2.f); - EXPECT_EQ(20, test_layer->content_bounds().width()); - EXPECT_EQ(40, test_layer->content_bounds().height()); - - CalcDrawProps(host.get(), 1.33f); - EXPECT_EQ(14, test_layer->content_bounds().width()); - EXPECT_EQ(27, test_layer->content_bounds().height()); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/layers/delegated_frame_provider_unittest.cc b/chromium/cc/layers/delegated_frame_provider_unittest.cc index fe8117e797a..3aef0d18c7d 100644 --- a/chromium/cc/layers/delegated_frame_provider_unittest.cc +++ b/chromium/cc/layers/delegated_frame_provider_unittest.cc @@ -7,8 +7,10 @@ #include "cc/layers/delegated_renderer_layer.h" #include "cc/output/delegated_frame_data.h" #include "cc/quads/texture_draw_quad.h" +#include "cc/resources/resource_provider.h" #include "cc/resources/returned_resource.h" #include "cc/resources/transferable_resource.h" +#include "cc/trees/layer_tree_settings.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -35,15 +37,14 @@ class DelegatedFrameProviderTest } void AddTransferableResource(DelegatedFrameData* frame, - ResourceProvider::ResourceId resource_id) { + ResourceId resource_id) { TransferableResource resource; resource.id = resource_id; resource.mailbox_holder.texture_target = GL_TEXTURE_2D; frame->resource_list.push_back(resource); } - void AddTextureQuad(DelegatedFrameData* frame, - ResourceProvider::ResourceId resource_id) { + void AddTextureQuad(DelegatedFrameData* frame, ResourceId resource_id) { SharedQuadState* sqs = frame->render_pass_list[0]->CreateAndAppendSharedQuadState(); TextureDrawQuad* quad = @@ -90,6 +91,7 @@ class DelegatedFrameProviderTest scoped_refptr<DelegatedFrameProvider> frame_provider_; bool resources_available_; ReturnedResourceArray resources_; + LayerSettings layer_settings_; }; TEST_F(DelegatedFrameProviderTest, SameResources) { @@ -153,9 +155,9 @@ TEST_F(DelegatedFrameProviderTest, RefResources) { SetFrameProvider(frame.Pass()); scoped_refptr<DelegatedRendererLayer> observer1 = - DelegatedRendererLayer::Create(frame_provider_); + DelegatedRendererLayer::Create(layer_settings_, frame_provider_); scoped_refptr<DelegatedRendererLayer> observer2 = - DelegatedRendererLayer::Create(frame_provider_); + DelegatedRendererLayer::Create(layer_settings_, frame_provider_); gfx::RectF damage; @@ -211,9 +213,9 @@ TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProvider) { SetFrameProvider(frame.Pass()); scoped_refptr<DelegatedRendererLayer> observer1 = - DelegatedRendererLayer::Create(frame_provider_); + DelegatedRendererLayer::Create(layer_settings_, frame_provider_); scoped_refptr<DelegatedRendererLayer> observer2 = - DelegatedRendererLayer::Create(frame_provider_); + DelegatedRendererLayer::Create(layer_settings_, frame_provider_); gfx::RectF damage; @@ -253,9 +255,9 @@ TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProviderUntilDestroy) { SetFrameProvider(frame.Pass()); scoped_refptr<DelegatedRendererLayer> observer1 = - DelegatedRendererLayer::Create(frame_provider_); + DelegatedRendererLayer::Create(layer_settings_, frame_provider_); scoped_refptr<DelegatedRendererLayer> observer2 = - DelegatedRendererLayer::Create(frame_provider_); + DelegatedRendererLayer::Create(layer_settings_, frame_provider_); gfx::RectF damage; @@ -297,9 +299,9 @@ TEST_F(DelegatedFrameProviderTest, Damage) { SetFrameProvider(frame.Pass()); scoped_refptr<DelegatedRendererLayer> observer1 = - DelegatedRendererLayer::Create(frame_provider_); + DelegatedRendererLayer::Create(layer_settings_, frame_provider_); scoped_refptr<DelegatedRendererLayer> observer2 = - DelegatedRendererLayer::Create(frame_provider_); + DelegatedRendererLayer::Create(layer_settings_, frame_provider_); gfx::RectF damage; diff --git a/chromium/cc/layers/delegated_renderer_layer.cc b/chromium/cc/layers/delegated_renderer_layer.cc index f95c9bd205b..b48d1eae91e 100644 --- a/chromium/cc/layers/delegated_renderer_layer.cc +++ b/chromium/cc/layers/delegated_renderer_layer.cc @@ -12,14 +12,16 @@ namespace cc { scoped_refptr<DelegatedRendererLayer> DelegatedRendererLayer::Create( + const LayerSettings& settings, const scoped_refptr<DelegatedFrameProvider>& frame_provider) { return scoped_refptr<DelegatedRendererLayer>( - new DelegatedRendererLayer(frame_provider)); + new DelegatedRendererLayer(settings, frame_provider)); } DelegatedRendererLayer::DelegatedRendererLayer( + const LayerSettings& settings, const scoped_refptr<DelegatedFrameProvider>& frame_provider) - : Layer(), + : Layer(settings), frame_provider_(frame_provider), should_collect_new_frame_(true), frame_data_(nullptr), @@ -81,9 +83,8 @@ void DelegatedRendererLayer::ProviderHasNewFrame() { SetNextCommitWaitsForActivation(); } -bool DelegatedRendererLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - bool updated = Layer::Update(queue, occlusion); +bool DelegatedRendererLayer::Update() { + bool updated = Layer::Update(); if (!should_collect_new_frame_) return updated; diff --git a/chromium/cc/layers/delegated_renderer_layer.h b/chromium/cc/layers/delegated_renderer_layer.h index 39d2696c5f1..124b389a0f7 100644 --- a/chromium/cc/layers/delegated_renderer_layer.h +++ b/chromium/cc/layers/delegated_renderer_layer.h @@ -19,12 +19,12 @@ namespace cc { class CC_EXPORT DelegatedRendererLayer : public Layer { public: static scoped_refptr<DelegatedRendererLayer> Create( + const LayerSettings& settings, const scoped_refptr<DelegatedFrameProvider>& frame_provider); scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void SetLayerTreeHost(LayerTreeHost* host) override; - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; + bool Update() override; void PushPropertiesTo(LayerImpl* impl) override; // Called by the DelegatedFrameProvider when a new frame is available to be @@ -34,6 +34,7 @@ class CC_EXPORT DelegatedRendererLayer : public Layer { protected: DelegatedRendererLayer( + const LayerSettings& settings, const scoped_refptr<DelegatedFrameProvider>& frame_provider); ~DelegatedRendererLayer() override; diff --git a/chromium/cc/layers/delegated_renderer_layer_impl.cc b/chromium/cc/layers/delegated_renderer_layer_impl.cc index a99cd17b2c7..9235af5a826 100644 --- a/chromium/cc/layers/delegated_renderer_layer_impl.cc +++ b/chromium/cc/layers/delegated_renderer_layer_impl.cc @@ -44,24 +44,6 @@ bool DelegatedRendererLayerImpl::HasContributingDelegatedRenderPasses() const { return render_passes_in_draw_order_.size() > 1; } -static ResourceProvider::ResourceId ResourceRemapHelper( - bool* invalid_frame, - const ResourceProvider::ResourceIdMap& child_to_parent_map, - ResourceProvider::ResourceIdSet* resources_in_frame, - ResourceProvider::ResourceId id) { - ResourceProvider::ResourceIdMap::const_iterator it = - child_to_parent_map.find(id); - if (it == child_to_parent_map.end()) { - *invalid_frame = true; - return 0; - } - - DCHECK_EQ(it->first, id); - ResourceProvider::ResourceId remapped_id = it->second; - resources_in_frame->insert(id); - return remapped_id; -} - void DelegatedRendererLayerImpl::PushPropertiesTo(LayerImpl* layer) { LayerImpl::PushPropertiesTo(layer); @@ -134,14 +116,22 @@ void DelegatedRendererLayerImpl::SetFrameData( if (reserve_size) resources_in_frame.resize(reserve_size); #endif - DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback = - base::Bind(&ResourceRemapHelper, - &invalid_frame, - resource_map, - &resources_in_frame); for (const auto& pass : render_pass_list) { - for (const auto& quad : pass->quad_list) - quad->IterateResources(remap_resources_to_parent_callback); + for (const auto& quad : pass->quad_list) { + for (ResourceId& resource_id : quad->resources) { + ResourceProvider::ResourceIdMap::const_iterator it = + resource_map.find(resource_id); + if (it == resource_map.end()) { + invalid_frame = true; + break; + } + + DCHECK_EQ(it->first, resource_id); + ResourceId remapped_id = it->second; + resources_in_frame.insert(resource_id); + resource_id = remapped_id; + } + } } if (invalid_frame) { @@ -190,7 +180,7 @@ void DelegatedRendererLayerImpl::SetRenderPasses( RenderPassList::iterator to_take = render_passes_in_draw_order->begin() + i; render_passes_index_by_id_.insert( - std::pair<RenderPassId, int>((*to_take)->id, i)); + RenderPassToIndexMap::value_type((*to_take)->id, i)); scoped_ptr<RenderPass> taken_render_pass = render_passes_in_draw_order->take(to_take); render_passes_in_draw_order_.push_back(taken_render_pass.Pass()); @@ -220,8 +210,13 @@ void DelegatedRendererLayerImpl::ReleaseResources() { have_render_passes_to_push_ = false; } -static inline int IndexToId(int index) { return index + 1; } -static inline int IdToIndex(int id) { return id - 1; } +static inline size_t IndexToId(size_t index) { + return index + 1; +} +static inline size_t IdToIndex(size_t id) { + DCHECK_GT(id, 0u); + return id - 1; +} RenderPassId DelegatedRendererLayerImpl::FirstContributingRenderPassId() const { return RenderPassId(id(), IndexToId(0)); @@ -235,13 +230,13 @@ RenderPassId DelegatedRendererLayerImpl::NextContributingRenderPassId( bool DelegatedRendererLayerImpl::ConvertDelegatedRenderPassId( RenderPassId delegated_render_pass_id, RenderPassId* output_render_pass_id) const { - base::hash_map<RenderPassId, int>::const_iterator found = + RenderPassToIndexMap::const_iterator found = render_passes_index_by_id_.find(delegated_render_pass_id); if (found == render_passes_index_by_id_.end()) { // Be robust against a RenderPass id that isn't part of the frame. return false; } - unsigned delegated_render_pass_index = found->second; + size_t delegated_render_pass_index = found->second; *output_render_pass_id = RenderPassId(id(), IndexToId(delegated_render_pass_index)); return true; @@ -259,7 +254,7 @@ void DelegatedRendererLayerImpl::AppendContributingRenderPasses( inverse_device_scale_factor_); for (size_t i = 0; i < render_passes_in_draw_order_.size() - 1; ++i) { - RenderPassId output_render_pass_id(-1, -1); + RenderPassId output_render_pass_id; bool present = ConvertDelegatedRenderPassId(render_passes_in_draw_order_[i]->id, &output_render_pass_id); @@ -267,7 +262,7 @@ void DelegatedRendererLayerImpl::AppendContributingRenderPasses( // Don't clash with the RenderPass we generate if we own a RenderSurface. DCHECK(present) << render_passes_in_draw_order_[i]->id.layer_id << ", " << render_passes_in_draw_order_[i]->id.index; - DCHECK_GT(output_render_pass_id.index, 0); + DCHECK_GT(output_render_pass_id.index, 0u); scoped_ptr<RenderPass> copy_pass = render_passes_in_draw_order_[i]->Copy(output_render_pass_id); @@ -318,7 +313,7 @@ void DelegatedRendererLayerImpl::AppendQuads( // Verify that the RenderPass we are appending to was created by us. DCHECK(target_render_pass_id.layer_id == id()); - int render_pass_index = IdToIndex(target_render_pass_id.index); + size_t render_pass_index = IdToIndex(target_render_pass_id.index); const RenderPass* delegated_render_pass = render_passes_in_draw_order_[render_pass_index]; AppendRenderPassQuads(render_pass, @@ -353,25 +348,19 @@ void DelegatedRendererLayerImpl::AppendRainbowDebugBorder( const int kStripeWidth = 300; const int kStripeHeight = 300; - for (size_t i = 0; ; ++i) { + for (int i = 0;; ++i) { // For horizontal lines. int x = kStripeWidth * i; - int width = std::min(kStripeWidth, content_bounds().width() - x - 1); + int width = std::min(kStripeWidth, bounds().width() - x - 1); // For vertical lines. int y = kStripeHeight * i; - int height = std::min(kStripeHeight, content_bounds().height() - y - 1); + int height = std::min(kStripeHeight, bounds().height() - y - 1); gfx::Rect top(x, 0, width, border_width); - gfx::Rect bottom(x, - content_bounds().height() - border_width, - width, - border_width); + gfx::Rect bottom(x, bounds().height() - border_width, width, border_width); gfx::Rect left(0, y, border_width, height); - gfx::Rect right(content_bounds().width() - border_width, - y, - border_width, - height); + gfx::Rect right(bounds().width() - border_width, y, border_width, height); if (top.IsEmpty() && left.IsEmpty()) break; @@ -400,7 +389,7 @@ void DelegatedRendererLayerImpl::AppendRainbowDebugBorder( colors[i % kNumColors], static_cast<uint8_t>(SkColorGetA(colors[i % kNumColors]) * kFillOpacity)); - gfx::Rect fill_rect(x, 0, width, content_bounds().height()); + gfx::Rect fill_rect(x, 0, width, bounds().height()); solid_quad->SetNew(shared_quad_state, fill_rect, fill_rect, fill_color, force_anti_aliasing_off); } @@ -440,13 +429,13 @@ void DelegatedRendererLayerImpl::AppendRenderPassQuads( output_shared_quad_state->CopyFrom(delegated_shared_quad_state); if (is_root_delegated_render_pass) { - output_shared_quad_state->content_to_target_transform.ConcatTransform( + output_shared_quad_state->quad_to_target_transform.ConcatTransform( delegated_frame_to_target_transform); if (render_target() == this) { DCHECK(!is_clipped()); DCHECK(render_surface()); - DCHECK_EQ(0, num_unclipped_descendants()); + DCHECK_EQ(0u, num_unclipped_descendants()); output_shared_quad_state->clip_rect = MathUtil::MapEnclosingClippedRect( delegated_frame_to_target_transform, @@ -468,7 +457,7 @@ void DelegatedRendererLayerImpl::AppendRenderPassQuads( DCHECK(output_shared_quad_state); gfx::Transform quad_content_to_delegated_target_space = - output_shared_quad_state->content_to_target_transform; + output_shared_quad_state->quad_to_target_transform; if (!is_root_delegated_render_pass) { quad_content_to_delegated_target_space.ConcatTransform( delegated_render_pass->transform_to_root_target); @@ -496,7 +485,7 @@ void DelegatedRendererLayerImpl::AppendRenderPassQuads( } else { RenderPassId delegated_contributing_render_pass_id = RenderPassDrawQuad::MaterialCast(delegated_quad)->render_pass_id; - RenderPassId output_contributing_render_pass_id(-1, -1); + RenderPassId output_contributing_render_pass_id; bool present = ConvertDelegatedRenderPassId(delegated_contributing_render_pass_id, diff --git a/chromium/cc/layers/delegated_renderer_layer_impl.h b/chromium/cc/layers/delegated_renderer_layer_impl.h index 617d76f3b1e..2543894c5d4 100644 --- a/chromium/cc/layers/delegated_renderer_layer_impl.h +++ b/chromium/cc/layers/delegated_renderer_layer_impl.h @@ -87,7 +87,9 @@ class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl { bool have_render_passes_to_push_; float inverse_device_scale_factor_; RenderPassList render_passes_in_draw_order_; - base::hash_map<RenderPassId, int> render_passes_index_by_id_; + + using RenderPassToIndexMap = base::hash_map<RenderPassId, size_t>; + RenderPassToIndexMap render_passes_index_by_id_; ResourceProvider::ResourceIdSet resources_; int child_id_; diff --git a/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc b/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc index cc45c53f19e..a2e8d704725 100644 --- a/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc +++ b/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc @@ -24,7 +24,6 @@ #include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/frame_time.h" #include "ui/gfx/transform.h" namespace cc { @@ -73,19 +72,16 @@ class DelegatedRendererLayerImplTestSimple layer_before->SetPosition(gfx::Point(20, 20)); layer_before->SetBounds(gfx::Size(14, 14)); - layer_before->SetContentBounds(gfx::Size(14, 14)); layer_before->SetDrawsContent(true); layer_before->SetHasRenderSurface(true); layer_after->SetPosition(gfx::Point(5, 5)); layer_after->SetBounds(gfx::Size(15, 15)); - layer_after->SetContentBounds(gfx::Size(15, 15)); layer_after->SetDrawsContent(true); layer_after->SetHasRenderSurface(true); delegated_renderer_layer->SetPosition(gfx::Point(3, 3)); delegated_renderer_layer->SetBounds(gfx::Size(10, 10)); - delegated_renderer_layer->SetContentBounds(gfx::Size(10, 10)); delegated_renderer_layer->SetDrawsContent(true); gfx::Transform transform; transform.Translate(1.0, 1.0); @@ -149,7 +145,6 @@ TEST_F(DelegatedRendererLayerImplTest, delegated_renderer_layer->SetPosition(gfx::Point(3, 3)); delegated_renderer_layer->SetBounds(gfx::Size(10, 10)); - delegated_renderer_layer->SetContentBounds(gfx::Size(10, 10)); delegated_renderer_layer->SetDrawsContent(true); delegated_renderer_layer->SetHasRenderSurface(true); gfx::Transform transform; @@ -229,7 +224,6 @@ TEST_F(DelegatedRendererLayerImplTest, delegated_renderer_layer->SetPosition(gfx::Point(3, 3)); delegated_renderer_layer->SetBounds(gfx::Size(10, 10)); - delegated_renderer_layer->SetContentBounds(gfx::Size(10, 10)); delegated_renderer_layer->SetDrawsContent(true); delegated_renderer_layer->SetHasRenderSurface(true); gfx::Transform transform; @@ -308,16 +302,16 @@ TEST_F(DelegatedRendererLayerImplTestSimple, AddsContributingRenderPasses) { // The DelegatedRendererLayer should have added its contributing RenderPasses // to the frame. EXPECT_EQ(4, frame.render_passes[1]->id.layer_id); - EXPECT_EQ(1, frame.render_passes[1]->id.index); + EXPECT_EQ(1u, frame.render_passes[1]->id.index); EXPECT_EQ(4, frame.render_passes[2]->id.layer_id); - EXPECT_EQ(2, frame.render_passes[2]->id.index); + EXPECT_EQ(2u, frame.render_passes[2]->id.index); // And all other RenderPasses should be non-delegated. EXPECT_NE(4, frame.render_passes[0]->id.layer_id); - EXPECT_EQ(0, frame.render_passes[0]->id.index); + EXPECT_EQ(0u, frame.render_passes[0]->id.index); EXPECT_NE(4, frame.render_passes[3]->id.layer_id); - EXPECT_EQ(0, frame.render_passes[3]->id.index); + EXPECT_EQ(0u, frame.render_passes[3]->id.index); EXPECT_NE(4, frame.render_passes[4]->id.layer_id); - EXPECT_EQ(0, frame.render_passes[4]->id.index); + EXPECT_EQ(0u, frame.render_passes[4]->id.index); // The DelegatedRendererLayer should have added its RenderPasses to the frame // in order. @@ -342,9 +336,9 @@ TEST_F(DelegatedRendererLayerImplTestSimple, // The DelegatedRendererLayer should have added its contributing RenderPasses // to the frame. EXPECT_EQ(4, frame.render_passes[1]->id.layer_id); - EXPECT_EQ(1, frame.render_passes[1]->id.index); + EXPECT_EQ(1u, frame.render_passes[1]->id.index); EXPECT_EQ(4, frame.render_passes[2]->id.layer_id); - EXPECT_EQ(2, frame.render_passes[2]->id.index); + EXPECT_EQ(2u, frame.render_passes[2]->id.index); // The DelegatedRendererLayer should have added copies of its quads to // contributing RenderPasses. @@ -408,21 +402,26 @@ TEST_F(DelegatedRendererLayerImplTestSimple, gfx::Transform transform; transform.Translate(4.0, 4.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - transform, frame.render_passes[3]->quad_list.front()->quadTransform()); + transform, frame.render_passes[3] + ->quad_list.front() + ->shared_quad_state->quad_to_target_transform); // Quads from non-root RenderPasses should not be shifted though. ASSERT_EQ(2u, frame.render_passes[2]->quad_list.size()); EXPECT_TRANSFORMATION_MATRIX_EQ( - gfx::Transform(), - frame.render_passes[2]->quad_list.front()->quadTransform()); + gfx::Transform(), frame.render_passes[2] + ->quad_list.front() + ->shared_quad_state->quad_to_target_transform); EXPECT_TRANSFORMATION_MATRIX_EQ( - gfx::Transform(), - frame.render_passes[2]->quad_list.ElementAt(1)->quadTransform()); + gfx::Transform(), frame.render_passes[2] + ->quad_list.ElementAt(1) + ->shared_quad_state->quad_to_target_transform); ASSERT_EQ(1u, frame.render_passes[1]->quad_list.size()); EXPECT_TRANSFORMATION_MATRIX_EQ( - gfx::Transform(), - frame.render_passes[1]->quad_list.front()->quadTransform()); + gfx::Transform(), frame.render_passes[1] + ->quad_list.front() + ->shared_quad_state->quad_to_target_transform); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -481,20 +480,20 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, AddsRenderPasses) { // The DelegatedRendererLayer should have added its contributing RenderPasses // to the frame. EXPECT_EQ(4, frame.render_passes[1]->id.layer_id); - EXPECT_EQ(1, frame.render_passes[1]->id.index); + EXPECT_EQ(1u, frame.render_passes[1]->id.index); EXPECT_EQ(4, frame.render_passes[2]->id.layer_id); - EXPECT_EQ(2, frame.render_passes[2]->id.index); + EXPECT_EQ(2u, frame.render_passes[2]->id.index); // The DelegatedRendererLayer should have added a RenderPass for its surface // to the frame. EXPECT_EQ(4, frame.render_passes[1]->id.layer_id); - EXPECT_EQ(0, frame.render_passes[3]->id.index); + EXPECT_EQ(0u, frame.render_passes[3]->id.index); // And all other RenderPasses should be non-delegated. EXPECT_NE(4, frame.render_passes[0]->id.layer_id); - EXPECT_EQ(0, frame.render_passes[0]->id.index); + EXPECT_EQ(0u, frame.render_passes[0]->id.index); EXPECT_NE(4, frame.render_passes[4]->id.layer_id); - EXPECT_EQ(0, frame.render_passes[4]->id.index); + EXPECT_EQ(0u, frame.render_passes[4]->id.index); EXPECT_NE(4, frame.render_passes[5]->id.layer_id); - EXPECT_EQ(0, frame.render_passes[5]->id.index); + EXPECT_EQ(0u, frame.render_passes[5]->id.index); // The DelegatedRendererLayer should have added its RenderPasses to the frame // in order. @@ -520,9 +519,9 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, // The DelegatedRendererLayer should have added its contributing RenderPasses // to the frame. EXPECT_EQ(4, frame.render_passes[1]->id.layer_id); - EXPECT_EQ(1, frame.render_passes[1]->id.index); + EXPECT_EQ(1u, frame.render_passes[1]->id.index); EXPECT_EQ(4, frame.render_passes[2]->id.layer_id); - EXPECT_EQ(2, frame.render_passes[2]->id.index); + EXPECT_EQ(2u, frame.render_passes[2]->id.index); // The DelegatedRendererLayer should have added copies of its quads to // contributing RenderPasses. @@ -583,22 +582,26 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, // Because the DelegatedRendererLayer owns a RenderSurfaceImpl, its root // RenderPass' quads do not need to be translated at all. EXPECT_TRANSFORMATION_MATRIX_EQ( - gfx::Transform(), - frame.render_passes[3]->quad_list.front()->quadTransform()); + gfx::Transform(), frame.render_passes[3] + ->quad_list.front() + ->shared_quad_state->quad_to_target_transform); // Quads from non-root RenderPasses should not be shifted either. ASSERT_EQ(2u, frame.render_passes[2]->quad_list.size()); EXPECT_TRANSFORMATION_MATRIX_EQ( - gfx::Transform(), - frame.render_passes[2]->quad_list.front()->quadTransform()); + gfx::Transform(), frame.render_passes[2] + ->quad_list.front() + ->shared_quad_state->quad_to_target_transform); EXPECT_TRANSFORMATION_MATRIX_EQ( - gfx::Transform(), - frame.render_passes[2]->quad_list.ElementAt(1)->quadTransform()); + gfx::Transform(), frame.render_passes[2] + ->quad_list.ElementAt(1) + ->shared_quad_state->quad_to_target_transform); ASSERT_EQ(1u, frame.render_passes[1]->quad_list.size()); EXPECT_TRANSFORMATION_MATRIX_EQ( - gfx::Transform(), - frame.render_passes[1]->quad_list.front()->quadTransform()); + gfx::Transform(), frame.render_passes[1] + ->quad_list.front() + ->shared_quad_state->quad_to_target_transform); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -625,7 +628,6 @@ class DelegatedRendererLayerImplTestTransform delegated_renderer_layer->SetPosition(gfx::Point(20, 20)); delegated_renderer_layer->SetBounds(gfx::Size(75, 75)); - delegated_renderer_layer->SetContentBounds(gfx::Size(75, 75)); delegated_renderer_layer->SetDrawsContent(true); gfx::Transform transform; transform.Scale(2.0, 2.0); @@ -634,7 +636,7 @@ class DelegatedRendererLayerImplTestTransform RenderPassList delegated_render_passes; - gfx::Size child_pass_content_bounds(7, 7); + gfx::Size child_pass_bounds(7, 7); gfx::Rect child_pass_rect(20, 20, 7, 7); gfx::Transform child_pass_transform; child_pass_transform.Scale(0.8f, 0.8f); @@ -649,14 +651,10 @@ class DelegatedRendererLayerImplTestTransform gfx::Transform()); SharedQuadState* shared_quad_state = pass->CreateAndAppendSharedQuadState(); - shared_quad_state->SetAll(child_pass_transform, - child_pass_content_bounds, - child_pass_rect, - child_pass_clip_rect, - child_pass_clipped, - 1.f, - SkXfermode::kSrcOver_Mode, - 0); + shared_quad_state->SetAll(child_pass_transform, child_pass_bounds, + child_pass_rect, child_pass_clip_rect, + child_pass_clipped, 1.f, + SkXfermode::kSrcOver_Mode, 0); SolidColorDrawQuad* color_quad; color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -674,7 +672,7 @@ class DelegatedRendererLayerImplTestTransform false); } - gfx::Size root_pass_content_bounds(100, 100); + gfx::Size root_pass_bounds(100, 100); gfx::Rect root_pass_rect(0, 0, 100, 100); gfx::Transform root_pass_transform; root_pass_transform.Scale(1.5, 1.5); @@ -687,13 +685,9 @@ class DelegatedRendererLayerImplTestTransform root_pass_rect, gfx::Transform()); SharedQuadState* shared_quad_state = pass->CreateAndAppendSharedQuadState(); - shared_quad_state->SetAll(root_pass_transform, - root_pass_content_bounds, - root_pass_rect, - root_pass_clip_rect, - root_pass_clipped, - 1.f, - SkXfermode::kSrcOver_Mode, + shared_quad_state->SetAll(root_pass_transform, root_pass_bounds, + root_pass_rect, root_pass_clip_rect, + root_pass_clipped, 1.f, SkXfermode::kSrcOver_Mode, 0); RenderPassDrawQuad* render_pass_quad = @@ -756,10 +750,10 @@ class DelegatedRendererLayerImplTestTransform ASSERT_EQ(num_render_passes, frame.render_passes.size()); // The contributing render pass in the DelegatedRendererLayer. EXPECT_EQ(2, frame.render_passes[0]->id.layer_id); - EXPECT_EQ(1, frame.render_passes[0]->id.index); + EXPECT_EQ(1u, frame.render_passes[0]->id.index); // The root render pass. EXPECT_EQ(1, frame.render_passes.back()->id.layer_id); - EXPECT_EQ(0, frame.render_passes.back()->id.index); + EXPECT_EQ(0u, frame.render_passes.back()->id.index); const QuadList& contrib_delegated_quad_list = frame.render_passes[0]->quad_list; @@ -835,7 +829,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_NoSurface) { expected.Scale(1.5, 1.5); expected.Translate(7.0, 7.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, root_delegated_shared_quad_state->content_to_target_transform); + expected, root_delegated_shared_quad_state->quad_to_target_transform); // The contributing render pass should not be transformed from its input. EXPECT_EQ(gfx::Rect(21, 21, 3, 3).ToString(), @@ -845,8 +839,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_NoSurface) { expected.Scale(0.8f, 0.8f); expected.Translate(9.0, 9.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, - contrib_delegated_shared_quad_state->content_to_target_transform); + expected, contrib_delegated_shared_quad_state->quad_to_target_transform); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -894,7 +887,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_NoSurface) { expected.Scale(1.5, 1.5); expected.Translate(7.0, 7.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, root_delegated_shared_quad_state->content_to_target_transform); + expected, root_delegated_shared_quad_state->quad_to_target_transform); // The contributing render pass should not be transformed from its input. EXPECT_EQ(gfx::Rect(21, 21, 3, 3).ToString(), @@ -904,8 +897,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_NoSurface) { expected.Scale(0.8f, 0.8f); expected.Translate(9.0, 9.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, - contrib_delegated_shared_quad_state->content_to_target_transform); + expected, contrib_delegated_shared_quad_state->quad_to_target_transform); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -943,7 +935,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_Surface) { expected.Scale(3.0, 3.0); expected.Translate(7.0, 7.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, root_delegated_shared_quad_state->content_to_target_transform); + expected, root_delegated_shared_quad_state->quad_to_target_transform); // The contributing render pass should not be transformed from its input. EXPECT_EQ(gfx::Rect(21, 21, 3, 3).ToString(), @@ -953,8 +945,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_Surface) { expected.Scale(0.8f, 0.8f); expected.Translate(9.0, 9.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, - contrib_delegated_shared_quad_state->content_to_target_transform); + expected, contrib_delegated_shared_quad_state->quad_to_target_transform); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -991,7 +982,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_Surface) { expected.Scale(3.0, 3.0); expected.Translate(7.0, 7.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, root_delegated_shared_quad_state->content_to_target_transform); + expected, root_delegated_shared_quad_state->quad_to_target_transform); // The contributing render pass should not be transformed from its input. EXPECT_EQ(gfx::Rect(21, 21, 3, 3).ToString(), @@ -1001,8 +992,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_Surface) { expected.Scale(0.8f, 0.8f); expected.Translate(9.0, 9.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, - contrib_delegated_shared_quad_state->content_to_target_transform); + expected, contrib_delegated_shared_quad_state->quad_to_target_transform); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -1041,7 +1031,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, MismatchedDeviceScaleFactor) { expected.Scale(1.5, 1.5); expected.Translate(7.0, 7.0); EXPECT_TRANSFORMATION_MATRIX_EQ( - expected, root_delegated_shared_quad_state->content_to_target_transform); + expected, root_delegated_shared_quad_state->quad_to_target_transform); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -1066,12 +1056,11 @@ class DelegatedRendererLayerImplTestClip delegated_renderer_layer->SetPosition(gfx::Point(20, 20)); delegated_renderer_layer->SetBounds(gfx::Size(50, 50)); - delegated_renderer_layer->SetContentBounds(gfx::Size(50, 50)); delegated_renderer_layer->SetDrawsContent(true); RenderPassList delegated_render_passes; - gfx::Size child_pass_content_bounds(7, 7); + gfx::Size child_pass_bounds(7, 7); gfx::Rect child_pass_rect(20, 20, 7, 7); gfx::Transform child_pass_transform; gfx::Rect child_pass_clip_rect(21, 21, 3, 3); @@ -1084,14 +1073,10 @@ class DelegatedRendererLayerImplTestClip gfx::Transform()); SharedQuadState* shared_quad_state = pass->CreateAndAppendSharedQuadState(); - shared_quad_state->SetAll(child_pass_transform, - child_pass_content_bounds, - child_pass_rect, - child_pass_clip_rect, - child_pass_clipped, - 1.f, - SkXfermode::kSrcOver_Mode, - 0); + shared_quad_state->SetAll(child_pass_transform, child_pass_bounds, + child_pass_rect, child_pass_clip_rect, + child_pass_clipped, 1.f, + SkXfermode::kSrcOver_Mode, 0); SolidColorDrawQuad* color_quad; color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -1109,7 +1094,7 @@ class DelegatedRendererLayerImplTestClip false); } - gfx::Size root_pass_content_bounds(50, 50); + gfx::Size root_pass_bounds(50, 50); gfx::Rect root_pass_rect(0, 0, 50, 50); gfx::Transform root_pass_transform; gfx::Rect root_pass_clip_rect(5, 5, 40, 40); @@ -1120,13 +1105,9 @@ class DelegatedRendererLayerImplTestClip root_pass_rect, gfx::Transform()); SharedQuadState* shared_quad_state = pass->CreateAndAppendSharedQuadState(); - shared_quad_state->SetAll(root_pass_transform, - root_pass_content_bounds, - root_pass_rect, - root_pass_clip_rect, - root_pass_clipped, - 1.f, - SkXfermode::kSrcOver_Mode, + shared_quad_state->SetAll(root_pass_transform, root_pass_bounds, + root_pass_rect, root_pass_clip_rect, + root_pass_clipped, 1.f, SkXfermode::kSrcOver_Mode, 0); RenderPassDrawQuad* render_pass_quad = @@ -1182,7 +1163,6 @@ class DelegatedRendererLayerImplTestClip clip_layer->SetPosition(clip_rect.origin()); clip_layer->SetBounds(clip_rect.size()); - clip_layer->SetContentBounds(clip_rect.size()); clip_layer->SetMasksToBounds(true); origin_layer->SetPosition( @@ -1454,7 +1434,6 @@ TEST_F(DelegatedRendererLayerImplTest, Occlusion) { FakeDelegatedRendererLayerImpl* delegated_renderer_layer_impl = impl.AddChildToRoot<FakeDelegatedRendererLayerImpl>(); delegated_renderer_layer_impl->SetBounds(layer_size); - delegated_renderer_layer_impl->SetContentBounds(layer_size); delegated_renderer_layer_impl->SetDrawsContent(true); // Contributing render pass is offset by a transform and holds a quad that @@ -1513,7 +1492,7 @@ TEST_F(DelegatedRendererLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); { - gfx::Rect occluded(delegated_renderer_layer_impl->visible_content_rect()); + gfx::Rect occluded(delegated_renderer_layer_impl->visible_layer_rect()); SCOPED_TRACE("Root render pass"); impl.AppendQuadsForPassWithOcclusion(delegated_renderer_layer_impl, pass1, @@ -1523,7 +1502,7 @@ TEST_F(DelegatedRendererLayerImplTest, Occlusion) { EXPECT_EQ(pass1->quad_list.size(), 0u); } { - gfx::Rect occluded(delegated_renderer_layer_impl->visible_content_rect()); + gfx::Rect occluded(delegated_renderer_layer_impl->visible_layer_rect()); SCOPED_TRACE("Contributing render pass"); impl.AppendQuadsForPassWithOcclusion(delegated_renderer_layer_impl, pass2, @@ -1583,6 +1562,9 @@ TEST_F(DelegatedRendererLayerImplTest, Occlusion) { gfx::Transform layer_transform; layer_transform.Translate(11.0, 0.0); delegated_renderer_layer_impl->SetTransform(layer_transform); + delegated_renderer_layer_impl->layer_tree_impl() + ->property_trees() + ->needs_rebuild = true; occlusion_in_target_of_delegated_quad += gfx::Vector2d(11, 0); @@ -1619,7 +1601,6 @@ TEST_F(DelegatedRendererLayerImplTest, DeviceScaleFactorOcclusion) { FakeDelegatedRendererLayerImpl* delegated_renderer_layer_impl = impl.AddChildToRoot<FakeDelegatedRendererLayerImpl>(); delegated_renderer_layer_impl->SetBounds(layer_size); - delegated_renderer_layer_impl->SetContentBounds(layer_size); delegated_renderer_layer_impl->SetDrawsContent(true); // Contributing render pass is offset by a transform and holds a quad that @@ -1677,7 +1658,6 @@ TEST_F(DelegatedRendererLayerImplTest, PushPropertiesTo) { scoped_ptr<FakeDelegatedRendererLayerImpl> delegated_renderer_layer_impl = FakeDelegatedRendererLayerImpl::Create(host_impl_->active_tree(), 5); delegated_renderer_layer_impl->SetBounds(layer_size); - delegated_renderer_layer_impl->SetContentBounds(layer_size); delegated_renderer_layer_impl->SetDrawsContent(true); RenderPassList delegated_render_passes; diff --git a/chromium/cc/layers/delegated_renderer_layer_unittest.cc b/chromium/cc/layers/delegated_renderer_layer_unittest.cc index f243d73c260..ad4a345fc0f 100644 --- a/chromium/cc/layers/delegated_renderer_layer_unittest.cc +++ b/chromium/cc/layers/delegated_renderer_layer_unittest.cc @@ -11,6 +11,7 @@ #include "cc/test/fake_delegated_renderer_layer.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_proxy.h" +#include "cc/test/test_task_graph_runner.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -23,13 +24,15 @@ class DelegatedRendererLayerTest : public testing::Test { LayerTreeSettings settings; settings.minimum_occlusion_tracking_size = gfx::Size(); - host_impl_ = FakeLayerTreeHost::Create(&host_client_, settings); + host_impl_ = + FakeLayerTreeHost::Create(&host_client_, &task_graph_runner_, settings); host_impl_->SetViewportSize(gfx::Size(10, 10)); } protected: FakeProxy proxy_; FakeLayerTreeHostClient host_client_; + TestTaskGraphRunner task_graph_runner_; TestSharedBitmapManager shared_bitmap_manager_; scoped_ptr<LayerTreeHost> host_impl_; }; @@ -44,10 +47,11 @@ class DelegatedRendererLayerTestSimple : public DelegatedRendererLayerTest { frame_data->render_pass_list.push_back(root_pass.Pass()); resources_ = new DelegatedFrameResourceCollection; provider_ = new DelegatedFrameProvider(resources_, frame_data.Pass()); - root_layer_ = SolidColorLayer::Create(); - layer_before_ = SolidColorLayer::Create(); + LayerSettings layer_settings; + root_layer_ = SolidColorLayer::Create(layer_settings); + layer_before_ = SolidColorLayer::Create(layer_settings); delegated_renderer_layer_ = - FakeDelegatedRendererLayer::Create(provider_.get()); + FakeDelegatedRendererLayer::Create(layer_settings, provider_.get()); } protected: diff --git a/chromium/cc/layers/draw_properties.h b/chromium/cc/layers/draw_properties.h index 3dfb203b33b..5a07af04e32 100644 --- a/chromium/cc/layers/draw_properties.h +++ b/chromium/cc/layers/draw_properties.h @@ -27,25 +27,17 @@ struct CC_EXPORT DrawProperties { can_use_lcd_text(false), is_clipped(false), render_target(nullptr), - contents_scale_x(1.f), - contents_scale_y(1.f), num_unclipped_descendants(0), layer_or_descendant_has_copy_request(false), layer_or_descendant_has_input_handler(false), - layer_or_descendant_is_drawn(false), has_child_with_a_scroll_parent(false), - sorted_for_recursion(false), - visited(false), index_of_first_descendants_addition(0), num_descendants_added(0), index_of_first_render_surface_layer_list_addition(0), num_render_surfaces_added(0), last_drawn_render_surface_layer_list_id(0), - ideal_contents_scale(0.f), maximum_animation_contents_scale(0.f), - starting_animation_contents_scale(0.f), - page_scale_factor(0.f), - device_scale_factor(0.f) {} + starting_animation_contents_scale(0.f) {} // Transforms objects from content space to target surface space, where // this layer would be drawn. @@ -86,8 +78,9 @@ struct CC_EXPORT DrawProperties { // ancestor of this layer. LayerType* render_target; - // This rect is in the layer's content space. - gfx::Rect visible_content_rect; + // This rect is a bounding box around what part of the layer is visible, in + // the layer's coordinate space. + gfx::Rect visible_layer_rect; // In target surface space, the rect that encloses the clipped, drawable // content of the layer. @@ -97,17 +90,9 @@ struct CC_EXPORT DrawProperties { // value is used to avoid unnecessarily changing GL scissor state. gfx::Rect clip_rect; - // The scale used to move between layer space and content space, and bounds - // of the space. One is always a function of the other, but which one - // depends on the layer type. For picture layers, this is an ideal scale, - // and not always the one used. - float contents_scale_x; - float contents_scale_y; - gfx::Size content_bounds; - // Number of descendants with a clip parent that is our ancestor. NB - this // does not include our clip children because they are clipped by us. - int num_unclipped_descendants; + size_t num_unclipped_descendants; // If true, the layer or some layer in its sub-tree has a CopyOutputRequest // present on it. @@ -116,22 +101,12 @@ struct CC_EXPORT DrawProperties { // If true, the layer or one of its descendants has a wheel or touch handler. bool layer_or_descendant_has_input_handler; - // If true, the layer or one of its descendants is drawn - bool layer_or_descendant_is_drawn; - // This is true if the layer has any direct child that has a scroll parent. // This layer will not be the scroll parent in this case. This information // lets us avoid work in CalculateDrawPropertiesInternal -- if none of our // children have scroll parents, we will not need to recur out of order. bool has_child_with_a_scroll_parent; - // This is true if the order (wrt to its siblings in the tree) in which the - // layer will be visited while computing draw properties has been determined. - bool sorted_for_recursion; - - // This is used to sanity-check CDP and ensure that we don't revisit a layer. - bool visited; - // If this layer is visited out of order, its contribution to the descendant // and render surface layer lists will be put aside in a temporary list. // These values will allow for an efficient reordering of these additions. @@ -149,10 +124,6 @@ struct CC_EXPORT DrawProperties { // of date or 0. int last_drawn_render_surface_layer_list_id; - // The scale at which content for the layer should be rastered in order to be - // perfectly crisp. - float ideal_contents_scale; - // The maximum scale during the layers current animation at which content // should be rastered at to be crisp. float maximum_animation_contents_scale; @@ -160,13 +131,6 @@ struct CC_EXPORT DrawProperties { // The scale during the layer animation start at which content should be // rastered at to be crisp. float starting_animation_contents_scale; - - // The page scale factor that is applied to the layer. Since some layers may - // have page scale applied and others not, this may differ between layers. - float page_scale_factor; - - // The device scale factor that is applied to the layer. - float device_scale_factor; }; } // namespace cc diff --git a/chromium/cc/layers/heads_up_display_layer.cc b/chromium/cc/layers/heads_up_display_layer.cc index 5dd4bd24d52..388c2ad2473 100644 --- a/chromium/cc/layers/heads_up_display_layer.cc +++ b/chromium/cc/layers/heads_up_display_layer.cc @@ -12,11 +12,13 @@ namespace cc { -scoped_refptr<HeadsUpDisplayLayer> HeadsUpDisplayLayer::Create() { - return make_scoped_refptr(new HeadsUpDisplayLayer()); +scoped_refptr<HeadsUpDisplayLayer> HeadsUpDisplayLayer::Create( + const LayerSettings& settings) { + return make_scoped_refptr(new HeadsUpDisplayLayer(settings)); } -HeadsUpDisplayLayer::HeadsUpDisplayLayer() { +HeadsUpDisplayLayer::HeadsUpDisplayLayer(const LayerSettings& settings) + : Layer(settings) { SetIsDrawable(true); UpdateDrawsContent(HasDrawableContent()); } diff --git a/chromium/cc/layers/heads_up_display_layer.h b/chromium/cc/layers/heads_up_display_layer.h index ddc34f286d8..0760353ed9f 100644 --- a/chromium/cc/layers/heads_up_display_layer.h +++ b/chromium/cc/layers/heads_up_display_layer.h @@ -15,7 +15,8 @@ namespace cc { class CC_EXPORT HeadsUpDisplayLayer : public Layer { public: - static scoped_refptr<HeadsUpDisplayLayer> Create(); + static scoped_refptr<HeadsUpDisplayLayer> Create( + const LayerSettings& settings); void PrepareForCalculateDrawProperties( const gfx::Size& device_viewport, float device_scale_factor); @@ -23,7 +24,7 @@ class CC_EXPORT HeadsUpDisplayLayer : public Layer { scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; protected: - HeadsUpDisplayLayer(); + explicit HeadsUpDisplayLayer(const LayerSettings& settings); bool HasDrawableContent() const override; private: diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc index 986c332e406..dffa6d18d65 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.cc +++ b/chromium/cc/layers/heads_up_display_layer_impl.cc @@ -7,6 +7,7 @@ #include <algorithm> #include <vector> +#include "base/numerics/safe_conversions.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" @@ -129,7 +130,7 @@ bool HeadsUpDisplayLayerImpl::WillDraw(DrawMode draw_mode, if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) return false; - internal_contents_scale_ = draw_properties().ideal_contents_scale; + internal_contents_scale_ = GetIdealContentsScale(); internal_content_bounds_ = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), internal_contents_scale_)); @@ -225,6 +226,7 @@ void HeadsUpDisplayLayerImpl::ReleaseResources() { } gfx::Rect HeadsUpDisplayLayerImpl::GetEnclosingRectInTargetSpace() const { + DCHECK_GT(internal_contents_scale_, 0.f); return GetScaledEnclosingRectInTargetSpace(internal_contents_scale_); } @@ -383,7 +385,8 @@ SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay( const int kFontHeight = 15; - const int kGraphWidth = fps_counter->time_stamp_history_size() - 2; + const int kGraphWidth = + base::saturated_cast<int>(fps_counter->time_stamp_history_size()) - 2; const int kGraphHeight = 40; const int kHistogramWidth = 37; @@ -625,7 +628,8 @@ SkRect HeadsUpDisplayLayerImpl::DrawPaintTimeDisplay( const int kPadding = 4; const int kFontHeight = 14; - const int kGraphWidth = paint_time_counter->HistorySize(); + const int kGraphWidth = + base::saturated_cast<int>(paint_time_counter->HistorySize()); const int kGraphHeight = 40; SkPaint paint = CreatePaint(); diff --git a/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc b/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc index ab38fdd087d..ad2215595aa 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc +++ b/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc @@ -8,6 +8,7 @@ #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/fake_output_surface.h" #include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -32,13 +33,14 @@ void CheckDrawLayer(HeadsUpDisplayLayerImpl* layer, TEST(HeadsUpDisplayLayerImplTest, ResourcelessSoftwareDrawAfterResourceLoss) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); scoped_ptr<HeadsUpDisplayLayerImpl> layer = HeadsUpDisplayLayerImpl::Create(host_impl.pending_tree(), 1); layer->SetBounds(gfx::Size(100, 100)); - layer->draw_properties().ideal_contents_scale = 1.f; // Check regular hardware draw is ok. CheckDrawLayer( diff --git a/chromium/cc/layers/heads_up_display_unittest.cc b/chromium/cc/layers/heads_up_display_unittest.cc index 312e482ff2d..532a169c368 100644 --- a/chromium/cc/layers/heads_up_display_unittest.cc +++ b/chromium/cc/layers/heads_up_display_unittest.cc @@ -26,7 +26,7 @@ class DrawsContentLayer : public Layer { bool DrawsContent() const override { return true; } private: - DrawsContentLayer() : Layer() {} + DrawsContentLayer() : Layer(LayerSettings()) {} ~DrawsContentLayer() override {} }; diff --git a/chromium/cc/layers/image_layer.cc b/chromium/cc/layers/image_layer.cc deleted file mode 100644 index 67e620c6e2e..00000000000 --- a/chromium/cc/layers/image_layer.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2010 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/layers/image_layer.h" - -#include "base/compiler_specific.h" -#include "cc/resources/image_layer_updater.h" -#include "cc/resources/layer_updater.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/resource_update_queue.h" -#include "cc/trees/layer_tree_host.h" - -namespace cc { - -scoped_refptr<ImageLayer> ImageLayer::Create() { - return make_scoped_refptr(new ImageLayer()); -} - -ImageLayer::ImageLayer() : TiledLayer() {} - -ImageLayer::~ImageLayer() {} - -void ImageLayer::SetBitmap(const SkBitmap& bitmap) { - // SetBitmap() currently gets called whenever there is any - // style change that affects the layer even if that change doesn't - // affect the actual contents of the image (e.g. a CSS animation). - // With this check in place we avoid unecessary texture uploads. - if (bitmap.pixelRef() && bitmap.pixelRef() == bitmap_.pixelRef()) - return; - - bitmap_ = bitmap; - UpdateDrawsContent(HasDrawableContent()); - SetNeedsDisplay(); -} - -bool ImageLayer::HasDrawableContent() const { - return !bitmap_.isNull() && TiledLayer::HasDrawableContent(); -} - -void ImageLayer::SetTexturePriorities(const PriorityCalculator& priority_calc) { - // Update the tile data before creating all the layer's tiles. - UpdateTileSizeAndTilingOption(); - - TiledLayer::SetTexturePriorities(priority_calc); -} - -bool ImageLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - CreateUpdaterIfNeeded(); - if (!updater_->UsingBitmap(bitmap_)) { - updater_->SetBitmap(bitmap_); - UpdateTileSizeAndTilingOption(); - InvalidateContentRect(gfx::Rect(content_bounds())); - } - return TiledLayer::Update(queue, occlusion); -} - -void ImageLayer::CreateUpdaterIfNeeded() { - if (updater_.get()) - return; - - updater_ = ImageLayerUpdater::Create(); - SetTextureFormat( - layer_tree_host()->GetRendererCapabilities().best_texture_format); -} - -LayerUpdater* ImageLayer::Updater() const { - return updater_.get(); -} - -void ImageLayer::CalculateContentsScale(float ideal_contents_scale, - float* contents_scale_x, - float* contents_scale_y, - gfx::Size* content_bounds) { - *contents_scale_x = ImageContentsScaleX(); - *contents_scale_y = ImageContentsScaleY(); - *content_bounds = gfx::Size(bitmap_.width(), bitmap_.height()); -} - -void ImageLayer::OnOutputSurfaceCreated() { - SetTextureFormat( - layer_tree_host()->GetRendererCapabilities().best_texture_format); - TiledLayer::OnOutputSurfaceCreated(); -} - -float ImageLayer::ImageContentsScaleX() const { - if (bounds().IsEmpty() || bitmap_.width() == 0) - return 1; - return static_cast<float>(bitmap_.width()) / bounds().width(); -} - -float ImageLayer::ImageContentsScaleY() const { - if (bounds().IsEmpty() || bitmap_.height() == 0) - return 1; - return static_cast<float>(bitmap_.height()) / bounds().height(); -} - -} // namespace cc diff --git a/chromium/cc/layers/image_layer.h b/chromium/cc/layers/image_layer.h deleted file mode 100644 index ed2a2a3bd89..00000000000 --- a/chromium/cc/layers/image_layer.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_LAYERS_IMAGE_LAYER_H_ -#define CC_LAYERS_IMAGE_LAYER_H_ - -#include "cc/base/cc_export.h" -#include "cc/layers/content_layer.h" -#include "third_party/skia/include/core/SkBitmap.h" - -namespace cc { - -class ImageLayerUpdater; - -// A Layer that contains only an Image element. -class CC_EXPORT ImageLayer : public TiledLayer { - public: - static scoped_refptr<ImageLayer> Create(); - - // Layer implementation. - void SetTexturePriorities(const PriorityCalculator& priority_calc) override; - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; - void CalculateContentsScale(float ideal_contents_scale, - float* contents_scale_x, - float* contents_scale_y, - gfx::Size* content_bounds) override; - void OnOutputSurfaceCreated() override; - - void SetBitmap(const SkBitmap& image); - - protected: - bool HasDrawableContent() const override; - - private: - ImageLayer(); - ~ImageLayer() override; - - // TiledLayer Implementation. - LayerUpdater* Updater() const override; - void CreateUpdaterIfNeeded() override; - - float ImageContentsScaleX() const; - float ImageContentsScaleY() const; - - SkBitmap bitmap_; - - scoped_refptr<ImageLayerUpdater> updater_; - - DISALLOW_COPY_AND_ASSIGN(ImageLayer); -}; - -} // namespace cc - -#endif // CC_LAYERS_IMAGE_LAYER_H_ diff --git a/chromium/cc/layers/io_surface_layer.cc b/chromium/cc/layers/io_surface_layer.cc index 05d5fb90f04..c2e35304b60 100644 --- a/chromium/cc/layers/io_surface_layer.cc +++ b/chromium/cc/layers/io_surface_layer.cc @@ -8,11 +8,14 @@ namespace cc { -scoped_refptr<IOSurfaceLayer> IOSurfaceLayer::Create() { - return make_scoped_refptr(new IOSurfaceLayer()); +scoped_refptr<IOSurfaceLayer> IOSurfaceLayer::Create( + const LayerSettings& settings) { + return make_scoped_refptr(new IOSurfaceLayer(settings)); } -IOSurfaceLayer::IOSurfaceLayer() : Layer(), io_surface_id_(0) {} +IOSurfaceLayer::IOSurfaceLayer(const LayerSettings& settings) + : Layer(settings), io_surface_id_(0) { +} IOSurfaceLayer::~IOSurfaceLayer() {} @@ -41,10 +44,8 @@ void IOSurfaceLayer::PushPropertiesTo(LayerImpl* layer) { io_surface_layer->SetIOSurfaceProperties(io_surface_id_, io_surface_size_); } -bool IOSurfaceLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - bool updated = Layer::Update(queue, occlusion); - +bool IOSurfaceLayer::Update() { + bool updated = Layer::Update(); // This layer doesn't update any resources from the main thread side, // but repaint rects need to be sent to the layer impl via commit. return updated || !update_rect_.IsEmpty(); diff --git a/chromium/cc/layers/io_surface_layer.h b/chromium/cc/layers/io_surface_layer.h index 90bcf3e8323..14eabd98a1e 100644 --- a/chromium/cc/layers/io_surface_layer.h +++ b/chromium/cc/layers/io_surface_layer.h @@ -12,18 +12,17 @@ namespace cc { class CC_EXPORT IOSurfaceLayer : public Layer { public: - static scoped_refptr<IOSurfaceLayer> Create(); + static scoped_refptr<IOSurfaceLayer> Create(const LayerSettings& settings); void SetIOSurfaceProperties(uint32_t io_surface_id, const gfx::Size& size); scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void PushPropertiesTo(LayerImpl* layer) override; - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; + bool Update() override; protected: bool HasDrawableContent() const override; - IOSurfaceLayer(); + explicit IOSurfaceLayer(const LayerSettings& settings); private: ~IOSurfaceLayer() override; diff --git a/chromium/cc/layers/io_surface_layer_impl.cc b/chromium/cc/layers/io_surface_layer_impl.cc index a7da986859d..234d3f3a767 100644 --- a/chromium/cc/layers/io_surface_layer_impl.cc +++ b/chromium/cc/layers/io_surface_layer_impl.cc @@ -66,10 +66,10 @@ void IOSurfaceLayerImpl::AppendQuads( render_pass->CreateAndAppendSharedQuadState(); PopulateSharedQuadState(shared_quad_state); - AppendDebugBorderQuad( - render_pass, content_bounds(), shared_quad_state, append_quads_data); + AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state, + append_quads_data); - gfx::Rect quad_rect(content_bounds()); + gfx::Rect quad_rect(bounds()); gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect()); gfx::Rect visible_quad_rect = draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( diff --git a/chromium/cc/layers/io_surface_layer_impl_unittest.cc b/chromium/cc/layers/io_surface_layer_impl_unittest.cc index 1c9256c2551..75c2cf77f83 100644 --- a/chromium/cc/layers/io_surface_layer_impl_unittest.cc +++ b/chromium/cc/layers/io_surface_layer_impl_unittest.cc @@ -19,7 +19,6 @@ TEST(IOSurfaceLayerImplTest, Occlusion) { IOSurfaceLayerImpl* io_surface_layer_impl = impl.AddChildToRoot<IOSurfaceLayerImpl>(); io_surface_layer_impl->SetBounds(layer_size); - io_surface_layer_impl->SetContentBounds(layer_size); io_surface_layer_impl->SetDrawsContent(true); io_surface_layer_impl->SetIOSurfaceProperties(1, gfx::Size(1, 1)); @@ -40,7 +39,7 @@ TEST(IOSurfaceLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(io_surface_layer_impl->visible_content_rect()); + gfx::Rect occluded(io_surface_layer_impl->visible_layer_rect()); impl.AppendQuadsWithOcclusion(io_surface_layer_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc index 9a10f5d55be..b9867d6217c 100644 --- a/chromium/cc/layers/layer.cc +++ b/chromium/cc/layers/layer.cc @@ -34,13 +34,13 @@ namespace cc { base::StaticAtomicSequenceNumber g_next_layer_id; -scoped_refptr<Layer> Layer::Create() { - return make_scoped_refptr(new Layer()); +scoped_refptr<Layer> Layer::Create(const LayerSettings& settings) { + return make_scoped_refptr(new Layer(settings)); } -Layer::Layer() +Layer::Layer(const LayerSettings& settings) : needs_push_properties_(false), - num_dependents_need_push_properties_(false), + num_dependents_need_push_properties_(0), stacking_order_changed_(false), // Layer IDs start from 1. layer_id_(g_next_layer_id.GetNext() + 1), @@ -56,6 +56,7 @@ Layer::Layer() property_tree_sequence_number_(-1), num_layer_or_descendants_with_copy_request_(0), num_layer_or_descendants_with_input_handler_(0), + num_children_with_scroll_parent_(0), should_flatten_transform_from_property_tree_(false), should_scroll_on_main_thread_(false), have_wheel_event_handlers_(false), @@ -81,14 +82,18 @@ Layer::Layer() opacity_(1.f), blend_mode_(SkXfermode::kSrcOver_Mode), scroll_parent_(nullptr), + layer_or_descendant_is_drawn_tracker_(0), + sorted_for_recursion_tracker_(0), + visited_tracker_(0), clip_parent_(nullptr), replica_layer_(nullptr), - raster_scale_(0.f), client_(nullptr), frame_timing_requests_dirty_(false) { - layer_animation_controller_ = LayerAnimationController::Create(layer_id_); - layer_animation_controller_->AddValueObserver(this); - layer_animation_controller_->set_value_provider(this); + if (!settings.use_compositor_animation_timelines) { + layer_animation_controller_ = LayerAnimationController::Create(layer_id_); + layer_animation_controller_->AddValueObserver(this); + layer_animation_controller_->set_value_provider(this); + } } Layer::~Layer() { @@ -99,8 +104,10 @@ Layer::~Layer() { // reference to us. DCHECK(!layer_tree_host()); - layer_animation_controller_->RemoveValueObserver(this); - layer_animation_controller_->remove_value_provider(this); + if (layer_animation_controller_) { + layer_animation_controller_->RemoveValueObserver(this); + layer_animation_controller_->remove_value_provider(this); + } RemoveFromScrollTree(); RemoveFromClipTree(); @@ -121,11 +128,14 @@ void Layer::SetLayerTreeHost(LayerTreeHost* host) { if (layer_tree_host_ == host) return; - if (layer_tree_host_) + if (layer_tree_host_) { layer_tree_host_->property_trees()->needs_rebuild = true; - - if (host) + layer_tree_host_->UnregisterLayer(this); + } + if (host) { host->property_trees()->needs_rebuild = true; + host->RegisterLayer(this); + } InvalidatePropertyTreesIndices(); @@ -143,15 +153,16 @@ void Layer::SetLayerTreeHost(LayerTreeHost* host) { if (replica_layer_.get()) replica_layer_->SetLayerTreeHost(host); - if (host) { - layer_animation_controller_->SetAnimationRegistrar( - host->animation_registrar()); + if (host) + RegisterForAnimations(host->animation_registrar()); - if (host->settings().layer_transforms_should_scale_layer_contents) - reset_raster_scale_to_unknown(); - } + bool has_any_animation = false; + if (layer_animation_controller_) + has_any_animation = layer_animation_controller_->has_any_animation(); + else if (layer_tree_host_) + has_any_animation = layer_tree_host_->HasAnyAnimation(this); - if (host && layer_animation_controller_->has_any_animation()) + if (host && has_any_animation) host->SetNeedsCommit(); } @@ -234,15 +245,6 @@ bool Layer::IsPropertyChangeAllowed() const { return !layer_tree_host_->in_paint_layer_contents(); } -gfx::Rect Layer::LayerRectToContentRect(const gfx::Rect& layer_rect) const { - gfx::Rect content_rect = gfx::ScaleToEnclosingRect( - layer_rect, contents_scale_x(), contents_scale_y()); - // Intersect with content rect to avoid the extra pixel because for some - // values x and y, ceil((x / y) * y) may be x + 1. - content_rect.Intersect(gfx::Rect(content_bounds())); - return content_rect; -} - skia::RefPtr<SkPicture> Layer::GetPicture() const { return skia::RefPtr<SkPicture>(); } @@ -264,16 +266,6 @@ void Layer::SetParent(Layer* layer) { return; layer_tree_host_->property_trees()->needs_rebuild = true; - - const LayerTreeSettings& settings = layer_tree_host_->settings(); - if (!settings.layer_transforms_should_scale_layer_contents) - return; - - reset_raster_scale_to_unknown(); - if (mask_layer_.get()) - mask_layer_->reset_raster_scale_to_unknown(); - if (replica_layer_.get() && replica_layer_->mask_layer_.get()) - replica_layer_->mask_layer_->reset_raster_scale_to_unknown(); } void Layer::AddChild(scoped_refptr<Layer> child) { @@ -336,12 +328,14 @@ void Layer::ReplaceChild(Layer* reference, scoped_refptr<Layer> new_layer) { if (reference == new_layer.get()) return; - int reference_index = IndexOfChild(reference); - if (reference_index == -1) { - NOTREACHED(); - return; - } - + // Find the index of |reference| in |children_|. + auto reference_it = + std::find_if(children_.begin(), children_.end(), + [reference](const scoped_refptr<Layer>& layer) { + return layer.get() == reference; + }); + DCHECK(reference_it != children_.end()); + size_t reference_index = reference_it - children_.begin(); reference->RemoveFromParent(); if (new_layer.get()) { @@ -350,14 +344,6 @@ void Layer::ReplaceChild(Layer* reference, scoped_refptr<Layer> new_layer) { } } -int Layer::IndexOfChild(const Layer* reference) { - for (size_t i = 0; i < children_.size(); ++i) { - if (children_[i].get() == reference) - return i; - } - return -1; -} - void Layer::SetBounds(const gfx::Size& size) { DCHECK(IsPropertyChangeAllowed()); if (bounds() == size) @@ -415,7 +401,7 @@ bool Layer::HasAncestor(const Layer* ancestor) const { void Layer::RequestCopyOfOutput( scoped_ptr<CopyOutputRequest> request) { DCHECK(IsPropertyChangeAllowed()); - int size = copy_requests_.size(); + bool had_no_copy_requests = copy_requests_.empty(); if (void* source = request->source()) { auto it = std::find_if( copy_requests_.begin(), copy_requests_.end(), @@ -426,7 +412,7 @@ void Layer::RequestCopyOfOutput( if (request->IsEmpty()) return; copy_requests_.push_back(request.Pass()); - if (size == 0) { + if (had_no_copy_requests) { bool copy_request_added = true; UpdateNumCopyRequestsForSubtree(copy_request_added); } @@ -470,17 +456,6 @@ SkColor Layer::SafeOpaqueBackgroundColor() const { return color; } -void Layer::CalculateContentsScale(float ideal_contents_scale, - float* contents_scale_x, - float* contents_scale_y, - gfx::Size* content_bounds) { - DCHECK(layer_tree_host_); - - *contents_scale_x = 1; - *contents_scale_y = 1; - *content_bounds = bounds(); -} - void Layer::SetMasksToBounds(bool masks_to_bounds) { DCHECK(IsPropertyChangeAllowed()); if (masks_to_bounds_ == masks_to_bounds) @@ -533,7 +508,11 @@ void Layer::SetFilters(const FilterOperations& filters) { } bool Layer::FilterIsAnimating() const { - return layer_animation_controller_->IsAnimatingProperty(Animation::FILTER); + DCHECK(layer_tree_host_); + return layer_animation_controller_ + ? layer_animation_controller_->IsAnimatingProperty( + Animation::FILTER) + : layer_tree_host_->IsAnimatingFilterProperty(this); } void Layer::SetBackgroundFilters(const FilterOperations& filters) { @@ -553,7 +532,24 @@ void Layer::SetOpacity(float opacity) { } bool Layer::OpacityIsAnimating() const { - return layer_animation_controller_->IsAnimatingProperty(Animation::OPACITY); + DCHECK(layer_tree_host_); + return layer_animation_controller_ + ? layer_animation_controller_->IsAnimatingProperty( + Animation::OPACITY) + : layer_tree_host_->IsAnimatingOpacityProperty(this); +} + +bool Layer::HasPotentiallyRunningOpacityAnimation() const { + if (layer_animation_controller_) { + if (Animation* animation = + layer_animation_controller()->GetAnimation(Animation::OPACITY)) { + return !animation->is_finished(); + } + return false; + } else { + DCHECK(layer_tree_host_); + return layer_tree_host_->HasPotentiallyRunningOpacityAnimation(this); + } } bool Layer::OpacityCanAnimateOnImplThread() const { @@ -737,11 +733,39 @@ void Layer::SetTransformOrigin(const gfx::Point3F& transform_origin) { } bool Layer::AnimationsPreserveAxisAlignment() const { - return layer_animation_controller_->AnimationsPreserveAxisAlignment(); + DCHECK(layer_tree_host_); + return layer_animation_controller_ + ? layer_animation_controller_->AnimationsPreserveAxisAlignment() + : layer_tree_host_->AnimationsPreserveAxisAlignment(this); } bool Layer::TransformIsAnimating() const { - return layer_animation_controller_->IsAnimatingProperty(Animation::TRANSFORM); + DCHECK(layer_tree_host_); + return layer_animation_controller_ + ? layer_animation_controller_->IsAnimatingProperty( + Animation::TRANSFORM) + : layer_tree_host_->IsAnimatingTransformProperty(this); +} + +bool Layer::HasPotentiallyRunningTransformAnimation() const { + if (layer_animation_controller_) { + if (Animation* animation = + layer_animation_controller()->GetAnimation(Animation::TRANSFORM)) { + return !animation->is_finished(); + } + return false; + } else { + DCHECK(layer_tree_host_); + return layer_tree_host_->HasPotentiallyRunningTransformAnimation(this); + } +} + +bool Layer::ScrollOffsetAnimationWasInterrupted() const { + DCHECK(layer_tree_host_); + return layer_animation_controller_ + ? layer_animation_controller_ + ->scroll_offset_animation_was_interrupted() + : layer_tree_host_->ScrollOffsetAnimationWasInterrupted(this); } void Layer::SetScrollParent(Layer* parent) { @@ -764,6 +788,10 @@ void Layer::AddScrollChild(Layer* child) { if (!scroll_children_) scroll_children_.reset(new std::set<Layer*>); scroll_children_->insert(child); + if (layer_tree_host_ && !layer_tree_host_->needs_meta_info_recomputation()) { + num_children_with_scroll_parent_++; + draw_properties().has_child_with_a_scroll_parent = true; + } SetNeedsCommit(); } @@ -771,6 +799,12 @@ void Layer::RemoveScrollChild(Layer* child) { scroll_children_->erase(child); if (scroll_children_->empty()) scroll_children_ = nullptr; + if (layer_tree_host_ && !layer_tree_host_->needs_meta_info_recomputation()) { + num_children_with_scroll_parent_--; + DCHECK_GE(num_children_with_scroll_parent_, 0); + draw_properties().has_child_with_a_scroll_parent = + (num_children_with_scroll_parent_ != 0); + } SetNeedsCommit(); } @@ -820,8 +854,7 @@ void Layer::SetScrollOffset(const gfx::ScrollOffset& scroll_offset) { layer_tree_host_->property_trees()->transform_tree.Node( transform_tree_index())) { if (transform_node->owner_id == id()) { - transform_node->data.scroll_offset = - gfx::ScrollOffsetToVector2dF(CurrentScrollOffset()); + transform_node->data.scroll_offset = CurrentScrollOffset(); transform_node->data.needs_local_transform_update = true; layer_tree_host_->property_trees()->transform_tree.set_needs_update(true); SetNeedsCommitNoRebuild(); @@ -860,8 +893,7 @@ void Layer::SetScrollOffsetFromImplSide( layer_tree_host_->property_trees()->transform_tree.Node( transform_tree_index())) { if (transform_node->owner_id == id()) { - transform_node->data.scroll_offset = - gfx::ScrollOffsetToVector2dF(CurrentScrollOffset()); + transform_node->data.scroll_offset = CurrentScrollOffset(); transform_node->data.needs_local_transform_update = true; layer_tree_host_->property_trees()->transform_tree.set_needs_update(true); needs_rebuild = false; @@ -1146,25 +1178,19 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->SetBounds(use_paint_properties ? paint_properties_.bounds : bounds_); - // TODO(enne): This is needed because CDP does this. Once main thread CDP - // goes away, content scale / bounds can be removed. - if (layer_tree_host()->settings().impl_side_painting) { - layer->SetContentsScale(1.f, 1.f); - layer->SetContentBounds(bounds()); - } else { - layer->SetContentBounds(content_bounds()); - layer->SetContentsScale(contents_scale_x(), contents_scale_y()); - } - if (frame_viewer_instrumentation::IsTracingLayerTreeSnapshots()) layer->SetDebugInfo(TakeDebugInfo()); + layer->SetTransformTreeIndex(transform_tree_index()); + layer->SetOpacityTreeIndex(opacity_tree_index()); + layer->SetClipTreeIndex(clip_tree_index()); + layer->set_offset_to_transform_parent(offset_to_transform_parent_); layer->SetDoubleSided(double_sided_); layer->SetDrawCheckerboardForMissingTiles( draw_checkerboard_for_missing_tiles_); layer->SetDrawsContent(DrawsContent()); layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); - layer->SetHasRenderSurface(has_render_surface_ || layer->HasCopyRequest()); + layer->SetHasRenderSurface(has_render_surface_); if (!layer->FilterIsAnimatingOnImplOnly() && !FilterIsAnimating()) layer->SetFilters(filters_); DCHECK(!(FilterIsAnimating() && layer->FilterIsAnimatingOnImplOnly())); @@ -1195,10 +1221,6 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { DCHECK(!(TransformIsAnimating() && layer->TransformIsAnimatingOnImplOnly())); layer->Set3dSortingContextId(sorting_context_id_); layer->SetNumDescendantsThatDrawContent(num_descendants_that_draw_content_); - layer->SetTransformTreeIndex(transform_tree_index()); - layer->SetOpacityTreeIndex(opacity_tree_index()); - layer->SetClipTreeIndex(clip_tree_index()); - layer->set_offset_to_transform_parent(offset_to_transform_parent_); layer->SetScrollClipLayer(scroll_clip_layer_id_); layer->set_user_scrollable_horizontal(user_scrollable_horizontal_); @@ -1253,14 +1275,14 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { // the pending tree will clobber any impl-side scrolling occuring on the // active tree. To do so, avoid scrolling the pending tree along with it // instead of trying to undo that scrolling later. - if (layer_animation_controller_->scroll_offset_animation_was_interrupted()) + if (ScrollOffsetAnimationWasInterrupted()) layer->PushScrollOffsetFromMainThreadAndClobberActiveValue(scroll_offset_); else layer->PushScrollOffsetFromMainThread(scroll_offset_); layer->SetScrollCompensationAdjustment(ScrollCompensationAdjustment()); // Wrap the copy_requests_ in a PostTask to the main thread. - int size = copy_requests_.size(); + bool had_copy_requests = !copy_requests_.empty(); ScopedPtrVector<CopyOutputRequest> main_thread_copy_requests; for (ScopedPtrVector<CopyOutputRequest>::iterator it = copy_requests_.begin(); it != copy_requests_.end(); @@ -1279,7 +1301,7 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { } if (!copy_requests_.empty() && layer_tree_host_) layer_tree_host_->property_trees()->needs_rebuild = true; - if (size != 0) + if (had_copy_requests) UpdateNumCopyRequestsForSubtree(false); copy_requests_.clear(); layer->PassCopyRequests(&main_thread_copy_requests); @@ -1293,14 +1315,20 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->SetStackingOrderChanged(stacking_order_changed_); - layer_animation_controller_->PushAnimationUpdatesTo( - layer->layer_animation_controller()); + if (layer->layer_animation_controller() && layer_animation_controller_) + layer_animation_controller_->PushAnimationUpdatesTo( + layer->layer_animation_controller()); if (frame_timing_requests_dirty_) { - layer->PassFrameTimingRequests(&frame_timing_requests_); + layer->SetFrameTimingRequests(frame_timing_requests_); frame_timing_requests_dirty_ = false; } + bool is_page_scale_layer = this == layer_tree_host()->page_scale_layer(); + bool parent_affected = + layer->parent() && layer->parent()->IsAffectedByPageScale(); + layer->SetIsAffectedByPageScale(is_page_scale_layer || parent_affected); + // Reset any state that should be cleared for the next update. stacking_order_changed_ = false; update_rect_ = gfx::Rect(); @@ -1357,8 +1385,7 @@ void Layer::SavePaintProperties() { layer_tree_host_->source_frame_number(); } -bool Layer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { +bool Layer::Update() { DCHECK(layer_tree_host_); DCHECK_EQ(layer_tree_host_->source_frame_number(), paint_properties_.source_frame_number) << @@ -1423,8 +1450,10 @@ void Layer::OnOpacityAnimated(float opacity) { if (OpacityNode* node = layer_tree_host_->property_trees()->opacity_tree.Node( opacity_tree_index())) { - if (node->owner_id == id()) - node->data = opacity; + if (node->owner_id == id()) { + node->data.opacity = opacity; + layer_tree_host_->property_trees()->opacity_tree.set_needs_update(true); + } } } } @@ -1465,6 +1494,7 @@ bool Layer::IsActive() const { } bool Layer::AddAnimation(scoped_ptr <Animation> animation) { + DCHECK(layer_animation_controller_); if (!layer_animation_controller_->animation_registrar()) return false; @@ -1481,24 +1511,28 @@ bool Layer::AddAnimation(scoped_ptr <Animation> animation) { } void Layer::PauseAnimation(int animation_id, double time_offset) { + DCHECK(layer_animation_controller_); layer_animation_controller_->PauseAnimation( animation_id, base::TimeDelta::FromSecondsD(time_offset)); SetNeedsCommit(); } void Layer::RemoveAnimation(int animation_id) { + DCHECK(layer_animation_controller_); layer_animation_controller_->RemoveAnimation(animation_id); SetNeedsCommit(); } void Layer::RemoveAnimation(int animation_id, Animation::TargetProperty property) { + DCHECK(layer_animation_controller_); layer_animation_controller_->RemoveAnimation(animation_id, property); SetNeedsCommit(); } void Layer::SetLayerAnimationControllerForTest( scoped_refptr<LayerAnimationController> controller) { + DCHECK(layer_animation_controller_); layer_animation_controller_->RemoveValueObserver(this); layer_animation_controller_ = controller; layer_animation_controller_->AddValueObserver(this); @@ -1506,25 +1540,29 @@ void Layer::SetLayerAnimationControllerForTest( } bool Layer::HasActiveAnimation() const { - return layer_animation_controller_->HasActiveAnimation(); + DCHECK(layer_tree_host_); + return layer_animation_controller_ + ? layer_animation_controller_->HasActiveAnimation() + : layer_tree_host_->HasActiveAnimation(this); +} + +void Layer::RegisterForAnimations(AnimationRegistrar* registrar) { + if (layer_animation_controller_) + layer_animation_controller_->SetAnimationRegistrar(registrar); } void Layer::AddLayerAnimationEventObserver( LayerAnimationEventObserver* animation_observer) { + DCHECK(layer_animation_controller_); layer_animation_controller_->AddEventObserver(animation_observer); } void Layer::RemoveLayerAnimationEventObserver( LayerAnimationEventObserver* animation_observer) { + DCHECK(layer_animation_controller_); layer_animation_controller_->RemoveEventObserver(animation_observer); } -SimpleEnclosedRegion Layer::VisibleContentOpaqueRegion() const { - if (contents_opaque()) - return SimpleEnclosedRegion(visible_content_rect()); - return SimpleEnclosedRegion(); -} - ScrollbarLayerInterface* Layer::ToScrollbarLayer() { return nullptr; } @@ -1576,6 +1614,9 @@ bool Layer::HasDelegatedContent() const { void Layer::SetFrameTimingRequests( const std::vector<FrameTimingRequest>& requests) { + // TODO(vmpstr): Early out if there are no changes earlier in the call stack. + if (requests == frame_timing_requests_) + return; frame_timing_requests_ = requests; frame_timing_requests_dirty_ = true; SetNeedsCommit(); @@ -1589,4 +1630,39 @@ void Layer::DidBeginTracing() { SetNeedsPushProperties(); } +void Layer::set_visited(bool visited) { + visited_tracker_ = + visited ? layer_tree_host()->meta_information_sequence_number() : 0; +} + +bool Layer::visited() { + return visited_tracker_ == + layer_tree_host()->meta_information_sequence_number(); +} + +void Layer::set_layer_or_descendant_is_drawn( + bool layer_or_descendant_is_drawn) { + layer_or_descendant_is_drawn_tracker_ = + layer_or_descendant_is_drawn + ? layer_tree_host()->meta_information_sequence_number() + : 0; +} + +bool Layer::layer_or_descendant_is_drawn() { + return layer_or_descendant_is_drawn_tracker_ == + layer_tree_host()->meta_information_sequence_number(); +} + +void Layer::set_sorted_for_recursion(bool sorted_for_recursion) { + sorted_for_recursion_tracker_ = + sorted_for_recursion + ? layer_tree_host()->meta_information_sequence_number() + : 0; +} + +bool Layer::sorted_for_recursion() { + return sorted_for_recursion_tracker_ == + layer_tree_host()->meta_information_sequence_number(); +} + } // namespace cc diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h index 2e4f172292f..3ff2810c9d6 100644 --- a/chromium/cc/layers/layer.h +++ b/chromium/cc/layers/layer.h @@ -58,17 +58,16 @@ class CopyOutputRequest; class LayerAnimationEventObserver; class LayerClient; class LayerImpl; +class LayerSettings; class LayerTreeHost; class LayerTreeHostCommon; class LayerTreeImpl; -class PriorityCalculator; +class LayerTreeSettings; class RenderingStatsInstrumentation; class ResourceUpdateQueue; class ScrollbarLayerInterface; class SimpleEnclosedRegion; struct AnimationEvent; -template <typename LayerType> -class OcclusionTracker; // Base class for composited layers. Special layer types are derived from // this class. @@ -84,7 +83,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, INVALID_ID = -1, }; - static scoped_refptr<Layer> Create(); + static scoped_refptr<Layer> Create(const LayerSettings& settings); int id() const { return layer_id_; } @@ -136,6 +135,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, void SetOpacity(float opacity); float opacity() const { return opacity_; } bool OpacityIsAnimating() const; + bool HasPotentiallyRunningOpacityAnimation() const; virtual bool OpacityCanAnimateOnImplThread() const; void SetBlendMode(SkXfermode::Mode blend_mode); @@ -172,6 +172,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, void SetPosition(const gfx::PointF& position); gfx::PointF position() const { return position_; } + // A layer that is a container for fixed position layers cannot be both + // scrollable and have a non-identity transform. void SetIsContainerForFixedPositionLayers(bool container); bool IsContainerForFixedPositionLayers() const; @@ -187,12 +189,15 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, void SetTransform(const gfx::Transform& transform); const gfx::Transform& transform() const { return transform_; } bool TransformIsAnimating() const; + bool HasPotentiallyRunningTransformAnimation() const; bool AnimationsPreserveAxisAlignment() const; bool transform_is_invertible() const { return transform_is_invertible_; } void SetTransformOrigin(const gfx::Point3F&); gfx::Point3F transform_origin() const { return transform_origin_; } + bool ScrollOffsetAnimationWasInterrupted() const; + void SetScrollParent(Layer* parent); Layer* scroll_parent() { return scroll_parent_; } @@ -252,8 +257,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, gfx::Rect drawable_content_rect() const { return draw_properties_.drawable_content_rect; } - gfx::Rect visible_content_rect() const { - return draw_properties_.visible_content_rect; + gfx::Rect visible_layer_rect() const { + return draw_properties_.visible_layer_rect; } Layer* render_target() { DCHECK(!draw_properties_.render_target || @@ -265,7 +270,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, draw_properties_.render_target->render_surface()); return draw_properties_.render_target; } - int num_unclipped_descendants() const { + size_t num_unclipped_descendants() const { return draw_properties_.num_unclipped_descendants; } @@ -372,9 +377,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, // This methods typically need to be overwritten by derived classes. virtual void SavePaintProperties(); - // Returns true iff any resources were updated that need to be committed. - virtual bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion); + // Returns true iff anything was updated that needs to be committed. + virtual bool Update(); virtual bool NeedMoreUpdates(); virtual void SetIsMask(bool is_mask) {} virtual void ReduceMemoryUsage() {} @@ -393,53 +397,34 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, void ClearRenderSurfaceLayerList(); - // The contents scale converts from logical, non-page-scaled pixels to target - // pixels. The contents scale is 1 for the root layer as it is already in - // physical pixels. By default contents scale is forced to be 1 except for - // subclasses of ContentsScalingLayer. - float contents_scale_x() const { return draw_properties_.contents_scale_x; } - float contents_scale_y() const { return draw_properties_.contents_scale_y; } - gfx::Size content_bounds() const { return draw_properties_.content_bounds; } - - virtual void CalculateContentsScale(float ideal_contents_scale, - float* contents_scale_x, - float* contents_scale_y, - gfx::Size* content_bounds); - LayerTreeHost* layer_tree_host() { return layer_tree_host_; } const LayerTreeHost* layer_tree_host() const { return layer_tree_host_; } - // Set the priority of all desired textures in this layer. - virtual void SetTexturePriorities(const PriorityCalculator& priority_calc) {} - bool AddAnimation(scoped_ptr<Animation> animation); void PauseAnimation(int animation_id, double time_offset); void RemoveAnimation(int animation_id); void RemoveAnimation(int animation_id, Animation::TargetProperty property); - - LayerAnimationController* layer_animation_controller() { + LayerAnimationController* layer_animation_controller() const { return layer_animation_controller_.get(); } void SetLayerAnimationControllerForTest( scoped_refptr<LayerAnimationController> controller); void set_layer_animation_delegate(AnimationDelegate* delegate) { + DCHECK(layer_animation_controller_); layer_animation_controller_->set_layer_animation_delegate(delegate); } bool HasActiveAnimation() const; + void RegisterForAnimations(AnimationRegistrar* registrar); void AddLayerAnimationEventObserver( LayerAnimationEventObserver* animation_observer); void RemoveLayerAnimationEventObserver( LayerAnimationEventObserver* animation_observer); - virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const; - virtual ScrollbarLayerInterface* ToScrollbarLayer(); - gfx::Rect LayerRectToContentRect(const gfx::Rect& layer_rect) const; - virtual skia::RefPtr<SkPicture> GetPicture() const; // Constructs a LayerImpl of the correct runtime type for this Layer type. @@ -454,14 +439,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, return paint_properties_; } - // The scale at which contents should be rastered, to match the scale at - // which they will drawn to the screen. This scale is a component of the - // contents scale but does not include page/device scale factors. - // TODO(danakj): This goes away when TiledLayer goes away. - void set_raster_scale(float scale) { raster_scale_ = scale; } - float raster_scale() const { return raster_scale_; } - bool raster_scale_is_unknown() const { return raster_scale_ == 0.f; } - void SetNeedsPushProperties(); bool needs_push_properties() const { return needs_push_properties_; } bool descendant_needs_push_properties() const { @@ -559,12 +536,28 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, return num_layer_or_descendants_with_input_handler_; } + void set_num_children_with_scroll_parent( + int num_children_with_scroll_parent) { + num_children_with_scroll_parent_ = num_children_with_scroll_parent; + } + + int num_children_with_scroll_parent() { + return num_children_with_scroll_parent_; + } + + void set_visited(bool visited); + bool visited(); + void set_layer_or_descendant_is_drawn(bool layer_or_descendant_is_drawn); + bool layer_or_descendant_is_drawn(); + void set_sorted_for_recursion(bool sorted_for_recursion); + bool sorted_for_recursion(); + protected: friend class LayerImpl; friend class TreeSynchronizer; ~Layer() override; - Layer(); + explicit Layer(const LayerSettings& settings); // These SetNeeds functions are in order of severity of update: // @@ -604,8 +597,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, bool IsPropertyChangeAllowed() const; - void reset_raster_scale_to_unknown() { raster_scale_ = 0.f; } - // This flag is set when the layer needs to push properties to the impl // side. bool needs_push_properties_; @@ -649,9 +640,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, // trigger a Commit. void SetHasRenderSurface(bool has_render_surface); - // Returns the index of the child or -1 if not found. - int IndexOfChild(const Layer* reference); - // This should only be called from RemoveFromParent(). void RemoveChildOrDependent(Layer* child); @@ -707,6 +695,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, int property_tree_sequence_number_; int num_layer_or_descendants_with_copy_request_; int num_layer_or_descendants_with_input_handler_; + int num_children_with_scroll_parent_; gfx::Vector2dF offset_to_transform_parent_; bool should_flatten_transform_from_property_tree_ : 1; bool should_scroll_on_main_thread_ : 1; @@ -741,6 +730,14 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, Layer* scroll_parent_; scoped_ptr<std::set<Layer*>> scroll_children_; + // The following three variables are tracker variables. They are bools + // wrapped inside an integer variable. If true, their value equals the + // LayerTreeHost's meta_information_sequence_number. This wrapping of bools + // inside ints is done to avoid a layer tree treewalk to reset their values. + int layer_or_descendant_is_drawn_tracker_; + int sorted_for_recursion_tracker_; + int visited_tracker_; + Layer* clip_parent_; scoped_ptr<std::set<Layer*>> clip_children_; @@ -750,9 +747,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, // Replica layer used for reflections. scoped_refptr<Layer> replica_layer_; - // Transient properties. - float raster_scale_; - LayerClient* client_; ScopedPtrVector<CopyOutputRequest> copy_requests_; diff --git a/chromium/cc/layers/layer_impl.cc b/chromium/cc/layers/layer_impl.cc index 8b3467a9128..588c8ac4d90 100644 --- a/chromium/cc/layers/layer_impl.cc +++ b/chromium/cc/layers/layer_impl.cc @@ -5,6 +5,7 @@ #include "cc/layers/layer_impl.h" #include "base/json/json_reader.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" @@ -69,6 +70,7 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, hide_layer_and_subtree_(false), transform_is_invertible_(true), is_container_for_fixed_position_layers_(false), + is_affected_by_page_scale_(true), background_color_(0), opacity_(1.0), blend_mode_(SkXfermode::kSrcOver_Mode), @@ -81,17 +83,23 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, num_dependents_need_push_properties_(0), sorting_context_id_(0), current_draw_mode_(DRAW_MODE_NONE), - frame_timing_requests_dirty_(false) { + frame_timing_requests_dirty_(false), + visited_(false), + layer_or_descendant_is_drawn_(false), + sorted_for_recursion_(false) { DCHECK_GT(layer_id_, 0); DCHECK(layer_tree_impl_); layer_tree_impl_->RegisterLayer(this); - AnimationRegistrar* registrar = layer_tree_impl_->GetAnimationRegistrar(); - layer_animation_controller_ = - registrar->GetAnimationControllerForId(layer_id_); - layer_animation_controller_->AddValueObserver(this); - if (IsActive()) { - layer_animation_controller_->set_value_provider(this); - layer_animation_controller_->set_layer_animation_delegate(this); + + if (!layer_tree_impl_->settings().use_compositor_animation_timelines) { + AnimationRegistrar* registrar = layer_tree_impl_->GetAnimationRegistrar(); + layer_animation_controller_ = + registrar->GetAnimationControllerForId(layer_id_); + layer_animation_controller_->AddValueObserver(this); + if (IsActive()) { + layer_animation_controller_->set_value_provider(this); + layer_animation_controller_->set_layer_animation_delegate(this); + } } SetNeedsPushProperties(); } @@ -99,9 +107,11 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, LayerImpl::~LayerImpl() { DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_); - layer_animation_controller_->RemoveValueObserver(this); - layer_animation_controller_->remove_value_provider(this); - layer_animation_controller_->remove_layer_animation_delegate(this); + if (layer_animation_controller_) { + layer_animation_controller_->RemoveValueObserver(this); + layer_animation_controller_->remove_value_provider(this); + layer_animation_controller_->remove_layer_animation_delegate(this); + } if (!copy_requests_.empty() && layer_tree_impl_->IsActiveTree()) layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this); @@ -224,8 +234,19 @@ void LayerImpl::SetOpacityTreeIndex(int index) { } void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) { + // In the case that a layer still has a copy request, this means that there's + // a commit to the active tree without a draw. This only happens in some + // edge cases during lost context or visibility changes, so don't try to + // handle preserving these output requests (and their surface). + if (!copy_requests_.empty()) { + layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this); + // Destroying these will abort them. + copy_requests_.clear(); + } + if (requests->empty()) return; + DCHECK(render_surface()); bool was_empty = copy_requests_.empty(); copy_requests_.insert_and_take(copy_requests_.end(), requests); @@ -252,10 +273,9 @@ void LayerImpl::TakeCopyRequestsAndTransformToTarget( continue; gfx::Rect request_in_layer_space = request->area(); - gfx::Rect request_in_content_space = - LayerRectToContentRect(request_in_layer_space); + request_in_layer_space.Intersect(gfx::Rect(bounds())); request->set_area(MathUtil::MapEnclosingClippedRect( - draw_properties_.target_space_transform, request_in_content_space)); + draw_properties_.target_space_transform, request_in_layer_space)); } layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this); @@ -268,11 +288,10 @@ void LayerImpl::ClearRenderSurfaceLayerList() { } void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const { - state->SetAll( - draw_properties_.target_space_transform, draw_properties_.content_bounds, - draw_properties_.visible_content_rect, draw_properties_.clip_rect, - draw_properties_.is_clipped, draw_properties_.opacity, - draw_properties_.blend_mode, sorting_context_id_); + state->SetAll(draw_properties_.target_space_transform, bounds(), + draw_properties_.visible_layer_rect, draw_properties_.clip_rect, + draw_properties_.is_clipped, draw_properties_.opacity, + draw_properties_.blend_mode, sorting_context_id_); } void LayerImpl::PopulateScaledSharedQuadState(SharedQuadState* state, @@ -280,16 +299,15 @@ void LayerImpl::PopulateScaledSharedQuadState(SharedQuadState* state, gfx::Transform scaled_draw_transform = draw_properties_.target_space_transform; scaled_draw_transform.Scale(SK_MScalar1 / scale, SK_MScalar1 / scale); - gfx::Size scaled_content_bounds = - gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale)); - gfx::Rect scaled_visible_content_rect = - gfx::ScaleToEnclosingRect(visible_content_rect(), scale); - scaled_visible_content_rect.Intersect(gfx::Rect(scaled_content_bounds)); + gfx::Size scaled_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale)); + gfx::Rect scaled_visible_layer_rect = + gfx::ScaleToEnclosingRect(visible_layer_rect(), scale); + scaled_visible_layer_rect.Intersect(gfx::Rect(scaled_bounds)); - state->SetAll(scaled_draw_transform, scaled_content_bounds, - scaled_visible_content_rect, draw_properties().clip_rect, - draw_properties().is_clipped, draw_properties().opacity, - draw_properties().blend_mode, sorting_context_id_); + state->SetAll(scaled_draw_transform, scaled_bounds, scaled_visible_layer_rect, + draw_properties().clip_rect, draw_properties().is_clipped, + draw_properties().opacity, draw_properties().blend_mode, + sorting_context_id_); } bool LayerImpl::WillDraw(DrawMode draw_mode, @@ -329,22 +347,18 @@ void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const { void LayerImpl::AppendDebugBorderQuad( RenderPass* render_pass, - const gfx::Size& content_bounds, + const gfx::Size& bounds, const SharedQuadState* shared_quad_state, AppendQuadsData* append_quads_data) const { SkColor color; float width; GetDebugBorderProperties(&color, &width); - AppendDebugBorderQuad(render_pass, - content_bounds, - shared_quad_state, - append_quads_data, - color, - width); + AppendDebugBorderQuad(render_pass, bounds, shared_quad_state, + append_quads_data, color, width); } void LayerImpl::AppendDebugBorderQuad(RenderPass* render_pass, - const gfx::Size& content_bounds, + const gfx::Size& bounds, const SharedQuadState* shared_quad_state, AppendQuadsData* append_quads_data, SkColor color, @@ -352,7 +366,7 @@ void LayerImpl::AppendDebugBorderQuad(RenderPass* render_pass, if (!ShowDebugBorders()) return; - gfx::Rect quad_rect(content_bounds); + gfx::Rect quad_rect(bounds); gfx::Rect visible_quad_rect(quad_rect); DebugBorderDrawQuad* debug_border_quad = render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>(); @@ -394,7 +408,7 @@ RenderPassId LayerImpl::NextContributingRenderPassId(RenderPassId id) const { return RenderPassId(0, 0); } -void LayerImpl::GetContentsResourceId(ResourceProvider::ResourceId* resource_id, +void LayerImpl::GetContentsResourceId(ResourceId* resource_id, gfx::Size* resource_size) const { NOTREACHED(); *resource_id = 0; @@ -402,12 +416,10 @@ void LayerImpl::GetContentsResourceId(ResourceProvider::ResourceId* resource_id, gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) { gfx::ScrollOffset adjusted_scroll(scroll); - if (layer_tree_impl()->settings().use_pinch_virtual_viewport) { - if (!user_scrollable_horizontal_) - adjusted_scroll.set_x(0); - if (!user_scrollable_vertical_) - adjusted_scroll.set_y(0); - } + if (!user_scrollable_horizontal_) + adjusted_scroll.set_x(0); + if (!user_scrollable_vertical_) + adjusted_scroll.set_y(0); DCHECK(scrollable()); gfx::ScrollOffset old_offset = CurrentScrollOffset(); gfx::ScrollOffset new_offset = @@ -457,14 +469,8 @@ InputHandler::ScrollStatus LayerImpl::TryScroll( // SCROLL_ON_MAIN_THREAD in this case? } - gfx::PointF hit_test_point_in_content_space = - MathUtil::ProjectPoint(inverse_screen_space_transform, - screen_space_point, - &clipped); - gfx::PointF hit_test_point_in_layer_space = - gfx::ScalePoint(hit_test_point_in_content_space, - 1.f / contents_scale_x(), - 1.f / contents_scale_y()); + gfx::PointF hit_test_point_in_layer_space = MathUtil::ProjectPoint( + inverse_screen_space_transform, screen_space_point, &clipped); if (!clipped && non_fast_scrollable_region().Contains( gfx::ToRoundedPoint(hit_test_point_in_layer_space))) { @@ -502,16 +508,6 @@ InputHandler::ScrollStatus LayerImpl::TryScroll( return InputHandler::SCROLL_STARTED; } -gfx::Rect LayerImpl::LayerRectToContentRect( - const gfx::RectF& layer_rect) const { - gfx::RectF content_rect = - gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y()); - // Intersect with content rect to avoid the extra pixel because for some - // values x and y, ceil((x / y) * y) may be x + 1. - content_rect.Intersect(gfx::Rect(content_bounds())); - return gfx::ToEnclosingRect(content_rect); -} - skia::RefPtr<SkPicture> LayerImpl::GetPicture() { return skia::RefPtr<SkPicture>(); } @@ -524,14 +520,12 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->SetTransformOrigin(transform_origin_); layer->SetBackgroundColor(background_color_); layer->SetBounds(bounds_); - layer->SetContentBounds(content_bounds()); - layer->SetContentsScale(contents_scale_x(), contents_scale_y()); layer->SetDoubleSided(double_sided_); layer->SetDrawCheckerboardForMissingTiles( draw_checkerboard_for_missing_tiles_); layer->SetDrawsContent(DrawsContent()); layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); - layer->SetHasRenderSurface(!!render_surface() || layer->HasCopyRequest()); + layer->SetHasRenderSurface(!!render_surface()); layer->SetFilters(filters()); layer->SetBackgroundFilters(background_filters()); layer->SetMasksToBounds(masks_to_bounds_); @@ -626,7 +620,7 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->SetDebugInfo(debug_info_); if (frame_timing_requests_dirty_) { - layer->PassFrameTimingRequests(&frame_timing_requests_); + layer->SetFrameTimingRequests(frame_timing_requests_); frame_timing_requests_dirty_ = false; } @@ -646,31 +640,12 @@ gfx::Vector2dF LayerImpl::FixedContainerSizeDelta() const { // In virtual-viewport mode, we don't need to compensate for pinch zoom or // scale since the fixed container is the outer viewport, which sits below // the page scale. - if (layer_tree_impl()->settings().use_pinch_virtual_viewport) - return delta_from_scroll; - - float scale_delta = layer_tree_impl()->page_scale_delta(); - float scale = layer_tree_impl()->current_page_scale_factor() / - layer_tree_impl()->page_scale_delta(); - - delta_from_scroll.Scale(1.f / scale); - - // The delta-from-pinch component requires some explanation: A viewport of - // size (w,h) will appear to be size (w/s,h/s) under scale s in the content - // space. If s -> s' on the impl thread, where s' = s * ds, then the apparent - // viewport size change in the content space due to ds is: - // - // (w/s',h/s') - (w/s,h/s) = (w,h)(1/s' - 1/s) = (w,h)(1 - ds)/(s ds) - // - gfx::Vector2dF delta_from_pinch = - gfx::Rect(scroll_clip_layer_->bounds()).bottom_right() - gfx::PointF(); - delta_from_pinch.Scale((1.f - scale_delta) / (scale * scale_delta)); - - return delta_from_scroll + delta_from_pinch; + return delta_from_scroll; } base::DictionaryValue* LayerImpl::LayerTreeAsJson() const { base::DictionaryValue* result = new base::DictionaryValue; + result->SetInteger("LayerId", id()); result->SetString("LayerType", LayerTypeAsString()); base::ListValue* list = new base::ListValue; @@ -761,20 +736,12 @@ void LayerImpl::NoteLayerPropertyChangedForDescendants() { SetNeedsPushProperties(); } -#if DCHECK_IS_ON() -// Verify that the resource id is valid. -static ResourceProvider::ResourceId ValidateResource( - const ResourceProvider* provider, - ResourceProvider::ResourceId id) { - provider->ValidateResource(id); - return id; -} -#endif - void LayerImpl::ValidateQuadResourcesInternal(DrawQuad* quad) const { #if DCHECK_IS_ON() - quad->IterateResources( - base::Bind(&ValidateResource, layer_tree_impl_->resource_provider())); + const ResourceProvider* resource_provider = + layer_tree_impl_->resource_provider(); + for (ResourceId resource_id : quad->resources) + resource_provider->ValidateResource(resource_id); #endif } @@ -806,6 +773,46 @@ void LayerImpl::ResetAllChangeTrackingForSubtree() { num_dependents_need_push_properties_ = 0; } +void LayerImpl::UpdatePropertyTreeTransform() { + if (transform_tree_index_ != -1) { + TransformTree& transform_tree = + layer_tree_impl()->property_trees()->transform_tree; + TransformNode* node = transform_tree.Node(transform_tree_index_); + if (node->data.local != transform_) { + node->data.local = transform_; + node->data.needs_local_transform_update = true; + transform_tree.set_needs_update(true); + // TODO(ajuma): The current criteria for creating clip nodes means that + // property trees may need to be rebuilt when the new transform isn't + // axis-aligned wrt the old transform (see Layer::SetTransform). Since + // rebuilding property trees every frame of a transform animation is + // something we should try to avoid, change property tree-building so that + // it doesn't depend on axis aliginment. + } + } +} + +void LayerImpl::UpdatePropertyTreeOpacity() { + if (opacity_tree_index_ != -1) { + OpacityTree& opacity_tree = + layer_tree_impl()->property_trees()->opacity_tree; + OpacityNode* node = opacity_tree.Node(opacity_tree_index_); + node->data.opacity = opacity_; + opacity_tree.set_needs_update(true); + } +} + +void LayerImpl::UpdatePropertyTreeForScrollingAndAnimationIfNeeded() { + if (scrollable()) + UpdatePropertyTreeScrollOffset(); + + if (OpacityIsAnimating()) + UpdatePropertyTreeOpacity(); + + if (TransformIsAnimating()) + UpdatePropertyTreeTransform(); +} + gfx::ScrollOffset LayerImpl::ScrollOffsetForAnimation() const { return CurrentScrollOffset(); } @@ -816,10 +823,12 @@ void LayerImpl::OnFilterAnimated(const FilterOperations& filters) { void LayerImpl::OnOpacityAnimated(float opacity) { SetOpacity(opacity); + UpdatePropertyTreeOpacity(); } void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) { SetTransform(transform); + UpdatePropertyTreeTransform(); } void LayerImpl::OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) { @@ -865,16 +874,36 @@ void LayerImpl::SetBounds(const gfx::Size& bounds) { } void LayerImpl::SetBoundsDelta(const gfx::Vector2dF& bounds_delta) { + DCHECK(IsActive()); if (bounds_delta_ == bounds_delta) return; bounds_delta_ = bounds_delta; + TransformTree& transform_tree = + layer_tree_impl()->property_trees()->transform_tree; + if (this == layer_tree_impl()->InnerViewportContainerLayer()) + transform_tree.SetInnerViewportBoundsDelta(bounds_delta); + else if (this == layer_tree_impl()->OuterViewportContainerLayer()) + transform_tree.SetOuterViewportBoundsDelta(bounds_delta); + ScrollbarParametersDidChange(true); - if (masks_to_bounds()) + + if (masks_to_bounds()) { + // If layer is clipping, then update the clip node using the new bounds. + ClipNode* clip_node = + layer_tree_impl()->property_trees()->clip_tree.Node(clip_tree_index()); + if (clip_node) { + DCHECK(id() == clip_node->owner_id); + clip_node->data.clip = + gfx::RectF(gfx::PointF() + offset_to_transform_parent(), bounds()); + layer_tree_impl()->property_trees()->clip_tree.set_needs_update(true); + } + NoteLayerPropertyChangedForSubtree(); - else + } else { NoteLayerPropertyChanged(); + } } void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) { @@ -984,10 +1013,16 @@ void LayerImpl::SetFilters(const FilterOperations& filters) { } bool LayerImpl::FilterIsAnimating() const { - return layer_animation_controller_->IsAnimatingProperty(Animation::FILTER); + return layer_animation_controller_ + ? layer_animation_controller_->IsAnimatingProperty( + Animation::FILTER) + : layer_tree_impl_->IsAnimatingFilterProperty(this); } bool LayerImpl::FilterIsAnimatingOnImplOnly() const { + if (!layer_animation_controller_) + return layer_tree_impl_->FilterIsAnimatingOnImplOnly(this); + Animation* filter_animation = layer_animation_controller_->GetAnimation(Animation::FILTER); return filter_animation && filter_animation->is_impl_only(); @@ -1027,10 +1062,28 @@ void LayerImpl::SetOpacity(float opacity) { } bool LayerImpl::OpacityIsAnimating() const { - return layer_animation_controller_->IsAnimatingProperty(Animation::OPACITY); + return layer_animation_controller_ + ? layer_animation_controller_->IsAnimatingProperty( + Animation::OPACITY) + : layer_tree_impl_->IsAnimatingOpacityProperty(this); +} + +bool LayerImpl::HasPotentiallyRunningOpacityAnimation() const { + if (layer_animation_controller_) { + if (Animation* animation = + layer_animation_controller()->GetAnimation(Animation::OPACITY)) { + return !animation->is_finished(); + } + return false; + } else { + return layer_tree_impl_->HasPotentiallyRunningOpacityAnimation(this); + } } bool LayerImpl::OpacityIsAnimatingOnImplOnly() const { + if (!layer_animation_controller_) + return layer_tree_impl_->OpacityIsAnimatingOnImplOnly(this); + Animation* opacity_animation = layer_animation_controller_->GetAnimation(Animation::OPACITY); return opacity_animation && opacity_animation->is_impl_only(); @@ -1075,9 +1128,9 @@ void LayerImpl::Set3dSortingContextId(int id) { NoteLayerPropertyChangedForSubtree(); } -void LayerImpl::PassFrameTimingRequests( - std::vector<FrameTimingRequest>* requests) { - frame_timing_requests_.swap(*requests); +void LayerImpl::SetFrameTimingRequests( + const std::vector<FrameTimingRequest>& requests) { + frame_timing_requests_ = requests; frame_timing_requests_dirty_ = true; SetNeedsPushProperties(); } @@ -1109,45 +1162,103 @@ void LayerImpl::SetTransformAndInvertibility(const gfx::Transform& transform, } bool LayerImpl::TransformIsAnimating() const { - return layer_animation_controller_->IsAnimatingProperty(Animation::TRANSFORM); + return layer_animation_controller_ + ? layer_animation_controller_->IsAnimatingProperty( + Animation::TRANSFORM) + : layer_tree_impl_->IsAnimatingTransformProperty(this); +} + +bool LayerImpl::HasPotentiallyRunningTransformAnimation() const { + if (layer_animation_controller_) { + if (Animation* animation = + layer_animation_controller()->GetAnimation(Animation::TRANSFORM)) { + return !animation->is_finished(); + } + return false; + } else { + return layer_tree_impl_->HasPotentiallyRunningTransformAnimation(this); + } } bool LayerImpl::TransformIsAnimatingOnImplOnly() const { + if (!layer_animation_controller_) + return layer_tree_impl_->TransformIsAnimatingOnImplOnly(this); + Animation* transform_animation = layer_animation_controller_->GetAnimation(Animation::TRANSFORM); return transform_animation && transform_animation->is_impl_only(); } -void LayerImpl::SetUpdateRect(const gfx::Rect& update_rect) { - update_rect_ = update_rect; - SetNeedsPushProperties(); +bool LayerImpl::HasOnlyTranslationTransforms() const { + if (!layer_animation_controller_) + return layer_tree_impl_->HasOnlyTranslationTransforms(this); + + return layer_animation_controller_->HasOnlyTranslationTransforms(); } -void LayerImpl::AddDamageRect(const gfx::RectF& damage_rect) { - damage_rect_ = gfx::UnionRects(damage_rect_, damage_rect); +bool LayerImpl::MaximumTargetScale(float* max_scale) const { + if (!layer_animation_controller_) + return layer_tree_impl_->MaximumTargetScale(this, max_scale); + + return layer_animation_controller_->MaximumTargetScale(max_scale); } -void LayerImpl::SetContentBounds(const gfx::Size& content_bounds) { - if (this->content_bounds() == content_bounds) - return; +bool LayerImpl::AnimationStartScale(float* start_scale) const { + if (!layer_animation_controller_) + return layer_tree_impl_->AnimationStartScale(this, start_scale); - draw_properties_.content_bounds = content_bounds; - NoteLayerPropertyChanged(); + return layer_animation_controller_->AnimationStartScale(start_scale); } -void LayerImpl::SetContentsScale(float contents_scale_x, - float contents_scale_y) { - if (this->contents_scale_x() == contents_scale_x && - this->contents_scale_y() == contents_scale_y) - return; +bool LayerImpl::HasFilterAnimationThatInflatesBounds() const { + if (!layer_animation_controller_) + return layer_tree_impl_->HasFilterAnimationThatInflatesBounds(this); - draw_properties_.contents_scale_x = contents_scale_x; - draw_properties_.contents_scale_y = contents_scale_y; - NoteLayerPropertyChanged(); + return layer_animation_controller_->HasFilterAnimationThatInflatesBounds(); +} + +bool LayerImpl::HasTransformAnimationThatInflatesBounds() const { + if (!layer_animation_controller_) + return layer_tree_impl_->HasTransformAnimationThatInflatesBounds(this); + + return layer_animation_controller_->HasTransformAnimationThatInflatesBounds(); } -bool LayerImpl::IsExternalFlingActive() const { - return layer_tree_impl_->IsExternalFlingActive(); +bool LayerImpl::HasAnimationThatInflatesBounds() const { + if (!layer_animation_controller_) + return layer_tree_impl_->HasAnimationThatInflatesBounds(this); + + return layer_animation_controller_->HasAnimationThatInflatesBounds(); +} + +bool LayerImpl::FilterAnimationBoundsForBox(const gfx::BoxF& box, + gfx::BoxF* bounds) const { + if (!layer_animation_controller_) + return layer_tree_impl_->FilterAnimationBoundsForBox(this, box, bounds); + + return layer_animation_controller_->FilterAnimationBoundsForBox(box, bounds); +} + +bool LayerImpl::TransformAnimationBoundsForBox(const gfx::BoxF& box, + gfx::BoxF* bounds) const { + if (!layer_animation_controller_) + return layer_tree_impl_->TransformAnimationBoundsForBox(this, box, bounds); + + return layer_animation_controller_->TransformAnimationBoundsForBox(box, + bounds); +} + +void LayerImpl::SetUpdateRect(const gfx::Rect& update_rect) { + update_rect_ = update_rect; + SetNeedsPushProperties(); +} + +void LayerImpl::AddDamageRect(const gfx::RectF& damage_rect) { + damage_rect_ = gfx::UnionRects(damage_rect_, damage_rect); +} + +bool LayerImpl::IsExternalScrollActive() const { + return layer_tree_impl_->IsExternalScrollActive(); } void LayerImpl::SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset) { @@ -1205,6 +1316,7 @@ gfx::Vector2dF LayerImpl::ScrollDelta() const { void LayerImpl::SetScrollDelta(const gfx::Vector2dF& delta) { DCHECK(IsActive()); + DCHECK(scrollable() || delta.IsZero()); SetCurrentScrollOffset(scroll_offset_->ActiveBase() + gfx::ScrollOffset(delta)); } @@ -1231,16 +1343,37 @@ void LayerImpl::PushScrollOffset(const gfx::ScrollOffset* scroll_offset) { DidUpdateScrollOffset(false); } +void LayerImpl::UpdatePropertyTreeScrollOffset() { + // TODO(enne): in the future, scrolling should update the scroll tree + // directly instead of going through layers. + if (transform_tree_index_ != -1) { + TransformTree& transform_tree = + layer_tree_impl()->property_trees()->transform_tree; + TransformNode* node = transform_tree.Node(transform_tree_index_); + gfx::ScrollOffset current_offset = scroll_offset_->Current(IsActive()); + if (node->data.scroll_offset != current_offset) { + node->data.scroll_offset = current_offset; + node->data.needs_local_transform_update = true; + transform_tree.set_needs_update(true); + } + } +} + void LayerImpl::DidUpdateScrollOffset(bool is_from_root_delegate) { + DCHECK(scroll_offset_); + if (!is_from_root_delegate) layer_tree_impl()->DidUpdateScrollOffset(id()); NoteLayerPropertyChangedForSubtree(); ScrollbarParametersDidChange(false); + + UpdatePropertyTreeScrollOffset(); + // Inform the pending twin that a property changed. if (layer_tree_impl()->IsActiveTree()) { LayerImpl* pending_twin = layer_tree_impl()->FindPendingTreeLayerById(id()); if (pending_twin) - pending_twin->NoteLayerPropertyChangedForSubtree(); + pending_twin->DidUpdateScrollOffset(is_from_root_delegate); } } @@ -1252,9 +1385,9 @@ void LayerImpl::SetDoubleSided(bool double_sided) { NoteLayerPropertyChangedForSubtree(); } -SimpleEnclosedRegion LayerImpl::VisibleContentOpaqueRegion() const { +SimpleEnclosedRegion LayerImpl::VisibleOpaqueRegion() const { if (contents_opaque()) - return SimpleEnclosedRegion(visible_content_rect()); + return SimpleEnclosedRegion(visible_layer_rect()); return SimpleEnclosedRegion(); } @@ -1362,7 +1495,7 @@ void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer, scrollbar_needs_animation |= scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio); if (y_offset_did_change && layer_tree_impl()->IsActiveTree() && - this == layer_tree_impl()->InnerViewportScrollLayer()) { + this == layer_tree_impl()->OuterViewportScrollLayer()) { TRACE_COUNTER_ID1("cc", "scroll_offset_y", this->id(), current_offset.y()); } @@ -1496,7 +1629,8 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { MathUtil::AddToTracedValue("position", position_, state); state->SetInteger("draws_content", DrawsContent()); - state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes()); + state->SetInteger("gpu_memory_usage", + base::saturated_cast<int>(GPUMemoryUsageInBytes())); MathUtil::AddToTracedValue( "scroll_offset", scroll_offset_ ? scroll_offset_->Current(IsActive()) @@ -1507,9 +1641,7 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { bool clipped; gfx::QuadF layer_quad = MathUtil::MapQuad( - screen_space_transform(), - gfx::QuadF(gfx::Rect(content_bounds())), - &clipped); + screen_space_transform(), gfx::QuadF(gfx::Rect(bounds())), &clipped); MathUtil::AddToTracedValue("layer_quad", layer_quad, state); if (!touch_event_handler_region_.IsEmpty()) { state->BeginArray("touch_event_handler_region"); @@ -1517,14 +1649,14 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->EndArray(); } if (have_wheel_event_handlers_) { - gfx::Rect wheel_rect(content_bounds()); + gfx::Rect wheel_rect(bounds()); Region wheel_region(wheel_rect); state->BeginArray("wheel_event_handler_region"); wheel_region.AsValueInto(state); state->EndArray(); } if (have_scroll_event_handlers_) { - gfx::Rect scroll_rect(content_bounds()); + gfx::Rect scroll_rect(bounds()); Region scroll_region(scroll_rect); state->BeginArray("scroll_event_handler_region"); scroll_region.AsValueInto(state); @@ -1568,7 +1700,9 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->SetBoolean( "has_animation_bounds", - layer_animation_controller()->HasAnimationThatInflatesBounds()); + layer_animation_controller_ + ? layer_animation_controller_->HasAnimationThatInflatesBounds() + : layer_tree_impl_->HasAnimationThatInflatesBounds(this)); gfx::BoxF box; if (LayerUtils::GetAnimationBounds(*this, &box)) @@ -1648,18 +1782,36 @@ Region LayerImpl::GetInvalidationRegion() { gfx::Rect LayerImpl::GetEnclosingRectInTargetSpace() const { return MathUtil::MapEnclosingClippedRect( - draw_properties_.target_space_transform, - gfx::Rect(draw_properties_.content_bounds)); + draw_properties_.target_space_transform, gfx::Rect(bounds())); } gfx::Rect LayerImpl::GetScaledEnclosingRectInTargetSpace(float scale) const { gfx::Transform scaled_draw_transform = draw_properties_.target_space_transform; scaled_draw_transform.Scale(SK_MScalar1 / scale, SK_MScalar1 / scale); - gfx::Size scaled_content_bounds = - gfx::ToCeiledSize(gfx::ScaleSize(content_bounds(), scale)); + gfx::Size scaled_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale)); return MathUtil::MapEnclosingClippedRect(scaled_draw_transform, - gfx::Rect(scaled_content_bounds)); + gfx::Rect(scaled_bounds)); +} + +float LayerImpl::GetIdealContentsScale() const { + float page_scale = IsAffectedByPageScale() + ? layer_tree_impl()->current_page_scale_factor() + : 1.f; + float device_scale = layer_tree_impl()->device_scale_factor(); + + float default_scale = page_scale * device_scale; + if (!layer_tree_impl() + ->settings() + .layer_transforms_should_scale_layer_contents) { + return default_scale; + } + + // TODO(enne): the transform needs to come from property trees instead of + // draw properties. + gfx::Vector2dF transform_scales = MathUtil::ComputeTransform2dScaleComponents( + draw_properties().target_space_transform, default_scale); + return std::max(transform_scales.x(), transform_scales.y()); } } // namespace cc diff --git a/chromium/cc/layers/layer_impl.h b/chromium/cc/layers/layer_impl.h index 08db87f1392..57a0be1204a 100644 --- a/chromium/cc/layers/layer_impl.h +++ b/chromium/cc/layers/layer_impl.h @@ -57,8 +57,6 @@ class LayerTreeHostImpl; class LayerTreeImpl; class MicroBenchmarkImpl; class Occlusion; -template <typename LayerType> -class OcclusionTracker; class OpacityTree; class PrioritizedTile; class RenderPass; @@ -185,6 +183,10 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, return should_flatten_transform_from_property_tree_; } + void UpdatePropertyTreeTransform(); + void UpdatePropertyTreeOpacity(); + void UpdatePropertyTreeScrollOffset(); + // For compatibility with Layer. bool has_render_surface() const { return !!render_surface(); } @@ -250,7 +252,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, #endif } - virtual void GetContentsResourceId(ResourceProvider::ResourceId* resource_id, + virtual void GetContentsResourceId(ResourceId* resource_id, gfx::Size* resource_size) const; virtual bool HasDelegatedContent() const; @@ -298,6 +300,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, void SetOpacity(float opacity); float opacity() const { return opacity_; } bool OpacityIsAnimating() const; + bool HasPotentiallyRunningOpacityAnimation() const; bool OpacityIsAnimatingOnImplOnly() const; void SetBlendMode(SkXfermode::Mode); @@ -322,6 +325,11 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, return is_container_for_fixed_position_layers_; } + bool IsAffectedByPageScale() const { return is_affected_by_page_scale_; } + void SetIsAffectedByPageScale(bool is_affected) { + is_affected_by_page_scale_ = is_affected; + } + gfx::Vector2dF FixedContainerSizeDelta() const; void SetPositionConstraint(const LayerPositionConstraint& constraint) { @@ -390,8 +398,8 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, gfx::Rect drawable_content_rect() const { return draw_properties_.drawable_content_rect; } - gfx::Rect visible_content_rect() const { - return draw_properties_.visible_content_rect; + gfx::Rect visible_layer_rect() const { + return draw_properties_.visible_layer_rect; } LayerImpl* render_target() { DCHECK(!draw_properties_.render_target || @@ -404,7 +412,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, return draw_properties_.render_target; } - int num_unclipped_descendants() const { + size_t num_unclipped_descendants() const { return draw_properties_.num_unclipped_descendants; } @@ -420,14 +428,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, void SetBoundsDelta(const gfx::Vector2dF& bounds_delta); gfx::Vector2dF bounds_delta() const { return bounds_delta_; } - void SetContentBounds(const gfx::Size& content_bounds); - gfx::Size content_bounds() const { return draw_properties_.content_bounds; } - - float contents_scale_x() const { return draw_properties_.contents_scale_x; } - float contents_scale_y() const { return draw_properties_.contents_scale_y; } - void SetContentsScale(float contents_scale_x, float contents_scale_y); - - bool IsExternalFlingActive() const; + bool IsExternalScrollActive() const; void SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset); void SetCurrentScrollOffsetFromDelegate( @@ -535,11 +536,25 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, void SetTransform(const gfx::Transform& transform); const gfx::Transform& transform() const { return transform_; } bool TransformIsAnimating() const; + bool HasPotentiallyRunningTransformAnimation() const; bool TransformIsAnimatingOnImplOnly() const; + bool HasOnlyTranslationTransforms() const; void SetTransformAndInvertibility(const gfx::Transform& transform, bool transform_is_invertible); bool transform_is_invertible() const { return transform_is_invertible_; } + bool MaximumTargetScale(float* max_scale) const; + bool AnimationStartScale(float* start_scale) const; + + bool HasFilterAnimationThatInflatesBounds() const; + bool HasTransformAnimationThatInflatesBounds() const; + bool HasAnimationThatInflatesBounds() const; + + bool FilterAnimationBoundsForBox(const gfx::BoxF& box, + gfx::BoxF* bounds) const; + bool TransformAnimationBoundsForBox(const gfx::BoxF& box, + gfx::BoxF* bounds) const; + // Note this rect is in layer space (not content space). void SetUpdateRect(const gfx::Rect& update_rect); gfx::Rect update_rect() const { return update_rect_; } @@ -564,7 +579,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, return layer_animation_controller_.get(); } - virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const; + virtual SimpleEnclosedRegion VisibleOpaqueRegion() const; virtual void DidBecomeActive(); @@ -593,8 +608,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, return scroll_clip_layer_ ? scroll_clip_layer_->bounds().height() : 0; } - gfx::Rect LayerRectToContentRect(const gfx::RectF& layer_rect) const; - virtual skia::RefPtr<SkPicture> GetPicture(); virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl); @@ -628,8 +641,8 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, void Set3dSortingContextId(int id); int sorting_context_id() { return sorting_context_id_; } - void PassFrameTimingRequests( - std::vector<FrameTimingRequest>* frame_timing_requests); + void SetFrameTimingRequests( + const std::vector<FrameTimingRequest>& frame_timing_requests); const std::vector<FrameTimingRequest>& frame_timing_requests() const { return frame_timing_requests_; } @@ -643,6 +656,26 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, virtual gfx::Rect GetEnclosingRectInTargetSpace() const; + void set_visited(bool visited) { visited_ = visited; } + + bool visited() { return visited_; } + + void set_layer_or_descendant_is_drawn(bool layer_or_descendant_is_drawn) { + layer_or_descendant_is_drawn_ = layer_or_descendant_is_drawn; + } + + bool layer_or_descendant_is_drawn() { return layer_or_descendant_is_drawn_; } + + void set_sorted_for_recursion(bool sorted_for_recursion) { + sorted_for_recursion_ = sorted_for_recursion; + } + + bool sorted_for_recursion() { return sorted_for_recursion_; } + + void UpdatePropertyTreeForScrollingAndAnimationIfNeeded(); + + float GetIdealContentsScale() const; + protected: LayerImpl(LayerTreeImpl* layer_impl, int id, @@ -653,11 +686,11 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, virtual void GetDebugBorderProperties(SkColor* color, float* width) const; void AppendDebugBorderQuad(RenderPass* render_pass, - const gfx::Size& content_bounds, + const gfx::Size& bounds, const SharedQuadState* shared_quad_state, AppendQuadsData* append_quads_data) const; void AppendDebugBorderQuad(RenderPass* render_pass, - const gfx::Size& content_bounds, + const gfx::Size& bounds, const SharedQuadState* shared_quad_state, AppendQuadsData* append_quads_data, SkColor color, @@ -751,6 +784,8 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, // Set for the layer that other layers are fixed to. bool is_container_for_fixed_position_layers_ : 1; + bool is_affected_by_page_scale_ : 1; + Region non_fast_scrollable_region_; Region touch_event_handler_region_; SkColor background_color_; @@ -825,6 +860,9 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, std::vector<FrameTimingRequest> frame_timing_requests_; bool frame_timing_requests_dirty_; + bool visited_; + bool layer_or_descendant_is_drawn_; + bool sorted_for_recursion_; DISALLOW_COPY_AND_ASSIGN(LayerImpl); }; diff --git a/chromium/cc/layers/layer_impl_unittest.cc b/chromium/cc/layers/layer_impl_unittest.cc index d9811bc1553..964b9994085 100644 --- a/chromium/cc/layers/layer_impl_unittest.cc +++ b/chromium/cc/layers/layer_impl_unittest.cc @@ -88,7 +88,9 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { // Create a simple LayerImpl tree: FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); EXPECT_TRUE(host_impl.InitializeRenderer(FakeOutputSurface::Create3d())); scoped_ptr<LayerImpl> root_clip = LayerImpl::Create(host_impl.active_tree(), 1); @@ -172,9 +174,6 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetTransform(arbitrary_transform)); // Changing these properties only affects the layer itself. - EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->SetContentBounds(arbitrary_size)); - EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED( - root->SetContentsScale(arbitrary_number, arbitrary_number)); EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->SetDrawsContent(true)); EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED( root->SetBackgroundColor(arbitrary_color)); @@ -226,10 +225,6 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE( root->PushScrollOffsetFromMainThread( gfx::ScrollOffset(arbitrary_vector2d))); - EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE( - root->SetContentBounds(arbitrary_size)); - EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE( - root->SetContentsScale(arbitrary_number, arbitrary_number)); EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetContentsOpaque(true)); EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetOpacity(arbitrary_number)); EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE( @@ -251,7 +246,9 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); EXPECT_TRUE(host_impl.InitializeRenderer(FakeOutputSurface::Create3d())); host_impl.active_tree()->SetRootLayer( LayerImpl::Create(host_impl.active_tree(), 1)); @@ -323,9 +320,6 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( layer->SetDoubleSided(false)); // constructor initializes it to "true". - VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetContentBounds(arbitrary_size)); - VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( - layer->SetContentsScale(arbitrary_number, arbitrary_number)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetDrawsContent(true)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( layer->SetBackgroundColor(arbitrary_color)); @@ -347,10 +341,6 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->Set3dSortingContextId(1)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( layer->SetDoubleSided(false)); // constructor initializes it to "true". - VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( - layer->SetContentBounds(arbitrary_size)); - VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( - layer->SetContentsScale(arbitrary_number, arbitrary_number)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetDrawsContent(true)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( layer->SetBackgroundColor(arbitrary_color)); @@ -369,7 +359,9 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { TEST(LayerImplTest, SafeOpaqueBackgroundColor) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); EXPECT_TRUE(host_impl.InitializeRenderer(FakeOutputSurface::Create3d())); scoped_ptr<LayerImpl> layer = LayerImpl::Create(host_impl.active_tree(), 1); @@ -400,7 +392,9 @@ TEST(LayerImplTest, SafeOpaqueBackgroundColor) { TEST(LayerImplTest, TransformInvertibility) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); scoped_ptr<LayerImpl> layer = LayerImpl::Create(host_impl.active_tree(), 1); EXPECT_TRUE(layer->transform().IsInvertible()); @@ -458,7 +452,6 @@ class LayerImplScrollTest : public testing::Test { LayerTreeSettings settings() { LayerTreeSettings settings; - settings.use_pinch_virtual_viewport = true; return settings; } @@ -682,7 +675,6 @@ class LayerImplScrollbarSyncTest : public testing::Test { LayerTreeSettings settings() { LayerTreeSettings settings; - settings.use_pinch_virtual_viewport = true; return settings; } diff --git a/chromium/cc/layers/layer_iterator.h b/chromium/cc/layers/layer_iterator.h index ba5c6aa5da5..2c129e48cb3 100644 --- a/chromium/cc/layers/layer_iterator.h +++ b/chromium/cc/layers/layer_iterator.h @@ -6,24 +6,24 @@ #define CC_LAYERS_LAYER_ITERATOR_H_ #include "cc/base/cc_export.h" +#include "cc/layers/layer_impl.h" #include "cc/trees/layer_tree_host_common.h" namespace cc { // These classes provide means to iterate over the -// RenderSurface-Layer tree. +// RenderSurfaceImpl-LayerImpl tree. -// Example code follows, for a tree of Layer/RenderSurface objects. +// Example code follows, for a tree of LayerImpl/RenderSurfaceImpl objects. // See below for details. // // void DoStuffOnLayers( -// const RenderSurfaceLayerList& render_surface_layer_list) { -// typedef LayerIterator<Layer> LayerIteratorType; +// const LayerImplList& render_surface_layer_list) { // -// LayerIteratorType end = -// LayerIteratorType::End(&render_surface_layer_list); -// for (LayerIteratorType -// it = LayerIteratorType::Begin(&render_surface_layer_list); +// LayerIterator end = +// LayerIterator::End(&render_surface_layer_list); +// for (LayerIterator +// it = LayerIterator::Begin(&render_surface_layer_list); // it != end; // ++it) { // // Only one of these will be true @@ -79,47 +79,41 @@ namespace cc { //////////////////////////////////////////////////////////////////////////////// -// Non-templated constants struct LayerIteratorValue { static const int kInvalidTargetRenderSurfaceLayerIndex = -1; - // This must be -1 since the iterator action code assumes that this value can - // be reached by subtracting one from the position of the first layer in the - // current target surface's child layer list, which is 0. - static const int kLayerIndexRepresentingTargetRenderSurface = -1; + // This must be (size_t)-1 since the iterator action code assumes that this + // value can be reached by subtracting one from the position of the first + // layer in the current target surface's child layer list, which is 0. + static const size_t kLayerIndexRepresentingTargetRenderSurface = + static_cast<size_t>(-1); }; // The position of a layer iterator that is independent // of its many template types. -template <typename LayerType> struct LayerIteratorPosition { +struct LayerIteratorPosition { bool represents_target_render_surface; bool represents_contributing_render_surface; bool represents_itself; - LayerType* target_render_surface_layer; - LayerType* current_layer; + LayerImpl* target_render_surface_layer; + LayerImpl* current_layer; }; // An iterator class for walking over layers in the // RenderSurface-Layer tree. -template <typename LayerType> +// TODO(enne): This class probably shouldn't be entirely inline and +// should get moved to a .cc file where it makes sense. class LayerIterator { - typedef LayerIterator<LayerType> LayerIteratorType; - typedef typename LayerType::LayerListType LayerList; - typedef typename LayerType::RenderSurfaceListType RenderSurfaceLayerList; - typedef typename LayerType::RenderSurfaceType RenderSurfaceType; - public: LayerIterator() : render_surface_layer_list_(nullptr) {} - static LayerIteratorType Begin( - const RenderSurfaceLayerList* render_surface_layer_list) { - return LayerIteratorType(render_surface_layer_list, true); + static LayerIterator Begin(const LayerImplList* render_surface_layer_list) { + return LayerIterator(render_surface_layer_list, true); } - static LayerIteratorType End( - const RenderSurfaceLayerList* render_surface_layer_list) { - return LayerIteratorType(render_surface_layer_list, false); + static LayerIterator End(const LayerImplList* render_surface_layer_list) { + return LayerIterator(render_surface_layer_list, false); } - LayerIteratorType& operator++() { + LayerIterator& operator++() { MoveToNext(); return *this; } @@ -128,12 +122,12 @@ class LayerIterator { other.target_render_surface_layer_index_ && current_layer_index_ == other.current_layer_index_; } - bool operator!=(const LayerIteratorType& other) const { + bool operator!=(const LayerIterator& other) const { return !(*this == other); } - LayerType* operator->() const { return current_layer(); } - LayerType* operator*() const { return current_layer(); } + LayerImpl* operator->() const { return current_layer(); } + LayerImpl* operator*() const { return current_layer(); } bool represents_target_render_surface() const { return current_layer_represents_target_render_surface(); @@ -147,12 +141,12 @@ class LayerIterator { !represents_contributing_render_surface(); } - LayerType* target_render_surface_layer() const { + LayerImpl* target_render_surface_layer() const { return render_surface_layer_list_->at(target_render_surface_layer_index_); } - operator const LayerIteratorPosition<LayerType>() const { - LayerIteratorPosition<LayerType> position; + operator const LayerIteratorPosition() const { + LayerIteratorPosition position; position.represents_target_render_surface = represents_target_render_surface(); position.represents_contributing_render_surface = @@ -164,8 +158,7 @@ class LayerIterator { } private: - LayerIterator(const RenderSurfaceLayerList* render_surface_layer_list, - bool start) + LayerIterator(const LayerImplList* render_surface_layer_list, bool start) : render_surface_layer_list_(render_surface_layer_list), target_render_surface_layer_index_(0) { for (size_t i = 0; i < render_surface_layer_list->size(); ++i) { @@ -237,7 +230,7 @@ class LayerIterator { int previous_target_render_surface_layer = target_render_surface_layer_index_; - for (LayerType* layer = current_layer(); + for (LayerImpl* layer = current_layer(); target_render_surface_layer() != layer; ++target_render_surface_layer_index_) { } @@ -248,7 +241,7 @@ class LayerIterator { } } - inline LayerType* current_layer() const { + inline LayerImpl* current_layer() const { return current_layer_represents_target_render_surface() ? target_render_surface_layer() : LayerTreeHostCommon::get_layer_as_raw_ptr( @@ -256,7 +249,7 @@ class LayerIterator { } inline bool current_layer_represents_contributing_render_surface() const { - return LayerTreeHostCommon::RenderSurfaceContributesToTarget<LayerType>( + return LayerTreeHostCommon::RenderSurfaceContributesToTarget<LayerImpl>( current_layer(), target_render_surface_layer()->id()); } inline bool current_layer_represents_target_render_surface() const { @@ -264,14 +257,14 @@ class LayerIterator { LayerIteratorValue::kLayerIndexRepresentingTargetRenderSurface; } - inline RenderSurfaceType* target_render_surface() const { + inline RenderSurfaceImpl* target_render_surface() const { return target_render_surface_layer()->render_surface(); } - inline const LayerList& target_render_surface_children() const { + inline const LayerImplList& target_render_surface_children() const { return target_render_surface()->layer_list(); } - const RenderSurfaceLayerList* render_surface_layer_list_; + const LayerImplList* render_surface_layer_list_; // The iterator's current position. @@ -286,9 +279,10 @@ class LayerIterator { // current target surface. When pointing to one of these layers, // this is a value from 0 to n-1 (n = number of children). // Since the iterator must also stop at the layers representing - // the target surface, this is done by setting the current_layerIndex - // to a value of LayerIteratorValue::LayerRepresentingTargetRenderSurface. - int current_layer_index_; + // the target surface, this is done by setting the current_layer_index + // to a value of + // LayerIteratorValue::kLayerIndexRepresentingTargetRenderSurface. + size_t current_layer_index_; }; } // namespace cc diff --git a/chromium/cc/layers/layer_iterator_unittest.cc b/chromium/cc/layers/layer_iterator_unittest.cc index cdc14732b8f..01815f9b36c 100644 --- a/chromium/cc/layers/layer_iterator_unittest.cc +++ b/chromium/cc/layers/layer_iterator_unittest.cc @@ -8,6 +8,7 @@ #include "cc/layers/layer.h" #include "cc/test/fake_layer_tree_host.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host_common.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,27 +22,27 @@ using ::testing::AnyNumber; namespace cc { namespace { -class TestLayer : public Layer { +class TestLayerImpl : public LayerImpl { public: - static scoped_refptr<TestLayer> Create() { - return make_scoped_refptr(new TestLayer()); + static scoped_ptr<TestLayerImpl> Create(LayerTreeImpl* tree, int id) { + return make_scoped_ptr(new TestLayerImpl(tree, id)); } + ~TestLayerImpl() override {} int count_representing_target_surface_; int count_representing_contributing_surface_; int count_representing_itself_; - bool DrawsContent() const override { return draws_content_; } - void set_draws_content(bool draws_content) { draws_content_ = draws_content; } - private: - TestLayer() : Layer(), draws_content_(true) { + explicit TestLayerImpl(LayerTreeImpl* tree, int id) + : LayerImpl(tree, id, new SyncedScrollOffset), + count_representing_target_surface_(-1), + count_representing_contributing_surface_(-1), + count_representing_itself_(-1) { SetBounds(gfx::Size(100, 100)); SetPosition(gfx::Point()); + SetDrawsContent(true); } - ~TestLayer() override {} - - bool draws_content_; }; #define EXPECT_COUNT(layer, target, contrib, itself) \ @@ -49,15 +50,13 @@ class TestLayer : public Layer { EXPECT_EQ(contrib, layer->count_representing_contributing_surface_); \ EXPECT_EQ(itself, layer->count_representing_itself_); -typedef LayerIterator<Layer> FrontToBack; - -void ResetCounts(RenderSurfaceLayerList* render_surface_layer_list) { +void ResetCounts(LayerImplList* render_surface_layer_list) { for (unsigned surface_index = 0; surface_index < render_surface_layer_list->size(); ++surface_index) { - TestLayer* render_surface_layer = static_cast<TestLayer*>( + TestLayerImpl* render_surface_layer = static_cast<TestLayerImpl*>( render_surface_layer_list->at(surface_index)); - RenderSurface* render_surface = render_surface_layer->render_surface(); + RenderSurfaceImpl* render_surface = render_surface_layer->render_surface(); render_surface_layer->count_representing_target_surface_ = -1; render_surface_layer->count_representing_contributing_surface_ = -1; @@ -66,8 +65,8 @@ void ResetCounts(RenderSurfaceLayerList* render_surface_layer_list) { for (unsigned layer_index = 0; layer_index < render_surface->layer_list().size(); ++layer_index) { - TestLayer* layer = static_cast<TestLayer*>( - render_surface->layer_list().at(layer_index).get()); + TestLayerImpl* layer = static_cast<TestLayerImpl*>( + render_surface->layer_list()[layer_index]); layer->count_representing_target_surface_ = -1; layer->count_representing_contributing_surface_ = -1; @@ -76,14 +75,12 @@ void ResetCounts(RenderSurfaceLayerList* render_surface_layer_list) { } } -void IterateFrontToBack( - RenderSurfaceLayerList* render_surface_layer_list) { +void IterateFrontToBack(LayerImplList* render_surface_layer_list) { ResetCounts(render_surface_layer_list); int count = 0; - for (FrontToBack it = FrontToBack::Begin(render_surface_layer_list); - it != FrontToBack::End(render_surface_layer_list); - ++it, ++count) { - TestLayer* layer = static_cast<TestLayer*>(*it); + for (LayerIterator it = LayerIterator::Begin(render_surface_layer_list); + it != LayerIterator::End(render_surface_layer_list); ++it, ++count) { + TestLayerImpl* layer = static_cast<TestLayerImpl*>(*it); if (it.represents_target_render_surface()) layer->count_representing_target_surface_ = count; if (it.represents_contributing_render_surface()) @@ -93,126 +90,167 @@ void IterateFrontToBack( } } -TEST(LayerIteratorTest, EmptyTree) { - RenderSurfaceLayerList render_surface_layer_list; +class LayerIteratorTest : public testing::Test { + public: + LayerIteratorTest() + : host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_), + id_(1) {} + + scoped_ptr<TestLayerImpl> CreateLayer() { + return TestLayerImpl::Create(host_impl_.active_tree(), id_++); + } + + protected: + FakeImplProxy proxy_; + TestSharedBitmapManager shared_bitmap_manager_; + TestTaskGraphRunner task_graph_runner_; + FakeLayerTreeHostImpl host_impl_; + + int id_; +}; + +TEST_F(LayerIteratorTest, EmptyTree) { + LayerImplList render_surface_layer_list; IterateFrontToBack(&render_surface_layer_list); } -TEST(LayerIteratorTest, SimpleTree) { - scoped_refptr<TestLayer> root_layer = TestLayer::Create(); - scoped_refptr<TestLayer> first = TestLayer::Create(); - scoped_refptr<TestLayer> second = TestLayer::Create(); - scoped_refptr<TestLayer> third = TestLayer::Create(); - scoped_refptr<TestLayer> fourth = TestLayer::Create(); - - root_layer->AddChild(first); - root_layer->AddChild(second); - root_layer->AddChild(third); - root_layer->AddChild(fourth); - - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client); - host->SetRootLayer(root_layer); - - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root_layer.get(), root_layer->bounds(), &render_surface_layer_list); +TEST_F(LayerIteratorTest, SimpleTree) { + scoped_ptr<TestLayerImpl> root_layer = CreateLayer(); + scoped_ptr<TestLayerImpl> first = CreateLayer(); + scoped_ptr<TestLayerImpl> second = CreateLayer(); + scoped_ptr<TestLayerImpl> third = CreateLayer(); + scoped_ptr<TestLayerImpl> fourth = CreateLayer(); + + TestLayerImpl* root_ptr = root_layer.get(); + TestLayerImpl* first_ptr = first.get(); + TestLayerImpl* second_ptr = second.get(); + TestLayerImpl* third_ptr = third.get(); + TestLayerImpl* fourth_ptr = fourth.get(); + + root_layer->AddChild(first.Pass()); + root_layer->AddChild(second.Pass()); + root_layer->AddChild(third.Pass()); + root_layer->AddChild(fourth.Pass()); + + root_layer->SetHasRenderSurface(true); + host_impl_.active_tree()->SetRootLayer(root_layer.Pass()); + + LayerImplList render_surface_layer_list; + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root_ptr, root_ptr->bounds(), &render_surface_layer_list); LayerTreeHostCommon::CalculateDrawProperties(&inputs); IterateFrontToBack(&render_surface_layer_list); - EXPECT_COUNT(root_layer, 5, -1, 4); - EXPECT_COUNT(first, -1, -1, 3); - EXPECT_COUNT(second, -1, -1, 2); - EXPECT_COUNT(third, -1, -1, 1); - EXPECT_COUNT(fourth, -1, -1, 0); + EXPECT_COUNT(root_ptr, 5, -1, 4); + EXPECT_COUNT(first_ptr, -1, -1, 3); + EXPECT_COUNT(second_ptr, -1, -1, 2); + EXPECT_COUNT(third_ptr, -1, -1, 1); + EXPECT_COUNT(fourth_ptr, -1, -1, 0); } -TEST(LayerIteratorTest, ComplexTree) { - scoped_refptr<TestLayer> root_layer = TestLayer::Create(); - scoped_refptr<TestLayer> root1 = TestLayer::Create(); - scoped_refptr<TestLayer> root2 = TestLayer::Create(); - scoped_refptr<TestLayer> root3 = TestLayer::Create(); - scoped_refptr<TestLayer> root21 = TestLayer::Create(); - scoped_refptr<TestLayer> root22 = TestLayer::Create(); - scoped_refptr<TestLayer> root23 = TestLayer::Create(); - scoped_refptr<TestLayer> root221 = TestLayer::Create(); - scoped_refptr<TestLayer> root231 = TestLayer::Create(); - - root_layer->AddChild(root1); - root_layer->AddChild(root2); - root_layer->AddChild(root3); - root2->AddChild(root21); - root2->AddChild(root22); - root2->AddChild(root23); - root22->AddChild(root221); - root23->AddChild(root231); - - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client); - host->SetRootLayer(root_layer); - - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root_layer.get(), root_layer->bounds(), &render_surface_layer_list); +TEST_F(LayerIteratorTest, ComplexTree) { + scoped_ptr<TestLayerImpl> root_layer = CreateLayer(); + scoped_ptr<TestLayerImpl> root1 = CreateLayer(); + scoped_ptr<TestLayerImpl> root2 = CreateLayer(); + scoped_ptr<TestLayerImpl> root3 = CreateLayer(); + scoped_ptr<TestLayerImpl> root21 = CreateLayer(); + scoped_ptr<TestLayerImpl> root22 = CreateLayer(); + scoped_ptr<TestLayerImpl> root23 = CreateLayer(); + scoped_ptr<TestLayerImpl> root221 = CreateLayer(); + scoped_ptr<TestLayerImpl> root231 = CreateLayer(); + + TestLayerImpl* root_ptr = root_layer.get(); + TestLayerImpl* root1_ptr = root1.get(); + TestLayerImpl* root2_ptr = root2.get(); + TestLayerImpl* root3_ptr = root3.get(); + TestLayerImpl* root21_ptr = root21.get(); + TestLayerImpl* root22_ptr = root22.get(); + TestLayerImpl* root23_ptr = root23.get(); + TestLayerImpl* root221_ptr = root221.get(); + TestLayerImpl* root231_ptr = root231.get(); + + root22->AddChild(root221.Pass()); + root23->AddChild(root231.Pass()); + root2->AddChild(root21.Pass()); + root2->AddChild(root22.Pass()); + root2->AddChild(root23.Pass()); + root_layer->AddChild(root1.Pass()); + root_layer->AddChild(root2.Pass()); + root_layer->AddChild(root3.Pass()); + + root_layer->SetHasRenderSurface(true); + host_impl_.active_tree()->SetRootLayer(root_layer.Pass()); + + LayerImplList render_surface_layer_list; + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root_ptr, root_ptr->bounds(), &render_surface_layer_list); LayerTreeHostCommon::CalculateDrawProperties(&inputs); IterateFrontToBack(&render_surface_layer_list); - EXPECT_COUNT(root_layer, 9, -1, 8); - EXPECT_COUNT(root1, -1, -1, 7); - EXPECT_COUNT(root2, -1, -1, 6); - EXPECT_COUNT(root21, -1, -1, 5); - EXPECT_COUNT(root22, -1, -1, 4); - EXPECT_COUNT(root221, -1, -1, 3); - EXPECT_COUNT(root23, -1, -1, 2); - EXPECT_COUNT(root231, -1, -1, 1); - EXPECT_COUNT(root3, -1, -1, 0); + EXPECT_COUNT(root_ptr, 9, -1, 8); + EXPECT_COUNT(root1_ptr, -1, -1, 7); + EXPECT_COUNT(root2_ptr, -1, -1, 6); + EXPECT_COUNT(root21_ptr, -1, -1, 5); + EXPECT_COUNT(root22_ptr, -1, -1, 4); + EXPECT_COUNT(root221_ptr, -1, -1, 3); + EXPECT_COUNT(root23_ptr, -1, -1, 2); + EXPECT_COUNT(root231_ptr, -1, -1, 1); + EXPECT_COUNT(root3_ptr, -1, -1, 0); } -TEST(LayerIteratorTest, ComplexTreeMultiSurface) { - scoped_refptr<TestLayer> root_layer = TestLayer::Create(); - scoped_refptr<TestLayer> root1 = TestLayer::Create(); - scoped_refptr<TestLayer> root2 = TestLayer::Create(); - scoped_refptr<TestLayer> root3 = TestLayer::Create(); - scoped_refptr<TestLayer> root21 = TestLayer::Create(); - scoped_refptr<TestLayer> root22 = TestLayer::Create(); - scoped_refptr<TestLayer> root23 = TestLayer::Create(); - scoped_refptr<TestLayer> root221 = TestLayer::Create(); - scoped_refptr<TestLayer> root231 = TestLayer::Create(); - - root_layer->AddChild(root1); - root_layer->AddChild(root2); - root_layer->AddChild(root3); - root2->set_draws_content(false); - root2->SetOpacity(0.5f); - root2->SetForceRenderSurface(true); // Force the layer to own a new surface. - root2->AddChild(root21); - root2->AddChild(root22); - root2->AddChild(root23); - root22->SetOpacity(0.5f); - root22->AddChild(root221); - root23->SetOpacity(0.5f); - root23->AddChild(root231); - - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client); - host->SetRootLayer(root_layer); - - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root_layer.get(), root_layer->bounds(), &render_surface_layer_list); +TEST_F(LayerIteratorTest, ComplexTreeMultiSurface) { + scoped_ptr<TestLayerImpl> root_layer = CreateLayer(); + scoped_ptr<TestLayerImpl> root1 = CreateLayer(); + scoped_ptr<TestLayerImpl> root2 = CreateLayer(); + scoped_ptr<TestLayerImpl> root3 = CreateLayer(); + scoped_ptr<TestLayerImpl> root21 = CreateLayer(); + scoped_ptr<TestLayerImpl> root22 = CreateLayer(); + scoped_ptr<TestLayerImpl> root23 = CreateLayer(); + scoped_ptr<TestLayerImpl> root221 = CreateLayer(); + scoped_ptr<TestLayerImpl> root231 = CreateLayer(); + + TestLayerImpl* root_ptr = root_layer.get(); + TestLayerImpl* root1_ptr = root1.get(); + TestLayerImpl* root2_ptr = root2.get(); + TestLayerImpl* root3_ptr = root3.get(); + TestLayerImpl* root21_ptr = root21.get(); + TestLayerImpl* root22_ptr = root22.get(); + TestLayerImpl* root23_ptr = root23.get(); + TestLayerImpl* root221_ptr = root221.get(); + TestLayerImpl* root231_ptr = root231.get(); + + root22->SetHasRenderSurface(true); + root22->AddChild(root221.Pass()); + root23->SetHasRenderSurface(true); + root23->AddChild(root231.Pass()); + root2->SetDrawsContent(false); + root2->SetHasRenderSurface(true); + root2->AddChild(root21.Pass()); + root2->AddChild(root22.Pass()); + root2->AddChild(root23.Pass()); + root_layer->AddChild(root1.Pass()); + root_layer->AddChild(root2.Pass()); + root_layer->AddChild(root3.Pass()); + + root_layer->SetHasRenderSurface(true); + host_impl_.active_tree()->SetRootLayer(root_layer.Pass()); + + LayerImplList render_surface_layer_list; + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root_ptr, root_ptr->bounds(), &render_surface_layer_list); LayerTreeHostCommon::CalculateDrawProperties(&inputs); IterateFrontToBack(&render_surface_layer_list); - EXPECT_COUNT(root_layer, 14, -1, 13); - EXPECT_COUNT(root1, -1, -1, 12); - EXPECT_COUNT(root2, 10, 11, -1); - EXPECT_COUNT(root21, -1, -1, 9); - EXPECT_COUNT(root22, 7, 8, 6); - EXPECT_COUNT(root221, -1, -1, 5); - EXPECT_COUNT(root23, 3, 4, 2); - EXPECT_COUNT(root231, -1, -1, 1); - EXPECT_COUNT(root3, -1, -1, 0); + EXPECT_COUNT(root_ptr, 14, -1, 13); + EXPECT_COUNT(root1_ptr, -1, -1, 12); + EXPECT_COUNT(root2_ptr, 10, 11, -1); + EXPECT_COUNT(root21_ptr, -1, -1, 9); + EXPECT_COUNT(root22_ptr, 7, 8, 6); + EXPECT_COUNT(root221_ptr, -1, -1, 5); + EXPECT_COUNT(root23_ptr, 3, 4, 2); + EXPECT_COUNT(root231_ptr, -1, -1, 1); + EXPECT_COUNT(root3_ptr, -1, -1, 0); } } // namespace diff --git a/chromium/cc/layers/layer_perftest.cc b/chromium/cc/layers/layer_perftest.cc index c7cac01f5b2..0c0fb4185a4 100644 --- a/chromium/cc/layers/layer_perftest.cc +++ b/chromium/cc/layers/layer_perftest.cc @@ -6,7 +6,6 @@ #include "base/thread_task_runner_handle.h" #include "cc/debug/lap_timer.h" -#include "cc/resources/layer_painter.h" #include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -22,12 +21,6 @@ static const int kTimeLimitMillis = 3000; static const int kWarmupRuns = 5; static const int kTimeCheckInterval = 10; -class MockLayerPainter : public LayerPainter { - public: - void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) override {} -}; - - class LayerPerfTest : public testing::Test { public: LayerPerfTest() @@ -39,7 +32,8 @@ class LayerPerfTest : public testing::Test { protected: void SetUp() override { - layer_tree_host_ = FakeLayerTreeHost::Create(&fake_client_); + layer_tree_host_ = + FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_); layer_tree_host_->InitializeSingleThreaded( &fake_client_, base::ThreadTaskRunnerHandle::Get(), nullptr); } @@ -60,7 +54,7 @@ class LayerPerfTest : public testing::Test { }; TEST_F(LayerPerfTest, PushPropertiesTo) { - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(LayerSettings()); scoped_ptr<LayerImpl> impl_layer = LayerImpl::Create(host_impl_.active_tree(), 1); diff --git a/chromium/cc/layers/layer_position_constraint_unittest.cc b/chromium/cc/layers/layer_position_constraint_unittest.cc index 1eea9c98b44..fdb7f5b6ea4 100644 --- a/chromium/cc/layers/layer_position_constraint_unittest.cc +++ b/chromium/cc/layers/layer_position_constraint_unittest.cc @@ -6,11 +6,10 @@ #include <vector> +#include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" -#include "cc/test/fake_impl_proxy.h" -#include "cc/test/fake_layer_tree_host_impl.h" +#include "cc/test/fake_layer_tree_host.h" #include "cc/test/geometry_test_utils.h" -#include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host_common.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,7 +17,22 @@ namespace cc { namespace { -void SetLayerPropertiesForTesting(LayerImpl* layer, +class LayerWithForcedDrawsContent : public Layer { + public: + explicit LayerWithForcedDrawsContent(const LayerSettings& settings) + : Layer(settings) {} + + bool DrawsContent() const override; + + private: + ~LayerWithForcedDrawsContent() override {} +}; + +bool LayerWithForcedDrawsContent::DrawsContent() const { + return true; +} + +void SetLayerPropertiesForTesting(Layer* layer, const gfx::Transform& transform, const gfx::Point3F& transform_origin, const gfx::PointF& position, @@ -29,110 +43,147 @@ void SetLayerPropertiesForTesting(LayerImpl* layer, layer->SetPosition(position); layer->SetBounds(bounds); layer->SetShouldFlattenTransform(flatten_transform); - layer->SetContentBounds(bounds); } -void ExecuteCalculateDrawProperties(LayerImpl* root_layer, - float device_scale_factor, - float page_scale_factor, - LayerImpl* page_scale_application_layer, - bool can_use_lcd_text) { - gfx::Transform identity_matrix; +void ExecuteCalculateDrawProperties(LayerImpl* root_layer) { std::vector<LayerImpl*> dummy_render_surface_layer_list; - LayerImpl* scroll_layer = root_layer->children()[0]; - gfx::Size device_viewport_size = - gfx::Size(root_layer->bounds().width() * device_scale_factor, - root_layer->bounds().height() * device_scale_factor); - - // We are probably not testing what is intended if the scroll_layer bounds are - // empty. - DCHECK(!scroll_layer->bounds().IsEmpty()); LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( - root_layer, device_viewport_size, &dummy_render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = page_scale_application_layer; - inputs.can_use_lcd_text = can_use_lcd_text; + root_layer, root_layer->bounds(), &dummy_render_surface_layer_list); + inputs.inner_viewport_scroll_layer = + root_layer->layer_tree_impl()->InnerViewportScrollLayer(); + inputs.outer_viewport_scroll_layer = + root_layer->layer_tree_impl()->OuterViewportScrollLayer(); LayerTreeHostCommon::CalculateDrawProperties(&inputs); } -void ExecuteCalculateDrawProperties(LayerImpl* root_layer) { - LayerImpl* page_scale_application_layer = nullptr; - ExecuteCalculateDrawProperties( - root_layer, 1.f, 1.f, page_scale_application_layer, false); -} - class LayerPositionConstraintTest : public testing::Test { public: LayerPositionConstraintTest() - : host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_) { - root_ = CreateTreeForTest(); - scroll_ = root_->children()[0]; + : fake_client_(FakeLayerTreeHostClient::DIRECT_3D), + layer_tree_host_( + FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_)), + root_impl_(nullptr), + inner_viewport_container_layer_impl_(nullptr), + scroll_layer_impl_(nullptr), + outer_viewport_container_layer_impl_(nullptr), + child_transform_layer_impl_(nullptr), + child_impl_(nullptr), + grand_child_impl_(nullptr), + great_grand_child_impl_(nullptr) { + layer_tree_host_->InitializeForTesting(scoped_ptr<Proxy>(new FakeProxy)); + CreateTreeForTest(); fixed_to_top_left_.set_is_fixed_position(true); fixed_to_bottom_right_.set_is_fixed_position(true); fixed_to_bottom_right_.set_is_fixed_to_right_edge(true); fixed_to_bottom_right_.set_is_fixed_to_bottom_edge(true); } - scoped_ptr<LayerImpl> CreateTreeForTest() { - scoped_ptr<LayerImpl> root = - LayerImpl::Create(host_impl_.active_tree(), 42); - scoped_ptr<LayerImpl> scroll_layer = - LayerImpl::Create(host_impl_.active_tree(), 1); - scoped_ptr<LayerImpl> child = - LayerImpl::Create(host_impl_.active_tree(), 2); - scoped_ptr<LayerImpl> grand_child = - LayerImpl::Create(host_impl_.active_tree(), 3); - scoped_ptr<LayerImpl> great_grand_child = - LayerImpl::Create(host_impl_.active_tree(), 4); - - root->SetHasRenderSurface(true); + void CreateTreeForTest() { + // scroll_layer_ is the inner viewport scroll layer and child_ is the outer + // viewport scroll layer. + root_ = Layer::Create(layer_settings_); + inner_viewport_container_layer_ = Layer::Create(layer_settings_); + scroll_layer_ = Layer::Create(layer_settings_); + outer_viewport_container_layer_ = Layer::Create(layer_settings_); + child_transform_layer_ = Layer::Create(layer_settings_); + child_ = Layer::Create(layer_settings_); + grand_child_ = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings_)); + great_grand_child_ = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings_)); + gfx::Transform IdentityMatrix; gfx::Point3F transform_origin; gfx::PointF position; gfx::Size bounds(200, 200); gfx::Size clip_bounds(100, 100); - SetLayerPropertiesForTesting(scroll_layer.get(), - IdentityMatrix, - transform_origin, - position, - bounds, - true); - SetLayerPropertiesForTesting( - child.get(), IdentityMatrix, transform_origin, position, bounds, true); - SetLayerPropertiesForTesting(grand_child.get(), - IdentityMatrix, - transform_origin, - position, - bounds, - true); - SetLayerPropertiesForTesting(great_grand_child.get(), - IdentityMatrix, - transform_origin, - position, - bounds, - true); - - root->SetBounds(clip_bounds); - scroll_layer->SetScrollClipLayer(root->id()); - child->SetScrollClipLayer(root->id()); - grand_child->SetScrollClipLayer(root->id()); - - grand_child->AddChild(great_grand_child.Pass()); - child->AddChild(grand_child.Pass()); - scroll_layer->AddChild(child.Pass()); - root->AddChild(scroll_layer.Pass()); - - return root.Pass(); + SetLayerPropertiesForTesting(inner_viewport_container_layer_.get(), + IdentityMatrix, transform_origin, position, + clip_bounds, true); + SetLayerPropertiesForTesting(scroll_layer_.get(), IdentityMatrix, + transform_origin, position, bounds, true); + SetLayerPropertiesForTesting(outer_viewport_container_layer_.get(), + IdentityMatrix, transform_origin, position, + clip_bounds, true); + SetLayerPropertiesForTesting(child_.get(), IdentityMatrix, transform_origin, + position, bounds, true); + SetLayerPropertiesForTesting(grand_child_.get(), IdentityMatrix, + transform_origin, position, bounds, true); + SetLayerPropertiesForTesting(great_grand_child_.get(), IdentityMatrix, + transform_origin, position, bounds, true); + + root_->SetBounds(clip_bounds); + + inner_viewport_container_layer_->SetMasksToBounds(true); + scroll_layer_->SetScrollClipLayerId(inner_viewport_container_layer_->id()); + scroll_layer_->SetIsContainerForFixedPositionLayers(true); + + outer_viewport_container_layer_->SetMasksToBounds(true); + child_->SetScrollClipLayerId(outer_viewport_container_layer_->id()); + grand_child_->SetScrollClipLayerId(outer_viewport_container_layer_->id()); + + grand_child_->AddChild(great_grand_child_); + child_->AddChild(grand_child_); + child_transform_layer_->AddChild(child_); + outer_viewport_container_layer_->AddChild(child_transform_layer_); + scroll_layer_->AddChild(outer_viewport_container_layer_); + inner_viewport_container_layer_->AddChild(scroll_layer_); + root_->AddChild(inner_viewport_container_layer_); + + layer_tree_host_->SetRootLayer(root_); + layer_tree_host_->RegisterViewportLayers(nullptr, root_, scroll_layer_, + child_); + } + + void CommitAndUpdateImplPointers() { + RenderSurfaceLayerList render_surface_layer_list; + LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( + root_.get(), root_->bounds(), &render_surface_layer_list); + inputs.inner_viewport_scroll_layer = + layer_tree_host_->inner_viewport_scroll_layer(); + inputs.outer_viewport_scroll_layer = + layer_tree_host_->outer_viewport_scroll_layer(); + LayerTreeHostCommon::CalculateDrawProperties(&inputs); + + // Since scroll deltas aren't sent back to the main thread in this test + // setup, clear them to maintain consistent state. + if (root_impl_) { + scroll_layer_impl_->SetScrollDelta(gfx::Vector2dF()); + child_impl_->SetScrollDelta(gfx::Vector2dF()); + grand_child_impl_->SetScrollDelta(gfx::Vector2dF()); + } + root_impl_ = layer_tree_host_->CommitAndCreateLayerImplTree(); + inner_viewport_container_layer_impl_ = root_impl_->children()[0]; + scroll_layer_impl_ = inner_viewport_container_layer_impl_->children()[0]; + outer_viewport_container_layer_impl_ = scroll_layer_impl_->children()[0]; + child_transform_layer_impl_ = + outer_viewport_container_layer_impl_->children()[0]; + child_impl_ = child_transform_layer_impl_->children()[0]; + grand_child_impl_ = child_impl_->children()[0]; + great_grand_child_impl_ = grand_child_impl_->children()[0]; } protected: - FakeImplProxy proxy_; - TestSharedBitmapManager shared_bitmap_manager_; + FakeLayerTreeHostClient fake_client_; TestTaskGraphRunner task_graph_runner_; - FakeLayerTreeHostImpl host_impl_; - scoped_ptr<LayerImpl> root_; - LayerImpl* scroll_; + scoped_ptr<FakeLayerTreeHost> layer_tree_host_; + LayerSettings layer_settings_; + scoped_refptr<Layer> root_; + scoped_refptr<Layer> inner_viewport_container_layer_; + scoped_refptr<Layer> scroll_layer_; + scoped_refptr<Layer> outer_viewport_container_layer_; + scoped_refptr<Layer> child_transform_layer_; + scoped_refptr<Layer> child_; + scoped_refptr<Layer> grand_child_; + scoped_refptr<Layer> great_grand_child_; + LayerImpl* root_impl_; + LayerImpl* inner_viewport_container_layer_impl_; + LayerImpl* scroll_layer_impl_; + LayerImpl* outer_viewport_container_layer_impl_; + LayerImpl* child_transform_layer_impl_; + LayerImpl* child_impl_; + LayerImpl* grand_child_impl_; + LayerImpl* great_grand_child_impl_; LayerPositionConstraint fixed_to_top_left_; LayerPositionConstraint fixed_to_bottom_right_; @@ -154,27 +205,26 @@ TEST_F(LayerPositionConstraintTest, ScrollCompensationForFixedPositionLayerWithDirectContainer) { // This test checks for correct scroll compensation when the fixed-position // container is the direct parent of the fixed-position layer. - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; + child_->SetIsContainerForFixedPositionLayers(true); + grand_child_->SetPositionConstraint(fixed_to_top_left_); - child->SetIsContainerForFixedPositionLayers(true); - grand_child->SetPositionConstraint(fixed_to_top_left_); + CommitAndUpdateImplPointers(); // Case 1: scroll delta of 0, 0 - child->SetScrollDelta(gfx::Vector2d(0, 0)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(0, 0)); + ExecuteCalculateDrawProperties(root_impl_); gfx::Transform expected_child_transform; gfx::Transform expected_grand_child_transform = expected_child_transform; EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); // Case 2: scroll delta of 10, 10 - child->SetScrollDelta(gfx::Vector2d(10, 10)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + ExecuteCalculateDrawProperties(root_impl_); // Here the child is affected by scroll delta, but the fixed position // grand_child should not be affected. @@ -182,129 +232,52 @@ TEST_F(LayerPositionConstraintTest, expected_child_transform.Translate(-10.0, -10.0); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); // Case 3: fixed-container size delta of 20, 20 - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Top-left fixed-position layer should not be affected by container size. EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); // Case 4: Bottom-right fixed-position layer. - grand_child->SetPositionConstraint(fixed_to_bottom_right_); - ExecuteCalculateDrawProperties(root_.get()); + grand_child_->SetPositionConstraint(fixed_to_bottom_right_); + CommitAndUpdateImplPointers(); - // Bottom-right fixed-position layer moves as container resizes. - expected_grand_child_transform.MakeIdentity(); - // Apply size delta from the child(container) layer. - expected_grand_child_transform.Translate(20.0, 20.0); - - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); -} - -TEST_F(LayerPositionConstraintTest, - ScrollCompensationForFixedPositionLayerWithTransformedDirectContainer) { - // This test checks for correct scroll compensation when the fixed-position - // container is the direct parent of the fixed-position layer, but that - // container is transformed. In this case, the fixed position element - // inherits the container's transform, but the scroll delta that has to be - // undone should not be affected by that transform. - // - // Transforms are in general non-commutative; using something like a - // non-uniform scale helps to verify that translations and non-uniform scales - // are applied in the correct order. - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; - - // This scale will cause child and grand_child to be effectively 200 x 800 - // with respect to the render target. - gfx::Transform non_uniform_scale; - non_uniform_scale.Scale(2.0, 8.0); - child->SetTransform(non_uniform_scale); - - child->SetIsContainerForFixedPositionLayers(true); - grand_child->SetPositionConstraint(fixed_to_top_left_); - - // Case 1: scroll delta of 0, 0 - child->SetScrollDelta(gfx::Vector2d(0, 0)); - ExecuteCalculateDrawProperties(root_.get()); - - gfx::Transform expected_child_transform; - expected_child_transform.PreconcatTransform(non_uniform_scale); - - gfx::Transform expected_grand_child_transform = expected_child_transform; - - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); - - // Case 2: scroll delta of 10, 20 - child->SetScrollDelta(gfx::Vector2d(10, 20)); - ExecuteCalculateDrawProperties(root_.get()); - - // The child should be affected by scroll delta, but the fixed position - // grand_child should not be affected. - expected_child_transform.MakeIdentity(); - expected_child_transform.Translate(-10.0, -20.0); // scroll delta - expected_child_transform.PreconcatTransform(non_uniform_scale); - - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); - - // Case 3: fixed-container size delta of 20, 20 - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); - - // Top-left fixed-position layer should not be affected by container size. - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); - - // Case 4: Bottom-right fixed-position layer. - grand_child->SetPositionConstraint(fixed_to_bottom_right_); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Bottom-right fixed-position layer moves as container resizes. expected_grand_child_transform.MakeIdentity(); - // Apply child layer transform. - expected_grand_child_transform.PreconcatTransform(non_uniform_scale); // Apply size delta from the child(container) layer. expected_grand_child_transform.Translate(20.0, 20.0); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); } TEST_F(LayerPositionConstraintTest, ScrollCompensationForFixedPositionLayerWithDistantContainer) { // This test checks for correct scroll compensation when the fixed-position // container is NOT the direct parent of the fixed-position layer. - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; - LayerImpl* great_grand_child = grand_child->children()[0]; + child_->SetIsContainerForFixedPositionLayers(true); + grand_child_->SetPosition(gfx::PointF(8.f, 6.f)); + great_grand_child_->SetPositionConstraint(fixed_to_top_left_); - child->SetIsContainerForFixedPositionLayers(true); - grand_child->SetPosition(gfx::PointF(8.f, 6.f)); - great_grand_child->SetPositionConstraint(fixed_to_top_left_); + CommitAndUpdateImplPointers(); // Case 1: scroll delta of 0, 0 - child->SetScrollDelta(gfx::Vector2d(0, 0)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(0, 0)); + ExecuteCalculateDrawProperties(root_impl_); gfx::Transform expected_child_transform; gfx::Transform expected_grand_child_transform; @@ -314,15 +287,15 @@ TEST_F(LayerPositionConstraintTest, expected_grand_child_transform; EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); // Case 2: scroll delta of 10, 10 - child->SetScrollDelta(gfx::Vector2d(10, 10)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + ExecuteCalculateDrawProperties(root_impl_); // Here the child and grand_child are affected by scroll delta, but the fixed // position great_grand_child should not be affected. @@ -331,179 +304,64 @@ TEST_F(LayerPositionConstraintTest, expected_grand_child_transform.MakeIdentity(); expected_grand_child_transform.Translate(-2.0, -4.0); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); - - // Case 3: fixed-container size delta of 20, 20 - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); - - // Top-left fixed-position layer should not be affected by container size. - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); - - // Case 4: Bottom-right fixed-position layer. - great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); - ExecuteCalculateDrawProperties(root_.get()); - - // Bottom-right fixed-position layer moves as container resizes. - expected_great_grand_child_transform.MakeIdentity(); - // Apply size delta from the child(container) layer. - expected_great_grand_child_transform.Translate(20.0, 20.0); - // Apply layer position from the grand child layer. - expected_great_grand_child_transform.Translate(8.0, 6.0); - - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); -} - -TEST_F(LayerPositionConstraintTest, - ScrollCompensationForFixedPositionLayerWithDistantContainerAndTransforms) { - // This test checks for correct scroll compensation when the fixed-position - // container is NOT the direct parent of the fixed-position layer, and the - // hierarchy has various transforms that have to be processed in the correct - // order. - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; - LayerImpl* great_grand_child = grand_child->children()[0]; - - gfx::Transform rotation_about_z; - rotation_about_z.RotateAboutZAxis(90.0); - - child->SetIsContainerForFixedPositionLayers(true); - child->SetTransform(rotation_about_z); - grand_child->SetPosition(gfx::PointF(8.f, 6.f)); - grand_child->SetTransform(rotation_about_z); - // great_grand_child is positioned upside-down with respect to the render - // target. - great_grand_child->SetPositionConstraint(fixed_to_top_left_); - - // Case 1: scroll delta of 0, 0 - child->SetScrollDelta(gfx::Vector2d(0, 0)); - ExecuteCalculateDrawProperties(root_.get()); - - gfx::Transform expected_child_transform; - expected_child_transform.PreconcatTransform(rotation_about_z); - - gfx::Transform expected_grand_child_transform; - expected_grand_child_transform.PreconcatTransform( - rotation_about_z); // child's local transform is inherited - // translation because of position occurs before layer's local transform. - expected_grand_child_transform.Translate(8.0, 6.0); - expected_grand_child_transform.PreconcatTransform( - rotation_about_z); // grand_child's local transform - - gfx::Transform expected_great_grand_child_transform = - expected_grand_child_transform; - - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); - - // Case 2: scroll delta of 10, 20 - child->SetScrollDelta(gfx::Vector2d(10, 20)); - ExecuteCalculateDrawProperties(root_.get()); - - // Here the child and grand_child are affected by scroll delta, but the fixed - // position great_grand_child should not be affected. - expected_child_transform.MakeIdentity(); - expected_child_transform.Translate(-10.0, -20.0); // scroll delta - expected_child_transform.PreconcatTransform(rotation_about_z); - - expected_grand_child_transform.MakeIdentity(); - expected_grand_child_transform.Translate( - -10.0, -20.0); // child's scroll delta is inherited - expected_grand_child_transform.PreconcatTransform( - rotation_about_z); // child's local transform is inherited - // translation because of position occurs before layer's local transform. - expected_grand_child_transform.Translate(8.0, 6.0); - expected_grand_child_transform.PreconcatTransform( - rotation_about_z); // grand_child's local transform - - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); // Case 3: fixed-container size delta of 20, 20 - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Top-left fixed-position layer should not be affected by container size. EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); // Case 4: Bottom-right fixed-position layer. - great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); - ExecuteCalculateDrawProperties(root_.get()); + great_grand_child_->SetPositionConstraint(fixed_to_bottom_right_); + CommitAndUpdateImplPointers(); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Bottom-right fixed-position layer moves as container resizes. expected_great_grand_child_transform.MakeIdentity(); - // Apply child layer transform. - expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); // Apply size delta from the child(container) layer. expected_great_grand_child_transform.Translate(20.0, 20.0); // Apply layer position from the grand child layer. expected_great_grand_child_transform.Translate(8.0, 6.0); - // Apply grand child layer transform. - expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); } TEST_F(LayerPositionConstraintTest, ScrollCompensationForFixedPositionLayerWithMultipleScrollDeltas) { // This test checks for correct scroll compensation when the fixed-position // container has multiple ancestors that have nonzero scroll delta before - // reaching the space where the layer is fixed. In this test, each scroll - // delta occurs in a different space because of each layer's local transform. - // This test checks for correct scroll compensation when the fixed-position - // container is NOT the direct parent of the fixed-position layer, and the - // hierarchy has various transforms that have to be processed in the correct - // order. - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; - LayerImpl* great_grand_child = grand_child->children()[0]; - + // reaching the space where the layer is fixed. gfx::Transform rotation_about_z; rotation_about_z.RotateAboutZAxis(90.0); - child->SetIsContainerForFixedPositionLayers(true); - child->SetTransform(rotation_about_z); - grand_child->SetPosition(gfx::PointF(8.f, 6.f)); - grand_child->SetTransform(rotation_about_z); - // great_grand_child is positioned upside-down with respect to the render - // target. - great_grand_child->SetPositionConstraint(fixed_to_top_left_); + child_transform_layer_->SetIsContainerForFixedPositionLayers(true); + child_transform_layer_->SetTransform(rotation_about_z); + grand_child_->SetPosition(gfx::PointF(8.f, 6.f)); + great_grand_child_->SetPositionConstraint(fixed_to_top_left_); + + CommitAndUpdateImplPointers(); // Case 1: scroll delta of 0, 0 - child->SetScrollDelta(gfx::Vector2d(0, 0)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(0, 0)); + ExecuteCalculateDrawProperties(root_impl_); gfx::Transform expected_child_transform; expected_child_transform.PreconcatTransform(rotation_about_z); @@ -513,82 +371,44 @@ TEST_F(LayerPositionConstraintTest, rotation_about_z); // child's local transform is inherited // translation because of position occurs before layer's local transform. expected_grand_child_transform.Translate(8.0, 6.0); - expected_grand_child_transform.PreconcatTransform( - rotation_about_z); // grand_child's local transform gfx::Transform expected_great_grand_child_transform = expected_grand_child_transform; EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); // Case 2: scroll delta of 10, 20 - child->SetScrollDelta(gfx::Vector2d(10, 0)); - grand_child->SetScrollDelta(gfx::Vector2d(5, 0)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 0)); + grand_child_impl_->SetScrollDelta(gfx::Vector2d(5, 0)); + ExecuteCalculateDrawProperties(root_impl_); // Here the child and grand_child are affected by scroll delta, but the fixed // position great_grand_child should not be affected. expected_child_transform.MakeIdentity(); - expected_child_transform.Translate(-10.0, 0.0); // scroll delta expected_child_transform.PreconcatTransform(rotation_about_z); + expected_child_transform.Translate(-10.0, 0.0); // scroll delta expected_grand_child_transform.MakeIdentity(); - expected_grand_child_transform.Translate( - -10.0, 0.0); // child's scroll delta is inherited expected_grand_child_transform.PreconcatTransform( rotation_about_z); // child's local transform is inherited + expected_grand_child_transform.Translate( + -10.0, 0.0); // child's scroll delta is inherited expected_grand_child_transform.Translate(-5.0, 0.0); // grand_child's scroll delta - // translation because of position occurs before layer's local transform. + // translation because of position expected_grand_child_transform.Translate(8.0, 6.0); - expected_grand_child_transform.PreconcatTransform( - rotation_about_z); // grand_child's local transform EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); - - // Case 3: fixed-container size delta of 20, 20 - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); - - // Top-left fixed-position layer should not be affected by container size. - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); - - // Case 4: Bottom-right fixed-position layer. - great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); - ExecuteCalculateDrawProperties(root_.get()); - - // Bottom-right fixed-position layer moves as container resizes. - expected_great_grand_child_transform.MakeIdentity(); - // Apply child layer transform. - expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); - // Apply size delta from the child(container) layer. - expected_great_grand_child_transform.Translate(20.0, 20.0); - // Apply layer position from the grand child layer. - expected_great_grand_child_transform.Translate(8.0, 6.0); - // Apply grand child layer transform. - expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); - - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); } TEST_F(LayerPositionConstraintTest, @@ -597,44 +417,41 @@ TEST_F(LayerPositionConstraintTest, // container contributes to a different render surface than the fixed-position // layer. In this case, the surface draw transforms also have to be accounted // for when checking the scroll delta. - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; - LayerImpl* great_grand_child = grand_child->children()[0]; - - child->SetIsContainerForFixedPositionLayers(true); - grand_child->SetPosition(gfx::PointF(8.f, 6.f)); - grand_child->SetHasRenderSurface(true); - great_grand_child->SetPositionConstraint(fixed_to_top_left_); - great_grand_child->SetDrawsContent(true); + child_->SetIsContainerForFixedPositionLayers(true); + grand_child_->SetPosition(gfx::PointF(8.f, 6.f)); + grand_child_->SetForceRenderSurface(true); + great_grand_child_->SetPositionConstraint(fixed_to_top_left_); gfx::Transform rotation_about_z; rotation_about_z.RotateAboutZAxis(90.0); - grand_child->SetTransform(rotation_about_z); + great_grand_child_->SetTransform(rotation_about_z); + + CommitAndUpdateImplPointers(); // Case 1: scroll delta of 0, 0 - child->SetScrollDelta(gfx::Vector2d(0, 0)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(0, 0)); + ExecuteCalculateDrawProperties(root_impl_); gfx::Transform expected_child_transform; gfx::Transform expected_surface_draw_transform; expected_surface_draw_transform.Translate(8.0, 6.0); - expected_surface_draw_transform.PreconcatTransform(rotation_about_z); gfx::Transform expected_grand_child_transform; gfx::Transform expected_great_grand_child_transform; - ASSERT_TRUE(grand_child->render_surface()); + expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); + EXPECT_TRUE(grand_child_impl_->render_surface()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ( expected_surface_draw_transform, - grand_child->render_surface()->draw_transform()); + grand_child_impl_->render_surface()->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); // Case 2: scroll delta of 10, 30 - child->SetScrollDelta(gfx::Vector2d(10, 30)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 30)); + ExecuteCalculateDrawProperties(root_impl_); // Here the grand_child remains unchanged, because it scrolls along with the // render surface, and the translation is actually in the render surface. But, @@ -650,55 +467,47 @@ TEST_F(LayerPositionConstraintTest, expected_surface_draw_transform.MakeIdentity(); expected_surface_draw_transform.Translate(-10.0, -30.0); // scroll delta expected_surface_draw_transform.Translate(8.0, 6.0); - expected_surface_draw_transform.PreconcatTransform(rotation_about_z); - // The rotation and its inverse are needed to place the scroll delta - // compensation in the correct space. This test will fail if the - // rotation/inverse are backwards, too, so it requires perfect order of - // operations. expected_great_grand_child_transform.MakeIdentity(); - expected_great_grand_child_transform.PreconcatTransform( - Inverse(rotation_about_z)); // explicit canceling out the scroll delta that gets embedded in the fixed // position layer's surface. expected_great_grand_child_transform.Translate(10.0, 30.0); expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); - ASSERT_TRUE(grand_child->render_surface()); + EXPECT_TRUE(grand_child_impl_->render_surface()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ( expected_surface_draw_transform, - grand_child->render_surface()->draw_transform()); + grand_child_impl_->render_surface()->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); // Case 3: fixed-container size delta of 20, 20 - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Top-left fixed-position layer should not be affected by container size. EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); // Case 4: Bottom-right fixed-position layer. - great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); - ExecuteCalculateDrawProperties(root_.get()); + great_grand_child_->SetPositionConstraint(fixed_to_bottom_right_); + + CommitAndUpdateImplPointers(); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 30)); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + + ExecuteCalculateDrawProperties(root_impl_); // Bottom-right fixed-position layer moves as container resizes. expected_great_grand_child_transform.MakeIdentity(); - // The rotation and its inverse are needed to place the scroll delta - // compensation in the correct space. This test will fail if the - // rotation/inverse are backwards, too, so it requires perfect order of - // operations. - expected_great_grand_child_transform.PreconcatTransform( - Inverse(rotation_about_z)); // explicit canceling out the scroll delta that gets embedded in the fixed // position layer's surface. expected_great_grand_child_transform.Translate(10.0, 30.0); @@ -707,11 +516,11 @@ TEST_F(LayerPositionConstraintTest, expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); } TEST_F(LayerPositionConstraintTest, @@ -721,35 +530,24 @@ TEST_F(LayerPositionConstraintTest, // layer, with additional render surfaces in-between. This checks that the // conversion to ancestor surfaces is accumulated properly in the final matrix // transform. - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; - LayerImpl* great_grand_child = grand_child->children()[0]; // Add one more layer to the test tree for this scenario. - { - gfx::Transform identity; - scoped_ptr<LayerImpl> fixed_position_child = - LayerImpl::Create(host_impl_.active_tree(), 5); - SetLayerPropertiesForTesting(fixed_position_child.get(), - identity, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - true); - great_grand_child->AddChild(fixed_position_child.Pass()); - } - LayerImpl* fixed_position_child = great_grand_child->children()[0]; + scoped_refptr<Layer> fixed_position_child = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings_)); + SetLayerPropertiesForTesting(fixed_position_child.get(), gfx::Transform(), + gfx::Point3F(), gfx::PointF(), + gfx::Size(100, 100), true); + great_grand_child_->AddChild(fixed_position_child); // Actually set up the scenario here. - child->SetIsContainerForFixedPositionLayers(true); - grand_child->SetPosition(gfx::PointF(8.f, 6.f)); - grand_child->SetHasRenderSurface(true); - great_grand_child->SetPosition(gfx::PointF(40.f, 60.f)); - great_grand_child->SetHasRenderSurface(true); + child_->SetIsContainerForFixedPositionLayers(true); + grand_child_->SetPosition(gfx::PointF(8.f, 6.f)); + grand_child_->SetForceRenderSurface(true); + great_grand_child_->SetPosition(gfx::PointF(40.f, 60.f)); + great_grand_child_->SetForceRenderSurface(true); fixed_position_child->SetPositionConstraint(fixed_to_top_left_); - fixed_position_child->SetDrawsContent(true); - // The additional rotations, which are non-commutative with translations, help + // The additional rotation, which is non-commutative with translations, helps // to verify that we have correct order-of-operations in the final scroll // compensation. Note that rotating about the center of the layer ensures we // do not accidentally clip away layers that we want to test. @@ -757,51 +555,50 @@ TEST_F(LayerPositionConstraintTest, rotation_about_z.Translate(50.0, 50.0); rotation_about_z.RotateAboutZAxis(90.0); rotation_about_z.Translate(-50.0, -50.0); - grand_child->SetTransform(rotation_about_z); - great_grand_child->SetTransform(rotation_about_z); + fixed_position_child->SetTransform(rotation_about_z); + + CommitAndUpdateImplPointers(); + LayerImpl* fixed_position_child_impl = great_grand_child_impl_->children()[0]; // Case 1: scroll delta of 0, 0 - child->SetScrollDelta(gfx::Vector2d(0, 0)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(0, 0)); + ExecuteCalculateDrawProperties(root_impl_); gfx::Transform expected_child_transform; gfx::Transform expected_grand_child_surface_draw_transform; expected_grand_child_surface_draw_transform.Translate(8.0, 6.0); - expected_grand_child_surface_draw_transform.PreconcatTransform( - rotation_about_z); gfx::Transform expected_grand_child_transform; gfx::Transform expected_great_grand_child_surface_draw_transform; expected_great_grand_child_surface_draw_transform.Translate(40.0, 60.0); - expected_great_grand_child_surface_draw_transform.PreconcatTransform( - rotation_about_z); gfx::Transform expected_great_grand_child_transform; gfx::Transform expected_fixed_position_child_transform; + expected_fixed_position_child_transform.PreconcatTransform(rotation_about_z); - ASSERT_TRUE(grand_child->render_surface()); - ASSERT_TRUE(great_grand_child->render_surface()); + EXPECT_TRUE(grand_child_impl_->render_surface()); + EXPECT_TRUE(great_grand_child_impl_->render_surface()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ( expected_grand_child_surface_draw_transform, - grand_child->render_surface()->draw_transform()); + grand_child_impl_->render_surface()->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ( expected_great_grand_child_surface_draw_transform, - great_grand_child->render_surface()->draw_transform()); + great_grand_child_impl_->render_surface()->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, - fixed_position_child->draw_transform()); + fixed_position_child_impl->draw_transform()); // Case 2: scroll delta of 10, 30 - child->SetScrollDelta(gfx::Vector2d(10, 30)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 30)); + ExecuteCalculateDrawProperties(root_impl_); expected_child_transform.MakeIdentity(); expected_child_transform.Translate(-10.0, -30.0); // scroll delta @@ -810,8 +607,6 @@ TEST_F(LayerPositionConstraintTest, expected_grand_child_surface_draw_transform.Translate(-10.0, -30.0); // scroll delta expected_grand_child_surface_draw_transform.Translate(8.0, 6.0); - expected_grand_child_surface_draw_transform.PreconcatTransform( - rotation_about_z); // grand_child, great_grand_child, and great_grand_child's surface are not // expected to change, since they are all not fixed, and they are all drawn @@ -819,85 +614,191 @@ TEST_F(LayerPositionConstraintTest, // accounted for. // But the great-great grandchild, "fixed_position_child", should have a - // transform that explicitly cancels out the scroll delta. The expected - // transform is: compound_draw_transform.Inverse() * translate(positive scroll - // delta) * compound_origin_transform from great_grand_childSurface's origin - // to the root surface. - gfx::Transform compound_draw_transform; - compound_draw_transform.Translate(8.0, - 6.0); // origin translation of grand_child - compound_draw_transform.PreconcatTransform( - rotation_about_z); // rotation of grand_child - compound_draw_transform.Translate( - 40.0, 60.0); // origin translation of great_grand_child - compound_draw_transform.PreconcatTransform( - rotation_about_z); // rotation of great_grand_child - + // transform that explicitly cancels out the scroll delta. expected_fixed_position_child_transform.MakeIdentity(); - expected_fixed_position_child_transform.PreconcatTransform( - Inverse(compound_draw_transform)); - // explicit canceling out the scroll delta that gets embedded in the fixed - // position layer's surface. expected_fixed_position_child_transform.Translate(10.0, 30.0); - expected_fixed_position_child_transform.PreconcatTransform( - compound_draw_transform); + expected_fixed_position_child_transform.PreconcatTransform(rotation_about_z); - ASSERT_TRUE(grand_child->render_surface()); - ASSERT_TRUE(great_grand_child->render_surface()); + EXPECT_TRUE(grand_child_impl_->render_surface()); + EXPECT_TRUE(great_grand_child_impl_->render_surface()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ( expected_grand_child_surface_draw_transform, - grand_child->render_surface()->draw_transform()); + grand_child_impl_->render_surface()->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ( expected_great_grand_child_surface_draw_transform, - great_grand_child->render_surface()->draw_transform()); + great_grand_child_impl_->render_surface()->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, - fixed_position_child->draw_transform()); - + fixed_position_child_impl->draw_transform()); // Case 3: fixed-container size delta of 20, 20 - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Top-left fixed-position layer should not be affected by container size. EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, - fixed_position_child->draw_transform()); + fixed_position_child_impl->draw_transform()); // Case 4: Bottom-right fixed-position layer. fixed_position_child->SetPositionConstraint(fixed_to_bottom_right_); - ExecuteCalculateDrawProperties(root_.get()); + CommitAndUpdateImplPointers(); + fixed_position_child_impl = great_grand_child_impl_->children()[0]; + child_impl_->SetScrollDelta(gfx::Vector2d(10, 30)); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Bottom-right fixed-position layer moves as container resizes. expected_fixed_position_child_transform.MakeIdentity(); - expected_fixed_position_child_transform.PreconcatTransform( - Inverse(compound_draw_transform)); // explicit canceling out the scroll delta that gets embedded in the fixed // position layer's surface. expected_fixed_position_child_transform.Translate(10.0, 30.0); // Also apply size delta in the child(container) layer space. expected_fixed_position_child_transform.Translate(20.0, 20.0); - expected_fixed_position_child_transform.PreconcatTransform( - compound_draw_transform); + expected_fixed_position_child_transform.PreconcatTransform(rotation_about_z); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, - fixed_position_child->draw_transform()); + fixed_position_child_impl->draw_transform()); +} + +TEST_F( + LayerPositionConstraintTest, + ScrollCompensationForFixedPositionLayerWithMultipleSurfacesAndTransforms) { + // This test checks for correct scroll compensation when the fixed-position + // container contributes to a different render surface than the fixed-position + // layer, with additional render surfaces in-between, and the fixed-position + // container is transformed. This checks that the conversion to ancestor + // surfaces is accumulated properly in the final matrix transform. + + // Add one more layer to the test tree for this scenario. + scoped_refptr<Layer> fixed_position_child = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings_)); + SetLayerPropertiesForTesting(fixed_position_child.get(), gfx::Transform(), + gfx::Point3F(), gfx::PointF(), + gfx::Size(100, 100), true); + great_grand_child_->AddChild(fixed_position_child); + + // Actually set up the scenario here. + child_transform_layer_->SetIsContainerForFixedPositionLayers(true); + grand_child_->SetPosition(gfx::PointF(8.f, 6.f)); + grand_child_->SetForceRenderSurface(true); + great_grand_child_->SetPosition(gfx::PointF(40.f, 60.f)); + great_grand_child_->SetForceRenderSurface(true); + fixed_position_child->SetPositionConstraint(fixed_to_top_left_); + + // The additional rotations, which are non-commutative with translations, help + // to verify that we have correct order-of-operations in the final scroll + // compensation. Note that rotating about the center of the layer ensures we + // do not accidentally clip away layers that we want to test. + gfx::Transform rotation_about_z; + rotation_about_z.Translate(50.0, 50.0); + rotation_about_z.RotateAboutZAxis(90.0); + rotation_about_z.Translate(-50.0, -50.0); + child_transform_layer_->SetTransform(rotation_about_z); + fixed_position_child->SetTransform(rotation_about_z); + + CommitAndUpdateImplPointers(); + LayerImpl* fixed_position_child_impl = great_grand_child_impl_->children()[0]; + + // Case 1: scroll delta of 0, 0 + child_impl_->SetScrollDelta(gfx::Vector2d(0, 0)); + ExecuteCalculateDrawProperties(root_impl_); + + gfx::Transform expected_child_transform; + expected_child_transform.PreconcatTransform(rotation_about_z); + + gfx::Transform expected_grand_child_surface_draw_transform; + expected_grand_child_surface_draw_transform.PreconcatTransform( + rotation_about_z); + expected_grand_child_surface_draw_transform.Translate(8.0, 6.0); + + gfx::Transform expected_grand_child_transform; + + gfx::Transform expected_great_grand_child_surface_draw_transform; + expected_great_grand_child_surface_draw_transform.Translate(40.0, 60.0); + + gfx::Transform expected_great_grand_child_transform; + + gfx::Transform expected_fixed_position_child_transform; + expected_fixed_position_child_transform.PreconcatTransform(rotation_about_z); + + EXPECT_TRUE(grand_child_impl_->render_surface()); + EXPECT_TRUE(great_grand_child_impl_->render_surface()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, + child_impl_->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ( + expected_grand_child_surface_draw_transform, + grand_child_impl_->render_surface()->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, + grand_child_impl_->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ( + expected_great_grand_child_surface_draw_transform, + great_grand_child_impl_->render_surface()->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, + great_grand_child_impl_->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, + fixed_position_child_impl->draw_transform()); + + // Case 2: scroll delta of 10, 30 + child_impl_->SetScrollDelta(gfx::Vector2d(10, 30)); + ExecuteCalculateDrawProperties(root_impl_); + + expected_child_transform.MakeIdentity(); + expected_child_transform.PreconcatTransform(rotation_about_z); + expected_child_transform.Translate(-10.0, -30.0); // scroll delta + + expected_grand_child_surface_draw_transform.MakeIdentity(); + expected_grand_child_surface_draw_transform.PreconcatTransform( + rotation_about_z); + expected_grand_child_surface_draw_transform.Translate(-10.0, + -30.0); // scroll delta + expected_grand_child_surface_draw_transform.Translate(8.0, 6.0); + + // grand_child, great_grand_child, and great_grand_child's surface are not + // expected to change, since they are all not fixed, and they are all drawn + // with respect to grand_child's surface that already has the scroll delta + // accounted for. + + // But the great-great grandchild, "fixed_position_child", should have a + // transform that explicitly cancels out the scroll delta. + expected_fixed_position_child_transform.MakeIdentity(); + // explicit canceling out the scroll delta that gets embedded in the fixed + // position layer's surface. + expected_fixed_position_child_transform.Translate(10.0, 30.0); + expected_fixed_position_child_transform.PreconcatTransform(rotation_about_z); + + EXPECT_TRUE(grand_child_impl_->render_surface()); + EXPECT_TRUE(great_grand_child_impl_->render_surface()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, + child_impl_->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ( + expected_grand_child_surface_draw_transform, + grand_child_impl_->render_surface()->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, + grand_child_impl_->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ( + expected_great_grand_child_surface_draw_transform, + great_grand_child_impl_->render_surface()->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, + great_grand_child_impl_->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, + fixed_position_child_impl->draw_transform()); } TEST_F(LayerPositionConstraintTest, @@ -907,33 +808,31 @@ TEST_F(LayerPositionConstraintTest, // should be treated like a layer that contributes to a render target, and // that render target is completely irrelevant; it should not affect the // scroll compensation. - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; + child_->SetIsContainerForFixedPositionLayers(true); + child_->SetForceRenderSurface(true); + grand_child_->SetPositionConstraint(fixed_to_top_left_); - child->SetIsContainerForFixedPositionLayers(true); - child->SetHasRenderSurface(true); - grand_child->SetPositionConstraint(fixed_to_top_left_); - grand_child->SetDrawsContent(true); + CommitAndUpdateImplPointers(); // Case 1: scroll delta of 0, 0 - child->SetScrollDelta(gfx::Vector2d(0, 0)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(0, 0)); + ExecuteCalculateDrawProperties(root_impl_); gfx::Transform expected_surface_draw_transform; - expected_surface_draw_transform.Translate(0.0, 0.0); gfx::Transform expected_child_transform; gfx::Transform expected_grand_child_transform; - ASSERT_TRUE(child->render_surface()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform, - child->render_surface()->draw_transform()); + EXPECT_TRUE(child_impl_->render_surface()); + EXPECT_TRANSFORMATION_MATRIX_EQ( + expected_surface_draw_transform, + child_impl_->render_surface()->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); // Case 2: scroll delta of 10, 10 - child->SetScrollDelta(gfx::Vector2d(10, 10)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + ExecuteCalculateDrawProperties(root_impl_); // The surface is translated by scroll delta, the child transform doesn't // change because it scrolls along with the surface, but the fixed position @@ -943,27 +842,31 @@ TEST_F(LayerPositionConstraintTest, expected_grand_child_transform.MakeIdentity(); expected_grand_child_transform.Translate(10.0, 10.0); - ASSERT_TRUE(child->render_surface()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform, - child->render_surface()->draw_transform()); + EXPECT_TRUE(child_impl_->render_surface()); + EXPECT_TRANSFORMATION_MATRIX_EQ( + expected_surface_draw_transform, + child_impl_->render_surface()->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); // Case 3: fixed-container size delta of 20, 20 - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Top-left fixed-position layer should not be affected by container size. EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); // Case 4: Bottom-right fixed-position layer. - grand_child->SetPositionConstraint(fixed_to_bottom_right_); - ExecuteCalculateDrawProperties(root_.get()); + grand_child_->SetPositionConstraint(fixed_to_bottom_right_); + CommitAndUpdateImplPointers(); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Bottom-right fixed-position layer moves as container resizes. expected_grand_child_transform.MakeIdentity(); @@ -975,9 +878,9 @@ TEST_F(LayerPositionConstraintTest, expected_grand_child_transform.Translate(20.0, 20.0); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); } TEST_F(LayerPositionConstraintTest, @@ -985,53 +888,56 @@ TEST_F(LayerPositionConstraintTest, // This test checks the scenario where a fixed-position layer also happens to // be a container itself for a descendant fixed position layer. In particular, // the layer should not accidentally be fixed to itself. - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; - - child->SetIsContainerForFixedPositionLayers(true); - grand_child->SetPositionConstraint(fixed_to_top_left_); + child_->SetIsContainerForFixedPositionLayers(true); + grand_child_->SetPositionConstraint(fixed_to_top_left_); // This should not confuse the grand_child. If correct, the grand_child would // still be considered fixed to its container (i.e. "child"). - grand_child->SetIsContainerForFixedPositionLayers(true); + grand_child_->SetIsContainerForFixedPositionLayers(true); + + CommitAndUpdateImplPointers(); // Case 1: scroll delta of 0, 0 - child->SetScrollDelta(gfx::Vector2d(0, 0)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(0, 0)); + ExecuteCalculateDrawProperties(root_impl_); gfx::Transform expected_child_transform; gfx::Transform expected_grand_child_transform; EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); // Case 2: scroll delta of 10, 10 - child->SetScrollDelta(gfx::Vector2d(10, 10)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + ExecuteCalculateDrawProperties(root_impl_); // Here the child is affected by scroll delta, but the fixed position // grand_child should not be affected. expected_child_transform.MakeIdentity(); expected_child_transform.Translate(-10.0, -10.0); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); // Case 3: fixed-container size delta of 20, 20 - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); // Top-left fixed-position layer should not be affected by container size. EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); // Case 4: Bottom-right fixed-position layer. - grand_child->SetPositionConstraint(fixed_to_bottom_right_); - ExecuteCalculateDrawProperties(root_.get()); + grand_child_->SetPositionConstraint(fixed_to_bottom_right_); + CommitAndUpdateImplPointers(); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + + ExecuteCalculateDrawProperties(root_impl_); // Bottom-right fixed-position layer moves as container resizes. expected_grand_child_transform.MakeIdentity(); @@ -1039,9 +945,9 @@ TEST_F(LayerPositionConstraintTest, expected_grand_child_transform.Translate(20.0, 20.0); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); } TEST_F(LayerPositionConstraintTest, @@ -1051,22 +957,19 @@ TEST_F(LayerPositionConstraintTest, // In this situation, the parent fixed-position layer will receive // the scroll compensation, and the child fixed-position layer does not // need to compensate further. - - LayerImpl* child = scroll_->children()[0]; - LayerImpl* grand_child = child->children()[0]; - LayerImpl* great_grand_child = grand_child->children()[0]; - - child->SetIsContainerForFixedPositionLayers(true); - grand_child->SetPositionConstraint(fixed_to_top_left_); + child_->SetIsContainerForFixedPositionLayers(true); + grand_child_->SetPositionConstraint(fixed_to_top_left_); // Note carefully - great_grand_child is fixed to bottom right, to test // sizeDelta being applied correctly; the compensation skips the grand_child // because it is fixed to top left. - great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); + great_grand_child_->SetPositionConstraint(fixed_to_bottom_right_); + + CommitAndUpdateImplPointers(); // Case 1: scrollDelta - child->SetScrollDelta(gfx::Vector2d(10, 10)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + ExecuteCalculateDrawProperties(root_impl_); // Here the child is affected by scroll delta, but the fixed position // grand_child should not be affected. @@ -1077,16 +980,16 @@ TEST_F(LayerPositionConstraintTest, gfx::Transform expected_great_grand_child_transform; EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); // Case 2: sizeDelta - child->SetScrollDelta(gfx::Vector2d(0, 0)); - SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); - ExecuteCalculateDrawProperties(root_.get()); + child_impl_->SetScrollDelta(gfx::Vector2d(0, 0)); + SetFixedContainerSizeDelta(child_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); expected_child_transform.MakeIdentity(); @@ -1097,11 +1000,11 @@ TEST_F(LayerPositionConstraintTest, expected_great_grand_child_transform.Translate(20.0, 20.0); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); + child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, - grand_child->draw_transform()); + grand_child_impl_->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, - great_grand_child->draw_transform()); + great_grand_child_impl_->draw_transform()); } TEST_F(LayerPositionConstraintTest, @@ -1111,27 +1014,27 @@ TEST_F(LayerPositionConstraintTest, // position containers. In this situation, the child fixed-position element // would still have to compensate with respect to its container. - LayerImpl* container1 = scroll_->children()[0]; - LayerImpl* fixed_to_container1 = container1->children()[0]; - LayerImpl* container2 = fixed_to_container1->children()[0]; + // Add one more layer to the hierarchy for this test. + scoped_refptr<Layer> great_great_grand_child = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings_)); + great_grand_child_->AddChild(great_great_grand_child); - { - // Add one more layer to the hierarchy for this test. - scoped_ptr<LayerImpl> fixed_to_container2_ptr = - LayerImpl::Create(host_impl_.active_tree(), 5); - container2->AddChild(fixed_to_container2_ptr.Pass()); - } + child_->SetIsContainerForFixedPositionLayers(true); + grand_child_->SetPositionConstraint(fixed_to_top_left_); + great_grand_child_->SetIsContainerForFixedPositionLayers(true); + great_grand_child_->SetScrollClipLayerId(root_->id()); + great_great_grand_child->SetPositionConstraint(fixed_to_top_left_); - LayerImpl* fixed_to_container2 = container2->children()[0]; + CommitAndUpdateImplPointers(); - container1->SetIsContainerForFixedPositionLayers(true); - fixed_to_container1->SetPositionConstraint(fixed_to_top_left_); - container2->SetIsContainerForFixedPositionLayers(true); - fixed_to_container2->SetPositionConstraint(fixed_to_top_left_); + LayerImpl* container1 = child_impl_; + LayerImpl* fixed_to_container1 = grand_child_impl_; + LayerImpl* container2 = great_grand_child_impl_; + LayerImpl* fixed_to_container2 = container2->children()[0]; container1->SetScrollDelta(gfx::Vector2d(0, 15)); container2->SetScrollDelta(gfx::Vector2d(30, 0)); - ExecuteCalculateDrawProperties(root_.get()); + ExecuteCalculateDrawProperties(root_impl_); gfx::Transform expected_container1_transform; expected_container1_transform.Translate(0.0, -15.0); @@ -1158,5 +1061,57 @@ TEST_F(LayerPositionConstraintTest, EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container2_transform, fixed_to_container2->draw_transform()); } + +TEST_F(LayerPositionConstraintTest, + ScrollCompensationForInnerViewportBoundsDelta) { + // This test checks for correct scroll compensation when the fixed-position + // container is the inner viewport scroll layer and has non-zero bounds delta. + scoped_refptr<Layer> fixed_child = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings_)); + fixed_child->SetBounds(gfx::Size(300, 300)); + scroll_layer_->AddChild(fixed_child); + fixed_child->SetPositionConstraint(fixed_to_top_left_); + + CommitAndUpdateImplPointers(); + + LayerImpl* fixed_child_impl = + root_impl_->layer_tree_impl()->FindActiveTreeLayerById(fixed_child->id()); + + // Case 1: fixed-container size delta of 20, 20 + scroll_layer_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + SetFixedContainerSizeDelta(scroll_layer_impl_, gfx::Vector2d(20, 20)); + gfx::Transform expected_scroll_layer_transform; + expected_scroll_layer_transform.Translate(-10.0, -10.0); + gfx::Transform expected_fixed_child_transform; + + ExecuteCalculateDrawProperties(root_impl_); + + // Top-left fixed-position layer should not be affected by container size. + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_scroll_layer_transform, + scroll_layer_impl_->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_child_transform, + fixed_child_impl->draw_transform()); + + // Case 2: Bottom-right fixed-position layer. + fixed_child->SetPositionConstraint(fixed_to_bottom_right_); + CommitAndUpdateImplPointers(); + fixed_child_impl = + root_impl_->layer_tree_impl()->FindActiveTreeLayerById(fixed_child->id()); + + scroll_layer_impl_->SetScrollDelta(gfx::Vector2d(10, 10)); + SetFixedContainerSizeDelta(scroll_layer_impl_, gfx::Vector2d(20, 20)); + ExecuteCalculateDrawProperties(root_impl_); + + // Bottom-right fixed-position layer moves as container resizes. + expected_fixed_child_transform.MakeIdentity(); + // Apply size delta. + expected_fixed_child_transform.Translate(20.0, 20.0); + + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_scroll_layer_transform, + scroll_layer_impl_->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_child_transform, + fixed_child_impl->draw_transform()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/layers/layer_unittest.cc b/chromium/cc/layers/layer_unittest.cc index 6b4d36b9412..ba8e92d75b9 100644 --- a/chromium/cc/layers/layer_unittest.cc +++ b/chromium/cc/layers/layer_unittest.cc @@ -10,7 +10,6 @@ #include "cc/layers/layer_impl.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" -#include "cc/resources/layer_painter.h" #include "cc/test/animation_test_common.h" #include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -56,11 +55,6 @@ class MockLayerTreeHost : public LayerTreeHost { MOCK_METHOD0(SetNeedsFullTreeSync, void()); }; -class MockLayerPainter : public LayerPainter { - public: - void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) override {} -}; - class LayerTest : public testing::Test { public: LayerTest() @@ -73,6 +67,7 @@ class LayerTest : public testing::Test { LayerTreeSettings settings; params.client = &fake_client_; params.settings = &settings; + params.task_graph_runner = &task_graph_runner_; layer_tree_host_.reset( new StrictMock<MockLayerTreeHost>(&fake_client_, ¶ms)); } @@ -115,13 +110,13 @@ class LayerTest : public testing::Test { } void CreateSimpleTestTree() { - parent_ = Layer::Create(); - child1_ = Layer::Create(); - child2_ = Layer::Create(); - child3_ = Layer::Create(); - grand_child1_ = Layer::Create(); - grand_child2_ = Layer::Create(); - grand_child3_ = Layer::Create(); + parent_ = Layer::Create(layer_settings_); + child1_ = Layer::Create(layer_settings_); + child2_ = Layer::Create(layer_settings_); + child3_ = Layer::Create(layer_settings_); + grand_child1_ = Layer::Create(layer_settings_); + grand_child2_ = Layer::Create(layer_settings_); + grand_child3_ = Layer::Create(layer_settings_); EXPECT_CALL(*layer_tree_host_, SetNeedsFullTreeSync()).Times(AnyNumber()); layer_tree_host_->SetRootLayer(parent_); @@ -152,10 +147,12 @@ class LayerTest : public testing::Test { scoped_refptr<Layer> grand_child1_; scoped_refptr<Layer> grand_child2_; scoped_refptr<Layer> grand_child3_; + + LayerSettings layer_settings_; }; TEST_F(LayerTest, BasicCreateAndDestroy) { - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); ASSERT_TRUE(test_layer.get()); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0); @@ -167,8 +164,8 @@ TEST_F(LayerTest, BasicCreateAndDestroy) { } TEST_F(LayerTest, AddAndRemoveChild) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child = Layer::Create(layer_settings_); // Upon creation, layers should not have children or parent. ASSERT_EQ(0U, parent->children().size()); @@ -188,8 +185,8 @@ TEST_F(LayerTest, AddAndRemoveChild) { TEST_F(LayerTest, AddSameChildTwice) { EXPECT_CALL(*layer_tree_host_, SetNeedsFullTreeSync()).Times(AtLeast(1)); - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child = Layer::Create(layer_settings_); layer_tree_host_->SetRootLayer(parent); @@ -205,11 +202,11 @@ TEST_F(LayerTest, AddSameChildTwice) { } TEST_F(LayerTest, InsertChild) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child1 = Layer::Create(); - scoped_refptr<Layer> child2 = Layer::Create(); - scoped_refptr<Layer> child3 = Layer::Create(); - scoped_refptr<Layer> child4 = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child1 = Layer::Create(layer_settings_); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings_); + scoped_refptr<Layer> child3 = Layer::Create(layer_settings_); + scoped_refptr<Layer> child4 = Layer::Create(layer_settings_); EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, layer_tree_host_->SetRootLayer(parent)); @@ -250,9 +247,9 @@ TEST_F(LayerTest, InsertChild) { } TEST_F(LayerTest, InsertChildPastEndOfList) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child1 = Layer::Create(); - scoped_refptr<Layer> child2 = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child1 = Layer::Create(layer_settings_); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings_); ASSERT_EQ(0U, parent->children().size()); @@ -271,9 +268,9 @@ TEST_F(LayerTest, InsertChildPastEndOfList) { } TEST_F(LayerTest, InsertSameChildTwice) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child1 = Layer::Create(); - scoped_refptr<Layer> child2 = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child1 = Layer::Create(layer_settings_); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings_); EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, layer_tree_host_->SetRootLayer(parent)); @@ -300,7 +297,7 @@ TEST_F(LayerTest, InsertSameChildTwice) { TEST_F(LayerTest, ReplaceChildWithNewChild) { CreateSimpleTestTree(); - scoped_refptr<Layer> child4 = Layer::Create(); + scoped_refptr<Layer> child4 = Layer::Create(layer_settings_); EXPECT_FALSE(child4->parent()); @@ -325,8 +322,8 @@ TEST_F(LayerTest, ReplaceChildWithNewChildThatHasOtherParent) { CreateSimpleTestTree(); // create another simple tree with test_layer and child4. - scoped_refptr<Layer> test_layer = Layer::Create(); - scoped_refptr<Layer> child4 = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); + scoped_refptr<Layer> child4 = Layer::Create(layer_settings_); test_layer->AddChild(child4); ASSERT_EQ(1U, test_layer->children().size()); EXPECT_EQ(child4, test_layer->children()[0]); @@ -348,9 +345,9 @@ TEST_F(LayerTest, ReplaceChildWithNewChildThatHasOtherParent) { } TEST_F(LayerTest, DeleteRemovedScrollParent) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child1 = Layer::Create(); - scoped_refptr<Layer> child2 = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child1 = Layer::Create(layer_settings_); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings_); EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, layer_tree_host_->SetRootLayer(parent)); @@ -377,9 +374,9 @@ TEST_F(LayerTest, DeleteRemovedScrollParent) { } TEST_F(LayerTest, DeleteRemovedScrollChild) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child1 = Layer::Create(); - scoped_refptr<Layer> child2 = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child1 = Layer::Create(layer_settings_); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings_); EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, layer_tree_host_->SetRootLayer(parent)); @@ -429,11 +426,11 @@ TEST_F(LayerTest, RemoveAllChildren) { } TEST_F(LayerTest, SetChildren) { - scoped_refptr<Layer> old_parent = Layer::Create(); - scoped_refptr<Layer> new_parent = Layer::Create(); + scoped_refptr<Layer> old_parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> new_parent = Layer::Create(layer_settings_); - scoped_refptr<Layer> child1 = Layer::Create(); - scoped_refptr<Layer> child2 = Layer::Create(); + scoped_refptr<Layer> child1 = Layer::Create(layer_settings_); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings_); LayerList new_children; new_children.push_back(child1); @@ -460,17 +457,17 @@ TEST_F(LayerTest, SetChildren) { } TEST_F(LayerTest, HasAncestor) { - scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); EXPECT_FALSE(parent->HasAncestor(parent.get())); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(layer_settings_); parent->AddChild(child); EXPECT_FALSE(child->HasAncestor(child.get())); EXPECT_TRUE(child->HasAncestor(parent.get())); EXPECT_FALSE(parent->HasAncestor(child.get())); - scoped_refptr<Layer> child_child = Layer::Create(); + scoped_refptr<Layer> child_child = Layer::Create(layer_settings_); child->AddChild(child_child); EXPECT_FALSE(child_child->HasAncestor(child_child.get())); @@ -486,7 +483,7 @@ TEST_F(LayerTest, GetRootLayerAfterTreeManipulations) { // For this test we don't care about SetNeedsFullTreeSync calls. EXPECT_CALL(*layer_tree_host_, SetNeedsFullTreeSync()).Times(AnyNumber()); - scoped_refptr<Layer> child4 = Layer::Create(); + scoped_refptr<Layer> child4 = Layer::Create(layer_settings_); EXPECT_EQ(parent_.get(), parent_->RootLayer()); EXPECT_EQ(parent_.get(), child1_->RootLayer()); @@ -541,7 +538,7 @@ TEST_F(LayerTest, CheckSetNeedsDisplayCausesCorrectBehavior) { // 2. indirectly calls SetNeedsUpdate, exactly once for each call to // SetNeedsDisplay. - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); EXPECT_SET_NEEDS_FULL_TREE_SYNC( 1, layer_tree_host_->SetRootLayer(test_layer)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetIsDrawable(true)); @@ -594,13 +591,13 @@ TEST_F(LayerTest, CheckSetNeedsDisplayCausesCorrectBehavior) { } TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) { - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); EXPECT_SET_NEEDS_FULL_TREE_SYNC( 1, layer_tree_host_->SetRootLayer(test_layer)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetIsDrawable(true)); - scoped_refptr<Layer> dummy_layer1 = Layer::Create(); - scoped_refptr<Layer> dummy_layer2 = Layer::Create(); + scoped_refptr<Layer> dummy_layer1 = Layer::Create(layer_settings_); + scoped_refptr<Layer> dummy_layer2 = Layer::Create(layer_settings_); // sanity check of initial test condition EXPECT_FALSE(test_layer->NeedsDisplayForTesting()); @@ -653,7 +650,7 @@ TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) { } TEST_F(LayerTest, PushPropertiesAccumulatesUpdateRect) { - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); scoped_ptr<LayerImpl> impl_layer = LayerImpl::Create(host_impl_.active_tree(), 1); @@ -682,7 +679,7 @@ TEST_F(LayerTest, PushPropertiesAccumulatesUpdateRect) { } TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForTransform) { - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); scoped_ptr<LayerImpl> impl_layer = LayerImpl::Create(host_impl_.active_tree(), 1); @@ -701,7 +698,7 @@ TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForTransform) { } TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForOpacity) { - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); scoped_ptr<LayerImpl> impl_layer = LayerImpl::Create(host_impl_.active_tree(), 1); @@ -719,7 +716,7 @@ TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForOpacity) { TEST_F(LayerTest, PushPropsDoesntCauseLayerPropertyChangedDuringImplOnlyTransformAnim) { - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); scoped_ptr<LayerImpl> impl_layer = LayerImpl::Create(host_impl_.active_tree(), 1); @@ -761,7 +758,7 @@ TEST_F(LayerTest, TEST_F(LayerTest, PushPropsDoesntCauseLayerPropertyChangedDuringImplOnlyOpacityAnim) { - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); scoped_ptr<LayerImpl> impl_layer = LayerImpl::Create(host_impl_.active_tree(), 1); @@ -802,7 +799,7 @@ TEST_F(LayerTest, TEST_F(LayerTest, PushPropsDoesntCauseLayerPropertyChangedDuringImplOnlyFilterAnim) { - scoped_refptr<Layer> test_layer = Layer::Create(); + scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); scoped_ptr<LayerImpl> impl_layer = LayerImpl::Create(host_impl_.active_tree(), 1); @@ -839,14 +836,15 @@ TEST_F(LayerTest, } TEST_F(LayerTest, MaskAndReplicaHasParent) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> mask = Layer::Create(); - scoped_refptr<Layer> replica = Layer::Create(); - scoped_refptr<Layer> replica_mask = Layer::Create(); - scoped_refptr<Layer> mask_replacement = Layer::Create(); - scoped_refptr<Layer> replica_replacement = Layer::Create(); - scoped_refptr<Layer> replica_mask_replacement = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child = Layer::Create(layer_settings_); + scoped_refptr<Layer> mask = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica_mask = Layer::Create(layer_settings_); + scoped_refptr<Layer> mask_replacement = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica_replacement = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica_mask_replacement = + Layer::Create(layer_settings_); parent->AddChild(child); child->SetMaskLayer(mask.get()); @@ -874,7 +872,7 @@ TEST_F(LayerTest, MaskAndReplicaHasParent) { } TEST_F(LayerTest, CheckTranformIsInvertible) { - scoped_refptr<Layer> layer = Layer::Create(); + scoped_refptr<Layer> layer = Layer::Create(layer_settings_); scoped_ptr<LayerImpl> impl_layer = LayerImpl::Create(host_impl_.active_tree(), 1); EXPECT_CALL(*layer_tree_host_, SetNeedsFullTreeSync()).Times(1); @@ -905,7 +903,7 @@ TEST_F(LayerTest, CheckTranformIsInvertible) { } TEST_F(LayerTest, TranformIsInvertibleAnimation) { - scoped_refptr<Layer> layer = Layer::Create(); + scoped_refptr<Layer> layer = Layer::Create(layer_settings_); scoped_ptr<LayerImpl> impl_layer = LayerImpl::Create(host_impl_.active_tree(), 1); EXPECT_CALL(*layer_tree_host_, SetNeedsFullTreeSync()).Times(1); @@ -938,18 +936,16 @@ TEST_F(LayerTest, TranformIsInvertibleAnimation) { class LayerTreeHostFactory { public: - LayerTreeHostFactory() - : client_(FakeLayerTreeHostClient::DIRECT_3D), - shared_bitmap_manager_(new TestSharedBitmapManager), - gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager) {} + LayerTreeHostFactory() : client_(FakeLayerTreeHostClient::DIRECT_3D) {} scoped_ptr<LayerTreeHost> Create() { return Create(LayerTreeSettings()); } scoped_ptr<LayerTreeHost> Create(LayerTreeSettings settings) { LayerTreeHost::InitParams params; params.client = &client_; - params.shared_bitmap_manager = shared_bitmap_manager_.get(); - params.gpu_memory_buffer_manager = gpu_memory_buffer_manager_.get(); + params.shared_bitmap_manager = &shared_bitmap_manager_; + params.task_graph_runner = &task_graph_runner_; + params.gpu_memory_buffer_manager = &gpu_memory_buffer_manager_; params.settings = &settings; params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); return LayerTreeHost::CreateSingleThreaded(&client_, ¶ms); @@ -957,8 +953,9 @@ class LayerTreeHostFactory { private: FakeLayerTreeHostClient client_; - scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_; - scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_; + TestSharedBitmapManager shared_bitmap_manager_; + TestTaskGraphRunner task_graph_runner_; + TestGpuMemoryBufferManager gpu_memory_buffer_manager_; }; void AssertLayerTreeHostMatchesForSubtree(Layer* layer, LayerTreeHost* host) { @@ -974,12 +971,18 @@ void AssertLayerTreeHostMatchesForSubtree(Layer* layer, LayerTreeHost* host) { AssertLayerTreeHostMatchesForSubtree(layer->replica_layer(), host); } -TEST(LayerLayerTreeHostTest, EnteringTree) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> mask = Layer::Create(); - scoped_refptr<Layer> replica = Layer::Create(); - scoped_refptr<Layer> replica_mask = Layer::Create(); +class LayerLayerTreeHostTest : public testing::Test { + public: + protected: + LayerSettings layer_settings_; +}; + +TEST_F(LayerLayerTreeHostTest, EnteringTree) { + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child = Layer::Create(layer_settings_); + scoped_refptr<Layer> mask = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica_mask = Layer::Create(layer_settings_); // Set up a detached tree of layers. The host pointer should be nil for these // layers. @@ -1005,8 +1008,8 @@ TEST(LayerLayerTreeHostTest, EnteringTree) { AssertLayerTreeHostMatchesForSubtree(parent.get(), nullptr); } -TEST(LayerLayerTreeHostTest, AddingLayerSubtree) { - scoped_refptr<Layer> parent = Layer::Create(); +TEST_F(LayerLayerTreeHostTest, AddingLayerSubtree) { + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); LayerTreeHostFactory factory; scoped_ptr<LayerTreeHost> layer_tree_host = factory.Create(); @@ -1016,16 +1019,16 @@ TEST(LayerLayerTreeHostTest, AddingLayerSubtree) { // Adding a subtree to a layer already associated with a host should set the // host pointer on all layers in that subtree. - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grand_child = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(layer_settings_); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings_); child->AddChild(grand_child); // Masks, replicas, and replica masks should pick up the new host too. - scoped_refptr<Layer> child_mask = Layer::Create(); + scoped_refptr<Layer> child_mask = Layer::Create(layer_settings_); child->SetMaskLayer(child_mask.get()); - scoped_refptr<Layer> child_replica = Layer::Create(); + scoped_refptr<Layer> child_replica = Layer::Create(layer_settings_); child->SetReplicaLayer(child_replica.get()); - scoped_refptr<Layer> child_replica_mask = Layer::Create(); + scoped_refptr<Layer> child_replica_mask = Layer::Create(layer_settings_); child_replica->SetMaskLayer(child_replica_mask.get()); parent->AddChild(child); @@ -1034,12 +1037,12 @@ TEST(LayerLayerTreeHostTest, AddingLayerSubtree) { layer_tree_host->SetRootLayer(nullptr); } -TEST(LayerLayerTreeHostTest, ChangeHost) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> mask = Layer::Create(); - scoped_refptr<Layer> replica = Layer::Create(); - scoped_refptr<Layer> replica_mask = Layer::Create(); +TEST_F(LayerLayerTreeHostTest, ChangeHost) { + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> child = Layer::Create(layer_settings_); + scoped_refptr<Layer> mask = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica_mask = Layer::Create(layer_settings_); // Same setup as the previous test. parent->AddChild(child); @@ -1065,12 +1068,12 @@ TEST(LayerLayerTreeHostTest, ChangeHost) { second_layer_tree_host->SetRootLayer(nullptr); } -TEST(LayerLayerTreeHostTest, ChangeHostInSubtree) { - scoped_refptr<Layer> first_parent = Layer::Create(); - scoped_refptr<Layer> first_child = Layer::Create(); - scoped_refptr<Layer> second_parent = Layer::Create(); - scoped_refptr<Layer> second_child = Layer::Create(); - scoped_refptr<Layer> second_grand_child = Layer::Create(); +TEST_F(LayerLayerTreeHostTest, ChangeHostInSubtree) { + scoped_refptr<Layer> first_parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> first_child = Layer::Create(layer_settings_); + scoped_refptr<Layer> second_parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> second_child = Layer::Create(layer_settings_); + scoped_refptr<Layer> second_grand_child = Layer::Create(layer_settings_); // First put all children under the first parent and set the first host. first_parent->AddChild(first_child); @@ -1101,14 +1104,14 @@ TEST(LayerLayerTreeHostTest, ChangeHostInSubtree) { second_layer_tree_host->SetRootLayer(nullptr); } -TEST(LayerLayerTreeHostTest, ReplaceMaskAndReplicaLayer) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> mask = Layer::Create(); - scoped_refptr<Layer> replica = Layer::Create(); - scoped_refptr<Layer> mask_child = Layer::Create(); - scoped_refptr<Layer> replica_child = Layer::Create(); - scoped_refptr<Layer> mask_replacement = Layer::Create(); - scoped_refptr<Layer> replica_replacement = Layer::Create(); +TEST_F(LayerLayerTreeHostTest, ReplaceMaskAndReplicaLayer) { + scoped_refptr<Layer> parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> mask = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica = Layer::Create(layer_settings_); + scoped_refptr<Layer> mask_child = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica_child = Layer::Create(layer_settings_); + scoped_refptr<Layer> mask_replacement = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica_replacement = Layer::Create(layer_settings_); parent->SetMaskLayer(mask.get()); parent->SetReplicaLayer(replica.get()); @@ -1135,9 +1138,9 @@ TEST(LayerLayerTreeHostTest, ReplaceMaskAndReplicaLayer) { layer_tree_host->SetRootLayer(nullptr); } -TEST(LayerLayerTreeHostTest, DestroyHostWithNonNullRootLayer) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); +TEST_F(LayerLayerTreeHostTest, DestroyHostWithNonNullRootLayer) { + scoped_refptr<Layer> root = Layer::Create(layer_settings_); + scoped_refptr<Layer> child = Layer::Create(layer_settings_); root->AddChild(child); LayerTreeHostFactory factory; scoped_ptr<LayerTreeHost> layer_tree_host = factory.Create(); @@ -1156,15 +1159,15 @@ static bool AddTestAnimation(Layer* layer) { return layer->AddAnimation(animation.Pass()); } -TEST(LayerLayerTreeHostTest, ShouldNotAddAnimationWithoutAnimationRegistrar) { - scoped_refptr<Layer> layer = Layer::Create(); +TEST_F(LayerLayerTreeHostTest, ShouldNotAddAnimationWithoutAnimationRegistrar) { + scoped_refptr<Layer> layer = Layer::Create(layer_settings_); // Case 1: without a LayerTreeHost and without an AnimationRegistrar, the // animation should not be accepted. EXPECT_FALSE(AddTestAnimation(layer.get())); scoped_ptr<AnimationRegistrar> registrar = AnimationRegistrar::Create(); - layer->layer_animation_controller()->SetAnimationRegistrar(registrar.get()); + layer->RegisterForAnimations(registrar.get()); // Case 2: with an AnimationRegistrar, the animation should be accepted. EXPECT_TRUE(AddTestAnimation(layer.get())); @@ -1185,7 +1188,7 @@ TEST_F(LayerTest, SafeOpaqueBackgroundColor) { LayerTreeHostFactory factory; scoped_ptr<LayerTreeHost> layer_tree_host = factory.Create(); - scoped_refptr<Layer> layer = Layer::Create(); + scoped_refptr<Layer> layer = Layer::Create(layer_settings_); layer_tree_host->SetRootLayer(layer); for (int contents_opaque = 0; contents_opaque < 2; ++contents_opaque) { @@ -1214,8 +1217,9 @@ TEST_F(LayerTest, SafeOpaqueBackgroundColor) { class DrawsContentChangeLayer : public Layer { public: - static scoped_refptr<DrawsContentChangeLayer> Create() { - return make_scoped_refptr(new DrawsContentChangeLayer()); + static scoped_refptr<DrawsContentChangeLayer> Create( + const LayerSettings& settings) { + return make_scoped_refptr(new DrawsContentChangeLayer(settings)); } void SetLayerTreeHost(LayerTreeHost* host) override { @@ -1233,18 +1237,19 @@ class DrawsContentChangeLayer : public Layer { } private: - DrawsContentChangeLayer() : Layer(), fake_draws_content_(false) {} + explicit DrawsContentChangeLayer(const LayerSettings& settings) + : Layer(settings), fake_draws_content_(false) {} ~DrawsContentChangeLayer() override {} bool fake_draws_content_; }; TEST_F(LayerTest, DrawsContentChangedInSetLayerTreeHost) { - scoped_refptr<Layer> root_layer = Layer::Create(); + scoped_refptr<Layer> root_layer = Layer::Create(layer_settings_); scoped_refptr<DrawsContentChangeLayer> becomes_not_draws_content = - DrawsContentChangeLayer::Create(); + DrawsContentChangeLayer::Create(layer_settings_); scoped_refptr<DrawsContentChangeLayer> becomes_draws_content = - DrawsContentChangeLayer::Create(); + DrawsContentChangeLayer::Create(layer_settings_); root_layer->SetIsDrawable(true); becomes_not_draws_content->SetIsDrawable(true); becomes_not_draws_content->SetFakeDrawsContent(true); @@ -1263,7 +1268,7 @@ void ReceiveCopyOutputResult(int* result_count, } TEST_F(LayerTest, DedupesCopyOutputRequestsBySource) { - scoped_refptr<Layer> layer = Layer::Create(); + scoped_refptr<Layer> layer = Layer::Create(layer_settings_); int result_count = 0; // Create identical requests without the source being set, and expect the @@ -1281,7 +1286,7 @@ TEST_F(LayerTest, DedupesCopyOutputRequestsBySource) { layer = nullptr; EXPECT_EQ(2, result_count); - layer = Layer::Create(); + layer = Layer::Create(layer_settings_); result_count = 0; // Create identical requests, but this time the source is being set. Expect diff --git a/chromium/cc/layers/layer_utils.cc b/chromium/cc/layers/layer_utils.cc index 888174a46d3..42d0e1b1d75 100644 --- a/chromium/cc/layers/layer_utils.cc +++ b/chromium/cc/layers/layer_utils.cc @@ -13,17 +13,15 @@ namespace cc { namespace { bool HasAnimationThatInflatesBounds(const LayerImpl& layer) { - return layer.layer_animation_controller()->HasAnimationThatInflatesBounds(); + return layer.HasAnimationThatInflatesBounds(); } bool HasFilterAnimationThatInflatesBounds(const LayerImpl& layer) { - return layer.layer_animation_controller() - ->HasFilterAnimationThatInflatesBounds(); + return layer.HasFilterAnimationThatInflatesBounds(); } bool HasTransformAnimationThatInflatesBounds(const LayerImpl& layer) { - return layer.layer_animation_controller() - ->HasTransformAnimationThatInflatesBounds(); + return layer.HasTransformAnimationThatInflatesBounds(); } inline bool HasAncestorTransformAnimation(const LayerImpl& layer) { @@ -112,16 +110,14 @@ bool LayerUtils::GetAnimationBounds(const LayerImpl& layer_in, gfx::BoxF* out) { // Perform the inflation if (HasFilterAnimationThatInflatesBounds(*layer)) { gfx::BoxF inflated; - if (!layer->layer_animation_controller()->FilterAnimationBoundsForBox( - box, &inflated)) + if (!layer->FilterAnimationBoundsForBox(box, &inflated)) return false; box = inflated; } if (HasTransformAnimationThatInflatesBounds(*layer)) { gfx::BoxF inflated; - if (!layer->layer_animation_controller()->TransformAnimationBoundsForBox( - box, &inflated)) + if (!layer->TransformAnimationBoundsForBox(box, &inflated)) return false; box = inflated; } diff --git a/chromium/cc/layers/nine_patch_layer.cc b/chromium/cc/layers/nine_patch_layer.cc index ad8f04dfeff..575090cad9e 100644 --- a/chromium/cc/layers/nine_patch_layer.cc +++ b/chromium/cc/layers/nine_patch_layer.cc @@ -5,20 +5,20 @@ #include "cc/layers/nine_patch_layer.h" #include "cc/layers/nine_patch_layer_impl.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/resource_update.h" -#include "cc/resources/resource_update_queue.h" #include "cc/resources/scoped_ui_resource.h" #include "cc/resources/ui_resource_bitmap.h" #include "cc/trees/layer_tree_host.h" namespace cc { -scoped_refptr<NinePatchLayer> NinePatchLayer::Create() { - return make_scoped_refptr(new NinePatchLayer()); +scoped_refptr<NinePatchLayer> NinePatchLayer::Create( + const LayerSettings& settings) { + return make_scoped_refptr(new NinePatchLayer(settings)); } -NinePatchLayer::NinePatchLayer() : fill_center_(false) {} +NinePatchLayer::NinePatchLayer(const LayerSettings& settings) + : UIResourceLayer(settings), fill_center_(false) { +} NinePatchLayer::~NinePatchLayer() {} diff --git a/chromium/cc/layers/nine_patch_layer.h b/chromium/cc/layers/nine_patch_layer.h index 9054610b8ee..714a407ddb0 100644 --- a/chromium/cc/layers/nine_patch_layer.h +++ b/chromium/cc/layers/nine_patch_layer.h @@ -19,7 +19,7 @@ class ScopedUIResource; class CC_EXPORT NinePatchLayer : public UIResourceLayer { public: - static scoped_refptr<NinePatchLayer> Create(); + static scoped_refptr<NinePatchLayer> Create(const LayerSettings& settings); void PushPropertiesTo(LayerImpl* layer) override; @@ -40,7 +40,7 @@ class CC_EXPORT NinePatchLayer : public UIResourceLayer { void SetFillCenter(bool fill_center); private: - NinePatchLayer(); + explicit NinePatchLayer(const LayerSettings& settings); ~NinePatchLayer() override; scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; diff --git a/chromium/cc/layers/nine_patch_layer_impl.cc b/chromium/cc/layers/nine_patch_layer_impl.cc index fc2f4575262..b31382f6580 100644 --- a/chromium/cc/layers/nine_patch_layer_impl.cc +++ b/chromium/cc/layers/nine_patch_layer_impl.cc @@ -88,13 +88,13 @@ void NinePatchLayerImpl::AppendQuads( render_pass->CreateAndAppendSharedQuadState(); PopulateSharedQuadState(shared_quad_state); - AppendDebugBorderQuad( - render_pass, content_bounds(), shared_quad_state, append_quads_data); + AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state, + append_quads_data); if (!ui_resource_id_) return; - ResourceProvider::ResourceId resource = + ResourceId resource = layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_); if (!resource) diff --git a/chromium/cc/layers/nine_patch_layer_impl_unittest.cc b/chromium/cc/layers/nine_patch_layer_impl_unittest.cc index a71f92ef0dd..3535c985106 100644 --- a/chromium/cc/layers/nine_patch_layer_impl_unittest.cc +++ b/chromium/cc/layers/nine_patch_layer_impl_unittest.cc @@ -37,7 +37,7 @@ void NinePatchLayerLayoutTest(const gfx::Size& bitmap_size, bool fill_center, size_t expected_quad_size) { scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - gfx::Rect visible_content_rect(layer_size); + gfx::Rect visible_layer_rect(layer_size); gfx::Rect expected_remaining(border.x(), border.y(), layer_size.width() - border.width(), @@ -45,14 +45,15 @@ void NinePatchLayerLayoutTest(const gfx::Size& bitmap_size, FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager); + TestTaskGraphRunner task_graph_runner; + FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); scoped_ptr<NinePatchLayerImpl> layer = NinePatchLayerImpl::Create(host_impl.active_tree(), 1); - layer->draw_properties().visible_content_rect = visible_content_rect; + layer->draw_properties().visible_layer_rect = visible_layer_rect; layer->SetBounds(layer_size); - layer->SetContentBounds(layer_size); layer->SetHasRenderSurface(true); layer->draw_properties().render_target = layer.get(); @@ -71,11 +72,11 @@ void NinePatchLayerLayoutTest(const gfx::Size& bitmap_size, const QuadList& quads = render_pass->quad_list; EXPECT_EQ(expected_quad_size, quads.size()); - Region remaining(visible_content_rect); + Region remaining(visible_layer_rect); for (auto iter = quads.cbegin(); iter != quads.cend(); ++iter) { gfx::Rect quad_rect = iter->rect; - EXPECT_TRUE(visible_content_rect.Contains(quad_rect)) << iter.index(); + EXPECT_TRUE(visible_layer_rect.Contains(quad_rect)) << iter.index(); EXPECT_TRUE(remaining.Contains(quad_rect)) << iter.index(); remaining.Subtract(Region(quad_rect)); } @@ -229,7 +230,6 @@ TEST(NinePatchLayerImplTest, Occlusion) { NinePatchLayerImpl* nine_patch_layer_impl = impl.AddChildToRoot<NinePatchLayerImpl>(); nine_patch_layer_impl->SetBounds(layer_size); - nine_patch_layer_impl->SetContentBounds(layer_size); nine_patch_layer_impl->SetDrawsContent(true); nine_patch_layer_impl->SetUIResourceId(uid); nine_patch_layer_impl->SetImageBounds(gfx::Size(10, 10)); @@ -252,7 +252,7 @@ TEST(NinePatchLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(nine_patch_layer_impl->visible_content_rect()); + gfx::Rect occluded(nine_patch_layer_impl->visible_layer_rect()); impl.AppendQuadsWithOcclusion(nine_patch_layer_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); @@ -302,7 +302,6 @@ TEST(NinePatchLayerImplTest, OpaqueRect) { NinePatchLayerImpl *nine_patch_layer_impl = impl.AddChildToRoot<NinePatchLayerImpl>(); nine_patch_layer_impl->SetBounds(layer_size); - nine_patch_layer_impl->SetContentBounds(layer_size); nine_patch_layer_impl->SetDrawsContent(true); impl.CalcDrawProps(viewport_size); diff --git a/chromium/cc/layers/nine_patch_layer_unittest.cc b/chromium/cc/layers/nine_patch_layer_unittest.cc index 1783ba9fa41..75af3be073e 100644 --- a/chromium/cc/layers/nine_patch_layer_unittest.cc +++ b/chromium/cc/layers/nine_patch_layer_unittest.cc @@ -4,18 +4,15 @@ #include "cc/layers/nine_patch_layer.h" -#include "cc/resources/prioritized_resource_manager.h" #include "cc/resources/resource_provider.h" -#include "cc/resources/resource_update_queue.h" #include "cc/resources/scoped_ui_resource.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/geometry_test_utils.h" -#include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host.h" -#include "cc/trees/occlusion_tracker.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,7 +32,8 @@ class NinePatchLayerTest : public testing::Test { protected: void SetUp() override { - layer_tree_host_ = FakeLayerTreeHost::Create(&fake_client_); + layer_tree_host_ = + FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_); } void TearDown() override { @@ -43,11 +41,13 @@ class NinePatchLayerTest : public testing::Test { } FakeLayerTreeHostClient fake_client_; + TestTaskGraphRunner task_graph_runner_; scoped_ptr<FakeLayerTreeHost> layer_tree_host_; }; TEST_F(NinePatchLayerTest, SetLayerProperties) { - scoped_refptr<NinePatchLayer> test_layer = NinePatchLayer::Create(); + scoped_refptr<NinePatchLayer> test_layer = + NinePatchLayer::Create(LayerSettings()); ASSERT_TRUE(test_layer.get()); test_layer->SetIsDrawable(true); test_layer->SetBounds(gfx::Size(100, 100)); @@ -56,11 +56,9 @@ TEST_F(NinePatchLayerTest, SetLayerProperties) { Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get()); - ResourceUpdateQueue queue; gfx::Rect screen_space_clip_rect; - OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); test_layer->SavePaintProperties(); - test_layer->Update(&queue, &occlusion_tracker); + test_layer->Update(); EXPECT_FALSE(test_layer->DrawsContent()); @@ -72,7 +70,7 @@ TEST_F(NinePatchLayerTest, SetLayerProperties) { test_layer->SetAperture(aperture); test_layer->SetUIResourceId(resource->id()); test_layer->SetFillCenter(fill_center); - test_layer->Update(&queue, &occlusion_tracker); + test_layer->Update(); EXPECT_TRUE(test_layer->DrawsContent()); } diff --git a/chromium/cc/layers/painted_scrollbar_layer.cc b/chromium/cc/layers/painted_scrollbar_layer.cc index d82ef989589..f537ffc7e07 100644 --- a/chromium/cc/layers/painted_scrollbar_layer.cc +++ b/chromium/cc/layers/painted_scrollbar_layer.cc @@ -32,18 +32,21 @@ scoped_ptr<LayerImpl> PaintedScrollbarLayer::CreateLayerImpl( } scoped_refptr<PaintedScrollbarLayer> PaintedScrollbarLayer::Create( + const LayerSettings& settings, scoped_ptr<Scrollbar> scrollbar, int scroll_layer_id) { return make_scoped_refptr( - new PaintedScrollbarLayer(scrollbar.Pass(), scroll_layer_id)); + new PaintedScrollbarLayer(settings, scrollbar.Pass(), scroll_layer_id)); } -PaintedScrollbarLayer::PaintedScrollbarLayer(scoped_ptr<Scrollbar> scrollbar, +PaintedScrollbarLayer::PaintedScrollbarLayer(const LayerSettings& settings, + scoped_ptr<Scrollbar> scrollbar, int scroll_layer_id) - : scrollbar_(scrollbar.Pass()), + : Layer(settings), + scrollbar_(scrollbar.Pass()), scroll_layer_id_(scroll_layer_id), clip_layer_id_(Layer::INVALID_ID), - internal_contents_scale_(0.f), + internal_contents_scale_(1.f), thumb_thickness_(scrollbar_->ThumbThickness()), thumb_length_(scrollbar_->ThumbLength()), is_overlay_(scrollbar_->IsOverlay()), @@ -205,12 +208,8 @@ void PaintedScrollbarLayer::UpdateInternalContentScale() { ->settings() .layer_transforms_should_scale_layer_contents) { gfx::Transform transform; - if (layer_tree_host()->using_only_property_trees()) { - transform = DrawTransformFromPropertyTrees( - this, layer_tree_host()->property_trees()->transform_tree); - } else { - transform = draw_transform(); - } + transform = DrawTransformFromPropertyTrees( + this, layer_tree_host()->property_trees()->transform_tree); gfx::Vector2dF transform_scales = MathUtil::ComputeTransform2dScaleComponents(transform, scale); @@ -228,12 +227,11 @@ void PaintedScrollbarLayer::UpdateInternalContentScale() { } } -bool PaintedScrollbarLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { +bool PaintedScrollbarLayer::Update() { { base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, true); - Layer::Update(queue, occlusion); + Layer::Update(); UpdateInternalContentScale(); } diff --git a/chromium/cc/layers/painted_scrollbar_layer.h b/chromium/cc/layers/painted_scrollbar_layer.h index ae2b125e785..3e376b1959e 100644 --- a/chromium/cc/layers/painted_scrollbar_layer.h +++ b/chromium/cc/layers/painted_scrollbar_layer.h @@ -10,7 +10,6 @@ #include "cc/layers/layer.h" #include "cc/layers/scrollbar_layer_interface.h" #include "cc/layers/scrollbar_theme_painter.h" -#include "cc/resources/layer_updater.h" #include "cc/resources/scoped_ui_resource.h" namespace cc { @@ -22,6 +21,7 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface, scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; static scoped_refptr<PaintedScrollbarLayer> Create( + const LayerSettings& settings, scoped_ptr<Scrollbar> scrollbar, int scroll_layer_id); @@ -36,8 +36,7 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface, ScrollbarOrientation orientation() const override; // Layer interface - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; + bool Update() override; void SetLayerTreeHost(LayerTreeHost* host) override; void PushPropertiesTo(LayerImpl* layer) override; void PushScrollClipPropertiesTo(LayerImpl* layer) override; @@ -47,7 +46,9 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface, } protected: - PaintedScrollbarLayer(scoped_ptr<Scrollbar> scrollbar, int scroll_layer_id); + PaintedScrollbarLayer(const LayerSettings& settings, + scoped_ptr<Scrollbar> scrollbar, + int scroll_layer_id); ~PaintedScrollbarLayer() override; // For unit tests diff --git a/chromium/cc/layers/painted_scrollbar_layer_impl.cc b/chromium/cc/layers/painted_scrollbar_layer_impl.cc index 005e0876948..0b5b5801dd6 100644 --- a/chromium/cc/layers/painted_scrollbar_layer_impl.cc +++ b/chromium/cc/layers/painted_scrollbar_layer_impl.cc @@ -95,9 +95,9 @@ void PaintedScrollbarLayerImpl::AppendQuads( gfx::Rect scaled_visible_thumb_quad_rect = gfx::ScaleToEnclosingRect( visible_thumb_quad_rect, internal_contents_scale_); - ResourceProvider::ResourceId thumb_resource_id = + ResourceId thumb_resource_id = layer_tree_impl()->ResourceIdForUIResource(thumb_ui_resource_id_); - ResourceProvider::ResourceId track_resource_id = + ResourceId track_resource_id = layer_tree_impl()->ResourceIdForUIResource(track_ui_resource_id_); if (thumb_resource_id && !visible_thumb_quad_rect.IsEmpty()) { @@ -134,6 +134,9 @@ void PaintedScrollbarLayerImpl::AppendQuads( } gfx::Rect PaintedScrollbarLayerImpl::GetEnclosingRectInTargetSpace() const { + if (internal_content_bounds_.IsEmpty()) + return gfx::Rect(); + DCHECK_GT(internal_contents_scale_, 0.f); return GetScaledEnclosingRectInTargetSpace(internal_contents_scale_); } diff --git a/chromium/cc/layers/painted_scrollbar_layer_impl_unittest.cc b/chromium/cc/layers/painted_scrollbar_layer_impl_unittest.cc index 3fb3fb22bd1..eac32b67efa 100644 --- a/chromium/cc/layers/painted_scrollbar_layer_impl_unittest.cc +++ b/chromium/cc/layers/painted_scrollbar_layer_impl_unittest.cc @@ -38,7 +38,6 @@ TEST(PaintedScrollbarLayerImplTest, Occlusion) { PaintedScrollbarLayerImpl* scrollbar_layer_impl = impl.AddChildToRoot<PaintedScrollbarLayerImpl>(orientation); scrollbar_layer_impl->SetBounds(layer_size); - scrollbar_layer_impl->SetContentBounds(layer_size); scrollbar_layer_impl->SetContentsOpaque(true); scrollbar_layer_impl->set_internal_contents_scale_and_bounds( scale, scaled_layer_size); @@ -89,7 +88,7 @@ TEST(PaintedScrollbarLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(scrollbar_layer_impl->visible_content_rect()); + gfx::Rect occluded(scrollbar_layer_impl->visible_layer_rect()); impl.AppendQuadsWithOcclusion(scrollbar_layer_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); diff --git a/chromium/cc/layers/picture_image_layer.cc b/chromium/cc/layers/picture_image_layer.cc index 345ee2b4e95..6d903bd40bc 100644 --- a/chromium/cc/layers/picture_image_layer.cc +++ b/chromium/cc/layers/picture_image_layer.cc @@ -12,11 +12,14 @@ namespace cc { -scoped_refptr<PictureImageLayer> PictureImageLayer::Create() { - return make_scoped_refptr(new PictureImageLayer()); +scoped_refptr<PictureImageLayer> PictureImageLayer::Create( + const LayerSettings& settings) { + return make_scoped_refptr(new PictureImageLayer(settings)); } -PictureImageLayer::PictureImageLayer() : PictureLayer(this) {} +PictureImageLayer::PictureImageLayer(const LayerSettings& settings) + : PictureLayer(settings, this) { +} PictureImageLayer::~PictureImageLayer() { ClearClient(); @@ -63,10 +66,15 @@ void PictureImageLayer::PaintContents( canvas->drawBitmap(bitmap_, 0, 0); } -void PictureImageLayer::PaintContentsToDisplayList( - DisplayItemList* display_list, +scoped_refptr<DisplayItemList> PictureImageLayer::PaintContentsToDisplayList( const gfx::Rect& clip, ContentLayerClient::PaintingControlSetting painting_control) { + // Picture image layers can be used with GatherPixelRefs, so cached SkPictures + // are currently required. + const bool use_cached_picture = true; + scoped_refptr<DisplayItemList> display_list = + DisplayItemList::Create(clip, use_cached_picture); + SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(gfx::RectToSkRect(clip)); PaintContents(canvas, clip, painting_control); @@ -75,6 +83,9 @@ void PictureImageLayer::PaintContentsToDisplayList( skia::AdoptRef(recorder.endRecordingAsPicture()); auto* item = display_list->CreateAndAppendItem<DrawingDisplayItem>(); item->SetNew(picture.Pass()); + + display_list->Finalize(); + return display_list; } bool PictureImageLayer::FillsBoundsCompletely() const { diff --git a/chromium/cc/layers/picture_image_layer.h b/chromium/cc/layers/picture_image_layer.h index a12a1b9085d..df597f3bf02 100644 --- a/chromium/cc/layers/picture_image_layer.h +++ b/chromium/cc/layers/picture_image_layer.h @@ -15,7 +15,7 @@ namespace cc { class CC_EXPORT PictureImageLayer : public PictureLayer, ContentLayerClient { public: - static scoped_refptr<PictureImageLayer> Create(); + static scoped_refptr<PictureImageLayer> Create(const LayerSettings& settings); void SetBitmap(const SkBitmap& image); @@ -27,8 +27,7 @@ class CC_EXPORT PictureImageLayer : public PictureLayer, ContentLayerClient { SkCanvas* canvas, const gfx::Rect& clip, ContentLayerClient::PaintingControlSetting painting_control) override; - void PaintContentsToDisplayList( - DisplayItemList* display_list, + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, ContentLayerClient::PaintingControlSetting painting_control) override; bool FillsBoundsCompletely() const override; @@ -37,7 +36,7 @@ class CC_EXPORT PictureImageLayer : public PictureLayer, ContentLayerClient { bool HasDrawableContent() const override; private: - PictureImageLayer(); + explicit PictureImageLayer(const LayerSettings& settings); ~PictureImageLayer() override; SkBitmap bitmap_; diff --git a/chromium/cc/layers/picture_image_layer_impl_unittest.cc b/chromium/cc/layers/picture_image_layer_impl_unittest.cc index fa4cb6e7e06..2a9dda710db 100644 --- a/chromium/cc/layers/picture_image_layer_impl_unittest.cc +++ b/chromium/cc/layers/picture_image_layer_impl_unittest.cc @@ -11,7 +11,6 @@ #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_picture_pile_impl.h" -#include "cc/test/impl_side_painting_settings.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/tiles/tile_priority.h" @@ -33,11 +32,18 @@ class TestablePictureImageLayerImpl : public PictureImageLayerImpl { friend class PictureImageLayerImplTest; }; +class PictureLayerImplImageTestSettings : public LayerTreeSettings { + public: + PictureLayerImplImageTestSettings() { + layer_transforms_should_scale_layer_contents = true; + } +}; + class PictureImageLayerImplTest : public testing::Test { public: PictureImageLayerImplTest() : proxy_(base::ThreadTaskRunnerHandle::Get()), - host_impl_(ImplSidePaintingSettings(), + host_impl_(PictureLayerImplImageTestSettings(), &proxy_, &shared_bitmap_manager_, &task_graph_runner_) { @@ -60,7 +66,6 @@ class PictureImageLayerImplTest : public testing::Test { new TestablePictureImageLayerImpl(tree, id); layer->raster_source_ = FakePicturePileImpl::CreateInfiniteFilledPile(); layer->SetBounds(layer->raster_source_->GetSize()); - layer->SetContentBounds(layer->raster_source_->GetSize()); return make_scoped_ptr(layer); } @@ -71,14 +76,15 @@ class PictureImageLayerImplTest : public testing::Test { float maximum_animation_contents_scale, bool animating_transform_to_screen, gfx::Rect viewport_rect) { - layer->draw_properties().ideal_contents_scale = ideal_contents_scale; - layer->draw_properties().device_scale_factor = device_scale_factor; - layer->draw_properties().page_scale_factor = page_scale_factor; + gfx::Transform scale_transform; + scale_transform.Scale(ideal_contents_scale, ideal_contents_scale); + layer->draw_properties().target_space_transform = scale_transform; + DCHECK_EQ(layer->GetIdealContentsScale(), ideal_contents_scale); layer->draw_properties().maximum_animation_contents_scale = maximum_animation_contents_scale; layer->draw_properties().screen_space_transform_is_animating = animating_transform_to_screen; - layer->draw_properties().visible_content_rect = viewport_rect; + layer->draw_properties().visible_layer_rect = viewport_rect; bool resourceless_software_draw = false; layer->UpdateTiles(resourceless_software_draw); } @@ -97,9 +103,6 @@ TEST_F(PictureImageLayerImplTest, CalculateContentsScale) { gfx::Rect viewport(100, 200); SetupDrawPropertiesAndUpdateTiles( layer.get(), 2.f, 3.f, 4.f, 1.f, false, viewport); - - EXPECT_FLOAT_EQ(1.f, layer->contents_scale_x()); - EXPECT_FLOAT_EQ(1.f, layer->contents_scale_y()); EXPECT_FLOAT_EQ(1.f, layer->MaximumTilingContentsScale()); } diff --git a/chromium/cc/layers/picture_image_layer_unittest.cc b/chromium/cc/layers/picture_image_layer_unittest.cc index 786e30979a3..fafdbf12541 100644 --- a/chromium/cc/layers/picture_image_layer_unittest.cc +++ b/chromium/cc/layers/picture_image_layer_unittest.cc @@ -6,6 +6,7 @@ #include "cc/playback/display_item.h" #include "cc/test/skia_common.h" +#include "cc/trees/layer_tree_settings.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -15,7 +16,8 @@ namespace cc { namespace { TEST(PictureImageLayerTest, PaintContentsToDisplayList) { - scoped_refptr<PictureImageLayer> layer = PictureImageLayer::Create(); + scoped_refptr<PictureImageLayer> layer = + PictureImageLayer::Create(LayerSettings()); gfx::Rect layer_rect(200, 200); SkBitmap image_bitmap; @@ -33,46 +35,9 @@ TEST(PictureImageLayerTest, PaintContentsToDisplayList) { layer->SetBitmap(image_bitmap); layer->SetBounds(gfx::Size(layer_rect.width(), layer_rect.height())); - bool use_cached_picture = false; scoped_refptr<DisplayItemList> display_list = - DisplayItemList::Create(layer_rect, use_cached_picture); - layer->PaintContentsToDisplayList( - display_list.get(), layer_rect, - ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); - display_list->ProcessAppendedItems(); - unsigned char actual_pixels[4 * 200 * 200] = {0}; - DrawDisplayList(actual_pixels, layer_rect, display_list); - - EXPECT_EQ(0, memcmp(actual_pixels, image_pixels, 4 * 200 * 200)); -} - -TEST(PictureImageLayerTest, PaintContentsToCachedDisplayList) { - scoped_refptr<PictureImageLayer> layer = PictureImageLayer::Create(); - gfx::Rect layer_rect(200, 200); - - SkBitmap image_bitmap; - unsigned char image_pixels[4 * 200 * 200] = {0}; - SkImageInfo info = - SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); - image_bitmap.installPixels(info, image_pixels, info.minRowBytes()); - SkCanvas image_canvas(image_bitmap); - image_canvas.clear(SK_ColorRED); - SkPaint blue_paint; - blue_paint.setColor(SK_ColorBLUE); - image_canvas.drawRectCoords(0.f, 0.f, 100.f, 100.f, blue_paint); - image_canvas.drawRectCoords(100.f, 100.f, 200.f, 200.f, blue_paint); - - layer->SetBitmap(image_bitmap); - layer->SetBounds(gfx::Size(layer_rect.width(), layer_rect.height())); - - bool use_cached_picture = true; - scoped_refptr<DisplayItemList> display_list = - DisplayItemList::Create(layer_rect, use_cached_picture); - layer->PaintContentsToDisplayList( - display_list.get(), layer_rect, - ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); - display_list->ProcessAppendedItems(); - display_list->CreateAndCacheSkPicture(); + layer->PaintContentsToDisplayList( + layer_rect, ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); unsigned char actual_pixels[4 * 200 * 200] = {0}; DrawDisplayList(actual_pixels, layer_rect, display_list); diff --git a/chromium/cc/layers/picture_layer.cc b/chromium/cc/layers/picture_layer.cc index 999363282a0..53d5d97d456 100644 --- a/chromium/cc/layers/picture_layer.cc +++ b/chromium/cc/layers/picture_layer.cc @@ -16,21 +16,25 @@ namespace cc { -scoped_refptr<PictureLayer> PictureLayer::Create(ContentLayerClient* client) { - return make_scoped_refptr(new PictureLayer(client)); +scoped_refptr<PictureLayer> PictureLayer::Create(const LayerSettings& settings, + ContentLayerClient* client) { + return make_scoped_refptr(new PictureLayer(settings, client)); } -PictureLayer::PictureLayer(ContentLayerClient* client) - : client_(client), +PictureLayer::PictureLayer(const LayerSettings& settings, + ContentLayerClient* client) + : Layer(settings), + client_(client), instrumentation_object_tracker_(id()), update_source_frame_number_(-1), is_mask_(false), nearest_neighbor_(false) { } -PictureLayer::PictureLayer(ContentLayerClient* client, +PictureLayer::PictureLayer(const LayerSettings& settings, + ContentLayerClient* client, scoped_ptr<RecordingSource> source) - : PictureLayer(client) { + : PictureLayer(settings, client) { recording_source_ = source.Pass(); } @@ -88,9 +92,8 @@ void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) { const LayerTreeSettings& settings = layer_tree_host()->settings(); if (!recording_source_) { if (settings.use_display_lists) { - recording_source_.reset(new DisplayListRecordingSource( - settings.default_tile_grid_size, - settings.use_cached_picture_in_display_list)); + recording_source_.reset( + new DisplayListRecordingSource(settings.default_tile_grid_size)); } else { recording_source_.reset(new PicturePile(settings.minimum_contents_scale, settings.default_tile_grid_size)); @@ -99,8 +102,6 @@ void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) { recording_source_->SetSlowdownRasterScaleFactor( host->debug_state().slow_down_raster_scale_factor); recording_source_->SetGatherPixelRefs(settings.gather_pixel_refs); - - DCHECK(settings.raster_enabled); } void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) { @@ -112,16 +113,14 @@ void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) { Layer::SetNeedsDisplayRect(layer_rect); } -bool PictureLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { +bool PictureLayer::Update() { update_source_frame_number_ = layer_tree_host()->source_frame_number(); - bool updated = Layer::Update(queue, occlusion); + bool updated = Layer::Update(); - gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect( - visible_content_rect(), 1.f / contents_scale_x()); + gfx::Rect update_rect = visible_layer_rect(); gfx::Size layer_size = paint_properties().bounds; - if (last_updated_visible_content_rect_ == visible_content_rect() && + if (last_updated_visible_layer_rect_ == update_rect && recording_source_->GetSize() == layer_size && pending_invalidation_.IsEmpty()) { // Only early out if the visible content rect of this layer hasn't changed. @@ -146,7 +145,7 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue, if (layer_tree_host()->settings().record_full_layer) { // Workaround for http://crbug.com/235910 - to retain backwards compat // the full page content must always be provided in the picture layer. - visible_layer_rect = gfx::Rect(layer_size); + update_rect = gfx::Rect(layer_size); } // UpdateAndExpandInvalidation will give us an invalidation that covers @@ -155,9 +154,9 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue, // for them. DCHECK(client_); updated |= recording_source_->UpdateAndExpandInvalidation( - client_, &recording_invalidation_, layer_size, visible_layer_rect, + client_, &recording_invalidation_, layer_size, update_rect, update_source_frame_number_, RecordingSource::RECORD_NORMALLY); - last_updated_visible_content_rect_ = visible_content_rect(); + last_updated_visible_layer_rect_ = visible_layer_rect(); if (updated) { SetNeedsPushProperties(); @@ -186,9 +185,8 @@ skia::RefPtr<SkPicture> PictureLayer::GetPicture() const { if (settings.use_display_lists) { scoped_ptr<RecordingSource> recording_source; - recording_source.reset(new DisplayListRecordingSource( - settings.default_tile_grid_size, - settings.use_cached_picture_in_display_list)); + recording_source.reset( + new DisplayListRecordingSource(settings.default_tile_grid_size)); Region recording_invalidation; recording_source->UpdateAndExpandInvalidation( client_, &recording_invalidation, layer_size, gfx::Rect(layer_size), diff --git a/chromium/cc/layers/picture_layer.h b/chromium/cc/layers/picture_layer.h index 767de273302..771484c19cc 100644 --- a/chromium/cc/layers/picture_layer.h +++ b/chromium/cc/layers/picture_layer.h @@ -9,7 +9,6 @@ #include "cc/debug/devtools_instrumentation.h" #include "cc/debug/micro_benchmark_controller.h" #include "cc/layers/layer.h" -#include "cc/trees/occlusion_tracker.h" namespace cc { @@ -19,7 +18,8 @@ class ResourceUpdateQueue; class CC_EXPORT PictureLayer : public Layer { public: - static scoped_refptr<PictureLayer> Create(ContentLayerClient* client); + static scoped_refptr<PictureLayer> Create(const LayerSettings& settings, + ContentLayerClient* client); void ClearClient(); @@ -30,8 +30,7 @@ class CC_EXPORT PictureLayer : public Layer { void SetLayerTreeHost(LayerTreeHost* host) override; void PushPropertiesTo(LayerImpl* layer) override; void SetNeedsDisplayRect(const gfx::Rect& layer_rect) override; - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; + bool Update() override; void SetIsMask(bool is_mask) override; skia::RefPtr<SkPicture> GetPicture() const override; bool IsSuitableForGpuRasterization() const override; @@ -45,9 +44,11 @@ class CC_EXPORT PictureLayer : public Layer { } protected: - explicit PictureLayer(ContentLayerClient* client); + PictureLayer(const LayerSettings& settings, ContentLayerClient* client); // Allow tests to inject a recording source. - PictureLayer(ContentLayerClient* client, scoped_ptr<RecordingSource> source); + PictureLayer(const LayerSettings& settings, + ContentLayerClient* client, + scoped_ptr<RecordingSource> source); ~PictureLayer() override; bool HasDrawableContent() const override; @@ -63,7 +64,7 @@ class CC_EXPORT PictureLayer : public Layer { InvalidationRegion pending_invalidation_; // Invalidation from the last time update was called. Region recording_invalidation_; - gfx::Rect last_updated_visible_content_rect_; + gfx::Rect last_updated_visible_layer_rect_; int update_source_frame_number_; bool is_mask_; diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc index f9f6d978714..c7076bdc1e1 100644 --- a/chromium/cc/layers/picture_layer_impl.cc +++ b/chromium/cc/layers/picture_layer_impl.cc @@ -12,7 +12,6 @@ #include "base/time/time.h" #include "base/trace_event/trace_event_argument.h" #include "cc/base/math_util.h" -#include "cc/base/util.h" #include "cc/debug/debug_colors.h" #include "cc/debug/micro_benchmark_impl.h" #include "cc/debug/traced_value.h" @@ -162,7 +161,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, SolidColorLayerImpl::AppendSolidQuads( render_pass, draw_properties().occlusion_in_content_space, - shared_quad_state, visible_content_rect(), + shared_quad_state, visible_layer_rect(), raster_source_->GetSolidColor(), append_quads_data); return; } @@ -172,22 +171,22 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, Occlusion scaled_occlusion = draw_properties() .occlusion_in_content_space.GetOcclusionWithGivenDrawTransform( - shared_quad_state->content_to_target_transform); + shared_quad_state->quad_to_target_transform); if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) { AppendDebugBorderQuad( - render_pass, shared_quad_state->content_bounds, shared_quad_state, + render_pass, shared_quad_state->quad_layer_bounds, shared_quad_state, append_quads_data, DebugColors::DirectPictureBorderColor(), DebugColors::DirectPictureBorderWidth(layer_tree_impl())); - gfx::Rect geometry_rect = shared_quad_state->visible_content_rect; + gfx::Rect geometry_rect = shared_quad_state->visible_quad_layer_rect; gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect(); gfx::Rect visible_geometry_rect = scaled_occlusion.GetUnoccludedContentRect(geometry_rect); if (visible_geometry_rect.IsEmpty()) return; - gfx::Rect quad_content_rect = shared_quad_state->visible_content_rect; + gfx::Rect quad_content_rect = shared_quad_state->visible_quad_layer_rect; gfx::Size texture_size = quad_content_rect.size(); gfx::RectF texture_rect = gfx::RectF(texture_size); @@ -201,13 +200,13 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, return; } - AppendDebugBorderQuad(render_pass, shared_quad_state->content_bounds, + AppendDebugBorderQuad(render_pass, shared_quad_state->quad_layer_bounds, shared_quad_state, append_quads_data); if (ShowDebugBorders()) { for (PictureLayerTilingSet::CoverageIterator iter( tilings_.get(), max_contents_scale, - shared_quad_state->visible_content_rect, ideal_contents_scale_); + shared_quad_state->visible_quad_layer_rect, ideal_contents_scale_); iter; ++iter) { SkColor color; float width; @@ -264,7 +263,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, only_used_low_res_last_append_quads_ = true; for (PictureLayerTilingSet::CoverageIterator iter( tilings_.get(), max_contents_scale, - shared_quad_state->visible_content_rect, ideal_contents_scale_); + shared_quad_state->visible_quad_layer_rect, ideal_contents_scale_); iter; ++iter) { gfx::Rect geometry_rect = iter.geometry_rect(); gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect(); @@ -273,7 +272,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, if (visible_geometry_rect.IsEmpty()) continue; - append_quads_data->visible_content_area += + append_quads_data->visible_layer_area += visible_geometry_rect.width() * visible_geometry_rect.height(); bool has_draw_quad = false; @@ -302,6 +301,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, texture_rect, draw_info.resource_size(), draw_info.contents_swizzled(), nearest_neighbor_); ValidateQuadResources(quad); + iter->draw_info().set_was_ever_used_to_draw(); has_draw_quad = true; break; } @@ -311,6 +311,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect, draw_info.solid_color(), false); ValidateQuadResources(quad); + iter->draw_info().set_was_ever_used_to_draw(); has_draw_quad = true; break; } @@ -320,23 +321,14 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, } if (!has_draw_quad) { - if (draw_checkerboard_for_missing_tiles()) { - CheckerboardDrawQuad* quad = - render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>(); - SkColor color = DebugColors::DefaultCheckerboardColor(); - quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect, - color, draw_properties().device_scale_factor); - } else { - SkColor color = SafeOpaqueBackgroundColor(); - SolidColorDrawQuad* quad = - render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - quad->SetNew(shared_quad_state, - geometry_rect, - visible_geometry_rect, - color, - false); - ValidateQuadResources(quad); - } + // Checkerboard. + // TODO(danakj): Make this a different color when debugging. + SkColor color = SafeOpaqueBackgroundColor(); + SolidColorDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect, + color, false); + ValidateQuadResources(quad); if (geometry_rect.Intersects(scaled_viewport_for_tile_priority)) { append_quads_data->num_missing_tiles++; @@ -377,17 +369,14 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, // Aggressively remove any tilings that are not seen to save memory. Note // that this is at the expense of doing cause more frequent re-painting. A - // better scheme would be to maintain a tighter visible_content_rect for the + // better scheme would be to maintain a tighter visible_layer_rect for the // finer tilings. CleanUpTilingsOnActiveLayer(last_append_quads_tilings_); } bool PictureLayerImpl::UpdateTiles(bool resourceless_software_draw) { - DCHECK_EQ(1.f, contents_scale_x()); - DCHECK_EQ(1.f, contents_scale_y()); - if (!resourceless_software_draw) { - visible_rect_for_tile_priority_ = visible_content_rect(); + visible_rect_for_tile_priority_ = visible_layer_rect(); } if (!CanHaveTilings()) { @@ -478,6 +467,21 @@ void PictureLayerImpl::UpdateViewportRectForTilePriorityInContentSpace() { visible_rect_in_content_space = gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( view_to_layer, viewport_rect_for_tile_priority)); + + // We have to allow for a viewport that is outside of the layer bounds in + // order to compute tile priorities correctly for offscreen content that + // is going to make it on screen. However, we also have to limit the + // viewport since it can be very large due to screen_space_transforms. As + // a heuristic, we clip to bounds padded by skewport_extrapolation_limit * + // maximum tiling scale, since this should allow sufficient room for + // skewport calculations. + gfx::Rect padded_bounds(bounds()); + int padding_amount = layer_tree_impl() + ->settings() + .skewport_extrapolation_limit_in_content_pixels * + MaximumTilingContentsScale(); + padded_bounds.Inset(-padding_amount, -padding_amount); + visible_rect_in_content_space.Intersect(padded_bounds); } } viewport_rect_for_tile_priority_in_content_space_ = @@ -490,12 +494,6 @@ PictureLayerImpl* PictureLayerImpl::GetPendingOrActiveTwinLayer() const { return twin_layer_; } -PictureLayerImpl* PictureLayerImpl::GetRecycledTwinLayer() const { - if (!twin_layer_ || twin_layer_->IsOnActiveOrPendingTree()) - return nullptr; - return twin_layer_; -} - void PictureLayerImpl::UpdateRasterSource( scoped_refptr<RasterSource> raster_source, Region* new_invalidation, @@ -583,6 +581,12 @@ void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) { gfx::ScaleRect(tile->content_rect(), 1.f / tile->contents_scale()); AddDamageRect(layer_damage_rect); } + if (tile->draw_info().NeedsRaster()) { + PictureLayerTiling* tiling = + tilings_->FindTilingWithScale(tile->contents_scale()); + if (tiling) + tiling->set_all_tiles_done(false); + } } void PictureLayerImpl::DidBeginTracing() { @@ -651,12 +655,6 @@ const PictureLayerTiling* PictureLayerImpl::GetPendingOrActiveTwinTiling( return twin_layer->tilings_->FindTilingWithScale(tiling->contents_scale()); } -TilePriority::PriorityBin PictureLayerImpl::GetMaxTilePriorityBin() const { - if (!HasValidTilePriorities()) - return TilePriority::EVENTUALLY; - return TilePriority::NOW; -} - bool PictureLayerImpl::RequiresHighResToDraw() const { return layer_tree_impl()->RequiresHighResToDraw(); } @@ -695,7 +693,7 @@ gfx::Size PictureLayerImpl::CalculateTileSize( divisor = 2; if (content_bounds.width() <= viewport_width / 4) divisor = 1; - default_tile_height = RoundUp(viewport_height, divisor) / divisor; + default_tile_height = MathUtil::RoundUp(viewport_height, divisor) / divisor; // Grow default sizes to account for overlapping border texels. default_tile_width += 2 * PictureLayerTiling::kBorderTexels; @@ -731,12 +729,12 @@ gfx::Size PictureLayerImpl::CalculateTileSize( // Clamp the tile width/height to the content width/height to save space. if (content_bounds.width() < default_tile_width) { tile_width = std::min(tile_width, content_bounds.width()); - tile_width = RoundUp(tile_width, kTileRoundUp); + tile_width = MathUtil::RoundUp(tile_width, kTileRoundUp); tile_width = std::min(tile_width, default_tile_width); } if (content_bounds.height() < default_tile_height) { tile_height = std::min(tile_height, content_bounds.height()); - tile_height = RoundUp(tile_height, kTileRoundUp); + tile_height = MathUtil::RoundUp(tile_height, kTileRoundUp); tile_height = std::min(tile_height, default_tile_height); } @@ -746,9 +744,8 @@ gfx::Size PictureLayerImpl::CalculateTileSize( return gfx::Size(tile_width, tile_height); } -void PictureLayerImpl::GetContentsResourceId( - ResourceProvider::ResourceId* resource_id, - gfx::Size* resource_size) const { +void PictureLayerImpl::GetContentsResourceId(ResourceId* resource_id, + gfx::Size* resource_size) const { // The bounds and the pile size may differ if the pile wasn't updated (ie. // PictureLayer::Update didn't happen). In that case the pile will be empty. DCHECK_IMPLIES(!raster_source_->GetSize().IsEmpty(), @@ -813,31 +810,29 @@ void PictureLayerImpl::AddTilingsForRasterScale() { // We always need a high res tiling, so create one if it doesn't exist. if (!high_res) high_res = AddTiling(raster_contents_scale_); - - // Try and find a low res tiling. - PictureLayerTiling* low_res = nullptr; - if (raster_contents_scale_ == low_res_raster_contents_scale_) - low_res = high_res; - else - low_res = tilings_->FindTilingWithScale(low_res_raster_contents_scale_); - - // Only create new low res tilings when the transform is static. This - // prevents wastefully creating a paired low res tiling for every new high res - // tiling during a pinch or a CSS animation. - bool can_have_low_res = layer_tree_impl()->create_low_res_tiling(); - bool needs_low_res = !low_res; - bool is_pinching = layer_tree_impl()->PinchGestureActive(); - bool is_animating = draw_properties().screen_space_transform_is_animating; - if (can_have_low_res && needs_low_res && !is_pinching && !is_animating) - low_res = AddTiling(low_res_raster_contents_scale_); - - // Set low-res if we have one. - if (low_res && low_res != high_res) - low_res->set_resolution(LOW_RESOLUTION); - - // Make sure we always have one high-res (even if high == low). high_res->set_resolution(HIGH_RESOLUTION); + // If the low res scale is the same as the high res scale, that tiling + // will be treated as high res. + if (layer_tree_impl()->create_low_res_tiling() && + raster_contents_scale_ != low_res_raster_contents_scale_) { + PictureLayerTiling* low_res = + tilings_->FindTilingWithScale(low_res_raster_contents_scale_); + + // Only create new low res tilings when the transform is static. This + // prevents wastefully creating a paired low res tiling for every new high + // res tiling during a pinch or a CSS animation. + bool is_pinching = layer_tree_impl()->PinchGestureActive(); + bool is_animating = draw_properties().screen_space_transform_is_animating; + if (!low_res && !is_pinching && !is_animating) + low_res = AddTiling(low_res_raster_contents_scale_); + + if (low_res) { + DCHECK_NE(low_res, high_res); + low_res->set_resolution(LOW_RESOLUTION); + } + } + if (layer_tree_impl()->IsPendingTree()) { // On the pending tree, drop any tilings that are non-ideal since we don't // need them to activate anyway. @@ -1038,19 +1033,9 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer( } PictureLayerTilingSet* twin_set = twin ? twin->tilings_.get() : nullptr; - // TODO(vmpstr): See if this step is required without tile sharing. - PictureLayerImpl* recycled_twin = GetRecycledTwinLayer(); - PictureLayerTilingSet* recycled_twin_set = - recycled_twin ? recycled_twin->tilings_.get() : nullptr; - - tilings_->CleanUpTilings(min_acceptable_high_res_scale, - max_acceptable_high_res_scale, used_tilings, - layer_tree_impl()->create_low_res_tiling(), twin_set, - recycled_twin_set); - - if (recycled_twin_set && recycled_twin_set->num_tilings() == 0) - recycled_twin->ResetRasterScale(); - + tilings_->CleanUpTilings( + min_acceptable_high_res_scale, max_acceptable_high_res_scale, + used_tilings, layer_tree_impl()->create_low_res_tiling(), twin_set); DCHECK_GT(tilings_->num_tilings(), 0u); SanityCheckTilingState(); } @@ -1118,10 +1103,6 @@ bool PictureLayerImpl::CanHaveTilings() const { void PictureLayerImpl::SanityCheckTilingState() const { #if DCHECK_IS_ON() - // Recycle tree doesn't have any restrictions. - if (layer_tree_impl()->IsRecycleTree()) - return; - if (!CanHaveTilings()) { DCHECK_EQ(0u, tilings_->num_tilings()); return; @@ -1159,21 +1140,14 @@ void PictureLayerImpl::UpdateIdealScales() { float min_contents_scale = MinimumContentsScale(); DCHECK_GT(min_contents_scale, 0.f); - float min_page_scale = layer_tree_impl()->min_page_scale_factor(); - DCHECK_GT(min_page_scale, 0.f); - float min_device_scale = 1.f; - float min_source_scale = - min_contents_scale / min_page_scale / min_device_scale; - - float ideal_page_scale = draw_properties().page_scale_factor; - float ideal_device_scale = draw_properties().device_scale_factor; - float ideal_source_scale = draw_properties().ideal_contents_scale / - ideal_page_scale / ideal_device_scale; - ideal_contents_scale_ = - std::max(draw_properties().ideal_contents_scale, min_contents_scale); - ideal_page_scale_ = draw_properties().page_scale_factor; - ideal_device_scale_ = draw_properties().device_scale_factor; - ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale); + + ideal_page_scale_ = IsAffectedByPageScale() + ? layer_tree_impl()->current_page_scale_factor() + : 1.f; + ideal_device_scale_ = layer_tree_impl()->device_scale_factor(); + ideal_contents_scale_ = std::max(GetIdealContentsScale(), min_contents_scale); + ideal_source_scale_ = + ideal_contents_scale_ / ideal_page_scale_ / ideal_device_scale_; } void PictureLayerImpl::GetDebugBorderProperties( @@ -1202,7 +1176,7 @@ void PictureLayerImpl::AsValueInto( MathUtil::AddToTracedValue("tile_priority_rect", viewport_rect_for_tile_priority_in_content_space_, state); - MathUtil::AddToTracedValue("visible_rect", visible_content_rect(), state); + MathUtil::AddToTracedValue("visible_rect", visible_layer_rect(), state); state->BeginArray("pictures"); raster_source_->AsValueInto(state); diff --git a/chromium/cc/layers/picture_layer_impl.h b/chromium/cc/layers/picture_layer_impl.h index bca8224974c..a23dbba61d7 100644 --- a/chromium/cc/layers/picture_layer_impl.h +++ b/chromium/cc/layers/picture_layer_impl.h @@ -61,7 +61,7 @@ class CC_EXPORT PictureLayerImpl const Region* GetPendingInvalidation() override; const PictureLayerTiling* GetPendingOrActiveTwinTiling( const PictureLayerTiling* tiling) const override; - TilePriority::PriorityBin GetMaxTilePriorityBin() const override; + bool HasValidTilePriorities() const override; bool RequiresHighResToDraw() const override; gfx::Rect GetEnclosingRectInTargetSpace() const override; @@ -77,7 +77,7 @@ class CC_EXPORT PictureLayerImpl WhichTree GetTree() const; // Mask-related functions. - void GetContentsResourceId(ResourceProvider::ResourceId* resource_id, + void GetContentsResourceId(ResourceId* resource_id, gfx::Size* resource_size) const override; void SetNearestNeighbor(bool nearest_neighbor); @@ -93,8 +93,6 @@ class CC_EXPORT PictureLayerImpl // Functions used by tile manager. PictureLayerImpl* GetPendingOrActiveTwinLayer() const; bool IsOnActiveOrPendingTree() const; - // Virtual for testing. - virtual bool HasValidTilePriorities() const; // Used for benchmarking RasterSource* GetRasterSource() const { return raster_source_.get(); } diff --git a/chromium/cc/layers/picture_layer_impl_perftest.cc b/chromium/cc/layers/picture_layer_impl_perftest.cc index adb05976f72..dcbf2fba85f 100644 --- a/chromium/cc/layers/picture_layer_impl_perftest.cc +++ b/chromium/cc/layers/picture_layer_impl_perftest.cc @@ -11,7 +11,6 @@ #include "cc/test/fake_output_surface.h" #include "cc/test/fake_picture_layer_impl.h" #include "cc/test/fake_picture_pile_impl.h" -#include "cc/test/impl_side_painting_settings.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/tiles/tiling_set_raster_queue_all.h" @@ -41,7 +40,7 @@ class PictureLayerImplPerfTest : public testing::Test { public: PictureLayerImplPerfTest() : proxy_(base::ThreadTaskRunnerHandle::Get()), - host_impl_(ImplSidePaintingSettings(), + host_impl_(LayerTreeSettings(), &proxy_, &shared_bitmap_manager_, &task_graph_runner_), @@ -53,22 +52,21 @@ class PictureLayerImplPerfTest : public testing::Test { host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()); } - void SetupPendingTree(const gfx::Size& layer_bounds, - const gfx::Size& tile_size) { + void SetupActiveTree(const gfx::Size& layer_bounds, + const gfx::Size& tile_size) { scoped_refptr<FakePicturePileImpl> pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - host_impl_.CreatePendingTree(); - LayerTreeImpl* pending_tree = host_impl_.pending_tree(); - pending_tree->DetachLayerTree(); - - scoped_ptr<FakePictureLayerImpl> pending_layer = - FakePictureLayerImpl::CreateWithRasterSource(pending_tree, 7, pile); - pending_layer->SetDrawsContent(true); - pending_layer->SetHasRenderSurface(true); - pending_tree->SetRootLayer(pending_layer.Pass()); - - pending_layer_ = static_cast<FakePictureLayerImpl*>( - host_impl_.pending_tree()->LayerById(7)); + LayerTreeImpl* active_tree = host_impl_.active_tree(); + active_tree->DetachLayerTree(); + + scoped_ptr<FakePictureLayerImpl> active_layer = + FakePictureLayerImpl::CreateWithRasterSource(active_tree, 7, pile); + active_layer->SetDrawsContent(true); + active_layer->SetHasRenderSurface(true); + active_tree->SetRootLayer(active_layer.Pass()); + + active_layer_ = static_cast<FakePictureLayerImpl*>( + host_impl_.active_tree()->LayerById(7)); } void RunRasterQueueConstructAndIterateTest(const std::string& test_name, @@ -76,13 +74,13 @@ class PictureLayerImplPerfTest : public testing::Test { const gfx::Size& viewport_size) { host_impl_.SetViewportSize(viewport_size); bool update_lcd_text = false; - host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); + host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text); timer_.Reset(); do { int count = num_tiles; scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll( - pending_layer_->picture_layer_tiling_set(), false)); + active_layer_->picture_layer_tiling_set(), false)); while (count--) { ASSERT_TRUE(!queue->IsEmpty()) << "count: " << count; ASSERT_TRUE(queue->Top().tile()) << "count: " << count; @@ -98,15 +96,15 @@ class PictureLayerImplPerfTest : public testing::Test { void RunRasterQueueConstructTest(const std::string& test_name, const gfx::Rect& viewport) { host_impl_.SetViewportSize(viewport.size()); - pending_layer_->PushScrollOffsetFromMainThread( + active_layer_->PushScrollOffsetFromMainThreadAndClobberActiveValue( gfx::ScrollOffset(viewport.x(), viewport.y())); bool update_lcd_text = false; - host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); + host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text); timer_.Reset(); do { scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll( - pending_layer_->picture_layer_tiling_set(), false)); + active_layer_->picture_layer_tiling_set(), false)); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); @@ -119,14 +117,15 @@ class PictureLayerImplPerfTest : public testing::Test { int num_tiles, const gfx::Size& viewport_size) { host_impl_.SetViewportSize(viewport_size); + active_layer_->MarkAllTilingsUsed(); bool update_lcd_text = false; - host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); + host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text); timer_.Reset(); do { int count = num_tiles; scoped_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue( - pending_layer_->picture_layer_tiling_set())); + active_layer_->picture_layer_tiling_set())); while (count--) { ASSERT_TRUE(!queue->IsEmpty()) << "count: " << count; ASSERT_TRUE(queue->Top().tile()) << "count: " << count; @@ -143,15 +142,16 @@ class PictureLayerImplPerfTest : public testing::Test { void RunEvictionQueueConstructTest(const std::string& test_name, const gfx::Rect& viewport) { host_impl_.SetViewportSize(viewport.size()); - pending_layer_->PushScrollOffsetFromMainThread( + active_layer_->PushScrollOffsetFromMainThreadAndClobberActiveValue( gfx::ScrollOffset(viewport.x(), viewport.y())); + active_layer_->MarkAllTilingsUsed(); bool update_lcd_text = false; - host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); + host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text); timer_.Reset(); do { scoped_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue( - pending_layer_->picture_layer_tiling_set())); + active_layer_->picture_layer_tiling_set())); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); @@ -164,7 +164,7 @@ class PictureLayerImplPerfTest : public testing::Test { TestTaskGraphRunner task_graph_runner_; FakeImplProxy proxy_; FakeLayerTreeHostImpl host_impl_; - FakePictureLayerImpl* pending_layer_; + FakePictureLayerImpl* active_layer_; LapTimer timer_; private: @@ -172,15 +172,15 @@ class PictureLayerImplPerfTest : public testing::Test { }; TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstructAndIterate) { - SetupPendingTree(gfx::Size(10000, 10000), gfx::Size(256, 256)); + SetupActiveTree(gfx::Size(10000, 10000), gfx::Size(256, 256)); float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; - pending_layer_->AddTiling(low_res_factor); - pending_layer_->AddTiling(0.3f); - pending_layer_->AddTiling(0.7f); - pending_layer_->AddTiling(1.0f); - pending_layer_->AddTiling(2.0f); + active_layer_->AddTiling(low_res_factor); + active_layer_->AddTiling(0.3f); + active_layer_->AddTiling(0.7f); + active_layer_->AddTiling(1.0f); + active_layer_->AddTiling(2.0f); RunRasterQueueConstructAndIterateTest("32_100x100", 32, gfx::Size(100, 100)); RunRasterQueueConstructAndIterateTest("32_500x500", 32, gfx::Size(500, 500)); @@ -189,15 +189,15 @@ TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstructAndIterate) { } TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstruct) { - SetupPendingTree(gfx::Size(10000, 10000), gfx::Size(256, 256)); + SetupActiveTree(gfx::Size(10000, 10000), gfx::Size(256, 256)); float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; - pending_layer_->AddTiling(low_res_factor); - pending_layer_->AddTiling(0.3f); - pending_layer_->AddTiling(0.7f); - pending_layer_->AddTiling(1.0f); - pending_layer_->AddTiling(2.0f); + active_layer_->AddTiling(low_res_factor); + active_layer_->AddTiling(0.3f); + active_layer_->AddTiling(0.7f); + active_layer_->AddTiling(1.0f); + active_layer_->AddTiling(2.0f); RunRasterQueueConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100)); RunRasterQueueConstructTest("5000_0_100x100", gfx::Rect(5000, 0, 100, 100)); @@ -205,16 +205,16 @@ TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstruct) { } TEST_F(PictureLayerImplPerfTest, TilingSetEvictionQueueConstructAndIterate) { - SetupPendingTree(gfx::Size(10000, 10000), gfx::Size(256, 256)); + SetupActiveTree(gfx::Size(10000, 10000), gfx::Size(256, 256)); float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; std::vector<Tile*> all_tiles; - AddTiling(low_res_factor, pending_layer_, &all_tiles); - AddTiling(0.3f, pending_layer_, &all_tiles); - AddTiling(0.7f, pending_layer_, &all_tiles); - AddTiling(1.0f, pending_layer_, &all_tiles); - AddTiling(2.0f, pending_layer_, &all_tiles); + AddTiling(low_res_factor, active_layer_, &all_tiles); + AddTiling(0.3f, active_layer_, &all_tiles); + AddTiling(0.7f, active_layer_, &all_tiles); + AddTiling(1.0f, active_layer_, &all_tiles); + AddTiling(2.0f, active_layer_, &all_tiles); ASSERT_TRUE(host_impl_.tile_manager() != nullptr); host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles); @@ -230,16 +230,16 @@ TEST_F(PictureLayerImplPerfTest, TilingSetEvictionQueueConstructAndIterate) { } TEST_F(PictureLayerImplPerfTest, TilingSetEvictionQueueConstruct) { - SetupPendingTree(gfx::Size(10000, 10000), gfx::Size(256, 256)); + SetupActiveTree(gfx::Size(10000, 10000), gfx::Size(256, 256)); float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; std::vector<Tile*> all_tiles; - AddTiling(low_res_factor, pending_layer_, &all_tiles); - AddTiling(0.3f, pending_layer_, &all_tiles); - AddTiling(0.7f, pending_layer_, &all_tiles); - AddTiling(1.0f, pending_layer_, &all_tiles); - AddTiling(2.0f, pending_layer_, &all_tiles); + AddTiling(low_res_factor, active_layer_, &all_tiles); + AddTiling(0.3f, active_layer_, &all_tiles); + AddTiling(0.7f, active_layer_, &all_tiles); + AddTiling(1.0f, active_layer_, &all_tiles); + AddTiling(2.0f, active_layer_, &all_tiles); ASSERT_TRUE(host_impl_.tile_manager() != nullptr); host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles); diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc index cc89133b781..6e89caa802a 100644 --- a/chromium/cc/layers/picture_layer_impl_unittest.cc +++ b/chromium/cc/layers/picture_layer_impl_unittest.cc @@ -63,9 +63,16 @@ class MockCanvas : public SkCanvas { std::vector<SkRect> rects_; }; -class NoLowResTilingsSettings : public GpuRasterizationEnabledSettings {}; +class PictureLayerImplTestSettings : public GpuRasterizationEnabledSettings { + public: + PictureLayerImplTestSettings() { + layer_transforms_should_scale_layer_contents = true; + } +}; -class LowResTilingsSettings : public GpuRasterizationEnabledSettings { +class NoLowResTilingsSettings : public PictureLayerImplTestSettings {}; + +class LowResTilingsSettings : public PictureLayerImplTestSettings { public: LowResTilingsSettings() { create_low_res_tiling = true; } }; @@ -201,7 +208,8 @@ class PictureLayerImplTest : public testing::Test { const gfx::Size& tile_size, const Region& invalidation) { host_impl_.CreatePendingTree(); - host_impl_.pending_tree()->PushPageScaleFromMainThread(1.f, 0.25f, 100.f); + host_impl_.pending_tree()->PushPageScaleFromMainThread(1.f, 0.00001f, + 100000.f); LayerTreeImpl* pending_tree = host_impl_.pending_tree(); // Steal from the recycled tree if possible. @@ -223,7 +231,6 @@ class PictureLayerImplTest : public testing::Test { pending_root->SetHasRenderSurface(true); // The bounds() just mirror the pile size. pending_layer->SetBounds(raster_source->GetSize()); - pending_layer->SetContentBounds(raster_source->GetSize()); pending_layer->SetRasterSourceOnPending(raster_source, invalidation); pending_root->AddChild(pending_layer.Pass()); @@ -245,9 +252,13 @@ class PictureLayerImplTest : public testing::Test { float maximum_animation_contents_scale, float starting_animation_contents_scale, bool animating_transform_to_screen) { - layer->draw_properties().ideal_contents_scale = ideal_contents_scale; - layer->draw_properties().device_scale_factor = device_scale_factor; - layer->draw_properties().page_scale_factor = page_scale_factor; + host_impl_.SetDeviceScaleFactor(device_scale_factor); + host_impl_.SetPageScaleOnActiveTree(page_scale_factor); + + gfx::Transform scale_transform; + scale_transform.Scale(ideal_contents_scale, ideal_contents_scale); + layer->draw_properties().target_space_transform = scale_transform; + DCHECK_EQ(layer->GetIdealContentsScale(), ideal_contents_scale); layer->draw_properties().maximum_animation_contents_scale = maximum_animation_contents_scale; layer->draw_properties().starting_animation_contents_scale = @@ -342,6 +353,7 @@ class PictureLayerImplTest : public testing::Test { FakePictureLayerImpl* pending_layer_; FakePictureLayerImpl* old_pending_layer_; FakePictureLayerImpl* active_layer_; + LayerSettings layer_settings_; private: DISALLOW_COPY_AND_ASSIGN(PictureLayerImplTest); @@ -355,7 +367,7 @@ class NoLowResPictureLayerImplTest : public PictureLayerImplTest { TEST_F(PictureLayerImplTest, TileGridAlignment) { // Layer to span 4 raster tiles in x and in y - ImplSidePaintingSettings settings; + LayerTreeSettings settings; gfx::Size layer_size(settings.default_tile_size.width() * 7 / 2, settings.default_tile_size.height() * 7 / 2); @@ -427,10 +439,7 @@ TEST_F(PictureLayerImplTest, CloneNoInvalidation) { } TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(400, 400); @@ -444,9 +453,7 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) { SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, 0.f, false); - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); // Update tiles with viewport for tile priority as (0, 0, 100, 100) and the // identify transform for tile priority. @@ -483,9 +490,7 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) { // screen space and the transform for tile priority is translated and // rotated. The actual viewport for tile priority used by PictureLayerImpl // should be (200, 200, 100, 100) applied with the said transform. - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); viewport_rect_for_tile_priority = gfx::Rect(200, 200, 100, 100); transform_for_tile_priority.Translate(100, 100); @@ -523,10 +528,7 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) { } TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(400, 400); @@ -553,7 +555,7 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) { viewport, transform, resourceless_software_draw); - active_layer_->draw_properties().visible_content_rect = viewport; + active_layer_->draw_properties().visible_layer_rect = viewport; active_layer_->draw_properties().screen_space_transform = transform; active_layer_->UpdateTiles(resourceless_software_draw); @@ -565,13 +567,11 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) { // Expand viewport and set it as invalid for prioritizing tiles. // Should update viewport and transform, but not update visible rect. - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); resourceless_software_draw = true; viewport = gfx::ScaleToEnclosingRect(viewport, 2); transform.Translate(1.f, 1.f); - active_layer_->draw_properties().visible_content_rect = viewport; + active_layer_->draw_properties().visible_layer_rect = viewport; active_layer_->draw_properties().screen_space_transform = transform; host_impl_.SetExternalDrawConstraints(transform, viewport, @@ -589,9 +589,7 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) { active_layer_->visible_rect_for_tile_priority()); // Keep expanded viewport but mark it valid. Should update tile viewport. - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); resourceless_software_draw = false; host_impl_.SetExternalDrawConstraints(transform, viewport, @@ -607,10 +605,7 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) { } TEST_F(PictureLayerImplTest, ViewportRectForTilePriorityIsCached) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(400, 400); @@ -624,9 +619,7 @@ TEST_F(PictureLayerImplTest, ViewportRectForTilePriorityIsCached) { SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, 0.f, false); - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); bool resourceless_software_draw = false; gfx::Rect viewport = gfx::Rect(layer_bounds); @@ -642,9 +635,7 @@ TEST_F(PictureLayerImplTest, ViewportRectForTilePriorityIsCached) { EXPECT_EQ(viewport_rect_for_tile_priority, active_layer_->viewport_rect_for_tile_priority_in_content_space()); - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); gfx::Rect another_viewport_rect_for_tile_priority(11, 11, 50, 50); host_impl_.SetExternalDrawConstraints( @@ -1315,7 +1306,6 @@ TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) { FakePictureLayerImpl::CreateMaskWithRasterSource( host_impl_.pending_tree(), 3, pending_pile); mask->SetBounds(layer_bounds); - mask->SetContentBounds(layer_bounds); mask->SetDrawsContent(true); SetupDrawPropertiesAndUpdateTiles( @@ -1326,10 +1316,7 @@ TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) { } TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(1000, 1000); @@ -1342,14 +1329,11 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) { FakePictureLayerImpl::CreateMaskWithRasterSource( host_impl_.pending_tree(), 3, valid_pile); mask_ptr->SetBounds(layer_bounds); - mask_ptr->SetContentBounds(layer_bounds); mask_ptr->SetDrawsContent(true); pending_layer_->SetMaskLayer(mask_ptr.Pass()); pending_layer_->SetHasRenderSurface(true); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); @@ -1370,7 +1354,7 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) { // Mask layers have a tiling with a single tile in it. EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size()); // The mask resource exists. - ResourceProvider::ResourceId mask_resource_id; + ResourceId mask_resource_id; gfx::Size mask_texture_size; active_mask->GetContentsResourceId(&mask_resource_id, &mask_texture_size); EXPECT_NE(0u, mask_resource_id); @@ -1396,12 +1380,9 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) { SetupPendingTree(huge_pile); pending_mask->SetBounds(huge_bounds); - pending_mask->SetContentBounds(huge_bounds); pending_mask->SetRasterSourceOnPending(huge_pile, Region()); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); // The mask tiling gets scaled down. @@ -1451,24 +1432,18 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) { SetupPendingTree(extra_huge_pile); pending_mask->SetBounds(extra_huge_bounds); - pending_mask->SetContentBounds(extra_huge_bounds); pending_mask->SetRasterSourceOnPending(extra_huge_pile, Region()); EXPECT_FALSE(pending_mask->CanHaveTilings()); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); EXPECT_EQ(0u, pending_mask->num_tilings()); } TEST_F(PictureLayerImplTest, ScaledMaskLayer) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(1000, 1000); @@ -1483,14 +1458,11 @@ TEST_F(PictureLayerImplTest, ScaledMaskLayer) { FakePictureLayerImpl::CreateMaskWithRasterSource( host_impl_.pending_tree(), 3, valid_pile); mask_ptr->SetBounds(layer_bounds); - mask_ptr->SetContentBounds(layer_bounds); mask_ptr->SetDrawsContent(true); pending_layer_->SetMaskLayer(mask_ptr.Pass()); pending_layer_->SetHasRenderSurface(true); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); @@ -1512,7 +1484,7 @@ TEST_F(PictureLayerImplTest, ScaledMaskLayer) { // Mask layers have a tiling with a single tile in it. EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size()); // The mask resource exists. - ResourceProvider::ResourceId mask_resource_id; + ResourceId mask_resource_id; gfx::Size mask_texture_size; active_mask->GetContentsResourceId(&mask_resource_id, &mask_texture_size); EXPECT_NE(0u, mask_resource_id); @@ -1661,8 +1633,7 @@ TEST_F(PictureLayerImplTest, DisallowTileDrawQuads) { gfx::Rect layer_invalidation(150, 200, 30, 180); SetupTreesWithInvalidation(pending_pile, active_pile, layer_invalidation); - active_layer_->draw_properties().visible_content_rect = - gfx::Rect(layer_bounds); + active_layer_->draw_properties().visible_layer_rect = gfx::Rect(layer_bounds); AppendQuadsData data; active_layer_->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE, nullptr); @@ -1692,7 +1663,7 @@ TEST_F(PictureLayerImplTest, SolidColorLayerHasVisibleFullCoverage) { SetupTrees(pending_pile, active_pile); - active_layer_->draw_properties().visible_content_rect = visible_rect; + active_layer_->draw_properties().visible_layer_rect = visible_rect; AppendQuadsData data; active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr); @@ -1753,9 +1724,7 @@ TEST_F(NoLowResPictureLayerImplTest, MarkRequiredOffscreenTiles) { EXPECT_EQ(viewport, pending_layer_->visible_rect_for_tile_priority()); base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); pending_layer_->UpdateTiles(resourceless_software_draw); int num_visible = 0; @@ -1781,15 +1750,12 @@ TEST_F(NoLowResPictureLayerImplTest, MarkRequiredOffscreenTiles) { TEST_F(NoLowResPictureLayerImplTest, TileOutsideOfViewportForTilePriorityNotRequired) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(400, 400); gfx::Rect external_viewport_for_tile_priority(400, 200); - gfx::Rect visible_content_rect(200, 400); + gfx::Rect visible_layer_rect(200, 400); scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); @@ -1811,25 +1777,21 @@ TEST_F(NoLowResPictureLayerImplTest, external_viewport_for_tile_priority, transform_for_tile_priority, resourceless_software_draw); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); // Set visible content rect that is different from // external_viewport_for_tile_priority. - pending_layer_->draw_properties().visible_content_rect = visible_content_rect; - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + pending_layer_->draw_properties().visible_layer_rect = visible_layer_rect; + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); pending_layer_->UpdateTiles(resourceless_software_draw); // Intersect the two rects. Any tile outside should not be required for // activation. gfx::Rect viewport_for_tile_priority = pending_layer_->viewport_rect_for_tile_priority_in_content_space(); - viewport_for_tile_priority.Intersect(pending_layer_->visible_content_rect()); + viewport_for_tile_priority.Intersect(pending_layer_->visible_layer_rect()); EXPECT_TRUE(pending_layer_->HighResTiling()->AllTilesForTesting().empty()); @@ -1858,7 +1820,7 @@ TEST_F(NoLowResPictureLayerImplTest, // Activate and draw active layer. host_impl_.ActivateSyncTree(); host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text); - active_layer_->draw_properties().visible_content_rect = visible_content_rect; + active_layer_->draw_properties().visible_layer_rect = visible_layer_rect; scoped_ptr<RenderPass> render_pass = RenderPass::Create(); AppendQuadsData data; @@ -1873,10 +1835,7 @@ TEST_F(NoLowResPictureLayerImplTest, } TEST_F(PictureLayerImplTest, HighResTileIsComplete) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); @@ -1906,10 +1865,7 @@ TEST_F(PictureLayerImplTest, HighResTileIsComplete) { } TEST_F(PictureLayerImplTest, HighResTileIsIncomplete) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); @@ -1932,10 +1888,7 @@ TEST_F(PictureLayerImplTest, HighResTileIsIncomplete) { } TEST_F(PictureLayerImplTest, HighResTileIsIncompleteLowResComplete) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); @@ -1962,10 +1915,7 @@ TEST_F(PictureLayerImplTest, HighResTileIsIncompleteLowResComplete) { } TEST_F(PictureLayerImplTest, LowResTileIsIncomplete) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); @@ -2001,10 +1951,7 @@ TEST_F(PictureLayerImplTest, LowResTileIsIncomplete) { TEST_F(PictureLayerImplTest, HighResAndIdealResTileIsCompleteWhenRasterScaleIsNotIdeal) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); @@ -2422,10 +2369,7 @@ TEST_F(PictureLayerImplTest, RecreateInvalidPendingTreeTiles) { } TEST_F(PictureLayerImplTest, SyncTilingAfterGpuRasterizationToggles) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(10, 10); @@ -2451,9 +2395,7 @@ TEST_F(PictureLayerImplTest, SyncTilingAfterGpuRasterizationToggles) { // Make sure that we can still add tiling to the pending layer, // that gets synced to the active layer. - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); EXPECT_TRUE(pending_layer_->tilings()->FindTilingWithScale(1.f)); @@ -2503,11 +2445,8 @@ TEST_F(PictureLayerImplTest, HighResCreatedWhenBoundsShrink) { // Another sanity check. EXPECT_EQ(1.f, pending_layer_->MinimumContentsScale()); - // Since the MinContentsScale is 1, the 0.5 tiling should be replaced by a 1.0 - // tiling. - SetupDrawPropertiesAndUpdateTiles(pending_layer_, 0.5f, 1.f, 1.f, 1.f, 0.f, - false); - + // Since the MinContentsScale is 1, the 0.5 tiling should have been replaced + // by a 1.0 tiling during the UDP in SetupPendingTree. EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings()); PictureLayerTiling* tiling = pending_layer_->tilings()->FindTilingWithScale(1.0f); @@ -2592,11 +2531,12 @@ TEST_F(PictureLayerImplTest, FirstTilingDuringPinch) { // We start with a tiling at scale 1. EXPECT_EQ(1.f, pending_layer_->HighResTiling()->contents_scale()); - // When we scale up by 2.3, we get a new tiling that is a power of 2, in this - // case 4. + // When we page scale up by 2.3, we get a new tiling that is a power of 2, in + // this case 4. host_impl_.PinchGestureBegin(); float high_res_scale = 2.3f; - SetContentsScaleOnBothLayers(high_res_scale, 1.f, 1.f, 1.f, 0.f, false); + SetContentsScaleOnBothLayers(high_res_scale, 1.f, high_res_scale, 1.f, 0.f, + false); EXPECT_EQ(4.f, pending_layer_->HighResTiling()->contents_scale()); } @@ -2900,10 +2840,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForGpuRasterization) { } TEST_F(PictureLayerImplTest, TilingSetRasterQueue) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); host_impl_.SetViewportSize(gfx::Size(500, 500)); @@ -2985,11 +2922,9 @@ TEST_F(PictureLayerImplTest, TilingSetRasterQueue) { EXPECT_EQ(high_res_now_tiles, required_for_activation_count); // No NOW tiles. - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); - pending_layer_->draw_properties().visible_content_rect = + pending_layer_->draw_properties().visible_layer_rect = gfx::Rect(1100, 1100, 500, 500); bool resourceless_software_draw = false; pending_layer_->UpdateTiles(resourceless_software_draw); @@ -3017,11 +2952,9 @@ TEST_F(PictureLayerImplTest, TilingSetRasterQueue) { EXPECT_EQ(16, high_res_tile_count); EXPECT_EQ(high_res_tile_count, static_cast<int>(unique_tiles.size())); - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); - pending_layer_->draw_properties().visible_content_rect = + pending_layer_->draw_properties().visible_layer_rect = gfx::Rect(0, 0, 500, 500); pending_layer_->UpdateTiles(resourceless_software_draw); @@ -3058,10 +2991,7 @@ TEST_F(PictureLayerImplTest, TilingSetRasterQueue) { } TEST_F(PictureLayerImplTest, TilingSetRasterQueueActiveTree) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); host_impl_.SetViewportSize(gfx::Size(500, 500)); @@ -3144,11 +3074,8 @@ TEST_F(PictureLayerImplTest, TilingSetEvictionQueue) { for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) { PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i); for (PictureLayerTiling::CoverageIterator iter( - tiling, - pending_layer_->contents_scale_x(), - pending_layer_->visible_content_rect()); - iter; - ++iter) { + tiling, 1.f, pending_layer_->visible_layer_rect()); + iter; ++iter) { if (mark_required) { number_of_marked_tiles++; iter->set_required_for_activation(true); @@ -3290,7 +3217,7 @@ TEST_F(PictureLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(active_layer_->visible_content_rect()); + gfx::Rect occluded(active_layer_->visible_layer_rect()); impl.AppendQuadsWithOcclusion(active_layer_, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); @@ -3622,10 +3549,7 @@ TEST_F(NoLowResPictureLayerImplTest, NothingRequiredIfActiveMissingTiles) { } TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(400, 400); @@ -3652,7 +3576,7 @@ TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) { viewport, transform, resourceless_software_draw); - active_layer_->draw_properties().visible_content_rect = viewport; + active_layer_->draw_properties().visible_layer_rect = viewport; active_layer_->draw_properties().screen_space_transform = transform; active_layer_->UpdateTiles(resourceless_software_draw); @@ -3664,13 +3588,11 @@ TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) { // Expand viewport and set it as invalid for prioritizing tiles. // Should update viewport and transform, but not update visible rect. - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); resourceless_software_draw = true; viewport = gfx::ScaleToEnclosingRect(viewport, 2); transform.Translate(1.f, 1.f); - active_layer_->draw_properties().visible_content_rect = viewport; + active_layer_->draw_properties().visible_layer_rect = viewport; active_layer_->draw_properties().screen_space_transform = transform; host_impl_.SetExternalDrawConstraints(transform, viewport, @@ -3688,9 +3610,7 @@ TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) { active_layer_->visible_rect_for_tile_priority()); // Keep expanded viewport but mark it valid. Should update tile viewport. - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); resourceless_software_draw = false; host_impl_.SetExternalDrawConstraints(transform, viewport, @@ -3887,21 +3807,21 @@ TEST_F(PictureLayerImplTest, SharedQuadStateContainsMaxTilingScale) { // SharedQuadState should have be of size 1, as we are doing AppenQuad once. EXPECT_EQ(1u, render_pass->shared_quad_state_list.size()); - // The content_to_target_transform should be scaled by the + // The quad_to_target_transform should be scaled by the // MaximumTilingContentsScale on the layer. EXPECT_EQ(scaled_draw_transform.ToString(), render_pass->shared_quad_state_list.front() - ->content_to_target_transform.ToString()); + ->quad_to_target_transform.ToString()); // The content_bounds should be scaled by the // MaximumTilingContentsScale on the layer. - EXPECT_EQ( - gfx::Size(2500u, 5000u).ToString(), - render_pass->shared_quad_state_list.front()->content_bounds.ToString()); - // The visible_content_rect should be scaled by the + EXPECT_EQ(gfx::Size(2500u, 5000u).ToString(), + render_pass->shared_quad_state_list.front() + ->quad_layer_bounds.ToString()); + // The visible_layer_rect should be scaled by the // MaximumTilingContentsScale on the layer. EXPECT_EQ(gfx::Rect(0u, 0u, 2500u, 5000u).ToString(), render_pass->shared_quad_state_list.front() - ->visible_content_rect.ToString()); + ->visible_quad_layer_rect.ToString()); } class PictureLayerImplTestWithDelegatingRenderer : public PictureLayerImplTest { @@ -4018,10 +3938,7 @@ class OcclusionTrackingPictureLayerImplTest : public PictureLayerImplTest { TEST_F(OcclusionTrackingPictureLayerImplTest, OccludedTilesSkippedDuringRasterization) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(102, 102); gfx::Size layer_bounds(1000, 1000); @@ -4048,7 +3965,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, // Some tiles may not be visible (i.e. outside the viewport). The rest are // visible and at least partially unoccluded, verified by the above expect. bool tile_is_visible = - tile->content_rect().Intersects(pending_layer_->visible_content_rect()); + tile->content_rect().Intersects(pending_layer_->visible_layer_rect()); if (tile_is_visible) unoccluded_tile_count++; queue->Pop(); @@ -4059,14 +3976,11 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1)); LayerImpl* layer1 = pending_layer_->children()[0]; layer1->SetBounds(layer_bounds); - layer1->SetContentBounds(layer_bounds); layer1->SetDrawsContent(true); layer1->SetContentsOpaque(true); layer1->SetPosition(occluding_layer_position); - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); @@ -4080,7 +3994,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, EXPECT_FALSE(prioritized_tile.is_occluded()); bool tile_is_visible = - tile->content_rect().Intersects(pending_layer_->visible_content_rect()); + tile->content_rect().Intersects(pending_layer_->visible_layer_rect()); if (tile_is_visible) unoccluded_tile_count++; queue->Pop(); @@ -4090,9 +4004,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, // Full occlusion. layer1->SetPosition(gfx::Point(0, 0)); - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); unoccluded_tile_count = 0; @@ -4105,7 +4017,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, EXPECT_FALSE(prioritized_tile.is_occluded()); bool tile_is_visible = - tile->content_rect().Intersects(pending_layer_->visible_content_rect()); + tile->content_rect().Intersects(pending_layer_->visible_layer_rect()); if (tile_is_visible) unoccluded_tile_count++; queue->Pop(); @@ -4115,10 +4027,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, TEST_F(OcclusionTrackingPictureLayerImplTest, OccludedTilesNotMarkedAsRequired) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(102, 102); gfx::Size layer_bounds(1000, 1000); @@ -4139,12 +4048,9 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, tiling->UpdateAndGetAllPrioritizedTilesForTesting(); occluded_tile_count = 0; - for (PictureLayerTiling::CoverageIterator iter( - tiling, - pending_layer_->contents_scale_x(), - gfx::Rect(layer_bounds)); - iter; - ++iter) { + for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, + gfx::Rect(layer_bounds)); + iter; ++iter) { if (!*iter) continue; const Tile* tile = *iter; @@ -4162,14 +4068,11 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1)); LayerImpl* layer1 = pending_layer_->children()[0]; layer1->SetBounds(layer_bounds); - layer1->SetContentBounds(layer_bounds); layer1->SetDrawsContent(true); layer1->SetContentsOpaque(true); layer1->SetPosition(occluding_layer_position); - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); @@ -4179,12 +4082,9 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, tiling->UpdateAndGetAllPrioritizedTilesForTesting(); occluded_tile_count = 0; - for (PictureLayerTiling::CoverageIterator iter( - tiling, - pending_layer_->contents_scale_x(), - gfx::Rect(layer_bounds)); - iter; - ++iter) { + for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, + gfx::Rect(layer_bounds)); + iter; ++iter) { if (!*iter) continue; const Tile* tile = *iter; @@ -4209,9 +4109,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, // Full occlusion. layer1->SetPosition(gfx::PointF(0, 0)); - time_ticks += base::TimeDelta::FromMilliseconds(200); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) { @@ -4220,12 +4118,9 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, tiling->UpdateAndGetAllPrioritizedTilesForTesting(); occluded_tile_count = 0; - for (PictureLayerTiling::CoverageIterator iter( - tiling, - pending_layer_->contents_scale_x(), - gfx::Rect(layer_bounds)); - iter; - ++iter) { + for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, + gfx::Rect(layer_bounds)); + iter; ++iter) { if (!*iter) continue; const Tile* tile = *iter; @@ -4249,10 +4144,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, } TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(102, 102); gfx::Size layer_bounds(1000, 1000); @@ -4270,7 +4162,6 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) { pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1)); LayerImpl* layer1 = pending_layer_->children()[0]; layer1->SetBounds(layer_bounds); - layer1->SetContentBounds(layer_bounds); layer1->SetDrawsContent(true); layer1->SetContentsOpaque(true); layer1->SetPosition(occluding_layer_position); @@ -4283,9 +4174,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) { pending_layer_->AddTiling(1.0f); pending_layer_->AddTiling(2.0f); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); // UpdateDrawProperties with the occluding layer. bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); @@ -4348,7 +4237,6 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) { pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 2)); LayerImpl* layer1 = pending_layer_->children()[0]; layer1->SetBounds(layer_bounds); - layer1->SetContentBounds(layer_bounds); layer1->SetDrawsContent(true); layer1->SetContentsOpaque(true); layer1->SetPosition(occluding_layer_position); @@ -4360,10 +4248,9 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) { auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting(); - for ( - PictureLayerTiling::CoverageIterator iter( - tiling, active_layer_->contents_scale_x(), gfx::Rect(layer_bounds)); - iter; ++iter) { + for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, + gfx::Rect(layer_bounds)); + iter; ++iter) { if (!*iter) continue; const Tile* tile = *iter; @@ -4385,12 +4272,9 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) { auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting(); - for (PictureLayerTiling::CoverageIterator iter( - tiling, - active_layer_->contents_scale_x(), - gfx::Rect(layer_bounds)); - iter; - ++iter) { + for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, + gfx::Rect(layer_bounds)); + iter; ++iter) { if (!*iter) continue; const Tile* tile = *iter; @@ -4419,10 +4303,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) { TEST_F(OcclusionTrackingPictureLayerImplTest, OccludedTilesConsideredDuringEviction) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(102, 102); gfx::Size layer_bounds(1000, 1000); @@ -4445,7 +4326,6 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 2)); LayerImpl* active_occluding_layer = pending_layer_->children()[0]; active_occluding_layer->SetBounds(layer_bounds); - active_occluding_layer->SetContentBounds(layer_bounds); active_occluding_layer->SetDrawsContent(true); active_occluding_layer->SetContentsOpaque(true); active_occluding_layer->SetPosition(active_occluding_layer_position); @@ -4460,7 +4340,6 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 3)); LayerImpl* pending_occluding_layer = pending_layer_->children()[0]; pending_occluding_layer->SetBounds(layer_bounds); - pending_occluding_layer->SetContentBounds(layer_bounds); pending_occluding_layer->SetDrawsContent(true); pending_occluding_layer->SetContentsOpaque(true); pending_occluding_layer->SetPosition(pending_occluding_layer_position); @@ -4468,9 +4347,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, EXPECT_EQ(2u, pending_layer_->num_tilings()); EXPECT_EQ(2u, active_layer_->num_tilings()); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); // UpdateDrawProperties with the occluding layer. bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); @@ -4515,12 +4392,9 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, tiling->UpdateAndGetAllPrioritizedTilesForTesting(); size_t occluded_tile_count_on_active = 0u; - for (PictureLayerTiling::CoverageIterator iter( - tiling, - pending_layer_->contents_scale_x(), - gfx::Rect(layer_bounds)); - iter; - ++iter) { + for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, + gfx::Rect(layer_bounds)); + iter; ++iter) { Tile* tile = *iter; if (!tile) @@ -4602,47 +4476,20 @@ TEST_F(PictureLayerImplTest, PendingOrActiveTwinLayer) { EXPECT_FALSE(active_layer_->GetPendingOrActiveTwinLayer()); } -TEST_F(PictureLayerImplTest, RecycledTwinLayer) { - gfx::Size tile_size(102, 102); - gfx::Size layer_bounds(1000, 1000); - - scoped_refptr<FakePicturePileImpl> pile = - FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupPendingTree(pile); - EXPECT_FALSE(pending_layer_->GetRecycledTwinLayer()); - - ActivateTree(); - EXPECT_TRUE(active_layer_->GetRecycledTwinLayer()); - EXPECT_EQ(old_pending_layer_, active_layer_->GetRecycledTwinLayer()); - - SetupPendingTree(pile); - EXPECT_FALSE(pending_layer_->GetRecycledTwinLayer()); - EXPECT_FALSE(active_layer_->GetRecycledTwinLayer()); - - ActivateTree(); - EXPECT_TRUE(active_layer_->GetRecycledTwinLayer()); - EXPECT_EQ(old_pending_layer_, active_layer_->GetRecycledTwinLayer()); - - // Make an empty pending tree. - host_impl_.CreatePendingTree(); - host_impl_.pending_tree()->DetachLayerTree(); - EXPECT_FALSE(active_layer_->GetRecycledTwinLayer()); -} - void PictureLayerImplTest::TestQuadsForSolidColor(bool test_for_solid) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); gfx::Rect layer_rect(layer_bounds); FakeContentLayerClient client; - scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> layer = + PictureLayer::Create(layer_settings_, &client); FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&host_client); + TestTaskGraphRunner task_graph_runner; + scoped_ptr<FakeLayerTreeHost> host = + FakeLayerTreeHost::Create(&host_client, &task_graph_runner); host->SetRootLayer(layer); RecordingSource* recording_source = layer->GetRecordingSourceForTesting(); @@ -4693,19 +4540,19 @@ TEST_F(PictureLayerImplTest, DrawNonSolidQuads) { } TEST_F(PictureLayerImplTest, NonSolidToSolidNoTilings) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); gfx::Rect layer_rect(layer_bounds); FakeContentLayerClient client; - scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> layer = + PictureLayer::Create(layer_settings_, &client); FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&host_client); + TestTaskGraphRunner task_graph_runner; + scoped_ptr<FakeLayerTreeHost> host = + FakeLayerTreeHost::Create(&host_client, &task_graph_runner); host->SetRootLayer(layer); RecordingSource* recording_source = layer->GetRecordingSourceForTesting(); @@ -4749,10 +4596,7 @@ TEST_F(PictureLayerImplTest, NonSolidToSolidNoTilings) { } TEST_F(PictureLayerImplTest, ChangeInViewportAllowsTilingUpdates) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); gfx::Size layer_bounds(400, 4000); @@ -4771,7 +4615,7 @@ TEST_F(PictureLayerImplTest, ChangeInViewportAllowsTilingUpdates) { host_impl_.SetRequiresHighResToDraw(); // Update tiles. - pending_layer_->draw_properties().visible_content_rect = viewport; + pending_layer_->draw_properties().visible_layer_rect = viewport; pending_layer_->draw_properties().screen_space_transform = transform; SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, 0.f, false); @@ -4785,7 +4629,7 @@ TEST_F(PictureLayerImplTest, ChangeInViewportAllowsTilingUpdates) { viewport = gfx::Rect(0, 2000, 100, 100); // Update tiles. - pending_layer_->draw_properties().visible_content_rect = viewport; + pending_layer_->draw_properties().visible_layer_rect = viewport; pending_layer_->draw_properties().screen_space_transform = transform; SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, 0.f, false); @@ -4883,10 +4727,7 @@ TEST_F(PictureLayerImplTest, CloneMissingRecordings) { } TEST_F(PictureLayerImplTest, ScrollPastLiveTilesRectAndBack) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(102, 102); gfx::Size layer_bounds(100, 100); @@ -4939,10 +4780,7 @@ TEST_F(PictureLayerImplTest, ScrollPastLiveTilesRectAndBack) { } TEST_F(PictureLayerImplTest, ScrollPropagatesToPending) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(102, 102); gfx::Size layer_bounds(1000, 1000); @@ -4974,10 +4812,7 @@ TEST_F(PictureLayerImplTest, ScrollPropagatesToPending) { } TEST_F(PictureLayerImplTest, UpdateLCDInvalidatesPendingTree) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(102, 102); gfx::Size layer_bounds(100, 100); @@ -5015,7 +4850,51 @@ TEST_F(PictureLayerImplTest, UpdateLCDInvalidatesPendingTree) { prioritized_tiles[tile].raster_source()); } -class TileSizeSettings : public GpuRasterizationEnabledSettings { +TEST_F(PictureLayerImplTest, TilingAllTilesDone) { + gfx::Size tile_size = host_impl_.settings().default_tile_size; + size_t tile_mem = 4 * tile_size.width() * tile_size.height(); + gfx::Size layer_bounds(1000, 1000); + + // Create tiles. + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + SetupPendingTree(pending_pile); + pending_layer_->SetBounds(layer_bounds); + ActivateTree(); + host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting( + active_layer_->HighResTiling()->AllTilesForTesting()); + host_impl_.SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES); + + EXPECT_FALSE(active_layer_->HighResTiling()->all_tiles_done()); + + { + // Set a memory policy that will fit all tiles. + size_t max_tiles = 16; + size_t memory_limit = max_tiles * tile_mem; + ManagedMemoryPolicy policy(memory_limit, + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, + max_tiles); + host_impl_.SetMemoryPolicy(policy); + host_impl_.PrepareTiles(); + + EXPECT_TRUE(active_layer_->HighResTiling()->all_tiles_done()); + } + + { + // Set a memory policy that will cause tile eviction. + size_t max_tiles = 1; + size_t memory_limit = max_tiles * tile_mem; + ManagedMemoryPolicy policy(memory_limit, + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, + max_tiles); + host_impl_.SetMemoryPolicy(policy); + host_impl_.PrepareTiles(); + + EXPECT_FALSE(active_layer_->HighResTiling()->all_tiles_done()); + } +} + +class TileSizeSettings : public PictureLayerImplTestSettings { public: TileSizeSettings() { default_tile_size = gfx::Size(100, 100); @@ -5087,5 +4966,35 @@ TEST_F(TileSizeTest, TileSizes) { EXPECT_EQ(result.height(), 500 + 2); } +TEST_F(NoLowResPictureLayerImplTest, HighResLowResCollision) { + gfx::Size tile_size(400, 400); + gfx::Size layer_bounds(1300, 1900); + + float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; + + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + scoped_refptr<FakePicturePileImpl> active_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + + // Set up the high and low res tilings before pinch zoom. + SetupTrees(pending_pile, active_pile); + ResetTilingsAndRasterScales(); + + float page_scale = 2.f; + SetContentsScaleOnBothLayers(page_scale, 1.0f, page_scale, 1.0f, 0.f, false); + EXPECT_BOTH_EQ(num_tilings(), 1u); + EXPECT_BOTH_EQ(tilings()->tiling_at(0)->contents_scale(), page_scale); + + host_impl_.PinchGestureBegin(); + + // Zoom out to exactly the low res factor so that the previous high res + // would be equal to the current low res (if it were possible to have one). + float zoomed = page_scale / low_res_factor; + SetContentsScaleOnBothLayers(zoomed, 1.0f, zoomed, 1.0f, 0.f, false); + EXPECT_EQ(1u, pending_layer_->num_tilings()); + EXPECT_EQ(zoomed, pending_layer_->tilings()->tiling_at(0)->contents_scale()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/layers/picture_layer_unittest.cc b/chromium/cc/layers/picture_layer_unittest.cc index 37070127a77..b607f2eff99 100644 --- a/chromium/cc/layers/picture_layer_unittest.cc +++ b/chromium/cc/layers/picture_layer_unittest.cc @@ -7,13 +7,12 @@ #include "base/thread_task_runner_handle.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_layer_impl.h" -#include "cc/resources/resource_update_queue.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_picture_layer.h" #include "cc/test/fake_picture_layer_impl.h" #include "cc/test/fake_proxy.h" -#include "cc/test/impl_side_painting_settings.h" -#include "cc/trees/occlusion_tracker.h" +#include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,29 +24,29 @@ class MockContentLayerClient : public ContentLayerClient { void PaintContents(SkCanvas* canvas, const gfx::Rect& clip, PaintingControlSetting picture_control) override {} - void PaintContentsToDisplayList( - DisplayItemList* display_list, + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { NOTIMPLEMENTED(); + return nullptr; } bool FillsBoundsCompletely() const override { return false; }; }; TEST(PictureLayerTest, NoTilesIfEmptyBounds) { MockContentLayerClient client; - scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> layer = + PictureLayer::Create(LayerSettings(), &client); layer->SetBounds(gfx::Size(10, 10)); FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&host_client); + TestTaskGraphRunner task_graph_runner; + scoped_ptr<FakeLayerTreeHost> host = + FakeLayerTreeHost::Create(&host_client, &task_graph_runner); host->SetRootLayer(layer); layer->SetIsDrawable(true); layer->SavePaintProperties(); - - OcclusionTracker<Layer> occlusion(gfx::Rect(0, 0, 1000, 1000)); - scoped_ptr<ResourceUpdateQueue> queue(new ResourceUpdateQueue); - layer->Update(queue.get(), &occlusion); + layer->Update(); EXPECT_EQ(0, host->source_frame_number()); host->CommitComplete(); @@ -63,8 +62,8 @@ TEST(PictureLayerTest, NoTilesIfEmptyBounds) { DebugScopedSetImplThread impl_thread(&proxy); TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(ImplSidePaintingSettings(), &proxy, - &shared_bitmap_manager, nullptr); + FakeLayerTreeHostImpl host_impl(LayerTreeSettings(), &proxy, + &shared_bitmap_manager, &task_graph_runner); host_impl.CreatePendingTree(); scoped_ptr<FakePictureLayerImpl> layer_impl = FakePictureLayerImpl::Create(host_impl.pending_tree(), 1); @@ -79,9 +78,12 @@ TEST(PictureLayerTest, NoTilesIfEmptyBounds) { TEST(PictureLayerTest, SuitableForGpuRasterization) { MockContentLayerClient client; - scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> layer = + PictureLayer::Create(LayerSettings(), &client); FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&host_client); + TestTaskGraphRunner task_graph_runner; + scoped_ptr<FakeLayerTreeHost> host = + FakeLayerTreeHost::Create(&host_client, &task_graph_runner); host->SetRootLayer(layer); RecordingSource* recording_source = layer->GetRecordingSourceForTesting(); @@ -100,10 +102,12 @@ TEST(PictureLayerTest, UseTileGridSize) { settings.default_tile_grid_size = gfx::Size(123, 123); MockContentLayerClient client; - scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> layer = + PictureLayer::Create(LayerSettings(), &client); FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); + TestTaskGraphRunner task_graph_runner; scoped_ptr<FakeLayerTreeHost> host = - FakeLayerTreeHost::Create(&host_client, settings); + FakeLayerTreeHost::Create(&host_client, &task_graph_runner, settings); host->SetRootLayer(layer); // Tile-grid is set according to its setting. @@ -120,19 +124,23 @@ TEST(PictureLayerTest, UseTileGridSize) { TEST(PictureLayerTest, NonMonotonicSourceFrameNumber) { LayerTreeSettings settings; settings.single_thread_proxy_scheduler = false; + settings.use_zero_copy = true; + settings.use_one_copy = false; FakeLayerTreeHostClient host_client1(FakeLayerTreeHostClient::DIRECT_3D); FakeLayerTreeHostClient host_client2(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; MockContentLayerClient client; - scoped_refptr<FakePictureLayer> layer = FakePictureLayer::Create(&client); + scoped_refptr<FakePictureLayer> layer = + FakePictureLayer::Create(LayerSettings(), &client); LayerTreeHost::InitParams params; params.client = &host_client1; - params.shared_bitmap_manager = shared_bitmap_manager.get(); + params.shared_bitmap_manager = &shared_bitmap_manager; params.settings = &settings; + params.task_graph_runner = &task_graph_runner; params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); scoped_ptr<LayerTreeHost> host1 = LayerTreeHost::CreateSingleThreaded(&host_client1, ¶ms); @@ -146,16 +154,16 @@ TEST(PictureLayerTest, NonMonotonicSourceFrameNumber) { // The PictureLayer is put in one LayerTreeHost. host1->SetRootLayer(layer); // Do a main frame, record the picture layers. - EXPECT_EQ(0u, layer->update_count()); + EXPECT_EQ(0, layer->update_count()); layer->SetNeedsDisplay(); host1->Composite(base::TimeTicks::Now()); - EXPECT_EQ(1u, layer->update_count()); + EXPECT_EQ(1, layer->update_count()); EXPECT_EQ(1, host1->source_frame_number()); // The source frame number in |host1| is now higher than host2. layer->SetNeedsDisplay(); host1->Composite(base::TimeTicks::Now()); - EXPECT_EQ(2u, layer->update_count()); + EXPECT_EQ(2, layer->update_count()); EXPECT_EQ(2, host1->source_frame_number()); // Then moved to another LayerTreeHost. @@ -166,7 +174,7 @@ TEST(PictureLayerTest, NonMonotonicSourceFrameNumber) { // non-monotonically. layer->SetNeedsDisplay(); host2->Composite(base::TimeTicks::Now()); - EXPECT_EQ(3u, layer->update_count()); + EXPECT_EQ(3, layer->update_count()); EXPECT_EQ(1, host2->source_frame_number()); } diff --git a/chromium/cc/layers/render_surface.h b/chromium/cc/layers/render_surface.h index 1e3719d023b..29401e29951 100644 --- a/chromium/cc/layers/render_surface.h +++ b/chromium/cc/layers/render_surface.h @@ -19,8 +19,6 @@ namespace cc { class Layer; -template <typename LayerType> -class LayerIterator; class CC_EXPORT RenderSurface { public: @@ -116,8 +114,6 @@ class CC_EXPORT RenderSurface { void ClearLayerLists(); private: - friend class LayerIterator<Layer>; - Layer* owning_layer_; // Uses this surface's space. @@ -144,10 +140,6 @@ class CC_EXPORT RenderSurface { // surface, and that ignores outside occlusion. This can point to itself. RenderSurface* nearest_occlusion_immune_ancestor_; - // For LayerIteratorActions - int target_render_surface_layer_index_history_; - int current_layer_index_history_; - DISALLOW_COPY_AND_ASSIGN(RenderSurface); }; diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc index 2ca1241f719..ebb3016c64d 100644 --- a/chromium/cc/layers/render_surface_impl.cc +++ b/chromium/cc/layers/render_surface_impl.cc @@ -157,9 +157,9 @@ void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass, LayerImpl* mask_layer, AppendQuadsData* append_quads_data, RenderPassId render_pass_id) { - gfx::Rect visible_content_rect = + gfx::Rect visible_layer_rect = occlusion_in_content_space.GetUnoccludedContentRect(content_rect_); - if (visible_content_rect.IsEmpty()) + if (visible_layer_rect.IsEmpty()) return; SharedQuadState* shared_quad_state = @@ -173,11 +173,11 @@ void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass, DebugBorderDrawQuad* debug_border_quad = render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>(); debug_border_quad->SetNew(shared_quad_state, content_rect_, - visible_content_rect, debug_border_color, + visible_layer_rect, debug_border_color, debug_border_width); } - ResourceProvider::ResourceId mask_resource_id = 0; + ResourceId mask_resource_id = 0; gfx::Size mask_texture_size; gfx::Vector2dF mask_uv_scale; if (mask_layer && mask_layer->DrawsContent() && @@ -186,10 +186,9 @@ void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass, gfx::Vector2dF owning_layer_draw_scale = MathUtil::ComputeTransform2dScaleComponents( owning_layer_->draw_transform(), 1.f); - gfx::SizeF unclipped_mask_target_size = gfx::ScaleSize( - owning_layer_->content_bounds(), - owning_layer_draw_scale.x(), - owning_layer_draw_scale.y()); + gfx::SizeF unclipped_mask_target_size = + gfx::ScaleSize(owning_layer_->bounds(), owning_layer_draw_scale.x(), + owning_layer_draw_scale.y()); mask_uv_scale = gfx::Vector2dF( content_rect_.width() / unclipped_mask_target_size.width(), content_rect_.height() / unclipped_mask_target_size.height()); @@ -198,19 +197,12 @@ void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass, DCHECK(owning_layer_->draw_properties().target_space_transform.IsScale2d()); gfx::Vector2dF owning_layer_to_target_scale = owning_layer_->draw_properties().target_space_transform.Scale2d(); - owning_layer_to_target_scale.Scale(owning_layer_->contents_scale_x(), - owning_layer_->contents_scale_y()); RenderPassDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); - quad->SetNew(shared_quad_state, - content_rect_, - visible_content_rect, - render_pass_id, - mask_resource_id, - mask_uv_scale, - mask_texture_size, - owning_layer_->filters(), + quad->SetNew(shared_quad_state, content_rect_, visible_layer_rect, + render_pass_id, mask_resource_id, mask_uv_scale, + mask_texture_size, owning_layer_->filters(), owning_layer_to_target_scale, owning_layer_->background_filters()); } diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h index 2035e28b127..80a4f720b7b 100644 --- a/chromium/cc/layers/render_surface_impl.h +++ b/chromium/cc/layers/render_surface_impl.h @@ -27,7 +27,6 @@ class Occlusion; class RenderPassId; class RenderPassSink; class LayerImpl; -template <typename LayerType> class LayerIterator; struct AppendQuadsData; @@ -192,9 +191,9 @@ class CC_EXPORT RenderSurfaceImpl { // For LayerIteratorActions int target_render_surface_layer_index_history_; - int current_layer_index_history_; + size_t current_layer_index_history_; - friend class LayerIterator<LayerImpl>; + friend class LayerIterator; DISALLOW_COPY_AND_ASSIGN(RenderSurfaceImpl); }; diff --git a/chromium/cc/layers/render_surface_impl_unittest.cc b/chromium/cc/layers/render_surface_impl_unittest.cc index 9934cd652ba..ac406758501 100644 --- a/chromium/cc/layers/render_surface_impl_unittest.cc +++ b/chromium/cc/layers/render_surface_impl_unittest.cc @@ -18,7 +18,6 @@ TEST(RenderSurfaceLayerImplTest, Occlusion) { LayerImpl* owning_layer_impl = impl.AddChildToRoot<LayerImpl>(); owning_layer_impl->SetBounds(layer_size); - owning_layer_impl->SetContentBounds(layer_size); owning_layer_impl->SetDrawsContent(true); owning_layer_impl->SetHasRenderSurface(true); @@ -39,7 +38,7 @@ TEST(RenderSurfaceLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(owning_layer_impl->visible_content_rect()); + gfx::Rect occluded(owning_layer_impl->visible_layer_rect()); impl.AppendSurfaceQuadsWithOcclusion(render_surface_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); diff --git a/chromium/cc/layers/render_surface_unittest.cc b/chromium/cc/layers/render_surface_unittest.cc index 929407c4fe5..5ecf2f7bac8 100644 --- a/chromium/cc/layers/render_surface_unittest.cc +++ b/chromium/cc/layers/render_surface_unittest.cc @@ -13,6 +13,7 @@ #include "cc/test/geometry_test_utils.h" #include "cc/test/mock_occlusion_tracker.h" #include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -38,7 +39,9 @@ TEST(RenderSurfaceTest, VerifySurfaceChangesAreTrackedProperly) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); scoped_ptr<LayerImpl> owning_layer = LayerImpl::Create(host_impl.active_tree(), 1); owning_layer->SetHasRenderSurface(true); @@ -83,7 +86,9 @@ TEST(RenderSurfaceTest, VerifySurfaceChangesAreTrackedProperly) { TEST(RenderSurfaceTest, SanityCheckSurfaceCreatesCorrectSharedQuadState) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); scoped_ptr<LayerImpl> root_layer = LayerImpl::Create(host_impl.active_tree(), 1); @@ -121,11 +126,12 @@ TEST(RenderSurfaceTest, SanityCheckSurfaceCreatesCorrectSharedQuadState) { EXPECT_EQ( 30.0, - shared_quad_state->content_to_target_transform.matrix().getDouble(0, 3)); + shared_quad_state->quad_to_target_transform.matrix().getDouble(0, 3)); EXPECT_EQ( 40.0, - shared_quad_state->content_to_target_transform.matrix().getDouble(1, 3)); - EXPECT_EQ(content_rect, gfx::Rect(shared_quad_state->visible_content_rect)); + shared_quad_state->quad_to_target_transform.matrix().getDouble(1, 3)); + EXPECT_EQ(content_rect, + gfx::Rect(shared_quad_state->visible_quad_layer_rect)); EXPECT_EQ(1.f, shared_quad_state->opacity); EXPECT_EQ(blend_mode, shared_quad_state->blend_mode); } @@ -147,7 +153,9 @@ class TestRenderPassSink : public RenderPassSink { TEST(RenderSurfaceTest, SanityCheckSurfaceCreatesCorrectRenderPass) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); scoped_ptr<LayerImpl> root_layer = LayerImpl::Create(host_impl.active_tree(), 1); diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.cc b/chromium/cc/layers/scrollbar_layer_impl_base.cc index 35e716bdbd8..1d07a8349e4 100644 --- a/chromium/cc/layers/scrollbar_layer_impl_base.cc +++ b/chromium/cc/layers/scrollbar_layer_impl_base.cc @@ -94,16 +94,6 @@ void ScrollbarLayerImplBase::SetScrollLayerAndClipLayerByIds( ScrollbarParametersDidChange(false); } -gfx::Rect ScrollbarLayerImplBase::ScrollbarLayerRectToContentRect( - const gfx::RectF& layer_rect) const { - // Don't intersect with the bounds as in LayerRectToContentRect() because - // layer_rect here might be in coordinates of the containing layer. - gfx::RectF content_rect = gfx::ScaleRect(layer_rect, - contents_scale_x(), - contents_scale_y()); - return gfx::ToEnclosingRect(content_rect); -} - bool ScrollbarLayerImplBase::SetCurrentPos(float current_pos) { if (current_pos_ == current_pos) return false; @@ -249,7 +239,7 @@ gfx::Rect ScrollbarLayerImplBase::ComputeThumbQuadRect() const { thumb_length); } - return ScrollbarLayerRectToContentRect(thumb_rect); + return gfx::ToEnclosingRect(thumb_rect); } void ScrollbarLayerImplBase::ScrollbarParametersDidChange(bool on_resize) { diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.h b/chromium/cc/layers/scrollbar_layer_impl_base.h index d905c88f8c7..da7fa52d1f1 100644 --- a/chromium/cc/layers/scrollbar_layer_impl_base.h +++ b/chromium/cc/layers/scrollbar_layer_impl_base.h @@ -69,8 +69,6 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl { bool is_overlay); ~ScrollbarLayerImplBase() override; - gfx::Rect ScrollbarLayerRectToContentRect(const gfx::RectF& layer_rect) const; - float visible_to_total_length_ratio() const { return visible_to_total_length_ratio_; } diff --git a/chromium/cc/layers/scrollbar_layer_unittest.cc b/chromium/cc/layers/scrollbar_layer_unittest.cc index 97d1c80a992..0042204505e 100644 --- a/chromium/cc/layers/scrollbar_layer_unittest.cc +++ b/chromium/cc/layers/scrollbar_layer_unittest.cc @@ -12,7 +12,6 @@ #include "cc/layers/solid_color_scrollbar_layer.h" #include "cc/layers/solid_color_scrollbar_layer_impl.h" #include "cc/quads/solid_color_draw_quad.h" -#include "cc/resources/resource_update_queue.h" #include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -35,24 +34,24 @@ namespace cc { namespace { -LayerImpl* LayerImplForScrollAreaAndScrollbar(FakeLayerTreeHost* host, +LayerImpl* LayerImplForScrollAreaAndScrollbar(const LayerSettings& settings, + FakeLayerTreeHost* host, scoped_ptr<Scrollbar> scrollbar, bool reverse_order, bool use_solid_color_scrollbar, int thumb_thickness, int track_start) { - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - scoped_refptr<Layer> child1 = Layer::Create(); + scoped_refptr<Layer> layer_tree_root = Layer::Create(settings); + scoped_refptr<Layer> child1 = Layer::Create(settings); scoped_refptr<Layer> child2; if (use_solid_color_scrollbar) { const bool kIsLeftSideVerticalScrollbar = false; - child2 = SolidColorScrollbarLayer::Create(scrollbar->Orientation(), - thumb_thickness, - track_start, - kIsLeftSideVerticalScrollbar, - child1->id()); + child2 = SolidColorScrollbarLayer::Create( + settings, scrollbar->Orientation(), thumb_thickness, track_start, + kIsLeftSideVerticalScrollbar, child1->id()); } else { - child2 = PaintedScrollbarLayer::Create(scrollbar.Pass(), child1->id()); + child2 = + PaintedScrollbarLayer::Create(settings, scrollbar.Pass(), child1->id()); } child2->ToScrollbarLayer()->SetClipLayer(layer_tree_root->id()); layer_tree_root->AddChild(child1); @@ -121,10 +120,13 @@ class ScrollbarLayerTest : public testing::Test { public: ScrollbarLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) { layer_tree_settings_.single_thread_proxy_scheduler = false; + layer_tree_settings_.use_zero_copy = true; + layer_tree_settings_.use_one_copy = false; LayerTreeHost::InitParams params; params.client = &fake_client_; params.settings = &layer_tree_settings_; + params.task_graph_runner = &task_graph_runner_; layer_tree_host_.reset( new FakeResourceTrackingLayerTreeHost(&fake_client_, ¶ms)); @@ -134,16 +136,21 @@ class ScrollbarLayerTest : public testing::Test { EXPECT_FALSE(layer_tree_host_->output_surface_lost()); } + const LayerSettings& layer_settings() { return layer_settings_; } + protected: FakeLayerTreeHostClient fake_client_; + TestTaskGraphRunner task_graph_runner_; LayerTreeSettings layer_tree_settings_; + LayerSettings layer_settings_; scoped_ptr<FakeResourceTrackingLayerTreeHost> layer_tree_host_; }; TEST_F(ScrollbarLayerTest, ResolveScrollLayerPointer) { scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( - layer_tree_host_.get(), scrollbar.Pass(), false, false, 0, 0); + layer_settings(), layer_tree_host_.get(), scrollbar.Pass(), false, false, + 0, 0); LayerImpl* cc_child1 = layer_impl_tree_root->children()[0]; PaintedScrollbarLayerImpl* cc_child2 = @@ -157,7 +164,8 @@ TEST_F(ScrollbarLayerTest, ResolveScrollLayerPointer) { TEST_F(ScrollbarLayerTest, ResolveScrollLayerPointer_ReverseOrder) { scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( - layer_tree_host_.get(), scrollbar.Pass(), true, false, 0, 0); + layer_settings(), layer_tree_host_.get(), scrollbar.Pass(), true, false, + 0, 0); PaintedScrollbarLayerImpl* cc_child1 = static_cast<PaintedScrollbarLayerImpl*>( @@ -172,7 +180,8 @@ TEST_F(ScrollbarLayerTest, ShouldScrollNonOverlayOnMainThread) { // Create and attach a non-overlay scrollbar. scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( - layer_tree_host_.get(), scrollbar.Pass(), false, false, 0, 0); + layer_settings(), layer_tree_host_.get(), scrollbar.Pass(), false, false, + 0, 0); PaintedScrollbarLayerImpl* scrollbar_layer_impl = static_cast<PaintedScrollbarLayerImpl*>( layer_impl_tree_root->children()[1]); @@ -189,7 +198,8 @@ TEST_F(ScrollbarLayerTest, ShouldScrollNonOverlayOnMainThread) { scrollbar.reset(new FakeScrollbar(false, false, true)); layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( - layer_tree_host_.get(), scrollbar.Pass(), false, false, 0, 0); + layer_settings(), layer_tree_host_.get(), scrollbar.Pass(), false, false, + 0, 0); scrollbar_layer_impl = static_cast<PaintedScrollbarLayerImpl*>( layer_impl_tree_root->children()[1]); @@ -203,11 +213,11 @@ TEST_F(ScrollbarLayerTest, ShouldScrollNonOverlayOnMainThread) { TEST_F(ScrollbarLayerTest, ScrollOffsetSynchronization) { scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - scoped_refptr<Layer> scroll_layer = Layer::Create(); - scoped_refptr<Layer> content_layer = Layer::Create(); - scoped_refptr<Layer> scrollbar_layer = - PaintedScrollbarLayer::Create(scrollbar.Pass(), layer_tree_root->id()); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings()); + scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings()); + scoped_refptr<Layer> content_layer = Layer::Create(layer_settings()); + scoped_refptr<Layer> scrollbar_layer = PaintedScrollbarLayer::Create( + layer_settings(), scrollbar.Pass(), layer_tree_root->id()); // Choose bounds to give max_scroll_offset = (30, 50). layer_tree_root->SetBounds(gfx::Size(70, 150)); @@ -272,11 +282,12 @@ TEST_F(ScrollbarLayerTest, ScrollOffsetSynchronization) { } while (false) TEST_F(ScrollbarLayerTest, UpdatePropertiesOfScrollBarWhenThumbRemoved) { - scoped_refptr<Layer> root_clip_layer = Layer::Create(); - scoped_refptr<Layer> root_layer = Layer::Create(); - scoped_refptr<Layer> content_layer = Layer::Create(); + scoped_refptr<Layer> root_clip_layer = Layer::Create(layer_settings()); + scoped_refptr<Layer> root_layer = Layer::Create(layer_settings()); + scoped_refptr<Layer> content_layer = Layer::Create(layer_settings()); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, root_layer->id()); + FakePaintedScrollbarLayer::Create(layer_settings(), false, true, + root_layer->id()); root_layer->SetScrollClipLayerId(root_clip_layer->id()); // Give the root-clip a size that will result in MaxScrollOffset = (80, 0). @@ -313,11 +324,12 @@ TEST_F(ScrollbarLayerTest, UpdatePropertiesOfScrollBarWhenThumbRemoved) { } TEST_F(ScrollbarLayerTest, ThumbRect) { - scoped_refptr<Layer> root_clip_layer = Layer::Create(); - scoped_refptr<Layer> root_layer = Layer::Create(); - scoped_refptr<Layer> content_layer = Layer::Create(); + scoped_refptr<Layer> root_clip_layer = Layer::Create(layer_settings()); + scoped_refptr<Layer> root_layer = Layer::Create(layer_settings()); + scoped_refptr<Layer> content_layer = Layer::Create(layer_settings()); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, root_layer->id()); + FakePaintedScrollbarLayer::Create(layer_settings(), false, true, + root_layer->id()); root_layer->SetScrollClipLayerId(root_clip_layer->id()); // Give the root-clip a size that will result in MaxScrollOffset = (80, 0). @@ -397,8 +409,8 @@ TEST_F(ScrollbarLayerTest, SolidColorDrawQuads) { scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, true)); LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( - layer_tree_host_.get(), scrollbar.Pass(), false, true, kThumbThickness, - kTrackStart); + layer_settings(), layer_tree_host_.get(), scrollbar.Pass(), false, true, + kThumbThickness, kTrackStart); ScrollbarLayerImplBase* scrollbar_layer_impl = static_cast<SolidColorScrollbarLayerImpl*>( layer_impl_tree_root->children()[1]); @@ -419,22 +431,6 @@ TEST_F(ScrollbarLayerTest, SolidColorDrawQuads) { EXPECT_EQ(gfx::Rect(6, 0, 39, 3), quads.front()->rect); } - // Contents scale should scale the draw quad. - scrollbar_layer_impl->draw_properties().contents_scale_x = 2.f; - scrollbar_layer_impl->draw_properties().contents_scale_y = 2.f; - { - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - AppendQuadsData data; - scrollbar_layer_impl->AppendQuads(render_pass.get(), &data); - - const QuadList& quads = render_pass->quad_list; - ASSERT_EQ(1u, quads.size()); - EXPECT_EQ(DrawQuad::SOLID_COLOR, quads.front()->material); - EXPECT_EQ(gfx::Rect(12, 0, 78, 6), quads.front()->rect); - } - scrollbar_layer_impl->draw_properties().contents_scale_x = 1.f; - scrollbar_layer_impl->draw_properties().contents_scale_y = 1.f; - // For solid color scrollbars, position and size should reflect the // current viewport state. scrollbar_layer_impl->SetVisibleToTotalLengthRatio(0.2f); @@ -472,17 +468,15 @@ TEST_F(ScrollbarLayerTest, LayerDrivenSolidColorDrawQuads) { scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, true)); { - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - scoped_refptr<Layer> scroll_layer = Layer::Create(); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings()); + scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings()); scroll_layer->SetScrollClipLayerId(layer_tree_root->id()); - scoped_refptr<Layer> child1 = Layer::Create(); + scoped_refptr<Layer> child1 = Layer::Create(layer_settings()); scoped_refptr<Layer> child2; const bool kIsLeftSideVerticalScrollbar = false; - child2 = SolidColorScrollbarLayer::Create(scrollbar->Orientation(), - kThumbThickness, - kTrackStart, - kIsLeftSideVerticalScrollbar, - child1->id()); + child2 = SolidColorScrollbarLayer::Create( + layer_settings(), scrollbar->Orientation(), kThumbThickness, + kTrackStart, kIsLeftSideVerticalScrollbar, child1->id()); child2->ToScrollbarLayer()->SetScrollLayer(scroll_layer->id()); child2->ToScrollbarLayer()->SetClipLayer(layer_tree_root->id()); scroll_layer->AddChild(child1); @@ -631,12 +625,12 @@ class ScrollbarLayerTestMaxTextureSize : public LayerTreeTest { void SetScrollbarBounds(const gfx::Size& bounds) { bounds_ = bounds; } void BeginTest() override { - scroll_layer_ = Layer::Create(); + scroll_layer_ = Layer::Create(layer_settings()); layer_tree_host()->root_layer()->AddChild(scroll_layer_); scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); - scrollbar_layer_ = - PaintedScrollbarLayer::Create(scrollbar.Pass(), scroll_layer_->id()); + scrollbar_layer_ = PaintedScrollbarLayer::Create( + layer_settings(), scrollbar.Pass(), scroll_layer_->id()); scrollbar_layer_->SetScrollLayer(scroll_layer_->id()); scrollbar_layer_->SetLayerTreeHost(layer_tree_host()); scrollbar_layer_->SetBounds(bounds_); @@ -675,7 +669,7 @@ TEST_F(ScrollbarLayerTestMaxTextureSize, DirectRenderer) { int max_size = 0; context->getIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); SetScrollbarBounds(gfx::Size(max_size + 100, max_size + 100)); - RunTest(true, false, true); + RunTest(true, false); } TEST_F(ScrollbarLayerTestMaxTextureSize, DelegatingRenderer) { @@ -684,7 +678,7 @@ TEST_F(ScrollbarLayerTestMaxTextureSize, DelegatingRenderer) { int max_size = 0; context->getIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); SetScrollbarBounds(gfx::Size(max_size + 100, max_size + 100)); - RunTest(true, true, true); + RunTest(true, true); } class ScrollbarLayerTestResourceCreationAndRelease : public ScrollbarLayerTest { @@ -695,22 +689,19 @@ class ScrollbarLayerTestResourceCreationAndRelease : public ScrollbarLayerTest { int expected_deleted, bool use_solid_color_scrollbar) { scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, false)); - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - scoped_refptr<Layer> content_layer = Layer::Create(); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings()); + scoped_refptr<Layer> content_layer = Layer::Create(layer_settings()); scoped_refptr<Layer> scrollbar_layer; if (use_solid_color_scrollbar) { const int kThumbThickness = 3; const int kTrackStart = 0; const bool kIsLeftSideVerticalScrollbar = false; - scrollbar_layer = - SolidColorScrollbarLayer::Create(scrollbar->Orientation(), - kThumbThickness, - kTrackStart, - kIsLeftSideVerticalScrollbar, - layer_tree_root->id()); + scrollbar_layer = SolidColorScrollbarLayer::Create( + layer_settings(), scrollbar->Orientation(), kThumbThickness, + kTrackStart, kIsLeftSideVerticalScrollbar, layer_tree_root->id()); } else { - scrollbar_layer = PaintedScrollbarLayer::Create(scrollbar.Pass(), - layer_tree_root->id()); + scrollbar_layer = PaintedScrollbarLayer::Create( + layer_settings(), scrollbar.Pass(), layer_tree_root->id()); } layer_tree_root->AddChild(content_layer); layer_tree_root->AddChild(scrollbar_layer); @@ -722,8 +713,7 @@ class ScrollbarLayerTestResourceCreationAndRelease : public ScrollbarLayerTest { layer_tree_root->SetScrollOffset(gfx::ScrollOffset(10, 20)); layer_tree_root->SetBounds(gfx::Size(100, 200)); content_layer->SetBounds(gfx::Size(100, 200)); - scrollbar_layer->draw_properties().content_bounds = gfx::Size(100, 200); - scrollbar_layer->draw_properties().visible_content_rect = + scrollbar_layer->draw_properties().visible_layer_rect = gfx::Rect(0, 0, 100, 200); scrollbar_layer->CreateRenderSurface(); scrollbar_layer->draw_properties().render_target = scrollbar_layer.get(); @@ -731,13 +721,9 @@ class ScrollbarLayerTestResourceCreationAndRelease : public ScrollbarLayerTest { testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get()); - ResourceUpdateQueue queue; - gfx::Rect screen_space_clip_rect; - OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); - scrollbar_layer->SavePaintProperties(); for (int update_counter = 0; update_counter < num_updates; update_counter++) - scrollbar_layer->Update(&queue, &occlusion_tracker); + scrollbar_layer->Update(); // A non-solid-color scrollbar should have requested two textures. EXPECT_EQ(expected_resources, layer_tree_host_->UIResourceCount()); @@ -773,10 +759,11 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { gfx::Point scrollbar_location(0, 185); - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - scoped_refptr<Layer> content_layer = Layer::Create(); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings()); + scoped_refptr<Layer> content_layer = Layer::Create(layer_settings()); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, layer_tree_root->id()); + FakePaintedScrollbarLayer::Create(layer_settings(), false, true, + layer_tree_root->id()); layer_tree_root->AddChild(content_layer); layer_tree_root->AddChild(scrollbar_layer); @@ -789,8 +776,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { layer_tree_root->SetBounds(gfx::Size(100, 200)); content_layer->SetBounds(gfx::Size(100, 200)); - scrollbar_layer->draw_properties().content_bounds = gfx::Size(100, 200); - scrollbar_layer->draw_properties().visible_content_rect = + scrollbar_layer->draw_properties().visible_layer_rect = gfx::Rect(0, 0, 100, 200); scrollbar_layer->CreateRenderSurface(); @@ -799,17 +785,14 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get()); - ResourceUpdateQueue queue; - gfx::Rect screen_space_clip_rect; size_t resource_count; int expected_created, expected_deleted; - OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); scrollbar_layer->SavePaintProperties(); resource_count = 2; expected_created = 2; expected_deleted = 0; - EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); + EXPECT_TRUE(scrollbar_layer->Update()); EXPECT_NE(0, scrollbar_layer->track_resource_id()); EXPECT_NE(0, scrollbar_layer->thumb_resource_id()); EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); @@ -820,7 +803,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { expected_created = 2; expected_deleted = 2; scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0)); - EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); + EXPECT_TRUE(scrollbar_layer->Update()); EXPECT_EQ(0, scrollbar_layer->track_resource_id()); EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); @@ -831,7 +814,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { expected_created = 2; expected_deleted = 2; scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0)); - EXPECT_FALSE(scrollbar_layer->Update(&queue, &occlusion_tracker)); + EXPECT_FALSE(scrollbar_layer->Update()); EXPECT_EQ(0, scrollbar_layer->track_resource_id()); EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); @@ -842,7 +825,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { expected_created = 4; expected_deleted = 2; scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); - EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); + EXPECT_TRUE(scrollbar_layer->Update()); EXPECT_NE(0, scrollbar_layer->track_resource_id()); EXPECT_NE(0, scrollbar_layer->thumb_resource_id()); EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); @@ -853,7 +836,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { expected_created = 5; expected_deleted = 4; scrollbar_layer->fake_scrollbar()->set_has_thumb(false); - EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); + EXPECT_TRUE(scrollbar_layer->Update()); EXPECT_NE(0, scrollbar_layer->track_resource_id()); EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); @@ -864,7 +847,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { expected_created = 5; expected_deleted = 5; scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0)); - EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); + EXPECT_TRUE(scrollbar_layer->Update()); EXPECT_EQ(0, scrollbar_layer->track_resource_id()); EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); @@ -876,7 +859,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { expected_deleted = 5; scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); scrollbar_layer->fake_scrollbar()->set_has_thumb(true); - EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); + EXPECT_TRUE(scrollbar_layer->Update()); EXPECT_NE(0, scrollbar_layer->track_resource_id()); EXPECT_NE(0, scrollbar_layer->thumb_resource_id()); @@ -886,7 +869,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); scrollbar_layer->fake_scrollbar()->set_has_thumb(false); scrollbar_layer->SetBounds(gfx::Size(90, 15)); - EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); + EXPECT_TRUE(scrollbar_layer->Update()); EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); @@ -895,7 +878,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { layer_tree_host_->ui_resource_size(scrollbar_layer->track_resource_id())); scrollbar_layer->ResetNeedsDisplayForTesting(); - EXPECT_FALSE(scrollbar_layer->Update(&queue, &occlusion_tracker)); + EXPECT_FALSE(scrollbar_layer->Update()); EXPECT_NE(0, scrollbar_layer->track_resource_id()); EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); @@ -910,10 +893,11 @@ class ScaledScrollbarLayerTestResourceCreation : public ScrollbarLayerTest { public: void TestResourceUpload(const float test_scale) { gfx::Point scrollbar_location(0, 185); - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - scoped_refptr<Layer> content_layer = Layer::Create(); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings()); + scoped_refptr<Layer> content_layer = Layer::Create(layer_settings()); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, layer_tree_root->id()); + FakePaintedScrollbarLayer::Create(layer_settings(), false, true, + layer_tree_root->id()); layer_tree_root->AddChild(content_layer); layer_tree_root->AddChild(scrollbar_layer); @@ -925,30 +909,18 @@ class ScaledScrollbarLayerTestResourceCreation : public ScrollbarLayerTest { scrollbar_layer->SetPosition(scrollbar_location); layer_tree_root->SetBounds(gfx::Size(100, 200)); content_layer->SetBounds(gfx::Size(100, 200)); - gfx::SizeF scaled_size = - gfx::ScaleSize(scrollbar_layer->bounds(), test_scale, test_scale); - gfx::PointF scaled_location = - gfx::ScalePoint(scrollbar_layer->position(), test_scale, test_scale); - scrollbar_layer->draw_properties().content_bounds = - gfx::Size(scaled_size.width(), scaled_size.height()); - scrollbar_layer->draw_properties().contents_scale_x = test_scale; - scrollbar_layer->draw_properties().contents_scale_y = test_scale; - scrollbar_layer->draw_properties().visible_content_rect = - gfx::Rect(scaled_location.x(), - scaled_location.y(), - scaled_size.width(), - scaled_size.height()); + scrollbar_layer->draw_properties().visible_layer_rect = + gfx::Rect(scrollbar_location, scrollbar_layer->bounds()); scrollbar_layer->CreateRenderSurface(); scrollbar_layer->draw_properties().render_target = scrollbar_layer.get(); testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get()); - ResourceUpdateQueue queue; - gfx::Rect screen_space_clip_rect; - OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); + layer_tree_host_->SetDeviceScaleFactor(test_scale); + scrollbar_layer->SavePaintProperties(); - scrollbar_layer->Update(&queue, &occlusion_tracker); + scrollbar_layer->Update(); // Verify that we have not generated any content uploads that are larger // than their destination textures. @@ -986,11 +958,10 @@ class ScaledScrollbarLayerTestScaledRasterization : public ScrollbarLayerTest { void TestScale(const gfx::Rect scrollbar_rect, const float test_scale) { bool paint_during_update = true; bool has_thumb = false; - scoped_refptr<Layer> layer_tree_root = Layer::Create(); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings()); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(paint_during_update, - has_thumb, - layer_tree_root->id()); + FakePaintedScrollbarLayer::Create(layer_settings(), paint_during_update, + has_thumb, layer_tree_root->id()); layer_tree_root->AddChild(scrollbar_layer); @@ -1000,26 +971,14 @@ class ScaledScrollbarLayerTestScaledRasterization : public ScrollbarLayerTest { scrollbar_layer->SetPosition(scrollbar_rect.origin()); scrollbar_layer->fake_scrollbar()->set_location(scrollbar_rect.origin()); scrollbar_layer->fake_scrollbar()->set_track_rect(scrollbar_rect); - gfx::SizeF scaled_size = - gfx::ScaleSize(scrollbar_layer->bounds(), test_scale, test_scale); - gfx::PointF scaled_location = - gfx::ScalePoint(scrollbar_layer->position(), test_scale, test_scale); - scrollbar_layer->draw_properties().content_bounds = - gfx::Size(scaled_size.width(), scaled_size.height()); - scrollbar_layer->draw_properties().contents_scale_x = test_scale; - scrollbar_layer->draw_properties().contents_scale_y = test_scale; - scrollbar_layer->draw_properties().visible_content_rect = - gfx::Rect(scaled_location.x(), - scaled_location.y(), - scaled_size.width(), - scaled_size.height()); - - ResourceUpdateQueue queue; + scrollbar_layer->draw_properties().visible_layer_rect = scrollbar_rect; + + layer_tree_host_->SetDeviceScaleFactor(test_scale); + gfx::Rect screen_space_clip_rect; - OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); scrollbar_layer->SavePaintProperties(); - scrollbar_layer->Update(&queue, &occlusion_tracker); + scrollbar_layer->Update(); UIResourceBitmap* bitmap = layer_tree_host_->ui_resource_bitmap( scrollbar_layer->track_resource_id()); diff --git a/chromium/cc/layers/solid_color_layer.cc b/chromium/cc/layers/solid_color_layer.cc index 25e0ab85fbd..2fbaca167ff 100644 --- a/chromium/cc/layers/solid_color_layer.cc +++ b/chromium/cc/layers/solid_color_layer.cc @@ -13,12 +13,14 @@ scoped_ptr<LayerImpl> SolidColorLayer::CreateLayerImpl( return SolidColorLayerImpl::Create(tree_impl, id()); } -scoped_refptr<SolidColorLayer> SolidColorLayer::Create() { - return make_scoped_refptr(new SolidColorLayer()); +scoped_refptr<SolidColorLayer> SolidColorLayer::Create( + const LayerSettings& settings) { + return make_scoped_refptr(new SolidColorLayer(settings)); } -SolidColorLayer::SolidColorLayer() - : Layer() {} +SolidColorLayer::SolidColorLayer(const LayerSettings& settings) + : Layer(settings) { +} SolidColorLayer::~SolidColorLayer() {} diff --git a/chromium/cc/layers/solid_color_layer.h b/chromium/cc/layers/solid_color_layer.h index 8dc986075a5..b544f66311a 100644 --- a/chromium/cc/layers/solid_color_layer.h +++ b/chromium/cc/layers/solid_color_layer.h @@ -15,14 +15,14 @@ namespace cc { // SetBackgroundColor() on the base class. class CC_EXPORT SolidColorLayer : public Layer { public: - static scoped_refptr<SolidColorLayer> Create(); + static scoped_refptr<SolidColorLayer> Create(const LayerSettings& settings); scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void SetBackgroundColor(SkColor color) override; protected: - SolidColorLayer(); + explicit SolidColorLayer(const LayerSettings& settings); private: ~SolidColorLayer() override; diff --git a/chromium/cc/layers/solid_color_layer_impl.cc b/chromium/cc/layers/solid_color_layer_impl.cc index 276249744e8..76cd3fc4229 100644 --- a/chromium/cc/layers/solid_color_layer_impl.cc +++ b/chromium/cc/layers/solid_color_layer_impl.cc @@ -29,29 +29,29 @@ scoped_ptr<LayerImpl> SolidColorLayerImpl::CreateLayerImpl( void SolidColorLayerImpl::AppendSolidQuads( RenderPass* render_pass, - const Occlusion& occlusion_in_content_space, + const Occlusion& occlusion_in_layer_space, SharedQuadState* shared_quad_state, - const gfx::Rect& visible_content_rect, + const gfx::Rect& visible_layer_rect, SkColor color, AppendQuadsData* append_quads_data) { // We create a series of smaller quads instead of just one large one so that // the culler can reduce the total pixels drawn. - int right = visible_content_rect.right(); - int bottom = visible_content_rect.bottom(); - for (int x = visible_content_rect.x(); x < visible_content_rect.right(); + int right = visible_layer_rect.right(); + int bottom = visible_layer_rect.bottom(); + for (int x = visible_layer_rect.x(); x < visible_layer_rect.right(); x += kSolidQuadTileSize) { - for (int y = visible_content_rect.y(); y < visible_content_rect.bottom(); + for (int y = visible_layer_rect.y(); y < visible_layer_rect.bottom(); y += kSolidQuadTileSize) { gfx::Rect quad_rect(x, y, std::min(right - x, kSolidQuadTileSize), std::min(bottom - y, kSolidQuadTileSize)); gfx::Rect visible_quad_rect = - occlusion_in_content_space.GetUnoccludedContentRect(quad_rect); + occlusion_in_layer_space.GetUnoccludedContentRect(quad_rect); if (visible_quad_rect.IsEmpty()) continue; - append_quads_data->visible_content_area += + append_quads_data->visible_layer_area += visible_quad_rect.width() * visible_quad_rect.height(); SolidColorDrawQuad* quad = @@ -69,14 +69,14 @@ void SolidColorLayerImpl::AppendQuads( render_pass->CreateAndAppendSharedQuadState(); PopulateSharedQuadState(shared_quad_state); - AppendDebugBorderQuad( - render_pass, content_bounds(), shared_quad_state, append_quads_data); + AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state, + append_quads_data); // TODO(hendrikw): We need to pass the visible content rect rather than - // |content_bounds()| here. + // |bounds()| here. AppendSolidQuads(render_pass, draw_properties().occlusion_in_content_space, - shared_quad_state, gfx::Rect(content_bounds()), - background_color(), append_quads_data); + shared_quad_state, gfx::Rect(bounds()), background_color(), + append_quads_data); } const char* SolidColorLayerImpl::LayerTypeAsString() const { diff --git a/chromium/cc/layers/solid_color_layer_impl.h b/chromium/cc/layers/solid_color_layer_impl.h index 213e3f13a72..2068ac5db3f 100644 --- a/chromium/cc/layers/solid_color_layer_impl.h +++ b/chromium/cc/layers/solid_color_layer_impl.h @@ -19,9 +19,9 @@ class CC_EXPORT SolidColorLayerImpl : public LayerImpl { } static void AppendSolidQuads(RenderPass* render_pass, - const Occlusion& occlusion_in_content_space, + const Occlusion& occlusion_in_layer_space, SharedQuadState* shared_quad_state, - const gfx::Rect& visible_content_rect, + const gfx::Rect& visible_layer_rect, SkColor color, AppendQuadsData* append_quads_data); diff --git a/chromium/cc/layers/solid_color_layer_impl_unittest.cc b/chromium/cc/layers/solid_color_layer_impl_unittest.cc index f35b82a848d..59ef6ba70fa 100644 --- a/chromium/cc/layers/solid_color_layer_impl_unittest.cc +++ b/chromium/cc/layers/solid_color_layer_impl_unittest.cc @@ -12,7 +12,7 @@ #include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/layer_test_common.h" -#include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -24,16 +24,15 @@ TEST(SolidColorLayerImplTest, VerifyTilingCompleteAndNoOverlap) { scoped_ptr<RenderPass> render_pass = RenderPass::Create(); gfx::Size layer_size = gfx::Size(800, 600); - gfx::Rect visible_content_rect = gfx::Rect(layer_size); + gfx::Rect visible_layer_rect = gfx::Rect(layer_size); FakeImplProxy proxy; - TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, nullptr, &task_graph_runner); scoped_ptr<SolidColorLayerImpl> layer = SolidColorLayerImpl::Create(host_impl.active_tree(), 1); - layer->draw_properties().visible_content_rect = visible_content_rect; + layer->draw_properties().visible_layer_rect = visible_layer_rect; layer->SetBounds(layer_size); - layer->SetContentBounds(layer_size); layer->SetHasRenderSurface(true); layer->draw_properties().render_target = layer.get(); @@ -41,7 +40,7 @@ TEST(SolidColorLayerImplTest, VerifyTilingCompleteAndNoOverlap) { layer->AppendQuads(render_pass.get(), &data); LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list, - visible_content_rect); + visible_layer_rect); } TEST(SolidColorLayerImplTest, VerifyCorrectBackgroundColorInQuad) { @@ -50,16 +49,15 @@ TEST(SolidColorLayerImplTest, VerifyCorrectBackgroundColorInQuad) { scoped_ptr<RenderPass> render_pass = RenderPass::Create(); gfx::Size layer_size = gfx::Size(100, 100); - gfx::Rect visible_content_rect = gfx::Rect(layer_size); + gfx::Rect visible_layer_rect = gfx::Rect(layer_size); FakeImplProxy proxy; - TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, nullptr, &task_graph_runner); scoped_ptr<SolidColorLayerImpl> layer = SolidColorLayerImpl::Create(host_impl.active_tree(), 1); - layer->draw_properties().visible_content_rect = visible_content_rect; + layer->draw_properties().visible_layer_rect = visible_layer_rect; layer->SetBounds(layer_size); - layer->SetContentBounds(layer_size); layer->SetBackgroundColor(test_color); layer->SetHasRenderSurface(true); layer->draw_properties().render_target = layer.get(); @@ -79,16 +77,15 @@ TEST(SolidColorLayerImplTest, VerifyCorrectOpacityInQuad) { scoped_ptr<RenderPass> render_pass = RenderPass::Create(); gfx::Size layer_size = gfx::Size(100, 100); - gfx::Rect visible_content_rect = gfx::Rect(layer_size); + gfx::Rect visible_layer_rect = gfx::Rect(layer_size); FakeImplProxy proxy; - TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, nullptr, &task_graph_runner); scoped_ptr<SolidColorLayerImpl> layer = SolidColorLayerImpl::Create(host_impl.active_tree(), 1); - layer->draw_properties().visible_content_rect = visible_content_rect; + layer->draw_properties().visible_layer_rect = visible_layer_rect; layer->SetBounds(layer_size); - layer->SetContentBounds(layer_size); layer->draw_properties().opacity = opacity; layer->SetHasRenderSurface(true); layer->draw_properties().render_target = layer.get(); @@ -99,7 +96,7 @@ TEST(SolidColorLayerImplTest, VerifyCorrectOpacityInQuad) { ASSERT_EQ(render_pass->quad_list.size(), 1U); EXPECT_EQ(opacity, SolidColorDrawQuad::MaterialCast(render_pass->quad_list.front()) - ->opacity()); + ->shared_quad_state->opacity); } TEST(SolidColorLayerImplTest, VerifyCorrectBlendModeInQuad) { @@ -108,15 +105,14 @@ TEST(SolidColorLayerImplTest, VerifyCorrectBlendModeInQuad) { scoped_ptr<RenderPass> render_pass = RenderPass::Create(); gfx::Size layer_size = gfx::Size(100, 100); - gfx::Rect visible_content_rect = gfx::Rect(layer_size); + gfx::Rect visible_layer_rect = gfx::Rect(layer_size); FakeImplProxy proxy; - TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, nullptr, &task_graph_runner); scoped_ptr<SolidColorLayerImpl> layer = SolidColorLayerImpl::Create(host_impl.active_tree(), 1); layer->SetBounds(layer_size); - layer->SetContentBounds(layer_size); layer->draw_properties().blend_mode = blend_mode; AppendQuadsData data; @@ -129,17 +125,22 @@ TEST(SolidColorLayerImplTest, VerifyCorrectBlendModeInQuad) { TEST(SolidColorLayerImplTest, VerifyOpaqueRect) { gfx::Size layer_size = gfx::Size(100, 100); - gfx::Rect visible_content_rect = gfx::Rect(layer_size); + gfx::Rect visible_layer_rect = gfx::Rect(layer_size); - scoped_refptr<SolidColorLayer> layer = SolidColorLayer::Create(); + LayerSettings layer_settings; + + scoped_refptr<SolidColorLayer> layer = + SolidColorLayer::Create(layer_settings); layer->SetBounds(layer_size); layer->SetForceRenderSurface(true); - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings); root->AddChild(layer); FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client); + TestTaskGraphRunner task_graph_runner; + scoped_ptr<FakeLayerTreeHost> host = + FakeLayerTreeHost::Create(&client, &task_graph_runner); host->SetRootLayer(root); RenderSurfaceLayerList render_surface_layer_list; @@ -169,7 +170,7 @@ TEST(SolidColorLayerImplTest, VerifyOpaqueRect) { layer_impl->AppendQuads(render_pass.get(), &data); ASSERT_EQ(render_pass->quad_list.size(), 1U); - EXPECT_EQ(visible_content_rect.ToString(), + EXPECT_EQ(visible_layer_rect.ToString(), render_pass->quad_list.front()->opaque_rect.ToString()); } @@ -210,7 +211,6 @@ TEST(SolidColorLayerImplTest, Occlusion) { impl.AddChildToRoot<SolidColorLayerImpl>(); solid_color_layer_impl->SetBackgroundColor(SkColorSetARGB(255, 10, 20, 30)); solid_color_layer_impl->SetBounds(layer_size); - solid_color_layer_impl->SetContentBounds(layer_size); solid_color_layer_impl->SetDrawsContent(true); impl.CalcDrawProps(viewport_size); @@ -227,7 +227,7 @@ TEST(SolidColorLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(solid_color_layer_impl->visible_content_rect()); + gfx::Rect occluded(solid_color_layer_impl->visible_layer_rect()); impl.AppendQuadsWithOcclusion(solid_color_layer_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); diff --git a/chromium/cc/layers/solid_color_scrollbar_layer.cc b/chromium/cc/layers/solid_color_scrollbar_layer.cc index b2c1ed495f0..4ed55cacd3a 100644 --- a/chromium/cc/layers/solid_color_scrollbar_layer.cc +++ b/chromium/cc/layers/solid_color_scrollbar_layer.cc @@ -23,31 +23,32 @@ scoped_ptr<LayerImpl> SolidColorScrollbarLayer::CreateLayerImpl( } scoped_refptr<SolidColorScrollbarLayer> SolidColorScrollbarLayer::Create( + const LayerSettings& settings, ScrollbarOrientation orientation, int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar, int scroll_layer_id) { - return make_scoped_refptr( - new SolidColorScrollbarLayer(orientation, - thumb_thickness, - track_start, - is_left_side_vertical_scrollbar, - scroll_layer_id)); + return make_scoped_refptr(new SolidColorScrollbarLayer( + settings, orientation, thumb_thickness, track_start, + is_left_side_vertical_scrollbar, scroll_layer_id)); } SolidColorScrollbarLayer::SolidColorScrollbarLayer( + const LayerSettings& settings, ScrollbarOrientation orientation, int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar, int scroll_layer_id) - : scroll_layer_id_(Layer::INVALID_ID), + : Layer(settings), + scroll_layer_id_(Layer::INVALID_ID), clip_layer_id_(scroll_layer_id), orientation_(orientation), thumb_thickness_(thumb_thickness), track_start_(track_start), - is_left_side_vertical_scrollbar_(is_left_side_vertical_scrollbar) {} + is_left_side_vertical_scrollbar_(is_left_side_vertical_scrollbar) { +} SolidColorScrollbarLayer::~SolidColorScrollbarLayer() {} diff --git a/chromium/cc/layers/solid_color_scrollbar_layer.h b/chromium/cc/layers/solid_color_scrollbar_layer.h index fc6306e47b3..6097014ca22 100644 --- a/chromium/cc/layers/solid_color_scrollbar_layer.h +++ b/chromium/cc/layers/solid_color_scrollbar_layer.h @@ -17,6 +17,7 @@ class CC_EXPORT SolidColorScrollbarLayer : public ScrollbarLayerInterface, scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; static scoped_refptr<SolidColorScrollbarLayer> Create( + const LayerSettings& settings, ScrollbarOrientation orientation, int thumb_thickness, int track_start, @@ -40,7 +41,8 @@ class CC_EXPORT SolidColorScrollbarLayer : public ScrollbarLayerInterface, ScrollbarOrientation orientation() const override; protected: - SolidColorScrollbarLayer(ScrollbarOrientation orientation, + SolidColorScrollbarLayer(const LayerSettings& settings, + ScrollbarOrientation orientation, int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar, diff --git a/chromium/cc/layers/solid_color_scrollbar_layer_impl.cc b/chromium/cc/layers/solid_color_scrollbar_layer_impl.cc index fa1849e86e8..0b78de7f8c7 100644 --- a/chromium/cc/layers/solid_color_scrollbar_layer_impl.cc +++ b/chromium/cc/layers/solid_color_scrollbar_layer_impl.cc @@ -100,8 +100,8 @@ void SolidColorScrollbarLayerImpl::AppendQuads( render_pass->CreateAndAppendSharedQuadState(); PopulateSharedQuadState(shared_quad_state); - AppendDebugBorderQuad( - render_pass, content_bounds(), shared_quad_state, append_quads_data); + AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state, + append_quads_data); gfx::Rect thumb_quad_rect(ComputeThumbQuadRect()); gfx::Rect visible_quad_rect = diff --git a/chromium/cc/layers/solid_color_scrollbar_layer_impl_unittest.cc b/chromium/cc/layers/solid_color_scrollbar_layer_impl_unittest.cc index b27c84bfae7..c758497c9ce 100644 --- a/chromium/cc/layers/solid_color_scrollbar_layer_impl_unittest.cc +++ b/chromium/cc/layers/solid_color_scrollbar_layer_impl_unittest.cc @@ -30,7 +30,6 @@ TEST(SolidColorScrollbarLayerImplTest, Occlusion) { is_left_side_vertical_scrollbar, is_overlay); scrollbar_layer_impl->SetBounds(layer_size); - scrollbar_layer_impl->SetContentBounds(layer_size); scrollbar_layer_impl->SetDrawsContent(true); scrollbar_layer_impl->SetCurrentPos(100.f / 4); scrollbar_layer_impl->SetMaximum(100); @@ -55,7 +54,7 @@ TEST(SolidColorScrollbarLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(scrollbar_layer_impl->visible_content_rect()); + gfx::Rect occluded(scrollbar_layer_impl->visible_layer_rect()); impl.AppendQuadsWithOcclusion(scrollbar_layer_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); diff --git a/chromium/cc/layers/surface_layer.cc b/chromium/cc/layers/surface_layer.cc index 67a263229de..e1862303caa 100644 --- a/chromium/cc/layers/surface_layer.cc +++ b/chromium/cc/layers/surface_layer.cc @@ -36,15 +36,17 @@ class SatisfySwapPromise : public SwapPromise { }; scoped_refptr<SurfaceLayer> SurfaceLayer::Create( + const LayerSettings& settings, const SatisfyCallback& satisfy_callback, const RequireCallback& require_callback) { return make_scoped_refptr( - new SurfaceLayer(satisfy_callback, require_callback)); + new SurfaceLayer(settings, satisfy_callback, require_callback)); } -SurfaceLayer::SurfaceLayer(const SatisfyCallback& satisfy_callback, +SurfaceLayer::SurfaceLayer(const LayerSettings& settings, + const SatisfyCallback& satisfy_callback, const RequireCallback& require_callback) - : Layer(), + : Layer(settings), surface_scale_(1.f), satisfy_callback_(satisfy_callback), require_callback_(require_callback) { @@ -92,15 +94,8 @@ void SurfaceLayer::PushPropertiesTo(LayerImpl* layer) { SurfaceLayerImpl* layer_impl = static_cast<SurfaceLayerImpl*>(layer); layer_impl->SetSurfaceId(surface_id_); -} - -void SurfaceLayer::CalculateContentsScale(float ideal_contents_scale, - float* contents_scale_x, - float* contents_scale_y, - gfx::Size* content_bounds) { - *content_bounds = surface_size_; - *contents_scale_x = surface_scale_; - *contents_scale_y = surface_scale_; + layer_impl->SetSurfaceSize(surface_size_); + layer_impl->SetSurfaceScale(surface_scale_); } void SurfaceLayer::CreateNewDestroySequence() { diff --git a/chromium/cc/layers/surface_layer.h b/chromium/cc/layers/surface_layer.h index 381369f5c61..e62d6a2c9dc 100644 --- a/chromium/cc/layers/surface_layer.h +++ b/chromium/cc/layers/surface_layer.h @@ -27,6 +27,7 @@ class CC_EXPORT SurfaceLayer : public Layer { using RequireCallback = base::Callback<void(SurfaceId, SurfaceSequence)>; static scoped_refptr<SurfaceLayer> Create( + const LayerSettings& settings, const SatisfyCallback& satisfy_callback, const RequireCallback& require_callback); @@ -36,13 +37,10 @@ class CC_EXPORT SurfaceLayer : public Layer { scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void SetLayerTreeHost(LayerTreeHost* host) override; void PushPropertiesTo(LayerImpl* layer) override; - void CalculateContentsScale(float ideal_contents_scale, - float* contents_scale_x, - float* contents_scale_y, - gfx::Size* content_bounds) override; protected: - SurfaceLayer(const SatisfyCallback& satisfy_callback, + SurfaceLayer(const LayerSettings& settings, + const SatisfyCallback& satisfy_callback, const RequireCallback& require_callback); bool HasDrawableContent() const override; diff --git a/chromium/cc/layers/surface_layer_impl.cc b/chromium/cc/layers/surface_layer_impl.cc index 966112d7f54..0cd4f248645 100644 --- a/chromium/cc/layers/surface_layer_impl.cc +++ b/chromium/cc/layers/surface_layer_impl.cc @@ -12,7 +12,7 @@ namespace cc { SurfaceLayerImpl::SurfaceLayerImpl(LayerTreeImpl* tree_impl, int id) - : LayerImpl(tree_impl, id) { + : LayerImpl(tree_impl, id), surface_scale_(0.f) { } SurfaceLayerImpl::~SurfaceLayerImpl() {} @@ -30,26 +30,44 @@ void SurfaceLayerImpl::SetSurfaceId(SurfaceId surface_id) { NoteLayerPropertyChanged(); } +void SurfaceLayerImpl::SetSurfaceScale(float scale) { + if (surface_scale_ == scale) + return; + + surface_scale_ = scale; + NoteLayerPropertyChanged(); +} + +void SurfaceLayerImpl::SetSurfaceSize(const gfx::Size& size) { + if (surface_size_ == size) + return; + + surface_size_ = size; + NoteLayerPropertyChanged(); +} + void SurfaceLayerImpl::PushPropertiesTo(LayerImpl* layer) { LayerImpl::PushPropertiesTo(layer); SurfaceLayerImpl* layer_impl = static_cast<SurfaceLayerImpl*>(layer); layer_impl->SetSurfaceId(surface_id_); + layer_impl->SetSurfaceSize(surface_size_); + layer_impl->SetSurfaceScale(surface_scale_); } void SurfaceLayerImpl::AppendQuads(RenderPass* render_pass, AppendQuadsData* append_quads_data) { SharedQuadState* shared_quad_state = render_pass->CreateAndAppendSharedQuadState(); - PopulateSharedQuadState(shared_quad_state); + PopulateScaledSharedQuadState(shared_quad_state, surface_scale_); - AppendDebugBorderQuad( - render_pass, content_bounds(), shared_quad_state, append_quads_data); + AppendDebugBorderQuad(render_pass, surface_size_, shared_quad_state, + append_quads_data); if (surface_id_.is_null()) return; - gfx::Rect quad_rect(content_bounds()); + gfx::Rect quad_rect(surface_size_); gfx::Rect visible_quad_rect = draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( quad_rect); @@ -58,6 +76,7 @@ void SurfaceLayerImpl::AppendQuads(RenderPass* render_pass, SurfaceDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, surface_id_); + render_pass->referenced_surfaces.push_back(surface_id_); } void SurfaceLayerImpl::GetDebugBorderProperties(SkColor* color, diff --git a/chromium/cc/layers/surface_layer_impl.h b/chromium/cc/layers/surface_layer_impl.h index 90c0f4565c6..b190b3af940 100644 --- a/chromium/cc/layers/surface_layer_impl.h +++ b/chromium/cc/layers/surface_layer_impl.h @@ -20,6 +20,8 @@ class CC_EXPORT SurfaceLayerImpl : public LayerImpl { ~SurfaceLayerImpl() override; void SetSurfaceId(SurfaceId surface_id); + void SetSurfaceScale(float scale); + void SetSurfaceSize(const gfx::Size& size); // LayerImpl overrides. scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; @@ -36,6 +38,8 @@ class CC_EXPORT SurfaceLayerImpl : public LayerImpl { const char* LayerTypeAsString() const override; SurfaceId surface_id_; + gfx::Size surface_size_; + float surface_scale_; DISALLOW_COPY_AND_ASSIGN(SurfaceLayerImpl); }; diff --git a/chromium/cc/layers/surface_layer_impl_unittest.cc b/chromium/cc/layers/surface_layer_impl_unittest.cc index 74543a84428..3ff8255f151 100644 --- a/chromium/cc/layers/surface_layer_impl_unittest.cc +++ b/chromium/cc/layers/surface_layer_impl_unittest.cc @@ -19,10 +19,11 @@ TEST(SurfaceLayerImplTest, Occlusion) { SurfaceLayerImpl* surface_layer_impl = impl.AddChildToRoot<SurfaceLayerImpl>(); surface_layer_impl->SetBounds(layer_size); - surface_layer_impl->SetContentBounds(layer_size); surface_layer_impl->SetDrawsContent(true); SurfaceId surface_id(9); surface_layer_impl->SetSurfaceId(surface_id); + surface_layer_impl->SetSurfaceScale(1.f); + surface_layer_impl->SetSurfaceSize(layer_size); impl.CalcDrawProps(viewport_size); @@ -38,7 +39,7 @@ TEST(SurfaceLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(surface_layer_impl->visible_content_rect()); + gfx::Rect occluded(surface_layer_impl->visible_layer_rect()); impl.AppendQuadsWithOcclusion(surface_layer_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); diff --git a/chromium/cc/layers/surface_layer_unittest.cc b/chromium/cc/layers/surface_layer_unittest.cc index 6661a1a243a..eac14a0c245 100644 --- a/chromium/cc/layers/surface_layer_unittest.cc +++ b/chromium/cc/layers/surface_layer_unittest.cc @@ -16,7 +16,7 @@ #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/fake_output_surface.h" #include "cc/test/layer_tree_test.h" -#include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -32,7 +32,8 @@ class SurfaceLayerTest : public testing::Test { protected: void SetUp() override { - layer_tree_host_ = FakeLayerTreeHost::Create(&fake_client_); + layer_tree_host_ = + FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_); layer_tree_host_->SetViewportSize(gfx::Size(10, 10)); } @@ -43,9 +44,10 @@ class SurfaceLayerTest : public testing::Test { } } - scoped_ptr<FakeLayerTreeHost> layer_tree_host_; FakeLayerTreeHostClient fake_client_; - TestSharedBitmapManager shared_bitmap_manager_; + TestTaskGraphRunner task_graph_runner_; + scoped_ptr<FakeLayerTreeHost> layer_tree_host_; + LayerSettings layer_settings_; }; void SatisfyCallback(SurfaceSequence* out, SurfaceSequence in) { @@ -68,16 +70,16 @@ TEST_F(SurfaceLayerTest, MultipleFramesOneSurface) { SurfaceId required_id; std::set<SurfaceSequence> required_seq; scoped_refptr<SurfaceLayer> layer(SurfaceLayer::Create( - base::Bind(&SatisfyCallback, &blank_change), + layer_settings_, base::Bind(&SatisfyCallback, &blank_change), base::Bind(&RequireCallback, &required_id, &required_seq))); layer->SetSurfaceId(SurfaceId(1), 1.f, gfx::Size(1, 1)); layer_tree_host_->set_surface_id_namespace(1); layer_tree_host_->SetRootLayer(layer); scoped_ptr<FakeLayerTreeHost> layer_tree_host2 = - FakeLayerTreeHost::Create(&fake_client_); + FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_); scoped_refptr<SurfaceLayer> layer2(SurfaceLayer::Create( - base::Bind(&SatisfyCallback, &blank_change), + layer_settings_, base::Bind(&SatisfyCallback, &blank_change), base::Bind(&RequireCallback, &required_id, &required_seq))); layer2->SetSurfaceId(SurfaceId(1), 1.f, gfx::Size(1, 1)); layer_tree_host2->set_surface_id_namespace(2); @@ -115,36 +117,6 @@ TEST_F(SurfaceLayerTest, MultipleFramesOneSurface) { EXPECT_EQ(2u, required_seq.size()); } -static void CalcDrawProps(FakeLayerTreeHost* host, float device_scale_factor) { - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - host->root_layer(), gfx::Size(500, 500), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); -} - -// Check that setting content scale on the surface works. -TEST_F(SurfaceLayerTest, ScaleSurface) { - SurfaceSequence blank_change; - SurfaceId required_id; - std::set<SurfaceSequence> required_seq; - scoped_refptr<SurfaceLayer> layer(SurfaceLayer::Create( - base::Bind(&SatisfyCallback, &blank_change), - base::Bind(&RequireCallback, &required_id, &required_seq))); - gfx::Size surface_size(10, 15); - layer->SetSurfaceId(SurfaceId(1), 2.f, surface_size); - layer->SetBounds(gfx::Size(25, 45)); - layer_tree_host_->SetRootLayer(layer); - - CalcDrawProps(layer_tree_host_.get(), 5.f); - EXPECT_EQ(2.f, layer->contents_scale_x()); - EXPECT_EQ(2.f, layer->contents_scale_y()); - EXPECT_EQ(surface_size.ToString(), layer->content_bounds().ToString()); - - layer_tree_host_->SetRootLayer(nullptr); - layer_tree_host_.reset(); -} - // Check that SurfaceSequence is sent through swap promise. class SurfaceLayerSwapPromise : public LayerTreeTest { public: @@ -154,7 +126,7 @@ class SurfaceLayerSwapPromise : public LayerTreeTest { void BeginTest() override { layer_tree_host()->set_surface_id_namespace(1); layer_ = SurfaceLayer::Create( - base::Bind(&SatisfyCallback, &satisfied_sequence_), + layer_settings(), base::Bind(&SatisfyCallback, &satisfied_sequence_), base::Bind(&RequireCallback, &required_id_, &required_set_)); layer_->SetSurfaceId(SurfaceId(1), 1.f, gfx::Size(1, 1)); @@ -185,7 +157,7 @@ class SurfaceLayerSwapPromise : public LayerTreeTest { switch (commit_count_) { case 1: // Remove SurfaceLayer from tree to cause SwapPromise to be created. - blank_layer_ = SolidColorLayer::Create(); + blank_layer_ = SolidColorLayer::Create(layer_settings()); blank_layer_->SetIsDrawable(true); blank_layer_->SetBounds(gfx::Size(10, 10)); layer_tree_host()->SetRootLayer(blank_layer_); diff --git a/chromium/cc/layers/texture_layer.cc b/chromium/cc/layers/texture_layer.cc index cf1149b5161..20741fddad8 100644 --- a/chromium/cc/layers/texture_layer.cc +++ b/chromium/cc/layers/texture_layer.cc @@ -19,12 +19,14 @@ namespace cc { scoped_refptr<TextureLayer> TextureLayer::CreateForMailbox( + const LayerSettings& settings, TextureLayerClient* client) { - return scoped_refptr<TextureLayer>(new TextureLayer(client)); + return scoped_refptr<TextureLayer>(new TextureLayer(settings, client)); } -TextureLayer::TextureLayer(TextureLayerClient* client) - : Layer(), +TextureLayer::TextureLayer(const LayerSettings& settings, + TextureLayerClient* client) + : Layer(settings), client_(client), flipped_(true), nearest_neighbor_(false), @@ -214,9 +216,8 @@ bool TextureLayer::HasDrawableContent() const { return (client_ || holder_ref_) && Layer::HasDrawableContent(); } -bool TextureLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - bool updated = Layer::Update(queue, occlusion); +bool TextureLayer::Update() { + bool updated = Layer::Update(); if (client_) { TextureMailbox mailbox; scoped_ptr<SingleReleaseCallback> release_callback; @@ -266,16 +267,6 @@ void TextureLayer::PushPropertiesTo(LayerImpl* layer) { } } -SimpleEnclosedRegion TextureLayer::VisibleContentOpaqueRegion() const { - if (contents_opaque()) - return SimpleEnclosedRegion(visible_content_rect()); - - if (blend_background_color_ && (SkColorGetA(background_color()) == 0xFF)) - return SimpleEnclosedRegion(visible_content_rect()); - - return SimpleEnclosedRegion(); -} - TextureLayer::TextureMailboxHolder::MainThreadReference::MainThreadReference( TextureMailboxHolder* holder) : holder_(holder) { diff --git a/chromium/cc/layers/texture_layer.h b/chromium/cc/layers/texture_layer.h index 00c9e7452ad..53f2d8d4065 100644 --- a/chromium/cc/layers/texture_layer.h +++ b/chromium/cc/layers/texture_layer.h @@ -86,6 +86,7 @@ class CC_EXPORT TextureLayer : public Layer { // Used when mailbox names are specified instead of texture IDs. static scoped_refptr<TextureLayer> CreateForMailbox( + const LayerSettings& settings, TextureLayerClient* client); // Resets the client, which also resets the texture. @@ -141,13 +142,11 @@ class CC_EXPORT TextureLayer : public Layer { void SetNeedsDisplayRect(const gfx::Rect& dirty_rect) override; void SetLayerTreeHost(LayerTreeHost* layer_tree_host) override; - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; + bool Update() override; void PushPropertiesTo(LayerImpl* layer) override; - SimpleEnclosedRegion VisibleContentOpaqueRegion() const override; protected: - explicit TextureLayer(TextureLayerClient* client); + TextureLayer(const LayerSettings& settings, TextureLayerClient* client); ~TextureLayer() override; bool HasDrawableContent() const override; diff --git a/chromium/cc/layers/texture_layer_impl.cc b/chromium/cc/layers/texture_layer_impl.cc index 8728b89db9c..404d479721a 100644 --- a/chromium/cc/layers/texture_layer_impl.cc +++ b/chromium/cc/layers/texture_layer_impl.cc @@ -99,12 +99,12 @@ bool TextureLayerImpl::WillDraw(DrawMode draw_mode, // hardware draw. if (!texture_copy_) texture_copy_ = ScopedResource::Create(resource_provider); - if (texture_copy_->size() != texture_mailbox_.shared_memory_size() || + if (texture_copy_->size() != texture_mailbox_.size_in_pixels() || resource_provider->InUseByConsumer(texture_copy_->id())) texture_copy_->Free(); if (!texture_copy_->id()) { - texture_copy_->Allocate(texture_mailbox_.shared_memory_size(), + texture_copy_->Allocate(texture_mailbox_.size_in_pixels(), ResourceProvider::TEXTURE_HINT_IMMUTABLE, resource_provider->best_texture_format()); } @@ -126,12 +126,8 @@ bool TextureLayerImpl::WillDraw(DrawMode draw_mode, pixels = &swizzled[0]; } - resource_provider->SetPixels( - texture_copy_->id(), - pixels, - gfx::Rect(texture_mailbox_.shared_memory_size()), - gfx::Rect(texture_mailbox_.shared_memory_size()), - gfx::Vector2d()); + resource_provider->CopyToResource(texture_copy_->id(), pixels, + texture_mailbox_.size_in_pixels()); valid_texture_copy_ = true; } @@ -148,14 +144,14 @@ void TextureLayerImpl::AppendQuads(RenderPass* render_pass, render_pass->CreateAndAppendSharedQuadState(); PopulateSharedQuadState(shared_quad_state); - AppendDebugBorderQuad( - render_pass, content_bounds(), shared_quad_state, append_quads_data); + AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state, + append_quads_data); SkColor bg_color = blend_background_color_ ? background_color() : SK_ColorTRANSPARENT; bool opaque = contents_opaque() || (SkColorGetA(bg_color) == 0xFF); - gfx::Rect quad_rect(content_bounds()); + gfx::Rect quad_rect(bounds()); gfx::Rect opaque_rect = opaque ? quad_rect : gfx::Rect(); gfx::Rect visible_quad_rect = draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( @@ -165,7 +161,7 @@ void TextureLayerImpl::AppendQuads(RenderPass* render_pass, TextureDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); - ResourceProvider::ResourceId id = + ResourceId id = valid_texture_copy_ ? texture_copy_->id() : external_texture_resource_; quad->SetNew(shared_quad_state, quad_rect, @@ -179,15 +175,19 @@ void TextureLayerImpl::AppendQuads(RenderPass* render_pass, vertex_opacity_, flipped_, nearest_neighbor_); + if (!valid_texture_copy_) { + quad->set_resource_size_in_pixels(texture_mailbox_.size_in_pixels()); + quad->set_allow_overlay(texture_mailbox_.allow_overlay()); + } ValidateQuadResources(quad); } -SimpleEnclosedRegion TextureLayerImpl::VisibleContentOpaqueRegion() const { +SimpleEnclosedRegion TextureLayerImpl::VisibleOpaqueRegion() const { if (contents_opaque()) - return SimpleEnclosedRegion(visible_content_rect()); + return SimpleEnclosedRegion(visible_layer_rect()); if (blend_background_color_ && (SkColorGetA(background_color()) == 0xFF)) - return SimpleEnclosedRegion(visible_content_rect()); + return SimpleEnclosedRegion(visible_layer_rect()); return SimpleEnclosedRegion(); } diff --git a/chromium/cc/layers/texture_layer_impl.h b/chromium/cc/layers/texture_layer_impl.h index 56def7a0541..680aaf0aec0 100644 --- a/chromium/cc/layers/texture_layer_impl.h +++ b/chromium/cc/layers/texture_layer_impl.h @@ -30,7 +30,7 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl { ResourceProvider* resource_provider) override; void AppendQuads(RenderPass* render_pass, AppendQuadsData* append_quads_data) override; - SimpleEnclosedRegion VisibleContentOpaqueRegion() const override; + SimpleEnclosedRegion VisibleOpaqueRegion() const override; void ReleaseResources() override; // These setter methods don't cause any implicit damage, so the texture client @@ -59,7 +59,7 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl { const char* LayerTypeAsString() const override; void FreeTextureMailbox(); - ResourceProvider::ResourceId external_texture_resource_; + ResourceId external_texture_resource_; bool premultiplied_alpha_; bool blend_background_color_; bool flipped_; diff --git a/chromium/cc/layers/texture_layer_impl_unittest.cc b/chromium/cc/layers/texture_layer_impl_unittest.cc index cbe80e161d9..27efd971502 100644 --- a/chromium/cc/layers/texture_layer_impl_unittest.cc +++ b/chromium/cc/layers/texture_layer_impl_unittest.cc @@ -17,6 +17,32 @@ void IgnoreCallback(uint32 sync_point, BlockingTaskRunner* main_thread_task_runner) { } +TEST(TextureLayerImplTest, VisibleOpaqueRegion) { + const gfx::Size layer_bounds(100, 100); + const gfx::Rect layer_rect(layer_bounds); + const Region layer_region(layer_rect); + + LayerTestCommon::LayerImplTest impl; + + TextureLayerImpl* layer = impl.AddChildToRoot<TextureLayerImpl>(); + layer->SetBounds(layer_bounds); + layer->draw_properties().visible_layer_rect = layer_rect; + layer->SetBlendBackgroundColor(true); + + // Verify initial conditions. + EXPECT_FALSE(layer->contents_opaque()); + EXPECT_EQ(0u, layer->background_color()); + EXPECT_EQ(Region().ToString(), layer->VisibleOpaqueRegion().ToString()); + + // Opaque background. + layer->SetBackgroundColor(SK_ColorWHITE); + EXPECT_EQ(layer_region.ToString(), layer->VisibleOpaqueRegion().ToString()); + + // Transparent background. + layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255)); + EXPECT_EQ(Region().ToString(), layer->VisibleOpaqueRegion().ToString()); +} + TEST(TextureLayerImplTest, Occlusion) { gfx::Size layer_size(1000, 1000); gfx::Size viewport_size(1000, 1000); @@ -31,7 +57,6 @@ TEST(TextureLayerImplTest, Occlusion) { TextureLayerImpl* texture_layer_impl = impl.AddChildToRoot<TextureLayerImpl>(); texture_layer_impl->SetBounds(layer_size); - texture_layer_impl->SetContentBounds(layer_size); texture_layer_impl->SetDrawsContent(true); texture_layer_impl->SetTextureMailbox( texture_mailbox, @@ -51,7 +76,7 @@ TEST(TextureLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(texture_layer_impl->visible_content_rect()); + gfx::Rect occluded(texture_layer_impl->visible_layer_rect()); impl.AppendQuadsWithOcclusion(texture_layer_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); diff --git a/chromium/cc/layers/texture_layer_unittest.cc b/chromium/cc/layers/texture_layer_unittest.cc index c33db7c3b1c..97bb7a15b20 100644 --- a/chromium/cc/layers/texture_layer_unittest.cc +++ b/chromium/cc/layers/texture_layer_unittest.cc @@ -54,9 +54,12 @@ gpu::Mailbox MailboxFromChar(char value) { class MockLayerTreeHost : public LayerTreeHost { public: - static scoped_ptr<MockLayerTreeHost> Create(FakeLayerTreeHostClient* client) { + static scoped_ptr<MockLayerTreeHost> Create( + FakeLayerTreeHostClient* client, + TaskGraphRunner* task_graph_runner) { LayerTreeHost::InitParams params; params.client = client; + params.task_graph_runner = task_graph_runner; LayerTreeSettings settings; params.settings = &settings; return make_scoped_ptr(new MockLayerTreeHost(client, ¶ms)); @@ -190,7 +193,8 @@ class TextureLayerTest : public testing::Test { protected: void SetUp() override { - layer_tree_host_ = MockLayerTreeHost::Create(&fake_client_); + layer_tree_host_ = + MockLayerTreeHost::Create(&fake_client_, &task_graph_runner_); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); layer_tree_host_->SetViewportSize(gfx::Size(10, 10)); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); @@ -211,11 +215,12 @@ class TextureLayerTest : public testing::Test { TestTaskGraphRunner task_graph_runner_; FakeLayerTreeHostImpl host_impl_; CommonMailboxObjects test_data_; + LayerSettings layer_settings_; }; TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) { scoped_refptr<TextureLayer> test_layer = - TextureLayer::CreateForMailbox(nullptr); + TextureLayer::CreateForMailbox(layer_settings_, nullptr); EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer)); // Test properties that should call SetNeedsCommit. All properties need to @@ -230,37 +235,10 @@ TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) { EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true)); } -TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) { - const gfx::Size layer_bounds(100, 100); - const gfx::Rect layer_rect(layer_bounds); - const Region layer_region(layer_rect); - - scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(nullptr); - layer->SetBounds(layer_bounds); - layer->draw_properties().visible_content_rect = layer_rect; - layer->SetBlendBackgroundColor(true); - - // Verify initial conditions. - EXPECT_FALSE(layer->contents_opaque()); - EXPECT_EQ(0u, layer->background_color()); - EXPECT_EQ(Region().ToString(), - layer->VisibleContentOpaqueRegion().ToString()); - - // Opaque background. - layer->SetBackgroundColor(SK_ColorWHITE); - EXPECT_EQ(layer_region.ToString(), - layer->VisibleContentOpaqueRegion().ToString()); - - // Transparent background. - layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255)); - EXPECT_EQ(Region().ToString(), - layer->VisibleContentOpaqueRegion().ToString()); -} - TEST_F(TextureLayerTest, RateLimiter) { FakeTextureLayerClient client; - scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox( - &client); + scoped_refptr<TextureLayer> test_layer = + TextureLayer::CreateForMailbox(layer_settings_, &client); test_layer->SetIsDrawable(true); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); layer_tree_host_->SetRootLayer(test_layer); @@ -288,8 +266,7 @@ TEST_F(TextureLayerTest, RateLimiter) { Mock::VerifyAndClearExpectations(layer_tree_host_.get()); // Reset to a layer with a client, that started the rate limiter. - test_layer = TextureLayer::CreateForMailbox( - &client); + test_layer = TextureLayer::CreateForMailbox(layer_settings_, &client); test_layer->SetIsDrawable(true); test_layer->SetRateLimitContext(true); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); @@ -329,7 +306,7 @@ class TextureLayerWithMailboxTest : public TextureLayerTest { TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { scoped_refptr<TextureLayer> test_layer = - TextureLayer::CreateForMailbox(nullptr); + TextureLayer::CreateForMailbox(layer_settings_, nullptr); ASSERT_TRUE(test_layer.get()); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); @@ -387,7 +364,7 @@ TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) { scoped_refptr<TextureLayer> test_layer = - TextureLayer::CreateForMailbox(nullptr); + TextureLayer::CreateForMailbox(layer_settings_, nullptr); ASSERT_TRUE(test_layer.get()); // These use the same gpu::Mailbox, but different sync points. @@ -467,7 +444,7 @@ class TextureLayerMailboxHolderTest : public TextureLayerTest { TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { scoped_refptr<TextureLayer> test_layer = - TextureLayer::CreateForMailbox(nullptr); + TextureLayer::CreateForMailbox(layer_settings_, nullptr); ASSERT_TRUE(test_layer.get()); main_thread_.message_loop()->task_runner()->PostTask( @@ -517,7 +494,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { scoped_refptr<TextureLayer> test_layer = - TextureLayer::CreateForMailbox(nullptr); + TextureLayer::CreateForMailbox(layer_settings_, nullptr); ASSERT_TRUE(test_layer.get()); main_thread_.message_loop()->task_runner()->PostTask( @@ -568,7 +545,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { scoped_refptr<TextureLayer> test_layer = - TextureLayer::CreateForMailbox(nullptr); + TextureLayer::CreateForMailbox(layer_settings_, nullptr); ASSERT_TRUE(test_layer.get()); main_thread_.message_loop()->task_runner()->PostTask( @@ -619,7 +596,7 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { scoped_refptr<TextureLayer> test_layer = - TextureLayer::CreateForMailbox(nullptr); + TextureLayer::CreateForMailbox(layer_settings_, nullptr); ASSERT_TRUE(test_layer.get()); main_thread_.message_loop()->task_runner()->PostTask( @@ -717,10 +694,10 @@ class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); gfx::Size bounds(100, 100); - root_ = Layer::Create(); + root_ = Layer::Create(layer_settings()); root_->SetBounds(bounds); - layer_ = TextureLayer::CreateForMailbox(nullptr); + layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr); layer_->SetIsDrawable(true); layer_->SetBounds(bounds); @@ -761,17 +738,13 @@ class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { layer_->SetTextureMailbox(TextureMailbox(), nullptr); break; case 4: - if (layer_tree_host()->settings().impl_side_painting) { - // With impl painting, the texture mailbox will still be on the impl - // thread when the commit finishes, because the layer is not drawble - // when it has no texture mailbox, and thus does not block the commit - // on activation. So, we wait for activation. - // TODO(danakj): fix this. crbug.com/277953 - layer_tree_host()->SetNeedsCommit(); - break; - } else { - ++commit_count_; - } + // With impl painting, the texture mailbox will still be on the impl + // thread when the commit finishes, because the layer is not drawble + // when it has no texture mailbox, and thus does not block the commit + // on activation. So, we wait for activation. + // TODO(danakj): fix this. crbug.com/277953 + layer_tree_host()->SetNeedsCommit(); + break; case 5: EXPECT_EQ(4, callback_count_); // Restore a mailbox for the next step. @@ -784,16 +757,12 @@ class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { layer_->RemoveFromParent(); break; case 7: - if (layer_tree_host()->settings().impl_side_painting) { - // With impl painting, the texture mailbox will still be on the impl - // thread when the commit finishes, because the layer is not around to - // block the commit on activation anymore. So, we wait for activation. - // TODO(danakj): fix this. crbug.com/277953 - layer_tree_host()->SetNeedsCommit(); - break; - } else { - ++commit_count_; - } + // With impl painting, the texture mailbox will still be on the impl + // thread when the commit finishes, because the layer is not around to + // block the commit on activation anymore. So, we wait for activation. + // TODO(danakj): fix this. crbug.com/277953 + layer_tree_host()->SetNeedsCommit(); + break; case 8: EXPECT_EQ(4, callback_count_); // Resetting the mailbox will call the callback now. @@ -838,10 +807,10 @@ class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest { void BeginTest() override { gfx::Size bounds(100, 100); - root_ = Layer::Create(); + root_ = Layer::Create(layer_settings()); root_->SetBounds(bounds); - layer_ = TextureLayer::CreateForMailbox(nullptr); + layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr); layer_->SetIsDrawable(true); layer_->SetBounds(bounds); @@ -918,7 +887,8 @@ class TextureLayerImplWithMailboxTest : public TextureLayerTest { void SetUp() override { TextureLayerTest::SetUp(); - layer_tree_host_ = MockLayerTreeHost::Create(&fake_client_); + layer_tree_host_ = + MockLayerTreeHost::Create(&fake_client_, &task_graph_runner_); EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d())); } @@ -1086,7 +1056,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) { ResourceProvider* provider = host_impl_.active_tree()->resource_provider(); - ResourceProvider::ResourceId id = provider->CreateResourceFromTextureMailbox( + ResourceId id = provider->CreateResourceFromTextureMailbox( test_data_.mailbox1_, SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_)); provider->AllocateForTesting(id); @@ -1139,11 +1109,11 @@ class TextureLayerNoExtraCommitForMailboxTest } void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(10, 10)); root->SetIsDrawable(true); - texture_layer_ = TextureLayer::CreateForMailbox(this); + texture_layer_ = TextureLayer::CreateForMailbox(layer_settings(), this); texture_layer_->SetBounds(gfx::Size(10, 10)); texture_layer_->SetIsDrawable(true); root->AddChild(texture_layer_); @@ -1234,22 +1204,22 @@ class TextureLayerChangeInvisibleMailboxTest } void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(10, 10)); root->SetIsDrawable(true); - solid_layer_ = SolidColorLayer::Create(); + solid_layer_ = SolidColorLayer::Create(layer_settings()); solid_layer_->SetBounds(gfx::Size(10, 10)); solid_layer_->SetIsDrawable(true); solid_layer_->SetBackgroundColor(SK_ColorWHITE); root->AddChild(solid_layer_); - parent_layer_ = Layer::Create(); + parent_layer_ = Layer::Create(layer_settings()); parent_layer_->SetBounds(gfx::Size(10, 10)); parent_layer_->SetIsDrawable(true); root->AddChild(parent_layer_); - texture_layer_ = TextureLayer::CreateForMailbox(this); + texture_layer_ = TextureLayer::CreateForMailbox(layer_settings(), this); texture_layer_->SetBounds(gfx::Size(10, 10)); texture_layer_->SetIsDrawable(true); parent_layer_->AddChild(texture_layer_); @@ -1364,7 +1334,7 @@ class TextureLayerReleaseResourcesBase LayerTreeTest::SetupTree(); scoped_refptr<TextureLayer> texture_layer = - TextureLayer::CreateForMailbox(this); + TextureLayer::CreateForMailbox(layer_settings(), this); texture_layer->SetBounds(gfx::Size(10, 10)); texture_layer->SetIsDrawable(true); @@ -1428,10 +1398,10 @@ class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest { void SetupTree() override { gfx::Size bounds(100, 100); - root_ = Layer::Create(); + root_ = Layer::Create(layer_settings()); root_->SetBounds(bounds); - layer_ = TextureLayer::CreateForMailbox(nullptr); + layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr); layer_->SetIsDrawable(true); layer_->SetBounds(bounds); @@ -1497,10 +1467,10 @@ class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest { void SetupTree() override { gfx::Size bounds(100, 100); - root_ = Layer::Create(); + root_ = Layer::Create(layer_settings()); root_->SetBounds(bounds); - layer_ = TextureLayer::CreateForMailbox(nullptr); + layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr); layer_->SetIsDrawable(true); layer_->SetBounds(bounds); diff --git a/chromium/cc/layers/tiled_layer.cc b/chromium/cc/layers/tiled_layer.cc deleted file mode 100644 index 55143befe93..00000000000 --- a/chromium/cc/layers/tiled_layer.cc +++ /dev/null @@ -1,869 +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/layers/tiled_layer.h" - -#include <algorithm> -#include <vector> - -#include "base/auto_reset.h" -#include "base/basictypes.h" -#include "build/build_config.h" -#include "cc/base/simple_enclosed_region.h" -#include "cc/layers/layer_impl.h" -#include "cc/layers/tiled_layer_impl.h" -#include "cc/resources/layer_updater.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/priority_calculator.h" -#include "cc/trees/layer_tree_host.h" -#include "cc/trees/occlusion_tracker.h" -#include "ui/gfx/geometry/rect_conversions.h" - -namespace cc { - -// Maximum predictive expansion of the visible area. -static const int kMaxPredictiveTilesCount = 2; - -// Number of rows/columns of tiles to pre-paint. -// We should increase these further as all textures are -// prioritized and we insure performance doesn't suffer. -static const int kPrepaintRows = 4; -static const int kPrepaintColumns = 2; - -class UpdatableTile : public LayerTilingData::Tile { - public: - static scoped_ptr<UpdatableTile> Create( - scoped_ptr<LayerUpdater::Resource> updater_resource) { - return make_scoped_ptr(new UpdatableTile(updater_resource.Pass())); - } - - LayerUpdater::Resource* updater_resource() { return updater_resource_.get(); } - PrioritizedResource* managed_resource() { - return updater_resource_->texture(); - } - - bool is_dirty() const { return !dirty_rect.IsEmpty(); } - - // Reset update state for the current frame. This should occur before painting - // for all layers. Since painting one layer can invalidate another layer after - // it has already painted, mark all non-dirty tiles as valid before painting - // such that invalidations during painting won't prevent them from being - // pushed. - void ResetUpdateState() { - update_rect = gfx::Rect(); - occluded = false; - partial_update = false; - valid_for_frame = !is_dirty(); - } - - // This promises to update the tile and therefore also guarantees the tile - // will be valid for this frame. dirty_rect is copied into update_rect so we - // can continue to track re-entrant invalidations that occur during painting. - void MarkForUpdate() { - valid_for_frame = true; - update_rect = dirty_rect; - dirty_rect = gfx::Rect(); - } - - gfx::Rect dirty_rect; - gfx::Rect update_rect; - bool partial_update; - bool valid_for_frame; - bool occluded; - - private: - explicit UpdatableTile(scoped_ptr<LayerUpdater::Resource> updater_resource) - : partial_update(false), - valid_for_frame(false), - occluded(false), - updater_resource_(updater_resource.Pass()) {} - - scoped_ptr<LayerUpdater::Resource> updater_resource_; - - DISALLOW_COPY_AND_ASSIGN(UpdatableTile); -}; - -TiledLayer::TiledLayer() - : ContentsScalingLayer(), - texture_format_(RGBA_8888), - skips_draw_(false), - failed_update_(false), - tiling_option_(AUTO_TILE) { - tiler_ = - LayerTilingData::Create(gfx::Size(), LayerTilingData::HAS_BORDER_TEXELS); -} - -TiledLayer::~TiledLayer() {} - -scoped_ptr<LayerImpl> TiledLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) { - return TiledLayerImpl::Create(tree_impl, id()); -} - -void TiledLayer::UpdateTileSizeAndTilingOption() { - DCHECK(layer_tree_host()); - - gfx::Size default_tile_size = layer_tree_host()->settings().default_tile_size; - gfx::Size max_untiled_layer_size = - layer_tree_host()->settings().max_untiled_layer_size; - int layer_width = content_bounds().width(); - int layer_height = content_bounds().height(); - - gfx::Size tile_size(std::min(default_tile_size.width(), layer_width), - std::min(default_tile_size.height(), layer_height)); - - // Tile if both dimensions large, or any one dimension large and the other - // extends into a second tile but the total layer area isn't larger than that - // of the largest possible untiled layer. This heuristic allows for long - // skinny layers (e.g. scrollbars) that are Nx1 tiles to minimize wasted - // texture space but still avoids creating very large tiles. - bool any_dimension_large = layer_width > max_untiled_layer_size.width() || - layer_height > max_untiled_layer_size.height(); - bool any_dimension_one_tile = - (layer_width <= default_tile_size.width() || - layer_height <= default_tile_size.height()) && - (layer_width * layer_height) <= (max_untiled_layer_size.width() * - max_untiled_layer_size.height()); - bool auto_tiled = any_dimension_large && !any_dimension_one_tile; - - bool is_tiled; - if (tiling_option_ == ALWAYS_TILE) - is_tiled = true; - else if (tiling_option_ == NEVER_TILE) - is_tiled = false; - else - is_tiled = auto_tiled; - - gfx::Size requested_size = is_tiled ? tile_size : content_bounds(); - const int max_size = - layer_tree_host()->GetRendererCapabilities().max_texture_size; - requested_size.SetToMin(gfx::Size(max_size, max_size)); - SetTileSize(requested_size); -} - -void TiledLayer::UpdateBounds() { - gfx::Size old_tiling_size = tiler_->tiling_size(); - gfx::Size new_tiling_size = content_bounds(); - if (old_tiling_size == new_tiling_size) - return; - tiler_->SetTilingSize(new_tiling_size); - - // Invalidate any areas that the new bounds exposes. - Region new_region = - SubtractRegions(gfx::Rect(new_tiling_size), gfx::Rect(old_tiling_size)); - for (Region::Iterator new_rects(new_region); new_rects.has_rect(); - new_rects.next()) - InvalidateContentRect(new_rects.rect()); - UpdateDrawsContent(HasDrawableContent()); -} - -void TiledLayer::SetTileSize(const gfx::Size& size) { - tiler_->SetTileSize(size); - UpdateDrawsContent(HasDrawableContent()); -} - -void TiledLayer::SetBorderTexelOption( - LayerTilingData::BorderTexelOption border_texel_option) { - tiler_->SetBorderTexelOption(border_texel_option); - UpdateDrawsContent(HasDrawableContent()); -} - -bool TiledLayer::HasDrawableContent() const { - bool has_more_than_one_tile = - (tiler_->num_tiles_x() > 1) || (tiler_->num_tiles_y() > 1); - - return !(tiling_option_ == NEVER_TILE && has_more_than_one_tile) && - ContentsScalingLayer::HasDrawableContent(); -} - -void TiledLayer::ReduceMemoryUsage() { - if (Updater()) - Updater()->ReduceMemoryUsage(); -} - -void TiledLayer::SetIsMask(bool is_mask) { - set_tiling_option(is_mask ? NEVER_TILE : AUTO_TILE); -} - -void TiledLayer::PushPropertiesTo(LayerImpl* layer) { - ContentsScalingLayer::PushPropertiesTo(layer); - - TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer); - - tiled_layer->set_skips_draw(skips_draw_); - tiled_layer->SetTilingData(*tiler_); - std::vector<UpdatableTile*> invalid_tiles; - - for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); - iter != tiler_->tiles().end(); - ++iter) { - int i = iter->first.first; - int j = iter->first.second; - UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); - // TODO(enne): This should not ever be null. - if (!tile) - continue; - - if (!tile->managed_resource()->have_backing_texture()) { - // Evicted tiles get deleted from both layers - invalid_tiles.push_back(tile); - continue; - } - - if (!tile->valid_for_frame) { - // Invalidated tiles are set so they can get different debug colors. - tiled_layer->PushInvalidTile(i, j); - continue; - } - - tiled_layer->PushTileProperties( - i, - j, - tile->managed_resource()->resource_id(), - tile->managed_resource()->contents_swizzled()); - } - for (std::vector<UpdatableTile*>::const_iterator iter = invalid_tiles.begin(); - iter != invalid_tiles.end(); - ++iter) - tiler_->TakeTile((*iter)->i(), (*iter)->j()); - - // TiledLayer must push properties every frame, since viewport state and - // occlusion from anywhere in the tree can change what the layer decides to - // push to the impl tree. - needs_push_properties_ = true; -} - -PrioritizedResourceManager* TiledLayer::ResourceManager() { - if (!layer_tree_host()) - return nullptr; - return layer_tree_host()->contents_texture_manager(); -} - -const PrioritizedResource* TiledLayer::ResourceAtForTesting(int i, - int j) const { - UpdatableTile* tile = TileAt(i, j); - if (!tile) - return nullptr; - return tile->managed_resource(); -} - -void TiledLayer::SetLayerTreeHost(LayerTreeHost* host) { - if (host && host != layer_tree_host()) { - for (LayerTilingData::TileMap::const_iterator - iter = tiler_->tiles().begin(); - iter != tiler_->tiles().end(); - ++iter) { - UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); - // TODO(enne): This should not ever be null. - if (!tile) - continue; - tile->managed_resource()->SetTextureManager( - host->contents_texture_manager()); - } - } - ContentsScalingLayer::SetLayerTreeHost(host); -} - -UpdatableTile* TiledLayer::TileAt(int i, int j) const { - return static_cast<UpdatableTile*>(tiler_->TileAt(i, j)); -} - -UpdatableTile* TiledLayer::CreateTile(int i, int j) { - CreateUpdaterIfNeeded(); - - scoped_ptr<UpdatableTile> tile( - UpdatableTile::Create(Updater()->CreateResource(ResourceManager()))); - tile->managed_resource()->SetDimensions(tiler_->tile_size(), texture_format_); - - UpdatableTile* added_tile = tile.get(); - tiler_->AddTile(tile.Pass(), i, j); - - added_tile->dirty_rect = tiler_->TileRect(added_tile); - - // Temporary diagnostic crash. - CHECK(added_tile); - CHECK(TileAt(i, j)); - - return added_tile; -} - -void TiledLayer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) { - InvalidateContentRect(LayerRectToContentRect(dirty_rect)); - ContentsScalingLayer::SetNeedsDisplayRect(dirty_rect); -} - -void TiledLayer::InvalidateContentRect(const gfx::Rect& content_rect) { - UpdateBounds(); - if (tiler_->is_empty() || content_rect.IsEmpty() || skips_draw_) - return; - - for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); - iter != tiler_->tiles().end(); - ++iter) { - UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); - DCHECK(tile); - // TODO(enne): This should not ever be null. - if (!tile) - continue; - gfx::Rect bound = tiler_->TileRect(tile); - bound.Intersect(content_rect); - tile->dirty_rect.Union(bound); - } -} - -// Returns true if tile is dirty and only part of it needs to be updated. -bool TiledLayer::TileOnlyNeedsPartialUpdate(UpdatableTile* tile) { - return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) && - tile->managed_resource()->have_backing_texture(); -} - -bool TiledLayer::UpdateTiles(int left, - int top, - int right, - int bottom, - ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion, - bool* updated) { - CreateUpdaterIfNeeded(); - - bool ignore_occlusions = !occlusion; - if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) { - failed_update_ = true; - return false; - } - - gfx::Rect update_rect; - gfx::Rect paint_rect; - MarkTilesForUpdate( - &update_rect, &paint_rect, left, top, right, bottom, ignore_occlusions); - - if (paint_rect.IsEmpty()) - return true; - - *updated = true; - UpdateTileTextures( - update_rect, paint_rect, left, top, right, bottom, queue, occlusion); - return true; -} - -void TiledLayer::MarkOcclusionsAndRequestTextures( - int left, - int top, - int right, - int bottom, - const OcclusionTracker<Layer>* occlusion) { - int occluded_tile_count = 0; - bool succeeded = true; - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = TileAt(i, j); - DCHECK(tile); // Did SetTexturePriorities get skipped? - // TODO(enne): This should not ever be null. - if (!tile) - continue; - // Did ResetUpdateState get skipped? Are we doing more than one occlusion - // pass? - DCHECK(!tile->occluded); - gfx::Rect visible_tile_rect = gfx::IntersectRects( - tiler_->tile_bounds(i, j), visible_content_rect()); - if (!draw_transform_is_animating() && occlusion && - occlusion->GetCurrentOcclusionForLayer(draw_transform()) - .IsOccluded(visible_tile_rect)) { - tile->occluded = true; - occluded_tile_count++; - } else { - succeeded &= tile->managed_resource()->RequestLate(); - } - } - } -} - -bool TiledLayer::HaveTexturesForTiles(int left, - int top, - int right, - int bottom, - bool ignore_occlusions) { - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = TileAt(i, j); - DCHECK(tile); // Did SetTexturePriorites get skipped? - // TODO(enne): This should not ever be null. - if (!tile) - continue; - - // Ensure the entire tile is dirty if we don't have the texture. - if (!tile->managed_resource()->have_backing_texture()) - tile->dirty_rect = tiler_->TileRect(tile); - - // If using occlusion and the visible region of the tile is occluded, - // don't reserve a texture or update the tile. - if (tile->occluded && !ignore_occlusions) - continue; - - if (!tile->managed_resource()->can_acquire_backing_texture()) - return false; - } - } - return true; -} - -void TiledLayer::MarkTilesForUpdate(gfx::Rect* update_rect, - gfx::Rect* paint_rect, - int left, - int top, - int right, - int bottom, - bool ignore_occlusions) { - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = TileAt(i, j); - DCHECK(tile); // Did SetTexturePriorites get skipped? - // TODO(enne): This should not ever be null. - if (!tile) - continue; - if (tile->occluded && !ignore_occlusions) - continue; - - // Prepare update rect from original dirty rects. - update_rect->Union(tile->dirty_rect); - - // TODO(reveman): Decide if partial update should be allowed based on cost - // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 - if (tile->is_dirty() && - !layer_tree_host()->AlwaysUsePartialTextureUpdates()) { - // If we get a partial update, we use the same texture, otherwise return - // the current texture backing, so we don't update visible textures - // non-atomically. If the current backing is in-use, it won't be - // deleted until after the commit as the texture manager will not allow - // deletion or recycling of in-use textures. - if (TileOnlyNeedsPartialUpdate(tile) && - layer_tree_host()->RequestPartialTextureUpdate()) { - tile->partial_update = true; - } else { - tile->dirty_rect = tiler_->TileRect(tile); - tile->managed_resource()->ReturnBackingTexture(); - } - } - - paint_rect->Union(tile->dirty_rect); - tile->MarkForUpdate(); - } - } -} - -void TiledLayer::UpdateTileTextures(const gfx::Rect& update_rect, - const gfx::Rect& paint_rect, - int left, - int top, - int right, - int bottom, - ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - // The update_rect should be in layer space. So we have to convert the - // paint_rect from content space to layer space. - float width_scale = 1 / draw_properties().contents_scale_x; - float height_scale = 1 / draw_properties().contents_scale_y; - update_rect_ = - gfx::ScaleToEnclosingRect(update_rect, width_scale, height_scale); - - // Calling PrepareToUpdate() calls into WebKit to paint, which may have the - // side effect of disabling compositing, which causes our reference to the - // texture updater to be deleted. However, we can't free the memory backing - // the SkCanvas until the paint finishes, so we grab a local reference here to - // hold the updater alive until the paint completes. - scoped_refptr<LayerUpdater> protector(Updater()); - Updater()->PrepareToUpdate(content_bounds(), - paint_rect, - tiler_->tile_size(), - 1.f / width_scale, - 1.f / height_scale); - - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = TileAt(i, j); - DCHECK(tile); // Did SetTexturePriorites get skipped? - // TODO(enne): This should not ever be null. - if (!tile) - continue; - - gfx::Rect tile_rect = tiler_->tile_bounds(i, j); - - // Use update_rect as the above loop copied the dirty rect for this frame - // to update_rect. - gfx::Rect dirty_rect = tile->update_rect; - if (dirty_rect.IsEmpty()) - continue; - - // source_rect starts as a full-sized tile with border texels included. - gfx::Rect source_rect = tiler_->TileRect(tile); - source_rect.Intersect(dirty_rect); - // Paint rect not guaranteed to line up on tile boundaries, so - // make sure that source_rect doesn't extend outside of it. - source_rect.Intersect(paint_rect); - - tile->update_rect = source_rect; - - if (source_rect.IsEmpty()) - continue; - - const gfx::Point anchor = tiler_->TileRect(tile).origin(); - - // Calculate tile-space rectangle to upload into. - gfx::Vector2d dest_offset = source_rect.origin() - anchor; - CHECK_GE(dest_offset.x(), 0); - CHECK_GE(dest_offset.y(), 0); - - // Offset from paint rectangle to this tile's dirty rectangle. - gfx::Vector2d paint_offset = source_rect.origin() - paint_rect.origin(); - CHECK_GE(paint_offset.x(), 0); - CHECK_GE(paint_offset.y(), 0); - CHECK_LE(paint_offset.x() + source_rect.width(), paint_rect.width()); - CHECK_LE(paint_offset.y() + source_rect.height(), paint_rect.height()); - - tile->updater_resource()->Update( - queue, source_rect, dest_offset, tile->partial_update); - } - } -} - -// This picks a small animated layer to be anything less than one viewport. This -// is specifically for page transitions which are viewport-sized layers. The -// extra tile of padding is due to these layers being slightly larger than the -// viewport in some cases. -bool TiledLayer::IsSmallAnimatedLayer() const { - if (!draw_transform_is_animating() && !screen_space_transform_is_animating()) - return false; - gfx::Size viewport_size = - layer_tree_host() ? layer_tree_host()->device_viewport_size() - : gfx::Size(); - gfx::Rect content_rect(content_bounds()); - return content_rect.width() <= - viewport_size.width() + tiler_->tile_size().width() && - content_rect.height() <= - viewport_size.height() + tiler_->tile_size().height(); -} - -namespace { -// TODO(epenner): Remove this and make this based on distance once distance can -// be calculated for offscreen layers. For now, prioritize all small animated -// layers after 512 pixels of pre-painting. -void SetPriorityForTexture(const gfx::Rect& visible_rect, - const gfx::Rect& tile_rect, - bool draws_to_root, - bool is_small_animated_layer, - PrioritizedResource* texture) { - int priority = PriorityCalculator::LowestPriority(); - if (!visible_rect.IsEmpty()) { - priority = PriorityCalculator::PriorityFromDistance( - visible_rect, tile_rect, draws_to_root); - } - - if (is_small_animated_layer) { - priority = PriorityCalculator::max_priority( - priority, PriorityCalculator::SmallAnimatedLayerMinPriority()); - } - - if (priority != PriorityCalculator::LowestPriority()) - texture->set_request_priority(priority); -} -} // namespace - -void TiledLayer::SetTexturePriorities(const PriorityCalculator& priority_calc) { - UpdateBounds(); - ResetUpdateState(); - UpdateScrollPrediction(); - - if (tiler_->has_empty_bounds()) - return; - - bool draws_to_root = !render_target()->parent(); - bool small_animated_layer = IsSmallAnimatedLayer(); - - // Minimally create the tiles in the desired pre-paint rect. - gfx::Rect create_tiles_rect = IdlePaintRect(); - if (small_animated_layer) - create_tiles_rect = gfx::Rect(content_bounds()); - if (!create_tiles_rect.IsEmpty()) { - int left, top, right, bottom; - tiler_->ContentRectToTileIndices( - create_tiles_rect, &left, &top, &right, &bottom); - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - if (!TileAt(i, j)) - CreateTile(i, j); - } - } - } - - // Now update priorities on all tiles we have in the layer, no matter where - // they are. - for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); - iter != tiler_->tiles().end(); - ++iter) { - UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); - // TODO(enne): This should not ever be null. - if (!tile) - continue; - gfx::Rect tile_rect = tiler_->TileRect(tile); - SetPriorityForTexture(predicted_visible_rect_, - tile_rect, - draws_to_root, - small_animated_layer, - tile->managed_resource()); - } -} - -SimpleEnclosedRegion TiledLayer::VisibleContentOpaqueRegion() const { - if (skips_draw_) - return SimpleEnclosedRegion(); - return Layer::VisibleContentOpaqueRegion(); -} - -void TiledLayer::ResetUpdateState() { - skips_draw_ = false; - failed_update_ = false; - - LayerTilingData::TileMap::const_iterator end = tiler_->tiles().end(); - for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); - iter != end; - ++iter) { - UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); - // TODO(enne): This should not ever be null. - if (!tile) - continue; - tile->ResetUpdateState(); - } -} - -namespace { -gfx::Rect ExpandRectByDelta(const gfx::Rect& rect, const gfx::Vector2d& delta) { - int width = rect.width() + std::abs(delta.x()); - int height = rect.height() + std::abs(delta.y()); - int x = rect.x() + ((delta.x() < 0) ? delta.x() : 0); - int y = rect.y() + ((delta.y() < 0) ? delta.y() : 0); - return gfx::Rect(x, y, width, height); -} -} - -void TiledLayer::UpdateScrollPrediction() { - // This scroll prediction is very primitive and should be replaced by a - // a recursive calculation on all layers which uses actual scroll/animation - // velocities. To insure this doesn't miss-predict, we only use it to predict - // the visible_rect if: - // - content_bounds() hasn't changed. - // - visible_rect.size() hasn't changed. - // These two conditions prevent rotations, scales, pinch-zooms etc. where - // the prediction would be incorrect. - gfx::Vector2d delta = visible_content_rect().CenterPoint() - - previous_visible_rect_.CenterPoint(); - predicted_scroll_ = -delta; - predicted_visible_rect_ = visible_content_rect(); - if (previous_content_bounds_ == content_bounds() && - previous_visible_rect_.size() == visible_content_rect().size()) { - // Only expand the visible rect in the major scroll direction, to prevent - // massive paints due to diagonal scrolls. - gfx::Vector2d major_scroll_delta = - (std::abs(delta.x()) > std::abs(delta.y())) ? - gfx::Vector2d(delta.x(), 0) : - gfx::Vector2d(0, delta.y()); - predicted_visible_rect_ = - ExpandRectByDelta(visible_content_rect(), major_scroll_delta); - - // Bound the prediction to prevent unbounded paints, and clamp to content - // bounds. - gfx::Rect bound = visible_content_rect(); - bound.Inset(-tiler_->tile_size().width() * kMaxPredictiveTilesCount, - -tiler_->tile_size().height() * kMaxPredictiveTilesCount); - bound.Intersect(gfx::Rect(content_bounds())); - predicted_visible_rect_.Intersect(bound); - } - previous_content_bounds_ = content_bounds(); - previous_visible_rect_ = visible_content_rect(); -} - -bool TiledLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - DCHECK(!skips_draw_ && !failed_update_); // Did ResetUpdateState get skipped? - - // Tiled layer always causes commits to wait for activation, as it does - // not support pending trees. - SetNextCommitWaitsForActivation(); - - bool updated = false; - - { - base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, - true); - - updated |= ContentsScalingLayer::Update(queue, occlusion); - UpdateBounds(); - } - - if (tiler_->has_empty_bounds() || !DrawsContent()) - return false; - - // Animation pre-paint. If the layer is small, try to paint it all - // immediately whether or not it is occluded, to avoid paint/upload - // hiccups while it is animating. - if (IsSmallAnimatedLayer()) { - int left, top, right, bottom; - tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()), - &left, - &top, - &right, - &bottom); - UpdateTiles(left, top, right, bottom, queue, nullptr, &updated); - if (updated) - return updated; - // This was an attempt to paint the entire layer so if we fail it's okay, - // just fallback on painting visible etc. below. - failed_update_ = false; - } - - if (predicted_visible_rect_.IsEmpty()) - return updated; - - // Visible painting. First occlude visible tiles and paint the non-occluded - // tiles. - int left, top, right, bottom; - tiler_->ContentRectToTileIndices( - predicted_visible_rect_, &left, &top, &right, &bottom); - MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); - skips_draw_ = !UpdateTiles( - left, top, right, bottom, queue, occlusion, &updated); - if (skips_draw_) - tiler_->reset(); - if (skips_draw_ || updated) - return true; - - // If we have already painting everything visible. Do some pre-painting while - // idle. - gfx::Rect idle_paint_content_rect = IdlePaintRect(); - if (idle_paint_content_rect.IsEmpty()) - return updated; - - // Prepaint anything that was occluded but inside the layer's visible region. - if (!UpdateTiles(left, top, right, bottom, queue, nullptr, &updated) || - updated) - return updated; - - int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom; - tiler_->ContentRectToTileIndices(idle_paint_content_rect, - &prepaint_left, - &prepaint_top, - &prepaint_right, - &prepaint_bottom); - - // Then expand outwards one row/column at a time until we find a dirty - // row/column to update. Increment along the major and minor scroll directions - // first. - gfx::Vector2d delta = -predicted_scroll_; - delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(), - delta.y() == 0 ? 1 : delta.y()); - gfx::Vector2d major_delta = - (std::abs(delta.x()) > std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) - : gfx::Vector2d(0, delta.y()); - gfx::Vector2d minor_delta = - (std::abs(delta.x()) <= std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) - : gfx::Vector2d(0, delta.y()); - gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta, - -minor_delta }; - for (int i = 0; i < 4; i++) { - if (deltas[i].y() > 0) { - while (bottom < prepaint_bottom) { - ++bottom; - if (!UpdateTiles( - left, bottom, right, bottom, queue, nullptr, &updated) || - updated) - return updated; - } - } - if (deltas[i].y() < 0) { - while (top > prepaint_top) { - --top; - if (!UpdateTiles(left, top, right, top, queue, nullptr, &updated) || - updated) - return updated; - } - } - if (deltas[i].x() < 0) { - while (left > prepaint_left) { - --left; - if (!UpdateTiles(left, top, left, bottom, queue, nullptr, &updated) || - updated) - return updated; - } - } - if (deltas[i].x() > 0) { - while (right < prepaint_right) { - ++right; - if (!UpdateTiles(right, top, right, bottom, queue, nullptr, &updated) || - updated) - return updated; - } - } - } - return updated; -} - -void TiledLayer::OnOutputSurfaceCreated() { - // Ensure that all textures are of the right format. - for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); - iter != tiler_->tiles().end(); - ++iter) { - UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); - if (!tile) - continue; - PrioritizedResource* resource = tile->managed_resource(); - resource->SetDimensions(resource->size(), texture_format_); - } -} - -bool TiledLayer::NeedsIdlePaint() { - // Don't trigger more paints if we failed (as we'll just fail again). - if (failed_update_ || visible_content_rect().IsEmpty() || - tiler_->has_empty_bounds() || !DrawsContent()) - return false; - - gfx::Rect idle_paint_content_rect = IdlePaintRect(); - if (idle_paint_content_rect.IsEmpty()) - return false; - - int left, top, right, bottom; - tiler_->ContentRectToTileIndices( - idle_paint_content_rect, &left, &top, &right, &bottom); - - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = TileAt(i, j); - DCHECK(tile); // Did SetTexturePriorities get skipped? - if (!tile) - continue; - - bool updated = !tile->update_rect.IsEmpty(); - bool can_acquire = - tile->managed_resource()->can_acquire_backing_texture(); - bool dirty = - tile->is_dirty() || !tile->managed_resource()->have_backing_texture(); - if (!updated && can_acquire && dirty) - return true; - } - } - return false; -} - -gfx::Rect TiledLayer::IdlePaintRect() { - // Don't inflate an empty rect. - if (visible_content_rect().IsEmpty()) - return gfx::Rect(); - - gfx::Rect prepaint_rect = visible_content_rect(); - prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns, - -tiler_->tile_size().height() * kPrepaintRows); - gfx::Rect content_rect(content_bounds()); - prepaint_rect.Intersect(content_rect); - - return prepaint_rect; -} - -} // namespace cc diff --git a/chromium/cc/layers/tiled_layer.h b/chromium/cc/layers/tiled_layer.h deleted file mode 100644 index 80697607ee6..00000000000 --- a/chromium/cc/layers/tiled_layer.h +++ /dev/null @@ -1,146 +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. - -#ifndef CC_LAYERS_TILED_LAYER_H_ -#define CC_LAYERS_TILED_LAYER_H_ - -#include "cc/base/cc_export.h" -#include "cc/layers/contents_scaling_layer.h" -#include "cc/resources/resource_format.h" -#include "cc/tiles/layer_tiling_data.h" - -namespace cc { -class LayerUpdater; -class PrioritizedResourceManager; -class PrioritizedResource; -class UpdatableTile; - -class CC_EXPORT TiledLayer : public ContentsScalingLayer { - public: - enum TilingOption { - ALWAYS_TILE, - NEVER_TILE, - AUTO_TILE, - }; - - // Layer implementation. - void SetIsMask(bool is_mask) override; - void PushPropertiesTo(LayerImpl* layer) override; - void ReduceMemoryUsage() override; - void SetNeedsDisplayRect(const gfx::Rect& dirty_rect) override; - void SetLayerTreeHost(LayerTreeHost* layer_tree_host) override; - void SetTexturePriorities(const PriorityCalculator& priority_calc) override; - SimpleEnclosedRegion VisibleContentOpaqueRegion() const override; - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; - void OnOutputSurfaceCreated() override; - - protected: - TiledLayer(); - ~TiledLayer() override; - - void UpdateTileSizeAndTilingOption(); - void UpdateBounds(); - - // Exposed to subclasses for testing. - void SetTileSize(const gfx::Size& size); - void SetTextureFormat(ResourceFormat texture_format) { - texture_format_ = texture_format; - } - void SetBorderTexelOption(LayerTilingData::BorderTexelOption option); - size_t NumPaintedTiles() { return tiler_->tiles().size(); } - - virtual LayerUpdater* Updater() const = 0; - virtual void CreateUpdaterIfNeeded() = 0; - - // Set invalidations to be potentially repainted during Update(). - void InvalidateContentRect(const gfx::Rect& content_rect); - - // Reset state on tiles that will be used for updating the layer. - void ResetUpdateState(); - - // After preparing an update, returns true if more painting is needed. - bool NeedsIdlePaint(); - gfx::Rect IdlePaintRect(); - - bool SkipsDraw() const { return skips_draw_; } - - bool HasDrawableContent() const override; - - // Virtual for testing - virtual PrioritizedResourceManager* ResourceManager(); - const LayerTilingData* TilerForTesting() const { return tiler_.get(); } - const PrioritizedResource* ResourceAtForTesting(int i, int j) const; - - private: - scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; - - void CreateTilerIfNeeded(); - void set_tiling_option(TilingOption tiling_option) { - tiling_option_ = tiling_option; - } - - bool TileOnlyNeedsPartialUpdate(UpdatableTile* tile); - bool TileNeedsBufferedUpdate(UpdatableTile* tile); - - void MarkOcclusionsAndRequestTextures( - int left, - int top, - int right, - int bottom, - const OcclusionTracker<Layer>* occlusion); - - bool UpdateTiles(int left, - int top, - int right, - int bottom, - ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion, - bool* did_paint); - bool HaveTexturesForTiles(int left, - int top, - int right, - int bottom, - bool ignore_occlusions); - void MarkTilesForUpdate(gfx::Rect* update_rect, - gfx::Rect* paint_rect, - int left, - int top, - int right, - int bottom, - bool ignore_occlusions); - void UpdateTileTextures(const gfx::Rect& update_rect, - const gfx::Rect& paint_rect, - int left, - int top, - int right, - int bottom, - ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion); - void UpdateScrollPrediction(); - - UpdatableTile* TileAt(int i, int j) const; - UpdatableTile* CreateTile(int i, int j); - - bool IsSmallAnimatedLayer() const; - - ResourceFormat texture_format_; - bool skips_draw_; - bool failed_update_; - - // Used for predictive painting. - gfx::Vector2d predicted_scroll_; - gfx::Rect predicted_visible_rect_; - gfx::Rect previous_visible_rect_; - gfx::Size previous_content_bounds_; - - TilingOption tiling_option_; - scoped_ptr<LayerTilingData> tiler_; - - DISALLOW_COPY_AND_ASSIGN(TiledLayer); -}; - -} // namespace cc - -#endif // CC_LAYERS_TILED_LAYER_H_ diff --git a/chromium/cc/layers/tiled_layer_impl.cc b/chromium/cc/layers/tiled_layer_impl.cc deleted file mode 100644 index 66aee5282c6..00000000000 --- a/chromium/cc/layers/tiled_layer_impl.cc +++ /dev/null @@ -1,324 +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/layers/tiled_layer_impl.h" - -#include "base/basictypes.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event_argument.h" -#include "cc/base/math_util.h" -#include "cc/base/simple_enclosed_region.h" -#include "cc/debug/debug_colors.h" -#include "cc/layers/append_quads_data.h" -#include "cc/quads/checkerboard_draw_quad.h" -#include "cc/quads/debug_border_draw_quad.h" -#include "cc/quads/solid_color_draw_quad.h" -#include "cc/quads/tile_draw_quad.h" -#include "cc/tiles/layer_tiling_data.h" -#include "cc/trees/layer_tree_impl.h" -#include "cc/trees/occlusion.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/geometry/quad_f.h" - -namespace cc { - -class DrawableTile : public LayerTilingData::Tile { - public: - static scoped_ptr<DrawableTile> Create() { - return make_scoped_ptr(new DrawableTile()); - } - - ResourceProvider::ResourceId resource_id() const { return resource_id_; } - void set_resource_id(ResourceProvider::ResourceId resource_id) { - resource_id_ = resource_id; - } - bool contents_swizzled() { return contents_swizzled_; } - void set_contents_swizzled(bool contents_swizzled) { - contents_swizzled_ = contents_swizzled; - } - - private: - DrawableTile() : resource_id_(0), contents_swizzled_(false) {} - - ResourceProvider::ResourceId resource_id_; - bool contents_swizzled_; - - DISALLOW_COPY_AND_ASSIGN(DrawableTile); -}; - -TiledLayerImpl::TiledLayerImpl(LayerTreeImpl* tree_impl, int id) - : TiledLayerImpl(tree_impl, id, new LayerImpl::SyncedScrollOffset) { -} - -TiledLayerImpl::TiledLayerImpl( - LayerTreeImpl* tree_impl, - int id, - scoped_refptr<LayerImpl::SyncedScrollOffset> synced_scroll_offset) - : LayerImpl(tree_impl, id, synced_scroll_offset), skips_draw_(true) { -} - -TiledLayerImpl::~TiledLayerImpl() { -} - -void TiledLayerImpl::GetContentsResourceId( - ResourceProvider::ResourceId* resource_id, - gfx::Size* resource_size) const { - // This function is only valid for single texture layers, e.g. masks. - DCHECK(tiler_); - // It's possible the mask layer is created but has no size or otherwise - // can't draw. - if (tiler_->num_tiles_x() == 0 || tiler_->num_tiles_y() == 0) { - *resource_id = 0; - return; - } - - // Any other number of tiles other than 0 or 1 is incorrect for masks. - DCHECK_EQ(tiler_->num_tiles_x(), 1); - DCHECK_EQ(tiler_->num_tiles_y(), 1); - - DrawableTile* tile = TileAt(0, 0); - *resource_id = tile ? tile->resource_id() : 0; - *resource_size = tiler_->tile_size(); -} - -bool TiledLayerImpl::HasTileAt(int i, int j) const { - return !!tiler_->TileAt(i, j); -} - -bool TiledLayerImpl::HasResourceIdForTileAt(int i, int j) const { - return HasTileAt(i, j) && TileAt(i, j)->resource_id(); -} - -DrawableTile* TiledLayerImpl::TileAt(int i, int j) const { - return static_cast<DrawableTile*>(tiler_->TileAt(i, j)); -} - -DrawableTile* TiledLayerImpl::CreateTile(int i, int j) { - scoped_ptr<DrawableTile> tile(DrawableTile::Create()); - DrawableTile* added_tile = tile.get(); - tiler_->AddTile(tile.Pass(), i, j); - - return added_tile; -} - -void TiledLayerImpl::GetDebugBorderProperties(SkColor* color, - float* width) const { - *color = DebugColors::TiledContentLayerBorderColor(); - *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl()); -} - -scoped_ptr<LayerImpl> TiledLayerImpl::CreateLayerImpl( - LayerTreeImpl* tree_impl) { - return TiledLayerImpl::Create(tree_impl, id(), synced_scroll_offset()); -} - -void TiledLayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { - LayerImpl::AsValueInto(state); - MathUtil::AddToTracedValue("invalidation", update_rect(), state); -} - -size_t TiledLayerImpl::GPUMemoryUsageInBytes() const { - size_t amount = 0; - const size_t kMemoryUsagePerTileInBytes = - 4 * tiler_->tile_size().width() * tiler_->tile_size().height(); - for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); - iter != tiler_->tiles().end(); - ++iter) { - const DrawableTile* tile = static_cast<DrawableTile*>(iter->second); - DCHECK(tile); - if (!tile->resource_id()) - continue; - amount += kMemoryUsagePerTileInBytes; - } - return amount; -} - -void TiledLayerImpl::PushPropertiesTo(LayerImpl* layer) { - LayerImpl::PushPropertiesTo(layer); - - TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer); - - tiled_layer->set_skips_draw(skips_draw_); - tiled_layer->SetTilingData(*tiler_); - - for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); - iter != tiler_->tiles().end(); - ++iter) { - int i = iter->first.first; - int j = iter->first.second; - DrawableTile* tile = static_cast<DrawableTile*>(iter->second); - DCHECK(tile); - tiled_layer->PushTileProperties(i, - j, - tile->resource_id(), - tile->contents_swizzled()); - } -} - -bool TiledLayerImpl::WillDraw(DrawMode draw_mode, - ResourceProvider* resource_provider) { - if (!tiler_ || tiler_->has_empty_bounds() || - visible_content_rect().IsEmpty() || - draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) - return false; - return LayerImpl::WillDraw(draw_mode, resource_provider); -} - -void TiledLayerImpl::AppendQuads(RenderPass* render_pass, - AppendQuadsData* append_quads_data) { - DCHECK(tiler_); - DCHECK(!tiler_->has_empty_bounds()); - DCHECK(!visible_content_rect().IsEmpty()); - - gfx::Rect content_rect = visible_content_rect(); - SharedQuadState* shared_quad_state = - render_pass->CreateAndAppendSharedQuadState(); - PopulateSharedQuadState(shared_quad_state); - - AppendDebugBorderQuad( - render_pass, content_bounds(), shared_quad_state, append_quads_data); - - int left, top, right, bottom; - tiler_->ContentRectToTileIndices(content_rect, &left, &top, &right, &bottom); - - if (ShowDebugBorders()) { - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - DrawableTile* tile = TileAt(i, j); - gfx::Rect tile_rect = tiler_->tile_bounds(i, j); - gfx::Rect visible_tile_rect = tile_rect; - SkColor border_color; - float border_width; - - if (skips_draw_ || !tile || !tile->resource_id()) { - border_color = DebugColors::MissingTileBorderColor(); - border_width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); - } else { - border_color = DebugColors::HighResTileBorderColor(); - border_width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); - } - DebugBorderDrawQuad* debug_border_quad = - render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>(); - debug_border_quad->SetNew(shared_quad_state, - tile_rect, - visible_tile_rect, - border_color, - border_width); - } - } - } - - if (skips_draw_) - return; - - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - DrawableTile* tile = TileAt(i, j); - gfx::Rect tile_rect = tiler_->tile_bounds(i, j); - gfx::Rect display_rect = tile_rect; - tile_rect.Intersect(content_rect); - - // Skip empty tiles. - if (tile_rect.IsEmpty()) - continue; - - gfx::Rect visible_tile_rect = - draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( - tile_rect); - if (visible_tile_rect.IsEmpty()) - continue; - - if (!tile || !tile->resource_id()) { - SkColor checker_color; - if (ShowDebugBorders()) { - checker_color = - tile ? DebugColors::InvalidatedTileCheckerboardColor() - : DebugColors::EvictedTileCheckerboardColor(); - } else { - checker_color = DebugColors::DefaultCheckerboardColor(); - } - - CheckerboardDrawQuad* checkerboard_quad = - render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>(); - checkerboard_quad->SetNew(shared_quad_state, tile_rect, - visible_tile_rect, checker_color, 1.f); - append_quads_data->num_missing_tiles++; - continue; - } - - gfx::Rect tile_opaque_rect = contents_opaque() ? tile_rect : gfx::Rect(); - - // Keep track of how the top left has moved, so the texture can be - // offset the same amount. - gfx::Vector2d display_offset = tile_rect.origin() - display_rect.origin(); - gfx::Vector2d texture_offset = - tiler_->texture_offset(i, j) + display_offset; - gfx::RectF tex_coord_rect = gfx::RectF(tile_rect.size()) + texture_offset; - - float tile_width = static_cast<float>(tiler_->tile_size().width()); - float tile_height = static_cast<float>(tiler_->tile_size().height()); - gfx::Size texture_size(tile_width, tile_height); - - TileDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TileDrawQuad>(); - quad->SetNew(shared_quad_state, - tile_rect, - tile_opaque_rect, - visible_tile_rect, - tile->resource_id(), - tex_coord_rect, - texture_size, - tile->contents_swizzled(), - false); - ValidateQuadResources(quad); - } - } -} - -void TiledLayerImpl::SetTilingData(const LayerTilingData& tiler) { - if (tiler_) { - tiler_->reset(); - } else { - tiler_ = LayerTilingData::Create(tiler.tile_size(), - tiler.has_border_texels() - ? LayerTilingData::HAS_BORDER_TEXELS - : LayerTilingData::NO_BORDER_TEXELS); - } - *tiler_ = tiler; -} - -void TiledLayerImpl::PushTileProperties( - int i, - int j, - ResourceProvider::ResourceId resource_id, - bool contents_swizzled) { - DrawableTile* tile = TileAt(i, j); - if (!tile) - tile = CreateTile(i, j); - tile->set_resource_id(resource_id); - tile->set_contents_swizzled(contents_swizzled); -} - -void TiledLayerImpl::PushInvalidTile(int i, int j) { - DrawableTile* tile = TileAt(i, j); - if (!tile) - tile = CreateTile(i, j); - tile->set_resource_id(0); - tile->set_contents_swizzled(false); -} - -SimpleEnclosedRegion TiledLayerImpl::VisibleContentOpaqueRegion() const { - if (skips_draw_) - return SimpleEnclosedRegion(); - return LayerImpl::VisibleContentOpaqueRegion(); -} - -void TiledLayerImpl::ReleaseResources() { - tiler_->reset(); -} - -const char* TiledLayerImpl::LayerTypeAsString() const { - return "cc::TiledLayerImpl"; -} - -} // namespace cc diff --git a/chromium/cc/layers/tiled_layer_impl.h b/chromium/cc/layers/tiled_layer_impl.h deleted file mode 100644 index c292790d0a5..00000000000 --- a/chromium/cc/layers/tiled_layer_impl.h +++ /dev/null @@ -1,87 +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. - -#ifndef CC_LAYERS_TILED_LAYER_IMPL_H_ -#define CC_LAYERS_TILED_LAYER_IMPL_H_ - -#include <string> - -#include "cc/base/cc_export.h" -#include "cc/layers/layer_impl.h" - -namespace cc { - -class LayerTilingData; -class DrawableTile; - -class CC_EXPORT TiledLayerImpl : public LayerImpl { - public: - static scoped_ptr<TiledLayerImpl> Create(LayerTreeImpl* tree_impl, int id) { - return make_scoped_ptr( - new TiledLayerImpl(tree_impl, id, new LayerImpl::SyncedScrollOffset)); - } - static scoped_ptr<TiledLayerImpl> Create( - LayerTreeImpl* tree_impl, - int id, - scoped_refptr<LayerImpl::SyncedScrollOffset> synced_scroll_offset) { - return make_scoped_ptr( - new TiledLayerImpl(tree_impl, id, synced_scroll_offset)); - } - ~TiledLayerImpl() override; - - scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; - void PushPropertiesTo(LayerImpl* layer) override; - - bool WillDraw(DrawMode draw_mode, - ResourceProvider* resource_provider) override; - void AppendQuads(RenderPass* render_pass, - AppendQuadsData* append_quads_data) override; - - void GetContentsResourceId(ResourceProvider::ResourceId* resource_id, - gfx::Size* resource_size) const override; - - void set_skips_draw(bool skips_draw) { skips_draw_ = skips_draw; } - void SetTilingData(const LayerTilingData& tiler); - void PushTileProperties(int i, - int j, - ResourceProvider::ResourceId resource, - bool contents_swizzled); - void PushInvalidTile(int i, int j); - - SimpleEnclosedRegion VisibleContentOpaqueRegion() const override; - void ReleaseResources() override; - - const LayerTilingData* TilingForTesting() const { return tiler_.get(); } - - size_t GPUMemoryUsageInBytes() const override; - - protected: - TiledLayerImpl(LayerTreeImpl* tree_impl, int id); - TiledLayerImpl( - LayerTreeImpl* tree_impl, - int id, - scoped_refptr<LayerImpl::SyncedScrollOffset> synced_scroll_offset); - // Exposed for testing. - bool HasTileAt(int i, int j) const; - bool HasResourceIdForTileAt(int i, int j) const; - - void GetDebugBorderProperties(SkColor* color, float* width) const override; - void AsValueInto(base::trace_event::TracedValue* dict) const override; - - private: - const char* LayerTypeAsString() const override; - - DrawableTile* TileAt(int i, int j) const; - DrawableTile* CreateTile(int i, int j); - - bool skips_draw_; - - scoped_ptr<LayerTilingData> tiler_; - - DISALLOW_COPY_AND_ASSIGN(TiledLayerImpl); -}; - -} // namespace cc - -#endif // CC_LAYERS_TILED_LAYER_IMPL_H_ diff --git a/chromium/cc/layers/tiled_layer_impl_unittest.cc b/chromium/cc/layers/tiled_layer_impl_unittest.cc deleted file mode 100644 index 6e662568bcd..00000000000 --- a/chromium/cc/layers/tiled_layer_impl_unittest.cc +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright 2012 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/layers/tiled_layer_impl.h" - -#include "cc/layers/append_quads_data.h" -#include "cc/quads/tile_draw_quad.h" -#include "cc/test/fake_impl_proxy.h" -#include "cc/test/fake_layer_tree_host_impl.h" -#include "cc/test/fake_output_surface.h" -#include "cc/test/layer_test_common.h" -#include "cc/test/test_task_graph_runner.h" -#include "cc/tiles/layer_tiling_data.h" -#include "cc/trees/single_thread_proxy.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace cc { -namespace { - -class TiledLayerImplTest : public testing::Test { - public: - TiledLayerImplTest() - : host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_) { - host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()); - } - - scoped_ptr<TiledLayerImpl> CreateLayerNoTiles( - const gfx::Size& tile_size, - const gfx::Size& layer_size, - LayerTilingData::BorderTexelOption border_texels) { - scoped_ptr<TiledLayerImpl> layer = - TiledLayerImpl::Create(host_impl_.active_tree(), 1); - scoped_ptr<LayerTilingData> tiler = - LayerTilingData::Create(tile_size, border_texels); - tiler->SetTilingSize(layer_size); - layer->SetTilingData(*tiler); - layer->set_skips_draw(false); - layer->draw_properties().visible_content_rect = - gfx::Rect(layer_size); - layer->draw_properties().opacity = 1; - layer->SetBounds(layer_size); - layer->SetContentBounds(layer_size); - layer->SetHasRenderSurface(true); - layer->draw_properties().render_target = layer.get(); - return layer.Pass(); - } - - // Create a default tiled layer with textures for all tiles and a default - // visibility of the entire layer size. - scoped_ptr<TiledLayerImpl> CreateLayer( - const gfx::Size& tile_size, - const gfx::Size& layer_size, - LayerTilingData::BorderTexelOption border_texels) { - scoped_ptr<TiledLayerImpl> layer = - CreateLayerNoTiles(tile_size, layer_size, border_texels); - - for (int i = 0; i < layer->TilingForTesting()->num_tiles_x(); ++i) { - for (int j = 0; j < layer->TilingForTesting()->num_tiles_y(); ++j) { - ResourceProvider::ResourceId resource_id = - host_impl_.resource_provider()->CreateResource( - gfx::Size(1, 1), GL_CLAMP_TO_EDGE, - ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); - layer->PushTileProperties(i, j, resource_id, false); - } - } - - return layer.Pass(); - } - - void GetQuads(RenderPass* render_pass, - const gfx::Size& tile_size, - const gfx::Size& layer_size, - LayerTilingData::BorderTexelOption border_texel_option, - const gfx::Rect& visible_content_rect) { - scoped_ptr<TiledLayerImpl> layer = - CreateLayer(tile_size, layer_size, border_texel_option); - layer->draw_properties().visible_content_rect = visible_content_rect; - layer->SetBounds(layer_size); - - AppendQuadsData data; - layer->AppendQuads(render_pass, &data); - } - - protected: - FakeImplProxy proxy_; - TestSharedBitmapManager shared_bitmap_manager_; - TestTaskGraphRunner task_graph_runner_; - FakeLayerTreeHostImpl host_impl_; -}; - -TEST_F(TiledLayerImplTest, EmptyQuadList) { - gfx::Size tile_size(90, 90); - int num_tiles_x = 8; - int num_tiles_y = 4; - gfx::Size layer_size(tile_size.width() * num_tiles_x, - tile_size.height() * num_tiles_y); - - // Verify default layer does creates quads - { - scoped_ptr<TiledLayerImpl> layer = - CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS); - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - - AppendQuadsData data; - EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, nullptr)); - layer->AppendQuads(render_pass.get(), &data); - layer->DidDraw(nullptr); - unsigned num_tiles = num_tiles_x * num_tiles_y; - EXPECT_EQ(render_pass->quad_list.size(), num_tiles); - } - - // Layer with empty visible layer rect produces no quads - { - scoped_ptr<TiledLayerImpl> layer = - CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS); - layer->draw_properties().visible_content_rect = gfx::Rect(); - - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - - EXPECT_FALSE(layer->WillDraw(DRAW_MODE_HARDWARE, nullptr)); - } - - // Layer with non-intersecting visible layer rect produces no quads - { - scoped_ptr<TiledLayerImpl> layer = - CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS); - - gfx::Rect outside_bounds(-100, -100, 50, 50); - layer->draw_properties().visible_content_rect = outside_bounds; - - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - - AppendQuadsData data; - EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, nullptr)); - layer->AppendQuads(render_pass.get(), &data); - layer->DidDraw(nullptr); - EXPECT_EQ(render_pass->quad_list.size(), 0u); - } - - // Layer with skips draw produces no quads - { - scoped_ptr<TiledLayerImpl> layer = - CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS); - layer->set_skips_draw(true); - - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - - AppendQuadsData data; - layer->AppendQuads(render_pass.get(), &data); - EXPECT_EQ(render_pass->quad_list.size(), 0u); - } -} - -TEST_F(TiledLayerImplTest, Checkerboarding) { - gfx::Size tile_size(10, 10); - int num_tiles_x = 2; - int num_tiles_y = 2; - gfx::Size layer_size(tile_size.width() * num_tiles_x, - tile_size.height() * num_tiles_y); - - scoped_ptr<TiledLayerImpl> layer = - CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS); - - // No checkerboarding - { - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - - AppendQuadsData data; - layer->AppendQuads(render_pass.get(), &data); - EXPECT_EQ(render_pass->quad_list.size(), 4u); - EXPECT_EQ(0u, data.num_missing_tiles); - - for (const auto& quad : render_pass->quad_list) - EXPECT_EQ(quad->material, DrawQuad::TILED_CONTENT); - } - - for (int i = 0; i < num_tiles_x; ++i) - for (int j = 0; j < num_tiles_y; ++j) - layer->PushTileProperties(i, j, 0, false); - - // All checkerboarding - { - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - - AppendQuadsData data; - layer->AppendQuads(render_pass.get(), &data); - EXPECT_LT(0u, data.num_missing_tiles); - EXPECT_EQ(render_pass->quad_list.size(), 4u); - for (const auto& quad : render_pass->quad_list) - EXPECT_NE(quad->material, DrawQuad::TILED_CONTENT); - } -} - -// Test with both border texels and without. -#define WITH_AND_WITHOUT_BORDER_TEST(text_fixture_name) \ - TEST_F(TiledLayerImplBorderTest, text_fixture_name##NoBorders) { \ - text_fixture_name(LayerTilingData::NO_BORDER_TEXELS); \ - } \ - TEST_F(TiledLayerImplBorderTest, text_fixture_name##HasBorders) { \ - text_fixture_name(LayerTilingData::HAS_BORDER_TEXELS); \ - } - -class TiledLayerImplBorderTest : public TiledLayerImplTest { - public: - void CoverageVisibleRectOnTileBoundaries( - LayerTilingData::BorderTexelOption borders) { - gfx::Size layer_size(1000, 1000); - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - GetQuads(render_pass.get(), - gfx::Size(100, 100), - layer_size, - borders, - gfx::Rect(layer_size)); - LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list, - gfx::Rect(layer_size)); - } - - void CoverageVisibleRectIntersectsTiles( - LayerTilingData::BorderTexelOption borders) { - // This rect intersects the middle 3x3 of the 5x5 tiles. - gfx::Point top_left(65, 73); - gfx::Point bottom_right(182, 198); - gfx::Rect visible_content_rect = gfx::BoundingRect(top_left, bottom_right); - - gfx::Size layer_size(250, 250); - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - GetQuads(render_pass.get(), - gfx::Size(50, 50), - gfx::Size(250, 250), - LayerTilingData::NO_BORDER_TEXELS, - visible_content_rect); - LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list, - visible_content_rect); - } - - void CoverageVisibleRectIntersectsBounds( - LayerTilingData::BorderTexelOption borders) { - gfx::Size layer_size(220, 210); - gfx::Rect visible_content_rect(layer_size); - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - GetQuads(render_pass.get(), - gfx::Size(100, 100), - layer_size, - LayerTilingData::NO_BORDER_TEXELS, - visible_content_rect); - LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list, - visible_content_rect); - } -}; -WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries); - -WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles); - -WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds); - -TEST_F(TiledLayerImplTest, TextureInfoForLayerNoBorders) { - gfx::Size tile_size(50, 50); - gfx::Size layer_size(250, 250); - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); - GetQuads(render_pass.get(), - tile_size, - layer_size, - LayerTilingData::NO_BORDER_TEXELS, - gfx::Rect(layer_size)); - - for (auto iter = render_pass->quad_list.cbegin(); - iter != render_pass->quad_list.cend(); - ++iter) { - const TileDrawQuad* quad = TileDrawQuad::MaterialCast(*iter); - - EXPECT_NE(0u, quad->resource_id) << LayerTestCommon::quad_string - << iter.index(); - EXPECT_EQ(gfx::RectF(gfx::PointF(), tile_size), quad->tex_coord_rect) - << LayerTestCommon::quad_string << iter.index(); - EXPECT_EQ(tile_size, quad->texture_size) << LayerTestCommon::quad_string - << iter.index(); - } -} - -TEST_F(TiledLayerImplTest, GPUMemoryUsage) { - gfx::Size tile_size(20, 30); - int num_tiles_x = 12; - int num_tiles_y = 32; - gfx::Size layer_size(tile_size.width() * num_tiles_x, - tile_size.height() * num_tiles_y); - - scoped_ptr<TiledLayerImpl> layer = CreateLayerNoTiles( - tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS); - - EXPECT_EQ(layer->GPUMemoryUsageInBytes(), 0u); - - ResourceProvider::ResourceId resource_id = 1; - layer->PushTileProperties(0, 1, resource_id++, false); - layer->PushTileProperties(2, 3, resource_id++, false); - layer->PushTileProperties(2, 0, resource_id++, false); - - EXPECT_EQ( - layer->GPUMemoryUsageInBytes(), - static_cast<size_t>(3 * 4 * tile_size.width() * tile_size.height())); - - ResourceProvider::ResourceId empty_resource(0); - layer->PushTileProperties(0, 1, empty_resource, false); - layer->PushTileProperties(2, 3, empty_resource, false); - layer->PushTileProperties(2, 0, empty_resource, false); - - EXPECT_EQ(layer->GPUMemoryUsageInBytes(), 0u); -} - -TEST_F(TiledLayerImplTest, EmptyMask) { - gfx::Size tile_size(20, 20); - gfx::Size layer_size(0, 0); - scoped_ptr<TiledLayerImpl> layer = - CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS); - - ResourceProvider::ResourceId mask_resource_id; - gfx::Size mask_texture_size; - layer->GetContentsResourceId(&mask_resource_id, &mask_texture_size); - EXPECT_EQ(0u, mask_resource_id); - EXPECT_EQ(0, layer->TilingForTesting()->num_tiles_x()); - EXPECT_EQ(0, layer->TilingForTesting()->num_tiles_y()); -} - -TEST_F(TiledLayerImplTest, Occlusion) { - gfx::Size tile_size(100, 100); - gfx::Size layer_bounds(1000, 1000); - gfx::Size viewport_size(1000, 1000); - - LayerTestCommon::LayerImplTest impl; - - TiledLayerImpl* tiled_layer = impl.AddChildToRoot<TiledLayerImpl>(); - tiled_layer->SetBounds(layer_bounds); - tiled_layer->SetContentBounds(layer_bounds); - tiled_layer->SetDrawsContent(true); - tiled_layer->set_skips_draw(false); - - scoped_ptr<LayerTilingData> tiler = - LayerTilingData::Create(tile_size, LayerTilingData::NO_BORDER_TEXELS); - tiler->SetTilingSize(layer_bounds); - tiled_layer->SetTilingData(*tiler); - - for (int i = 0; i < tiled_layer->TilingForTesting()->num_tiles_x(); ++i) { - for (int j = 0; j < tiled_layer->TilingForTesting()->num_tiles_y(); ++j) { - ResourceProvider::ResourceId resource_id = - impl.resource_provider()->CreateResource( - gfx::Size(1, 1), GL_CLAMP_TO_EDGE, - ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); - tiled_layer->PushTileProperties(i, j, resource_id, false); - } - } - - impl.CalcDrawProps(viewport_size); - - { - SCOPED_TRACE("No occlusion"); - gfx::Rect occluded; - impl.AppendQuadsWithOcclusion(tiled_layer, occluded); - - LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), - gfx::Rect(layer_bounds)); - EXPECT_EQ(100u, impl.quad_list().size()); - } - - { - SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(tiled_layer->visible_content_rect()); - impl.AppendQuadsWithOcclusion(tiled_layer, occluded); - - LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); - EXPECT_EQ(impl.quad_list().size(), 0u); - } - - { - SCOPED_TRACE("Partial occlusion"); - gfx::Rect occluded(150, 0, 200, 1000); - impl.AppendQuadsWithOcclusion(tiled_layer, occluded); - - size_t partially_occluded_count = 0; - LayerTestCommon::VerifyQuadsAreOccluded( - impl.quad_list(), occluded, &partially_occluded_count); - // The layer outputs one quad, which is partially occluded. - EXPECT_EQ(100u - 10u, impl.quad_list().size()); - EXPECT_EQ(10u + 10u, partially_occluded_count); - } -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/layers/tiled_layer_unittest.cc b/chromium/cc/layers/tiled_layer_unittest.cc deleted file mode 100644 index 7dbab998d1d..00000000000 --- a/chromium/cc/layers/tiled_layer_unittest.cc +++ /dev/null @@ -1,1762 +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/layers/tiled_layer.h" - -#include <limits> -#include <vector> - -#include "base/location.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "cc/resources/bitmap_content_layer_updater.h" -#include "cc/resources/layer_painter.h" -#include "cc/resources/prioritized_resource_manager.h" -#include "cc/resources/resource_update_controller.h" -#include "cc/test/animation_test_common.h" -#include "cc/test/fake_layer_tree_host_client.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_proxy.h" -#include "cc/test/geometry_test_utils.h" -#include "cc/test/test_shared_bitmap_manager.h" -#include "cc/test/tiled_layer_test_common.h" -#include "cc/trees/occlusion_tracker.h" -#include "cc/trees/single_thread_proxy.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/transform.h" - -namespace cc { -namespace { - -class TestOcclusionTracker : public OcclusionTracker<Layer> { - public: - TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) { - stack_.push_back(StackObject()); - } - - void SetRenderTarget(Layer* render_target) { - stack_.back().target = render_target; - } - - void SetOcclusion(const SimpleEnclosedRegion& occlusion) { - stack_.back().occlusion_from_inside_target = occlusion; - } -}; - -class SynchronousOutputSurfaceClient : public FakeLayerTreeHostClient { - public: - SynchronousOutputSurfaceClient() - : FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D) {} - - bool EnsureOutputSurfaceCreated() { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, run_loop_.QuitClosure(), base::TimeDelta::FromSeconds(5)); - run_loop_.Run(); - return output_surface_created_; - } - - void DidInitializeOutputSurface() override { - FakeLayerTreeHostClient::DidInitializeOutputSurface(); - output_surface_created_ = true; - run_loop_.Quit(); - } - - void DidFailToInitializeOutputSurface() override { - FakeLayerTreeHostClient::DidFailToInitializeOutputSurface(); - output_surface_created_ = false; - run_loop_.Quit(); - } - - private: - bool output_surface_created_; - base::RunLoop run_loop_; -}; - -class TiledLayerTest : public testing::Test { - public: - TiledLayerTest() - : proxy_(nullptr), - output_surface_(FakeOutputSurface::Create3d()), - queue_(make_scoped_ptr(new ResourceUpdateQueue)), - impl_thread_("ImplThread"), - occlusion_(nullptr) { - settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max(); - settings_.layer_transforms_should_scale_layer_contents = true; - settings_.impl_side_painting = false; - settings_.verify_property_trees = false; - } - - void SetUp() override { - impl_thread_.Start(); - shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - LayerTreeHost::InitParams params; - params.client = &synchronous_output_surface_client_; - params.shared_bitmap_manager = shared_bitmap_manager_.get(); - params.settings = &settings_; - params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); - - layer_tree_host_ = - LayerTreeHost::CreateThreaded(impl_thread_.task_runner(), ¶ms); - synchronous_output_surface_client_.SetLayerTreeHost(layer_tree_host_.get()); - proxy_ = layer_tree_host_->proxy(); - resource_manager_ = PrioritizedResourceManager::Create(proxy_); - layer_tree_host_->SetLayerTreeHostClientReady(); - CHECK(synchronous_output_surface_client_.EnsureOutputSurfaceCreated()); - - layer_tree_host_->SetRootLayer(Layer::Create()); - - CHECK(output_surface_->BindToClient(&output_surface_client_)); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(proxy_); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - nullptr, - nullptr, - 0, - false, - 1); - host_impl_ = make_scoped_ptr(new FakeLayerTreeHostImpl( - proxy_, shared_bitmap_manager_.get(), nullptr)); - } - - ~TiledLayerTest() override { - ResourceManagerClearAllMemory(resource_manager_.get(), - resource_provider_.get()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(proxy_); - resource_provider_ = nullptr; - host_impl_ = nullptr; - } - - void ResourceManagerClearAllMemory( - PrioritizedResourceManager* resource_manager, - ResourceProvider* resource_provider) { - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(proxy_); - resource_manager->ClearAllMemory(resource_provider); - resource_manager->ReduceMemory(resource_provider); - } - resource_manager->UnlinkAndClearEvictedBackings(); - } - - void UpdateTextures() { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(proxy_); - DCHECK(queue_); - scoped_ptr<ResourceUpdateController> update_controller = - ResourceUpdateController::Create(nullptr, - proxy_->ImplThreadTaskRunner(), - queue_.Pass(), - resource_provider_.get()); - update_controller->Finalize(); - queue_ = make_scoped_ptr(new ResourceUpdateQueue); - } - - void LayerPushPropertiesTo(FakeTiledLayer* layer, - FakeTiledLayerImpl* layer_impl) { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(proxy_); - layer->PushPropertiesTo(layer_impl); - layer->ResetNumDependentsNeedPushProperties(); - } - - void LayerUpdate(FakeTiledLayer* layer, TestOcclusionTracker* occluded) { - DebugScopedSetMainThread main_thread(proxy_); - layer->Update(queue_.get(), occluded); - } - - void CalcDrawProps(RenderSurfaceLayerList* render_surface_layer_list) { - if (occlusion_) - occlusion_->SetRenderTarget(layer_tree_host_->root_layer()); - - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - layer_tree_host_->root_layer(), - layer_tree_host_->device_viewport_size(), - render_surface_layer_list); - inputs.device_scale_factor = layer_tree_host_->device_scale_factor(); - inputs.max_texture_size = - layer_tree_host_->GetRendererCapabilities().max_texture_size; - inputs.can_adjust_raster_scales = true; - inputs.verify_property_trees = false; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - } - - bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1, - const scoped_ptr<FakeTiledLayerImpl>& layer_impl1) { - scoped_refptr<FakeTiledLayer> layer2; - scoped_ptr<FakeTiledLayerImpl> layer_impl2; - return UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2); - } - - bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1, - const scoped_ptr<FakeTiledLayerImpl>& layer_impl1, - const scoped_refptr<FakeTiledLayer>& layer2, - const scoped_ptr<FakeTiledLayerImpl>& layer_impl2) { - // Get textures - resource_manager_->ClearPriorities(); - if (layer1.get()) - layer1->SetTexturePriorities(priority_calculator_); - if (layer2.get()) - layer2->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - - // Save paint properties - if (layer1.get()) - layer1->SavePaintProperties(); - if (layer2.get()) - layer2->SavePaintProperties(); - - // Update content - if (layer1.get()) - layer1->Update(queue_.get(), occlusion_); - if (layer2.get()) - layer2->Update(queue_.get(), occlusion_); - - bool needs_update = false; - if (layer1.get()) - needs_update |= layer1->NeedsIdlePaint(); - if (layer2.get()) - needs_update |= layer2->NeedsIdlePaint(); - - // Update textures and push. - UpdateTextures(); - if (layer1.get()) - LayerPushPropertiesTo(layer1.get(), layer_impl1.get()); - if (layer2.get()) - LayerPushPropertiesTo(layer2.get(), layer_impl2.get()); - - return needs_update; - } - - public: - Proxy* proxy_; - LayerTreeSettings settings_; - FakeOutputSurfaceClient output_surface_client_; - scoped_ptr<OutputSurface> output_surface_; - scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; - scoped_ptr<ResourceProvider> resource_provider_; - scoped_ptr<ResourceUpdateQueue> queue_; - PriorityCalculator priority_calculator_; - base::Thread impl_thread_; - SynchronousOutputSurfaceClient synchronous_output_surface_client_; - scoped_ptr<LayerTreeHost> layer_tree_host_; - scoped_ptr<FakeLayerTreeHostImpl> host_impl_; - scoped_ptr<PrioritizedResourceManager> resource_manager_; - TestOcclusionTracker* occlusion_; -}; - -TEST_F(TiledLayerTest, PushDirtyTiles) { - layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); - - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100, so this invalidates and then paints two tiles. - layer->SetBounds(gfx::Size(100, 200)); - CalcDrawProps(&render_surface_layer_list); - UpdateAndPush(layer, layer_impl); - - // We should have both tiles on the impl side. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); - - // Invalidates both tiles, but then only update one of them. - layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 200)); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); - UpdateAndPush(layer, layer_impl); - - // We should only have the first tile since the other tile was invalidated but - // not painted. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); -} - -TEST_F(TiledLayerTest, Scale) { - layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); - - layer_tree_host_->SetDeviceScaleFactor(1.5); - - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - layer->SetBounds(gfx::Size(100, 200)); - CalcDrawProps(&render_surface_layer_list); - - // Change the width so that it doesn't divide cleanly by the scale. - layer->SetBounds(gfx::Size(101, 200)); - UpdateAndPush(layer, layer_impl); - - EXPECT_EQ(1.5, layer->fake_layer_updater()->last_contents_width_scale()); -} - -TEST_F(TiledLayerTest, PushOccludedDirtyTiles) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - TestOcclusionTracker occluded; - occlusion_ = &occluded; - layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); - - layer_tree_host_->root_layer()->AddChild(layer); - - { - RenderSurfaceLayerList render_surface_layer_list; - - // The tile size is 100x100, so this invalidates and then paints two tiles. - layer->SetBounds(gfx::Size(100, 200)); - CalcDrawProps(&render_surface_layer_list); - UpdateAndPush(layer, layer_impl); - - // We should have both tiles on the impl side. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); - } - - { - RenderSurfaceLayerList render_surface_layer_list; - - // Invalidates part of the top tile... - layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50)); - // ....but the area is occluded. - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50))); - CalcDrawProps(&render_surface_layer_list); - UpdateAndPush(layer, layer_impl); - - // We should still have both tiles, as part of the top tile is still - // unoccluded. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); - } -} - -TEST_F(TiledLayerTest, PushDeletedTiles) { - layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); - - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100, so this invalidates and then paints two tiles. - layer->SetBounds(gfx::Size(100, 200)); - CalcDrawProps(&render_surface_layer_list); - UpdateAndPush(layer, layer_impl); - - // We should have both tiles on the impl side. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); - - resource_manager_->ClearPriorities(); - ResourceManagerClearAllMemory(resource_manager_.get(), - resource_provider_.get()); - resource_manager_->SetMaxMemoryLimitBytes(4 * 1024 * 1024); - - // This should drop the tiles on the impl thread. - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - - // We should now have no textures on the impl thread. - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); - - // This should recreate and update one of the deleted textures. - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); - UpdateAndPush(layer, layer_impl); - - // We should have one tiles on the impl side. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); -} - -TEST_F(TiledLayerTest, PushIdlePaintTiles) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the - // center. This paints 1 visible of the 25 invalid tiles. - layer->SetBounds(gfx::Size(500, 500)); - CalcDrawProps(&render_surface_layer_list); - layer->draw_properties().visible_content_rect = gfx::Rect(200, 200, 100, 100); - bool needs_update = UpdateAndPush(layer, layer_impl); - // We should need idle-painting for surrounding tiles. - EXPECT_TRUE(needs_update); - - // We should have one tile on the impl side. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(2, 2)); - - // For the next four updates, we should detect we still need idle painting. - for (int i = 0; i < 4; i++) { - needs_update = UpdateAndPush(layer, layer_impl); - EXPECT_TRUE(needs_update); - } - - // We should always finish painting eventually. - for (int i = 0; i < 20; i++) - needs_update = UpdateAndPush(layer, layer_impl); - - // We should have pre-painted all of the surrounding tiles. - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 5; j++) - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j)); - } - - EXPECT_FALSE(needs_update); -} - -TEST_F(TiledLayerTest, PredictivePainting) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - - layer_tree_host_->root_layer()->AddChild(layer); - - // Prepainting should occur in the scroll direction first, and the - // visible rect should be extruded only along the dominant axis. - gfx::Vector2d directions[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0), - gfx::Vector2d(0, -10), gfx::Vector2d(0, 10), - gfx::Vector2d(10, 20), - gfx::Vector2d(-20, 10) }; - // We should push all tiles that touch the extruded visible rect. - gfx::Rect pushed_visible_tiles[6] = { - gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2), - gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1) - }; - // The first pre-paint should also paint first in the scroll - // direction so we should find one additional tile in the scroll direction. - gfx::Rect pushed_prepaint_tiles[6] = { - gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3), - gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1) - }; - for (int k = 0; k < 6; k++) { - // The tile size is 100x100. Setup 5x5 tiles with one visible tile - // in the center. - gfx::Size bounds = gfx::Size(500, 500); - gfx::Rect visible_rect = gfx::Rect(200, 200, 100, 100); - gfx::Rect previous_visible_rect = - gfx::Rect(visible_rect.origin() + directions[k], visible_rect.size()); - gfx::Rect next_visible_rect = - gfx::Rect(visible_rect.origin() - directions[k], visible_rect.size()); - - // Setup. Use the previous_visible_rect to setup the prediction for next - // frame. - layer->SetBounds(bounds); - - RenderSurfaceLayerList render_surface_layer_list; - CalcDrawProps(&render_surface_layer_list); - layer->draw_properties().visible_content_rect = previous_visible_rect; - bool needs_update = UpdateAndPush(layer, layer_impl); - - // Invalidate and move the visible_rect in the scroll direction. - // Check that the correct tiles have been painted in the visible pass. - layer->SetNeedsDisplay(); - layer->draw_properties().visible_content_rect = visible_rect; - needs_update = UpdateAndPush(layer, layer_impl); - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 5; j++) - EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), - pushed_visible_tiles[k].Contains(i, j)); - } - - // Move the transform in the same direction without invalidating. - // Check that non-visible pre-painting occured in the correct direction. - // Ignore diagonal scrolls here (k > 3) as these have new visible content - // now. - if (k <= 3) { - layer->draw_properties().visible_content_rect = next_visible_rect; - needs_update = UpdateAndPush(layer, layer_impl); - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 5; j++) - EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), - pushed_prepaint_tiles[k].Contains(i, j)); - } - } - - // We should always finish painting eventually. - for (int i = 0; i < 20; i++) - needs_update = UpdateAndPush(layer, layer_impl); - EXPECT_FALSE(needs_update); - } -} - -TEST_F(TiledLayerTest, PushTilesAfterIdlePaintFailed) { - // Start with 2mb of memory, but the test is going to try to use just more - // than 1mb, so we reduce to 1mb later. - resource_manager_->SetMaxMemoryLimitBytes(2 * 1024 * 1024); - scoped_refptr<FakeTiledLayer> layer1 = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl1 = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - scoped_refptr<FakeTiledLayer> layer2 = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl2 = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer1); - layer_tree_host_->root_layer()->AddChild(layer2); - - // For this test we have two layers. layer1 exhausts most texture memory, - // leaving room for 2 more tiles from layer2, but not all three tiles. First - // we paint layer1, and one tile from layer2. Then when we idle paint layer2, - // we will fail on the third tile of layer2, and this should not leave the - // second tile in a bad state. - - // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough - // for 2 tiles only in the other layer. - gfx::Rect layer1_rect(0, 0, 100, 2400); - - // This requires 4*30000 bytes of memory. - gfx::Rect layer2_rect(0, 0, 100, 300); - - // Paint a single tile in layer2 so that it will idle paint. - layer1->SetBounds(layer1_rect.size()); - layer2->SetBounds(layer2_rect.size()); - CalcDrawProps(&render_surface_layer_list); - layer1->draw_properties().visible_content_rect = layer1_rect; - layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); - bool needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2); - // We should need idle-painting for both remaining tiles in layer2. - EXPECT_TRUE(needs_update); - - // Reduce our memory limits to 1mb. - resource_manager_->SetMaxMemoryLimitBytes(1024 * 1024); - - // Now idle paint layer2. We are going to run out of memory though! - // Oh well, commit the frame and push. - for (int i = 0; i < 4; i++) { - needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2); - } - - // Sanity check, we should have textures for the big layer. - EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 23)); - - // We should only have the first two tiles from layer2 since - // it failed to idle update the last tile. - EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1)); - EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1)); - - EXPECT_FALSE(needs_update); - EXPECT_FALSE(layer_impl2->HasResourceIdForTileAt(0, 2)); -} - -TEST_F(TiledLayerTest, PushIdlePaintedOccludedTiles) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - TestOcclusionTracker occluded; - occlusion_ = &occluded; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100, so this invalidates one occluded tile, culls it - // during paint, but prepaints it. - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 100, 100))); - - layer->SetBounds(gfx::Size(100, 100)); - CalcDrawProps(&render_surface_layer_list); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); - UpdateAndPush(layer, layer_impl); - - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); -} - -TEST_F(TiledLayerTest, PushTilesMarkedDirtyDuringPaint) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100, so this invalidates and then paints two tiles. - // However, during the paint, we invalidate one of the tiles. This should - // not prevent the tile from being pushed. - layer->fake_layer_updater()->SetRectToInvalidate( - gfx::Rect(0, 50, 100, 50), layer.get()); - layer->SetBounds(gfx::Size(100, 200)); - CalcDrawProps(&render_surface_layer_list); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); - UpdateAndPush(layer, layer_impl); - - // We should have both tiles on the impl side. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); -} - -TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer) { - scoped_refptr<FakeTiledLayer> layer1 = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_refptr<FakeTiledLayer> layer2 = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer1_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - scoped_ptr<FakeTiledLayerImpl> layer2_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer1); - layer_tree_host_->root_layer()->AddChild(layer2); - - // Invalidate a tile on layer1, during update of layer 2. - layer2->fake_layer_updater()->SetRectToInvalidate( - gfx::Rect(0, 50, 100, 50), layer1.get()); - layer1->SetBounds(gfx::Size(100, 200)); - layer2->SetBounds(gfx::Size(100, 200)); - CalcDrawProps(&render_surface_layer_list); - layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); - layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); - UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl); - - // We should have both tiles on the impl side for all layers. - EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1)); - EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1)); -} - -TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer) { - scoped_refptr<FakeTiledLayer> layer1 = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_refptr<FakeTiledLayer> layer2 = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer1_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - scoped_ptr<FakeTiledLayerImpl> layer2_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer1); - layer_tree_host_->root_layer()->AddChild(layer2); - - layer1->fake_layer_updater()->SetRectToInvalidate( - gfx::Rect(0, 50, 100, 50), layer2.get()); - layer1->SetBounds(gfx::Size(100, 200)); - layer2->SetBounds(gfx::Size(100, 200)); - CalcDrawProps(&render_surface_layer_list); - layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); - layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); - UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl); - - // We should have both tiles on the impl side for all layers. - EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1)); - EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1)); -} - -TEST_F(TiledLayerTest, PaintSmallAnimatedLayersImmediately) { - // Create a LayerTreeHost that has the right viewportsize, - // so the layer is considered small enough. - bool run_out_of_memory[2] = { false, true }; - for (int i = 0; i < 2; i++) { - // Create a layer with 5x5 tiles, with 4x4 size viewport. - int viewport_width = 4 * FakeTiledLayer::tile_size().width(); - int viewport_height = 4 * FakeTiledLayer::tile_size().width(); - int layer_width = 5 * FakeTiledLayer::tile_size().width(); - int layer_height = 5 * FakeTiledLayer::tile_size().height(); - int memory_for_layer = layer_width * layer_height * 4; - layer_tree_host_->SetViewportSize( - gfx::Size(viewport_width, viewport_height)); - - // Use 10x5 tiles to run out of memory. - if (run_out_of_memory[i]) - layer_width *= 2; - - resource_manager_->SetMaxMemoryLimitBytes(memory_for_layer); - - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - // Full size layer with half being visible. - layer->SetBounds(gfx::Size(layer_width, layer_height)); - gfx::Rect visible_rect(0, 0, layer_width / 2, layer_height); - CalcDrawProps(&render_surface_layer_list); - - // Pretend the layer is animating. - layer->draw_properties().target_space_transform_is_animating = true; - layer->draw_properties().visible_content_rect = visible_rect; - layer->SetLayerTreeHost(layer_tree_host_.get()); - - // The layer should paint its entire contents on the first paint - // if it is close to the viewport size and has the available memory. - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), nullptr); - UpdateTextures(); - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - - // We should have all the tiles for the small animated layer. - // We should still have the visible tiles when we didn't - // have enough memory for all the tiles. - if (!run_out_of_memory[i]) { - for (int i = 0; i < 5; ++i) { - for (int j = 0; j < 5; ++j) - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j)); - } - } else { - for (int i = 0; i < 10; ++i) { - for (int j = 0; j < 5; ++j) - EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), i < 5); - } - } - - layer->RemoveFromParent(); - } -} - -TEST_F(TiledLayerTest, IdlePaintOutOfMemory) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - // We have enough memory for only the visible rect, so we will run out of - // memory in first idle paint. - int memory_limit = 4 * 100 * 100; // 1 tiles, 4 bytes per pixel. - resource_manager_->SetMaxMemoryLimitBytes(memory_limit); - - // The tile size is 100x100, so this invalidates and then paints two tiles. - bool needs_update = false; - layer->SetBounds(gfx::Size(300, 300)); - CalcDrawProps(&render_surface_layer_list); - layer->draw_properties().visible_content_rect = gfx::Rect(100, 100, 100, 100); - for (int i = 0; i < 2; i++) - needs_update = UpdateAndPush(layer, layer_impl); - - // Idle-painting should see no more priority tiles for painting. - EXPECT_FALSE(needs_update); - - // We should have one tile on the impl side. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1)); -} - -TEST_F(TiledLayerTest, IdlePaintZeroSizedLayer) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - - layer_tree_host_->root_layer()->AddChild(layer); - - bool animating[2] = { false, true }; - for (int i = 0; i < 2; i++) { - // Pretend the layer is animating. - layer->draw_properties().target_space_transform_is_animating = animating[i]; - - // The layer's bounds are empty. - // Empty layers don't paint or idle-paint. - layer->SetBounds(gfx::Size()); - - RenderSurfaceLayerList render_surface_layer_list; - CalcDrawProps(&render_surface_layer_list); - layer->draw_properties().visible_content_rect = gfx::Rect(); - bool needs_update = UpdateAndPush(layer, layer_impl); - - // Empty layers don't have tiles. - EXPECT_EQ(0u, layer->NumPaintedTiles()); - - // Empty layers don't need prepaint. - EXPECT_FALSE(needs_update); - - // Empty layers don't have tiles. - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0)); - } -} - -TEST_F(TiledLayerTest, IdlePaintNonVisibleLayers) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - - // Alternate between not visible and visible. - gfx::Rect v(0, 0, 100, 100); - gfx::Rect nv(0, 0, 0, 0); - gfx::Rect visible_rect[10] = { nv, nv, v, v, nv, nv, v, v, nv, nv }; - bool invalidate[10] = { true, true, true, true, true, true, true, true, false, - false }; - - // We should not have any tiles except for when the layer was visible - // or after the layer was visible and we didn't invalidate. - bool have_tile[10] = { false, false, true, true, false, false, true, true, - true, true }; - - layer_tree_host_->root_layer()->AddChild(layer); - - for (int i = 0; i < 10; i++) { - layer->SetBounds(gfx::Size(100, 100)); - - RenderSurfaceLayerList render_surface_layer_list; - CalcDrawProps(&render_surface_layer_list); - layer->draw_properties().visible_content_rect = visible_rect[i]; - - if (invalidate[i]) - layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 100)); - bool needs_update = UpdateAndPush(layer, layer_impl); - - // We should never signal idle paint, as we painted the entire layer - // or the layer was not visible. - EXPECT_FALSE(needs_update); - EXPECT_EQ(layer_impl->HasResourceIdForTileAt(0, 0), have_tile[i]); - } -} - -TEST_F(TiledLayerTest, InvalidateFromPrepare) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100, so this invalidates and then paints two tiles. - layer->SetBounds(gfx::Size(100, 200)); - CalcDrawProps(&render_surface_layer_list); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); - UpdateAndPush(layer, layer_impl); - - // We should have both tiles on the impl side. - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); - - layer->fake_layer_updater()->ClearPrepareCount(); - // Invoke update again. As the layer is valid update shouldn't be invoked on - // the LayerUpdater. - UpdateAndPush(layer, layer_impl); - EXPECT_EQ(0, layer->fake_layer_updater()->prepare_count()); - - // SetRectToInvalidate triggers InvalidateContentRect() being invoked from - // update. - layer->fake_layer_updater()->SetRectToInvalidate( - gfx::Rect(25, 25, 50, 50), layer.get()); - layer->fake_layer_updater()->ClearPrepareCount(); - layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50)); - UpdateAndPush(layer, layer_impl); - EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count()); - layer->fake_layer_updater()->ClearPrepareCount(); - - // The layer should still be invalid as update invoked invalidate. - UpdateAndPush(layer, layer_impl); // visible - EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count()); -} - -TEST_F(TiledLayerTest, VerifyUpdateRectWhenContentBoundsAreScaled) { - // The update rect (that indicates what was actually painted) should be in - // layer space, not the content space. - scoped_refptr<FakeTiledLayerWithScaledBounds> layer = make_scoped_refptr( - new FakeTiledLayerWithScaledBounds(resource_manager_.get())); - - layer_tree_host_->root_layer()->AddChild(layer); - - gfx::Rect layer_bounds(0, 0, 300, 200); - gfx::Rect content_bounds(0, 0, 150, 250); - - layer->SetBounds(layer_bounds.size()); - layer->SetContentBounds(content_bounds.size()); - layer->draw_properties().visible_content_rect = content_bounds; - layer->draw_properties().contents_scale_x = .5f; - layer->draw_properties().contents_scale_y = 1.25f; - - // On first update, the update_rect includes all tiles, even beyond the - // boundaries of the layer. - // However, it should still be in layer space, not content space. - layer->InvalidateContentRect(content_bounds); - - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), nullptr); - - // Update rect is 200x300 (tile size of 100x100). Scaled this gives 400x240. - EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 400, 240), layer->update_rect()); - UpdateTextures(); - - // After the tiles are updated once, another invalidate only needs to update - // the bounds of the layer. - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->InvalidateContentRect(content_bounds); - layer->SavePaintProperties(); - layer->Update(queue_.get(), nullptr); - EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds), layer->update_rect()); - UpdateTextures(); - - // Partial re-paint should also be represented by the update rect in layer - // space, not content space. - gfx::Rect partial_damage(30, 100, 10, 10); - layer->InvalidateContentRect(partial_damage); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), nullptr); - EXPECT_FLOAT_RECT_EQ(gfx::RectF(60, 80, 20, 8), layer->update_rect()); -} - -TEST_F(TiledLayerTest, VerifyInvalidationWhenContentsScaleChanges) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - // Create a layer with one tile. - layer->SetBounds(gfx::Size(100, 100)); - CalcDrawProps(&render_surface_layer_list); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); - layer->Update(queue_.get(), nullptr); - UpdateTextures(); - EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100), - layer->last_needs_display_rect()); - - // Push the tiles to the impl side and check that there is exactly one. - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), nullptr); - UpdateTextures(); - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0)); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1)); - - layer->SetNeedsDisplayRect(gfx::Rect()); - EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer->last_needs_display_rect()); - - // Change the contents scale. - layer->UpdateContentsScale(2.f); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 200, 200); - - // The impl side should get 2x2 tiles now. - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), nullptr); - UpdateTextures(); - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 0)); - EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1)); - - // Verify that changing the contents scale caused invalidation, and - // that the layer-space rectangle requiring painting is not scaled. - EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100), - layer->last_needs_display_rect()); - - // Invalidate the entire layer again, but do not paint. All tiles should be - // gone now from the impl side. - layer->SetNeedsDisplay(); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0)); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0)); - EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1)); -} - -TEST_F(TiledLayerTest, SkipsDrawGetsReset) { - // Create two 300 x 300 tiled layers. - gfx::Size content_bounds(300, 300); - gfx::Rect content_rect(content_bounds); - - // We have enough memory for only one of the two layers. - int memory_limit = 4 * 300 * 300; // 4 bytes per pixel. - - scoped_refptr<FakeTiledLayer> root_layer = make_scoped_refptr( - new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); - scoped_refptr<FakeTiledLayer> child_layer = make_scoped_refptr( - new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); - root_layer->AddChild(child_layer); - - root_layer->SetBounds(content_bounds); - root_layer->draw_properties().visible_content_rect = content_rect; - root_layer->SetPosition(gfx::PointF(0, 0)); - child_layer->SetBounds(content_bounds); - child_layer->draw_properties().visible_content_rect = content_rect; - child_layer->SetPosition(gfx::PointF(0, 0)); - root_layer->InvalidateContentRect(content_rect); - child_layer->InvalidateContentRect(content_rect); - - layer_tree_host_->SetRootLayer(root_layer); - layer_tree_host_->SetViewportSize(gfx::Size(300, 300)); - layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( - memory_limit); - - layer_tree_host_->UpdateLayers(queue_.get()); - - // We'll skip the root layer. - EXPECT_TRUE(root_layer->SkipsDraw()); - EXPECT_FALSE(child_layer->SkipsDraw()); - - layer_tree_host_->CommitComplete(); - - // Remove the child layer. - root_layer->RemoveAllChildren(); - - layer_tree_host_->UpdateLayers(queue_.get()); - EXPECT_FALSE(root_layer->SkipsDraw()); - - ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), - resource_provider_.get()); - layer_tree_host_->SetRootLayer(nullptr); -} - -TEST_F(TiledLayerTest, ResizeToSmaller) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - - layer_tree_host_->root_layer()->AddChild(layer); - - layer->SetBounds(gfx::Size(700, 700)); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700); - layer->InvalidateContentRect(gfx::Rect(0, 0, 700, 700)); - - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), nullptr); - - layer->SetBounds(gfx::Size(200, 200)); - layer->InvalidateContentRect(gfx::Rect(0, 0, 200, 200)); -} - -TEST_F(TiledLayerTest, HugeLayerUpdateCrash) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - - layer_tree_host_->root_layer()->AddChild(layer); - - int size = 1 << 30; - layer->SetBounds(gfx::Size(size, size)); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700); - layer->InvalidateContentRect(gfx::Rect(0, 0, size, size)); - - // Ensure no crash for bounds where size * size would overflow an int. - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), nullptr); -} - -class TiledLayerPartialUpdateTest : public TiledLayerTest { - public: - TiledLayerPartialUpdateTest() { settings_.max_partial_texture_updates = 4; } -}; - -TEST_F(TiledLayerPartialUpdateTest, PartialUpdates) { - // Create one 300 x 200 tiled layer with 3 x 2 tiles. - gfx::Size content_bounds(300, 200); - gfx::Rect content_rect(content_bounds); - - scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr( - new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); - layer->SetBounds(content_bounds); - layer->SetPosition(gfx::PointF(0, 0)); - layer->draw_properties().visible_content_rect = content_rect; - layer->InvalidateContentRect(content_rect); - - layer_tree_host_->SetRootLayer(layer); - layer_tree_host_->SetViewportSize(gfx::Size(300, 200)); - - // Full update of all 6 tiles. - layer_tree_host_->UpdateLayers(queue_.get()); - { - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - EXPECT_EQ(6u, queue_->FullUploadSize()); - EXPECT_EQ(0u, queue_->PartialUploadSize()); - UpdateTextures(); - EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); - EXPECT_FALSE(queue_->HasMoreUpdates()); - layer->fake_layer_updater()->ClearUpdateCount(); - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - } - layer_tree_host_->CommitComplete(); - - // Full update of 3 tiles and partial update of 3 tiles. - layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 150)); - layer_tree_host_->UpdateLayers(queue_.get()); - { - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - EXPECT_EQ(3u, queue_->FullUploadSize()); - EXPECT_EQ(3u, queue_->PartialUploadSize()); - UpdateTextures(); - EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); - EXPECT_FALSE(queue_->HasMoreUpdates()); - layer->fake_layer_updater()->ClearUpdateCount(); - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - } - layer_tree_host_->CommitComplete(); - - // Partial update of 6 tiles. - layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100)); - { - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - layer_tree_host_->UpdateLayers(queue_.get()); - EXPECT_EQ(2u, queue_->FullUploadSize()); - EXPECT_EQ(4u, queue_->PartialUploadSize()); - UpdateTextures(); - EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); - EXPECT_FALSE(queue_->HasMoreUpdates()); - layer->fake_layer_updater()->ClearUpdateCount(); - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - } - layer_tree_host_->CommitComplete(); - - // Checkerboard all tiles. - layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 200)); - { - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - } - layer_tree_host_->CommitComplete(); - - // Partial update of 6 checkerboard tiles. - layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100)); - { - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - layer_tree_host_->UpdateLayers(queue_.get()); - EXPECT_EQ(6u, queue_->FullUploadSize()); - EXPECT_EQ(0u, queue_->PartialUploadSize()); - UpdateTextures(); - EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); - EXPECT_FALSE(queue_->HasMoreUpdates()); - layer->fake_layer_updater()->ClearUpdateCount(); - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - } - layer_tree_host_->CommitComplete(); - - // Partial update of 4 tiles. - layer->InvalidateContentRect(gfx::Rect(50, 50, 100, 100)); - { - scoped_ptr<FakeTiledLayerImpl> layer_impl = - make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); - layer_tree_host_->UpdateLayers(queue_.get()); - EXPECT_EQ(0u, queue_->FullUploadSize()); - EXPECT_EQ(4u, queue_->PartialUploadSize()); - UpdateTextures(); - EXPECT_EQ(4, layer->fake_layer_updater()->update_count()); - EXPECT_FALSE(queue_->HasMoreUpdates()); - layer->fake_layer_updater()->ClearUpdateCount(); - LayerPushPropertiesTo(layer.get(), layer_impl.get()); - } - layer_tree_host_->CommitComplete(); - - ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), - resource_provider_.get()); - layer_tree_host_->SetRootLayer(nullptr); -} - -TEST_F(TiledLayerTest, TilesPaintedWithoutOcclusion) { - layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); - - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - RenderSurfaceLayerList render_surface_layer_list; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100, so this invalidates and then paints two tiles. - layer->SetBounds(gfx::Size(100, 200)); - CalcDrawProps(&render_surface_layer_list); - - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), nullptr); - EXPECT_EQ(2, layer->fake_layer_updater()->update_count()); -} - -TEST_F(TiledLayerTest, TilesPaintedWithOcclusion) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - RenderSurfaceLayerList render_surface_layer_list; - TestOcclusionTracker occluded; - occlusion_ = &occluded; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100. - - layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); - layer->SetBounds(gfx::Size(600, 600)); - CalcDrawProps(&render_surface_layer_list); - - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); - layer->draw_properties().drawable_content_rect = - gfx::Rect(layer->content_bounds()); - layer->draw_properties().visible_content_rect = - gfx::Rect(layer->content_bounds()); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count()); - - layer->fake_layer_updater()->ClearUpdateCount(); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 200, 300, 100))); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - EXPECT_EQ(36 - 2, layer->fake_layer_updater()->update_count()); - - layer->fake_layer_updater()->ClearUpdateCount(); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 250, 300, 100))); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - EXPECT_EQ(36, layer->fake_layer_updater()->update_count()); -} - -TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndVisiblityConstraints) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - RenderSurfaceLayerList render_surface_layer_list; - TestOcclusionTracker occluded; - occlusion_ = &occluded; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100. - - layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); - layer->SetBounds(gfx::Size(600, 600)); - CalcDrawProps(&render_surface_layer_list); - - // The partially occluded tiles (by the 150 occlusion height) are visible - // beyond the occlusion, so not culled. - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); - layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 360); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 360); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - EXPECT_EQ(24 - 3, layer->fake_layer_updater()->update_count()); - - layer->fake_layer_updater()->ClearUpdateCount(); - - // Now the visible region stops at the edge of the occlusion so the partly - // visible tiles become fully occluded. - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); - layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 350); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 350); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count()); - - layer->fake_layer_updater()->ClearUpdateCount(); - - // Now the visible region is even smaller than the occlusion, it should have - // the same result. - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); - layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 340); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 340); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count()); -} - -TEST_F(TiledLayerTest, TilesNotPaintedWithoutInvalidation) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - RenderSurfaceLayerList render_surface_layer_list; - TestOcclusionTracker occluded; - occlusion_ = &occluded; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100. - - layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); - layer->SetBounds(gfx::Size(600, 600)); - CalcDrawProps(&render_surface_layer_list); - - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); - layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 600); - layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 600); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count()); - UpdateTextures(); - - layer->fake_layer_updater()->ClearUpdateCount(); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - - // Repaint without marking it dirty. The 3 culled tiles will be pre-painted - // now. - layer->Update(queue_.get(), &occluded); - EXPECT_EQ(3, layer->fake_layer_updater()->update_count()); -} - -TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndTransforms) { - scoped_refptr<FakeTiledLayer> layer = - make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); - RenderSurfaceLayerList render_surface_layer_list; - TestOcclusionTracker occluded; - occlusion_ = &occluded; - - layer_tree_host_->root_layer()->AddChild(layer); - - // The tile size is 100x100. - - // This makes sure the painting works when the occluded region (in screen - // space) is transformed differently than the layer. - layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); - layer->SetBounds(gfx::Size(600, 600)); - CalcDrawProps(&render_surface_layer_list); - gfx::Transform screen_transform; - screen_transform.Scale(0.5, 0.5); - layer->draw_properties().screen_space_transform = screen_transform; - layer->draw_properties().target_space_transform = screen_transform; - - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 50))); - layer->draw_properties().drawable_content_rect = - gfx::Rect(layer->content_bounds()); - layer->draw_properties().visible_content_rect = - gfx::Rect(layer->content_bounds()); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count()); -} - -TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndScaling) { - scoped_refptr<FakeTiledLayer> layer = - new FakeTiledLayer(resource_manager_.get()); - RenderSurfaceLayerList render_surface_layer_list; - TestOcclusionTracker occluded; - occlusion_ = &occluded; - - scoped_refptr<FakeTiledLayer> scale_layer = - new FakeTiledLayer(resource_manager_.get()); - gfx::Transform scale_transform; - scale_transform.Scale(2.0, 2.0); - scale_layer->SetTransform(scale_transform); - - layer_tree_host_->root_layer()->AddChild(scale_layer); - - // The tile size is 100x100. - - // This makes sure the painting works when the content space is scaled to - // a different layer space. - layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); - layer->SetBounds(gfx::Size(300, 300)); - scale_layer->AddChild(layer); - CalcDrawProps(&render_surface_layer_list); - EXPECT_FLOAT_EQ(2.f, layer->contents_scale_x()); - EXPECT_FLOAT_EQ(2.f, layer->contents_scale_y()); - EXPECT_EQ(gfx::Size(600, 600).ToString(), - layer->content_bounds().ToString()); - - // No tiles are covered by the 300x50 occlusion. - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 50))); - layer->draw_properties().drawable_content_rect = - gfx::Rect(layer->bounds()); - layer->draw_properties().visible_content_rect = - gfx::Rect(layer->content_bounds()); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - int visible_tiles1 = 6 * 6; - EXPECT_EQ(visible_tiles1, layer->fake_layer_updater()->update_count()); - - layer->fake_layer_updater()->ClearUpdateCount(); - - // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still. - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); - layer->draw_properties().drawable_content_rect = - gfx::Rect(layer->bounds()); - layer->draw_properties().visible_content_rect = - gfx::Rect(layer->content_bounds()); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - int visible_tiles2 = 6 * 6 - 3; - EXPECT_EQ(visible_tiles2, layer->fake_layer_updater()->update_count()); - - layer->fake_layer_updater()->ClearUpdateCount(); - - // This makes sure content scaling and transforms work together. - // When the tiles are scaled down by half, they are 50x50 each in the - // screen. - gfx::Transform screen_transform; - screen_transform.Scale(0.5, 0.5); - layer->draw_properties().screen_space_transform = screen_transform; - layer->draw_properties().target_space_transform = screen_transform; - - // An occlusion of 150x100 will cover 3*2 = 6 tiles. - occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100))); - - gfx::Rect layer_bounds_rect(layer->bounds()); - layer->draw_properties().drawable_content_rect = - gfx::ScaleToEnclosingRect(layer_bounds_rect, 0.5f); - layer->draw_properties().visible_content_rect = - gfx::Rect(layer->content_bounds()); - layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - layer->Update(queue_.get(), &occluded); - int visible_tiles3 = 6 * 6 - 6; - EXPECT_EQ(visible_tiles3, layer->fake_layer_updater()->update_count()); -} - -TEST_F(TiledLayerTest, DontAllocateContentsWhenTargetSurfaceCantBeAllocated) { - // Tile size is 100x100. - gfx::Rect root_rect(0, 0, 300, 200); - gfx::Rect child_rect(0, 0, 300, 100); - gfx::Rect child2_rect(0, 100, 300, 100); - - scoped_refptr<FakeTiledLayer> root = make_scoped_refptr( - new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); - scoped_refptr<Layer> surface = Layer::Create(); - scoped_refptr<FakeTiledLayer> child = make_scoped_refptr( - new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); - scoped_refptr<FakeTiledLayer> child2 = make_scoped_refptr( - new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); - - root->SetBounds(root_rect.size()); - root->draw_properties().drawable_content_rect = root_rect; - root->draw_properties().visible_content_rect = root_rect; - root->AddChild(surface); - - surface->SetForceRenderSurface(true); - surface->SetOpacity(0.5); - surface->AddChild(child); - surface->AddChild(child2); - - child->SetBounds(child_rect.size()); - child->SetPosition(child_rect.origin()); - child->draw_properties().visible_content_rect = child_rect; - child->draw_properties().drawable_content_rect = root_rect; - - child2->SetBounds(child2_rect.size()); - child2->SetPosition(child2_rect.origin()); - child2->draw_properties().visible_content_rect = child2_rect; - child2->draw_properties().drawable_content_rect = root_rect; - - layer_tree_host_->SetRootLayer(root); - layer_tree_host_->SetViewportSize(root_rect.size()); - - // With a huge memory limit, all layers should update and push their textures. - root->InvalidateContentRect(root_rect); - child->InvalidateContentRect(child_rect); - child2->InvalidateContentRect(child2_rect); - layer_tree_host_->UpdateLayers(queue_.get()); - { - UpdateTextures(); - EXPECT_EQ(6, root->fake_layer_updater()->update_count()); - EXPECT_EQ(3, child->fake_layer_updater()->update_count()); - EXPECT_EQ(3, child2->fake_layer_updater()->update_count()); - EXPECT_FALSE(queue_->HasMoreUpdates()); - - root->fake_layer_updater()->ClearUpdateCount(); - child->fake_layer_updater()->ClearUpdateCount(); - child2->fake_layer_updater()->ClearUpdateCount(); - - scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr( - new FakeTiledLayerImpl(host_impl_->active_tree(), root->id())); - scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr( - new FakeTiledLayerImpl(host_impl_->active_tree(), child->id())); - scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr( - new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id())); - LayerPushPropertiesTo(child2.get(), child2_impl.get()); - LayerPushPropertiesTo(child.get(), child_impl.get()); - LayerPushPropertiesTo(root.get(), root_impl.get()); - - for (unsigned i = 0; i < 3; ++i) { - for (unsigned j = 0; j < 2; ++j) - EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j)); - EXPECT_TRUE(child_impl->HasResourceIdForTileAt(i, 0)); - EXPECT_TRUE(child2_impl->HasResourceIdForTileAt(i, 0)); - } - } - layer_tree_host_->CommitComplete(); - - // With a memory limit that includes only the root layer (3x2 tiles) and half - // the surface that the child layers draw into, the child layers will not be - // allocated. If the surface isn't accounted for, then one of the children - // would fit within the memory limit. - root->InvalidateContentRect(root_rect); - child->InvalidateContentRect(child_rect); - child2->InvalidateContentRect(child2_rect); - - size_t memory_limit = (3 * 2 + 3 * 1) * (100 * 100) * 4; - layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( - memory_limit); - layer_tree_host_->UpdateLayers(queue_.get()); - { - UpdateTextures(); - EXPECT_EQ(6, root->fake_layer_updater()->update_count()); - EXPECT_EQ(0, child->fake_layer_updater()->update_count()); - EXPECT_EQ(0, child2->fake_layer_updater()->update_count()); - EXPECT_FALSE(queue_->HasMoreUpdates()); - - root->fake_layer_updater()->ClearUpdateCount(); - child->fake_layer_updater()->ClearUpdateCount(); - child2->fake_layer_updater()->ClearUpdateCount(); - - scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr( - new FakeTiledLayerImpl(host_impl_->active_tree(), root->id())); - scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr( - new FakeTiledLayerImpl(host_impl_->active_tree(), child->id())); - scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr( - new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id())); - LayerPushPropertiesTo(child2.get(), child2_impl.get()); - LayerPushPropertiesTo(child.get(), child_impl.get()); - LayerPushPropertiesTo(root.get(), root_impl.get()); - - for (unsigned i = 0; i < 3; ++i) { - for (unsigned j = 0; j < 2; ++j) - EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j)); - EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0)); - EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0)); - } - } - layer_tree_host_->CommitComplete(); - - // With a memory limit that includes only half the root layer, no contents - // will be allocated. If render surface memory wasn't accounted for, there is - // enough space for one of the children layers, but they draw into a surface - // that can't be allocated. - root->InvalidateContentRect(root_rect); - child->InvalidateContentRect(child_rect); - child2->InvalidateContentRect(child2_rect); - - memory_limit = (3 * 1) * (100 * 100) * 4; - layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( - memory_limit); - layer_tree_host_->UpdateLayers(queue_.get()); - { - UpdateTextures(); - EXPECT_EQ(0, root->fake_layer_updater()->update_count()); - EXPECT_EQ(0, child->fake_layer_updater()->update_count()); - EXPECT_EQ(0, child2->fake_layer_updater()->update_count()); - EXPECT_FALSE(queue_->HasMoreUpdates()); - - root->fake_layer_updater()->ClearUpdateCount(); - child->fake_layer_updater()->ClearUpdateCount(); - child2->fake_layer_updater()->ClearUpdateCount(); - - scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr( - new FakeTiledLayerImpl(host_impl_->active_tree(), root->id())); - scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr( - new FakeTiledLayerImpl(host_impl_->active_tree(), child->id())); - scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr( - new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id())); - LayerPushPropertiesTo(child2.get(), child2_impl.get()); - LayerPushPropertiesTo(child.get(), child_impl.get()); - LayerPushPropertiesTo(root.get(), root_impl.get()); - - for (unsigned i = 0; i < 3; ++i) { - for (unsigned j = 0; j < 2; ++j) - EXPECT_FALSE(root_impl->HasResourceIdForTileAt(i, j)); - EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0)); - EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0)); - } - } - layer_tree_host_->CommitComplete(); - - ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), - resource_provider_.get()); - layer_tree_host_->SetRootLayer(nullptr); -} - -class TrackingLayerPainter : public LayerPainter { - public: - static scoped_ptr<TrackingLayerPainter> Create() { - return make_scoped_ptr(new TrackingLayerPainter()); - } - - void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) override { - painted_rect_ = content_rect; - } - - gfx::Rect PaintedRect() const { return painted_rect_; } - void ResetPaintedRect() { painted_rect_ = gfx::Rect(); } - - private: - gfx::Rect painted_rect_; -}; - -class UpdateTrackingTiledLayer : public FakeTiledLayer { - public: - explicit UpdateTrackingTiledLayer(PrioritizedResourceManager* manager) - : FakeTiledLayer(manager) { - scoped_ptr<TrackingLayerPainter> painter(TrackingLayerPainter::Create()); - tracking_layer_painter_ = painter.get(); - layer_updater_ = BitmapContentLayerUpdater::Create(painter.Pass(), 0); - } - - TrackingLayerPainter* tracking_layer_painter() const { - return tracking_layer_painter_; - } - - private: - LayerUpdater* Updater() const override { return layer_updater_.get(); } - ~UpdateTrackingTiledLayer() override {} - - TrackingLayerPainter* tracking_layer_painter_; - scoped_refptr<BitmapContentLayerUpdater> layer_updater_; -}; - -TEST_F(TiledLayerTest, NonIntegerContentsScaleIsNotDistortedDuringPaint) { - scoped_refptr<UpdateTrackingTiledLayer> layer = - make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get())); - - layer_tree_host_->root_layer()->AddChild(layer); - - gfx::Rect layer_rect(0, 0, 30, 31); - layer->SetPosition(layer_rect.origin()); - layer->SetBounds(layer_rect.size()); - layer->UpdateContentsScale(1.5f); - - gfx::Rect content_rect(0, 0, 45, 47); - EXPECT_EQ(content_rect.size(), layer->content_bounds()); - layer->draw_properties().visible_content_rect = content_rect; - layer->draw_properties().drawable_content_rect = content_rect; - - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - - // Update the whole tile. - layer->Update(queue_.get(), nullptr); - layer->tracking_layer_painter()->ResetPaintedRect(); - - EXPECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect()); - UpdateTextures(); - - // Invalidate the entire layer in content space. When painting, the rect given - // to webkit should match the layer's bounds. - layer->InvalidateContentRect(content_rect); - layer->Update(queue_.get(), nullptr); - - // Rounding leads to an extra pixel. - gfx::Rect expanded_layer_rect(layer_rect); - expanded_layer_rect.set_height(32); - EXPECT_EQ(expanded_layer_rect, - layer->tracking_layer_painter()->PaintedRect()); -} - -TEST_F(TiledLayerTest, - NonIntegerContentsScaleIsNotDistortedDuringInvalidation) { - scoped_refptr<UpdateTrackingTiledLayer> layer = - make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get())); - - layer_tree_host_->root_layer()->AddChild(layer); - - gfx::Rect layer_rect(0, 0, 30, 31); - layer->SetPosition(layer_rect.origin()); - layer->SetBounds(layer_rect.size()); - layer->UpdateContentsScale(1.3f); - - gfx::Rect content_rect(layer->content_bounds()); - layer->draw_properties().visible_content_rect = content_rect; - layer->draw_properties().drawable_content_rect = content_rect; - - layer->SetTexturePriorities(priority_calculator_); - resource_manager_->PrioritizeTextures(); - layer->SavePaintProperties(); - - // Update the whole tile. - layer->Update(queue_.get(), nullptr); - layer->tracking_layer_painter()->ResetPaintedRect(); - - EXPECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect()); - UpdateTextures(); - - // Invalidate the entire layer in layer space. When painting, the rect given - // to webkit should match the layer's bounds. - layer->SetNeedsDisplayRect(layer_rect); - layer->Update(queue_.get(), nullptr); - - // Rounding leads to an extra pixel. - gfx::Rect expanded_layer_rect(layer_rect); - expanded_layer_rect.set_height(32); - EXPECT_EQ(expanded_layer_rect, - layer->tracking_layer_painter()->PaintedRect()); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/layers/ui_resource_layer.cc b/chromium/cc/layers/ui_resource_layer.cc index fd107b1ed07..87512ebd016 100644 --- a/chromium/cc/layers/ui_resource_layer.cc +++ b/chromium/cc/layers/ui_resource_layer.cc @@ -5,9 +5,6 @@ #include "cc/layers/ui_resource_layer.h" #include "cc/layers/ui_resource_layer_impl.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/resource_update.h" -#include "cc/resources/resource_update_queue.h" #include "cc/resources/scoped_ui_resource.h" #include "cc/resources/ui_resource_bitmap.h" #include "cc/trees/layer_tree_host.h" @@ -51,14 +48,13 @@ class SharedUIResourceHolder : public UIResourceLayer::UIResourceHolder { UIResourceLayer::UIResourceHolder::~UIResourceHolder() {} -scoped_refptr<UIResourceLayer> UIResourceLayer::Create() { - return make_scoped_refptr(new UIResourceLayer()); +scoped_refptr<UIResourceLayer> UIResourceLayer::Create( + const LayerSettings& settings) { + return make_scoped_refptr(new UIResourceLayer(settings)); } -UIResourceLayer::UIResourceLayer() - : Layer(), - uv_top_left_(0.f, 0.f), - uv_bottom_right_(1.f, 1.f) { +UIResourceLayer::UIResourceLayer(const LayerSettings& settings) + : Layer(settings), uv_top_left_(0.f, 0.f), uv_bottom_right_(1.f, 1.f) { vertex_opacity_[0] = 1.0f; vertex_opacity_[1] = 1.0f; vertex_opacity_[2] = 1.0f; diff --git a/chromium/cc/layers/ui_resource_layer.h b/chromium/cc/layers/ui_resource_layer.h index dc2006e12bf..600f245dd6b 100644 --- a/chromium/cc/layers/ui_resource_layer.h +++ b/chromium/cc/layers/ui_resource_layer.h @@ -18,7 +18,7 @@ class ScopedUIResource; class CC_EXPORT UIResourceLayer : public Layer { public: - static scoped_refptr<UIResourceLayer> Create(); + static scoped_refptr<UIResourceLayer> Create(const LayerSettings& settings); void PushPropertiesTo(LayerImpl* layer) override; @@ -48,7 +48,7 @@ class CC_EXPORT UIResourceLayer : public Layer { }; protected: - UIResourceLayer(); + explicit UIResourceLayer(const LayerSettings& settings); ~UIResourceLayer() override; bool HasDrawableContent() const override; diff --git a/chromium/cc/layers/ui_resource_layer_impl.cc b/chromium/cc/layers/ui_resource_layer_impl.cc index 582ea9eb924..9fb703ef6fe 100644 --- a/chromium/cc/layers/ui_resource_layer_impl.cc +++ b/chromium/cc/layers/ui_resource_layer_impl.cc @@ -98,13 +98,13 @@ void UIResourceLayerImpl::AppendQuads( render_pass->CreateAndAppendSharedQuadState(); PopulateSharedQuadState(shared_quad_state); - AppendDebugBorderQuad( - render_pass, content_bounds(), shared_quad_state, append_quads_data); + AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state, + append_quads_data); if (!ui_resource_id_) return; - ResourceProvider::ResourceId resource = + ResourceId resource = layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_); if (!resource) diff --git a/chromium/cc/layers/ui_resource_layer_impl_unittest.cc b/chromium/cc/layers/ui_resource_layer_impl_unittest.cc index b725e6d44e9..e31d68ae6e5 100644 --- a/chromium/cc/layers/ui_resource_layer_impl_unittest.cc +++ b/chromium/cc/layers/ui_resource_layer_impl_unittest.cc @@ -13,6 +13,7 @@ #include "cc/test/fake_ui_resource_layer_tree_host_impl.h" #include "cc/test/layer_test_common.h" #include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -27,12 +28,11 @@ scoped_ptr<UIResourceLayerImpl> GenerateUIResourceLayer( const gfx::Size& layer_size, bool opaque, UIResourceId uid) { - gfx::Rect visible_content_rect(layer_size); + gfx::Rect visible_layer_rect(layer_size); scoped_ptr<UIResourceLayerImpl> layer = UIResourceLayerImpl::Create(host_impl->active_tree(), 1); - layer->draw_properties().visible_content_rect = visible_content_rect; + layer->draw_properties().visible_layer_rect = visible_layer_rect; layer->SetBounds(layer_size); - layer->SetContentBounds(layer_size); layer->SetHasRenderSurface(true); layer->draw_properties().render_target = layer.get(); @@ -59,7 +59,9 @@ void QuadSizeTest(scoped_ptr<UIResourceLayerImpl> layer, TEST(UIResourceLayerImplTest, VerifyDrawQuads) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager); + TestTaskGraphRunner task_graph_runner; + FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); // Make sure we're appending quads when there are valid values. @@ -103,7 +105,9 @@ void OpaqueBoundsTest(scoped_ptr<UIResourceLayerImpl> layer, TEST(UIResourceLayerImplTest, VerifySetOpaqueOnSkBitmap) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager); + TestTaskGraphRunner task_graph_runner; + FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); gfx::Size bitmap_size(100, 100); @@ -131,7 +135,9 @@ TEST(UIResourceLayerImplTest, VerifySetOpaqueOnSkBitmap) { TEST(UIResourceLayerImplTest, VerifySetOpaqueOnLayer) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager); + TestTaskGraphRunner task_graph_runner; + FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.InitializeRenderer(FakeOutputSurface::Create3d()); gfx::Size bitmap_size(100, 100); @@ -167,7 +173,6 @@ TEST(UIResourceLayerImplTest, Occlusion) { UIResourceLayerImpl* ui_resource_layer_impl = impl.AddChildToRoot<UIResourceLayerImpl>(); ui_resource_layer_impl->SetBounds(layer_size); - ui_resource_layer_impl->SetContentBounds(layer_size); ui_resource_layer_impl->SetDrawsContent(true); ui_resource_layer_impl->SetUIResourceId(uid); @@ -185,7 +190,7 @@ TEST(UIResourceLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(ui_resource_layer_impl->visible_content_rect()); + gfx::Rect occluded(ui_resource_layer_impl->visible_layer_rect()); impl.AppendQuadsWithOcclusion(ui_resource_layer_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); diff --git a/chromium/cc/layers/ui_resource_layer_unittest.cc b/chromium/cc/layers/ui_resource_layer_unittest.cc index d0d356d6c5a..3d2681e74bd 100644 --- a/chromium/cc/layers/ui_resource_layer_unittest.cc +++ b/chromium/cc/layers/ui_resource_layer_unittest.cc @@ -5,17 +5,15 @@ #include "cc/layers/ui_resource_layer.h" #include "base/thread_task_runner_handle.h" -#include "cc/resources/prioritized_resource_manager.h" #include "cc/resources/resource_provider.h" -#include "cc/resources/resource_update_queue.h" #include "cc/resources/scoped_ui_resource.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/geometry_test_utils.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host.h" -#include "cc/trees/occlusion_tracker.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -31,8 +29,9 @@ namespace { class TestUIResourceLayer : public UIResourceLayer { public: - static scoped_refptr<TestUIResourceLayer> Create() { - return make_scoped_refptr(new TestUIResourceLayer()); + static scoped_refptr<TestUIResourceLayer> Create( + const LayerSettings& settings) { + return make_scoped_refptr(new TestUIResourceLayer(settings)); } UIResourceId GetUIResourceId() { @@ -42,7 +41,10 @@ class TestUIResourceLayer : public UIResourceLayer { } protected: - TestUIResourceLayer() : UIResourceLayer() { SetIsDrawable(true); } + explicit TestUIResourceLayer(const LayerSettings& settings) + : UIResourceLayer(settings) { + SetIsDrawable(true); + } ~TestUIResourceLayer() override {} }; @@ -52,7 +54,8 @@ class UIResourceLayerTest : public testing::Test { protected: void SetUp() override { - layer_tree_host_ = FakeLayerTreeHost::Create(&fake_client_); + layer_tree_host_ = + FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_); layer_tree_host_->InitializeSingleThreaded( &fake_client_, base::ThreadTaskRunnerHandle::Get(), nullptr); } @@ -62,11 +65,14 @@ class UIResourceLayerTest : public testing::Test { } FakeLayerTreeHostClient fake_client_; + TestTaskGraphRunner task_graph_runner_; scoped_ptr<FakeLayerTreeHost> layer_tree_host_; + LayerSettings layer_settings_; }; TEST_F(UIResourceLayerTest, SetBitmap) { - scoped_refptr<UIResourceLayer> test_layer = TestUIResourceLayer::Create(); + scoped_refptr<UIResourceLayer> test_layer = + TestUIResourceLayer::Create(layer_settings_); ASSERT_TRUE(test_layer.get()); test_layer->SetBounds(gfx::Size(100, 100)); @@ -74,11 +80,8 @@ TEST_F(UIResourceLayerTest, SetBitmap) { Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get()); - ResourceUpdateQueue queue; - gfx::Rect screen_space_clip_rect; - OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); test_layer->SavePaintProperties(); - test_layer->Update(&queue, &occlusion_tracker); + test_layer->Update(); EXPECT_FALSE(test_layer->DrawsContent()); @@ -87,13 +90,14 @@ TEST_F(UIResourceLayerTest, SetBitmap) { bitmap.setImmutable(); test_layer->SetBitmap(bitmap); - test_layer->Update(&queue, &occlusion_tracker); + test_layer->Update(); EXPECT_TRUE(test_layer->DrawsContent()); } TEST_F(UIResourceLayerTest, SetUIResourceId) { - scoped_refptr<TestUIResourceLayer> test_layer = TestUIResourceLayer::Create(); + scoped_refptr<TestUIResourceLayer> test_layer = + TestUIResourceLayer::Create(layer_settings_); ASSERT_TRUE(test_layer.get()); test_layer->SetBounds(gfx::Size(100, 100)); @@ -101,11 +105,8 @@ TEST_F(UIResourceLayerTest, SetUIResourceId) { Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get()); - ResourceUpdateQueue queue; - gfx::Rect screen_space_clip_rect; - OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); test_layer->SavePaintProperties(); - test_layer->Update(&queue, &occlusion_tracker); + test_layer->Update(); EXPECT_FALSE(test_layer->DrawsContent()); @@ -113,7 +114,7 @@ TEST_F(UIResourceLayerTest, SetUIResourceId) { scoped_ptr<ScopedUIResource> resource = ScopedUIResource::Create( layer_tree_host_.get(), UIResourceBitmap(gfx::Size(10, 10), is_opaque)); test_layer->SetUIResourceId(resource->id()); - test_layer->Update(&queue, &occlusion_tracker); + test_layer->Update(); EXPECT_TRUE(test_layer->DrawsContent()); @@ -128,7 +129,8 @@ TEST_F(UIResourceLayerTest, SetUIResourceId) { } TEST_F(UIResourceLayerTest, BitmapClearedOnSetUIResourceId) { - scoped_refptr<UIResourceLayer> test_layer = TestUIResourceLayer::Create(); + scoped_refptr<UIResourceLayer> test_layer = + TestUIResourceLayer::Create(layer_settings_); ASSERT_TRUE(test_layer.get()); test_layer->SetBounds(gfx::Size(100, 100)); diff --git a/chromium/cc/layers/video_frame_provider_client_impl.h b/chromium/cc/layers/video_frame_provider_client_impl.h index 5429228b49b..e626b541405 100644 --- a/chromium/cc/layers/video_frame_provider_client_impl.h +++ b/chromium/cc/layers/video_frame_provider_client_impl.h @@ -59,6 +59,10 @@ class CC_EXPORT VideoFrameProviderClientImpl void DidReceiveFrame() override; void DidUpdateMatrix(const float* matrix) override; + const VideoFrameProvider* get_provider_for_testing() const { + return provider_; + } + private: friend class base::RefCounted<VideoFrameProviderClientImpl>; diff --git a/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc b/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc new file mode 100644 index 00000000000..05385e46e56 --- /dev/null +++ b/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc @@ -0,0 +1,166 @@ +// Copyright 2015 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/layers/video_frame_provider_client_impl.h" +#include "cc/layers/video_layer_impl.h" +#include "cc/output/begin_frame_args.h" +#include "cc/test/fake_video_frame_provider.h" +#include "cc/test/layer_test_common.h" +#include "media/base/video_frame.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; + +namespace cc { + +// NOTE: We cannot use DebugScopedSetImplThreadAndMainThreadBlocked in these +// tests because it gets destroyed before the VideoLayerImpl is destroyed. This +// causes a DCHECK in VideoLayerImpl's destructor to fail. +static void DebugSetImplThreadAndMainThreadBlocked(Proxy* proxy) { +#if DCHECK_IS_ON() + proxy->SetCurrentThreadIsImplThread(true); + proxy->SetMainThreadBlocked(true); +#endif +} + +class VideoFrameProviderClientImplTest : public testing::Test, + public VideoFrameControllerClient { + public: + VideoFrameProviderClientImplTest() + : client_impl_(VideoFrameProviderClientImpl::Create(&provider_, this)), + video_layer_impl_(nullptr), + test_frame_(media::VideoFrame::CreateFrame(media::VideoFrame::YV12, + gfx::Size(10, 10), + gfx::Rect(10, 10), + gfx::Size(10, 10), + base::TimeDelta())) { + DebugSetImplThreadAndMainThreadBlocked(impl_.proxy()); + } + + ~VideoFrameProviderClientImplTest() { + if (!client_impl_->Stopped()) { + client_impl_->Stop(); + DCHECK(client_impl_->Stopped()); + DCHECK(!client_impl_->ActiveVideoLayer()); + } + + provider_.SetVideoFrameProviderClient(nullptr); + } + + void StartRendering() { + EXPECT_CALL(*this, AddVideoFrameController(_)); + client_impl_->StartRendering(); + } + + void StopRendering() { + EXPECT_CALL(*this, RemoveVideoFrameController(_)); + client_impl_->StopRendering(); + } + + void StartRenderingAndRenderFrame() { + EXPECT_FALSE(client_impl_->HasCurrentFrame()); + provider_.set_frame(test_frame_); + EXPECT_TRUE(client_impl_->HasCurrentFrame()); + + // Start rendering and verify SetNeedsRedraw() was called for the new frame. + StartRendering(); + EXPECT_EQ(gfx::Rect(), video_layer_impl_->update_rect()); + client_impl_->OnBeginFrame(BeginFrameArgs()); + EXPECT_NE(gfx::Rect(), video_layer_impl_->update_rect()); + } + + void CreateActiveVideoLayer() { + gfx::Size layer_size(100, 100); + video_layer_impl_ = impl_.AddChildToRoot<VideoLayerImpl>( + &provider_, media::VIDEO_ROTATION_0); + video_layer_impl_->SetBounds(layer_size); + video_layer_impl_->SetDrawsContent(true); + client_impl_->SetActiveVideoLayer(video_layer_impl_); + ASSERT_TRUE(client_impl_->ActiveVideoLayer()); + } + + MOCK_METHOD1(AddVideoFrameController, void(VideoFrameController*)); + MOCK_METHOD1(RemoveVideoFrameController, void(VideoFrameController*)); + + protected: + FakeVideoFrameProvider provider_; + LayerTestCommon::LayerImplTest impl_; + scoped_refptr<VideoFrameProviderClientImpl> client_impl_; + VideoLayerImpl* video_layer_impl_; + scoped_refptr<media::VideoFrame> test_frame_; + + private: + DISALLOW_COPY_AND_ASSIGN(VideoFrameProviderClientImplTest); +}; + +TEST_F(VideoFrameProviderClientImplTest, StartStopRendering) { + StartRendering(); + StopRendering(); +} + +TEST_F(VideoFrameProviderClientImplTest, StopUsingProvider) { + ASSERT_TRUE(client_impl_->get_provider_for_testing()); + StartRendering(); + EXPECT_CALL(*this, RemoveVideoFrameController(_)); + client_impl_->StopUsingProvider(); + ASSERT_FALSE(client_impl_->get_provider_for_testing()); +} + +TEST_F(VideoFrameProviderClientImplTest, FrameAcquisition) { + CreateActiveVideoLayer(); + StartRenderingAndRenderFrame(); + + // Verify GetCurrentFrame() and PutCurrentFrame() work correctly. + EXPECT_EQ(test_frame_, client_impl_->AcquireLockAndCurrentFrame()); + EXPECT_EQ(0, provider_.put_current_frame_count()); + client_impl_->PutCurrentFrame(); + EXPECT_EQ(1, provider_.put_current_frame_count()); + + client_impl_->ReleaseLock(); + StopRendering(); +} + +TEST_F(VideoFrameProviderClientImplTest, DidReceiveFrame) { + CreateActiveVideoLayer(); + EXPECT_EQ(gfx::Rect(), video_layer_impl_->update_rect()); + client_impl_->DidReceiveFrame(); + EXPECT_NE(gfx::Rect(), video_layer_impl_->update_rect()); +} + +TEST_F(VideoFrameProviderClientImplTest, DidDrawFrameIssuesPutCurrentFrame) { + CreateActiveVideoLayer(); + StartRenderingAndRenderFrame(); + EXPECT_EQ(0, provider_.put_current_frame_count()); + client_impl_->DidDrawFrame(); + EXPECT_EQ(1, provider_.put_current_frame_count()); + StopRendering(); +} + +TEST_F(VideoFrameProviderClientImplTest, StreamTextureMatrix) { + const float kIdentityMatrix[] = { + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + }; + + EXPECT_FALSE(client_impl_->StreamTextureMatrix().IsIdentity()); + client_impl_->DidUpdateMatrix(kIdentityMatrix); + EXPECT_TRUE(client_impl_->StreamTextureMatrix().IsIdentity()); +} + +} // namespace cc diff --git a/chromium/cc/layers/video_layer.cc b/chromium/cc/layers/video_layer.cc index fe37fbf47de..cae00aacf1d 100644 --- a/chromium/cc/layers/video_layer.cc +++ b/chromium/cc/layers/video_layer.cc @@ -9,14 +9,16 @@ namespace cc { scoped_refptr<VideoLayer> VideoLayer::Create( + const LayerSettings& settings, VideoFrameProvider* provider, media::VideoRotation video_rotation) { - return make_scoped_refptr(new VideoLayer(provider, video_rotation)); + return make_scoped_refptr(new VideoLayer(settings, provider, video_rotation)); } -VideoLayer::VideoLayer(VideoFrameProvider* provider, +VideoLayer::VideoLayer(const LayerSettings& settings, + VideoFrameProvider* provider, media::VideoRotation video_rotation) - : provider_(provider), video_rotation_(video_rotation) { + : Layer(settings), provider_(provider), video_rotation_(video_rotation) { DCHECK(provider_); } @@ -28,9 +30,8 @@ scoped_ptr<LayerImpl> VideoLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) { return impl.Pass(); } -bool VideoLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - bool updated = Layer::Update(queue, occlusion); +bool VideoLayer::Update() { + bool updated = Layer::Update(); // Video layer doesn't update any resources from the main thread side, // but repaint rects need to be sent to the VideoLayerImpl via commit. diff --git a/chromium/cc/layers/video_layer.h b/chromium/cc/layers/video_layer.h index bbcff36d52d..575de4664f0 100644 --- a/chromium/cc/layers/video_layer.h +++ b/chromium/cc/layers/video_layer.h @@ -20,16 +20,18 @@ class VideoLayerImpl; // A Layer that contains a Video element. class CC_EXPORT VideoLayer : public Layer { public: - static scoped_refptr<VideoLayer> Create(VideoFrameProvider* provider, + static scoped_refptr<VideoLayer> Create(const LayerSettings& settings, + VideoFrameProvider* provider, media::VideoRotation video_rotation); scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override; + bool Update() override; private: - VideoLayer(VideoFrameProvider* provider, media::VideoRotation video_rotation); + VideoLayer(const LayerSettings& settings, + VideoFrameProvider* provider, + media::VideoRotation video_rotation); ~VideoLayer() override; // This pointer is only for passing to VideoLayerImpl's constructor. It should diff --git a/chromium/cc/layers/video_layer_impl.cc b/chromium/cc/layers/video_layer_impl.cc index d73786d9bf4..2233583ed09 100644 --- a/chromium/cc/layers/video_layer_impl.cc +++ b/chromium/cc/layers/video_layer_impl.cc @@ -124,8 +124,11 @@ bool VideoLayerImpl::WillDraw(DrawMode draw_mode, unsigned resource_id = resource_provider->CreateResourceFromTextureMailbox( external_resources.mailboxes[i], SingleReleaseCallbackImpl::Create( - external_resources.release_callbacks[i])); - frame_resources_.push_back(resource_id); + external_resources.release_callbacks[i]), + external_resources.read_lock_fences_enabled); + frame_resources_.push_back(FrameResource( + resource_id, external_resources.mailboxes[i].size_in_pixels(), + external_resources.mailboxes[i].allow_overlay())); } return true; @@ -136,7 +139,7 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass, DCHECK(frame_.get()); gfx::Transform transform = draw_transform(); - gfx::Size rotated_size = content_bounds(); + gfx::Size rotated_size = bounds(); switch (video_rotation_) { case media::VIDEO_ROTATION_90: @@ -158,7 +161,7 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass, SharedQuadState* shared_quad_state = render_pass->CreateAndAppendSharedQuadState(); - shared_quad_state->SetAll(transform, rotated_size, visible_content_rect(), + shared_quad_state->SetAll(transform, rotated_size, visible_layer_rect(), clip_rect(), is_clipped(), draw_opacity(), draw_blend_mode(), sorting_context_id()); @@ -219,17 +222,22 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass, DCHECK_GE(frame_resources_.size(), 3u); YUVVideoDrawQuad::ColorSpace color_space = YUVVideoDrawQuad::REC_601; - if (frame_->format() == media::VideoFrame::YV12J) { - color_space = YUVVideoDrawQuad::JPEG; - } else if (frame_->format() == media::VideoFrame::YV12HD) { - color_space = YUVVideoDrawQuad::REC_709; + int videoframe_color_space; + if (frame_->metadata()->GetInteger(media::VideoFrameMetadata::COLOR_SPACE, + &videoframe_color_space)) { + if (videoframe_color_space == media::VideoFrame::COLOR_SPACE_JPEG) { + color_space = YUVVideoDrawQuad::JPEG; + } else if (videoframe_color_space == + media::VideoFrame::COLOR_SPACE_HD_REC709) { + color_space = YUVVideoDrawQuad::REC_709; + } } const gfx::Size ya_tex_size = coded_size; gfx::Size uv_tex_size; - if (frame_->format() == media::VideoFrame::NATIVE_TEXTURE) { - DCHECK_EQ(media::VideoFrame::TEXTURE_YUV_420, frame_->texture_format()); + if (frame_->HasTextures()) { + DCHECK_EQ(media::VideoFrame::I420, frame_->format()); DCHECK_EQ(3u, frame_resources_.size()); // Alpha is not supported yet. DCHECK(visible_rect.origin().IsOrigin()); DCHECK(visible_rect.size() == coded_size); @@ -266,8 +274,10 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass, yuv_video_quad->SetNew( shared_quad_state, quad_rect, opaque_rect, visible_quad_rect, ya_tex_coord_rect, uv_tex_coord_rect, ya_tex_size, uv_tex_size, - frame_resources_[0], frame_resources_[1], frame_resources_[2], - frame_resources_.size() > 3 ? frame_resources_[3] : 0, color_space); + frame_resources_[0].id, frame_resources_[1].id, + frame_resources_[2].id, + frame_resources_.size() > 3 ? frame_resources_[3].id : 0, + color_space); ValidateQuadResources(yuv_video_quad); break; } @@ -285,17 +295,10 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass, bool nearest_neighbor = false; TextureDrawQuad* texture_quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); - texture_quad->SetNew(shared_quad_state, - quad_rect, - opaque_rect, - visible_quad_rect, - frame_resources_[0], - premultiplied_alpha, - uv_top_left, - uv_bottom_right, - SK_ColorTRANSPARENT, - opacity, - flipped, + texture_quad->SetNew(shared_quad_state, quad_rect, opaque_rect, + visible_quad_rect, frame_resources_[0].id, + premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, opacity, flipped, nearest_neighbor); ValidateQuadResources(texture_quad); break; @@ -310,7 +313,8 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass, render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>(); stream_video_quad->SetNew( shared_quad_state, quad_rect, opaque_rect, visible_quad_rect, - frame_resources_[0], + frame_resources_[0].id, frame_resources_[0].size_in_pixels, + frame_resources_[0].allow_overlay, scale * provider_client_impl_->StreamTextureMatrix()); ValidateQuadResources(stream_video_quad); break; @@ -321,12 +325,9 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass, break; IOSurfaceDrawQuad* io_surface_quad = render_pass->CreateAndAppendDrawQuad<IOSurfaceDrawQuad>(); - io_surface_quad->SetNew(shared_quad_state, - quad_rect, - opaque_rect, - visible_quad_rect, - visible_rect.size(), - frame_resources_[0], + io_surface_quad->SetNew(shared_quad_state, quad_rect, opaque_rect, + visible_quad_rect, visible_rect.size(), + frame_resources_[0].id, IOSurfaceDrawQuad::UNFLIPPED); ValidateQuadResources(io_surface_quad); break; @@ -378,7 +379,7 @@ void VideoLayerImpl::DidDraw(ResourceProvider* resource_provider) { software_release_callback_.Reset(); } else { for (size_t i = 0; i < frame_resources_.size(); ++i) - resource_provider->DeleteResource(frame_resources_[i]); + resource_provider->DeleteResource(frame_resources_[i].id); frame_resources_.clear(); } @@ -388,11 +389,11 @@ void VideoLayerImpl::DidDraw(ResourceProvider* resource_provider) { provider_client_impl_->ReleaseLock(); } -SimpleEnclosedRegion VideoLayerImpl::VisibleContentOpaqueRegion() const { +SimpleEnclosedRegion VideoLayerImpl::VisibleOpaqueRegion() const { // If we don't have a frame yet, then we don't have an opaque region. if (!provider_client_impl_->HasCurrentFrame()) return SimpleEnclosedRegion(); - return LayerImpl::VisibleContentOpaqueRegion(); + return LayerImpl::VisibleOpaqueRegion(); } void VideoLayerImpl::ReleaseResources() { diff --git a/chromium/cc/layers/video_layer_impl.h b/chromium/cc/layers/video_layer_impl.h index aea38b5cbbe..6fab7f58dcb 100644 --- a/chromium/cc/layers/video_layer_impl.h +++ b/chromium/cc/layers/video_layer_impl.h @@ -38,7 +38,7 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl { void AppendQuads(RenderPass* render_pass, AppendQuadsData* append_quads_data) override; void DidDraw(ResourceProvider* resource_provider) override; - SimpleEnclosedRegion VisibleContentOpaqueRegion() const override; + SimpleEnclosedRegion VisibleOpaqueRegion() const override; void DidBecomeActive() override; void ReleaseResources() override; @@ -62,7 +62,16 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl { scoped_ptr<VideoResourceUpdater> updater_; VideoFrameExternalResources::ResourceType frame_resource_type_; - std::vector<ResourceProvider::ResourceId> frame_resources_; + struct FrameResource { + FrameResource(ResourceId id, gfx::Size size_in_pixels, bool allow_overlay) + : id(id), + size_in_pixels(size_in_pixels), + allow_overlay(allow_overlay) {} + ResourceId id; + gfx::Size size_in_pixels; + bool allow_overlay; + }; + std::vector<FrameResource> frame_resources_; // TODO(danakj): Remove these, hide software path inside ResourceProvider and // ExternalResource (aka TextureMailbox) classes. diff --git a/chromium/cc/layers/video_layer_impl_unittest.cc b/chromium/cc/layers/video_layer_impl_unittest.cc index b0ecff95d39..da2de85d9ef 100644 --- a/chromium/cc/layers/video_layer_impl_unittest.cc +++ b/chromium/cc/layers/video_layer_impl_unittest.cc @@ -47,7 +47,6 @@ TEST(VideoLayerImplTest, Occlusion) { VideoLayerImpl* video_layer_impl = impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0); video_layer_impl->SetBounds(layer_size); - video_layer_impl->SetContentBounds(layer_size); video_layer_impl->SetDrawsContent(true); impl.CalcDrawProps(viewport_size); @@ -64,7 +63,7 @@ TEST(VideoLayerImplTest, Occlusion) { { SCOPED_TRACE("Full occlusion"); - gfx::Rect occluded(video_layer_impl->visible_content_rect()); + gfx::Rect occluded(video_layer_impl->visible_layer_rect()); impl.AppendQuadsWithOcclusion(video_layer_impl, occluded); LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect()); @@ -98,7 +97,6 @@ TEST(VideoLayerImplTest, OccludesOtherLayers) { scoped_ptr<LayerImpl> layer_impl = LayerImpl::Create(active_tree, 3); layer_impl->SetHasRenderSurface(true); layer_impl->SetBounds(layer_size); - layer_impl->SetContentBounds(layer_size); layer_impl->SetDrawsContent(true); const auto& draw_properties = layer_impl->draw_properties(); @@ -106,13 +104,14 @@ TEST(VideoLayerImplTest, OccludesOtherLayers) { scoped_ptr<VideoLayerImpl> video_layer_impl = VideoLayerImpl::Create( active_tree, 4, &provider, media::VIDEO_ROTATION_0); video_layer_impl->SetBounds(layer_size); - video_layer_impl->SetContentBounds(layer_size); video_layer_impl->SetDrawsContent(true); video_layer_impl->SetContentsOpaque(true); layer_impl->AddChild(video_layer_impl.Pass()); active_tree->SetRootLayer(layer_impl.Pass()); + active_tree->BuildPropertyTreesForTesting(); + active_tree->UpdateDrawProperties(false); // We don't have a frame yet, so the video doesn't occlude the layer below it. @@ -165,7 +164,6 @@ TEST(VideoLayerImplTest, Rotated0) { VideoLayerImpl* video_layer_impl = impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0); video_layer_impl->SetBounds(layer_size); - video_layer_impl->SetContentBounds(layer_size); video_layer_impl->SetDrawsContent(true); impl.CalcDrawProps(viewport_size); @@ -176,8 +174,12 @@ TEST(VideoLayerImplTest, Rotated0) { gfx::Point3F p1(0, impl.quad_list().front()->rect.height(), 0); gfx::Point3F p2(impl.quad_list().front()->rect.width(), 0, 0); - impl.quad_list().front()->quadTransform().TransformPoint(&p1); - impl.quad_list().front()->quadTransform().TransformPoint(&p2); + impl.quad_list() + .front() + ->shared_quad_state->quad_to_target_transform.TransformPoint(&p1); + impl.quad_list() + .front() + ->shared_quad_state->quad_to_target_transform.TransformPoint(&p2); EXPECT_EQ(gfx::Point3F(0, 50, 0), p1); EXPECT_EQ(gfx::Point3F(100, 0, 0), p2); } @@ -201,7 +203,6 @@ TEST(VideoLayerImplTest, Rotated90) { VideoLayerImpl* video_layer_impl = impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_90); video_layer_impl->SetBounds(layer_size); - video_layer_impl->SetContentBounds(layer_size); video_layer_impl->SetDrawsContent(true); impl.CalcDrawProps(viewport_size); @@ -212,8 +213,12 @@ TEST(VideoLayerImplTest, Rotated90) { gfx::Point3F p1(0, impl.quad_list().front()->rect.height(), 0); gfx::Point3F p2(impl.quad_list().front()->rect.width(), 0, 0); - impl.quad_list().front()->quadTransform().TransformPoint(&p1); - impl.quad_list().front()->quadTransform().TransformPoint(&p2); + impl.quad_list() + .front() + ->shared_quad_state->quad_to_target_transform.TransformPoint(&p1); + impl.quad_list() + .front() + ->shared_quad_state->quad_to_target_transform.TransformPoint(&p2); EXPECT_EQ(gfx::Point3F(0, 0, 0), p1); EXPECT_EQ(gfx::Point3F(100, 50, 0), p2); } @@ -237,7 +242,6 @@ TEST(VideoLayerImplTest, Rotated180) { VideoLayerImpl* video_layer_impl = impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_180); video_layer_impl->SetBounds(layer_size); - video_layer_impl->SetContentBounds(layer_size); video_layer_impl->SetDrawsContent(true); impl.CalcDrawProps(viewport_size); @@ -248,8 +252,12 @@ TEST(VideoLayerImplTest, Rotated180) { gfx::Point3F p1(0, impl.quad_list().front()->rect.height(), 0); gfx::Point3F p2(impl.quad_list().front()->rect.width(), 0, 0); - impl.quad_list().front()->quadTransform().TransformPoint(&p1); - impl.quad_list().front()->quadTransform().TransformPoint(&p2); + impl.quad_list() + .front() + ->shared_quad_state->quad_to_target_transform.TransformPoint(&p1); + impl.quad_list() + .front() + ->shared_quad_state->quad_to_target_transform.TransformPoint(&p2); EXPECT_EQ(gfx::Point3F(100, 0, 0), p1); EXPECT_EQ(gfx::Point3F(0, 50, 0), p2); } @@ -273,7 +281,6 @@ TEST(VideoLayerImplTest, Rotated270) { VideoLayerImpl* video_layer_impl = impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_270); video_layer_impl->SetBounds(layer_size); - video_layer_impl->SetContentBounds(layer_size); video_layer_impl->SetDrawsContent(true); impl.CalcDrawProps(viewport_size); @@ -284,8 +291,12 @@ TEST(VideoLayerImplTest, Rotated270) { gfx::Point3F p1(0, impl.quad_list().front()->rect.height(), 0); gfx::Point3F p2(impl.quad_list().front()->rect.width(), 0, 0); - impl.quad_list().front()->quadTransform().TransformPoint(&p1); - impl.quad_list().front()->quadTransform().TransformPoint(&p2); + impl.quad_list() + .front() + ->shared_quad_state->quad_to_target_transform.TransformPoint(&p1); + impl.quad_list() + .front() + ->shared_quad_state->quad_to_target_transform.TransformPoint(&p2); EXPECT_EQ(gfx::Point3F(100, 50, 0), p1); EXPECT_EQ(gfx::Point3F(0, 0, 0), p2); } @@ -313,7 +324,6 @@ TEST(VideoLayerImplTest, SoftwareVideoFrameGeneratesYUVQuad) { VideoLayerImpl* video_layer_impl = impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0); video_layer_impl->SetBounds(layer_size); - video_layer_impl->SetContentBounds(layer_size); video_layer_impl->SetDrawsContent(true); gfx::Rect occluded; @@ -345,14 +355,15 @@ TEST(VideoLayerImplTest, NativeYUVFrameGeneratesYUVQuad) { media::VideoFrame::WrapYUV420NativeTextures( mailbox_holder, mailbox_holder, mailbox_holder, base::Bind(EmptyCallback), gfx::Size(10, 10), gfx::Rect(10, 10), - gfx::Size(10, 10), base::TimeDelta(), true); + gfx::Size(10, 10), base::TimeDelta()); + video_frame->metadata()->SetBoolean(media::VideoFrameMetadata::ALLOW_OVERLAY, + true); FakeVideoFrameProvider provider; provider.set_frame(video_frame); VideoLayerImpl* video_layer_impl = impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0); video_layer_impl->SetBounds(layer_size); - video_layer_impl->SetContentBounds(layer_size); video_layer_impl->SetDrawsContent(true); gfx::Rect occluded; diff --git a/chromium/cc/layers/viewport.cc b/chromium/cc/layers/viewport.cc index 944f1bbd3cf..059e0a491a9 100644 --- a/chromium/cc/layers/viewport.cc +++ b/chromium/cc/layers/viewport.cc @@ -20,17 +20,26 @@ scoped_ptr<Viewport> Viewport::Create( } Viewport::Viewport(LayerTreeHostImpl* host_impl) - : host_impl_(host_impl) { + : host_impl_(host_impl) + , pinch_zoom_active_(false) { DCHECK(host_impl_); } +void Viewport::Pan(const gfx::Vector2dF& delta) { + gfx::Vector2dF pending_delta = delta; + float page_scale = host_impl_->active_tree()->current_page_scale_factor(); + pending_delta.Scale(1 / page_scale); + InnerScrollLayer()->ScrollBy(pending_delta); +} + Viewport::ScrollResult Viewport::ScrollBy(const gfx::Vector2dF& delta, const gfx::Point& viewport_point, - bool is_wheel_scroll) { + bool is_wheel_scroll, + bool affect_top_controls) { gfx::Vector2dF content_delta = delta; ScrollResult result; - if (ShouldTopControlsConsumeScroll(delta)) { + if (affect_top_controls && ShouldTopControlsConsumeScroll(delta)) { result.top_controls_applied_delta = ScrollTopControls(delta); content_delta -= result.top_controls_applied_delta; } @@ -59,6 +68,70 @@ Viewport::ScrollResult Viewport::ScrollBy(const gfx::Vector2dF& delta, return result; } +void Viewport::SnapPinchAnchorIfWithinMargin(const gfx::Point& anchor) { + gfx::SizeF viewport_size = + host_impl_->active_tree()->InnerViewportContainerLayer()->bounds(); + + if (anchor.x() < kPinchZoomSnapMarginDips) + pinch_anchor_adjustment_.set_x(-anchor.x()); + else if (anchor.x() > viewport_size.width() - kPinchZoomSnapMarginDips) + pinch_anchor_adjustment_.set_x(viewport_size.width() - anchor.x()); + + if (anchor.y() < kPinchZoomSnapMarginDips) + pinch_anchor_adjustment_.set_y(-anchor.y()); + else if (anchor.y() > viewport_size.height() - kPinchZoomSnapMarginDips) + pinch_anchor_adjustment_.set_y(viewport_size.height() - anchor.y()); +} + +void Viewport::PinchUpdate(float magnify_delta, const gfx::Point& anchor) { + if (!pinch_zoom_active_) { + // If this is the first pinch update and the pinch is within a margin- + // length of the screen edge, offset all updates by the amount so that we + // effectively snap the pinch zoom to the edge of the screen. This makes it + // easy to zoom in on position: fixed elements. + if (host_impl_->settings().invert_viewport_scroll_order) + SnapPinchAnchorIfWithinMargin(anchor); + + pinch_zoom_active_ = true; + } + + LayerTreeImpl* active_tree = host_impl_->active_tree(); + + // Keep the center-of-pinch anchor specified by (x, y) in a stable + // position over the course of the magnify. + gfx::Point adjusted_anchor = anchor + pinch_anchor_adjustment_; + float page_scale = active_tree->current_page_scale_factor(); + gfx::PointF previous_scale_anchor = + gfx::ScalePoint(adjusted_anchor, 1.f / page_scale); + active_tree->SetPageScaleOnActiveTree(page_scale * magnify_delta); + page_scale = active_tree->current_page_scale_factor(); + gfx::PointF new_scale_anchor = + gfx::ScalePoint(adjusted_anchor, 1.f / page_scale); + gfx::Vector2dF move = previous_scale_anchor - new_scale_anchor; + + // Scale back to viewport space since that's the coordinate space ScrollBy + // uses. + move.Scale(page_scale); + + // If clamping the inner viewport scroll offset causes a change, it should + // be accounted for from the intended move. + move -= InnerScrollLayer()->ClampScrollToMaxScrollOffset(); + + if (host_impl_->settings().invert_viewport_scroll_order) { + Pan(move); + } else { + gfx::Point viewport_point; + bool is_wheel_event = false; + bool affect_top_controls = false; + ScrollBy(move, viewport_point, is_wheel_event, affect_top_controls); + } +} + +void Viewport::PinchEnd() { + pinch_anchor_adjustment_ = gfx::Vector2d(); + pinch_zoom_active_ = false; +} + gfx::Vector2dF Viewport::ScrollTopControls(const gfx::Vector2dF& delta) { gfx::Vector2dF excess_delta = host_impl_->top_controls_manager()->ScrollBy(delta); diff --git a/chromium/cc/layers/viewport.h b/chromium/cc/layers/viewport.h index 25528af02a4..01885d7774f 100644 --- a/chromium/cc/layers/viewport.h +++ b/chromium/cc/layers/viewport.h @@ -20,6 +20,11 @@ class LayerTreeHostImpl; // class. class CC_EXPORT Viewport { public: + // If the pinch zoom anchor on the first PinchUpdate is within this length + // of the screen edge, "snap" the zoom to that edge. Experimentally + // determined. + static const int kPinchZoomSnapMarginDips = 100; + struct ScrollResult { gfx::Vector2dF applied_delta; gfx::Vector2dF unused_scroll_delta; @@ -28,11 +33,19 @@ class CC_EXPORT Viewport { static scoped_ptr<Viewport> Create(LayerTreeHostImpl* host_impl); + // Differs from scrolling in that only the visual viewport is moved, without + // affecting the top controls or outer viewport. + void Pan(const gfx::Vector2dF& delta); + // Scrolls the viewport, applying the unique bubbling between the inner and // outer viewport. Scrolls can be consumed by top controls. ScrollResult ScrollBy(const gfx::Vector2dF& delta, const gfx::Point& viewport_point, - bool is_wheel_scroll); + bool is_wheel_scroll, + bool affect_top_controls); + + void PinchUpdate(float magnify_delta, const gfx::Point& anchor); + void PinchEnd(); private: explicit Viewport(LayerTreeHostImpl* host_impl); @@ -49,8 +62,16 @@ class CC_EXPORT Viewport { LayerImpl* InnerScrollLayer() const; LayerImpl* OuterScrollLayer() const; + void SnapPinchAnchorIfWithinMargin(const gfx::Point& anchor); + LayerTreeHostImpl* host_impl_; + bool pinch_zoom_active_; + + // The pinch zoom anchor point is adjusted by this amount during a pinch. This + // is used to "snap" a pinch-zoom to the edge of the screen. + gfx::Vector2d pinch_anchor_adjustment_; + DISALLOW_COPY_AND_ASSIGN(Viewport); }; diff --git a/chromium/cc/output/begin_frame_args.cc b/chromium/cc/output/begin_frame_args.cc index 7a77be2bd52..216eb52587a 100644 --- a/chromium/cc/output/begin_frame_args.cc +++ b/chromium/cc/output/begin_frame_args.cc @@ -5,7 +5,6 @@ #include "cc/output/begin_frame_args.h" #include "base/trace_event/trace_event_argument.h" -#include "ui/gfx/frame_time.h" namespace cc { @@ -28,7 +27,8 @@ BeginFrameArgs::BeginFrameArgs() : frame_time(base::TimeTicks()), deadline(base::TimeTicks()), interval(base::TimeDelta::FromMicroseconds(-1)), - type(BeginFrameArgs::INVALID) { + type(BeginFrameArgs::INVALID), + on_critical_path(true) { } BeginFrameArgs::BeginFrameArgs(base::TimeTicks frame_time, @@ -38,7 +38,8 @@ BeginFrameArgs::BeginFrameArgs(base::TimeTicks frame_time, : frame_time(frame_time), deadline(deadline), interval(interval), - type(type) { + type(type), + on_critical_path(true) { } BeginFrameArgs BeginFrameArgs::Create(BeginFrameArgs::CreationLocation location, @@ -74,6 +75,7 @@ void BeginFrameArgs::AsValueInto(base::trace_event::TracedValue* state) const { #ifndef NDEBUG state->SetString("created_from", created_from.ToString()); #endif + state->SetBoolean("on_critical_path", on_critical_path); } // This is a hard-coded deadline adjustment that assumes 60Hz, to be used in diff --git a/chromium/cc/output/begin_frame_args.h b/chromium/cc/output/begin_frame_args.h index c22f7fdde97..1a7ae5f97a0 100644 --- a/chromium/cc/output/begin_frame_args.h +++ b/chromium/cc/output/begin_frame_args.h @@ -83,6 +83,7 @@ struct CC_EXPORT BeginFrameArgs { base::TimeTicks deadline; base::TimeDelta interval; BeginFrameArgsType type; + bool on_critical_path; private: BeginFrameArgs(base::TimeTicks frame_time, diff --git a/chromium/cc/output/begin_frame_args_unittest.cc b/chromium/cc/output/begin_frame_args_unittest.cc index 877a857c632..c6f5a4203c9 100644 --- a/chromium/cc/output/begin_frame_args_unittest.cc +++ b/chromium/cc/output/begin_frame_args_unittest.cc @@ -8,7 +8,6 @@ #include "cc/test/begin_frame_args_test.h" #include "testing/gtest/include/gtest/gtest-spi.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/frame_time.h" namespace cc { namespace { @@ -33,7 +32,7 @@ TEST(BeginFrameArgsTest, Helpers) { BeginFrameArgs args3 = CreateExpiredBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE); EXPECT_TRUE(args3.IsValid()) << args3; - EXPECT_GT(gfx::FrameTime::Now(), args3.deadline); + EXPECT_GT(base::TimeTicks::Now(), args3.deadline); EXPECT_EQ(BeginFrameArgs::NORMAL, args3.type); BeginFrameArgs args4 = CreateBeginFrameArgsForTesting( @@ -78,6 +77,7 @@ TEST(BeginFrameArgsTest, Create) { // BeginFrames are not valid by default BeginFrameArgs args1; EXPECT_FALSE(args1.IsValid()) << args1; + EXPECT_TRUE(args1.on_critical_path); BeginFrameArgs args2 = BeginFrameArgs::Create( BEGINFRAME_FROM_HERE, base::TimeTicks::FromInternalValue(1), diff --git a/chromium/cc/output/bsp_walk_action.cc b/chromium/cc/output/bsp_walk_action.cc index 9ffc2998d5e..8a3369416ce 100644 --- a/chromium/cc/output/bsp_walk_action.cc +++ b/chromium/cc/output/bsp_walk_action.cc @@ -27,7 +27,9 @@ BspWalkActionDrawPolygon::BspWalkActionDrawPolygon( void BspWalkActionDrawPolygon::operator()(DrawPolygon* item) { gfx::Transform inverse_transform; bool invertible = - item->original_ref()->quadTransform().GetInverse(&inverse_transform); + item->original_ref() + ->shared_quad_state->quad_to_target_transform.GetInverse( + &inverse_transform); DCHECK(invertible); item->TransformToLayerSpace(inverse_transform); renderer_->DoDrawPolygon(*item, frame_, render_pass_scissor_, diff --git a/chromium/cc/output/context_provider.h b/chromium/cc/output/context_provider.h index dfaab4a15b2..aa4367d97ff 100644 --- a/chromium/cc/output/context_provider.h +++ b/chromium/cc/output/context_provider.h @@ -58,9 +58,6 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> { // Returns the capabilities of the currently bound 3d context. virtual Capabilities ContextCapabilities() = 0; - // Checks if the context is currently known to be lost. - virtual bool IsContextLost() = 0; - // Ask the provider to check if the contexts are valid or lost. If they are, // this should invalidate the provider so that it can be replaced with a new // one. diff --git a/chromium/cc/output/delegating_renderer.cc b/chromium/cc/output/delegating_renderer.cc index 7906afa77e6..a8fbbb70cde 100644 --- a/chromium/cc/output/delegating_renderer.cc +++ b/chromium/cc/output/delegating_renderer.cc @@ -66,13 +66,6 @@ const RendererCapabilitiesImpl& DelegatingRenderer::Capabilities() const { return capabilities_; } -static ResourceProvider::ResourceId AppendToArray( - ResourceProvider::ResourceIdArray* array, - ResourceProvider::ResourceId id) { - array->push_back(id); - return id; -} - void DelegatingRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, float device_scale_factor, const gfx::Rect& device_viewport_rect, @@ -90,11 +83,11 @@ void DelegatingRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, // Collect all resource ids in the render passes into a ResourceIdArray. ResourceProvider::ResourceIdArray resources; - DrawQuad::ResourceIteratorCallback append_to_array = - base::Bind(&AppendToArray, &resources); for (const auto& render_pass : out_data.render_pass_list) { - for (const auto& quad : render_pass->quad_list) - quad->IterateResources(append_to_array); + for (const auto& quad : render_pass->quad_list) { + for (ResourceId resource_id : quad->resources) + resources.push_back(resource_id); + } } resource_provider_->PrepareSendToParent(resources, &out_data.resource_list); } @@ -116,7 +109,6 @@ void DelegatingRenderer::DidChangeVisibility() { ContextProvider* context_provider = output_surface_->context_provider(); if (!visible()) { TRACE_EVENT0("cc", "DelegatingRenderer::SetVisible dropping resources"); - resource_provider_->ReleaseCachedData(); if (context_provider) { context_provider->DeleteCachedResources(); context_provider->ContextGL()->Flush(); @@ -125,8 +117,13 @@ void DelegatingRenderer::DidChangeVisibility() { // We loop visibility to the GPU process, since that's what manages memory. // That will allow it to feed us with memory allocations that we can act // upon. - if (context_provider) + if (context_provider) { context_provider->ContextSupport()->SetSurfaceVisible(visible()); + + // If we are not visible, we ask the context to aggressively free resources. + context_provider->ContextSupport()->SetAggressivelyFreeResources( + !visible()); + } } } // namespace cc diff --git a/chromium/cc/output/direct_renderer.cc b/chromium/cc/output/direct_renderer.cc index 10bba297434..7ceaa00379f 100644 --- a/chromium/cc/output/direct_renderer.cc +++ b/chromium/cc/output/direct_renderer.cc @@ -10,6 +10,7 @@ #include "base/containers/hash_tables.h" #include "base/containers/scoped_ptr_hash_map.h" #include "base/metrics/histogram.h" +#include "base/numerics/safe_conversions.h" #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" #include "cc/output/bsp_tree.h" @@ -132,8 +133,7 @@ DirectRenderer::DirectRenderer(RendererClient* client, : Renderer(client, settings), output_surface_(output_surface), resource_provider_(resource_provider), - overlay_processor_( - new OverlayProcessor(output_surface, resource_provider)) { + overlay_processor_(new OverlayProcessor(output_surface)) { overlay_processor_->Initialize(); } @@ -193,8 +193,9 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, const gfx::Rect& device_clip_rect, bool disable_picture_quad_image_filtering) { TRACE_EVENT0("cc", "DirectRenderer::DrawFrame"); - UMA_HISTOGRAM_COUNTS("Renderer4.renderPassCount", - render_passes_in_draw_order->size()); + UMA_HISTOGRAM_COUNTS( + "Renderer4.renderPassCount", + base::saturated_cast<int>(render_passes_in_draw_order->size())); const RenderPass* root_render_pass = render_passes_in_draw_order->back(); DCHECK(root_render_pass); @@ -309,8 +310,8 @@ bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad, if (render_pass_scissor.IsEmpty()) return true; - if (quad.isClipped()) { - gfx::Rect r = quad.clipRect(); + if (quad.shared_quad_state->is_clipped) { + gfx::Rect r = quad.shared_quad_state->clip_rect; r.Intersect(render_pass_scissor); return r.IsEmpty(); } @@ -325,12 +326,12 @@ void DirectRenderer::SetScissorStateForQuad( bool use_render_pass_scissor) { if (use_render_pass_scissor) { gfx::Rect quad_scissor_rect = render_pass_scissor; - if (quad.isClipped()) - quad_scissor_rect.Intersect(quad.clipRect()); + if (quad.shared_quad_state->is_clipped) + quad_scissor_rect.Intersect(quad.shared_quad_state->clip_rect); SetScissorTestRectInDrawSpace(frame, quad_scissor_rect); return; - } else if (quad.isClipped()) { - SetScissorTestRectInDrawSpace(frame, quad.clipRect()); + } else if (quad.shared_quad_state->is_clipped) { + SetScissorTestRectInDrawSpace(frame, quad.shared_quad_state->clip_rect); return; } @@ -461,7 +462,8 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame, // polygons to go into the BSP tree. if (quad.shared_quad_state->sorting_context_id != 0) { scoped_ptr<DrawPolygon> new_polygon(new DrawPolygon( - *it, quad.visible_rect, quad.quadTransform(), next_polygon_id++)); + *it, quad.visible_rect, + quad.shared_quad_state->quad_to_target_transform, next_polygon_id++)); if (new_polygon->points().size() > 2u) { poly_list.push_back(new_polygon.Pass()); } diff --git a/chromium/cc/output/gl_renderer.cc b/chromium/cc/output/gl_renderer.cc index 69da9a74754..3ffc676a66d 100644 --- a/chromium/cc/output/gl_renderer.cc +++ b/chromium/cc/output/gl_renderer.cc @@ -394,6 +394,9 @@ void GLRenderer::DidChangeVisibility() { EnforceMemoryPolicy(); context_support_->SetSurfaceVisible(visible()); + + // If we are not visible, we ask the context to aggressively free resources. + context_support_->SetAggressivelyFreeResources(!visible()); } void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); } @@ -452,13 +455,6 @@ void GLRenderer::ClearFramebuffer(DrawingFrame* frame) { } } -static ResourceProvider::ResourceId WaitOnResourceSyncPoints( - ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id) { - resource_provider->WaitSyncPointIfNeeded(resource_id); - return resource_id; -} - void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { TRACE_EVENT0("cc", "GLRenderer::BeginDrawingFrame"); @@ -493,12 +489,12 @@ void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { // Insert WaitSyncPointCHROMIUM on quad resources prior to drawing the frame, // so that drawing can proceed without GL context switching interruptions. - DrawQuad::ResourceIteratorCallback wait_on_resource_syncpoints_callback = - base::Bind(&WaitOnResourceSyncPoints, resource_provider_); - + ResourceProvider* resource_provider = resource_provider_; for (const auto& pass : *frame->render_passes_in_draw_order) { - for (const auto& quad : pass->quad_list) - quad->IterateResources(wait_on_resource_syncpoints_callback); + for (const auto& quad : pass->quad_list) { + for (ResourceId resource_id : quad->resources) + resource_provider->WaitSyncPointIfNeeded(resource_id); + } } // TODO(enne): Do we need to reinitialize all of this state per frame? @@ -604,12 +600,10 @@ void GLRenderer::DrawCheckerboardQuad(const DrawingFrame* frame, gl_->Uniform1f(program->fragment_shader().frequency_location(), frequency); - SetShaderOpacity(quad->opacity(), + SetShaderOpacity(quad->shared_quad_state->opacity, program->fragment_shader().alpha_location()); - DrawQuadGeometry(frame, - quad->quadTransform(), - quad->rect, - program->vertex_shader().matrix_location()); + DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform, + quad->rect, program->vertex_shader().matrix_location()); } // This function does not handle 3D sorting right now, since the debug border @@ -628,7 +622,9 @@ void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame, // partial swaps. gfx::Rect layer_rect = quad->rect; gfx::Transform render_matrix; - QuadRectTransform(&render_matrix, quad->quadTransform(), layer_rect); + QuadRectTransform(&render_matrix, + quad->shared_quad_state->quad_to_target_transform, + layer_rect); GLRenderer::ToGLMatrix(&gl_matrix[0], frame->projection_matrix * render_matrix); gl_->UniformMatrix4fv(program->vertex_shader().matrix_location(), 1, false, @@ -720,15 +716,10 @@ static skia::RefPtr<SkImage> ApplyImageFilter( canvas->drawSprite(source, 0, 0, &paint); skia::RefPtr<SkImage> image = skia::AdoptRef(surface->newImageSnapshot()); - if (!image || !image->getTexture()) { + if (!image || !image->isTextureBacked()) { return skia::RefPtr<SkImage>(); } - // Flush the GrContext to ensure all buffered GL calls are drawn to the - // backing store before we access and return it, and have cc begin using the - // GL context again. - canvas->flush(); - return image; } @@ -938,7 +929,9 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, DCHECK(contents_texture->id()); gfx::Transform quad_rect_matrix; - QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect); + QuadRectTransform(&quad_rect_matrix, + quad->shared_quad_state->quad_to_target_transform, + quad->rect); gfx::Transform contents_device_transform = frame->window_matrix * frame->projection_matrix * quad_rect_matrix; contents_device_transform.FlattenTo2d(); @@ -948,13 +941,22 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, return; gfx::QuadF surface_quad = SharedGeometryQuad(); - float edge[24]; - bool use_aa = settings_->allow_antialiasing && - ShouldAntialiasQuad(contents_device_transform, quad, - settings_->force_antialiasing); - SetupQuadForClippingAndAntialiasing(contents_device_transform, quad, use_aa, - clip_region, &surface_quad, edge); + gfx::QuadF device_layer_quad; + bool use_aa = false; + if (settings_->allow_antialiasing) { + bool clipped = false; + device_layer_quad = + MathUtil::MapQuad(contents_device_transform, surface_quad, &clipped); + use_aa = ShouldAntialiasQuad(device_layer_quad, clipped, + settings_->force_antialiasing); + } + + float edge[24]; + const gfx::QuadF* aa_quad = use_aa ? &device_layer_quad : nullptr; + SetupRenderPassQuadForClippingAndAntialiasing(contents_device_transform, quad, + aa_quad, clip_region, + &surface_quad, edge); SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode; bool use_shaders_for_blending = !CanApplyBlendModeUsingBlendFunc(blend_mode) || @@ -963,6 +965,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, scoped_ptr<ScopedResource> background_texture; skia::RefPtr<SkImage> background_image; + GLuint background_image_id = 0; gfx::Rect background_rect; if (use_shaders_for_blending) { // Compute a bounding box around the pixels that will be visible through @@ -987,16 +990,19 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, // pixels' coordinate space. background_image = ApplyBackgroundFilters(frame, quad, background_texture.get()); + if (background_image) + background_image_id = background_image->getTextureHandle(true); + DCHECK(background_image_id); } } if (!background_texture) { // Something went wrong with reading the backdrop. - DCHECK(!background_image); + DCHECK(!background_image_id); use_shaders_for_blending = false; - } else if (background_image) { + } else if (background_image_id) { // Reset original background texture if there is not any mask - if (!quad->mask_resource_id) + if (!quad->mask_resource_id()) background_texture.reset(); } else if (CanApplyBlendModeUsingBlendFunc(blend_mode) && ShouldApplyBackgroundFilters(frame, quad)) { @@ -1007,9 +1013,9 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, } // Need original background texture for mask? bool mask_for_background = - background_texture && // Have original background texture - background_image && // Have filtered background texture - quad->mask_resource_id; // Have mask texture + background_texture && // Have original background texture + background_image_id && // Have filtered background texture + quad->mask_resource_id(); // Have mask texture SetBlendEnabled( !use_shaders_for_blending && (quad->ShouldDrawWithBlending() || !IsDefaultBlendMode(blend_mode))); @@ -1017,6 +1023,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, // TODO(senorblanco): Cache this value so that we don't have to do it for both // the surface and its replica. Apply filters to the contents texture. skia::RefPtr<SkImage> filter_image; + GLuint filter_image_id = 0; SkScalar color_matrix[20]; bool use_color_matrix = false; if (!quad->filters.IsEmpty()) { @@ -1039,6 +1046,10 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, filter_image = ApplyImageFilter( ScopedUseGrContext::Create(this, frame), resource_provider_, quad->rect, quad->filters_scale, filter.get(), contents_texture); + if (filter_image) { + filter_image_id = filter_image->getTextureHandle(true); + DCHECK(filter_image_id); + } } } } @@ -1046,18 +1057,17 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, scoped_ptr<ResourceProvider::ScopedSamplerGL> mask_resource_lock; unsigned mask_texture_id = 0; SamplerType mask_sampler = SAMPLER_TYPE_NA; - if (quad->mask_resource_id) { + if (quad->mask_resource_id()) { mask_resource_lock.reset(new ResourceProvider::ScopedSamplerGL( - resource_provider_, quad->mask_resource_id, GL_TEXTURE1, GL_LINEAR)); + resource_provider_, quad->mask_resource_id(), GL_TEXTURE1, GL_LINEAR)); mask_texture_id = mask_resource_lock->texture_id(); mask_sampler = SamplerTypeFromTextureTarget(mask_resource_lock->target()); } scoped_ptr<ResourceProvider::ScopedSamplerGL> contents_resource_lock; - if (filter_image) { - GrTexture* texture = filter_image->getTexture(); + if (filter_image_id) { DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_)); - gl_->BindTexture(GL_TEXTURE_2D, texture->getTextureHandle()); + gl_->BindTexture(GL_TEXTURE_2D, filter_image_id); } else { contents_resource_lock = make_scoped_ptr(new ResourceProvider::ScopedSamplerGL( @@ -1074,14 +1084,13 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, } TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( - gl_, - &highp_threshold_cache_, - highp_threshold_min_, - quad->shared_quad_state->visible_content_rect.bottom_right()); + gl_, &highp_threshold_cache_, highp_threshold_min_, + quad->shared_quad_state->visible_quad_layer_rect.bottom_right()); ShaderLocations locations; - DCHECK_EQ(background_texture || background_image, use_shaders_for_blending); + DCHECK_EQ(background_texture || background_image_id, + use_shaders_for_blending); BlendMode shader_blend_mode = use_shaders_for_blending ? BlendModeFromSkXfermode(blend_mode) : BLEND_MODE_NONE; @@ -1220,7 +1229,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, scoped_ptr<ResourceProvider::ScopedSamplerGL> shader_background_sampler_lock; if (locations.backdrop != -1) { - DCHECK(background_texture || background_image); + DCHECK(background_texture || background_image_id); DCHECK_NE(locations.backdrop, 0); DCHECK_NE(locations.backdrop_rect, 0); @@ -1230,10 +1239,9 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, background_rect.y(), background_rect.width(), background_rect.height()); - if (background_image) { - GrTexture* texture = background_image->getTexture(); + if (background_image_id) { gl_->ActiveTexture(GL_TEXTURE0 + last_texture_unit); - gl_->BindTexture(GL_TEXTURE_2D, texture->getTextureHandle()); + gl_->BindTexture(GL_TEXTURE_2D, background_image_id); gl_->ActiveTexture(GL_TEXTURE0); if (mask_for_background) gl_->Uniform1i(locations.original_backdrop, ++last_texture_unit); @@ -1249,14 +1257,14 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, } } - SetShaderOpacity(quad->opacity(), locations.alpha); + SetShaderOpacity(quad->shared_quad_state->opacity, locations.alpha); SetShaderQuadF(surface_quad, locations.quad); - DrawQuadGeometry( - frame, quad->quadTransform(), quad->rect, locations.matrix); + DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform, + quad->rect, locations.matrix); // Flush the compositor context before the filter bitmap goes out of // scope, so the draw gets processed before the filter texture gets deleted. - if (filter_image) + if (filter_image_id) gl_->Flush(); if (!use_shaders_for_blending) @@ -1303,10 +1311,10 @@ bool is_bottom(const gfx::QuadF* clip_region, const DrawQuad* quad) { return true; return std::abs(clip_region->p3().y() - - quad->shared_quad_state->content_bounds.height()) < + quad->shared_quad_state->quad_layer_bounds.height()) < kAntiAliasingEpsilon && std::abs(clip_region->p4().y() - - quad->shared_quad_state->content_bounds.height()) < + quad->shared_quad_state->quad_layer_bounds.height()) < kAntiAliasingEpsilon; } @@ -1327,10 +1335,10 @@ bool is_right(const gfx::QuadF* clip_region, const DrawQuad* quad) { return true; return std::abs(clip_region->p2().x() - - quad->shared_quad_state->content_bounds.width()) < + quad->shared_quad_state->quad_layer_bounds.width()) < kAntiAliasingEpsilon && std::abs(clip_region->p3().x() - - quad->shared_quad_state->content_bounds.width()) < + quad->shared_quad_state->quad_layer_bounds.width()) < kAntiAliasingEpsilon; } } // anonymous namespace @@ -1338,18 +1346,10 @@ bool is_right(const gfx::QuadF* clip_region, const DrawQuad* quad) { static gfx::QuadF GetDeviceQuadWithAntialiasingOnExteriorEdges( const LayerQuad& device_layer_edges, const gfx::Transform& device_transform, + const gfx::QuadF& tile_quad, const gfx::QuadF* clip_region, const DrawQuad* quad) { gfx::RectF tile_rect = quad->visible_rect; - gfx::QuadF tile_quad(tile_rect); - - if (clip_region) { - if (quad->material != DrawQuad::RENDER_PASS) { - tile_quad = *clip_region; - } else { - GetScaledRegion(quad->rect, clip_region, &tile_quad); - } - } gfx::PointF bottom_right = tile_quad.p3(); gfx::PointF bottom_left = tile_quad.p4(); @@ -1426,45 +1426,65 @@ void AlignQuadToBoundingBox(gfx::QuadF* clipped_quad) { *clipped_quad = best_rotation; } -// static -bool GLRenderer::ShouldAntialiasQuad(const gfx::Transform& device_transform, - const DrawQuad* quad, - bool force_antialiasing) { - bool is_render_pass_quad = (quad->material == DrawQuad::RENDER_PASS); - // For render pass quads, |device_transform| already contains quad's rect. - // TODO(rosca@adobe.com): remove branching on is_render_pass_quad - // crbug.com/429702 - if (!is_render_pass_quad && !quad->IsEdge()) - return false; - gfx::RectF content_rect = - is_render_pass_quad ? QuadVertexRect() : quad->visibleContentRect(); - +// Map device space quad to local space. Device_transform has no 3d +// component since it was flattened, so we don't need to project. We should +// have already checked that the transform was uninvertible before this call. +gfx::QuadF MapQuadToLocalSpace(const gfx::Transform& device_transform, + const gfx::QuadF& device_quad) { + gfx::Transform inverse_device_transform(gfx::Transform::kSkipInitialization); + DCHECK(device_transform.IsInvertible()); + bool did_invert = device_transform.GetInverse(&inverse_device_transform); + DCHECK(did_invert); bool clipped = false; - gfx::QuadF device_layer_quad = - MathUtil::MapQuad(device_transform, gfx::QuadF(content_rect), &clipped); + gfx::QuadF local_quad = + MathUtil::MapQuad(inverse_device_transform, device_quad, &clipped); + // We should not DCHECK(!clipped) here, because anti-aliasing inflation may + // cause device_quad to become clipped. To our knowledge this scenario does + // not need to be handled differently than the unclipped case. + return local_quad; +} + +void InflateAntiAliasingDistances(const gfx::QuadF& quad, + LayerQuad* device_layer_edges, + float edge[24]) { + DCHECK(!quad.BoundingBox().IsEmpty()); + LayerQuad device_layer_bounds(gfx::QuadF(quad.BoundingBox())); + + device_layer_edges->InflateAntiAliasingDistance(); + device_layer_edges->ToFloatArray(edge); + + device_layer_bounds.InflateAntiAliasingDistance(); + device_layer_bounds.ToFloatArray(&edge[12]); +} +// static +bool GLRenderer::ShouldAntialiasQuad(const gfx::QuadF& device_layer_quad, + bool clipped, + bool force_aa) { + // AAing clipped quads is not supported by the code yet. + if (clipped) + return false; if (device_layer_quad.BoundingBox().IsEmpty()) return false; + if (force_aa) + return true; bool is_axis_aligned_in_target = device_layer_quad.IsRectilinear(); bool is_nearest_rect_within_epsilon = is_axis_aligned_in_target && gfx::IsNearestRectWithinDistance(device_layer_quad.BoundingBox(), kAntiAliasingEpsilon); - // AAing clipped quads is not supported by the code yet. - bool use_aa = !clipped && !is_nearest_rect_within_epsilon; - return use_aa || force_antialiasing; + return !is_nearest_rect_within_epsilon; } // static void GLRenderer::SetupQuadForClippingAndAntialiasing( const gfx::Transform& device_transform, const DrawQuad* quad, - bool use_aa, + const gfx::QuadF* aa_quad, const gfx::QuadF* clip_region, gfx::QuadF* local_quad, float edge[24]) { - bool is_render_pass_quad = (quad->material == DrawQuad::RENDER_PASS); gfx::QuadF rotated_clip; const gfx::QuadF* local_clip_region = clip_region; if (local_clip_region) { @@ -1473,32 +1493,14 @@ void GLRenderer::SetupQuadForClippingAndAntialiasing( local_clip_region = &rotated_clip; } - gfx::QuadF content_rect = is_render_pass_quad - ? gfx::QuadF(QuadVertexRect()) - : gfx::QuadF(quad->visibleContentRect()); - if (!use_aa) { - if (local_clip_region) { - if (!is_render_pass_quad) { - content_rect = *local_clip_region; - } else { - GetScaledRegion(quad->rect, local_clip_region, &content_rect); - } - *local_quad = content_rect; - } + if (!aa_quad) { + if (local_clip_region) + *local_quad = *local_clip_region; return; } - bool clipped = false; - gfx::QuadF device_layer_quad = - MathUtil::MapQuad(device_transform, content_rect, &clipped); - LayerQuad device_layer_bounds(gfx::QuadF(device_layer_quad.BoundingBox())); - device_layer_bounds.InflateAntiAliasingDistance(); - - LayerQuad device_layer_edges(device_layer_quad); - device_layer_edges.InflateAntiAliasingDistance(); - - device_layer_edges.ToFloatArray(edge); - device_layer_bounds.ToFloatArray(&edge[12]); + LayerQuad device_layer_edges(*aa_quad); + InflateAntiAliasingDistances(*aa_quad, &device_layer_edges, edge); // If we have a clip region then we are split, and therefore // by necessity, at least one of our edges is not an external @@ -1511,26 +1513,60 @@ void GLRenderer::SetupQuadForClippingAndAntialiasing( is_bottom(local_clip_region, quad) && is_right(local_clip_region, quad)); bool use_aa_on_all_four_edges = - !local_clip_region && - (is_render_pass_quad || region_contains_all_outside_edges); - - gfx::QuadF device_quad = - use_aa_on_all_four_edges - ? device_layer_edges.ToQuadF() - : GetDeviceQuadWithAntialiasingOnExteriorEdges( - device_layer_edges, device_transform, local_clip_region, quad); - - // Map device space quad to local space. device_transform has no 3d - // component since it was flattened, so we don't need to project. We should - // have already checked that the transform was uninvertible above. - gfx::Transform inverse_device_transform(gfx::Transform::kSkipInitialization); - bool did_invert = device_transform.GetInverse(&inverse_device_transform); - DCHECK(did_invert); - *local_quad = - MathUtil::MapQuad(inverse_device_transform, device_quad, &clipped); - // We should not DCHECK(!clipped) here, because anti-aliasing inflation may - // cause device_quad to become clipped. To our knowledge this scenario does - // not need to be handled differently than the unclipped case. + !local_clip_region && region_contains_all_outside_edges; + + gfx::QuadF device_quad; + if (use_aa_on_all_four_edges) { + device_quad = device_layer_edges.ToQuadF(); + } else { + gfx::QuadF tile_quad(local_clip_region ? *local_clip_region + : gfx::QuadF(quad->visible_rect)); + device_quad = GetDeviceQuadWithAntialiasingOnExteriorEdges( + device_layer_edges, device_transform, tile_quad, local_clip_region, + quad); + } + + *local_quad = MapQuadToLocalSpace(device_transform, device_quad); +} + +// static +void GLRenderer::SetupRenderPassQuadForClippingAndAntialiasing( + const gfx::Transform& device_transform, + const RenderPassDrawQuad* quad, + const gfx::QuadF* aa_quad, + const gfx::QuadF* clip_region, + gfx::QuadF* local_quad, + float edge[24]) { + gfx::QuadF rotated_clip; + const gfx::QuadF* local_clip_region = clip_region; + if (local_clip_region) { + rotated_clip = *clip_region; + AlignQuadToBoundingBox(&rotated_clip); + local_clip_region = &rotated_clip; + } + + if (!aa_quad) { + GetScaledRegion(quad->rect, local_clip_region, local_quad); + return; + } + + LayerQuad device_layer_edges(*aa_quad); + InflateAntiAliasingDistances(*aa_quad, &device_layer_edges, edge); + + gfx::QuadF device_quad; + + // Apply anti-aliasing only to the edges that are not being clipped + if (local_clip_region) { + gfx::QuadF tile_quad(quad->visible_rect); + GetScaledRegion(quad->rect, local_clip_region, &tile_quad); + device_quad = GetDeviceQuadWithAntialiasingOnExteriorEdges( + device_layer_edges, device_transform, tile_quad, local_clip_region, + quad); + } else { + device_quad = device_layer_edges.ToQuadF(); + } + + *local_quad = MapQuadToLocalSpace(device_transform, device_quad); } void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame, @@ -1539,7 +1575,7 @@ void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame, gfx::Rect tile_rect = quad->visible_rect; SkColor color = quad->color; - float opacity = quad->opacity(); + float opacity = quad->shared_quad_state->opacity; float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; // Early out if alpha is small enough that quad doesn't contribute to output. @@ -1548,18 +1584,31 @@ void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame, return; gfx::Transform device_transform = - frame->window_matrix * frame->projection_matrix * quad->quadTransform(); + frame->window_matrix * frame->projection_matrix * + quad->shared_quad_state->quad_to_target_transform; device_transform.FlattenTo2d(); if (!device_transform.IsInvertible()) return; - bool force_aa = false; gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect)); + + gfx::QuadF device_layer_quad; + bool use_aa = false; + bool allow_aa = settings_->allow_antialiasing && + !quad->force_anti_aliasing_off && quad->IsEdge(); + + if (allow_aa) { + bool clipped = false; + bool force_aa = false; + device_layer_quad = MathUtil::MapQuad( + device_transform, + gfx::QuadF(quad->shared_quad_state->visible_quad_layer_rect), &clipped); + use_aa = ShouldAntialiasQuad(device_layer_quad, clipped, force_aa); + } + float edge[24]; - bool use_aa = settings_->allow_antialiasing && - !quad->force_anti_aliasing_off && - ShouldAntialiasQuad(device_transform, quad, force_aa); - SetupQuadForClippingAndAntialiasing(device_transform, quad, use_aa, + const gfx::QuadF* aa_quad = use_aa ? &device_layer_quad : nullptr; + SetupQuadForClippingAndAntialiasing(device_transform, quad, aa_quad, clip_region, &local_quad, edge); SolidColorProgramUniforms uniforms; @@ -1589,20 +1638,35 @@ void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame, // to use antialiasing. SetBlendEnabled(quad->ShouldDrawWithBlending() || use_aa); - // Normalize to tile_rect. - local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); - - SetShaderQuadF(local_quad, uniforms.quad_location); + // Antialising requires a normalized quad, but this could lead to floating + // point precision errors, so only normalize when antialising is on. + if (use_aa) { + // Normalize to tile_rect. + local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); + + SetShaderQuadF(local_quad, uniforms.quad_location); + + // The transform and vertex data are used to figure out the extents that the + // un-antialiased quad should have and which vertex this is and the float + // quad passed in via uniform is the actual geometry that gets used to draw + // it. This is why this centered rect is used and not the original + // quad_rect. + gfx::RectF centered_rect( + gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()), + tile_rect.size()); + DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform, + centered_rect, uniforms.matrix_location); + } else { + PrepareGeometry(SHARED_BINDING); + SetShaderQuadF(local_quad, uniforms.quad_location); + static float gl_matrix[16]; + ToGLMatrix(&gl_matrix[0], + frame->projection_matrix * + quad->shared_quad_state->quad_to_target_transform); + gl_->UniformMatrix4fv(uniforms.matrix_location, 1, false, &gl_matrix[0]); - // The transform and vertex data are used to figure out the extents that the - // un-antialiased quad should have and which vertex this is and the float - // quad passed in via uniform is the actual geometry that gets used to draw - // it. This is why this centered rect is used and not the original quad_rect. - gfx::RectF centered_rect( - gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()), - tile_rect.size()); - DrawQuadGeometry( - frame, quad->quadTransform(), centered_rect, uniforms.matrix_location); + gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); + } } struct TileProgramUniforms { @@ -1636,33 +1700,45 @@ static void TileUniformLocation(T program, TileProgramUniforms* uniforms) { void GLRenderer::DrawTileQuad(const DrawingFrame* frame, const TileDrawQuad* quad, const gfx::QuadF* clip_region) { - DrawContentQuad(frame, quad, quad->resource_id, clip_region); + DrawContentQuad(frame, quad, quad->resource_id(), clip_region); } void GLRenderer::DrawContentQuad(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, const gfx::QuadF* clip_region) { gfx::Transform device_transform = - frame->window_matrix * frame->projection_matrix * quad->quadTransform(); + frame->window_matrix * frame->projection_matrix * + quad->shared_quad_state->quad_to_target_transform; device_transform.FlattenTo2d(); - bool use_aa = settings_->allow_antialiasing && - ShouldAntialiasQuad(device_transform, quad, false); + gfx::QuadF device_layer_quad; + bool use_aa = false; + bool allow_aa = settings_->allow_antialiasing && quad->IsEdge(); + if (allow_aa) { + bool clipped = false; + bool force_aa = false; + device_layer_quad = MathUtil::MapQuad( + device_transform, + gfx::QuadF(quad->shared_quad_state->visible_quad_layer_rect), &clipped); + use_aa = ShouldAntialiasQuad(device_layer_quad, clipped, force_aa); + } // TODO(timav): simplify coordinate transformations in DrawContentQuadAA // similar to the way DrawContentQuadNoAA works and then consider // combining DrawContentQuadAA and DrawContentQuadNoAA into one method. if (use_aa) - DrawContentQuadAA(frame, quad, resource_id, device_transform, clip_region); + DrawContentQuadAA(frame, quad, resource_id, device_transform, + device_layer_quad, clip_region); else DrawContentQuadNoAA(frame, quad, resource_id, clip_region); } void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, const gfx::Transform& device_transform, + const gfx::QuadF& aa_quad, const gfx::QuadF* clip_region) { if (!device_transform.IsInvertible()) return; @@ -1708,8 +1784,8 @@ void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame, gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect)); float edge[24]; - SetupQuadForClippingAndAntialiasing(device_transform, quad, true, clip_region, - &local_quad, edge); + SetupQuadForClippingAndAntialiasing(device_transform, quad, &aa_quad, + clip_region, &local_quad, edge); ResourceProvider::ScopedSamplerGL quad_resource_lock( resource_provider_, resource_id, quad->nearest_neighbor ? GL_NEAREST : GL_LINEAR); @@ -1765,7 +1841,7 @@ void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame, // Normalize to tile_rect. local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); - SetShaderOpacity(quad->opacity(), uniforms.alpha_location); + SetShaderOpacity(quad->shared_quad_state->opacity, uniforms.alpha_location); SetShaderQuadF(local_quad, uniforms.quad_location); // The transform and vertex data are used to figure out the extents that the @@ -1775,13 +1851,13 @@ void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame, gfx::RectF centered_rect( gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()), tile_rect.size()); - DrawQuadGeometry( - frame, quad->quadTransform(), centered_rect, uniforms.matrix_location); + DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform, + centered_rect, uniforms.matrix_location); } void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, const gfx::QuadF* clip_region) { gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional( quad->tex_coord_rect, quad->rect, quad->visible_rect); @@ -1790,11 +1866,12 @@ void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame, quad->rect.height() / quad->tex_coord_rect.height(); bool scaled = (tex_to_geom_scale_x != 1.f || tex_to_geom_scale_y != 1.f); - GLenum filter = - (scaled || !quad->quadTransform().IsIdentityOrIntegerTranslation()) && - !quad->nearest_neighbor - ? GL_LINEAR - : GL_NEAREST; + GLenum filter = (scaled || + !quad->shared_quad_state->quad_to_target_transform + .IsIdentityOrIntegerTranslation()) && + !quad->nearest_neighbor + ? GL_LINEAR + : GL_NEAREST; ResourceProvider::ScopedSamplerGL quad_resource_lock( resource_provider_, resource_id, filter); @@ -1847,7 +1924,7 @@ void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame, SetBlendEnabled(quad->ShouldDrawWithBlending()); - SetShaderOpacity(quad->opacity(), uniforms.alpha_location); + SetShaderOpacity(quad->shared_quad_state->opacity, uniforms.alpha_location); // Pass quad coordinates to the uniform in the same order as GeometryBinding // does, then vertices will match the texture mapping in the vertex buffer. @@ -1888,7 +1965,9 @@ void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame, gl_->Uniform2fv(uniforms.quad_location, 4, gl_quad); static float gl_matrix[16]; - ToGLMatrix(&gl_matrix[0], frame->projection_matrix * quad->quadTransform()); + ToGLMatrix(&gl_matrix[0], + frame->projection_matrix * + quad->shared_quad_state->quad_to_target_transform); gl_->UniformMatrix4fv(uniforms.matrix_location, 1, false, &gl_matrix[0]); gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); @@ -1900,25 +1979,24 @@ void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame, SetBlendEnabled(quad->ShouldDrawWithBlending()); TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( - gl_, - &highp_threshold_cache_, - highp_threshold_min_, - quad->shared_quad_state->visible_content_rect.bottom_right()); + gl_, &highp_threshold_cache_, highp_threshold_min_, + quad->shared_quad_state->visible_quad_layer_rect.bottom_right()); - bool use_alpha_plane = quad->a_plane_resource_id != 0; + bool use_alpha_plane = quad->a_plane_resource_id() != 0; ResourceProvider::ScopedSamplerGL y_plane_lock( - resource_provider_, quad->y_plane_resource_id, GL_TEXTURE1, GL_LINEAR); + resource_provider_, quad->y_plane_resource_id(), GL_TEXTURE1, GL_LINEAR); ResourceProvider::ScopedSamplerGL u_plane_lock( - resource_provider_, quad->u_plane_resource_id, GL_TEXTURE2, GL_LINEAR); + resource_provider_, quad->u_plane_resource_id(), GL_TEXTURE2, GL_LINEAR); DCHECK_EQ(y_plane_lock.target(), u_plane_lock.target()); ResourceProvider::ScopedSamplerGL v_plane_lock( - resource_provider_, quad->v_plane_resource_id, GL_TEXTURE3, GL_LINEAR); + resource_provider_, quad->v_plane_resource_id(), GL_TEXTURE3, GL_LINEAR); DCHECK_EQ(y_plane_lock.target(), v_plane_lock.target()); scoped_ptr<ResourceProvider::ScopedSamplerGL> a_plane_lock; if (use_alpha_plane) { a_plane_lock.reset(new ResourceProvider::ScopedSamplerGL( - resource_provider_, quad->a_plane_resource_id, GL_TEXTURE4, GL_LINEAR)); + resource_provider_, quad->a_plane_resource_id(), GL_TEXTURE4, + GL_LINEAR)); DCHECK_EQ(y_plane_lock.target(), a_plane_lock->target()); } @@ -2093,17 +2171,19 @@ void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame, gl_->UniformMatrix3fv(yuv_matrix_location, 1, 0, yuv_to_rgb); gl_->Uniform3fv(yuv_adj_location, 1, yuv_adjust); - SetShaderOpacity(quad->opacity(), alpha_location); + SetShaderOpacity(quad->shared_quad_state->opacity, alpha_location); if (!clip_region) { - DrawQuadGeometry(frame, quad->quadTransform(), tile_rect, matrix_location); + DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform, + tile_rect, matrix_location); } else { float uvs[8] = {0}; GetScaledUVs(quad->visible_rect, clip_region, uvs); gfx::QuadF region_quad = *clip_region; region_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); region_quad -= gfx::Vector2dF(0.5f, 0.5f); - DrawQuadGeometryClippedByQuadF(frame, quad->quadTransform(), tile_rect, - region_quad, matrix_location, uvs); + DrawQuadGeometryClippedByQuadF( + frame, quad->shared_quad_state->quad_to_target_transform, tile_rect, + region_quad, matrix_location, uvs); } } @@ -2117,10 +2197,8 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame, DCHECK(capabilities_.using_egl_image); TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( - gl_, - &highp_threshold_cache_, - highp_threshold_min_, - quad->shared_quad_state->visible_content_rect.bottom_right()); + gl_, &highp_threshold_cache_, highp_threshold_min_, + quad->shared_quad_state->visible_quad_layer_rect.bottom_right()); const VideoStreamTextureProgram* program = GetVideoStreamTextureProgram(tex_coord_precision); @@ -2131,17 +2209,17 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame, false, gl_matrix); ResourceProvider::ScopedReadLockGL lock(resource_provider_, - quad->resource_id); + quad->resource_id()); DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_)); gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, lock.texture_id()); gl_->Uniform1i(program->fragment_shader().sampler_location(), 0); - SetShaderOpacity(quad->opacity(), + SetShaderOpacity(quad->shared_quad_state->opacity, program->fragment_shader().alpha_location()); if (!clip_region) { - DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, - program->vertex_shader().matrix_location()); + DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform, + quad->rect, program->vertex_shader().matrix_location()); } else { gfx::QuadF region_quad(*clip_region); region_quad.Scale(1.0f / quad->rect.width(), 1.0f / quad->rect.height()); @@ -2149,8 +2227,8 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame, float uvs[8] = {0}; GetScaledUVs(quad->visible_rect, clip_region, uvs); DrawQuadGeometryClippedByQuadF( - frame, quad->quadTransform(), quad->rect, region_quad, - program->vertex_shader().matrix_location(), uvs); + frame, quad->shared_quad_state->quad_to_target_transform, quad->rect, + region_quad, program->vertex_shader().matrix_location(), uvs); } } @@ -2232,8 +2310,11 @@ void GLRenderer::FlushTextureQuadCache(BoundGeometry flush_binding) { static_cast<int>(draw_cache_.vertex_opacity_data.size()), static_cast<float*>(&draw_cache_.vertex_opacity_data.front())); + DCHECK_LE(draw_cache_.matrix_data.size(), + static_cast<size_t>(std::numeric_limits<int>::max()) / 6u); // Draw the quads! - gl_->DrawElements(GL_TRIANGLES, 6 * draw_cache_.matrix_data.size(), + gl_->DrawElements(GL_TRIANGLES, + 6 * static_cast<int>(draw_cache_.matrix_data.size()), GL_UNSIGNED_SHORT, 0); // Clear the cache. @@ -2262,13 +2343,11 @@ void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame, } TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( - gl_, - &highp_threshold_cache_, - highp_threshold_min_, - quad->shared_quad_state->visible_content_rect.bottom_right()); + gl_, &highp_threshold_cache_, highp_threshold_min_, + quad->shared_quad_state->visible_quad_layer_rect.bottom_right()); ResourceProvider::ScopedReadLockGL lock(resource_provider_, - quad->resource_id); + quad->resource_id()); const SamplerType sampler = SamplerTypeFromTextureTarget(lock.target()); // Choose the correct texture program binding TexTransformTextureProgramBinding binding; @@ -2288,7 +2367,7 @@ void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame, } } - int resource_id = quad->resource_id; + int resource_id = quad->resource_id(); if (draw_cache_.program_id != binding.program_id || draw_cache_.resource_id != resource_id || @@ -2319,7 +2398,7 @@ void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame, } // Generate the vertex opacity - const float opacity = quad->opacity(); + const float opacity = quad->shared_quad_state->opacity; draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[0] * opacity); draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[1] * opacity); draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[2] * opacity); @@ -2327,7 +2406,9 @@ void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame, // Generate the transform matrix gfx::Transform quad_rect_matrix; - QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect); + QuadRectTransform(&quad_rect_matrix, + quad->shared_quad_state->quad_to_target_transform, + quad->rect); quad_rect_matrix = frame->projection_matrix * quad_rect_matrix; Float16 m; @@ -2362,10 +2443,8 @@ void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame, SetBlendEnabled(quad->ShouldDrawWithBlending()); TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( - gl_, - &highp_threshold_cache_, - highp_threshold_min_, - quad->shared_quad_state->visible_content_rect.bottom_right()); + gl_, &highp_threshold_cache_, highp_threshold_min_, + quad->shared_quad_state->visible_quad_layer_rect.bottom_right()); TexTransformTextureProgramBinding binding; binding.Set(GetTextureIOSurfaceProgram(tex_coord_precision)); @@ -2382,23 +2461,26 @@ void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame, quad->io_surface_size.height()); } - const float vertex_opacity[] = {quad->opacity(), quad->opacity(), - quad->opacity(), quad->opacity()}; + const float vertex_opacity[] = {quad->shared_quad_state->opacity, + quad->shared_quad_state->opacity, + quad->shared_quad_state->opacity, + quad->shared_quad_state->opacity}; gl_->Uniform1fv(binding.vertex_opacity_location, 4, vertex_opacity); ResourceProvider::ScopedReadLockGL lock(resource_provider_, - quad->io_surface_resource_id); + quad->io_surface_resource_id()); DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_)); gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, lock.texture_id()); if (!clip_region) { - DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, - binding.matrix_location); + DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform, + quad->rect, binding.matrix_location); } else { float uvs[8] = {0}; GetScaledUVs(quad->visible_rect, clip_region, uvs); - DrawQuadGeometryClippedByQuadF(frame, quad->quadTransform(), quad->rect, - *clip_region, binding.matrix_location, uvs); + DrawQuadGeometryClippedByQuadF( + frame, quad->shared_quad_state->quad_to_target_transform, quad->rect, + *clip_region, binding.matrix_location, uvs); } gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); @@ -2603,7 +2685,6 @@ void GLRenderer::EnforceMemoryPolicy() { TRACE_EVENT0("cc", "GLRenderer::EnforceMemoryPolicy dropping resources"); ReleaseRenderPassTextures(); DiscardBackbuffer(); - resource_provider_->ReleaseCachedData(); output_surface_->context_provider()->DeleteCachedResources(); gl_->Flush(); } @@ -3486,7 +3567,7 @@ void GLRenderer::RestoreFramebuffer(DrawingFrame* frame) { } bool GLRenderer::IsContextLost() { - return output_surface_->context_provider()->IsContextLost(); + return gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR; } void GLRenderer::ScheduleOverlays(DrawingFrame* frame) { diff --git a/chromium/cc/output/gl_renderer.h b/chromium/cc/output/gl_renderer.h index 324a7bd16e4..d80e1561502 100644 --- a/chromium/cc/output/gl_renderer.h +++ b/chromium/cc/output/gl_renderer.h @@ -122,9 +122,9 @@ class CC_EXPORT GLRenderer : public DirectRenderer { void FinishDrawingQuadList() override; // Returns true if quad requires antialiasing and false otherwise. - static bool ShouldAntialiasQuad(const gfx::Transform& device_transform, - const DrawQuad* quad, - bool force_antialiasing); + static bool ShouldAntialiasQuad(const gfx::QuadF& device_layer_quad, + bool clipped, + bool force_aa); // Inflate the quad and fill edge array for fragment shader. // |local_quad| is set to inflated quad. |edge| array is filled with @@ -132,7 +132,14 @@ class CC_EXPORT GLRenderer : public DirectRenderer { static void SetupQuadForClippingAndAntialiasing( const gfx::Transform& device_transform, const DrawQuad* quad, - bool use_aa, + const gfx::QuadF* device_layer_quad, + const gfx::QuadF* clip_region, + gfx::QuadF* local_quad, + float edge[24]); + static void SetupRenderPassQuadForClippingAndAntialiasing( + const gfx::Transform& device_transform, + const RenderPassDrawQuad* quad, + const gfx::QuadF* device_layer_quad, const gfx::QuadF* clip_region, gfx::QuadF* local_quad, float edge[24]); @@ -198,16 +205,17 @@ class CC_EXPORT GLRenderer : public DirectRenderer { const gfx::QuadF* clip_region); void DrawContentQuad(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, const gfx::QuadF* clip_region); void DrawContentQuadAA(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, const gfx::Transform& device_transform, + const gfx::QuadF& aa_quad, const gfx::QuadF* clip_region); void DrawContentQuadNoAA(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, const gfx::QuadF* clip_region); void DrawYUVVideoQuad(const DrawingFrame* frame, const YUVVideoDrawQuad* quad, @@ -515,7 +523,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer { bool use_blend_equation_advanced_coherent_; SkBitmap on_demand_tile_raster_bitmap_; - ResourceProvider::ResourceId on_demand_tile_raster_resource_id_; + ResourceId on_demand_tile_raster_resource_id_; BoundGeometry bound_geometry_; DISALLOW_COPY_AND_ASSIGN(GLRenderer); }; diff --git a/chromium/cc/output/gl_renderer_unittest.cc b/chromium/cc/output/gl_renderer_unittest.cc index 09407f55ed7..4b133c930a5 100644 --- a/chromium/cc/output/gl_renderer_unittest.cc +++ b/chromium/cc/output/gl_renderer_unittest.cc @@ -22,6 +22,7 @@ #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_renderer_client.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/pixel_test.h" #include "cc/test/render_pass_test_common.h" #include "cc/test/render_pass_test_utils.h" @@ -334,13 +335,8 @@ class GLRendererWithDefaultHarnessTest : public GLRendererTest { CHECK(output_surface_->BindToClient(&output_surface_client_)); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1).Pass(); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), shared_bitmap_manager_.get()); renderer_ = make_scoped_ptr(new FakeRendererGL(&renderer_client_, &settings_, output_surface_.get(), @@ -370,13 +366,8 @@ class GLRendererShaderTest : public GLRendererTest { CHECK(output_surface_->BindToClient(&output_surface_client_)); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1).Pass(); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), shared_bitmap_manager_.get()); renderer_.reset(new FakeRendererGL(&renderer_client_, &settings_, output_surface_.get(), @@ -674,14 +665,8 @@ TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -714,14 +699,8 @@ TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -753,14 +732,8 @@ TEST_F(GLRendererTest, OpaqueBackground) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -805,14 +778,8 @@ TEST_F(GLRendererTest, TransparentBackground) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -850,14 +817,8 @@ TEST_F(GLRendererTest, OffscreenOutputSurface) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -935,14 +896,8 @@ TEST_F(GLRendererTest, VisibilityChangeIsLastCall) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -1006,14 +961,8 @@ TEST_F(GLRendererTest, ActiveTextureState) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -1097,14 +1046,8 @@ TEST_F(GLRendererTest, ShouldClearRootRenderPass) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; settings.should_clear_root_render_pass = false; @@ -1195,14 +1138,8 @@ TEST_F(GLRendererTest, ScissorTestWhenClearing) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -1293,14 +1230,8 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; settings.partial_swap_enabled = true; @@ -1464,14 +1395,8 @@ TEST_F(GLRendererTest, ScissorAndViewportWithinNonreshapableSurface) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -1513,9 +1438,8 @@ TEST_F(GLRendererTest, DrawFramePreservesFramebuffer) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( - output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); RendererSettings settings; FakeRendererClient renderer_client; @@ -1558,7 +1482,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { RenderPassId root_pass_id(1, 0); TestRenderPass* root_pass; - ResourceProvider::ResourceId mask = resource_provider_->CreateResource( + ResourceId mask = resource_provider_->CreateResource( gfx::Size(20, 12), GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, resource_provider_->best_texture_format()); @@ -1933,13 +1857,8 @@ class MockOutputSurfaceTest : public GLRendererTest { CHECK(output_surface_.BindToClient(&output_surface_client_)); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - resource_provider_ = ResourceProvider::Create(&output_surface_, - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1).Pass(); + resource_provider_ = FakeResourceProvider::Create( + &output_surface_, shared_bitmap_manager_.get()); renderer_.reset(new FakeRendererGL(&renderer_client_, &settings_, @@ -2110,9 +2029,8 @@ class TestOverlayProcessor : public OverlayProcessor { OverlayCandidateList* candidates)); }; - TestOverlayProcessor(OutputSurface* surface, - ResourceProvider* resource_provider) - : OverlayProcessor(surface, resource_provider) {} + explicit TestOverlayProcessor(OutputSurface* surface) + : OverlayProcessor(surface) {} ~TestOverlayProcessor() override {} void Initialize() override { strategy_ = new Strategy(); @@ -2139,9 +2057,8 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( - output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); scoped_ptr<TextureMailboxDeleter> mailbox_deleter( new TextureMailboxDeleter(base::ThreadTaskRunnerHandle::Get())); @@ -2151,7 +2068,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) { resource_provider.get(), mailbox_deleter.get()); TestOverlayProcessor* processor = - new TestOverlayProcessor(output_surface.get(), resource_provider.get()); + new TestOverlayProcessor(output_surface.get()); processor->Initialize(); renderer.SetOverlayProcessor(processor); @@ -2166,12 +2083,10 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) { unsigned sync_point = 0; TextureMailbox mailbox = TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); - mailbox.set_allow_overlay(true); scoped_ptr<SingleReleaseCallbackImpl> release_callback = SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); - ResourceProvider::ResourceId resource_id = - resource_provider->CreateResourceFromTextureMailbox( - mailbox, release_callback.Pass()); + ResourceId resource_id = resource_provider->CreateResourceFromTextureMailbox( + mailbox, release_callback.Pass()); bool premultiplied_alpha = false; bool flipped = false; bool nearest_neighbor = false; @@ -2184,6 +2099,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) { premultiplied_alpha, gfx::PointF(0, 0), gfx::PointF(1, 1), SK_ColorTRANSPARENT, vertex_opacity, flipped, nearest_neighbor); + overlay_quad->set_allow_overlay(true); // DirectRenderer::DrawFrame calls into OverlayProcessor::ProcessForOverlays. // Attempt will be called for each strategy in OverlayProcessor. We have @@ -2223,13 +2139,12 @@ class SingleOverlayOnTopProcessor : public OverlayProcessor { } }; - SingleOverlayOnTopProcessor(OutputSurface* surface, - ResourceProvider* resource_provider) - : OverlayProcessor(surface, resource_provider) {} + explicit SingleOverlayOnTopProcessor(OutputSurface* surface) + : OverlayProcessor(surface) {} void Initialize() override { - strategies_.push_back(scoped_ptr<Strategy>( - new OverlayStrategySingleOnTop(&validator_, resource_provider_))); + strategies_.push_back( + scoped_ptr<Strategy>(new OverlayStrategySingleOnTop(&validator_))); } SingleOverlayValidator validator_; @@ -2268,9 +2183,8 @@ TEST_F(GLRendererTest, OverlaySyncPointsAreProcessed) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( - output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); scoped_ptr<TextureMailboxDeleter> mailbox_deleter( new TextureMailboxDeleter(base::ThreadTaskRunnerHandle::Get())); @@ -2279,8 +2193,8 @@ TEST_F(GLRendererTest, OverlaySyncPointsAreProcessed) { FakeRendererGL renderer(&renderer_client, &settings, output_surface.get(), resource_provider.get(), mailbox_deleter.get()); - SingleOverlayOnTopProcessor* processor = new SingleOverlayOnTopProcessor( - output_surface.get(), resource_provider.get()); + SingleOverlayOnTopProcessor* processor = + new SingleOverlayOnTopProcessor(output_surface.get()); processor->Initialize(); renderer.SetOverlayProcessor(processor); @@ -2293,12 +2207,10 @@ TEST_F(GLRendererTest, OverlaySyncPointsAreProcessed) { unsigned sync_point = TestRenderPass::kSyncPointForMailboxTextureQuad; TextureMailbox mailbox = TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); - mailbox.set_allow_overlay(true); scoped_ptr<SingleReleaseCallbackImpl> release_callback = SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); - ResourceProvider::ResourceId resource_id = - resource_provider->CreateResourceFromTextureMailbox( - mailbox, release_callback.Pass()); + ResourceId resource_id = resource_provider->CreateResourceFromTextureMailbox( + mailbox, release_callback.Pass()); bool premultiplied_alpha = false; bool flipped = false; bool nearest_neighbor = false; @@ -2315,6 +2227,7 @@ TEST_F(GLRendererTest, OverlaySyncPointsAreProcessed) { viewport_rect, resource_id, premultiplied_alpha, uv_top_left, uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity, flipped, nearest_neighbor); + overlay_quad->set_allow_overlay(true); // Verify that overlay_quad actually gets turned into an overlay, and even // though it's not drawn, that its sync point is waited on. diff --git a/chromium/cc/output/latency_info_swap_promise.cc b/chromium/cc/output/latency_info_swap_promise.cc index afc0f2d8502..5e08470fb07 100644 --- a/chromium/cc/output/latency_info_swap_promise.cc +++ b/chromium/cc/output/latency_info_swap_promise.cc @@ -5,6 +5,7 @@ #include "cc/output/latency_info_swap_promise.h" #include "base/logging.h" +#include "base/trace_event/trace_event.h" namespace { ui::LatencyComponentType DidNotSwapReasonToLatencyComponentType( @@ -49,4 +50,11 @@ int64 LatencyInfoSwapPromise::TraceId() const { return latency_.trace_id; } +// Trace the original LatencyInfo of a LatencyInfoSwapPromise +void LatencyInfoSwapPromise::OnCommit() { + TRACE_EVENT_FLOW_STEP0("input,benchmark", "LatencyInfo.Flow", + TRACE_ID_DONT_MANGLE(TraceId()), + "HanldeInputEventMainCommit"); +} + } // namespace cc diff --git a/chromium/cc/output/latency_info_swap_promise.h b/chromium/cc/output/latency_info_swap_promise.h index 74810b8d1a2..9a4deb6e9c6 100644 --- a/chromium/cc/output/latency_info_swap_promise.h +++ b/chromium/cc/output/latency_info_swap_promise.h @@ -19,6 +19,7 @@ class CC_EXPORT LatencyInfoSwapPromise : public SwapPromise { void DidActivate() override {} void DidSwap(CompositorFrameMetadata* metadata) override; void DidNotSwap(DidNotSwapReason reason) override; + void OnCommit() override; int64 TraceId() const override; diff --git a/chromium/cc/output/managed_memory_policy.cc b/chromium/cc/output/managed_memory_policy.cc index 049d2b03f9f..d46790d5fef 100644 --- a/chromium/cc/output/managed_memory_policy.cc +++ b/chromium/cc/output/managed_memory_policy.cc @@ -5,7 +5,6 @@ #include "cc/output/managed_memory_policy.h" #include "base/logging.h" -#include "cc/resources/priority_calculator.h" namespace cc { @@ -43,23 +42,6 @@ bool ManagedMemoryPolicy::operator!=(const ManagedMemoryPolicy& other) const { } // static -int ManagedMemoryPolicy::PriorityCutoffToValue( - MemoryAllocation::PriorityCutoff priority_cutoff) { - switch (priority_cutoff) { - case MemoryAllocation::CUTOFF_ALLOW_NOTHING: - return PriorityCalculator::AllowNothingCutoff(); - case MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY: - return PriorityCalculator::AllowVisibleOnlyCutoff(); - case MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE: - return PriorityCalculator::AllowVisibleAndNearbyCutoff(); - case MemoryAllocation::CUTOFF_ALLOW_EVERYTHING: - return PriorityCalculator::AllowEverythingCutoff(); - } - NOTREACHED(); - return PriorityCalculator::AllowNothingCutoff(); -} - -// static TileMemoryLimitPolicy ManagedMemoryPolicy::PriorityCutoffToTileMemoryLimitPolicy( gpu::MemoryAllocation::PriorityCutoff priority_cutoff) { diff --git a/chromium/cc/output/managed_memory_policy.h b/chromium/cc/output/managed_memory_policy.h index a7273822a78..dee74ee1e8d 100644 --- a/chromium/cc/output/managed_memory_policy.h +++ b/chromium/cc/output/managed_memory_policy.h @@ -29,8 +29,6 @@ struct CC_EXPORT ManagedMemoryPolicy { gpu::MemoryAllocation::PriorityCutoff priority_cutoff_when_visible; size_t num_resources_limit; - static int PriorityCutoffToValue( - gpu::MemoryAllocation::PriorityCutoff priority_cutoff); static TileMemoryLimitPolicy PriorityCutoffToTileMemoryLimitPolicy( gpu::MemoryAllocation::PriorityCutoff priority_cutoff); }; diff --git a/chromium/cc/output/output_surface.cc b/chromium/cc/output/output_surface.cc index 670578ad6b0..a597a87d845 100644 --- a/chromium/cc/output/output_surface.cc +++ b/chromium/cc/output/output_surface.cc @@ -12,7 +12,9 @@ #include "cc/output/managed_memory_policy.h" #include "cc/output/output_surface_client.h" #include "gpu/GLES2/gl2extchromium.h" +#include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" +#include "third_party/skia/include/gpu/GrContext.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -209,4 +211,34 @@ OverlayCandidateValidator* OutputSurface::GetOverlayCandidateValidator() const { return nullptr; } +void OutputSurface::SetWorkerContextShouldAggressivelyFreeResources( + bool aggressively_free_resources) { + TRACE_EVENT1("cc", + "OutputSurface::SetWorkerContextShouldAggressivelyFreeResources", + "aggressively_free_resources", aggressively_free_resources); + if (auto* context_provider = worker_context_provider()) { + // The context lock must be held while accessing the worker context. + base::AutoLock context_lock(*context_provider->GetLock()); + + // Allow context to bind to current thread. + context_provider->DetachFromThread(); + + if (aggressively_free_resources) { + context_provider->DeleteCachedResources(); + } + + if (auto* context_support = context_provider->ContextSupport()) { + context_support->SetAggressivelyFreeResources( + aggressively_free_resources); + } + + // Allow context to bind to other threads. + context_provider->DetachFromThread(); + } +} + +bool OutputSurface::SurfaceIsSuspendForRecycle() const { + return false; +} + } // namespace cc diff --git a/chromium/cc/output/output_surface.h b/chromium/cc/output/output_surface.h index deaf97b4825..423dc6317c3 100644 --- a/chromium/cc/output/output_surface.h +++ b/chromium/cc/output/output_surface.h @@ -152,6 +152,13 @@ class CC_EXPORT OutputSurface { // there's new content. virtual void Invalidate() {} + // Updates the worker context provider's visibility, freeing GPU resources if + // appropriate. + virtual void SetWorkerContextShouldAggressivelyFreeResources(bool is_visible); + + // If this returns true, then the surface will not attempt to draw. + virtual bool SurfaceIsSuspendForRecycle() const; + protected: OutputSurfaceClient* client_; diff --git a/chromium/cc/output/output_surface_unittest.cc b/chromium/cc/output/output_surface_unittest.cc index 3b027027729..63373326507 100644 --- a/chromium/cc/output/output_surface_unittest.cc +++ b/chromium/cc/output/output_surface_unittest.cc @@ -15,7 +15,6 @@ #include "cc/test/test_web_graphics_context_3d.h" #include "gpu/GLES2/gl2extchromium.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/frame_time.h" namespace cc { namespace { diff --git a/chromium/cc/output/overlay_candidate.h b/chromium/cc/output/overlay_candidate.h index 36396358e65..b3e7fb359f1 100644 --- a/chromium/cc/output/overlay_candidate.h +++ b/chromium/cc/output/overlay_candidate.h @@ -34,6 +34,8 @@ class CC_EXPORT OverlayCandidate { gfx::OverlayTransform transform; // Format of the buffer to composite. ResourceFormat format; + // Size of the resource, in pixels. + gfx::Size resource_size_in_pixels; // Rect on the display to position the overlay to. Implementer must convert // to integer coordinates if setting |overlay_handled| to true. gfx::RectF display_rect; diff --git a/chromium/cc/output/overlay_processor.cc b/chromium/cc/output/overlay_processor.cc index 0f5ec560dd6..baae69dd10e 100644 --- a/chromium/cc/output/overlay_processor.cc +++ b/chromium/cc/output/overlay_processor.cc @@ -12,22 +12,19 @@ namespace cc { -OverlayProcessor::OverlayProcessor(OutputSurface* surface, - ResourceProvider* resource_provider) - : surface_(surface), resource_provider_(resource_provider) {} +OverlayProcessor::OverlayProcessor(OutputSurface* surface) : surface_(surface) { +} void OverlayProcessor::Initialize() { DCHECK(surface_); - if (!resource_provider_) - return; OverlayCandidateValidator* candidates = surface_->GetOverlayCandidateValidator(); if (candidates) { - strategies_.push_back(scoped_ptr<Strategy>( - new OverlayStrategySingleOnTop(candidates, resource_provider_))); - strategies_.push_back(scoped_ptr<Strategy>( - new OverlayStrategyUnderlay(candidates, resource_provider_))); + strategies_.push_back( + scoped_ptr<Strategy>(new OverlayStrategySingleOnTop(candidates))); + strategies_.push_back( + scoped_ptr<Strategy>(new OverlayStrategyUnderlay(candidates))); } } diff --git a/chromium/cc/output/overlay_processor.h b/chromium/cc/output/overlay_processor.h index e50972e711d..e37816c9565 100644 --- a/chromium/cc/output/overlay_processor.h +++ b/chromium/cc/output/overlay_processor.h @@ -29,7 +29,7 @@ class CC_EXPORT OverlayProcessor { }; typedef ScopedPtrVector<Strategy> StrategyList; - OverlayProcessor(OutputSurface* surface, ResourceProvider* resource_provider); + explicit OverlayProcessor(OutputSurface* surface); virtual ~OverlayProcessor(); // Virtual to allow testing different strategies. virtual void Initialize(); @@ -40,7 +40,6 @@ class CC_EXPORT OverlayProcessor { protected: StrategyList strategies_; OutputSurface* surface_; - ResourceProvider* resource_provider_; private: DISALLOW_COPY_AND_ASSIGN(OverlayProcessor); diff --git a/chromium/cc/output/overlay_strategy_common.cc b/chromium/cc/output/overlay_strategy_common.cc index be352a5130a..33b45942398 100644 --- a/chromium/cc/output/overlay_strategy_common.cc +++ b/chromium/cc/output/overlay_strategy_common.cc @@ -9,6 +9,7 @@ #include "cc/quads/solid_color_draw_quad.h" #include "cc/quads/stream_video_draw_quad.h" #include "cc/quads/texture_draw_quad.h" +#include "cc/resources/resource_provider.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/transform.h" @@ -16,28 +17,42 @@ namespace cc { OverlayStrategyCommon::OverlayStrategyCommon( - OverlayCandidateValidator* capability_checker, - ResourceProvider* resource_provider) - : capability_checker_(capability_checker), - resource_provider_(resource_provider) { + OverlayCandidateValidator* capability_checker) + : capability_checker_(capability_checker) { } OverlayStrategyCommon::~OverlayStrategyCommon() { } +bool OverlayStrategyCommon::Attempt(RenderPassList* render_passes_in_draw_order, + OverlayCandidateList* candidate_list) { + if (!capability_checker_) + return false; + RenderPass* root_render_pass = render_passes_in_draw_order->back(); + DCHECK(root_render_pass); + + QuadList& quad_list = root_render_pass->quad_list; + for (auto it = quad_list.begin(); it != quad_list.end(); ++it) { + OverlayCandidate candidate; + const DrawQuad* draw_quad = *it; + if (IsOverlayQuad(draw_quad) && + GetCandidateQuadInfo(*draw_quad, &candidate) && + TryOverlay(capability_checker_, render_passes_in_draw_order, + candidate_list, candidate, it)) + return true; + } + return false; +} + bool OverlayStrategyCommon::IsOverlayQuad(const DrawQuad* draw_quad) { - unsigned int resource_id; switch (draw_quad->material) { case DrawQuad::TEXTURE_CONTENT: - resource_id = TextureDrawQuad::MaterialCast(draw_quad)->resource_id; - break; + return TextureDrawQuad::MaterialCast(draw_quad)->allow_overlay(); case DrawQuad::STREAM_VIDEO_CONTENT: - resource_id = StreamVideoDrawQuad::MaterialCast(draw_quad)->resource_id; - break; + return StreamVideoDrawQuad::MaterialCast(draw_quad)->allow_overlay(); default: return false; } - return resource_provider_->AllowOverlay(resource_id); } bool OverlayStrategyCommon::IsInvisibleQuad(const DrawQuad* draw_quad) { @@ -45,7 +60,7 @@ bool OverlayStrategyCommon::IsInvisibleQuad(const DrawQuad* draw_quad) { const SolidColorDrawQuad* solid_quad = SolidColorDrawQuad::MaterialCast(draw_quad); SkColor color = solid_quad->color; - float opacity = solid_quad->opacity(); + float opacity = solid_quad->shared_quad_state->opacity; float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; return solid_quad->ShouldDrawWithBlending() && alpha < std::numeric_limits<float>::epsilon(); @@ -56,13 +71,14 @@ bool OverlayStrategyCommon::IsInvisibleQuad(const DrawQuad* draw_quad) { bool OverlayStrategyCommon::GetTextureQuadInfo(const TextureDrawQuad& quad, OverlayCandidate* quad_info) { gfx::OverlayTransform overlay_transform = - OverlayCandidate::GetOverlayTransform(quad.quadTransform(), - quad.y_flipped); + OverlayCandidate::GetOverlayTransform( + quad.shared_quad_state->quad_to_target_transform, quad.y_flipped); if (quad.background_color != SK_ColorTRANSPARENT || quad.premultiplied_alpha || overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID) return false; - quad_info->resource_id = quad.resource_id; + quad_info->resource_id = quad.resource_id(); + quad_info->resource_size_in_pixels = quad.resource_size_in_pixels(); quad_info->transform = overlay_transform; quad_info->uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right); return true; @@ -71,7 +87,8 @@ bool OverlayStrategyCommon::GetTextureQuadInfo(const TextureDrawQuad& quad, bool OverlayStrategyCommon::GetVideoQuadInfo(const StreamVideoDrawQuad& quad, OverlayCandidate* quad_info) { gfx::OverlayTransform overlay_transform = - OverlayCandidate::GetOverlayTransform(quad.quadTransform(), false); + OverlayCandidate::GetOverlayTransform( + quad.shared_quad_state->quad_to_target_transform, false); if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID) return false; if (!quad.matrix.IsScaleOrTranslation()) { @@ -79,7 +96,8 @@ bool OverlayStrategyCommon::GetVideoQuadInfo(const StreamVideoDrawQuad& quad, // coordinates yet. return false; } - quad_info->resource_id = quad.resource_id; + quad_info->resource_id = quad.resource_id(); + quad_info->resource_size_in_pixels = quad.resource_size_in_pixels(); quad_info->transform = overlay_transform; gfx::Point3F uv0 = gfx::Point3F(0, 0, 0); @@ -129,7 +147,7 @@ bool OverlayStrategyCommon::GetCandidateQuadInfo(const DrawQuad& draw_quad, quad_info->format = RGBA_8888; quad_info->display_rect = OverlayCandidate::GetOverlayRect( - draw_quad.quadTransform(), draw_quad.rect); + draw_quad.shared_quad_state->quad_to_target_transform, draw_quad.rect); return true; } diff --git a/chromium/cc/output/overlay_strategy_common.h b/chromium/cc/output/overlay_strategy_common.h index 515a106e782..2b81b90ee40 100644 --- a/chromium/cc/output/overlay_strategy_common.h +++ b/chromium/cc/output/overlay_strategy_common.h @@ -17,10 +17,12 @@ class OverlayCandidate; class CC_EXPORT OverlayStrategyCommon : public OverlayProcessor::Strategy { public: - OverlayStrategyCommon(OverlayCandidateValidator* capability_checker, - ResourceProvider* resource_provider); + explicit OverlayStrategyCommon(OverlayCandidateValidator* capability_checker); ~OverlayStrategyCommon() override; + bool Attempt(RenderPassList* render_passes_in_draw_order, + OverlayCandidateList* candidate_list) override; + protected: bool GetCandidateQuadInfo(const DrawQuad& draw_quad, OverlayCandidate* quad_info); @@ -38,10 +40,15 @@ class CC_EXPORT OverlayStrategyCommon : public OverlayProcessor::Strategy { bool GetVideoQuadInfo(const StreamVideoDrawQuad& quad, OverlayCandidate* quad_info); - OverlayCandidateValidator* capability_checker_; - ResourceProvider* resource_provider_; + virtual bool TryOverlay(OverlayCandidateValidator* capability_checker, + RenderPassList* render_passes_in_draw_order, + OverlayCandidateList* candidate_list, + const OverlayCandidate& candidate, + QuadList::Iterator iter) = 0; private: + OverlayCandidateValidator* capability_checker_; + DISALLOW_COPY_AND_ASSIGN(OverlayStrategyCommon); }; } // namespace cc diff --git a/chromium/cc/output/overlay_strategy_single_on_top.cc b/chromium/cc/output/overlay_strategy_single_on_top.cc index 65b039e6052..fd47e0f3b72 100644 --- a/chromium/cc/output/overlay_strategy_single_on_top.cc +++ b/chromium/cc/output/overlay_strategy_single_on_top.cc @@ -6,53 +6,38 @@ #include <limits> +#include "cc/output/overlay_candidate_validator.h" #include "cc/quads/draw_quad.h" namespace cc { OverlayStrategySingleOnTop::OverlayStrategySingleOnTop( - OverlayCandidateValidator* capability_checker, - ResourceProvider* resource_provider) - : OverlayStrategyCommon(capability_checker, resource_provider) { + OverlayCandidateValidator* capability_checker) + : OverlayStrategyCommon(capability_checker) { } -bool OverlayStrategySingleOnTop::Attempt( - RenderPassList* render_passes_in_draw_order, - OverlayCandidateList* candidate_list) { - // Only attempt to handle very simple case for now. - if (!capability_checker_) - return false; +bool OverlayStrategySingleOnTop::TryOverlay( + OverlayCandidateValidator* capability_checker, + RenderPassList* render_passes_in_draw_order, + OverlayCandidateList* candidate_list, + const OverlayCandidate& candidate, + QuadList::Iterator candidate_iterator) { RenderPass* root_render_pass = render_passes_in_draw_order->back(); - DCHECK(root_render_pass); - - OverlayCandidate candidate; QuadList& quad_list = root_render_pass->quad_list; - auto candidate_iterator = quad_list.end(); - for (auto it = quad_list.begin(); it != quad_list.end(); ++it) { - const DrawQuad* draw_quad = *it; - if (IsOverlayQuad(draw_quad)) { - // Check that no prior quads overlap it. - bool intersects = false; - gfx::RectF rect = draw_quad->rect; - draw_quad->quadTransform().TransformRect(&rect); - for (auto overlap_iter = quad_list.cbegin(); overlap_iter != it; - ++overlap_iter) { - gfx::RectF overlap_rect = overlap_iter->rect; - overlap_iter->quadTransform().TransformRect(&overlap_rect); - if (rect.Intersects(overlap_rect) && !IsInvisibleQuad(*overlap_iter)) { - intersects = true; - break; - } - } - if (intersects || !GetCandidateQuadInfo(*draw_quad, &candidate)) - continue; - candidate_iterator = it; - break; - } + const DrawQuad* draw_quad = *candidate_iterator; + gfx::RectF rect = draw_quad->rect; + draw_quad->shared_quad_state->quad_to_target_transform.TransformRect(&rect); + + // Check that no prior quads overlap it. + for (auto overlap_iter = quad_list.cbegin(); + overlap_iter != candidate_iterator; ++overlap_iter) { + gfx::RectF overlap_rect = overlap_iter->rect; + overlap_iter->shared_quad_state->quad_to_target_transform.TransformRect( + &overlap_rect); + if (rect.Intersects(overlap_rect) && !IsInvisibleQuad(*overlap_iter)) + return false; } - if (candidate_iterator == quad_list.end()) - return false; // Add our primary surface. OverlayCandidateList candidates; @@ -61,11 +46,11 @@ bool OverlayStrategySingleOnTop::Attempt( candidates.push_back(main_image); // Add the overlay. - candidate.plane_z_order = 1; candidates.push_back(candidate); + candidates.back().plane_z_order = 1; // Check for support. - capability_checker_->CheckOverlaySupport(&candidates); + capability_checker->CheckOverlaySupport(&candidates); // If the candidate can be handled by an overlay, create a pass for it. if (candidates[1].overlay_handled) { diff --git a/chromium/cc/output/overlay_strategy_single_on_top.h b/chromium/cc/output/overlay_strategy_single_on_top.h index eeecd32fa4c..2b9cf4d04fd 100644 --- a/chromium/cc/output/overlay_strategy_single_on_top.h +++ b/chromium/cc/output/overlay_strategy_single_on_top.h @@ -19,10 +19,13 @@ class TextureDrawQuad; class CC_EXPORT OverlayStrategySingleOnTop : public OverlayStrategyCommon { public: - OverlayStrategySingleOnTop(OverlayCandidateValidator* capability_checker, - ResourceProvider* resource_provider); - bool Attempt(RenderPassList* render_passes_in_draw_order, - OverlayCandidateList* candidate_list) override; + explicit OverlayStrategySingleOnTop( + OverlayCandidateValidator* capability_checker); + bool TryOverlay(OverlayCandidateValidator* capability_checker, + RenderPassList* render_passes_in_draw_order, + OverlayCandidateList* candidate_list, + const OverlayCandidate& candidate, + QuadList::Iterator candidate_iterator) override; private: DISALLOW_COPY_AND_ASSIGN(OverlayStrategySingleOnTop); diff --git a/chromium/cc/output/overlay_strategy_underlay.cc b/chromium/cc/output/overlay_strategy_underlay.cc index 631ce03d95a..dd2b90f4814 100644 --- a/chromium/cc/output/overlay_strategy_underlay.cc +++ b/chromium/cc/output/overlay_strategy_underlay.cc @@ -4,37 +4,26 @@ #include "cc/output/overlay_strategy_underlay.h" +#include "cc/output/overlay_candidate_validator.h" #include "cc/quads/draw_quad.h" #include "cc/quads/solid_color_draw_quad.h" namespace cc { OverlayStrategyUnderlay::OverlayStrategyUnderlay( - OverlayCandidateValidator* capability_checker, - ResourceProvider* resource_provider) - : OverlayStrategyCommon(capability_checker, resource_provider) { + OverlayCandidateValidator* capability_checker) + : OverlayStrategyCommon(capability_checker) { } -bool OverlayStrategyUnderlay::Attempt( - RenderPassList* render_passes_in_draw_order, - OverlayCandidateList* candidate_list) { - if (!capability_checker_) - return false; +bool OverlayStrategyUnderlay::TryOverlay( + OverlayCandidateValidator* capability_checker, + RenderPassList* render_passes_in_draw_order, + OverlayCandidateList* candidate_list, + const OverlayCandidate& candidate, + QuadList::Iterator candidate_iterator) { RenderPass* root_render_pass = render_passes_in_draw_order->back(); - DCHECK(root_render_pass); - - OverlayCandidate candidate; QuadList& quad_list = root_render_pass->quad_list; - auto candidate_iterator = quad_list.end(); - for (auto it = quad_list.begin(); it != quad_list.end(); ++it) { - if (IsOverlayQuad(*it) && GetCandidateQuadInfo(**it, &candidate)) { - candidate_iterator = it; - break; - } - } - if (candidate_iterator == quad_list.end()) - return false; // Add our primary surface. OverlayCandidateList candidates; @@ -43,11 +32,11 @@ bool OverlayStrategyUnderlay::Attempt( candidates.push_back(main_image); // Add the overlay. - candidate.plane_z_order = -1; candidates.push_back(candidate); + candidates.back().plane_z_order = -1; // Check for support. - capability_checker_->CheckOverlaySupport(&candidates); + capability_checker->CheckOverlaySupport(&candidates); // If the candidate can be handled by an overlay, create a pass for it. We // need to switch out the video quad with a black transparent one. diff --git a/chromium/cc/output/overlay_strategy_underlay.h b/chromium/cc/output/overlay_strategy_underlay.h index 881e170535f..fd55bef4319 100644 --- a/chromium/cc/output/overlay_strategy_underlay.h +++ b/chromium/cc/output/overlay_strategy_underlay.h @@ -18,10 +18,13 @@ class TextureDrawQuad; // are fully opaque. class CC_EXPORT OverlayStrategyUnderlay : public OverlayStrategyCommon { public: - OverlayStrategyUnderlay(OverlayCandidateValidator* capability_checker, - ResourceProvider* resource_provider); - bool Attempt(RenderPassList* render_passes_in_draw_order, - OverlayCandidateList* candidate_list) override; + explicit OverlayStrategyUnderlay( + OverlayCandidateValidator* capability_checker); + bool TryOverlay(OverlayCandidateValidator* capability_checker, + RenderPassList* render_passes_in_draw_order, + OverlayCandidateList* candidate_list, + const OverlayCandidate& candidate, + QuadList::Iterator candidate_iterator) override; private: DISALLOW_COPY_AND_ASSIGN(OverlayStrategyUnderlay); diff --git a/chromium/cc/output/overlay_unittest.cc b/chromium/cc/output/overlay_unittest.cc index c9a2ae0c19a..6ac9b1c64c8 100644 --- a/chromium/cc/output/overlay_unittest.cc +++ b/chromium/cc/output/overlay_unittest.cc @@ -18,6 +18,7 @@ #include "cc/resources/resource_provider.h" #include "cc/resources/texture_mailbox.h" #include "cc/test/fake_output_surface_client.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/test_context_provider.h" #include "cc/test/test_shared_bitmap_manager.h" @@ -77,11 +78,9 @@ void SingleOverlayValidator::CheckOverlaySupport( template <typename OverlayStrategyType> class SingleOverlayProcessor : public OverlayProcessor { public: - SingleOverlayProcessor(OutputSurface* surface, - ResourceProvider* resource_provider) - : OverlayProcessor(surface, resource_provider) { + explicit SingleOverlayProcessor(OutputSurface* surface) + : OverlayProcessor(surface) { EXPECT_EQ(surface, surface_); - EXPECT_EQ(resource_provider, resource_provider_); } // Virtual to allow testing different strategies. @@ -89,22 +88,20 @@ class SingleOverlayProcessor : public OverlayProcessor { OverlayCandidateValidator* candidates = surface_->GetOverlayCandidateValidator(); ASSERT_TRUE(candidates != NULL); - strategies_.push_back(scoped_ptr<Strategy>( - new OverlayStrategyType(candidates, resource_provider_))); + strategies_.push_back( + scoped_ptr<Strategy>(new OverlayStrategyType(candidates))); } }; class DefaultOverlayProcessor : public OverlayProcessor { public: - DefaultOverlayProcessor(OutputSurface* surface, - ResourceProvider* resource_provider); + explicit DefaultOverlayProcessor(OutputSurface* surface); size_t GetStrategyCount(); }; -DefaultOverlayProcessor::DefaultOverlayProcessor( - OutputSurface* surface, - ResourceProvider* resource_provider) - : OverlayProcessor(surface, resource_provider) {} +DefaultOverlayProcessor::DefaultOverlayProcessor(OutputSurface* surface) + : OverlayProcessor(surface) { +} size_t DefaultOverlayProcessor::GetStrategyCount() { return strategies_.size(); @@ -152,12 +149,10 @@ scoped_ptr<RenderPass> CreateRenderPass() { return pass.Pass(); } -ResourceProvider::ResourceId CreateResource( - ResourceProvider* resource_provider) { +ResourceId CreateResource(ResourceProvider* resource_provider) { unsigned sync_point = 0; TextureMailbox mailbox = TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); - mailbox.set_allow_overlay(true); scoped_ptr<SingleReleaseCallbackImpl> release_callback = SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); @@ -180,11 +175,13 @@ TextureDrawQuad* CreateCandidateQuadAt(ResourceProvider* resource_provider, const SharedQuadState* shared_quad_state, RenderPass* render_pass, const gfx::Rect& rect) { - ResourceProvider::ResourceId resource_id = CreateResource(resource_provider); + ResourceId resource_id = CreateResource(resource_provider); bool premultiplied_alpha = false; bool flipped = false; bool nearest_neighbor = false; float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + gfx::Size resource_size_in_pixels = gfx::Size(64, 64); + bool allow_overlay = true; TextureDrawQuad* overlay_quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); @@ -200,6 +197,8 @@ TextureDrawQuad* CreateCandidateQuadAt(ResourceProvider* resource_provider, vertex_opacity, flipped, nearest_neighbor); + overlay_quad->set_allow_overlay(allow_overlay); + overlay_quad->set_resource_size_in_pixels(resource_size_in_pixels); return overlay_quad; } @@ -210,12 +209,14 @@ StreamVideoDrawQuad* CreateCandidateVideoQuadAt( RenderPass* render_pass, const gfx::Rect& rect, const gfx::Transform& transform) { - ResourceProvider::ResourceId resource_id = CreateResource(resource_provider); + ResourceId resource_id = CreateResource(resource_provider); + gfx::Size resource_size_in_pixels = gfx::Size(64, 64); + bool allow_overlay = true; StreamVideoDrawQuad* overlay_quad = render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>(); overlay_quad->SetNew(shared_quad_state, rect, rect, rect, resource_id, - transform); + resource_size_in_pixels, allow_overlay, transform); return overlay_quad; } @@ -277,8 +278,8 @@ static void CompareRenderPassLists(const RenderPassList& expected_list, exp_iter != expected->quad_list.cend(); ++exp_iter, ++act_iter) { EXPECT_EQ(exp_iter->rect.ToString(), act_iter->rect.ToString()); - EXPECT_EQ(exp_iter->shared_quad_state->content_bounds.ToString(), - act_iter->shared_quad_state->content_bounds.ToString()); + EXPECT_EQ(exp_iter->shared_quad_state->quad_layer_bounds.ToString(), + act_iter->shared_quad_state->quad_layer_bounds.ToString()); } } } @@ -302,11 +303,11 @@ TEST(OverlayTest, OverlaysProcessorHasStrategy) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( - &output_surface, shared_bitmap_manager.get(), NULL, NULL, 0, false, 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + &output_surface, shared_bitmap_manager.get()); scoped_ptr<DefaultOverlayProcessor> overlay_processor( - new DefaultOverlayProcessor(&output_surface, resource_provider.get())); + new DefaultOverlayProcessor(&output_surface)); overlay_processor->Initialize(); EXPECT_GE(2U, overlay_processor->GetStrategyCount()); } @@ -322,16 +323,11 @@ class OverlayTest : public testing::Test { EXPECT_TRUE(output_surface_->GetOverlayCandidateValidator() != NULL); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1); - - overlay_processor_.reset(new SingleOverlayProcessor<OverlayStrategyType>( - output_surface_.get(), resource_provider_.get())); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), shared_bitmap_manager_.get()); + + overlay_processor_.reset( + new SingleOverlayProcessor<OverlayStrategyType>(output_surface_.get())); overlay_processor_->Initialize(); } @@ -352,7 +348,7 @@ TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) { CreateFullscreenCandidateQuad(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); - unsigned original_resource_id = original_quad->resource_id; + unsigned original_resource_id = original_quad->resource_id(); // Add something behind it. CreateFullscreenCheckeredQuad(resource_provider_.get(), @@ -550,7 +546,7 @@ TEST_F(SingleOverlayOnTopTest, RejectNonAxisAlignedTransform) { pass->shared_quad_state_list.back(), pass.get()); pass->shared_quad_state_list.back() - ->content_to_target_transform.RotateAboutXAxis(45.f); + ->quad_to_target_transform.RotateAboutXAxis(45.f); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -567,8 +563,8 @@ TEST_F(SingleOverlayOnTopTest, AllowVerticalFlip) { scoped_ptr<RenderPass> pass = CreateRenderPass(); CreateCandidateQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), rect); - pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.0f, - -1.0f); + pass->shared_quad_state_list.back()->quad_to_target_transform.Scale(2.0f, + -1.0f); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -587,8 +583,8 @@ TEST_F(SingleOverlayOnTopTest, AllowHorizontalFlip) { scoped_ptr<RenderPass> pass = CreateRenderPass(); CreateCandidateQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), rect); - pass->shared_quad_state_list.back()->content_to_target_transform.Scale(-1.0f, - 2.0f); + pass->shared_quad_state_list.back()->quad_to_target_transform.Scale(-1.0f, + 2.0f); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -606,8 +602,8 @@ TEST_F(SingleOverlayOnTopTest, AllowPositiveScaleTransform) { scoped_ptr<RenderPass> pass = CreateRenderPass(); CreateCandidateQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), rect); - pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.0f, - 1.0f); + pass->shared_quad_state_list.back()->quad_to_target_transform.Scale(2.0f, + 1.0f); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -624,7 +620,7 @@ TEST_F(SingleOverlayOnTopTest, Allow90DegreeRotation) { CreateCandidateQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), rect); pass->shared_quad_state_list.back() - ->content_to_target_transform.RotateAboutZAxis(90.f); + ->quad_to_target_transform.RotateAboutZAxis(90.f); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -642,7 +638,7 @@ TEST_F(SingleOverlayOnTopTest, Allow180DegreeRotation) { CreateCandidateQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), rect); pass->shared_quad_state_list.back() - ->content_to_target_transform.RotateAboutZAxis(180.f); + ->quad_to_target_transform.RotateAboutZAxis(180.f); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -660,7 +656,7 @@ TEST_F(SingleOverlayOnTopTest, Allow270DegreeRotation) { CreateCandidateQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), rect); pass->shared_quad_state_list.back() - ->content_to_target_transform.RotateAboutZAxis(270.f); + ->quad_to_target_transform.RotateAboutZAxis(270.f); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -961,8 +957,8 @@ class GLRendererWithOverlaysTest : public testing::Test { provider_ = TestContextProvider::Create(); output_surface_.reset(new OverlayOutputSurface(provider_)); CHECK(output_surface_->BindToClient(&output_surface_client_)); - resource_provider_ = ResourceProvider::Create( - output_surface_.get(), NULL, NULL, NULL, 0, false, 1); + resource_provider_ = + FakeResourceProvider::Create(output_surface_.get(), nullptr); provider_->support()->SetScheduleOverlayPlaneCallback(base::Bind( &MockOverlayScheduler::Schedule, base::Unretained(&scheduler_))); @@ -1104,10 +1100,8 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) { Init(use_validator); renderer_->set_expect_overlays(true); - ResourceProvider::ResourceId resource1 = - CreateResource(resource_provider_.get()); - ResourceProvider::ResourceId resource2 = - CreateResource(resource_provider_.get()); + ResourceId resource1 = CreateResource(resource_provider_.get()); + ResourceId resource2 = CreateResource(resource_provider_.get()); scoped_ptr<RenderPass> pass = CreateRenderPass(); RenderPassList pass_list; diff --git a/chromium/cc/output/program_binding.cc b/chromium/cc/output/program_binding.cc index 7809e1085c7..c05447c7d65 100644 --- a/chromium/cc/output/program_binding.cc +++ b/chromium/cc/output/program_binding.cc @@ -6,6 +6,7 @@ #include "base/trace_event/trace_event.h" #include "cc/output/geometry_binding.h" +#include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/gles2_interface.h" using gpu::gles2::GLES2Interface; @@ -129,4 +130,8 @@ void ProgramBindingBase::CleanupShaders(GLES2Interface* context) { } } +bool ProgramBindingBase::IsContextLost(GLES2Interface* context) { + return context->GetGraphicsResetStatusKHR() != GL_NO_ERROR; +} + } // namespace cc diff --git a/chromium/cc/output/program_binding.h b/chromium/cc/output/program_binding.h index 1d5132bdaea..8018cad76e3 100644 --- a/chromium/cc/output/program_binding.h +++ b/chromium/cc/output/program_binding.h @@ -42,6 +42,8 @@ class ProgramBindingBase { unsigned fragment_shader); void CleanupShaders(gpu::gles2::GLES2Interface* context); + bool IsContextLost(gpu::gles2::GLES2Interface* context); + unsigned program_; unsigned vertex_shader_id_; unsigned fragment_shader_id_; @@ -79,7 +81,7 @@ class ProgramBinding : public ProgramBindingBase { DCHECK(context_provider); DCHECK(!initialized_); - if (context_provider->IsContextLost()) + if (IsContextLost(context_provider->ContextGL())) return; fragment_shader_.set_blend_mode(blend_mode); @@ -89,7 +91,7 @@ class ProgramBinding : public ProgramBindingBase { context_provider->ContextGL(), vertex_shader_.GetShaderString(), fragment_shader_.GetShaderString(precision, sampler))) { - DCHECK(context_provider->IsContextLost()); + DCHECK(IsContextLost(context_provider->ContextGL())); return; } @@ -101,7 +103,7 @@ class ProgramBinding : public ProgramBindingBase { // Link after binding uniforms if (!Link(context_provider->ContextGL())) { - DCHECK(context_provider->IsContextLost()); + DCHECK(IsContextLost(context_provider->ContextGL())); return; } diff --git a/chromium/cc/output/renderer_pixeltest.cc b/chromium/cc/output/renderer_pixeltest.cc index 330c8bfd983..8472ff50613 100644 --- a/chromium/cc/output/renderer_pixeltest.cc +++ b/chromium/cc/output/renderer_pixeltest.cc @@ -47,48 +47,38 @@ scoped_ptr<RenderPass> CreateTestRenderPass( } SharedQuadState* CreateTestSharedQuadState( - gfx::Transform content_to_target_transform, + gfx::Transform quad_to_target_transform, const gfx::Rect& rect, RenderPass* render_pass) { - const gfx::Size content_bounds = rect.size(); - const gfx::Rect visible_content_rect = rect; + const gfx::Size layer_bounds = rect.size(); + const gfx::Rect visible_layer_rect = rect; const gfx::Rect clip_rect = rect; const bool is_clipped = false; const float opacity = 1.0f; const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode; int sorting_context_id = 0; SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState(); - shared_state->SetAll(content_to_target_transform, - content_bounds, - visible_content_rect, - clip_rect, - is_clipped, - opacity, - blend_mode, - sorting_context_id); + shared_state->SetAll(quad_to_target_transform, layer_bounds, + visible_layer_rect, clip_rect, is_clipped, opacity, + blend_mode, sorting_context_id); return shared_state; } SharedQuadState* CreateTestSharedQuadStateClipped( - gfx::Transform content_to_target_transform, + gfx::Transform quad_to_target_transform, const gfx::Rect& rect, const gfx::Rect& clip_rect, RenderPass* render_pass) { - const gfx::Size content_bounds = rect.size(); - const gfx::Rect visible_content_rect = clip_rect; + const gfx::Size layer_bounds = rect.size(); + const gfx::Rect visible_layer_rect = clip_rect; const bool is_clipped = true; const float opacity = 1.0f; const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode; int sorting_context_id = 0; SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState(); - shared_state->SetAll(content_to_target_transform, - content_bounds, - visible_content_rect, - clip_rect, - is_clipped, - opacity, - blend_mode, - sorting_context_id); + shared_state->SetAll(quad_to_target_transform, layer_bounds, + visible_layer_rect, clip_rect, is_clipped, opacity, + blend_mode, sorting_context_id); return shared_state; } @@ -137,12 +127,11 @@ void CreateTestTwoColoredTextureDrawQuad(const gfx::Rect& rect, pixels[i * rect.width() + k] = pixel_stripe_color; } } - ResourceProvider::ResourceId resource = resource_provider->CreateResource( + ResourceId resource = resource_provider->CreateResource( rect.size(), GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); - resource_provider->SetPixels(resource, - reinterpret_cast<uint8_t*>(&pixels.front()), - rect, rect, gfx::Vector2d()); + resource_provider->CopyToResource( + resource, reinterpret_cast<uint8_t*>(&pixels.front()), rect.size()); float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; const gfx::PointF uv_top_left(0.0f, 0.0f); @@ -172,7 +161,7 @@ void CreateTestTextureDrawQuad(const gfx::Rect& rect, size_t num_pixels = static_cast<size_t>(rect.width()) * rect.height(); std::vector<uint32_t> pixels(num_pixels, pixel_color); - ResourceProvider::ResourceId resource = resource_provider->CreateResource( + ResourceId resource = resource_provider->CreateResource( rect.size(), GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); resource_provider->CopyToResource( @@ -202,10 +191,14 @@ void CreateTestYUVVideoDrawQuad_FromVideoFrame( const gfx::Rect& visible_rect, ResourceProvider* resource_provider) { const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A); - const YUVVideoDrawQuad::ColorSpace color_space = - (video_frame->format() == media::VideoFrame::YV12J - ? YUVVideoDrawQuad::JPEG - : YUVVideoDrawQuad::REC_601); + YUVVideoDrawQuad::ColorSpace color_space = YUVVideoDrawQuad::REC_601; + int video_frame_color_space; + if (video_frame->metadata()->GetInteger( + media::VideoFrameMetadata::COLOR_SPACE, &video_frame_color_space) && + video_frame_color_space == media::VideoFrame::COLOR_SPACE_JPEG) { + color_space = YUVVideoDrawQuad::JPEG; + } + const gfx::Rect opaque_rect(0, 0, 0, 0); if (with_alpha) { @@ -224,22 +217,19 @@ void CreateTestYUVVideoDrawQuad_FromVideoFrame( EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()), resources.release_callbacks.size()); - ResourceProvider::ResourceId y_resource = - resource_provider->CreateResourceFromTextureMailbox( - resources.mailboxes[media::VideoFrame::kYPlane], - SingleReleaseCallbackImpl::Create( - resources.release_callbacks[media::VideoFrame::kYPlane])); - ResourceProvider::ResourceId u_resource = - resource_provider->CreateResourceFromTextureMailbox( - resources.mailboxes[media::VideoFrame::kUPlane], - SingleReleaseCallbackImpl::Create( - resources.release_callbacks[media::VideoFrame::kUPlane])); - ResourceProvider::ResourceId v_resource = - resource_provider->CreateResourceFromTextureMailbox( - resources.mailboxes[media::VideoFrame::kVPlane], - SingleReleaseCallbackImpl::Create( - resources.release_callbacks[media::VideoFrame::kVPlane])); - ResourceProvider::ResourceId a_resource = 0; + ResourceId y_resource = resource_provider->CreateResourceFromTextureMailbox( + resources.mailboxes[media::VideoFrame::kYPlane], + SingleReleaseCallbackImpl::Create( + resources.release_callbacks[media::VideoFrame::kYPlane])); + ResourceId u_resource = resource_provider->CreateResourceFromTextureMailbox( + resources.mailboxes[media::VideoFrame::kUPlane], + SingleReleaseCallbackImpl::Create( + resources.release_callbacks[media::VideoFrame::kUPlane])); + ResourceId v_resource = resource_provider->CreateResourceFromTextureMailbox( + resources.mailboxes[media::VideoFrame::kVPlane], + SingleReleaseCallbackImpl::Create( + resources.release_callbacks[media::VideoFrame::kVPlane])); + ResourceId a_resource = 0; if (with_alpha) { a_resource = resource_provider->CreateResourceFromTextureMailbox( resources.mailboxes[media::VideoFrame::kAPlane], @@ -327,6 +317,7 @@ void CreateTestYUVVideoDrawQuad_Striped( void CreateTestYUVVideoDrawQuad_TwoColor( const SharedQuadState* shared_state, media::VideoFrame::Format format, + media::VideoFrame::ColorSpace color_space, bool is_transparent, const gfx::RectF& tex_coord_rect, const gfx::Size& background_size, @@ -346,6 +337,8 @@ void CreateTestYUVVideoDrawQuad_TwoColor( scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(format, background_size, foreground_rect, foreground_rect.size(), base::TimeDelta()); + video_frame->metadata()->SetInteger(media::VideoFrameMetadata::COLOR_SPACE, + color_space); int planes[] = {media::VideoFrame::kYPlane, media::VideoFrame::kUPlane, @@ -388,6 +381,7 @@ void CreateTestYUVVideoDrawQuad_TwoColor( void CreateTestYUVVideoDrawQuad_Solid( const SharedQuadState* shared_state, media::VideoFrame::Format format, + media::VideoFrame::ColorSpace color_space, bool is_transparent, const gfx::RectF& tex_coord_rect, uint8 y, @@ -400,6 +394,8 @@ void CreateTestYUVVideoDrawQuad_Solid( ResourceProvider* resource_provider) { scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame( format, rect.size(), rect, rect.size(), base::TimeDelta()); + video_frame->metadata()->SetInteger(media::VideoFrameMetadata::COLOR_SPACE, + color_space); // YUV values of a solid, constant, color. Useful for testing that color // space/color range are being handled properly. @@ -847,14 +843,16 @@ TYPED_TEST(IntersectingQuadGLPixelTest, YUVVideoQuads) { (this->quad_rect_.height() / 2) & ~0xF); CreateTestYUVVideoDrawQuad_TwoColor( - this->front_quad_state_, media::VideoFrame::YV12J, false, + this->front_quad_state_, media::VideoFrame::YV12, + media::VideoFrame::COLOR_SPACE_JPEG, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(), this->quad_rect_, 0, 128, 128, inner_rect, 29, 255, 107, this->render_pass_.get(), this->video_resource_updater_.get(), this->resource_provider_.get()); CreateTestYUVVideoDrawQuad_TwoColor( - this->back_quad_state_, media::VideoFrame::YV12J, false, + this->back_quad_state_, media::VideoFrame::YV12, + media::VideoFrame::COLOR_SPACE_JPEG, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(), this->quad_rect_, 149, 43, 21, inner_rect, 0, 128, 128, this->render_pass_.get(), this->video_resource_updater2_.get(), @@ -933,6 +931,7 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) { class VideoGLRendererPixelTest : public GLRendererPixelTest { protected: void CreateEdgeBleedPass(media::VideoFrame::Format format, + media::VideoFrame::ColorSpace color_space, RenderPassList* pass_list) { gfx::Rect rect(200, 200); @@ -961,9 +960,10 @@ class VideoGLRendererPixelTest : public GLRendererPixelTest { // the final image. Bleeding will appear on all four sides of the video // if the tex coords are not clamped. CreateTestYUVVideoDrawQuad_TwoColor( - shared_state, format, false, tex_coord_rect, background_size, - gfx::Rect(background_size), 128, 128, 128, green_rect, 149, 43, 21, - pass.get(), video_resource_updater_.get(), resource_provider_.get()); + shared_state, format, color_space, false, tex_coord_rect, + background_size, gfx::Rect(background_size), 128, 128, 128, green_rect, + 149, 43, 21, pass.get(), video_resource_updater_.get(), + resource_provider_.get()); pass_list->push_back(pass.Pass()); } @@ -1058,7 +1058,8 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVRectBlack) { // In MPEG color range YUV values of (15,128,128) should produce black. CreateTestYUVVideoDrawQuad_Solid( - shared_state, media::VideoFrame::YV12, false, + shared_state, media::VideoFrame::YV12, + media::VideoFrame::COLOR_SPACE_UNSPECIFIED, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(), video_resource_updater_.get(), rect, rect, resource_provider_.get()); @@ -1083,7 +1084,8 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) { // YUV of (149,43,21) should be green (0,255,0) in RGB. CreateTestYUVVideoDrawQuad_Solid( - shared_state, media::VideoFrame::YV12J, false, + shared_state, media::VideoFrame::YV12, + media::VideoFrame::COLOR_SPACE_JPEG, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(), video_resource_updater_.get(), rect, rect, resource_provider_.get()); @@ -1099,7 +1101,8 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) { // tex coord rect is only a partial subrectangle of the coded contents. TEST_F(VideoGLRendererPixelTest, YUVEdgeBleed) { RenderPassList pass_list; - CreateEdgeBleedPass(media::VideoFrame::YV12J, &pass_list); + CreateEdgeBleedPass(media::VideoFrame::YV12, + media::VideoFrame::COLOR_SPACE_JPEG, &pass_list); EXPECT_TRUE(this->RunPixelTest(&pass_list, base::FilePath(FILE_PATH_LITERAL("green.png")), FuzzyPixelOffByOneComparator(true))); @@ -1107,7 +1110,8 @@ TEST_F(VideoGLRendererPixelTest, YUVEdgeBleed) { TEST_F(VideoGLRendererPixelTest, YUVAEdgeBleed) { RenderPassList pass_list; - CreateEdgeBleedPass(media::VideoFrame::YV12A, &pass_list); + CreateEdgeBleedPass(media::VideoFrame::YV12A, + media::VideoFrame::COLOR_SPACE_UNSPECIFIED, &pass_list); EXPECT_TRUE(this->RunPixelTest(&pass_list, base::FilePath(FILE_PATH_LITERAL("green.png")), FuzzyPixelOffByOneComparator(true))); @@ -1124,7 +1128,8 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVJRectGrey) { // Dark grey in JPEG color range (in MPEG, this is black). CreateTestYUVVideoDrawQuad_Solid( - shared_state, media::VideoFrame::YV12J, false, + shared_state, media::VideoFrame::YV12, + media::VideoFrame::COLOR_SPACE_JPEG, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(), video_resource_updater_.get(), rect, rect, resource_provider_.get()); @@ -1204,9 +1209,9 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); shared_state->opacity = 0.5f; gfx::Rect blue_rect(0, @@ -1225,7 +1230,7 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) { yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false); SharedQuadState* blank_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); SolidColorDrawQuad* white = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -1296,9 +1301,9 @@ TYPED_TEST(RendererPixelTest, FastPassSaturateFilter) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); shared_state->opacity = 0.5f; gfx::Rect blue_rect(0, @@ -1317,7 +1322,7 @@ TYPED_TEST(RendererPixelTest, FastPassSaturateFilter) { yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false); SharedQuadState* blank_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); SolidColorDrawQuad* white = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -1367,9 +1372,9 @@ TYPED_TEST(RendererPixelTest, FastPassFilterChain) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); shared_state->opacity = 0.5f; gfx::Rect blue_rect(0, @@ -1388,7 +1393,7 @@ TYPED_TEST(RendererPixelTest, FastPassFilterChain) { yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false); SharedQuadState* blank_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); SolidColorDrawQuad* white = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -1440,9 +1445,9 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); shared_state->opacity = 0.5f; gfx::Rect blue_rect(0, @@ -1461,7 +1466,7 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) { yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false); SharedQuadState* blank_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); SolidColorDrawQuad* white = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -1536,9 +1541,9 @@ TYPED_TEST(RendererPixelTest, EnlargedRenderPassTexture) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); gfx::Rect blue_rect(0, 0, @@ -1585,9 +1590,9 @@ TYPED_TEST(RendererPixelTest, EnlargedRenderPassTextureWithAntiAliasing) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); gfx::Rect blue_rect(0, 0, @@ -1679,10 +1684,9 @@ TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad) { rect.Inset(6, 6, 4, 4); } - ResourceProvider::ResourceId mask_resource_id = - this->resource_provider_->CreateResource( - mask_rect.size(), GL_CLAMP_TO_EDGE, - ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); + ResourceId mask_resource_id = this->resource_provider_->CreateResource( + mask_rect.size(), GL_CLAMP_TO_EDGE, + ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); { SkAutoLockPixels lock(bitmap); this->resource_provider_->CopyToResource( @@ -1743,41 +1747,32 @@ class RendererPixelTestWithBackgroundFilter CreateTestRootRenderPass(root_id, device_viewport_rect); root_pass->has_transparent_background = false; - gfx::Transform identity_content_to_target_transform; + gfx::Transform identity_quad_to_target_transform; RenderPassId filter_pass_id(2, 1); gfx::Transform transform_to_root; - scoped_ptr<RenderPass> filter_pass = - CreateTestRenderPass(filter_pass_id, - filter_pass_content_rect_, - transform_to_root); + scoped_ptr<RenderPass> filter_pass = CreateTestRenderPass( + filter_pass_id, filter_pass_layer_rect_, transform_to_root); // A non-visible quad in the filtering render pass. { SharedQuadState* shared_state = - CreateTestSharedQuadState(identity_content_to_target_transform, - filter_pass_content_rect_, - filter_pass.get()); + CreateTestSharedQuadState(identity_quad_to_target_transform, + filter_pass_layer_rect_, filter_pass.get()); SolidColorDrawQuad* color_quad = filter_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - color_quad->SetNew(shared_state, - filter_pass_content_rect_, - filter_pass_content_rect_, - SK_ColorTRANSPARENT, - false); + color_quad->SetNew(shared_state, filter_pass_layer_rect_, + filter_pass_layer_rect_, SK_ColorTRANSPARENT, false); } { SharedQuadState* shared_state = CreateTestSharedQuadState(filter_pass_to_target_transform_, - filter_pass_content_rect_, - filter_pass.get()); + filter_pass_layer_rect_, filter_pass.get()); RenderPassDrawQuad* filter_pass_quad = root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); - filter_pass_quad->SetNew(shared_state, - filter_pass_content_rect_, - filter_pass_content_rect_, - filter_pass_id, + filter_pass_quad->SetNew(shared_state, filter_pass_layer_rect_, + filter_pass_layer_rect_, filter_pass_id, 0, // mask_resource_id gfx::Vector2dF(), // mask_uv_scale gfx::Size(), // mask_texture_size @@ -1791,7 +1786,7 @@ class RendererPixelTestWithBackgroundFilter gfx::Rect left_rect = gfx::Rect(0, 0, kColumnWidth, 20); for (int i = 0; left_rect.y() < device_viewport_rect.height(); ++i) { SharedQuadState* shared_state = CreateTestSharedQuadState( - identity_content_to_target_transform, left_rect, root_pass.get()); + identity_quad_to_target_transform, left_rect, root_pass.get()); SolidColorDrawQuad* color_quad = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); color_quad->SetNew( @@ -1802,7 +1797,7 @@ class RendererPixelTestWithBackgroundFilter gfx::Rect middle_rect = gfx::Rect(kColumnWidth+1, 0, kColumnWidth, 20); for (int i = 0; middle_rect.y() < device_viewport_rect.height(); ++i) { SharedQuadState* shared_state = CreateTestSharedQuadState( - identity_content_to_target_transform, middle_rect, root_pass.get()); + identity_quad_to_target_transform, middle_rect, root_pass.get()); SolidColorDrawQuad* color_quad = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); color_quad->SetNew( @@ -1813,7 +1808,7 @@ class RendererPixelTestWithBackgroundFilter gfx::Rect right_rect = gfx::Rect((kColumnWidth+1)*2, 0, kColumnWidth, 20); for (int i = 0; right_rect.y() < device_viewport_rect.height(); ++i) { SharedQuadState* shared_state = CreateTestSharedQuadState( - identity_content_to_target_transform, right_rect, root_pass.get()); + identity_quad_to_target_transform, right_rect, root_pass.get()); SolidColorDrawQuad* color_quad = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); color_quad->SetNew( @@ -1822,9 +1817,8 @@ class RendererPixelTestWithBackgroundFilter } SharedQuadState* shared_state = - CreateTestSharedQuadState(identity_content_to_target_transform, - device_viewport_rect, - root_pass.get()); + CreateTestSharedQuadState(identity_quad_to_target_transform, + device_viewport_rect, root_pass.get()); SolidColorDrawQuad* background_quad = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); background_quad->SetNew(shared_state, @@ -1840,7 +1834,7 @@ class RendererPixelTestWithBackgroundFilter RenderPassList pass_list_; FilterOperations background_filters_; gfx::Transform filter_pass_to_target_transform_; - gfx::Rect filter_pass_content_rect_; + gfx::Rect filter_pass_layer_rect_; }; typedef ::testing::Types<GLRenderer, SoftwareRenderer> @@ -1856,8 +1850,8 @@ TEST_F(GLRendererPixelTestWithBackgroundFilter, InvertFilter) { this->background_filters_.Append( FilterOperation::CreateInvertFilter(1.f)); - this->filter_pass_content_rect_ = gfx::Rect(this->device_viewport_size_); - this->filter_pass_content_rect_.Inset(12, 14, 16, 18); + this->filter_pass_layer_rect_ = gfx::Rect(this->device_viewport_size_); + this->filter_pass_layer_rect_.Inset(12, 14, 16, 18); this->SetUpRenderPassList(); EXPECT_TRUE(this->RunPixelTest( @@ -1964,9 +1958,9 @@ TEST_F(ExternalStencilPixelTest, RenderSurfacesIgnoreStencil) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); gfx::Rect blue_rect(0, 0, @@ -2021,26 +2015,26 @@ TEST_F(GLRendererPixelTest, AntiAliasing) { RenderPassId id(1, 1); scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); - gfx::Transform red_content_to_target_transform; - red_content_to_target_transform.Rotate(10); - SharedQuadState* red_shared_state = CreateTestSharedQuadState( - red_content_to_target_transform, rect, pass.get()); + gfx::Transform red_quad_to_target_transform; + red_quad_to_target_transform.Rotate(10); + SharedQuadState* red_shared_state = + CreateTestSharedQuadState(red_quad_to_target_transform, rect, pass.get()); SolidColorDrawQuad* red = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); red->SetNew(red_shared_state, rect, rect, SK_ColorRED, false); - gfx::Transform yellow_content_to_target_transform; - yellow_content_to_target_transform.Rotate(5); + gfx::Transform yellow_quad_to_target_transform; + yellow_quad_to_target_transform.Rotate(5); SharedQuadState* yellow_shared_state = CreateTestSharedQuadState( - yellow_content_to_target_transform, rect, pass.get()); + yellow_quad_to_target_transform, rect, pass.get()); SolidColorDrawQuad* yellow = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); yellow->SetNew(yellow_shared_state, rect, rect, SK_ColorYELLOW, false); - gfx::Transform blue_content_to_target_transform; + gfx::Transform blue_quad_to_target_transform; SharedQuadState* blue_shared_state = CreateTestSharedQuadState( - blue_content_to_target_transform, rect, pass.get()); + blue_quad_to_target_transform, rect, pass.get()); SolidColorDrawQuad* blue = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -2065,30 +2059,29 @@ TEST_F(GLRendererPixelTest, AxisAligned) { scoped_ptr<RenderPass> pass = CreateTestRenderPass(id, rect, transform_to_root); - gfx::Transform red_content_to_target_transform; - red_content_to_target_transform.Translate(50, 50); - red_content_to_target_transform.Scale( - 0.5f + 1.0f / (rect.width() * 2.0f), - 0.5f + 1.0f / (rect.height() * 2.0f)); - SharedQuadState* red_shared_state = CreateTestSharedQuadState( - red_content_to_target_transform, rect, pass.get()); + gfx::Transform red_quad_to_target_transform; + red_quad_to_target_transform.Translate(50, 50); + red_quad_to_target_transform.Scale(0.5f + 1.0f / (rect.width() * 2.0f), + 0.5f + 1.0f / (rect.height() * 2.0f)); + SharedQuadState* red_shared_state = + CreateTestSharedQuadState(red_quad_to_target_transform, rect, pass.get()); SolidColorDrawQuad* red = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); red->SetNew(red_shared_state, rect, rect, SK_ColorRED, false); - gfx::Transform yellow_content_to_target_transform; - yellow_content_to_target_transform.Translate(25.5f, 25.5f); - yellow_content_to_target_transform.Scale(0.5f, 0.5f); + gfx::Transform yellow_quad_to_target_transform; + yellow_quad_to_target_transform.Translate(25.5f, 25.5f); + yellow_quad_to_target_transform.Scale(0.5f, 0.5f); SharedQuadState* yellow_shared_state = CreateTestSharedQuadState( - yellow_content_to_target_transform, rect, pass.get()); + yellow_quad_to_target_transform, rect, pass.get()); SolidColorDrawQuad* yellow = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); yellow->SetNew(yellow_shared_state, rect, rect, SK_ColorYELLOW, false); - gfx::Transform blue_content_to_target_transform; + gfx::Transform blue_quad_to_target_transform; SharedQuadState* blue_shared_state = CreateTestSharedQuadState( - blue_content_to_target_transform, rect, pass.get()); + blue_quad_to_target_transform, rect, pass.get()); SolidColorDrawQuad* blue = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -2113,22 +2106,21 @@ TEST_F(GLRendererPixelTest, ForceAntiAliasingOff) { scoped_ptr<RenderPass> pass = CreateTestRenderPass(id, rect, transform_to_root); - gfx::Transform hole_content_to_target_transform; - hole_content_to_target_transform.Translate(50, 50); - hole_content_to_target_transform.Scale( - 0.5f + 1.0f / (rect.width() * 2.0f), - 0.5f + 1.0f / (rect.height() * 2.0f)); + gfx::Transform hole_quad_to_target_transform; + hole_quad_to_target_transform.Translate(50, 50); + hole_quad_to_target_transform.Scale(0.5f + 1.0f / (rect.width() * 2.0f), + 0.5f + 1.0f / (rect.height() * 2.0f)); SharedQuadState* hole_shared_state = CreateTestSharedQuadState( - hole_content_to_target_transform, rect, pass.get()); + hole_quad_to_target_transform, rect, pass.get()); SolidColorDrawQuad* hole = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); hole->SetAll( hole_shared_state, rect, rect, rect, false, SK_ColorTRANSPARENT, true); - gfx::Transform green_content_to_target_transform; + gfx::Transform green_quad_to_target_transform; SharedQuadState* green_shared_state = CreateTestSharedQuadState( - green_content_to_target_transform, rect, pass.get()); + green_quad_to_target_transform, rect, pass.get()); SolidColorDrawQuad* green = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -2150,13 +2142,11 @@ TEST_F(GLRendererPixelTest, AntiAliasingPerspective) { CreateTestRootRenderPass(RenderPassId(1, 1), rect); gfx::Rect red_rect(0, 0, 180, 500); - gfx::Transform red_content_to_target_transform( - 1.0f, 2.4520f, 10.6206f, 19.0f, - 0.0f, 0.3528f, 5.9737f, 9.5f, - 0.0f, -0.2250f, -0.9744f, 0.0f, - 0.0f, 0.0225f, 0.0974f, 1.0f); + gfx::Transform red_quad_to_target_transform( + 1.0f, 2.4520f, 10.6206f, 19.0f, 0.0f, 0.3528f, 5.9737f, 9.5f, 0.0f, + -0.2250f, -0.9744f, 0.0f, 0.0f, 0.0225f, 0.0974f, 1.0f); SharedQuadState* red_shared_state = CreateTestSharedQuadState( - red_content_to_target_transform, red_rect, pass.get()); + red_quad_to_target_transform, red_rect, pass.get()); SolidColorDrawQuad* red = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); red->SetNew(red_shared_state, red_rect, red_rect, SK_ColorRED, false); @@ -2213,16 +2203,14 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) { scoped_refptr<FakePicturePileImpl> blue_pile = FakePicturePileImpl::CreateFromPile(blue_recording.get(), nullptr); - gfx::Transform blue_content_to_target_transform; + gfx::Transform blue_quad_to_target_transform; gfx::Vector2d offset(viewport.bottom_right() - blue_rect.bottom_right()); - blue_content_to_target_transform.Translate(offset.x(), offset.y()); + blue_quad_to_target_transform.Translate(offset.x(), offset.y()); gfx::RectF blue_scissor_rect = blue_clip_rect; - blue_content_to_target_transform.TransformRect(&blue_scissor_rect); - SharedQuadState* blue_shared_state = - CreateTestSharedQuadStateClipped(blue_content_to_target_transform, - blue_rect, - gfx::ToEnclosingRect(blue_scissor_rect), - pass.get()); + blue_quad_to_target_transform.TransformRect(&blue_scissor_rect); + SharedQuadState* blue_shared_state = CreateTestSharedQuadStateClipped( + blue_quad_to_target_transform, blue_rect, + gfx::ToEnclosingRect(blue_scissor_rect), pass.get()); PictureDrawQuad* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); @@ -2242,9 +2230,9 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) { scoped_refptr<FakePicturePileImpl> green_pile = FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr); - gfx::Transform green_content_to_target_transform; + gfx::Transform green_quad_to_target_transform; SharedQuadState* green_shared_state = CreateTestSharedQuadState( - green_content_to_target_transform, viewport, pass.get()); + green_quad_to_target_transform, viewport, pass.get()); PictureDrawQuad* green_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); @@ -2284,9 +2272,9 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadOpacity) { scoped_refptr<FakePicturePileImpl> green_pile = FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr); - gfx::Transform green_content_to_target_transform; + gfx::Transform green_quad_to_target_transform; SharedQuadState* green_shared_state = CreateTestSharedQuadState( - green_content_to_target_transform, viewport, pass.get()); + green_quad_to_target_transform, viewport, pass.get()); green_shared_state->opacity = 0.5f; PictureDrawQuad* green_quad = @@ -2305,9 +2293,9 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadOpacity) { scoped_refptr<FakePicturePileImpl> white_pile = FakePicturePileImpl::CreateFromPile(white_recording.get(), nullptr); - gfx::Transform white_content_to_target_transform; + gfx::Transform white_quad_to_target_transform; SharedQuadState* white_shared_state = CreateTestSharedQuadState( - white_content_to_target_transform, viewport, pass.get()); + white_quad_to_target_transform, viewport, pass.get()); PictureDrawQuad* white_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); @@ -2376,9 +2364,9 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadDisableImageFiltering) { scoped_refptr<FakePicturePileImpl> pile = FakePicturePileImpl::CreateFromPile(recording.get(), nullptr); - gfx::Transform content_to_target_transform; - SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport, pass.get()); + gfx::Transform quad_to_target_transform; + SharedQuadState* shared_state = + CreateTestSharedQuadState(quad_to_target_transform, viewport, pass.get()); PictureDrawQuad* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, @@ -2428,9 +2416,9 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNearestNeighbor) { scoped_refptr<FakePicturePileImpl> pile = FakePicturePileImpl::CreateFromPile(recording.get(), nullptr); - gfx::Transform content_to_target_transform; - SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport, pass.get()); + gfx::Transform quad_to_target_transform; + SharedQuadState* shared_state = + CreateTestSharedQuadState(quad_to_target_transform, viewport, pass.get()); PictureDrawQuad* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, @@ -2464,10 +2452,9 @@ TYPED_TEST(RendererPixelTest, TileDrawQuadNearestNeighbor) { } gfx::Size tile_size(2, 2); - ResourceProvider::ResourceId resource = - this->resource_provider_->CreateResource( - tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, - RGBA_8888); + ResourceId resource = this->resource_provider_->CreateResource( + tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, + RGBA_8888); { SkAutoLockPixels lock(bitmap); @@ -2480,9 +2467,9 @@ TYPED_TEST(RendererPixelTest, TileDrawQuadNearestNeighbor) { scoped_ptr<RenderPass> pass = CreateTestRenderPass(id, viewport, transform_to_root); - gfx::Transform content_to_target_transform; - SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport, pass.get()); + gfx::Transform quad_to_target_transform; + SharedQuadState* shared_state = + CreateTestSharedQuadState(quad_to_target_transform, viewport, pass.get()); TileDrawQuad* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>(); quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, resource, @@ -2516,10 +2503,9 @@ TYPED_TEST(SoftwareRendererPixelTest, TextureDrawQuadNearestNeighbor) { } gfx::Size tile_size(2, 2); - ResourceProvider::ResourceId resource = - this->resource_provider_->CreateResource( - tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, - RGBA_8888); + ResourceId resource = this->resource_provider_->CreateResource( + tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, + RGBA_8888); { SkAutoLockPixels lock(bitmap); @@ -2532,9 +2518,9 @@ TYPED_TEST(SoftwareRendererPixelTest, TextureDrawQuadNearestNeighbor) { scoped_ptr<RenderPass> pass = CreateTestRenderPass(id, viewport, transform_to_root); - gfx::Transform content_to_target_transform; - SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport, pass.get()); + gfx::Transform quad_to_target_transform; + SharedQuadState* shared_state = + CreateTestSharedQuadState(quad_to_target_transform, viewport, pass.get()); float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); @@ -2569,10 +2555,9 @@ TYPED_TEST(SoftwareRendererPixelTest, TextureDrawQuadLinear) { } gfx::Size tile_size(2, 2); - ResourceProvider::ResourceId resource = - this->resource_provider_->CreateResource( - tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, - RGBA_8888); + ResourceId resource = this->resource_provider_->CreateResource( + tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, + RGBA_8888); { SkAutoLockPixels lock(bitmap); @@ -2585,9 +2570,9 @@ TYPED_TEST(SoftwareRendererPixelTest, TextureDrawQuadLinear) { scoped_ptr<RenderPass> pass = CreateTestRenderPass(id, viewport, transform_to_root); - gfx::Transform content_to_target_transform; - SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport, pass.get()); + gfx::Transform quad_to_target_transform; + SharedQuadState* shared_state = + CreateTestSharedQuadState(quad_to_target_transform, viewport, pass.get()); float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); @@ -2622,7 +2607,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) { // a few extra "cleanup rects" need to be added to clobber the blending // to make the output image more clean. This will also test subrects // of the layer. - gfx::Transform green_content_to_target_transform; + gfx::Transform green_quad_to_target_transform; gfx::Rect green_rect1(gfx::Point(80, 0), gfx::Size(20, 100)); gfx::Rect green_rect2(gfx::Point(0, 80), gfx::Size(100, 20)); @@ -2641,8 +2626,8 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) { FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr); SharedQuadState* top_right_green_shared_quad_state = - CreateTestSharedQuadState( - green_content_to_target_transform, viewport, pass.get()); + CreateTestSharedQuadState(green_quad_to_target_transform, viewport, + pass.get()); PictureDrawQuad* green_quad1 = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); @@ -2664,10 +2649,8 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) { gfx::Point(viewport.width() / 2, viewport.height() / 2), gfx::Size(viewport.width() / 2, viewport.height() / 2)); SharedQuadState* bottom_right_green_shared_state = - CreateTestSharedQuadStateClipped(green_content_to_target_transform, - viewport, - bottom_right_rect, - pass.get()); + CreateTestSharedQuadStateClipped(green_quad_to_target_transform, viewport, + bottom_right_rect, pass.get()); SolidColorDrawQuad* bottom_right_color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); bottom_right_color_quad->SetNew(bottom_right_green_shared_state, @@ -2717,11 +2700,11 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) { // At a scale of 4x the rectangles with a width of 2.5 will take up 10 pixels, // so scale an additional 10x to make them 100x100. - gfx::Transform content_to_target_transform; - content_to_target_transform.Scale(10.0, 10.0); + gfx::Transform quad_to_target_transform; + quad_to_target_transform.Scale(10.0, 10.0); gfx::Rect quad_content_rect(gfx::Size(20, 20)); SharedQuadState* blue_shared_state = CreateTestSharedQuadState( - content_to_target_transform, quad_content_rect, pass.get()); + quad_to_target_transform, quad_content_rect, pass.get()); PictureDrawQuad* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); blue_quad->SetNew(blue_shared_state, quad_content_rect, gfx::Rect(), @@ -2730,10 +2713,10 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) { content_union_rect, contents_scale, pile.get()); // Fill left half of viewport with green. - gfx::Transform half_green_content_to_target_transform; + gfx::Transform half_green_quad_to_target_transform; gfx::Rect half_green_rect(gfx::Size(viewport.width() / 2, viewport.height())); SharedQuadState* half_green_shared_state = CreateTestSharedQuadState( - half_green_content_to_target_transform, half_green_rect, pass.get()); + half_green_quad_to_target_transform, half_green_rect, pass.get()); SolidColorDrawQuad* half_color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); half_color_quad->SetNew(half_green_shared_state, @@ -2768,9 +2751,9 @@ TEST_F(GLRendererPixelTestWithFlippedOutputSurface, ExplicitFlipTest) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); gfx::Rect blue_rect(0, 0, @@ -2816,9 +2799,9 @@ TEST_F(GLRendererPixelTestWithFlippedOutputSurface, CheckChildPassUnflipped) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); gfx::Rect blue_rect(0, 0, @@ -2865,9 +2848,9 @@ TEST_F(GLRendererPixelTest, CheckReadbackSubset) { scoped_ptr<RenderPass> child_pass = CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root); - gfx::Transform content_to_target_transform; + gfx::Transform quad_to_target_transform; SharedQuadState* shared_state = CreateTestSharedQuadState( - content_to_target_transform, viewport_rect, child_pass.get()); + quad_to_target_transform, viewport_rect, child_pass.get()); // Draw a green quad full-size with a blue quad in the lower-right corner. gfx::Rect blue_rect(this->device_viewport_size_.width() * 3 / 4, @@ -2929,10 +2912,9 @@ TYPED_TEST(RendererPixelTest, WrapModeRepeat) { colors[2], colors[2], colors[3], colors[3], colors[2], colors[2], colors[3], colors[3], }; - ResourceProvider::ResourceId resource = - this->resource_provider_->CreateResource( - texture_size, GL_REPEAT, ResourceProvider::TEXTURE_HINT_IMMUTABLE, - RGBA_8888); + ResourceId resource = this->resource_provider_->CreateResource( + texture_size, GL_REPEAT, ResourceProvider::TEXTURE_HINT_IMMUTABLE, + RGBA_8888); this->resource_provider_->CopyToResource( resource, reinterpret_cast<uint8_t*>(pixels), texture_size); diff --git a/chromium/cc/output/renderer_settings.cc b/chromium/cc/output/renderer_settings.cc index 2277af3ed3c..0c0a10d1e01 100644 --- a/chromium/cc/output/renderer_settings.cc +++ b/chromium/cc/output/renderer_settings.cc @@ -17,6 +17,7 @@ RendererSettings::RendererSettings() partial_swap_enabled(false), finish_rendering_on_resize(false), should_clear_root_render_pass(true), + disable_gpu_vsync(false), refresh_rate(60.0), highp_threshold_min(0), use_rgba_4444_textures(false), diff --git a/chromium/cc/output/renderer_settings.h b/chromium/cc/output/renderer_settings.h index 6da02383826..4757f8d5571 100644 --- a/chromium/cc/output/renderer_settings.h +++ b/chromium/cc/output/renderer_settings.h @@ -21,6 +21,7 @@ class CC_EXPORT RendererSettings { bool partial_swap_enabled; bool finish_rendering_on_resize; bool should_clear_root_render_pass; + bool disable_gpu_vsync; double refresh_rate; int highp_threshold_min; bool use_rgba_4444_textures; diff --git a/chromium/cc/output/renderer_unittest.cc b/chromium/cc/output/renderer_unittest.cc index a8f09ff9474..48545587759 100644 --- a/chromium/cc/output/renderer_unittest.cc +++ b/chromium/cc/output/renderer_unittest.cc @@ -7,6 +7,7 @@ #include "cc/output/output_surface.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_renderer_client.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/test_context_provider.h" #include "cc/test/test_web_graphics_context_3d.h" #include "testing/gmock/include/gmock/gmock.h" @@ -82,8 +83,8 @@ class RendererTest : public ::testing::Test { new MockContextProvider(TestWebGraphicsContext3D::Create()); output_surface_.reset(new TestOutputSurface(context_provider_)); output_surface_->BindToClient(&output_surface_client_); - resource_provider_ = ResourceProvider::Create( - output_surface_.get(), NULL, NULL, NULL, 0, false, 1); + resource_provider_ = + FakeResourceProvider::Create(output_surface_.get(), nullptr); renderer_ = CreateRenderer<T>(&renderer_client_, &tree_settings_, output_surface_.get(), diff --git a/chromium/cc/output/software_renderer.cc b/chromium/cc/output/software_renderer.cc index 80a5f0e53ca..a8110efb4dc 100644 --- a/chromium/cc/output/software_renderer.cc +++ b/chromium/cc/output/software_renderer.cc @@ -20,7 +20,7 @@ #include "cc/quads/solid_color_draw_quad.h" #include "cc/quads/texture_draw_quad.h" #include "cc/quads/tile_draw_quad.h" -#include "skia/ext/opacity_draw_filter.h" +#include "skia/ext/opacity_filter_canvas.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkImageFilter.h" @@ -229,8 +229,7 @@ void SoftwareRenderer::PrepareSurfaceForPass( } } -bool SoftwareRenderer::IsSoftwareResource( - ResourceProvider::ResourceId resource_id) const { +bool SoftwareRenderer::IsSoftwareResource(ResourceId resource_id) const { switch (resource_provider_->GetResourceType(resource_id)) { case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: return false; @@ -251,7 +250,9 @@ void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame, TRACE_EVENT0("cc", "SoftwareRenderer::DoDrawQuad"); gfx::Transform quad_rect_matrix; - QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect); + QuadRectTransform(&quad_rect_matrix, + quad->shared_quad_state->quad_to_target_transform, + quad->rect); gfx::Transform contents_device_transform = frame->window_matrix * frame->projection_matrix * quad_rect_matrix; contents_device_transform.FlattenTo2d(); @@ -277,7 +278,7 @@ void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame, if (quad->ShouldDrawWithBlending() || quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode) { - current_paint_.setAlpha(quad->opacity() * 255); + current_paint_.setAlpha(quad->shared_quad_state->opacity * 255); current_paint_.setXfermodeMode(quad->shared_quad_state->blend_mode); } else { current_paint_.setXfermodeMode(SkXfermode::kSrc_Mode); @@ -352,7 +353,7 @@ void SoftwareRenderer::DrawCheckerboardQuad(const DrawingFrame* frame, gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional( QuadVertexRect(), quad->rect, quad->visible_rect); current_paint_.setColor(quad->color); - current_paint_.setAlpha(quad->opacity()); + current_paint_.setAlpha(quad->shared_quad_state->opacity); current_canvas_->drawRect(gfx::RectFToSkRect(visible_quad_vertex_rect), current_paint_); } @@ -369,7 +370,8 @@ void SoftwareRenderer::DrawDebugBorderQuad(const DrawingFrame* frame, current_canvas_->resetMatrix(); current_paint_.setColor(quad->color); - current_paint_.setAlpha(quad->opacity() * SkColorGetA(quad->color)); + current_paint_.setAlpha(quad->shared_quad_state->opacity * + SkColorGetA(quad->color)); current_paint_.setStyle(SkPaint::kStroke_Style); current_paint_.setStrokeWidth(quad->width); current_canvas_->drawPoints(SkCanvas::kPolygon_PointMode, @@ -385,23 +387,26 @@ void SoftwareRenderer::DrawPictureQuad(const DrawingFrame* frame, SkMatrix::kFill_ScaleToFit); current_canvas_->concat(content_matrix); - // TODO(aelias): This isn't correct in all cases. We should detect these - // cases and fall back to a persistent bitmap backing - // (http://crbug.com/280374). - skia::RefPtr<SkDrawFilter> opacity_filter = - skia::AdoptRef(new skia::OpacityDrawFilter( - quad->opacity(), frame->disable_picture_quad_image_filtering || - quad->nearest_neighbor)); - DCHECK(!current_canvas_->getDrawFilter()); - current_canvas_->setDrawFilter(opacity_filter.get()); - - TRACE_EVENT0("cc", - "SoftwareRenderer::DrawPictureQuad"); - - quad->raster_source->PlaybackToSharedCanvas( - current_canvas_, quad->content_rect, quad->contents_scale); - - current_canvas_->setDrawFilter(NULL); + const bool needs_transparency = + SkScalarRoundToInt(quad->shared_quad_state->opacity * 255) < 255; + const bool disable_image_filtering = + frame->disable_picture_quad_image_filtering || quad->nearest_neighbor; + + TRACE_EVENT0("cc", "SoftwareRenderer::DrawPictureQuad"); + + if (needs_transparency || disable_image_filtering) { + // TODO(aelias): This isn't correct in all cases. We should detect these + // cases and fall back to a persistent bitmap backing + // (http://crbug.com/280374). + skia::OpacityFilterCanvas filtered_canvas(current_canvas_, + quad->shared_quad_state->opacity, + disable_image_filtering); + quad->raster_source->PlaybackToSharedCanvas( + &filtered_canvas, quad->content_rect, quad->contents_scale); + } else { + quad->raster_source->PlaybackToSharedCanvas( + current_canvas_, quad->content_rect, quad->contents_scale); + } } void SoftwareRenderer::DrawSolidColorQuad(const DrawingFrame* frame, @@ -409,21 +414,22 @@ void SoftwareRenderer::DrawSolidColorQuad(const DrawingFrame* frame, gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional( QuadVertexRect(), quad->rect, quad->visible_rect); current_paint_.setColor(quad->color); - current_paint_.setAlpha(quad->opacity() * SkColorGetA(quad->color)); + current_paint_.setAlpha(quad->shared_quad_state->opacity * + SkColorGetA(quad->color)); current_canvas_->drawRect(gfx::RectFToSkRect(visible_quad_vertex_rect), current_paint_); } void SoftwareRenderer::DrawTextureQuad(const DrawingFrame* frame, const TextureDrawQuad* quad) { - if (!IsSoftwareResource(quad->resource_id)) { + if (!IsSoftwareResource(quad->resource_id())) { DrawUnsupportedQuad(frame, quad); return; } // TODO(skaslev): Add support for non-premultiplied alpha. ResourceProvider::ScopedReadLockSoftware lock(resource_provider_, - quad->resource_id); + quad->resource_id()); if (!lock.valid()) return; const SkBitmap* bitmap = lock.sk_bitmap(); @@ -481,10 +487,10 @@ void SoftwareRenderer::DrawTileQuad(const DrawingFrame* frame, // |resource_provider_| can be NULL in resourceless software draws, which // should never produce tile quads in the first place. DCHECK(resource_provider_); - DCHECK(IsSoftwareResource(quad->resource_id)); + DCHECK(IsSoftwareResource(quad->resource_id())); ResourceProvider::ScopedReadLockSoftware lock(resource_provider_, - quad->resource_id); + quad->resource_id()); if (!lock.valid()) return; DCHECK_EQ(GL_CLAMP_TO_EDGE, lock.wrap_mode()); @@ -561,9 +567,9 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame, } current_paint_.setShader(shader.get()); - if (quad->mask_resource_id) { - ResourceProvider::ScopedReadLockSoftware mask_lock(resource_provider_, - quad->mask_resource_id); + if (quad->mask_resource_id()) { + ResourceProvider::ScopedReadLockSoftware mask_lock( + resource_provider_, quad->mask_resource_id()); if (!lock.valid()) return; SkShader::TileMode mask_tile_mode = WrapModeToTileMode( @@ -608,7 +614,7 @@ void SoftwareRenderer::DrawUnsupportedQuad(const DrawingFrame* frame, #else current_paint_.setColor(SK_ColorMAGENTA); #endif - current_paint_.setAlpha(quad->opacity() * 255); + current_paint_.setAlpha(quad->shared_quad_state->opacity * 255); current_canvas_->drawRect(gfx::RectFToSkRect(QuadVertexRect()), current_paint_); } diff --git a/chromium/cc/output/software_renderer.h b/chromium/cc/output/software_renderer.h index 74f328edc01..c3090429635 100644 --- a/chromium/cc/output/software_renderer.h +++ b/chromium/cc/output/software_renderer.h @@ -74,7 +74,7 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer { void ClearCanvas(SkColor color); void ClearFramebuffer(DrawingFrame* frame); void SetClipRect(const gfx::Rect& rect); - bool IsSoftwareResource(ResourceProvider::ResourceId resource_id) const; + bool IsSoftwareResource(ResourceId resource_id) const; void DrawCheckerboardQuad(const DrawingFrame* frame, const CheckerboardDrawQuad* quad); diff --git a/chromium/cc/output/software_renderer_unittest.cc b/chromium/cc/output/software_renderer_unittest.cc index 3b2c4bc2317..a7ef1a20f7d 100644 --- a/chromium/cc/output/software_renderer_unittest.cc +++ b/chromium/cc/output/software_renderer_unittest.cc @@ -16,6 +16,7 @@ #include "cc/test/animation_test_common.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/render_pass_test_common.h" #include "cc/test/render_pass_test_utils.h" @@ -36,13 +37,8 @@ class SoftwareRendererTest : public testing::Test, public RendererClient { CHECK(output_surface_->BindToClient(&output_surface_client_)); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), shared_bitmap_manager_.get()); renderer_ = SoftwareRenderer::Create( this, &settings_, output_surface_.get(), resource_provider()); } @@ -134,8 +130,8 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) { gfx::Rect device_viewport_rect(outer_size); scoped_ptr<SkBitmap> output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect); - EXPECT_EQ(outer_rect.width(), output->info().fWidth); - EXPECT_EQ(outer_rect.height(), output->info().fHeight); + EXPECT_EQ(outer_rect.width(), output->info().width()); + EXPECT_EQ(outer_rect.height(), output->info().height()); EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0)); EXPECT_EQ(SK_ColorYELLOW, @@ -153,14 +149,12 @@ TEST_F(SoftwareRendererTest, TileQuad) { gfx::Rect inner_rect(gfx::Point(1, 1), inner_size); InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice)); - ResourceProvider::ResourceId resource_yellow = - resource_provider()->CreateResource( - outer_size, GL_CLAMP_TO_EDGE, - ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); - ResourceProvider::ResourceId resource_cyan = - resource_provider()->CreateResource( - inner_size, GL_CLAMP_TO_EDGE, - ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); + ResourceId resource_yellow = resource_provider()->CreateResource( + outer_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, + RGBA_8888); + ResourceId resource_cyan = resource_provider()->CreateResource( + inner_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, + RGBA_8888); SkBitmap yellow_tile; yellow_tile.allocN32Pixels(outer_size.width(), outer_size.height()); @@ -222,8 +216,8 @@ TEST_F(SoftwareRendererTest, TileQuad) { gfx::Rect device_viewport_rect(outer_size); scoped_ptr<SkBitmap> output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect); - EXPECT_EQ(outer_rect.width(), output->info().fWidth); - EXPECT_EQ(outer_rect.height(), output->info().fHeight); + EXPECT_EQ(outer_rect.width(), output->info().width()); + EXPECT_EQ(outer_rect.height(), output->info().height()); EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0)); EXPECT_EQ(SK_ColorYELLOW, @@ -240,10 +234,9 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) { visible_rect.Inset(1, 2, 3, 4); InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice)); - ResourceProvider::ResourceId resource_cyan = - resource_provider()->CreateResource( - tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, - RGBA_8888); + ResourceId resource_cyan = resource_provider()->CreateResource( + tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, + RGBA_8888); SkBitmap cyan_tile; // The lowest five rows are yellow. cyan_tile.allocN32Pixels(tile_size.width(), tile_size.height()); @@ -292,8 +285,8 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) { gfx::Rect device_viewport_rect(tile_size); scoped_ptr<SkBitmap> output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect); - EXPECT_EQ(tile_rect.width(), output->info().fWidth); - EXPECT_EQ(tile_rect.height(), output->info().fHeight); + EXPECT_EQ(tile_rect.width(), output->info().width()); + EXPECT_EQ(tile_rect.height(), output->info().height()); // Check portion of tile not in visible rect isn't drawn. const unsigned int kTransparent = SK_ColorTRANSPARENT; @@ -334,8 +327,8 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) { scoped_ptr<SkBitmap> output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect); - EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth); - EXPECT_EQ(device_viewport_rect.height(), output->info().fHeight); + EXPECT_EQ(device_viewport_rect.width(), output->info().width()); + EXPECT_EQ(device_viewport_rect.height(), output->info().height()); EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0)); EXPECT_EQ(SK_ColorGREEN, @@ -356,8 +349,8 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) { renderer()->DecideRenderPassAllocationsForFrame(list); output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect); - EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth); - EXPECT_EQ(device_viewport_rect.height(), output->info().fHeight); + EXPECT_EQ(device_viewport_rect.width(), output->info().width()); + EXPECT_EQ(device_viewport_rect.height(), output->info().height()); // If we didn't clear, the borders should still be green. EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0)); @@ -401,8 +394,8 @@ TEST_F(SoftwareRendererTest, RenderPassVisibleRect) { scoped_ptr<SkBitmap> output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect); - EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth); - EXPECT_EQ(device_viewport_rect.height(), output->info().fHeight); + EXPECT_EQ(device_viewport_rect.width(), output->info().width()); + EXPECT_EQ(device_viewport_rect.height(), output->info().height()); EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0)); EXPECT_EQ(SK_ColorGREEN, diff --git a/chromium/cc/output/swap_promise.h b/chromium/cc/output/swap_promise.h index 45deee83401..cf0b88de9eb 100644 --- a/chromium/cc/output/swap_promise.h +++ b/chromium/cc/output/swap_promise.h @@ -54,6 +54,8 @@ class CC_EXPORT SwapPromise { virtual void DidActivate() = 0; virtual void DidSwap(CompositorFrameMetadata* metadata) = 0; virtual void DidNotSwap(DidNotSwapReason reason) = 0; + // This is called when the main thread starts a (blocking) commit + virtual void OnCommit() {} // A non-zero trace id identifies a trace flow object that is embedded in the // swap promise. This can be used for registering additional flow steps to diff --git a/chromium/cc/output/texture_mailbox_deleter.cc b/chromium/cc/output/texture_mailbox_deleter.cc index aaf2a0ef223..7729c4ec7a1 100644 --- a/chromium/cc/output/texture_mailbox_deleter.cc +++ b/chromium/cc/output/texture_mailbox_deleter.cc @@ -65,9 +65,13 @@ scoped_ptr<SingleReleaseCallback> TextureMailboxDeleter::GetReleaseCallback( // Provide a callback for the main thread that posts back to the impl // thread. - scoped_ptr<SingleReleaseCallback> main_callback = - SingleReleaseCallback::Create(base::Bind( - &PostTaskFromMainToImplThread, impl_task_runner_, run_impl_callback)); + scoped_ptr<SingleReleaseCallback> main_callback; + if (impl_task_runner_) { + main_callback = SingleReleaseCallback::Create(base::Bind( + &PostTaskFromMainToImplThread, impl_task_runner_, run_impl_callback)); + } else { + main_callback = SingleReleaseCallback::Create(run_impl_callback); + } return main_callback.Pass(); } diff --git a/chromium/cc/output/texture_mailbox_deleter.h b/chromium/cc/output/texture_mailbox_deleter.h index 286512626d4..19760ea0a4c 100644 --- a/chromium/cc/output/texture_mailbox_deleter.h +++ b/chromium/cc/output/texture_mailbox_deleter.h @@ -19,6 +19,8 @@ class SingleReleaseCallback; class CC_EXPORT TextureMailboxDeleter { public: + // task_runner corresponds with the thread the delete task should be posted + // to. If null, the delete will happen on the calling thread. explicit TextureMailboxDeleter( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); ~TextureMailboxDeleter(); diff --git a/chromium/cc/output/texture_mailbox_deleter_unittest.cc b/chromium/cc/output/texture_mailbox_deleter_unittest.cc index 34d8595aa20..37b97123725 100644 --- a/chromium/cc/output/texture_mailbox_deleter_unittest.cc +++ b/chromium/cc/output/texture_mailbox_deleter_unittest.cc @@ -44,5 +44,31 @@ TEST(TextureMailboxDeleterTest, Destroy) { cb->Run(0, false); } +TEST(TextureMailboxDeleterTest, NullTaskRunner) { + scoped_ptr<TextureMailboxDeleter> deleter(new TextureMailboxDeleter(nullptr)); + + scoped_refptr<TestContextProvider> context_provider = + TestContextProvider::Create(); + context_provider->BindToCurrentThread(); + + GLuint texture_id = 0u; + context_provider->ContextGL()->GenTextures(1, &texture_id); + + EXPECT_TRUE(context_provider->HasOneRef()); + EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures()); + + scoped_ptr<SingleReleaseCallback> cb = + deleter->GetReleaseCallback(context_provider, texture_id); + EXPECT_FALSE(context_provider->HasOneRef()); + EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures()); + + cb->Run(0, false); + + // With no task runner the callback will immediately drops its ref on the + // ContextProvider and delete the texture. + EXPECT_TRUE(context_provider->HasOneRef()); + EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/output/vsync_parameter_observer.h b/chromium/cc/output/vsync_parameter_observer.h deleted file mode 100644 index e586925e110..00000000000 --- a/chromium/cc/output/vsync_parameter_observer.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_OUTPUT_VSYNC_PARAMETER_OBSERVER_H_ -#define CC_OUTPUT_VSYNC_PARAMETER_OBSERVER_H_ - -#include "base/time/time.h" - -// Interface for a class which observes the parameters regarding vsync -// information. -class VSyncParameterObserver { - public: - virtual void OnUpdateVSyncParameters(base::TimeTicks timebase, - base::TimeDelta interval) = 0; -}; - -#endif // CC_OUTPUT_VSYNC_PARAMETER_OBSERVER_H_ diff --git a/chromium/cc/playback/clip_display_item.cc b/chromium/cc/playback/clip_display_item.cc index a29787409c3..5941502860b 100644 --- a/chromium/cc/playback/clip_display_item.cc +++ b/chromium/cc/playback/clip_display_item.cc @@ -24,16 +24,16 @@ void ClipDisplayItem::SetNew(gfx::Rect clip_rect, clip_rect_ = clip_rect; rounded_clip_rects_ = rounded_clip_rects; - size_t memory_usage = sizeof(gfx::Rect); - for (size_t i = 0; i < rounded_clip_rects_.size(); ++i) { - memory_usage += sizeof(rounded_clip_rects_[i]); - } + size_t external_memory_usage = + rounded_clip_rects_.capacity() * sizeof(rounded_clip_rects_[0]); + DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 1 /* op_count */, - memory_usage); + external_memory_usage); } void ClipDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->save(); canvas->clipRect(SkRect::MakeXYWH(clip_rect_.x(), clip_rect_.y(), clip_rect_.width(), clip_rect_.height())); @@ -76,14 +76,15 @@ void ClipDisplayItem::AsValueInto(base::trace_event::TracedValue* array) const { EndClipDisplayItem::EndClipDisplayItem() { DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 0 /* op_count */, - 0 /* memory_usage */); + 0 /* external_memory_usage */); } EndClipDisplayItem::~EndClipDisplayItem() { } void EndClipDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->restore(); } diff --git a/chromium/cc/playback/clip_display_item.h b/chromium/cc/playback/clip_display_item.h index a4acc9f9893..83e0b6bf21a 100644 --- a/chromium/cc/playback/clip_display_item.h +++ b/chromium/cc/playback/clip_display_item.h @@ -14,7 +14,6 @@ #include "ui/gfx/geometry/rect.h" class SkCanvas; -class SkDrawPictureCallback; namespace cc { @@ -26,7 +25,9 @@ class CC_EXPORT ClipDisplayItem : public DisplayItem { void SetNew(gfx::Rect clip_rect, const std::vector<SkRRect>& rounded_clip_rects); - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; private: @@ -39,7 +40,9 @@ class CC_EXPORT EndClipDisplayItem : public DisplayItem { EndClipDisplayItem(); ~EndClipDisplayItem() override; - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; }; diff --git a/chromium/cc/playback/clip_path_display_item.cc b/chromium/cc/playback/clip_path_display_item.cc index 7be8922fca7..f7fd60626e5 100644 --- a/chromium/cc/playback/clip_path_display_item.cc +++ b/chromium/cc/playback/clip_path_display_item.cc @@ -23,13 +23,15 @@ void ClipPathDisplayItem::SetNew(const SkPath& clip_path, clip_op_ = clip_op; antialias_ = antialias; - size_t memory_usage = sizeof(SkPath) + sizeof(SkRegion::Op) + sizeof(bool); + // The size of SkPath's external storage is not currently accounted for (and + // may well be shared anyway). DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 1 /* op_count */, - memory_usage); + 0 /* external_memory_usage */); } void ClipPathDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->save(); canvas->clipPath(clip_path_, clip_op_, antialias_); } @@ -42,14 +44,16 @@ void ClipPathDisplayItem::AsValueInto( EndClipPathDisplayItem::EndClipPathDisplayItem() { DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 0 /* op_count */, - 0 /* memory_usage */); + 0 /* external_memory_usage */); } EndClipPathDisplayItem::~EndClipPathDisplayItem() { } -void EndClipPathDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { +void EndClipPathDisplayItem::Raster( + SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->restore(); } diff --git a/chromium/cc/playback/clip_path_display_item.h b/chromium/cc/playback/clip_path_display_item.h index 19d4a7ced39..732087b9789 100644 --- a/chromium/cc/playback/clip_path_display_item.h +++ b/chromium/cc/playback/clip_path_display_item.h @@ -12,7 +12,6 @@ #include "third_party/skia/include/core/SkRegion.h" class SkCanvas; -class SkDrawPictureCallback; namespace cc { @@ -23,7 +22,9 @@ class CC_EXPORT ClipPathDisplayItem : public DisplayItem { void SetNew(const SkPath& path, SkRegion::Op clip_op, bool antialias); - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; private: @@ -41,7 +42,9 @@ class CC_EXPORT EndClipPathDisplayItem : public DisplayItem { return make_scoped_ptr(new EndClipPathDisplayItem()); } - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; }; diff --git a/chromium/cc/playback/compositing_display_item.cc b/chromium/cc/playback/compositing_display_item.cc index bee1fb15dcb..31365b5881c 100644 --- a/chromium/cc/playback/compositing_display_item.cc +++ b/chromium/cc/playback/compositing_display_item.cc @@ -31,14 +31,15 @@ void CompositingDisplayItem::SetNew(uint8_t alpha, color_filter_ = cf; // TODO(pdr): Include color_filter's memory here. - size_t memory_usage = - sizeof(float) + sizeof(bool) + sizeof(SkRect) + sizeof(SkXfermode::Mode); + size_t external_memory_usage = 0; DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 1 /* op_count */, - memory_usage); + external_memory_usage); } -void CompositingDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { +void CompositingDisplayItem::Raster( + SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { SkPaint paint; paint.setXfermodeMode(xfermode_); paint.setAlpha(alpha_); @@ -59,14 +60,16 @@ void CompositingDisplayItem::AsValueInto( EndCompositingDisplayItem::EndCompositingDisplayItem() { DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 0 /* op_count */, - 0 /* memory_usage */); + 0 /* external_memory_usage */); } EndCompositingDisplayItem::~EndCompositingDisplayItem() { } -void EndCompositingDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { +void EndCompositingDisplayItem::Raster( + SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->restore(); } diff --git a/chromium/cc/playback/compositing_display_item.h b/chromium/cc/playback/compositing_display_item.h index d2af8d5ceb7..91cd3e71f8e 100644 --- a/chromium/cc/playback/compositing_display_item.h +++ b/chromium/cc/playback/compositing_display_item.h @@ -15,7 +15,6 @@ #include "ui/gfx/geometry/rect_f.h" class SkCanvas; -class SkDrawPictureCallback; namespace cc { @@ -29,7 +28,9 @@ class CC_EXPORT CompositingDisplayItem : public DisplayItem { SkRect* bounds, skia::RefPtr<SkColorFilter> color_filter); - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; private: @@ -49,7 +50,9 @@ class CC_EXPORT EndCompositingDisplayItem : public DisplayItem { return make_scoped_ptr(new EndCompositingDisplayItem()); } - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; }; diff --git a/chromium/cc/playback/display_item.h b/chromium/cc/playback/display_item.h index 2eedb91b5f3..d89807dd3ce 100644 --- a/chromium/cc/playback/display_item.h +++ b/chromium/cc/playback/display_item.h @@ -8,10 +8,10 @@ #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" #include "cc/debug/traced_value.h" +#include "third_party/skia/include/core/SkPicture.h" #include "ui/gfx/geometry/rect.h" class SkCanvas; -class SkDrawPictureCallback; namespace cc { @@ -21,29 +21,32 @@ class CC_EXPORT DisplayItem { void SetNew(bool is_suitable_for_gpu_rasterization, int approximate_op_count, - size_t picture_memory_usage) { + size_t external_memory_usage) { is_suitable_for_gpu_rasterization_ = is_suitable_for_gpu_rasterization; approximate_op_count_ = approximate_op_count; - picture_memory_usage_ = - picture_memory_usage + sizeof(bool) + sizeof(int) + sizeof(size_t); + external_memory_usage_ = external_memory_usage; } virtual void Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const = 0; + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const = 0; virtual void AsValueInto(base::trace_event::TracedValue* array) const = 0; bool is_suitable_for_gpu_rasterization() const { return is_suitable_for_gpu_rasterization_; } int approximate_op_count() const { return approximate_op_count_; } - size_t picture_memory_usage() const { return picture_memory_usage_; } + size_t external_memory_usage() const { return external_memory_usage_; } protected: DisplayItem(); bool is_suitable_for_gpu_rasterization_; int approximate_op_count_; - size_t picture_memory_usage_; + + // The size, in bytes, of the memory owned by this display item but not + // allocated within it (e.g. held through scoped_ptr or vector). + size_t external_memory_usage_; }; } // namespace cc diff --git a/chromium/cc/playback/display_item_list.cc b/chromium/cc/playback/display_item_list.cc index 656ade1deff..08fe71d26e6 100644 --- a/chromium/cc/playback/display_item_list.cc +++ b/chromium/cc/playback/display_item_list.cc @@ -6,15 +6,17 @@ #include <string> +#include "base/numerics/safe_conversions.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/base/math_util.h" #include "cc/debug/picture_debug_util.h" +#include "cc/debug/traced_display_item_list.h" #include "cc/debug/traced_picture.h" #include "cc/debug/traced_value.h" +#include "cc/playback/display_item_list_settings.h" #include "cc/playback/largest_display_item.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkDrawPictureCallback.h" #include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/utils/SkPictureUtils.h" #include "ui/gfx/skia_util.h" @@ -23,12 +25,10 @@ namespace cc { namespace { -bool PictureTracingEnabled() { +bool DisplayItemsTracingEnabled() { bool tracing_enabled; TRACE_EVENT_CATEGORY_GROUP_ENABLED( - TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") "," - TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"), - &tracing_enabled); + TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items"), &tracing_enabled); return tracing_enabled; } @@ -37,15 +37,19 @@ const int kDefaultNumDisplayItemsToReserve = 100; } // namespace DisplayItemList::DisplayItemList(gfx::Rect layer_rect, - bool use_cached_picture, + const DisplayItemListSettings& settings, bool retain_individual_display_items) - : items_(LargestDisplayItemSize(), kDefaultNumDisplayItemsToReserve), - use_cached_picture_(use_cached_picture), + : items_(LargestDisplayItemSize(), + settings.max_sidecar_size, + kDefaultNumDisplayItemsToReserve, + settings.sidecar_destroyer), + use_cached_picture_(settings.use_cached_picture), retain_individual_display_items_(retain_individual_display_items), layer_rect_(layer_rect), - is_suitable_for_gpu_rasterization_(true), + all_items_are_suitable_for_gpu_rasterization_(true), approximate_op_count_(0), - picture_memory_usage_(0) { + picture_memory_usage_(0), + external_memory_usage_(0) { #if DCHECK_IS_ON() needs_process_ = false; #endif @@ -59,31 +63,47 @@ DisplayItemList::DisplayItemList(gfx::Rect layer_rect, } } -DisplayItemList::DisplayItemList(gfx::Rect layer_rect, bool use_cached_picture) - : DisplayItemList(layer_rect, - use_cached_picture, - !use_cached_picture || PictureTracingEnabled()) { +DisplayItemList::DisplayItemList(gfx::Rect layer_rect, + const DisplayItemListSettings& settings) + : DisplayItemList( + layer_rect, + settings, + !settings.use_cached_picture || DisplayItemsTracingEnabled()) { +} + +scoped_refptr<DisplayItemList> DisplayItemList::CreateWithoutCachedPicture( + const DisplayItemListSettings& settings) { + DCHECK(!settings.use_cached_picture); + return Create(gfx::Rect(), settings); } scoped_refptr<DisplayItemList> DisplayItemList::Create( gfx::Rect layer_rect, bool use_cached_picture) { - return make_scoped_refptr( - new DisplayItemList(layer_rect, use_cached_picture)); + DisplayItemListSettings settings; + settings.use_cached_picture = use_cached_picture; + return Create(layer_rect, settings); +} + +scoped_refptr<DisplayItemList> DisplayItemList::Create( + gfx::Rect layer_rect, + const DisplayItemListSettings& settings) { + return make_scoped_refptr(new DisplayItemList(layer_rect, settings)); } DisplayItemList::~DisplayItemList() { } void DisplayItemList::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback, + SkPicture::AbortCallback* callback, + const gfx::Rect& canvas_target_playback_rect, float contents_scale) const { DCHECK(ProcessAppendedItemsCalled()); if (!use_cached_picture_) { canvas->save(); canvas->scale(contents_scale, contents_scale); for (auto* item : items_) - item->Raster(canvas, callback); + item->Raster(canvas, canvas_target_playback_rect, callback); canvas->restore(); } else { DCHECK(picture_); @@ -121,20 +141,20 @@ void DisplayItemList::ProcessAppendedItems() { #if DCHECK_IS_ON() needs_process_ = false; #endif - for (DisplayItem* item : items_) { - is_suitable_for_gpu_rasterization_ &= + for (const DisplayItem* item : items_) { + all_items_are_suitable_for_gpu_rasterization_ &= item->is_suitable_for_gpu_rasterization(); approximate_op_count_ += item->approximate_op_count(); if (use_cached_picture_) { DCHECK(canvas_); - item->Raster(canvas_.get(), NULL); + item->Raster(canvas_.get(), gfx::Rect(), NULL); } if (retain_individual_display_items_) { // Warning: this double-counts SkPicture data if use_cached_picture_ is // also true. - picture_memory_usage_ += item->picture_memory_usage(); + external_memory_usage_ += item->external_memory_usage(); } } @@ -142,24 +162,55 @@ void DisplayItemList::ProcessAppendedItems() { items_.clear(); } -void DisplayItemList::CreateAndCacheSkPicture() { - DCHECK(ProcessAppendedItemsCalled()); - // Convert to an SkPicture for faster rasterization. - DCHECK(use_cached_picture_); - DCHECK(!picture_); - picture_ = skia::AdoptRef(recorder_->endRecordingAsPicture()); - DCHECK(picture_); - picture_memory_usage_ += SkPictureUtils::ApproximateBytesUsed(picture_.get()); - recorder_.reset(); - canvas_.clear(); +void DisplayItemList::RasterIntoCanvas(const DisplayItem& item) { + DCHECK(canvas_); + DCHECK(!retain_individual_display_items_); + all_items_are_suitable_for_gpu_rasterization_ &= + item.is_suitable_for_gpu_rasterization(); + approximate_op_count_ += item.approximate_op_count(); + + item.Raster(canvas_.get(), gfx::Rect(), NULL); +} + +bool DisplayItemList::RetainsIndividualDisplayItems() const { + return retain_individual_display_items_; +} + +void DisplayItemList::RemoveLast() { + // We cannot remove the last item if it has been squashed into a picture. + // The last item should not have been handled by ProcessAppendedItems, so we + // don't need to remove it from approximate_op_count_, etc. + DCHECK(retain_individual_display_items_); + DCHECK(!use_cached_picture_); + items_.RemoveLast(); +} + +void DisplayItemList::Finalize() { + ProcessAppendedItems(); + + if (use_cached_picture_) { + // Convert to an SkPicture for faster rasterization. + DCHECK(use_cached_picture_); + DCHECK(!picture_); + picture_ = skia::AdoptRef(recorder_->endRecordingAsPicture()); + DCHECK(picture_); + picture_memory_usage_ = + SkPictureUtils::ApproximateBytesUsed(picture_.get()); + recorder_.reset(); + canvas_.clear(); + } } bool DisplayItemList::IsSuitableForGpuRasterization() const { DCHECK(ProcessAppendedItemsCalled()); + if (use_cached_picture_) + return picture_->suitableForGpuRasterization(NULL); + // This is more permissive than Picture's implementation, since none of the // items might individually trigger a veto even though they collectively have - // enough "bad" operations that a corresponding Picture would get vetoed. - return is_suitable_for_gpu_rasterization_; + // enough "bad" operations that a corresponding Picture would get vetoed. See + // crbug.com/513016. + return all_items_are_suitable_for_gpu_rasterization_; } int DisplayItemList::ApproximateOpCount() const { @@ -167,42 +218,58 @@ int DisplayItemList::ApproximateOpCount() const { return approximate_op_count_; } -size_t DisplayItemList::PictureMemoryUsage() const { +size_t DisplayItemList::ApproximateMemoryUsage() const { DCHECK(ProcessAppendedItemsCalled()); // We double-count in this case. Produce zero to avoid being misleading. if (use_cached_picture_ && retain_individual_display_items_) return 0; DCHECK_IMPLIES(use_cached_picture_, picture_); - return picture_memory_usage_; + + size_t memory_usage = sizeof(*this); + + // Memory outside this class due to |items_|. + memory_usage += items_.GetCapacityInBytes() + external_memory_usage_; + + // Memory outside this class due to |picture|. + memory_usage += picture_memory_usage_; + + // TODO(jbroman): Does anything else owned by this class substantially + // contribute to memory usage? + + return memory_usage; } scoped_refptr<base::trace_event::ConvertableToTraceFormat> -DisplayItemList::AsValue() const { +DisplayItemList::AsValue(bool include_items) const { DCHECK(ProcessAppendedItemsCalled()); scoped_refptr<base::trace_event::TracedValue> state = new base::trace_event::TracedValue(); - state->SetInteger("length", items_.size()); - state->BeginArray("params.items"); - for (const DisplayItem* item : items_) { - item->AsValueInto(state.get()); + if (include_items) { + state->BeginArray("params.items"); + for (const DisplayItem* item : items_) { + item->AsValueInto(state.get()); + } + state->EndArray(); } - state->EndArray(); - state->SetValue("params.layer_rect", MathUtil::AsValue(layer_rect_)); - SkPictureRecorder recorder; - SkCanvas* canvas = - recorder.beginRecording(layer_rect_.width(), layer_rect_.height()); - canvas->translate(-layer_rect_.x(), -layer_rect_.y()); - canvas->clipRect(gfx::RectToSkRect(layer_rect_)); - Raster(canvas, NULL, 1.f); - skia::RefPtr<SkPicture> picture = - skia::AdoptRef(recorder.endRecordingAsPicture()); + state->SetValue("params.layer_rect", MathUtil::AsValue(layer_rect_)); - std::string b64_picture; - PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture); - state->SetString("skp64", b64_picture); + if (!layer_rect_.IsEmpty()) { + SkPictureRecorder recorder; + SkCanvas* canvas = + recorder.beginRecording(layer_rect_.width(), layer_rect_.height()); + canvas->translate(-layer_rect_.x(), -layer_rect_.y()); + canvas->clipRect(gfx::RectToSkRect(layer_rect_)); + Raster(canvas, NULL, gfx::Rect(), 1.f); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); + + std::string b64_picture; + PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture); + state->SetString("skp64", b64_picture); + } return state; } @@ -210,9 +277,12 @@ DisplayItemList::AsValue() const { void DisplayItemList::EmitTraceSnapshot() const { DCHECK(ProcessAppendedItemsCalled()); TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( + TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items") "," TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") "," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"), - "cc::DisplayItemList", this, AsValue()); + "cc::DisplayItemList", this, + TracedDisplayItemList::AsTraceableDisplayItemList(this, + DisplayItemsTracingEnabled())); } void DisplayItemList::GatherPixelRefs(const gfx::Size& grid_cell_size) { @@ -226,4 +296,9 @@ void DisplayItemList::GatherPixelRefs(const gfx::Size& grid_cell_size) { pixel_refs_->GatherPixelRefsFromPicture(picture_.get()); } + +void* DisplayItemList::GetSidecar(DisplayItem* display_item) { + return items_.GetSidecar(display_item); +} + } // namespace cc diff --git a/chromium/cc/playback/display_item_list.h b/chromium/cc/playback/display_item_list.h index 84b41683720..35bcb8cc4b6 100644 --- a/chromium/cc/playback/display_item_list.h +++ b/chromium/cc/playback/display_item_list.h @@ -11,30 +11,45 @@ #include "base/trace_event/trace_event.h" #include "cc/base/cc_export.h" #include "cc/base/scoped_ptr_vector.h" +#include "cc/base/sidecar_list_container.h" #include "cc/playback/display_item.h" #include "cc/playback/pixel_ref_map.h" -// TODO(danakj): Move ListContainer out of cc/quads/ -#include "cc/quads/list_container.h" #include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkPicture.h" #include "ui/gfx/geometry/rect.h" class SkCanvas; -class SkDrawPictureCallback; class SkPictureRecorder; namespace cc { +class DisplayItemListSettings; + class CC_EXPORT DisplayItemList : public base::RefCountedThreadSafe<DisplayItemList> { public: + static scoped_refptr<DisplayItemList> CreateWithoutCachedPicture( + const DisplayItemListSettings& settings); + + // Creates a display item list with the given cull rect (if picture caching + // is used). The resulting display list will not support sidecar data. static scoped_refptr<DisplayItemList> Create(gfx::Rect layer_rect, bool use_cached_picture); + static scoped_refptr<DisplayItemList> Create( + gfx::Rect layer_rect, + const DisplayItemListSettings& settings); + void Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback, + SkPicture::AbortCallback* callback, + const gfx::Rect& canvas_target_playback_rect, float contents_scale) const; + // This is a fast path for use only if canvas_ is set and + // retain_individual_display_items_ is false. This method also updates + // is_suitable_for_gpu_rasterization_ and approximate_op_count_. + void RasterIntoCanvas(const DisplayItem& display_item); + template <typename DisplayItemType> DisplayItemType* CreateAndAppendItem() { #if DCHECK_IS_ON() @@ -44,29 +59,43 @@ class CC_EXPORT DisplayItemList return items_.AllocateAndConstruct<DisplayItemType>(); } - void ProcessAppendedItems(); - void CreateAndCacheSkPicture(); + // Removes the last item. This cannot be called on lists with cached pictures + // (since the data may already have been incorporated into cached picture + // sizes, etc). + void RemoveLast(); + + // Called after all items are appended, to process the items and, if + // applicable, create an internally cached SkPicture. + void Finalize(); bool IsSuitableForGpuRasterization() const; int ApproximateOpCount() const; - size_t PictureMemoryUsage() const; + size_t ApproximateMemoryUsage() const; - scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const; + bool RetainsIndividualDisplayItems() const; + + scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue( + bool include_items) const; void EmitTraceSnapshot() const; void GatherPixelRefs(const gfx::Size& grid_cell_size); + // Finds the sidecar for a display item in this list. + void* GetSidecar(DisplayItem* display_item); + private: DisplayItemList(gfx::Rect layer_rect, - bool use_cached_picture, + const DisplayItemListSettings& display_list_settings, bool retain_individual_display_items); - DisplayItemList(gfx::Rect layer_rect, bool use_cached_picture); + DisplayItemList(gfx::Rect layer_rect, + const DisplayItemListSettings& display_list_settings); ~DisplayItemList(); // While appending new items, if they are not being retained, this can process // periodically to avoid retaining all the items and processing at the end. void ProcessAppendedItemsOnTheFly(); + void ProcessAppendedItems(); #if DCHECK_IS_ON() bool ProcessAppendedItemsCalled() const { return !needs_process_; } bool needs_process_; @@ -74,7 +103,7 @@ class CC_EXPORT DisplayItemList bool ProcessAppendedItemsCalled() const { return true; } #endif - ListContainer<DisplayItem> items_; + SidecarListContainer<DisplayItem> items_; skia::RefPtr<SkPicture> picture_; scoped_ptr<SkPictureRecorder> recorder_; @@ -83,15 +112,20 @@ class CC_EXPORT DisplayItemList bool retain_individual_display_items_; gfx::Rect layer_rect_; - bool is_suitable_for_gpu_rasterization_; + bool all_items_are_suitable_for_gpu_rasterization_; int approximate_op_count_; + + // Memory usage due to the cached SkPicture. size_t picture_memory_usage_; + // Memory usage due to external data held by display items. + size_t external_memory_usage_; + scoped_ptr<PixelRefMap> pixel_refs_; friend class base::RefCountedThreadSafe<DisplayItemList>; friend class PixelRefMap::Iterator; - FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, PictureMemoryUsage); + FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, ApproximateMemoryUsage); DISALLOW_COPY_AND_ASSIGN(DisplayItemList); }; diff --git a/chromium/cc/playback/display_item_list_settings.cc b/chromium/cc/playback/display_item_list_settings.cc new file mode 100644 index 00000000000..e471d7e54ca --- /dev/null +++ b/chromium/cc/playback/display_item_list_settings.cc @@ -0,0 +1,18 @@ +// Copyright 2015 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/playback/display_item_list_settings.h" + +namespace cc { + +DisplayItemListSettings::DisplayItemListSettings() + : use_cached_picture(false), + max_sidecar_size(0), + sidecar_destroyer([](void* sidecar) {}) { +} + +DisplayItemListSettings::~DisplayItemListSettings() { +} + +} // namespace cc diff --git a/chromium/cc/playback/display_item_list_settings.h b/chromium/cc/playback/display_item_list_settings.h new file mode 100644 index 00000000000..277a2ea8da9 --- /dev/null +++ b/chromium/cc/playback/display_item_list_settings.h @@ -0,0 +1,29 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PLAYBACK_DISPLAY_ITEM_LIST_SETTINGS_H_ +#define CC_PLAYBACK_DISPLAY_ITEM_LIST_SETTINGS_H_ + +#include <cstddef> + +#include "cc/base/cc_export.h" + +namespace cc { + +class CC_EXPORT DisplayItemListSettings { + public: + DisplayItemListSettings(); + ~DisplayItemListSettings(); + + // If set, a picture will be cached inside the DisplayItemList. + bool use_cached_picture; + + // Settings that control sidecar data. + size_t max_sidecar_size; + void (*sidecar_destroyer)(void* sidecar); +}; + +} // namespace cc + +#endif // CC_PLAYBACK_DISPLAY_ITEM_LIST_SETTINGS_H_ diff --git a/chromium/cc/playback/display_item_list_unittest.cc b/chromium/cc/playback/display_item_list_unittest.cc index 6a5bbf61ae8..89d4970da8a 100644 --- a/chromium/cc/playback/display_item_list_unittest.cc +++ b/chromium/cc/playback/display_item_list_unittest.cc @@ -9,6 +9,7 @@ #include "cc/output/filter_operation.h" #include "cc/output/filter_operations.h" #include "cc/playback/clip_display_item.h" +#include "cc/playback/display_item_list_settings.h" #include "cc/playback/drawing_display_item.h" #include "cc/playback/filter_display_item.h" #include "cc/playback/transform_display_item.h" @@ -50,8 +51,7 @@ TEST(DisplayItemListTest, SingleDrawingItem) { picture = skia::AdoptRef(recorder.endRecordingAsPicture()); auto* item = list->CreateAndAppendItem<DrawingDisplayItem>(); item->SetNew(picture); - list->ProcessAppendedItems(); - list->CreateAndCacheSkPicture(); + list->Finalize(); DrawDisplayList(pixels, layer_rect, list); SkBitmap expected_bitmap; @@ -110,8 +110,7 @@ TEST(DisplayItemListTest, ClipItem) { item3->SetNew(picture.Pass()); list->CreateAndAppendItem<EndClipDisplayItem>(); - list->ProcessAppendedItems(); - list->CreateAndCacheSkPicture(); + list->Finalize(); DrawDisplayList(pixels, layer_rect, list); @@ -173,8 +172,7 @@ TEST(DisplayItemListTest, TransformItem) { item3->SetNew(picture); list->CreateAndAppendItem<EndTransformDisplayItem>(); - list->ProcessAppendedItems(); - list->CreateAndCacheSkPicture(); + list->Finalize(); DrawDisplayList(pixels, layer_rect, list); @@ -228,8 +226,7 @@ TEST(DisplayItemListTest, FilterItem) { auto* item = list->CreateAndAppendItem<FilterDisplayItem>(); item->SetNew(filters, filter_bounds); list->CreateAndAppendItem<EndFilterDisplayItem>(); - list->ProcessAppendedItems(); - list->CreateAndCacheSkPicture(); + list->Finalize(); DrawDisplayList(pixels, layer_rect, list); @@ -272,7 +269,7 @@ TEST(DisplayItemListTest, CompactingItems) { picture = skia::AdoptRef(recorder.endRecordingAsPicture()); auto* item1 = list_without_caching->CreateAndAppendItem<DrawingDisplayItem>(); item1->SetNew(picture); - list_without_caching->ProcessAppendedItems(); + list_without_caching->Finalize(); DrawDisplayList(pixels, layer_rect, list_without_caching); unsigned char expected_pixels[4 * 100 * 100] = {0}; @@ -281,14 +278,141 @@ TEST(DisplayItemListTest, CompactingItems) { DisplayItemList::Create(layer_rect, use_cached_picture); auto* item2 = list_with_caching->CreateAndAppendItem<DrawingDisplayItem>(); item2->SetNew(picture); - list_with_caching->ProcessAppendedItems(); - list_with_caching->CreateAndCacheSkPicture(); + list_with_caching->Finalize(); DrawDisplayList(expected_pixels, layer_rect, list_with_caching); EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); } -TEST(DisplayItemListTest, PictureMemoryUsage) { +TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithCachedPicture) { + gfx::Rect layer_rect(1000, 1000); + SkPictureRecorder recorder; + skia::RefPtr<SkCanvas> canvas; + skia::RefPtr<SkPicture> picture; + + bool use_cached_picture = true; + scoped_refptr<DisplayItemList> list = + DisplayItemList::Create(layer_rect, use_cached_picture); + canvas = + skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect))); + + SkPath path; + path.moveTo(0, 0); + path.lineTo(0, 100); + path.lineTo(50, 50); + path.lineTo(100, 100); + path.lineTo(100, 0); + path.close(); + + SkPaint paint; + paint.setAntiAlias(true); + canvas->drawPath(path, paint); + + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); + DrawingDisplayItem* item = list->CreateAndAppendItem<DrawingDisplayItem>(); + item->SetNew(picture); + list->Finalize(); + + // A single DrawingDisplayItem with a large AA concave path shouldn't trigger + // a veto. + EXPECT_TRUE(list->IsSuitableForGpuRasterization()); + + list = DisplayItemList::Create(layer_rect, use_cached_picture); + canvas = + skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect))); + for (int i = 0; i < 10; ++i) + canvas->drawPath(path, paint); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); + item = list->CreateAndAppendItem<DrawingDisplayItem>(); + item->SetNew(picture); + list->Finalize(); + + // A single DrawingDisplayItem with several large AA concave paths should + // trigger a veto. + EXPECT_FALSE(list->IsSuitableForGpuRasterization()); + + list = DisplayItemList::Create(layer_rect, use_cached_picture); + for (int i = 0; i < 10; ++i) { + canvas = + skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect))); + canvas->drawPath(path, paint); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); + item = list->CreateAndAppendItem<DrawingDisplayItem>(); + item->SetNew(picture); + } + list->Finalize(); + + // Having several DrawingDisplayItems that each contain a large AA concave + // path should trigger a veto. + EXPECT_FALSE(list->IsSuitableForGpuRasterization()); +} + +TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithoutCachedPicture) { + gfx::Rect layer_rect(1000, 1000); + SkPictureRecorder recorder; + skia::RefPtr<SkCanvas> canvas; + skia::RefPtr<SkPicture> picture; + + bool use_cached_picture = false; + scoped_refptr<DisplayItemList> list = + DisplayItemList::Create(layer_rect, use_cached_picture); + canvas = + skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect))); + + SkPath path; + path.moveTo(0, 0); + path.lineTo(0, 100); + path.lineTo(50, 50); + path.lineTo(100, 100); + path.lineTo(100, 0); + path.close(); + + SkPaint paint; + paint.setAntiAlias(true); + canvas->drawPath(path, paint); + + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); + DrawingDisplayItem* item = list->CreateAndAppendItem<DrawingDisplayItem>(); + item->SetNew(picture); + list->Finalize(); + + // A single DrawingDisplayItem with a large AA concave path shouldn't trigger + // a veto. + EXPECT_TRUE(list->IsSuitableForGpuRasterization()); + + list = DisplayItemList::Create(layer_rect, use_cached_picture); + canvas = + skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect))); + for (int i = 0; i < 10; ++i) + canvas->drawPath(path, paint); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); + item = list->CreateAndAppendItem<DrawingDisplayItem>(); + item->SetNew(picture); + list->Finalize(); + + // A single DrawingDisplayItem with several large AA concave paths should + // trigger a veto. + EXPECT_FALSE(list->IsSuitableForGpuRasterization()); + + list = DisplayItemList::Create(layer_rect, use_cached_picture); + for (int i = 0; i < 10; ++i) { + canvas = + skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect))); + canvas->drawPath(path, paint); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); + item = list->CreateAndAppendItem<DrawingDisplayItem>(); + item->SetNew(picture); + } + list->Finalize(); + + // Without a cached picture, having several DrawingDisplayItems that each + // contain a single large AA concave will not trigger a veto, since each item + // is individually suitable for GPU rasterization. + EXPECT_TRUE(list->IsSuitableForGpuRasterization()); +} + +TEST(DisplayItemListTest, ApproximateMemoryUsage) { + const int kNumCommandsInTestSkPicture = 1000; scoped_refptr<DisplayItemList> list; size_t memory_usage; @@ -298,21 +422,19 @@ TEST(DisplayItemListTest, PictureMemoryUsage) { SkPaint blue_paint; blue_paint.setColor(SK_ColorBLUE); SkCanvas* canvas = recorder.beginRecording(gfx::RectFToSkRect(layer_rect)); - for (int i = 0; i < 100; i++) + for (int i = 0; i < kNumCommandsInTestSkPicture; i++) canvas->drawPaint(blue_paint); skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecordingAsPicture()); size_t picture_size = SkPictureUtils::ApproximateBytesUsed(picture.get()); - ASSERT_GE(picture_size, 100 * sizeof(SkPaint)); - ASSERT_LE(picture_size, 200 * sizeof(SkPaint)); + ASSERT_GE(picture_size, kNumCommandsInTestSkPicture * sizeof(blue_paint)); // Using a cached picture, we should get about the right size. list = DisplayItemList::Create(layer_rect, true); auto* item = list->CreateAndAppendItem<DrawingDisplayItem>(); item->SetNew(picture); - list->ProcessAppendedItems(); - list->CreateAndCacheSkPicture(); - memory_usage = list->PictureMemoryUsage(); + list->Finalize(); + memory_usage = list->ApproximateMemoryUsage(); EXPECT_GE(memory_usage, picture_size); EXPECT_LE(memory_usage, 2 * picture_size); @@ -320,20 +442,21 @@ TEST(DisplayItemListTest, PictureMemoryUsage) { list = DisplayItemList::Create(layer_rect, false); item = list->CreateAndAppendItem<DrawingDisplayItem>(); item->SetNew(picture); - list->ProcessAppendedItems(); - memory_usage = list->PictureMemoryUsage(); + list->Finalize(); + memory_usage = list->ApproximateMemoryUsage(); EXPECT_GE(memory_usage, picture_size); EXPECT_LE(memory_usage, 2 * picture_size); // To avoid double counting, we expect zero size to be computed if both the // picture and items are retained (currently this only happens due to certain // categories being traced). - list = new DisplayItemList(layer_rect, true, true); + DisplayItemListSettings settings; + settings.use_cached_picture = true; + list = new DisplayItemList(layer_rect, settings, true); item = list->CreateAndAppendItem<DrawingDisplayItem>(); item->SetNew(picture); - list->ProcessAppendedItems(); - list->CreateAndCacheSkPicture(); - memory_usage = list->PictureMemoryUsage(); + list->Finalize(); + memory_usage = list->ApproximateMemoryUsage(); EXPECT_EQ(static_cast<size_t>(0), memory_usage); } diff --git a/chromium/cc/playback/display_list_raster_source.cc b/chromium/cc/playback/display_list_raster_source.cc index 0dcd025f3c9..4911e846029 100644 --- a/chromium/cc/playback/display_list_raster_source.cc +++ b/chromium/cc/playback/display_list_raster_source.cc @@ -14,16 +14,6 @@ #include "third_party/skia/include/core/SkPictureRecorder.h" #include "ui/gfx/geometry/rect_conversions.h" -namespace { - -#ifdef NDEBUG -const bool kDefaultClearCanvasSetting = false; -#else -const bool kDefaultClearCanvasSetting = true; -#endif - -} // namespace - namespace cc { scoped_refptr<DisplayListRasterSource> @@ -40,7 +30,7 @@ DisplayListRasterSource::DisplayListRasterSource() can_use_lcd_text_(true), is_solid_color_(false), solid_color_(SK_ColorTRANSPARENT), - clear_canvas_with_debug_color_(kDefaultClearCanvasSetting), + clear_canvas_with_debug_color_(false), slow_down_raster_scale_factor_for_debug_(0), should_attempt_to_use_distance_field_text_(false) { } @@ -56,7 +46,7 @@ DisplayListRasterSource::DisplayListRasterSource( solid_color_(other->solid_color_), recorded_viewport_(other->recorded_viewport_), size_(other->size_), - clear_canvas_with_debug_color_(kDefaultClearCanvasSetting), + clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_), slow_down_raster_scale_factor_for_debug_( other->slow_down_raster_scale_factor_for_debug_), should_attempt_to_use_distance_field_text_(false) { @@ -73,7 +63,7 @@ DisplayListRasterSource::DisplayListRasterSource( solid_color_(other->solid_color_), recorded_viewport_(other->recorded_viewport_), size_(other->size_), - clear_canvas_with_debug_color_(kDefaultClearCanvasSetting), + clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_), slow_down_raster_scale_factor_for_debug_( other->slow_down_raster_scale_factor_for_debug_), should_attempt_to_use_distance_field_text_( @@ -87,38 +77,47 @@ void DisplayListRasterSource::PlaybackToSharedCanvas( SkCanvas* canvas, const gfx::Rect& canvas_rect, float contents_scale) const { - RasterCommon(canvas, NULL, canvas_rect, contents_scale); + RasterCommon(canvas, NULL, canvas_rect, canvas_rect, contents_scale); } void DisplayListRasterSource::RasterForAnalysis(skia::AnalysisCanvas* canvas, const gfx::Rect& canvas_rect, float contents_scale) const { - RasterCommon(canvas, canvas, canvas_rect, contents_scale); + RasterCommon(canvas, canvas, canvas_rect, canvas_rect, contents_scale); } -void DisplayListRasterSource::PlaybackToCanvas(SkCanvas* canvas, - const gfx::Rect& canvas_rect, - float contents_scale) const { +void DisplayListRasterSource::PlaybackToCanvas( + SkCanvas* canvas, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, + float contents_scale) const { RasterSourceHelper::PrepareForPlaybackToCanvas( - canvas, canvas_rect, gfx::Rect(size_), contents_scale, background_color_, - clear_canvas_with_debug_color_, requires_clear_); + canvas, canvas_bitmap_rect, canvas_playback_rect, gfx::Rect(size_), + contents_scale, background_color_, clear_canvas_with_debug_color_, + requires_clear_); - RasterCommon(canvas, NULL, canvas_rect, contents_scale); + RasterCommon(canvas, NULL, canvas_bitmap_rect, canvas_playback_rect, + contents_scale); } -void DisplayListRasterSource::RasterCommon(SkCanvas* canvas, - SkDrawPictureCallback* callback, - const gfx::Rect& canvas_rect, - float contents_scale) const { - canvas->translate(-canvas_rect.x(), -canvas_rect.y()); +void DisplayListRasterSource::RasterCommon( + SkCanvas* canvas, + SkPicture::AbortCallback* callback, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, + float contents_scale) const { + canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y()); gfx::Rect content_rect = gfx::ToEnclosingRect(gfx::ScaleRect(gfx::Rect(size_), contents_scale)); - content_rect.Intersect(canvas_rect); + content_rect.Intersect(canvas_playback_rect); canvas->clipRect(gfx::RectToSkRect(content_rect), SkRegion::kIntersect_Op); DCHECK(display_list_.get()); - display_list_->Raster(canvas, callback, contents_scale); + gfx::Rect canvas_target_playback_rect = + canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin(); + display_list_->Raster(canvas, callback, canvas_target_playback_rect, + contents_scale); } skia::RefPtr<SkPicture> DisplayListRasterSource::GetFlattenedPicture() { @@ -129,7 +128,7 @@ skia::RefPtr<SkPicture> DisplayListRasterSource::GetFlattenedPicture() { SkCanvas* canvas = recorder.beginRecording(display_list_rect.width(), display_list_rect.height()); if (!display_list_rect.IsEmpty()) - PlaybackToCanvas(canvas, display_list_rect, 1.0); + PlaybackToCanvas(canvas, display_list_rect, display_list_rect, 1.0); skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecordingAsPicture()); @@ -139,7 +138,7 @@ skia::RefPtr<SkPicture> DisplayListRasterSource::GetFlattenedPicture() { size_t DisplayListRasterSource::GetPictureMemoryUsage() const { if (!display_list_) return 0; - return display_list_->PictureMemoryUsage(); + return display_list_->ApproximateMemoryUsage(); } void DisplayListRasterSource::PerformSolidColorAnalysis( diff --git a/chromium/cc/playback/display_list_raster_source.h b/chromium/cc/playback/display_list_raster_source.h index e9010e59261..24faa33c7fc 100644 --- a/chromium/cc/playback/display_list_raster_source.h +++ b/chromium/cc/playback/display_list_raster_source.h @@ -27,7 +27,8 @@ class CC_EXPORT DisplayListRasterSource : public RasterSource { // RasterSource overrides. void PlaybackToCanvas(SkCanvas* canvas, - const gfx::Rect& canvas_rect, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, float contents_scale) const override; void PlaybackToSharedCanvas(SkCanvas* canvas, const gfx::Rect& canvas_rect, @@ -80,14 +81,15 @@ class CC_EXPORT DisplayListRasterSource : public RasterSource { private: // Called when analyzing a tile. We can use AnalysisCanvas as - // SkDrawPictureCallback, which allows us to early out from analysis. + // SkPicture::AbortCallback, which allows us to early out from analysis. void RasterForAnalysis(skia::AnalysisCanvas* canvas, const gfx::Rect& canvas_rect, float contents_scale) const; void RasterCommon(SkCanvas* canvas, - SkDrawPictureCallback* callback, - const gfx::Rect& canvas_rect, + SkPicture::AbortCallback* callback, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, float contents_scale) const; DISALLOW_COPY_AND_ASSIGN(DisplayListRasterSource); diff --git a/chromium/cc/playback/display_list_raster_source_unittest.cc b/chromium/cc/playback/display_list_raster_source_unittest.cc new file mode 100644 index 00000000000..d936af51f9c --- /dev/null +++ b/chromium/cc/playback/display_list_raster_source_unittest.cc @@ -0,0 +1,556 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_ptr.h" +#include "cc/playback/display_list_raster_source.h" +#include "cc/test/fake_display_list_recording_source.h" +#include "cc/test/skia_common.h" +#include "skia/ext/refptr.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkPixelRef.h" +#include "third_party/skia/include/core/SkShader.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size_conversions.h" + +namespace cc { +namespace { + +TEST(DisplayListRasterSourceTest, AnalyzeIsSolidUnscaled) { + gfx::Size layer_bounds(400, 400); + + scoped_ptr<FakeDisplayListRecordingSource> recording_source = + FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds); + + SkPaint solid_paint; + SkColor solid_color = SkColorSetARGB(255, 12, 23, 34); + solid_paint.setColor(solid_color); + + SkColor non_solid_color = SkColorSetARGB(128, 45, 56, 67); + SkPaint non_solid_paint; + non_solid_paint.setColor(non_solid_color); + + recording_source->add_draw_rect_with_paint(gfx::Rect(layer_bounds), + solid_paint); + recording_source->Rerecord(); + + scoped_refptr<DisplayListRasterSource> raster = + DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + + // Ensure everything is solid. + for (int y = 0; y <= 300; y += 100) { + for (int x = 0; x <= 300; x += 100) { + RasterSource::SolidColorAnalysis analysis; + gfx::Rect rect(x, y, 100, 100); + raster->PerformSolidColorAnalysis(rect, 1.0, &analysis); + EXPECT_TRUE(analysis.is_solid_color) << rect.ToString(); + EXPECT_EQ(solid_color, analysis.solid_color) << rect.ToString(); + } + } + + // Add one non-solid pixel and recreate the raster source. + recording_source->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1), + non_solid_paint); + recording_source->Rerecord(); + raster = DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + + RasterSource::SolidColorAnalysis analysis; + raster->PerformSolidColorAnalysis(gfx::Rect(0, 0, 100, 100), 1.0, &analysis); + EXPECT_FALSE(analysis.is_solid_color); + + raster->PerformSolidColorAnalysis(gfx::Rect(100, 0, 100, 100), 1.0, + &analysis); + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(solid_color, analysis.solid_color); + + // Boundaries should be clipped. + analysis.is_solid_color = false; + raster->PerformSolidColorAnalysis(gfx::Rect(350, 0, 100, 100), 1.0, + &analysis); + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(solid_color, analysis.solid_color); + + analysis.is_solid_color = false; + raster->PerformSolidColorAnalysis(gfx::Rect(0, 350, 100, 100), 1.0, + &analysis); + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(solid_color, analysis.solid_color); + + analysis.is_solid_color = false; + raster->PerformSolidColorAnalysis(gfx::Rect(350, 350, 100, 100), 1.0, + &analysis); + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(solid_color, analysis.solid_color); +} + +TEST(DisplayListRasterSourceTest, AnalyzeIsSolidScaled) { + gfx::Size layer_bounds(400, 400); + + scoped_ptr<FakeDisplayListRecordingSource> recording_source = + FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds); + + SkColor solid_color = SkColorSetARGB(255, 12, 23, 34); + SkPaint solid_paint; + solid_paint.setColor(solid_color); + + SkColor non_solid_color = SkColorSetARGB(128, 45, 56, 67); + SkPaint non_solid_paint; + non_solid_paint.setColor(non_solid_color); + + recording_source->add_draw_rect_with_paint(gfx::Rect(0, 0, 400, 400), + solid_paint); + recording_source->Rerecord(); + + scoped_refptr<DisplayListRasterSource> raster = + DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + + // Ensure everything is solid. + for (int y = 0; y <= 30; y += 10) { + for (int x = 0; x <= 30; x += 10) { + RasterSource::SolidColorAnalysis analysis; + gfx::Rect rect(x, y, 10, 10); + raster->PerformSolidColorAnalysis(rect, 0.1f, &analysis); + EXPECT_TRUE(analysis.is_solid_color) << rect.ToString(); + EXPECT_EQ(analysis.solid_color, solid_color) << rect.ToString(); + } + } + + // Add one non-solid pixel and recreate the raster source. + recording_source->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1), + non_solid_paint); + recording_source->Rerecord(); + raster = DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + + RasterSource::SolidColorAnalysis analysis; + raster->PerformSolidColorAnalysis(gfx::Rect(0, 0, 10, 10), 0.1f, &analysis); + EXPECT_FALSE(analysis.is_solid_color); + + raster->PerformSolidColorAnalysis(gfx::Rect(10, 0, 10, 10), 0.1f, &analysis); + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(analysis.solid_color, solid_color); + + // Boundaries should be clipped. + analysis.is_solid_color = false; + raster->PerformSolidColorAnalysis(gfx::Rect(35, 0, 10, 10), 0.1f, &analysis); + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(analysis.solid_color, solid_color); + + analysis.is_solid_color = false; + raster->PerformSolidColorAnalysis(gfx::Rect(0, 35, 10, 10), 0.1f, &analysis); + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(analysis.solid_color, solid_color); + + analysis.is_solid_color = false; + raster->PerformSolidColorAnalysis(gfx::Rect(35, 35, 10, 10), 0.1f, &analysis); + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(analysis.solid_color, solid_color); +} + +TEST(DisplayListRasterSourceTest, AnalyzeIsSolidEmpty) { + gfx::Size layer_bounds(400, 400); + + scoped_ptr<FakeDisplayListRecordingSource> recording_source = + FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds); + recording_source->Rerecord(); + + scoped_refptr<DisplayListRasterSource> raster = + DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + RasterSource::SolidColorAnalysis analysis; + EXPECT_FALSE(analysis.is_solid_color); + + raster->PerformSolidColorAnalysis(gfx::Rect(0, 0, 400, 400), 1.f, &analysis); + + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(analysis.solid_color, SkColorSetARGB(0, 0, 0, 0)); +} + +TEST(DisplayListRasterSourceTest, PixelRefIteratorDiscardableRefsOneTile) { + gfx::Size layer_bounds(512, 512); + + scoped_ptr<FakeDisplayListRecordingSource> recording_source = + FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds); + + SkBitmap discardable_bitmap[2][2]; + CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][0]); + CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][1]); + CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[1][1]); + + // Discardable pixel refs are found in the following cells: + // |---|---| + // | x | x | + // |---|---| + // | | x | + // |---|---| + recording_source->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0)); + recording_source->add_draw_bitmap(discardable_bitmap[0][1], + gfx::Point(260, 0)); + recording_source->add_draw_bitmap(discardable_bitmap[1][1], + gfx::Point(260, 260)); + recording_source->SetGatherPixelRefs(true); + recording_source->Rerecord(); + + scoped_refptr<DisplayListRasterSource> raster = + DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + + // Tile sized iterators. These should find only one pixel ref. + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 1.0, &pixel_refs); + EXPECT_EQ(1u, pixel_refs.size()); + EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]); + } + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 2.0, &pixel_refs); + EXPECT_EQ(1u, pixel_refs.size()); + EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]); + } + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 0.5, &pixel_refs); + EXPECT_EQ(1u, pixel_refs.size()); + EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]); + } + // Shifted tile sized iterators. These should find only one pixel ref. + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(260, 260, 256, 256), 1.0, &pixel_refs); + EXPECT_EQ(1u, pixel_refs.size()); + EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[0]); + } + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(520, 520, 512, 512), 2.0, &pixel_refs); + EXPECT_EQ(1u, pixel_refs.size()); + EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[0]); + } + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(130, 130, 128, 128), 0.5, &pixel_refs); + EXPECT_EQ(1u, pixel_refs.size()); + EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[0]); + } + // Ensure there's no discardable pixel refs in the empty cell + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(0, 256, 256, 256), 1.0, &pixel_refs); + EXPECT_EQ(0u, pixel_refs.size()); + } + // Layer sized iterators. These should find three pixel ref. + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 1.0, &pixel_refs); + EXPECT_EQ(3u, pixel_refs.size()); + EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]); + EXPECT_EQ(discardable_bitmap[0][1].pixelRef(), pixel_refs[1]); + EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[2]); + } + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(0, 0, 1024, 1024), 2.0, &pixel_refs); + EXPECT_EQ(3u, pixel_refs.size()); + EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]); + EXPECT_EQ(discardable_bitmap[0][1].pixelRef(), pixel_refs[1]); + EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[2]); + } + { + std::vector<SkPixelRef*> pixel_refs; + raster->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 0.5, &pixel_refs); + EXPECT_EQ(3u, pixel_refs.size()); + EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]); + EXPECT_EQ(discardable_bitmap[0][1].pixelRef(), pixel_refs[1]); + EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[2]); + } +} + +TEST(DisplayListRasterSourceTest, RasterFullContents) { + gfx::Size layer_bounds(3, 5); + float contents_scale = 1.5f; + float raster_divisions = 2.f; + + scoped_ptr<FakeDisplayListRecordingSource> recording_source = + FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds); + recording_source->SetBackgroundColor(SK_ColorBLACK); + recording_source->SetClearCanvasWithDebugColor(false); + + // Because the caller sets content opaque, it also promises that it + // has at least filled in layer_bounds opaquely. + SkPaint white_paint; + white_paint.setColor(SK_ColorWHITE); + recording_source->add_draw_rect_with_paint(gfx::Rect(layer_bounds), + white_paint); + recording_source->Rerecord(); + + scoped_refptr<DisplayListRasterSource> raster = + DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + + gfx::Size content_bounds( + gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale))); + + // Simulate drawing into different tiles at different offsets. + int step_x = std::ceil(content_bounds.width() / raster_divisions); + int step_y = std::ceil(content_bounds.height() / raster_divisions); + for (int offset_x = 0; offset_x < content_bounds.width(); + offset_x += step_x) { + for (int offset_y = 0; offset_y < content_bounds.height(); + offset_y += step_y) { + gfx::Rect content_rect(offset_x, offset_y, step_x, step_y); + content_rect.Intersect(gfx::Rect(content_bounds)); + + // Simulate a canvas rect larger than the content rect. Every pixel + // up to one pixel outside the content rect is guaranteed to be opaque. + // Outside of that is undefined. + gfx::Rect canvas_rect(content_rect); + canvas_rect.Inset(0, 0, -1, -1); + + SkBitmap bitmap; + bitmap.allocN32Pixels(canvas_rect.width(), canvas_rect.height()); + SkCanvas canvas(bitmap); + canvas.clear(SK_ColorTRANSPARENT); + + raster->PlaybackToCanvas(&canvas, canvas_rect, canvas_rect, + contents_scale); + + SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); + int num_pixels = bitmap.width() * bitmap.height(); + bool all_white = true; + for (int i = 0; i < num_pixels; ++i) { + EXPECT_EQ(SkColorGetA(pixels[i]), 255u); + all_white &= (SkColorGetR(pixels[i]) == 255); + all_white &= (SkColorGetG(pixels[i]) == 255); + all_white &= (SkColorGetB(pixels[i]) == 255); + } + + // If the canvas doesn't extend past the edge of the content, + // it should be entirely white. Otherwise, the edge of the content + // will be non-white. + EXPECT_EQ(all_white, gfx::Rect(content_bounds).Contains(canvas_rect)); + } + } +} + +TEST(DisplayListRasterSourceTest, RasterPartialContents) { + gfx::Size layer_bounds(3, 5); + float contents_scale = 1.5f; + + scoped_ptr<FakeDisplayListRecordingSource> recording_source = + FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds); + recording_source->SetBackgroundColor(SK_ColorGREEN); + recording_source->SetClearCanvasWithDebugColor(false); + + // First record everything as white. + SkPaint white_paint; + white_paint.setColor(SK_ColorWHITE); + recording_source->add_draw_rect_with_paint(gfx::Rect(layer_bounds), + white_paint); + recording_source->Rerecord(); + + scoped_refptr<DisplayListRasterSource> raster = + DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + + gfx::Size content_bounds( + gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale))); + + SkBitmap bitmap; + bitmap.allocN32Pixels(content_bounds.width(), content_bounds.height()); + SkCanvas canvas(bitmap); + canvas.clear(SK_ColorTRANSPARENT); + + // Playback the full rect which should make everything white. + gfx::Rect raster_full_rect(content_bounds); + gfx::Rect playback_rect(content_bounds); + raster->PlaybackToCanvas(&canvas, raster_full_rect, playback_rect, + contents_scale); + + { + SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); + for (int i = 0; i < bitmap.width(); ++i) { + for (int j = 0; j < bitmap.height(); ++j) { + SCOPED_TRACE(i); + SCOPED_TRACE(j); + EXPECT_EQ(255u, SkColorGetA(pixels[i + j * bitmap.width()])); + EXPECT_EQ(255u, SkColorGetR(pixels[i + j * bitmap.width()])); + EXPECT_EQ(255u, SkColorGetG(pixels[i + j * bitmap.width()])); + EXPECT_EQ(255u, SkColorGetB(pixels[i + j * bitmap.width()])); + } + } + } + + // Re-record everything as black. + SkPaint black_paint; + black_paint.setColor(SK_ColorBLACK); + recording_source->add_draw_rect_with_paint(gfx::Rect(layer_bounds), + black_paint); + recording_source->Rerecord(); + + // Make a new RasterSource from the new recording. + raster = DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + + // We're going to playback from "everything is black" into a smaller area, + // that touches the edge pixels of the recording. + playback_rect.Inset(1, 2, 0, 1); + raster->PlaybackToCanvas(&canvas, raster_full_rect, playback_rect, + contents_scale); + + SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); + int num_black = 0; + int num_white = 0; + for (int i = 0; i < bitmap.width(); ++i) { + for (int j = 0; j < bitmap.height(); ++j) { + SCOPED_TRACE(j); + SCOPED_TRACE(i); + bool expect_black = playback_rect.Contains(i, j); + if (expect_black) { + EXPECT_EQ(255u, SkColorGetA(pixels[i + j * bitmap.width()])); + EXPECT_EQ(0u, SkColorGetR(pixels[i + j * bitmap.width()])); + EXPECT_EQ(0u, SkColorGetG(pixels[i + j * bitmap.width()])); + EXPECT_EQ(0u, SkColorGetB(pixels[i + j * bitmap.width()])); + ++num_black; + } else { + EXPECT_EQ(255u, SkColorGetA(pixels[i + j * bitmap.width()])); + EXPECT_EQ(255u, SkColorGetR(pixels[i + j * bitmap.width()])); + EXPECT_EQ(255u, SkColorGetG(pixels[i + j * bitmap.width()])); + EXPECT_EQ(255u, SkColorGetB(pixels[i + j * bitmap.width()])); + ++num_white; + } + } + } + EXPECT_GT(num_black, 0); + EXPECT_GT(num_white, 0); +} + +TEST(DisplayListRasterSourceTest, RasterPartialClear) { + gfx::Size layer_bounds(3, 5); + gfx::Size partial_bounds(2, 4); + float contents_scale = 1.5f; + + scoped_ptr<FakeDisplayListRecordingSource> recording_source = + FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds); + recording_source->SetBackgroundColor(SK_ColorGREEN); + recording_source->SetRequiresClear(true); + recording_source->SetClearCanvasWithDebugColor(false); + + // First record everything as white. + const unsigned alpha_dark = 10u; + SkPaint white_paint; + white_paint.setColor(SK_ColorWHITE); + white_paint.setAlpha(alpha_dark); + recording_source->add_draw_rect_with_paint(gfx::Rect(layer_bounds), + white_paint); + recording_source->Rerecord(); + + scoped_refptr<DisplayListRasterSource> raster = + DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + + gfx::Size content_bounds( + gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale))); + + SkBitmap bitmap; + bitmap.allocN32Pixels(content_bounds.width(), content_bounds.height()); + SkCanvas canvas(bitmap); + canvas.clear(SK_ColorTRANSPARENT); + + // Playback the full rect which should make everything light gray (alpha=10). + gfx::Rect raster_full_rect(content_bounds); + gfx::Rect playback_rect(content_bounds); + raster->PlaybackToCanvas(&canvas, raster_full_rect, playback_rect, + contents_scale); + + { + SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); + for (int i = 0; i < bitmap.width(); ++i) { + for (int j = 0; j < bitmap.height(); ++j) { + SCOPED_TRACE(i); + SCOPED_TRACE(j); + EXPECT_EQ(alpha_dark, SkColorGetA(pixels[i + j * bitmap.width()])); + EXPECT_EQ(alpha_dark, SkColorGetR(pixels[i + j * bitmap.width()])); + EXPECT_EQ(alpha_dark, SkColorGetG(pixels[i + j * bitmap.width()])); + EXPECT_EQ(alpha_dark, SkColorGetB(pixels[i + j * bitmap.width()])); + } + } + } + + scoped_ptr<FakeDisplayListRecordingSource> recording_source_light = + FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds); + recording_source_light->SetBackgroundColor(SK_ColorGREEN); + recording_source_light->SetRequiresClear(true); + recording_source_light->SetClearCanvasWithDebugColor(false); + + // Record everything as a slightly lighter white. + const unsigned alpha_light = 18u; + white_paint.setAlpha(alpha_light); + recording_source_light->add_draw_rect_with_paint(gfx::Rect(layer_bounds), + white_paint); + recording_source_light->Rerecord(); + + // Make a new RasterSource from the new recording. + raster = DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source_light.get(), false); + + // We're going to playback from alpha(18) white rectangle into a smaller area + // of the recording resulting in a smaller lighter white rectangle over a + // darker white background rectangle. + playback_rect = gfx::Rect( + gfx::ToCeiledSize(gfx::ScaleSize(partial_bounds, contents_scale))); + raster->PlaybackToCanvas(&canvas, raster_full_rect, playback_rect, + contents_scale); + + // Test that the whole playback_rect was cleared and repainted with new alpha. + SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); + for (int i = 0; i < playback_rect.width(); ++i) { + for (int j = 0; j < playback_rect.height(); ++j) { + SCOPED_TRACE(j); + SCOPED_TRACE(i); + EXPECT_EQ(alpha_light, SkColorGetA(pixels[i + j * bitmap.width()])); + EXPECT_EQ(alpha_light, SkColorGetR(pixels[i + j * bitmap.width()])); + EXPECT_EQ(alpha_light, SkColorGetG(pixels[i + j * bitmap.width()])); + EXPECT_EQ(alpha_light, SkColorGetB(pixels[i + j * bitmap.width()])); + } + } +} + +TEST(DisplayListRasterSourceTest, RasterContentsTransparent) { + gfx::Size layer_bounds(5, 3); + float contents_scale = 0.5f; + + scoped_ptr<FakeDisplayListRecordingSource> recording_source = + FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds); + recording_source->SetBackgroundColor(SK_ColorTRANSPARENT); + recording_source->SetRequiresClear(true); + recording_source->SetClearCanvasWithDebugColor(false); + recording_source->Rerecord(); + + scoped_refptr<DisplayListRasterSource> raster = + DisplayListRasterSource::CreateFromDisplayListRecordingSource( + recording_source.get(), false); + gfx::Size content_bounds( + gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale))); + + gfx::Rect canvas_rect(content_bounds); + canvas_rect.Inset(0, 0, -1, -1); + + SkBitmap bitmap; + bitmap.allocN32Pixels(canvas_rect.width(), canvas_rect.height()); + SkCanvas canvas(bitmap); + + raster->PlaybackToCanvas(&canvas, canvas_rect, canvas_rect, contents_scale); + + SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); + int num_pixels = bitmap.width() * bitmap.height(); + for (int i = 0; i < num_pixels; ++i) { + EXPECT_EQ(SkColorGetA(pixels[i]), 0u); + } +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/playback/display_list_recording_source.cc b/chromium/cc/playback/display_list_recording_source.cc index 9d6e31f26c7..e88343cb6b7 100644 --- a/chromium/cc/playback/display_list_recording_source.cc +++ b/chromium/cc/playback/display_list_recording_source.cc @@ -6,6 +6,7 @@ #include <algorithm> +#include "cc/base/histograms.h" #include "cc/base/region.h" #include "cc/layers/content_layer_client.h" #include "cc/playback/display_item_list.h" @@ -22,18 +23,34 @@ const int kPixelDistanceToRecord = 8000; // operations. const int kOpCountThatIsOkToAnalyze = 10; +// This is the distance, in layer space, by which the recorded viewport has to +// change before causing a paint of the new content. For example, it means +// that one has to scroll a very large page by 512 pixels before we will +// re-record a new DisplayItemList for an updated recorded viewport. +const int kMinimumDistanceBeforeUpdatingRecordedViewport = 512; + +#ifdef NDEBUG +const bool kDefaultClearCanvasSetting = false; +#else +const bool kDefaultClearCanvasSetting = true; +#endif + +DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER( + ScopedDisplayListRecordingSourceUpdateTimer, + "Compositing.DisplayListRecordingSource.UpdateUs", + "Compositing.DisplayListRecordingSource.UpdateInvalidatedAreaPerMs"); + } // namespace namespace cc { DisplayListRecordingSource::DisplayListRecordingSource( - const gfx::Size& grid_cell_size, - bool use_cached_picture) - : use_cached_picture_(use_cached_picture), - slow_down_raster_scale_factor_for_debug_(0), + const gfx::Size& grid_cell_size) + : slow_down_raster_scale_factor_for_debug_(0), gather_pixel_refs_(false), requires_clear_(false), is_solid_color_(false), + clear_canvas_with_debug_color_(kDefaultClearCanvasSetting), solid_color_(SK_ColorTRANSPARENT), background_color_(SK_ColorTRANSPARENT), pixel_record_distance_(kPixelDistanceToRecord), @@ -44,6 +61,54 @@ DisplayListRecordingSource::DisplayListRecordingSource( DisplayListRecordingSource::~DisplayListRecordingSource() { } +// This method only really makes sense to call if the size of the layer didn't +// change. +bool DisplayListRecordingSource::ExposesEnoughNewArea( + const gfx::Rect& current_recorded_viewport, + const gfx::Rect& potential_new_recorded_viewport, + const gfx::Size& layer_size) { + // If both are empty, nothing to do. + if (current_recorded_viewport.IsEmpty() && + potential_new_recorded_viewport.IsEmpty()) + return false; + + // Re-record when going from empty to not-empty, to cover cases where + // the layer is recorded for the first time, or otherwise becomes visible. + if (current_recorded_viewport.IsEmpty()) + return true; + + // Re-record if the new viewport includes area outside of a skirt around the + // existing viewport. + gfx::Rect expanded_viewport(current_recorded_viewport); + expanded_viewport.Inset(-kMinimumDistanceBeforeUpdatingRecordedViewport, + -kMinimumDistanceBeforeUpdatingRecordedViewport); + if (!expanded_viewport.Contains(potential_new_recorded_viewport)) + return true; + + // Even if the new viewport doesn't include enough new area to satisfy the + // condition above, re-record anyway if touches a layer edge not touched by + // the existing viewport. Viewports are clipped to layer boundaries, so if the + // new viewport touches a layer edge not touched by the existing viewport, + // the new viewport must expose new area that touches this layer edge. Since + // this new area touches a layer edge, it's impossible to expose more area in + // that direction, so recording cannot be deferred until the exposed new area + // satisfies the condition above. + if (potential_new_recorded_viewport.x() == 0 && + current_recorded_viewport.x() != 0) + return true; + if (potential_new_recorded_viewport.y() == 0 && + current_recorded_viewport.y() != 0) + return true; + if (potential_new_recorded_viewport.right() == layer_size.width() && + current_recorded_viewport.right() != layer_size.width()) + return true; + if (potential_new_recorded_viewport.bottom() == layer_size.height() && + current_recorded_viewport.bottom() != layer_size.height()) + return true; + + return false; +} + bool DisplayListRecordingSource::UpdateAndExpandInvalidation( ContentLayerClient* painter, Region* invalidation, @@ -51,6 +116,7 @@ bool DisplayListRecordingSource::UpdateAndExpandInvalidation( const gfx::Rect& visible_layer_rect, int frame_number, RecordingMode recording_mode) { + ScopedDisplayListRecordingSourceUpdateTimer timer; bool updated = false; if (size_ != layer_size) { @@ -58,12 +124,20 @@ bool DisplayListRecordingSource::UpdateAndExpandInvalidation( updated = true; } - gfx::Rect old_recorded_viewport = recorded_viewport_; - recorded_viewport_ = visible_layer_rect; - recorded_viewport_.Inset(-pixel_record_distance_, -pixel_record_distance_); - recorded_viewport_.Intersect(gfx::Rect(GetSize())); + // The recorded viewport is the visible layer rect, expanded + // by the pixel record distance, up to a maximum of the total + // layer size. + gfx::Rect potential_new_recorded_viewport = visible_layer_rect; + potential_new_recorded_viewport.Inset(-pixel_record_distance_, + -pixel_record_distance_); + potential_new_recorded_viewport.Intersect(gfx::Rect(GetSize())); + + if (updated || + ExposesEnoughNewArea(recorded_viewport_, potential_new_recorded_viewport, + GetSize())) { + gfx::Rect old_recorded_viewport = recorded_viewport_; + recorded_viewport_ = potential_new_recorded_viewport; - if (recorded_viewport_ != old_recorded_viewport) { // Invalidate newly-exposed and no-longer-exposed areas. Region newly_exposed_region(recorded_viewport_); newly_exposed_region.Subtract(old_recorded_viewport); @@ -76,6 +150,12 @@ bool DisplayListRecordingSource::UpdateAndExpandInvalidation( updated = true; } + // Count the area that is being invalidated. + Region recorded_invalidation(*invalidation); + recorded_invalidation.Intersect(recorded_viewport_); + for (Region::Iterator it(recorded_invalidation); it.has_rect(); it.next()) + timer.AddArea(it.rect().size().GetArea()); + if (!updated && !invalidation->Intersects(recorded_viewport_)) return false; @@ -105,15 +185,11 @@ bool DisplayListRecordingSource::UpdateAndExpandInvalidation( repeat_count = slow_down_raster_scale_factor_for_debug_; painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED; } + for (int i = 0; i < repeat_count; ++i) { - display_list_ = - DisplayItemList::Create(recorded_viewport_, use_cached_picture_); - painter->PaintContentsToDisplayList(display_list_.get(), recorded_viewport_, - painting_control); + display_list_ = painter->PaintContentsToDisplayList(recorded_viewport_, + painting_control); } - display_list_->ProcessAppendedItems(); - if (use_cached_picture_) - display_list_->CreateAndCacheSkPicture(); is_suitable_for_gpu_rasterization_ = display_list_->IsSuitableForGpuRasterization(); @@ -179,7 +255,7 @@ void DisplayListRecordingSource::DetermineIfSolidColor() { gfx::Size layer_size = GetSize(); skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height()); - display_list_->Raster(&canvas, nullptr, 1.f); + display_list_->Raster(&canvas, nullptr, gfx::Rect(), 1.f); is_solid_color_ = canvas.GetColorIfSolid(&solid_color_); } diff --git a/chromium/cc/playback/display_list_recording_source.h b/chromium/cc/playback/display_list_recording_source.h index 8d652fa67de..8d4e52f0cc3 100644 --- a/chromium/cc/playback/display_list_recording_source.h +++ b/chromium/cc/playback/display_list_recording_source.h @@ -14,8 +14,7 @@ class DisplayListRasterSource; class CC_EXPORT DisplayListRecordingSource : public RecordingSource { public: - DisplayListRecordingSource(const gfx::Size& grid_cell_size, - bool use_cached_picture); + explicit DisplayListRecordingSource(const gfx::Size& grid_cell_size); ~DisplayListRecordingSource() override; // RecordingSource overrides. @@ -36,18 +35,25 @@ class CC_EXPORT DisplayListRecordingSource : public RecordingSource { bool IsSuitableForGpuRasterization() const override; void SetUnsuitableForGpuRasterizationForTesting() override; gfx::Size GetTileGridSizeForTesting() const override; + // Returns true if the new recorded viewport exposes enough new area to be + // worth re-recording. + static bool ExposesEnoughNewArea( + const gfx::Rect& current_recorded_viewport, + const gfx::Rect& potential_new_recorded_viewport, + const gfx::Size& layer_size); + + gfx::Rect recorded_viewport() const { return recorded_viewport_; } protected: void Clear(); - const bool use_cached_picture_; - gfx::Rect recorded_viewport_; gfx::Size size_; int slow_down_raster_scale_factor_for_debug_; bool gather_pixel_refs_; bool requires_clear_; bool is_solid_color_; + bool clear_canvas_with_debug_color_; SkColor solid_color_; SkColor background_color_; int pixel_record_distance_; diff --git a/chromium/cc/playback/display_list_recording_source_unittest.cc b/chromium/cc/playback/display_list_recording_source_unittest.cc index 0d7ec7c74f1..0ddfb6fc5c8 100644 --- a/chromium/cc/playback/display_list_recording_source_unittest.cc +++ b/chromium/cc/playback/display_list_recording_source_unittest.cc @@ -4,7 +4,9 @@ #include <vector> +#include "cc/base/region.h" #include "cc/playback/display_list_raster_source.h" +#include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_display_list_recording_source.h" #include "cc/test/skia_common.h" #include "testing/gtest/include/gtest/gtest.h" @@ -12,12 +14,18 @@ namespace cc { namespace { -TEST(DisplayListRecordingSourceTest, DiscardablePixelRefsWithTransform) { +class DisplayListRecordingSourceTest : public testing::Test { + public: + void SetUp() override {} +}; + +TEST_F(DisplayListRecordingSourceTest, DiscardablePixelRefsWithTransform) { gfx::Size grid_cell_size(128, 128); - gfx::Rect recorded_viewport(0, 0, 256, 256); + gfx::Rect recorded_viewport(256, 256); scoped_ptr<FakeDisplayListRecordingSource> recording_source = - FakeDisplayListRecordingSource::CreateRecordingSource(recorded_viewport); + FakeDisplayListRecordingSource::CreateFilledRecordingSource( + recorded_viewport.size()); recording_source->SetGridCellSize(grid_cell_size); SkBitmap discardable_bitmap[2][2]; gfx::Transform identity_transform; @@ -161,5 +169,137 @@ TEST(DisplayListRecordingSourceTest, DiscardablePixelRefsWithTransform) { } } +TEST_F(DisplayListRecordingSourceTest, ExposesEnoughNewAreaEmpty) { + gfx::Size layer_size(1000, 1000); + + // Both empty means there is nothing to do. + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + gfx::Rect(), gfx::Rect(), layer_size)); + // Going from empty to non-empty means we must re-record because it could be + // the first frame after construction or Clear. + EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( + gfx::Rect(), gfx::Rect(1, 1), layer_size)); + + // Going from non-empty to empty is not special-cased. + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + gfx::Rect(1, 1), gfx::Rect(), layer_size)); +} + +TEST_F(DisplayListRecordingSourceTest, ExposesEnoughNewAreaNotBigEnough) { + gfx::Size layer_size(1000, 1000); + gfx::Rect current_recorded_viewport(100, 100, 100, 100); + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, gfx::Rect(100, 100, 90, 90), layer_size)); + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, gfx::Rect(100, 100, 100, 100), layer_size)); + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, gfx::Rect(1, 1, 200, 200), layer_size)); +} + +TEST_F(DisplayListRecordingSourceTest, + ExposesEnoughNewAreaNotBigEnoughButNewAreaTouchesEdge) { + gfx::Size layer_size(500, 500); + gfx::Rect current_recorded_viewport(100, 100, 100, 100); + + // Top edge. + EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, gfx::Rect(100, 0, 100, 200), layer_size)); + + // Left edge. + EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, gfx::Rect(0, 100, 200, 100), layer_size)); + + // Bottom edge. + EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, gfx::Rect(100, 100, 100, 400), layer_size)); + + // Right edge. + EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, gfx::Rect(100, 100, 400, 100), layer_size)); +} + +// Verifies that having a current viewport that touches a layer edge does not +// force re-recording. +TEST_F(DisplayListRecordingSourceTest, + ExposesEnoughNewAreaCurrentViewportTouchesEdge) { + gfx::Size layer_size(500, 500); + gfx::Rect potential_new_viewport(100, 100, 300, 300); + + // Top edge. + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + gfx::Rect(100, 0, 100, 100), potential_new_viewport, layer_size)); + + // Left edge. + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + gfx::Rect(0, 100, 100, 100), potential_new_viewport, layer_size)); + + // Bottom edge. + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + gfx::Rect(300, 400, 100, 100), potential_new_viewport, layer_size)); + + // Right edge. + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + gfx::Rect(400, 300, 100, 100), potential_new_viewport, layer_size)); +} + +TEST_F(DisplayListRecordingSourceTest, ExposesEnoughNewAreaScrollScenarios) { + gfx::Size layer_size(1000, 1000); + gfx::Rect current_recorded_viewport(100, 100, 100, 100); + + gfx::Rect new_recorded_viewport(current_recorded_viewport); + new_recorded_viewport.Offset(512, 0); + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, new_recorded_viewport, layer_size)); + new_recorded_viewport.Offset(0, 512); + EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, new_recorded_viewport, layer_size)); + + new_recorded_viewport.Offset(1, 0); + EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, new_recorded_viewport, layer_size)); + + new_recorded_viewport.Offset(-1, 1); + EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( + current_recorded_viewport, new_recorded_viewport, layer_size)); +} + +// Verifies that UpdateAndExpandInvalidation calls ExposesEnoughNewArea with the +// right arguments. +TEST_F(DisplayListRecordingSourceTest, + ExposesEnoughNewAreaCalledWithCorrectArguments) { + gfx::Size grid_cell_size(128, 128); + DisplayListRecordingSource recording_source(grid_cell_size); + FakeContentLayerClient client; + Region invalidation; + gfx::Size layer_size(9000, 9000); + gfx::Rect visible_rect(0, 0, 256, 256); + + recording_source.UpdateAndExpandInvalidation( + &client, &invalidation, layer_size, visible_rect, 0, + RecordingSource::RECORD_NORMALLY); + EXPECT_EQ(gfx::Rect(0, 0, 8256, 8256), recording_source.recorded_viewport()); + + visible_rect.Offset(0, 512); + recording_source.UpdateAndExpandInvalidation( + &client, &invalidation, layer_size, visible_rect, 0, + RecordingSource::RECORD_NORMALLY); + EXPECT_EQ(gfx::Rect(0, 0, 8256, 8256), recording_source.recorded_viewport()); + + // Move past the threshold for enough exposed new area. + visible_rect.Offset(0, 1); + recording_source.UpdateAndExpandInvalidation( + &client, &invalidation, layer_size, visible_rect, 0, + RecordingSource::RECORD_NORMALLY); + EXPECT_EQ(gfx::Rect(0, 0, 8256, 8769), recording_source.recorded_viewport()); + + // Make the bottom of the potential new recorded viewport coincide with the + // layer's bottom edge. + visible_rect.Offset(0, 231); + recording_source.UpdateAndExpandInvalidation( + &client, &invalidation, layer_size, visible_rect, 0, + RecordingSource::RECORD_NORMALLY); + EXPECT_EQ(gfx::Rect(0, 0, 8256, 9000), recording_source.recorded_viewport()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/playback/drawing_display_item.cc b/chromium/cc/playback/drawing_display_item.cc index 51cd42edf41..6cebed2ae00 100644 --- a/chromium/cc/playback/drawing_display_item.cc +++ b/chromium/cc/playback/drawing_display_item.cc @@ -10,10 +10,10 @@ #include "base/trace_event/trace_event_argument.h" #include "cc/debug/picture_debug_util.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkDrawPictureCallback.h" #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/utils/SkPictureUtils.h" +#include "ui/gfx/skia_util.h" namespace cc { @@ -31,7 +31,18 @@ void DrawingDisplayItem::SetNew(skia::RefPtr<SkPicture> picture) { } void DrawingDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { + // The canvas_playback_rect can be empty to signify no culling is desired. + if (!canvas_target_playback_rect.IsEmpty()) { + const SkMatrix& matrix = canvas->getTotalMatrix(); + const SkRect& cull_rect = picture_->cullRect(); + SkRect target_rect; + matrix.mapRect(&target_rect, cull_rect); + if (!target_rect.intersect(gfx::RectToSkRect(canvas_target_playback_rect))) + return; + } + // SkPicture always does a wrapping save/restore on the canvas, so it is not // necessary here. if (callback) diff --git a/chromium/cc/playback/drawing_display_item.h b/chromium/cc/playback/drawing_display_item.h index 81ddbce4f11..f94e7c9ca6e 100644 --- a/chromium/cc/playback/drawing_display_item.h +++ b/chromium/cc/playback/drawing_display_item.h @@ -12,7 +12,6 @@ #include "ui/gfx/geometry/point_f.h" class SkCanvas; -class SkDrawPictureCallback; class SkPicture; namespace cc { @@ -24,7 +23,9 @@ class CC_EXPORT DrawingDisplayItem : public DisplayItem { void SetNew(skia::RefPtr<SkPicture> picture); - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; void CloneTo(DrawingDisplayItem* item) const; diff --git a/chromium/cc/playback/filter_display_item.cc b/chromium/cc/playback/filter_display_item.cc index 8e849cf6009..fbed01509c8 100644 --- a/chromium/cc/playback/filter_display_item.cc +++ b/chromium/cc/playback/filter_display_item.cc @@ -27,14 +27,16 @@ void FilterDisplayItem::SetNew(const FilterOperations& filters, filters_ = filters; bounds_ = bounds; - size_t memory_usage = - sizeof(skia::RefPtr<SkImageFilter>) + sizeof(gfx::RectF); + // FilterOperations doesn't expose its capacity, but size is probably good + // enough. + size_t external_memory_usage = filters_.size() * sizeof(filters_.at(0)); DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 1 /* op_count */, - memory_usage); + external_memory_usage); } void FilterDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->save(); canvas->translate(bounds_.x(), bounds_.y()); @@ -61,14 +63,15 @@ void FilterDisplayItem::AsValueInto( EndFilterDisplayItem::EndFilterDisplayItem() { DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 0 /* op_count */, - 0 /* memory_usage */); + 0 /* external_memory_usage */); } EndFilterDisplayItem::~EndFilterDisplayItem() { } void EndFilterDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->restore(); canvas->restore(); } diff --git a/chromium/cc/playback/filter_display_item.h b/chromium/cc/playback/filter_display_item.h index a999b3883bf..9672878752a 100644 --- a/chromium/cc/playback/filter_display_item.h +++ b/chromium/cc/playback/filter_display_item.h @@ -12,7 +12,6 @@ #include "ui/gfx/geometry/rect_f.h" class SkCanvas; -class SkDrawPictureCallback; namespace cc { @@ -23,7 +22,9 @@ class CC_EXPORT FilterDisplayItem : public DisplayItem { void SetNew(const FilterOperations& filters, const gfx::RectF& bounds); - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; private: @@ -40,7 +41,9 @@ class CC_EXPORT EndFilterDisplayItem : public DisplayItem { return make_scoped_ptr(new EndFilterDisplayItem()); } - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; }; diff --git a/chromium/cc/playback/float_clip_display_item.cc b/chromium/cc/playback/float_clip_display_item.cc index 0f368a65770..8b29fc214c5 100644 --- a/chromium/cc/playback/float_clip_display_item.cc +++ b/chromium/cc/playback/float_clip_display_item.cc @@ -20,13 +20,13 @@ FloatClipDisplayItem::~FloatClipDisplayItem() { void FloatClipDisplayItem::SetNew(const gfx::RectF& clip_rect) { clip_rect_ = clip_rect; - size_t memory_usage = sizeof(gfx::RectF); DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 1 /* op_count */, - memory_usage); + 0 /* external_memory_usage */); } void FloatClipDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->save(); canvas->clipRect(gfx::RectFToSkRect(clip_rect_)); } @@ -39,14 +39,16 @@ void FloatClipDisplayItem::AsValueInto( EndFloatClipDisplayItem::EndFloatClipDisplayItem() { DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 0 /* op_count */, - 0 /* memory_usage */); + 0 /* external_memory_usage */); } EndFloatClipDisplayItem::~EndFloatClipDisplayItem() { } -void EndFloatClipDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { +void EndFloatClipDisplayItem::Raster( + SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->restore(); } diff --git a/chromium/cc/playback/float_clip_display_item.h b/chromium/cc/playback/float_clip_display_item.h index 2812189ff61..13d637f85a3 100644 --- a/chromium/cc/playback/float_clip_display_item.h +++ b/chromium/cc/playback/float_clip_display_item.h @@ -13,7 +13,6 @@ #include "ui/gfx/geometry/rect_f.h" class SkCanvas; -class SkDrawPictureCallback; namespace cc { @@ -24,7 +23,9 @@ class CC_EXPORT FloatClipDisplayItem : public DisplayItem { void SetNew(const gfx::RectF& clip_rect); - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; private: @@ -40,7 +41,9 @@ class CC_EXPORT EndFloatClipDisplayItem : public DisplayItem { return make_scoped_ptr(new EndFloatClipDisplayItem()); } - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; }; diff --git a/chromium/cc/playback/picture.cc b/chromium/cc/playback/picture.cc index 4537bf72107..8ce9c66ff8f 100644 --- a/chromium/cc/playback/picture.cc +++ b/chromium/cc/playback/picture.cc @@ -12,14 +12,12 @@ #include "base/trace_event/trace_event_argument.h" #include "base/values.h" #include "cc/base/math_util.h" -#include "cc/base/util.h" #include "cc/debug/picture_debug_util.h" #include "cc/debug/traced_picture.h" #include "cc/debug/traced_value.h" #include "cc/layers/content_layer_client.h" #include "skia/ext/pixel_ref_utils.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkDrawPictureCallback.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/core/SkStream.h" diff --git a/chromium/cc/playback/picture_pile.cc b/chromium/cc/playback/picture_pile.cc index b7b2822195b..55a5f80997a 100644 --- a/chromium/cc/playback/picture_pile.cc +++ b/chromium/cc/playback/picture_pile.cc @@ -8,6 +8,7 @@ #include <limits> #include <vector> +#include "cc/base/histograms.h" #include "cc/base/region.h" #include "cc/playback/picture_pile_impl.h" #include "skia/ext/analysis_canvas.h" @@ -149,6 +150,11 @@ const bool kDefaultClearCanvasSetting = false; const bool kDefaultClearCanvasSetting = true; #endif +DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER( + ScopedPicturePileUpdateTimer, + "Compositing.PicturePile.UpdateUs", + "Compositing.PicturePile.UpdateInvalidatedAreaPerMs"); + } // namespace namespace cc { @@ -181,6 +187,8 @@ bool PicturePile::UpdateAndExpandInvalidation( const gfx::Rect& visible_layer_rect, int frame_number, RecordingSource::RecordingMode recording_mode) { + ScopedPicturePileUpdateTimer timer; + gfx::Rect interest_rect = visible_layer_rect; interest_rect.Inset(-pixel_record_distance_, -pixel_record_distance_); recorded_viewport_ = interest_rect; @@ -188,6 +196,13 @@ bool PicturePile::UpdateAndExpandInvalidation( bool updated = ApplyInvalidationAndResize(interest_rect, invalidation, layer_size, frame_number); + + // Count the area that is being invalidated. + Region recorded_invalidation(*invalidation); + recorded_invalidation.Intersect(recorded_viewport_); + for (Region::Iterator it(recorded_invalidation); it.has_rect(); it.next()) + timer.AddArea(it.rect().size().GetArea()); + std::vector<gfx::Rect> invalid_tiles; GetInvalidTileRects(interest_rect, &invalid_tiles); std::vector<gfx::Rect> record_rects; diff --git a/chromium/cc/playback/picture_pile_impl.cc b/chromium/cc/playback/picture_pile_impl.cc index 96c6f63addb..345c24c7093 100644 --- a/chromium/cc/playback/picture_pile_impl.cc +++ b/chromium/cc/playback/picture_pile_impl.cc @@ -100,12 +100,14 @@ void PicturePileImpl::RasterForAnalysis(skia::AnalysisCanvas* canvas, } void PicturePileImpl::PlaybackToCanvas(SkCanvas* canvas, - const gfx::Rect& canvas_rect, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, float contents_scale) const { RasterSourceHelper::PrepareForPlaybackToCanvas( - canvas, canvas_rect, gfx::Rect(tiling_.tiling_size()), contents_scale, - background_color_, clear_canvas_with_debug_color_, requires_clear_); - RasterCommon(canvas, NULL, canvas_rect, contents_scale); + canvas, canvas_bitmap_rect, canvas_bitmap_rect, + gfx::Rect(tiling_.tiling_size()), contents_scale, background_color_, + clear_canvas_with_debug_color_, requires_clear_); + RasterCommon(canvas, NULL, canvas_bitmap_rect, contents_scale); } void PicturePileImpl::CoalesceRasters(const gfx::Rect& canvas_rect, @@ -202,7 +204,7 @@ void PicturePileImpl::CoalesceRasters(const gfx::Rect& canvas_rect, } void PicturePileImpl::RasterCommon(SkCanvas* canvas, - SkDrawPictureCallback* callback, + SkPicture::AbortCallback* callback, const gfx::Rect& canvas_rect, float contents_scale) const { DCHECK(contents_scale >= min_contents_scale_); @@ -266,7 +268,7 @@ skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() { SkCanvas* canvas = recorder.beginRecording(tiling_rect.width(), tiling_rect.height()); if (!tiling_rect.IsEmpty()) - PlaybackToCanvas(canvas, tiling_rect, 1.0); + PlaybackToCanvas(canvas, tiling_rect, tiling_rect, 1.0); skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecordingAsPicture()); diff --git a/chromium/cc/playback/picture_pile_impl.h b/chromium/cc/playback/picture_pile_impl.h index e8be323225a..0e1164b2dff 100644 --- a/chromium/cc/playback/picture_pile_impl.h +++ b/chromium/cc/playback/picture_pile_impl.h @@ -39,7 +39,8 @@ class CC_EXPORT PicturePileImpl : public RasterSource { // reported rasterize time (in stats_instrumentation) is the minimum measured // value over all runs. void PlaybackToCanvas(SkCanvas* canvas, - const gfx::Rect& canvas_rect, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, float contents_scale) const override; void PlaybackToSharedCanvas(SkCanvas* canvas, const gfx::Rect& canvas_rect, @@ -130,7 +131,7 @@ class CC_EXPORT PicturePileImpl : public RasterSource { typedef std::map<const Picture*, Region> PictureRegionMap; // Called when analyzing a tile. We can use AnalysisCanvas as - // SkDrawPictureCallback, which allows us to early out from analysis. + // SkPicture::AbortCallback, which allows us to early out from analysis. void RasterForAnalysis(skia::AnalysisCanvas* canvas, const gfx::Rect& canvas_rect, float contents_scale) const; @@ -141,7 +142,7 @@ class CC_EXPORT PicturePileImpl : public RasterSource { PictureRegionMap* result) const; void RasterCommon(SkCanvas* canvas, - SkDrawPictureCallback* callback, + SkPicture::AbortCallback* callback, const gfx::Rect& canvas_rect, float contents_scale) const; diff --git a/chromium/cc/playback/picture_pile_impl_perftest.cc b/chromium/cc/playback/picture_pile_impl_perftest.cc index a70fe68ebde..e1560400f22 100644 --- a/chromium/cc/playback/picture_pile_impl_perftest.cc +++ b/chromium/cc/playback/picture_pile_impl_perftest.cc @@ -55,7 +55,8 @@ class PicturePileImplPerfTest : public testing::Test { timer_.Reset(); do { - pile->PlaybackToCanvas(&canvas, content_rect, contents_scale); + pile->PlaybackToCanvas(&canvas, content_rect, content_rect, + contents_scale); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); diff --git a/chromium/cc/playback/picture_pile_impl_unittest.cc b/chromium/cc/playback/picture_pile_impl_unittest.cc index 14b06eecd5d..81c2aec4713 100644 --- a/chromium/cc/playback/picture_pile_impl_unittest.cc +++ b/chromium/cc/playback/picture_pile_impl_unittest.cc @@ -345,7 +345,7 @@ TEST(PicturePileImplTest, RasterFullContents) { SkCanvas canvas(bitmap); canvas.clear(SK_ColorTRANSPARENT); - pile->PlaybackToCanvas(&canvas, canvas_rect, contents_scale); + pile->PlaybackToCanvas(&canvas, canvas_rect, canvas_rect, contents_scale); SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); int num_pixels = bitmap.width() * bitmap.height(); @@ -390,7 +390,7 @@ TEST(PicturePileImpl, RasterContentsTransparent) { bitmap.allocN32Pixels(canvas_rect.width(), canvas_rect.height()); SkCanvas canvas(bitmap); - pile->PlaybackToCanvas(&canvas, canvas_rect, contents_scale); + pile->PlaybackToCanvas(&canvas, canvas_rect, canvas_rect, contents_scale); SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); int num_pixels = bitmap.width() * bitmap.height(); @@ -437,7 +437,8 @@ TEST_P(OverlapTest, NoOverlap) { bitmap.allocN32Pixels(content_bounds.width(), content_bounds.height()); SkCanvas canvas(bitmap); - pile->PlaybackToCanvas(&canvas, gfx::Rect(content_bounds), contents_scale); + pile->PlaybackToCanvas(&canvas, gfx::Rect(content_bounds), + gfx::Rect(content_bounds), contents_scale); for (int y = 0; y < bitmap.height(); y++) { for (int x = 0; x < bitmap.width(); x++) { diff --git a/chromium/cc/playback/pixel_ref_map.cc b/chromium/cc/playback/pixel_ref_map.cc index bb5a84c37b5..a5c8f05f453 100644 --- a/chromium/cc/playback/pixel_ref_map.cc +++ b/chromium/cc/playback/pixel_ref_map.cc @@ -7,7 +7,7 @@ #include <algorithm> #include <limits> -#include "cc/base/util.h" +#include "cc/base/math_util.h" #include "cc/playback/display_item_list.h" #include "cc/playback/picture.h" #include "skia/ext/pixel_ref_utils.h" @@ -33,15 +33,16 @@ void PixelRefMap::GatherPixelRefsFromPicture(SkPicture* picture) { skia::PixelRefUtils::GatherDiscardablePixelRefs(picture, &pixel_refs); for (skia::DiscardablePixelRefList::const_iterator it = pixel_refs.begin(); it != pixel_refs.end(); ++it) { - gfx::Point min( - RoundDown(static_cast<int>(it->pixel_ref_rect.x()), cell_size_.width()), - RoundDown(static_cast<int>(it->pixel_ref_rect.y()), - cell_size_.height())); - gfx::Point max( - RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.right())), - cell_size_.width()), - RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.bottom())), - cell_size_.height())); + gfx::Point min(MathUtil::RoundDown(static_cast<int>(it->pixel_ref_rect.x()), + cell_size_.width()), + MathUtil::RoundDown(static_cast<int>(it->pixel_ref_rect.y()), + cell_size_.height())); + gfx::Point max(MathUtil::RoundDown( + static_cast<int>(std::ceil(it->pixel_ref_rect.right())), + cell_size_.width()), + MathUtil::RoundDown( + static_cast<int>(std::ceil(it->pixel_ref_rect.bottom())), + cell_size_.height())); for (int y = min.y(); y <= max.y(); y += cell_size_.height()) { for (int x = min.x(); x <= max.x(); x += cell_size_.width()) { @@ -147,11 +148,12 @@ void PixelRefMap::Iterator::PointToFirstPixelRef(const gfx::Rect& rect) { gfx::Size cell_size(target_pixel_ref_map_->cell_size_); // We have to find a cell_size aligned point that corresponds to // query_rect. Point is a multiple of cell_size. - min_point_ = gfx::Point(RoundDown(query_rect.x(), cell_size.width()), - RoundDown(query_rect.y(), cell_size.height())); - max_point_ = - gfx::Point(RoundDown(query_rect.right() - 1, cell_size.width()), - RoundDown(query_rect.bottom() - 1, cell_size.height())); + min_point_ = + gfx::Point(MathUtil::RoundDown(query_rect.x(), cell_size.width()), + MathUtil::RoundDown(query_rect.y(), cell_size.height())); + max_point_ = gfx::Point( + MathUtil::RoundDown(query_rect.right() - 1, cell_size.width()), + MathUtil::RoundDown(query_rect.bottom() - 1, cell_size.height())); // Limit the points to known pixel ref boundaries. min_point_ = gfx::Point( diff --git a/chromium/cc/playback/raster_source.h b/chromium/cc/playback/raster_source.h index c0a484aa8d9..8d0356fae38 100644 --- a/chromium/cc/playback/raster_source.h +++ b/chromium/cc/playback/raster_source.h @@ -41,7 +41,8 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { // It is assumed that the canvas passed here will only be rasterized by // this raster source via this call. virtual void PlaybackToCanvas(SkCanvas* canvas, - const gfx::Rect& canvas_rect, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, float contents_scale) const = 0; // Similar to above, except that the canvas passed here can (or was already) diff --git a/chromium/cc/playback/raster_source_helper.cc b/chromium/cc/playback/raster_source_helper.cc index 6510b3c0e78..bd5edda07c3 100644 --- a/chromium/cc/playback/raster_source_helper.cc +++ b/chromium/cc/playback/raster_source_helper.cc @@ -14,16 +14,28 @@ namespace cc { void RasterSourceHelper::PrepareForPlaybackToCanvas( SkCanvas* canvas, - const gfx::Rect& canvas_rect, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, const gfx::Rect& source_rect, float contents_scale, SkColor background_color, bool clear_canvas_with_debug_color, bool requires_clear) { - canvas->discard(); + bool partial_update = canvas_bitmap_rect != canvas_playback_rect; + + if (!partial_update) + canvas->discard(); if (clear_canvas_with_debug_color) { // Any non-painted areas in the content bounds will be left in this color. - canvas->clear(DebugColors::NonPaintedFillColor()); + if (!partial_update) { + canvas->clear(DebugColors::NonPaintedFillColor()); + } else { + canvas->save(); + canvas->clipRect(gfx::RectToSkRect( + canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin())); + canvas->drawColor(DebugColors::NonPaintedFillColor()); + canvas->restore(); + } } // If this raster source has opaque contents, it is guaranteeing that it will @@ -33,7 +45,15 @@ void RasterSourceHelper::PrepareForPlaybackToCanvas( TRACE_EVENT_INSTANT0("cc", "SkCanvas::clear", TRACE_EVENT_SCOPE_THREAD); // Clearing is about ~4x faster than drawing a rect even if the content // isn't covering a majority of the canvas. - canvas->clear(SK_ColorTRANSPARENT); + if (!partial_update) { + canvas->clear(SK_ColorTRANSPARENT); + } else { + canvas->save(); + canvas->clipRect(gfx::RectToSkRect( + canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin())); + canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kClear_Mode); + canvas->restore(); + } } else { // Even if completely covered, for rasterizations that touch the edge of the // layer, we also need to raster the background color underneath the last @@ -47,14 +67,15 @@ void RasterSourceHelper::PrepareForPlaybackToCanvas( // covered by content. gfx::Rect deflated_content_rect = content_rect; deflated_content_rect.Inset(0, 0, 1, 1); - if (!deflated_content_rect.Contains(canvas_rect)) { + deflated_content_rect.Intersect(canvas_playback_rect); + if (!deflated_content_rect.Contains(canvas_playback_rect)) { if (clear_canvas_with_debug_color) { // Any non-painted areas outside of the content bounds are left in // this color. If this is seen then it means that cc neglected to // rerasterize a tile that used to intersect with the content rect // after the content bounds grew. canvas->save(); - canvas->translate(-canvas_rect.x(), -canvas_rect.y()); + canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y()); canvas->clipRect(gfx::RectToSkRect(content_rect), SkRegion::kDifference_Op); canvas->drawColor(DebugColors::MissingResizeInvalidations(), @@ -65,9 +86,12 @@ void RasterSourceHelper::PrepareForPlaybackToCanvas( // Drawing at most 2 x 2 x (canvas width + canvas height) texels is 2-3X // faster than clearing, so special case this. canvas->save(); - canvas->translate(-canvas_rect.x(), -canvas_rect.y()); + canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y()); gfx::Rect inflated_content_rect = content_rect; + // Only clear edges that will be inside the canvas_playback_rect, else we + // clear things that are still valid from a previous raster. inflated_content_rect.Inset(0, 0, -1, -1); + inflated_content_rect.Intersect(canvas_playback_rect); canvas->clipRect(gfx::RectToSkRect(inflated_content_rect), SkRegion::kReplace_Op); canvas->clipRect(gfx::RectToSkRect(deflated_content_rect), diff --git a/chromium/cc/playback/raster_source_helper.h b/chromium/cc/playback/raster_source_helper.h index 30513030351..9918703cd1f 100644 --- a/chromium/cc/playback/raster_source_helper.h +++ b/chromium/cc/playback/raster_source_helper.h @@ -16,7 +16,8 @@ namespace cc { class CC_EXPORT RasterSourceHelper { public: static void PrepareForPlaybackToCanvas(SkCanvas* canvas, - const gfx::Rect& canvas_rect, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, const gfx::Rect& source_rect, float contents_scale, SkColor background_color, diff --git a/chromium/cc/playback/recording_source_unittest.cc b/chromium/cc/playback/recording_source_unittest.cc index 01a89a19ba3..f1506e32ec8 100644 --- a/chromium/cc/playback/recording_source_unittest.cc +++ b/chromium/cc/playback/recording_source_unittest.cc @@ -8,7 +8,6 @@ #include "cc/test/fake_display_list_recording_source.h" #include "cc/test/fake_picture_pile.h" #include "cc/test/fake_picture_pile_impl.h" -#include "cc/test/impl_side_painting_settings.h" #include "cc/test/skia_common.h" #include "testing/gtest/include/gtest/gtest.h" @@ -30,8 +29,10 @@ template <> scoped_ptr<FakeDisplayListRecordingSource> CreateRecordingSource< FakeDisplayListRecordingSource>(const gfx::Rect& viewport, const gfx::Size& grid_cell_size) { + gfx::Rect layer_rect(viewport.right(), viewport.bottom()); scoped_ptr<FakeDisplayListRecordingSource> recording_source = - FakeDisplayListRecordingSource::CreateRecordingSource(viewport); + FakeDisplayListRecordingSource::CreateRecordingSource(viewport, + layer_rect.size()); recording_source->SetGridCellSize(grid_cell_size); return recording_source.Pass(); diff --git a/chromium/cc/playback/transform_display_item.cc b/chromium/cc/playback/transform_display_item.cc index 1f4e5dbd733..df7ca1b8e56 100644 --- a/chromium/cc/playback/transform_display_item.cc +++ b/chromium/cc/playback/transform_display_item.cc @@ -20,13 +20,13 @@ TransformDisplayItem::~TransformDisplayItem() { void TransformDisplayItem::SetNew(const gfx::Transform& transform) { transform_ = transform; - size_t memory_usage = sizeof(gfx::Transform); DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 1 /* op_count */, - memory_usage); + 0 /* external_memory_usage */); } void TransformDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->save(); if (!transform_.IsIdentity()) canvas->concat(transform_.matrix()); @@ -40,14 +40,16 @@ void TransformDisplayItem::AsValueInto( EndTransformDisplayItem::EndTransformDisplayItem() { DisplayItem::SetNew(true /* suitable_for_gpu_raster */, 0 /* op_count */, - 0 /* memory_usage */); + 0 /* external_memory_usage */); } EndTransformDisplayItem::~EndTransformDisplayItem() { } -void EndTransformDisplayItem::Raster(SkCanvas* canvas, - SkDrawPictureCallback* callback) const { +void EndTransformDisplayItem::Raster( + SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const { canvas->restore(); } diff --git a/chromium/cc/playback/transform_display_item.h b/chromium/cc/playback/transform_display_item.h index 731249d338e..9d3f9c6da46 100644 --- a/chromium/cc/playback/transform_display_item.h +++ b/chromium/cc/playback/transform_display_item.h @@ -11,7 +11,6 @@ #include "ui/gfx/transform.h" class SkCanvas; -class SkDrawPictureCallback; namespace cc { @@ -22,7 +21,9 @@ class CC_EXPORT TransformDisplayItem : public DisplayItem { void SetNew(const gfx::Transform& transform); - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; private: @@ -38,7 +39,9 @@ class CC_EXPORT EndTransformDisplayItem : public DisplayItem { return make_scoped_ptr(new EndTransformDisplayItem()); } - void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + void Raster(SkCanvas* canvas, + const gfx::Rect& canvas_target_playback_rect, + SkPicture::AbortCallback* callback) const override; void AsValueInto(base::trace_event::TracedValue* array) const override; }; diff --git a/chromium/cc/quads/checkerboard_draw_quad.cc b/chromium/cc/quads/checkerboard_draw_quad.cc index db6ad1ea356..4cd3c2aa18b 100644 --- a/chromium/cc/quads/checkerboard_draw_quad.cc +++ b/chromium/cc/quads/checkerboard_draw_quad.cc @@ -39,9 +39,6 @@ void CheckerboardDrawQuad::SetAll(const SharedQuadState* shared_quad_state, this->scale = scale; } -void CheckerboardDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) {} - const CheckerboardDrawQuad* CheckerboardDrawQuad::MaterialCast( const DrawQuad* quad) { DCHECK(quad->material == DrawQuad::CHECKERBOARD); diff --git a/chromium/cc/quads/checkerboard_draw_quad.h b/chromium/cc/quads/checkerboard_draw_quad.h index 9ecf4f0fe23..fe793675a27 100644 --- a/chromium/cc/quads/checkerboard_draw_quad.h +++ b/chromium/cc/quads/checkerboard_draw_quad.h @@ -33,8 +33,6 @@ class CC_EXPORT CheckerboardDrawQuad : public DrawQuad { SkColor color; float scale; - void IterateResources(const ResourceIteratorCallback& callback) override; - static const CheckerboardDrawQuad* MaterialCast(const DrawQuad*); private: diff --git a/chromium/cc/quads/debug_border_draw_quad.cc b/chromium/cc/quads/debug_border_draw_quad.cc index f91bf3b84bf..529075aa9de 100644 --- a/chromium/cc/quads/debug_border_draw_quad.cc +++ b/chromium/cc/quads/debug_border_draw_quad.cc @@ -41,9 +41,6 @@ void DebugBorderDrawQuad::SetAll(const SharedQuadState* shared_quad_state, this->width = width; } -void DebugBorderDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) {} - const DebugBorderDrawQuad* DebugBorderDrawQuad::MaterialCast( const DrawQuad* quad) { DCHECK(quad->material == DrawQuad::DEBUG_BORDER); diff --git a/chromium/cc/quads/debug_border_draw_quad.h b/chromium/cc/quads/debug_border_draw_quad.h index 7ee0d82f2d9..7023ab23b5d 100644 --- a/chromium/cc/quads/debug_border_draw_quad.h +++ b/chromium/cc/quads/debug_border_draw_quad.h @@ -33,8 +33,6 @@ class CC_EXPORT DebugBorderDrawQuad : public DrawQuad { SkColor color; int width; - void IterateResources(const ResourceIteratorCallback& callback) override; - static const DebugBorderDrawQuad* MaterialCast(const DrawQuad*); private: diff --git a/chromium/cc/quads/draw_polygon.cc b/chromium/cc/quads/draw_polygon.cc index 6544b641acb..cdb94d0e33b 100644 --- a/chromium/cc/quads/draw_polygon.cc +++ b/chromium/cc/quads/draw_polygon.cc @@ -52,7 +52,7 @@ DrawPolygon::DrawPolygon(const DrawQuad* original, // a visible content rect to make the 4 corner points from, and a transformation // to move it and its normal into screen space. DrawPolygon::DrawPolygon(const DrawQuad* original_ref, - const gfx::RectF& visible_content_rect, + const gfx::RectF& visible_layer_rect, const gfx::Transform& transform, int draw_order_index) : normal_(0.0f, 0.0f, 1.0f), @@ -61,7 +61,7 @@ DrawPolygon::DrawPolygon(const DrawQuad* original_ref, is_split_(false) { gfx::Point3F points[8]; int num_vertices_in_clipped_quad; - gfx::QuadF send_quad(visible_content_rect); + gfx::QuadF send_quad(visible_layer_rect); // Doing this mapping here is very important, since we can't just transform // the points without clipping and not run into strange geometry issues when diff --git a/chromium/cc/quads/draw_polygon.h b/chromium/cc/quads/draw_polygon.h index b94ff1ef777..93c36024fc2 100644 --- a/chromium/cc/quads/draw_polygon.h +++ b/chromium/cc/quads/draw_polygon.h @@ -29,7 +29,7 @@ class CC_EXPORT DrawPolygon { const gfx::Vector3dF& normal, int draw_order_index = 0); DrawPolygon(const DrawQuad* original_ref, - const gfx::RectF& visible_content_rect, + const gfx::RectF& visible_layer_rect, const gfx::Transform& transform, int draw_order_index = 0); diff --git a/chromium/cc/quads/draw_quad.cc b/chromium/cc/quads/draw_quad.cc index ac1b43e6c20..606d7ab6058 100644 --- a/chromium/cc/quads/draw_quad.cc +++ b/chromium/cc/quads/draw_quad.cc @@ -62,10 +62,9 @@ void DrawQuad::AsValueInto(base::trace_event::TracedValue* value) const { MathUtil::AddToTracedValue("content_space_rect", rect, value); bool rect_is_clipped; - gfx::QuadF rect_as_target_space_quad = MathUtil::MapQuad( - shared_quad_state->content_to_target_transform, - gfx::QuadF(rect), - &rect_is_clipped); + gfx::QuadF rect_as_target_space_quad = + MathUtil::MapQuad(shared_quad_state->quad_to_target_transform, + gfx::QuadF(rect), &rect_is_clipped); MathUtil::AddToTracedValue("rect_as_target_space_quad", rect_as_target_space_quad, value); @@ -74,10 +73,9 @@ void DrawQuad::AsValueInto(base::trace_event::TracedValue* value) const { MathUtil::AddToTracedValue("content_space_opaque_rect", opaque_rect, value); bool opaque_rect_is_clipped; - gfx::QuadF opaque_rect_as_target_space_quad = MathUtil::MapQuad( - shared_quad_state->content_to_target_transform, - gfx::QuadF(opaque_rect), - &opaque_rect_is_clipped); + gfx::QuadF opaque_rect_as_target_space_quad = + MathUtil::MapQuad(shared_quad_state->quad_to_target_transform, + gfx::QuadF(opaque_rect), &opaque_rect_is_clipped); MathUtil::AddToTracedValue("opaque_rect_as_target_space_quad", opaque_rect_as_target_space_quad, value); @@ -86,10 +84,9 @@ void DrawQuad::AsValueInto(base::trace_event::TracedValue* value) const { MathUtil::AddToTracedValue("content_space_visible_rect", visible_rect, value); bool visible_rect_is_clipped; - gfx::QuadF visible_rect_as_target_space_quad = MathUtil::MapQuad( - shared_quad_state->content_to_target_transform, - gfx::QuadF(visible_rect), - &visible_rect_is_clipped); + gfx::QuadF visible_rect_as_target_space_quad = + MathUtil::MapQuad(shared_quad_state->quad_to_target_transform, + gfx::QuadF(visible_rect), &visible_rect_is_clipped); MathUtil::AddToTracedValue("visible_rect_as_target_space_quad", visible_rect_as_target_space_quad, value); @@ -101,4 +98,9 @@ void DrawQuad::AsValueInto(base::trace_event::TracedValue* value) const { ExtendValue(value); } +DrawQuad::Resources::Resources() : count(0) { + for (size_t i = 0; i < kMaxResourceIdCount; ++i) + ids[i] = 0; +} + } // namespace cc diff --git a/chromium/cc/quads/draw_quad.h b/chromium/cc/quads/draw_quad.h index 3897d1d1ce8..df3bc1213f5 100644 --- a/chromium/cc/quads/draw_quad.h +++ b/chromium/cc/quads/draw_quad.h @@ -7,8 +7,8 @@ #include "base/callback.h" #include "cc/base/cc_export.h" +#include "cc/base/resource_id.h" #include "cc/quads/shared_quad_state.h" -#include "cc/resources/resource_provider.h" namespace base { namespace trace_event { @@ -27,10 +27,10 @@ namespace cc { // Note: quads contain rects and sizes, which live in different spaces. There is // the "content space", which is the arbitrary space in which the quad's // geometry is defined (generally related to the layer that produced the quad, -// e.g. the content space for TiledLayerImpls, or the geometry space for -// PictureLayerImpls). There is also the "target space", which is the space, in -// "physical" pixels, of the render target where the quads is drawn. The quad's -// transform maps the content space to the target space. +// e.g. the geometry space for PictureLayerImpls or the layer's coordinate space +// for most other layers). There is also the "target space", which is the space, +// in "physical" pixels, of the render target where the quads is drawn. The +// quad's transform maps the content space to the target space. class CC_EXPORT DrawQuad { public: enum Material { @@ -51,17 +51,6 @@ class CC_EXPORT DrawQuad { virtual ~DrawQuad(); - // TODO(danakj): Chromify or remove these SharedQuadState helpers. - const gfx::Transform& quadTransform() const { - return shared_quad_state->content_to_target_transform; - } - gfx::Rect visibleContentRect() const { - return shared_quad_state->visible_content_rect; - } - gfx::Rect clipRect() const { return shared_quad_state->clip_rect; } - bool isClipped() const { return shared_quad_state->is_clipped; } - float opacity() const { return shared_quad_state->opacity; } - Material material; // This rect, after applying the quad_transform(), gives the geometry that @@ -96,10 +85,6 @@ class CC_EXPORT DrawQuad { return !opaque_rect.Contains(visible_rect); } - typedef ResourceProvider::ResourceId ResourceId; - typedef base::Callback<ResourceId(ResourceId)> ResourceIteratorCallback; - virtual void IterateResources(const ResourceIteratorCallback& callback) = 0; - // Is the left edge of this tile aligned with the originating layer's // left edge? bool IsLeftEdge() const { return !rect.x(); } @@ -111,13 +96,13 @@ class CC_EXPORT DrawQuad { // Is the right edge of this tile aligned with the originating layer's // right edge? bool IsRightEdge() const { - return rect.right() == shared_quad_state->content_bounds.width(); + return rect.right() == shared_quad_state->quad_layer_bounds.width(); } // Is the bottom edge of this tile aligned with the originating layer's // bottom edge? bool IsBottomEdge() const { - return rect.bottom() == shared_quad_state->content_bounds.height(); + return rect.bottom() == shared_quad_state->quad_layer_bounds.height(); } // Is any edge of this tile aligned with the originating layer's @@ -128,6 +113,22 @@ class CC_EXPORT DrawQuad { void AsValueInto(base::trace_event::TracedValue* value) const; + struct CC_EXPORT Resources { + enum : size_t { kMaxResourceIdCount = 4 }; + Resources(); + + ResourceId* begin() { return ids; } + ResourceId* end() { + DCHECK_LE(count, kMaxResourceIdCount); + return ids + count; + } + + size_t count; + ResourceId ids[kMaxResourceIdCount]; + }; + + Resources resources; + protected: DrawQuad(); diff --git a/chromium/cc/quads/draw_quad_perftest.cc b/chromium/cc/quads/draw_quad_perftest.cc new file mode 100644 index 00000000000..08ce6d07b29 --- /dev/null +++ b/chromium/cc/quads/draw_quad_perftest.cc @@ -0,0 +1,113 @@ +// Copyright 2015 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 <vector> + +#include "base/bind.h" +#include "base/time/time.h" +#include "cc/debug/lap_timer.h" +#include "cc/quads/draw_quad.h" +#include "cc/quads/render_pass.h" +#include "cc/quads/texture_draw_quad.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/perf/perf_test.h" + +namespace cc { +namespace { + +static const int kTimeLimitMillis = 2000; +static const int kWarmupRuns = 5; +static const int kTimeCheckInterval = 10; + +SharedQuadState* CreateSharedQuadState(RenderPass* render_pass) { + gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0); + gfx::Size content_bounds(26, 28); + gfx::Rect visible_layer_rect(10, 12, 14, 16); + gfx::Rect clip_rect(19, 21, 23, 25); + bool is_clipped = false; + float opacity = 1.f; + int sorting_context_id = 65536; + SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode; + + SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState(); + state->SetAll(quad_transform, content_bounds, visible_layer_rect, clip_rect, + is_clipped, opacity, blend_mode, sorting_context_id); + return state; +} + +class DrawQuadPerfTest : public testing::Test { + public: + DrawQuadPerfTest() + : timer_(kWarmupRuns, + base::TimeDelta::FromMilliseconds(kTimeLimitMillis), + kTimeCheckInterval) {} + + void CreateRenderPass() { + render_pass_ = RenderPass::Create(); + SharedQuadState* new_shared_state( + CreateSharedQuadState(render_pass_.get())); + shared_state_ = render_pass_->CreateAndAppendSharedQuadState(); + shared_state_->CopyFrom(new_shared_state); + } + + void CleanUpRenderPass() { + render_pass_.reset(); + shared_state_ = nullptr; + } + + void GenerateTextureDrawQuads(int count, std::vector<DrawQuad*>* quads) { + for (int i = 0; i < count; ++i) { + TextureDrawQuad* quad = + render_pass_->CreateAndAppendDrawQuad<TextureDrawQuad>(); + gfx::Rect rect(0, 0, 100, 100); + ResourceId resource_id = 1; + bool premultiplied_alpha = true; + gfx::PointF uv_top_left(0, 0); + gfx::PointF uv_bottom_right(1, 1); + SkColor background_color = SK_ColorRED; + float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f}; + bool y_flipped = false; + bool nearest_neighbor = true; + + quad->SetNew(shared_state_, rect, rect, rect, resource_id, + premultiplied_alpha, uv_top_left, uv_bottom_right, + background_color, vertex_opacity, y_flipped, + nearest_neighbor); + quads->push_back(quad); + } + } + + void RunIterateResourceTest(const std::string& test_name, int quad_count) { + CreateRenderPass(); + std::vector<DrawQuad*> quads; + GenerateTextureDrawQuads(quad_count, &quads); + + timer_.Reset(); + do { + for (auto* quad : quads) { + for (ResourceId& resource_id : quad->resources) + ++resource_id; + } + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + + perf_test::PrintResult("draw_quad_iterate_resources", "", test_name, + timer_.LapsPerSecond(), "runs/s", true); + CleanUpRenderPass(); + } + + private: + scoped_ptr<RenderPass> render_pass_; + SharedQuadState* shared_state_; + LapTimer timer_; +}; + +TEST_F(DrawQuadPerfTest, IterateResources) { + RunIterateResourceTest("10_quads", 10); + RunIterateResourceTest("100_quads", 100); + RunIterateResourceTest("500_quads", 500); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/quads/draw_quad_unittest.cc b/chromium/cc/quads/draw_quad_unittest.cc index 968a1d059fc..833f388aafb 100644 --- a/chromium/cc/quads/draw_quad_unittest.cc +++ b/chromium/cc/quads/draw_quad_unittest.cc @@ -34,8 +34,8 @@ namespace { TEST(DrawQuadTest, CopySharedQuadState) { gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0); - gfx::Size content_bounds(26, 28); - gfx::Rect visible_content_rect(10, 12, 14, 16); + gfx::Size layer_bounds(26, 28); + gfx::Rect visible_layer_rect(10, 12, 14, 16); gfx::Rect clip_rect(19, 21, 23, 25); bool is_clipped = true; float opacity = 0.25f; @@ -43,19 +43,13 @@ TEST(DrawQuadTest, CopySharedQuadState) { int sorting_context_id = 65536; scoped_ptr<SharedQuadState> state(new SharedQuadState); - state->SetAll(quad_transform, - content_bounds, - visible_content_rect, - clip_rect, - is_clipped, - opacity, - blend_mode, - sorting_context_id); + state->SetAll(quad_transform, layer_bounds, visible_layer_rect, clip_rect, + is_clipped, opacity, blend_mode, sorting_context_id); scoped_ptr<SharedQuadState> copy(new SharedQuadState); copy->CopyFrom(state.get()); - EXPECT_EQ(quad_transform, copy->content_to_target_transform); - EXPECT_EQ(visible_content_rect, copy->visible_content_rect); + EXPECT_EQ(quad_transform, copy->quad_to_target_transform); + EXPECT_EQ(visible_layer_rect, copy->visible_quad_layer_rect); EXPECT_EQ(opacity, copy->opacity); EXPECT_EQ(clip_rect, copy->clip_rect); EXPECT_EQ(is_clipped, copy->is_clipped); @@ -64,8 +58,8 @@ TEST(DrawQuadTest, CopySharedQuadState) { SharedQuadState* CreateSharedQuadState(RenderPass* render_pass) { gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0); - gfx::Size content_bounds(26, 28); - gfx::Rect visible_content_rect(10, 12, 14, 16); + gfx::Size layer_bounds(26, 28); + gfx::Rect visible_layer_rect(10, 12, 14, 16); gfx::Rect clip_rect(19, 21, 23, 25); bool is_clipped = false; float opacity = 1.f; @@ -73,14 +67,8 @@ SharedQuadState* CreateSharedQuadState(RenderPass* render_pass) { SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode; SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState(); - state->SetAll(quad_transform, - content_bounds, - visible_content_rect, - clip_rect, - is_clipped, - opacity, - blend_mode, - sorting_context_id); + state->SetAll(quad_transform, layer_bounds, visible_layer_rect, clip_rect, + is_clipped, opacity, blend_mode, sorting_context_id); return state; } @@ -330,6 +318,15 @@ void CompareDrawQuad(DrawQuad* quad, } \ SETUP_AND_COPY_QUAD_NEW(Type, quad_new); +#define CREATE_QUAD_10_ALL(Type, a, b, c, d, e, f, g, h, i, j) \ + Type* quad_all = render_pass->CreateAndAppendDrawQuad<Type>(); \ + { \ + QUAD_DATA quad_all->SetAll(shared_state, quad_rect, quad_opaque_rect, \ + quad_visible_rect, needs_blending, a, b, c, d, \ + e, f, g, h, i, j); \ + } \ + SETUP_AND_COPY_QUAD_ALL(Type, quad_all); + #define CREATE_QUAD_11_NEW(Type, a, b, c, d, e, f, g, h, i, j, k) \ Type* quad_new = render_pass->CreateAndAppendDrawQuad<Type>(); \ { \ @@ -404,7 +401,7 @@ TEST(DrawQuadTest, CopyIOSurfaceDrawQuad) { gfx::Rect opaque_rect(33, 47, 10, 12); gfx::Rect visible_rect(40, 50, 30, 20); gfx::Size size(58, 95); - ResourceProvider::ResourceId resource_id = 72; + ResourceId resource_id = 72; IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED; CREATE_SHARED_STATE(); @@ -418,20 +415,20 @@ TEST(DrawQuadTest, CopyIOSurfaceDrawQuad) { EXPECT_EQ(visible_rect, copy_quad->visible_rect); EXPECT_EQ(opaque_rect, copy_quad->opaque_rect); EXPECT_EQ(size, copy_quad->io_surface_size); - EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id); + EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id()); EXPECT_EQ(orientation, copy_quad->orientation); CREATE_QUAD_3_ALL(IOSurfaceDrawQuad, size, resource_id, orientation); EXPECT_EQ(DrawQuad::IO_SURFACE_CONTENT, copy_quad->material); EXPECT_EQ(size, copy_quad->io_surface_size); - EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id); + EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id()); EXPECT_EQ(orientation, copy_quad->orientation); } TEST(DrawQuadTest, CopyRenderPassDrawQuad) { gfx::Rect visible_rect(40, 50, 30, 20); RenderPassId render_pass_id(22, 64); - ResourceProvider::ResourceId mask_resource_id = 78; + ResourceId mask_resource_id = 78; gfx::Vector2dF mask_uv_scale(33.f, 19.f); gfx::Size mask_texture_size(128, 134); FilterOperations filters; @@ -457,7 +454,7 @@ TEST(DrawQuadTest, CopyRenderPassDrawQuad) { EXPECT_EQ(DrawQuad::RENDER_PASS, copy_quad->material); EXPECT_EQ(visible_rect, copy_quad->visible_rect); EXPECT_EQ(copied_render_pass_id, copy_quad->render_pass_id); - EXPECT_EQ(mask_resource_id, copy_quad->mask_resource_id); + EXPECT_EQ(mask_resource_id, copy_quad->mask_resource_id()); EXPECT_EQ(mask_uv_scale.ToString(), copy_quad->mask_uv_scale.ToString()); EXPECT_EQ(mask_texture_size.ToString(), copy_quad->mask_texture_size.ToString()); @@ -476,7 +473,7 @@ TEST(DrawQuadTest, CopyRenderPassDrawQuad) { copied_render_pass_id); EXPECT_EQ(DrawQuad::RENDER_PASS, copy_quad->material); EXPECT_EQ(copied_render_pass_id, copy_quad->render_pass_id); - EXPECT_EQ(mask_resource_id, copy_quad->mask_resource_id); + EXPECT_EQ(mask_resource_id, copy_quad->mask_resource_id()); EXPECT_EQ(mask_uv_scale.ToString(), copy_quad->mask_uv_scale.ToString()); EXPECT_EQ(mask_texture_size.ToString(), copy_quad->mask_texture_size.ToString()); @@ -507,21 +504,28 @@ TEST(DrawQuadTest, CopySolidColorDrawQuad) { TEST(DrawQuadTest, CopyStreamVideoDrawQuad) { gfx::Rect opaque_rect(33, 47, 10, 12); gfx::Rect visible_rect(40, 50, 30, 20); - ResourceProvider::ResourceId resource_id = 64; + ResourceId resource_id = 64; + gfx::Size resource_size_in_pixels = gfx::Size(40, 41); + bool allow_overlay = true; gfx::Transform matrix = gfx::Transform(0.5, 0.25, 1, 0.75, 0, 1); CREATE_SHARED_STATE(); - CREATE_QUAD_4_NEW( - StreamVideoDrawQuad, opaque_rect, visible_rect, resource_id, matrix); + CREATE_QUAD_6_NEW(StreamVideoDrawQuad, opaque_rect, visible_rect, resource_id, + resource_size_in_pixels, allow_overlay, matrix); EXPECT_EQ(DrawQuad::STREAM_VIDEO_CONTENT, copy_quad->material); EXPECT_EQ(visible_rect, copy_quad->visible_rect); EXPECT_EQ(opaque_rect, copy_quad->opaque_rect); - EXPECT_EQ(resource_id, copy_quad->resource_id); + EXPECT_EQ(resource_id, copy_quad->resource_id()); + EXPECT_EQ(allow_overlay, copy_quad->allow_overlay()); + EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels()); EXPECT_EQ(matrix, copy_quad->matrix); - CREATE_QUAD_2_ALL(StreamVideoDrawQuad, resource_id, matrix); + CREATE_QUAD_4_ALL(StreamVideoDrawQuad, resource_id, resource_size_in_pixels, + allow_overlay, matrix); EXPECT_EQ(DrawQuad::STREAM_VIDEO_CONTENT, copy_quad->material); - EXPECT_EQ(resource_id, copy_quad->resource_id); + EXPECT_EQ(resource_id, copy_quad->resource_id()); + EXPECT_EQ(allow_overlay, copy_quad->allow_overlay()); + EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels()); EXPECT_EQ(matrix, copy_quad->matrix); } @@ -545,6 +549,8 @@ TEST(DrawQuadTest, CopyTextureDrawQuad) { gfx::Rect opaque_rect(33, 47, 10, 12); gfx::Rect visible_rect(40, 50, 30, 20); unsigned resource_id = 82; + gfx::Size resource_size_in_pixels = gfx::Size(40, 41); + bool allow_overlay = true; bool premultiplied_alpha = true; gfx::PointF uv_top_left(0.5f, 224.f); gfx::PointF uv_bottom_right(51.5f, 260.f); @@ -567,7 +573,7 @@ TEST(DrawQuadTest, CopyTextureDrawQuad) { EXPECT_EQ(DrawQuad::TEXTURE_CONTENT, copy_quad->material); EXPECT_EQ(visible_rect, copy_quad->visible_rect); EXPECT_EQ(opaque_rect, copy_quad->opaque_rect); - EXPECT_EQ(resource_id, copy_quad->resource_id); + EXPECT_EQ(resource_id, copy_quad->resource_id()); EXPECT_EQ(premultiplied_alpha, copy_quad->premultiplied_alpha); EXPECT_EQ(uv_top_left, copy_quad->uv_top_left); EXPECT_EQ(uv_bottom_right, copy_quad->uv_bottom_right); @@ -575,17 +581,14 @@ TEST(DrawQuadTest, CopyTextureDrawQuad) { EXPECT_EQ(y_flipped, copy_quad->y_flipped); EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor); - CREATE_QUAD_8_ALL(TextureDrawQuad, - resource_id, - premultiplied_alpha, - uv_top_left, - uv_bottom_right, - SK_ColorTRANSPARENT, - vertex_opacity, - y_flipped, - nearest_neighbor); + CREATE_QUAD_10_ALL(TextureDrawQuad, resource_id, resource_size_in_pixels, + allow_overlay, premultiplied_alpha, uv_top_left, + uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity, + y_flipped, nearest_neighbor); EXPECT_EQ(DrawQuad::TEXTURE_CONTENT, copy_quad->material); - EXPECT_EQ(resource_id, copy_quad->resource_id); + EXPECT_EQ(resource_id, copy_quad->resource_id()); + EXPECT_EQ(allow_overlay, copy_quad->allow_overlay()); + EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels()); EXPECT_EQ(premultiplied_alpha, copy_quad->premultiplied_alpha); EXPECT_EQ(uv_top_left, copy_quad->uv_top_left); EXPECT_EQ(uv_bottom_right, copy_quad->uv_bottom_right); @@ -615,7 +618,7 @@ TEST(DrawQuadTest, CopyTileDrawQuad) { EXPECT_EQ(DrawQuad::TILED_CONTENT, copy_quad->material); EXPECT_EQ(opaque_rect, copy_quad->opaque_rect); EXPECT_EQ(visible_rect, copy_quad->visible_rect); - EXPECT_EQ(resource_id, copy_quad->resource_id); + EXPECT_EQ(resource_id, copy_quad->resource_id()); EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect); EXPECT_EQ(texture_size, copy_quad->texture_size); EXPECT_EQ(swizzle_contents, copy_quad->swizzle_contents); @@ -628,7 +631,7 @@ TEST(DrawQuadTest, CopyTileDrawQuad) { swizzle_contents, nearest_neighbor); EXPECT_EQ(DrawQuad::TILED_CONTENT, copy_quad->material); - EXPECT_EQ(resource_id, copy_quad->resource_id); + EXPECT_EQ(resource_id, copy_quad->resource_id()); EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect); EXPECT_EQ(texture_size, copy_quad->texture_size); EXPECT_EQ(swizzle_contents, copy_quad->swizzle_contents); @@ -642,10 +645,10 @@ TEST(DrawQuadTest, CopyYUVVideoDrawQuad) { gfx::RectF uv_tex_coord_rect(20, 25, 15, 10); gfx::Size ya_tex_size(32, 68); gfx::Size uv_tex_size(41, 51); - ResourceProvider::ResourceId y_plane_resource_id = 45; - ResourceProvider::ResourceId u_plane_resource_id = 532; - ResourceProvider::ResourceId v_plane_resource_id = 4; - ResourceProvider::ResourceId a_plane_resource_id = 63; + ResourceId y_plane_resource_id = 45; + ResourceId u_plane_resource_id = 532; + ResourceId v_plane_resource_id = 4; + ResourceId a_plane_resource_id = 63; YUVVideoDrawQuad::ColorSpace color_space = YUVVideoDrawQuad::JPEG; CREATE_SHARED_STATE(); @@ -660,10 +663,10 @@ TEST(DrawQuadTest, CopyYUVVideoDrawQuad) { EXPECT_EQ(uv_tex_coord_rect, copy_quad->uv_tex_coord_rect); EXPECT_EQ(ya_tex_size, copy_quad->ya_tex_size); EXPECT_EQ(uv_tex_size, copy_quad->uv_tex_size); - EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id); - EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id); - EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id); - EXPECT_EQ(a_plane_resource_id, copy_quad->a_plane_resource_id); + EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id()); + EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id()); + EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id()); + EXPECT_EQ(a_plane_resource_id, copy_quad->a_plane_resource_id()); EXPECT_EQ(color_space, copy_quad->color_space); CREATE_QUAD_9_ALL(YUVVideoDrawQuad, ya_tex_coord_rect, uv_tex_coord_rect, @@ -675,10 +678,10 @@ TEST(DrawQuadTest, CopyYUVVideoDrawQuad) { EXPECT_EQ(uv_tex_coord_rect, copy_quad->uv_tex_coord_rect); EXPECT_EQ(ya_tex_size, copy_quad->ya_tex_size); EXPECT_EQ(uv_tex_size, copy_quad->uv_tex_size); - EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id); - EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id); - EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id); - EXPECT_EQ(a_plane_resource_id, copy_quad->a_plane_resource_id); + EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id()); + EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id()); + EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id()); + EXPECT_EQ(a_plane_resource_id, copy_quad->a_plane_resource_id()); EXPECT_EQ(color_space, copy_quad->color_space); } @@ -725,16 +728,12 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) { class DrawQuadIteratorTest : public testing::Test { protected: - ResourceProvider::ResourceId IncrementResourceId( - ResourceProvider::ResourceId id) { - ++num_resources_; - return id + 1; - } - int IterateAndCount(DrawQuad* quad) { num_resources_ = 0; - quad->IterateResources(base::Bind( - &DrawQuadIteratorTest::IncrementResourceId, base::Unretained(this))); + for (ResourceId& resource_id : quad->resources) { + ++num_resources_; + ++resource_id; + } return num_resources_; } @@ -766,7 +765,7 @@ TEST_F(DrawQuadIteratorTest, IOSurfaceDrawQuad) { gfx::Rect opaque_rect(33, 47, 10, 12); gfx::Rect visible_rect(40, 50, 30, 20); gfx::Size size(58, 95); - ResourceProvider::ResourceId resource_id = 72; + ResourceId resource_id = 72; IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED; CREATE_SHARED_STATE(); @@ -776,15 +775,15 @@ TEST_F(DrawQuadIteratorTest, IOSurfaceDrawQuad) { size, resource_id, orientation); - EXPECT_EQ(resource_id, quad_new->io_surface_resource_id); + EXPECT_EQ(resource_id, quad_new->io_surface_resource_id()); EXPECT_EQ(1, IterateAndCount(quad_new)); - EXPECT_EQ(resource_id + 1, quad_new->io_surface_resource_id); + EXPECT_EQ(resource_id + 1, quad_new->io_surface_resource_id()); } TEST_F(DrawQuadIteratorTest, RenderPassDrawQuad) { gfx::Rect visible_rect(40, 50, 30, 20); RenderPassId render_pass_id(22, 64); - ResourceProvider::ResourceId mask_resource_id = 78; + ResourceId mask_resource_id = 78; gfx::Vector2dF mask_uv_scale(33.f, 19.f); gfx::Size mask_texture_size(128, 134); FilterOperations filters; @@ -807,12 +806,17 @@ TEST_F(DrawQuadIteratorTest, RenderPassDrawQuad) { filters_scale, background_filters, copied_render_pass_id); - EXPECT_EQ(mask_resource_id, quad_new->mask_resource_id); + EXPECT_EQ(mask_resource_id, quad_new->mask_resource_id()); EXPECT_EQ(1, IterateAndCount(quad_new)); - EXPECT_EQ(mask_resource_id + 1, quad_new->mask_resource_id); - quad_new->mask_resource_id = 0; + EXPECT_EQ(mask_resource_id + 1, quad_new->mask_resource_id()); + + ResourceId new_mask_resource_id = 0; + gfx::Rect quad_rect(30, 40, 50, 60); + quad_new->SetNew(shared_state, quad_rect, visible_rect, render_pass_id, + new_mask_resource_id, mask_uv_scale, mask_texture_size, + filters, filters_scale, background_filters); EXPECT_EQ(0, IterateAndCount(quad_new)); - EXPECT_EQ(0u, quad_new->mask_resource_id); + EXPECT_EQ(0u, quad_new->mask_resource_id()); } TEST_F(DrawQuadIteratorTest, SolidColorDrawQuad) { @@ -829,15 +833,19 @@ TEST_F(DrawQuadIteratorTest, SolidColorDrawQuad) { TEST_F(DrawQuadIteratorTest, StreamVideoDrawQuad) { gfx::Rect opaque_rect(33, 47, 10, 12); gfx::Rect visible_rect(40, 50, 30, 20); - ResourceProvider::ResourceId resource_id = 64; + ResourceId resource_id = 64; + gfx::Size resource_size_in_pixels = gfx::Size(40, 41); + bool allow_overlay = true; gfx::Transform matrix = gfx::Transform(0.5, 0.25, 1, 0.75, 0, 1); CREATE_SHARED_STATE(); - CREATE_QUAD_4_NEW( - StreamVideoDrawQuad, opaque_rect, visible_rect, resource_id, matrix); - EXPECT_EQ(resource_id, quad_new->resource_id); + CREATE_QUAD_6_NEW(StreamVideoDrawQuad, opaque_rect, visible_rect, resource_id, + resource_size_in_pixels, allow_overlay, matrix); + EXPECT_EQ(resource_id, quad_new->resource_id()); + EXPECT_EQ(allow_overlay, quad_new->allow_overlay()); + EXPECT_EQ(resource_size_in_pixels, quad_new->resource_size_in_pixels()); EXPECT_EQ(1, IterateAndCount(quad_new)); - EXPECT_EQ(resource_id + 1, quad_new->resource_id); + EXPECT_EQ(resource_id + 1, quad_new->resource_id()); } TEST_F(DrawQuadIteratorTest, SurfaceDrawQuad) { @@ -872,9 +880,9 @@ TEST_F(DrawQuadIteratorTest, TextureDrawQuad) { vertex_opacity, y_flipped, nearest_neighbor); - EXPECT_EQ(resource_id, quad_new->resource_id); + EXPECT_EQ(resource_id, quad_new->resource_id()); EXPECT_EQ(1, IterateAndCount(quad_new)); - EXPECT_EQ(resource_id + 1, quad_new->resource_id); + EXPECT_EQ(resource_id + 1, quad_new->resource_id()); } TEST_F(DrawQuadIteratorTest, TileDrawQuad) { @@ -895,9 +903,9 @@ TEST_F(DrawQuadIteratorTest, TileDrawQuad) { texture_size, swizzle_contents, nearest_neighbor); - EXPECT_EQ(resource_id, quad_new->resource_id); + EXPECT_EQ(resource_id, quad_new->resource_id()); EXPECT_EQ(1, IterateAndCount(quad_new)); - EXPECT_EQ(resource_id + 1, quad_new->resource_id); + EXPECT_EQ(resource_id + 1, quad_new->resource_id()); } TEST_F(DrawQuadIteratorTest, YUVVideoDrawQuad) { @@ -907,10 +915,10 @@ TEST_F(DrawQuadIteratorTest, YUVVideoDrawQuad) { gfx::RectF uv_tex_coord_rect(0.0f, 0.0f, 0.375f, 0.25f); gfx::Size ya_tex_size(32, 68); gfx::Size uv_tex_size(41, 51); - ResourceProvider::ResourceId y_plane_resource_id = 45; - ResourceProvider::ResourceId u_plane_resource_id = 532; - ResourceProvider::ResourceId v_plane_resource_id = 4; - ResourceProvider::ResourceId a_plane_resource_id = 63; + ResourceId y_plane_resource_id = 45; + ResourceId u_plane_resource_id = 532; + ResourceId v_plane_resource_id = 4; + ResourceId a_plane_resource_id = 63; YUVVideoDrawQuad::ColorSpace color_space = YUVVideoDrawQuad::JPEG; CREATE_SHARED_STATE(); @@ -919,16 +927,16 @@ TEST_F(DrawQuadIteratorTest, YUVVideoDrawQuad) { uv_tex_size, y_plane_resource_id, u_plane_resource_id, v_plane_resource_id, a_plane_resource_id, color_space); EXPECT_EQ(DrawQuad::YUV_VIDEO_CONTENT, copy_quad->material); - EXPECT_EQ(y_plane_resource_id, quad_new->y_plane_resource_id); - EXPECT_EQ(u_plane_resource_id, quad_new->u_plane_resource_id); - EXPECT_EQ(v_plane_resource_id, quad_new->v_plane_resource_id); - EXPECT_EQ(a_plane_resource_id, quad_new->a_plane_resource_id); + EXPECT_EQ(y_plane_resource_id, quad_new->y_plane_resource_id()); + EXPECT_EQ(u_plane_resource_id, quad_new->u_plane_resource_id()); + EXPECT_EQ(v_plane_resource_id, quad_new->v_plane_resource_id()); + EXPECT_EQ(a_plane_resource_id, quad_new->a_plane_resource_id()); EXPECT_EQ(color_space, quad_new->color_space); EXPECT_EQ(4, IterateAndCount(quad_new)); - EXPECT_EQ(y_plane_resource_id + 1, quad_new->y_plane_resource_id); - EXPECT_EQ(u_plane_resource_id + 1, quad_new->u_plane_resource_id); - EXPECT_EQ(v_plane_resource_id + 1, quad_new->v_plane_resource_id); - EXPECT_EQ(a_plane_resource_id + 1, quad_new->a_plane_resource_id); + EXPECT_EQ(y_plane_resource_id + 1, quad_new->y_plane_resource_id()); + EXPECT_EQ(u_plane_resource_id + 1, quad_new->u_plane_resource_id()); + EXPECT_EQ(v_plane_resource_id + 1, quad_new->v_plane_resource_id()); + EXPECT_EQ(a_plane_resource_id + 1, quad_new->a_plane_resource_id()); } // Disabled until picture draw quad is supported for ubercomp: crbug.com/231715 diff --git a/chromium/cc/quads/io_surface_draw_quad.cc b/chromium/cc/quads/io_surface_draw_quad.cc index 8a37b0a6f06..0ad70fcc6b8 100644 --- a/chromium/cc/quads/io_surface_draw_quad.cc +++ b/chromium/cc/quads/io_surface_draw_quad.cc @@ -11,9 +11,7 @@ namespace cc { -IOSurfaceDrawQuad::IOSurfaceDrawQuad() - : io_surface_resource_id(0), - orientation(FLIPPED) { +IOSurfaceDrawQuad::IOSurfaceDrawQuad() : orientation(FLIPPED) { } void IOSurfaceDrawQuad::SetNew(const SharedQuadState* shared_quad_state, @@ -27,7 +25,8 @@ void IOSurfaceDrawQuad::SetNew(const SharedQuadState* shared_quad_state, DrawQuad::SetAll(shared_quad_state, DrawQuad::IO_SURFACE_CONTENT, rect, opaque_rect, visible_rect, needs_blending); this->io_surface_size = io_surface_size; - this->io_surface_resource_id = io_surface_resource_id; + resources.ids[kIOSurfaceResourceIdIndex] = io_surface_resource_id; + resources.count = 1; this->orientation = orientation; } @@ -42,15 +41,11 @@ void IOSurfaceDrawQuad::SetAll(const SharedQuadState* shared_quad_state, DrawQuad::SetAll(shared_quad_state, DrawQuad::IO_SURFACE_CONTENT, rect, opaque_rect, visible_rect, needs_blending); this->io_surface_size = io_surface_size; - this->io_surface_resource_id = io_surface_resource_id; + resources.ids[kIOSurfaceResourceIdIndex] = io_surface_resource_id; + resources.count = 1; this->orientation = orientation; } -void IOSurfaceDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) { - io_surface_resource_id = callback.Run(io_surface_resource_id); -} - const IOSurfaceDrawQuad* IOSurfaceDrawQuad::MaterialCast( const DrawQuad* quad) { DCHECK(quad->material == DrawQuad::IO_SURFACE_CONTENT); @@ -61,7 +56,8 @@ void IOSurfaceDrawQuad::ExtendValue( base::trace_event::TracedValue* value) const { MathUtil::AddToTracedValue("io_surface_size", io_surface_size, value); - value->SetInteger("io_surface_resource_id", io_surface_resource_id); + value->SetInteger("io_surface_resource_id", + resources.ids[kIOSurfaceResourceIdIndex]); const char* orientation_string = NULL; switch (orientation) { case FLIPPED: diff --git a/chromium/cc/quads/io_surface_draw_quad.h b/chromium/cc/quads/io_surface_draw_quad.h index 2c77905cd79..4a8a072c61c 100644 --- a/chromium/cc/quads/io_surface_draw_quad.h +++ b/chromium/cc/quads/io_surface_draw_quad.h @@ -40,14 +40,17 @@ class CC_EXPORT IOSurfaceDrawQuad : public DrawQuad { Orientation orientation); gfx::Size io_surface_size; - unsigned io_surface_resource_id; Orientation orientation; - void IterateResources(const ResourceIteratorCallback& callback) override; + ResourceId io_surface_resource_id() const { + return resources.ids[kIOSurfaceResourceIdIndex]; + } static const IOSurfaceDrawQuad* MaterialCast(const DrawQuad*); private: + static const size_t kIOSurfaceResourceIdIndex = 0; + void ExtendValue(base::trace_event::TracedValue* value) const override; }; diff --git a/chromium/cc/quads/list_container.cc b/chromium/cc/quads/list_container.cc deleted file mode 100644 index 4edcbdfab56..00000000000 --- a/chromium/cc/quads/list_container.cc +++ /dev/null @@ -1,720 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/quads/list_container.h" - -#include <algorithm> -#include <vector> - -#include "cc/base/scoped_ptr_vector.h" -#include "cc/playback/display_item.h" -#include "cc/quads/draw_quad.h" -#include "cc/quads/shared_quad_state.h" - -namespace { -const size_t kDefaultNumElementTypesToReserve = 32; -} // namespace - -namespace cc { - -// ListContainerCharAllocator -//////////////////////////////////////////////////// -// This class deals only with char* and void*. It does allocation and passing -// out raw pointers, as well as memory deallocation when being destroyed. -template <typename BaseElementType> -class ListContainer<BaseElementType>::ListContainerCharAllocator { - public: - // ListContainerCharAllocator::InnerList - ///////////////////////////////////////////// - // This class holds the raw memory chunk, as well as information about its - // size and availability. - struct InnerList { - scoped_ptr<char[]> data; - // The number of elements in total the memory can hold. The difference - // between capacity and size is the how many more elements this list can - // hold. - size_t capacity; - // The number of elements have been put into this list. - size_t size; - // The size of each element is in bytes. This is used to move from between - // elements' memory locations. - size_t step; - - InnerList() : capacity(0), size(0), step(0) {} - - void Erase(char* position) { - // Confident that destructor is called by caller of this function. Since - // ListContainerCharAllocator does not handle construction after - // allocation, it doesn't handle desctrution before deallocation. - DCHECK_LE(position, LastElement()); - DCHECK_GE(position, Begin()); - char* start = position + step; - std::copy(start, End(), position); - - --size; - // Decrease capacity to avoid creating not full not last InnerList. - --capacity; - } - - bool IsFull() { return capacity == size; } - size_t NumElementsAvailable() const { return capacity - size; } - - void* AddElement() { - DCHECK_LT(size, capacity); - ++size; - return LastElement(); - } - - char* Begin() const { return data.get(); } - char* End() const { return data.get() + size * step; } - char* LastElement() const { return data.get() + (size - 1) * step; } - char* ElementAt(size_t index) const { return data.get() + index * step; } - - private: - DISALLOW_COPY_AND_ASSIGN(InnerList); - }; - - explicit ListContainerCharAllocator(size_t element_size) - : element_size_(element_size), - size_(0), - list_count_(0), - last_list_(NULL) { - AllocateNewList(kDefaultNumElementTypesToReserve); - } - - ListContainerCharAllocator(size_t element_size, size_t element_count) - : element_size_(element_size), - size_(0), - list_count_(0), - last_list_(NULL) { - AllocateNewList(element_count > 0 ? element_count - : kDefaultNumElementTypesToReserve); - } - - ~ListContainerCharAllocator() {} - - void* Allocate() { - if (last_list_->IsFull()) - AllocateNewList(last_list_->capacity * 2); - - ++size_; - return last_list_->AddElement(); - } - - size_t element_size() const { return element_size_; } - size_t list_count() const { return list_count_; } - size_t size() const { return size_; } - bool IsEmpty() const { return size() == 0; } - - size_t Capacity() const { - size_t capacity_sum = 0; - for (typename ScopedPtrVector<InnerList>::const_iterator iter = - storage_.begin(); - iter != storage_.end(); - ++iter) { - capacity_sum += (*iter)->capacity; - } - return capacity_sum; - } - - void Clear() { - size_t initial_allocation_size = storage_.front()->capacity; - storage_.clear(); - list_count_ = 0; - last_list_ = NULL; - size_ = 0; - AllocateNewList(initial_allocation_size); - } - - void Erase(PositionInListContainerCharAllocator position) { - DCHECK_EQ(this, position.ptr_to_container); - storage_[position.vector_index]->Erase(position.item_iterator); - // TODO(weiliangc): Free the InnerList if it is empty. - --size_; - } - - InnerList* InnerListById(size_t id) const { - DCHECK_LT(id, list_count_); - return storage_[id]; - } - - size_t FirstInnerListId() const { - // |size_| > 0 means that at least one vector in |storage_| will be - // non-empty. - DCHECK_GT(size_, 0u); - size_t id = 0; - while (storage_[id]->size == 0) - ++id; - return id; - } - - size_t LastInnerListId() const { - // |size_| > 0 means that at least one vector in |storage_| will be - // non-empty. - DCHECK_GT(size_, 0u); - size_t id = list_count_ - 1; - while (storage_[id]->size == 0) - --id; - return id; - } - - void AllocateNewList(size_t list_size) { - ++list_count_; - scoped_ptr<InnerList> new_list(new InnerList); - storage_.push_back(new_list.Pass()); - last_list_ = storage_.back(); - InnerList* list = last_list_; - list->capacity = list_size; - list->size = 0; - list->step = element_size_; - list->data.reset(new char[list->capacity * list->step]); - } - - size_t NumAvailableElementsInLastList() const { - return last_list_->NumElementsAvailable(); - } - - private: - ScopedPtrVector<InnerList> storage_; - const size_t element_size_; - size_t size_; - size_t list_count_; - InnerList* last_list_; - - DISALLOW_COPY_AND_ASSIGN(ListContainerCharAllocator); -}; - -// PositionInListContainerCharAllocator -////////////////////////////////////////////////////// -template <typename BaseElementType> -ListContainer<BaseElementType>::PositionInListContainerCharAllocator:: - PositionInListContainerCharAllocator(const typename ListContainer< - BaseElementType>::PositionInListContainerCharAllocator& other) - : ptr_to_container(other.ptr_to_container), - vector_index(other.vector_index), - item_iterator(other.item_iterator) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::PositionInListContainerCharAllocator:: - PositionInListContainerCharAllocator( - typename ListContainer<BaseElementType>::ListContainerCharAllocator* - container, - size_t vector_ind, - char* item_iter) - : ptr_to_container(container), - vector_index(vector_ind), - item_iterator(item_iter) { -} - -template <typename BaseElementType> -bool ListContainer<BaseElementType>::PositionInListContainerCharAllocator:: -operator==(const typename ListContainer< - BaseElementType>::PositionInListContainerCharAllocator& other) const { - DCHECK_EQ(ptr_to_container, other.ptr_to_container); - return vector_index == other.vector_index && - item_iterator == other.item_iterator; -} - -template <typename BaseElementType> -bool ListContainer<BaseElementType>::PositionInListContainerCharAllocator:: -operator!=(const typename ListContainer< - BaseElementType>::PositionInListContainerCharAllocator& other) const { - return !(*this == other); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::PositionInListContainerCharAllocator -ListContainer< - BaseElementType>::PositionInListContainerCharAllocator::Increment() { - typename ListContainerCharAllocator::InnerList* list = - ptr_to_container->InnerListById(vector_index); - if (item_iterator == list->LastElement()) { - ++vector_index; - while (vector_index < ptr_to_container->list_count()) { - if (ptr_to_container->InnerListById(vector_index)->size != 0) - break; - ++vector_index; - } - if (vector_index < ptr_to_container->list_count()) - item_iterator = ptr_to_container->InnerListById(vector_index)->Begin(); - else - item_iterator = NULL; - } else { - item_iterator += list->step; - } - return *this; -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::PositionInListContainerCharAllocator -ListContainer< - BaseElementType>::PositionInListContainerCharAllocator::ReverseIncrement() { - typename ListContainerCharAllocator::InnerList* list = - ptr_to_container->InnerListById(vector_index); - if (item_iterator == list->Begin()) { - --vector_index; - // Since |vector_index| is unsigned, we compare < list_count() instead of - // comparing >= 0, as the variable will wrap around when it goes out of - // range (below 0). - while (vector_index < ptr_to_container->list_count()) { - if (ptr_to_container->InnerListById(vector_index)->size != 0) - break; - --vector_index; - } - if (vector_index < ptr_to_container->list_count()) { - item_iterator = - ptr_to_container->InnerListById(vector_index)->LastElement(); - } else { - item_iterator = NULL; - } - } else { - item_iterator -= list->step; - } - return *this; -} - -// ListContainer -//////////////////////////////////////////// -template <typename BaseElementType> -ListContainer<BaseElementType>::ListContainer(size_t max_size_for_derived_class) - : data_(new ListContainerCharAllocator(max_size_for_derived_class)) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::ListContainer( - size_t max_size_for_derived_class, - size_t num_of_elements_to_reserve_for) - : data_(new ListContainerCharAllocator(max_size_for_derived_class, - num_of_elements_to_reserve_for)) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::ListContainer() - : data_(new ListContainerCharAllocator(sizeof(BaseElementType))) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::~ListContainer() { - for (Iterator i = begin(); i != end(); ++i) { - i->~BaseElementType(); - } -} - -template <typename BaseElementType> -void ListContainer<BaseElementType>::EraseAndInvalidateAllPointers( - typename ListContainer<BaseElementType>::Iterator position) { - BaseElementType* item = *position; - item->~BaseElementType(); - data_->Erase(position); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstReverseIterator -ListContainer<BaseElementType>::crbegin() const { - if (data_->IsEmpty()) - return crend(); - - size_t id = data_->LastInnerListId(); - return ConstReverseIterator(data_.get(), id, - data_->InnerListById(id)->LastElement(), 0); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstReverseIterator -ListContainer<BaseElementType>::crend() const { - return ConstReverseIterator(data_.get(), static_cast<size_t>(-1), NULL, - size()); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstReverseIterator -ListContainer<BaseElementType>::rbegin() const { - return crbegin(); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstReverseIterator -ListContainer<BaseElementType>::rend() const { - return crend(); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ReverseIterator -ListContainer<BaseElementType>::rbegin() { - if (data_->IsEmpty()) - return rend(); - - size_t id = data_->LastInnerListId(); - return ReverseIterator(data_.get(), id, - data_->InnerListById(id)->LastElement(), 0); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ReverseIterator -ListContainer<BaseElementType>::rend() { - return ReverseIterator(data_.get(), static_cast<size_t>(-1), NULL, size()); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstIterator -ListContainer<BaseElementType>::cbegin() const { - if (data_->IsEmpty()) - return cend(); - - size_t id = data_->FirstInnerListId(); - return ConstIterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstIterator -ListContainer<BaseElementType>::cend() const { - if (data_->IsEmpty()) - return ConstIterator(data_.get(), 0, NULL, size()); - - size_t id = data_->list_count(); - return ConstIterator(data_.get(), id, NULL, size()); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstIterator -ListContainer<BaseElementType>::begin() const { - return cbegin(); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstIterator -ListContainer<BaseElementType>::end() const { - return cend(); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::Iterator -ListContainer<BaseElementType>::begin() { - if (data_->IsEmpty()) - return end(); - - size_t id = data_->FirstInnerListId(); - return Iterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::Iterator -ListContainer<BaseElementType>::end() { - if (data_->IsEmpty()) - return Iterator(data_.get(), 0, NULL, size()); - - size_t id = data_->list_count(); - return Iterator(data_.get(), id, NULL, size()); -} - -template <typename BaseElementType> -BaseElementType* ListContainer<BaseElementType>::front() { - Iterator iter = begin(); - return *iter; -} - -template <typename BaseElementType> -BaseElementType* ListContainer<BaseElementType>::back() { - ReverseIterator iter = rbegin(); - return *iter; -} - -template <typename BaseElementType> -const BaseElementType* ListContainer<BaseElementType>::front() const { - ConstIterator iter = begin(); - return *iter; -} - -template <typename BaseElementType> -const BaseElementType* ListContainer<BaseElementType>::back() const { - ConstReverseIterator iter = rbegin(); - return *iter; -} - -template <typename BaseElementType> -const BaseElementType* ListContainer<BaseElementType>::ElementAt( - size_t index) const { - DCHECK_LT(index, size()); - size_t original_index = index; - size_t list_index; - for (list_index = 0; list_index < data_->list_count(); ++list_index) { - size_t current_size = data_->InnerListById(list_index)->size; - if (index < current_size) - break; - index -= current_size; - } - return *ConstIterator(data_.get(), - list_index, - data_->InnerListById(list_index)->ElementAt(index), - original_index); -} - -template <typename BaseElementType> -BaseElementType* ListContainer<BaseElementType>::ElementAt(size_t index) { - DCHECK_LT(index, size()); - size_t original_index = index; - size_t list_index; - for (list_index = 0; list_index < data_->list_count(); ++list_index) { - size_t current_size = data_->InnerListById(list_index)->size; - if (index < current_size) - break; - index -= current_size; - } - return *Iterator(data_.get(), - list_index, - data_->InnerListById(list_index)->ElementAt(index), - original_index); -} - -template <typename BaseElementType> -void* ListContainer<BaseElementType>::Allocate( - size_t size_of_actual_element_in_bytes) { - DCHECK_LE(size_of_actual_element_in_bytes, data_->element_size()); - return data_->Allocate(); -} - -template <typename BaseElementType> -size_t ListContainer<BaseElementType>::size() const { - return data_->size(); -} - -template <typename BaseElementType> -bool ListContainer<BaseElementType>::empty() const { - return data_->IsEmpty(); -} - -template <typename BaseElementType> -void ListContainer<BaseElementType>::clear() { - for (Iterator i = begin(); i != end(); ++i) { - i->~BaseElementType(); - } - data_->Clear(); -} - -template <typename BaseElementType> -size_t ListContainer< - BaseElementType>::AvailableSizeWithoutAnotherAllocationForTesting() const { - return data_->NumAvailableElementsInLastList(); -} - -// ListContainer::Iterator -///////////////////////////////////////////////// -template <typename BaseElementType> -ListContainer<BaseElementType>::Iterator::Iterator( - ListContainerCharAllocator* container, - size_t vector_ind, - char* item_iter, - size_t index) - : PositionInListContainerCharAllocator(container, vector_ind, item_iter), - index_(index) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::Iterator::~Iterator() { -} - -template <typename BaseElementType> -BaseElementType* ListContainer<BaseElementType>::Iterator::operator->() const { - return reinterpret_cast<BaseElementType*>(this->item_iterator); -} - -template <typename BaseElementType> -BaseElementType* ListContainer<BaseElementType>::Iterator::operator*() const { - return reinterpret_cast<BaseElementType*>(this->item_iterator); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::Iterator -ListContainer<BaseElementType>::Iterator:: -operator++(int unused_post_increment) { - Iterator tmp = *this; - operator++(); - return tmp; -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::Iterator& - ListContainer<BaseElementType>::Iterator:: - operator++() { - this->Increment(); - ++index_; - return *this; -} - -template <typename BaseElementType> -size_t ListContainer<BaseElementType>::Iterator::index() const { - return index_; -} - -// ListContainer::ConstIterator -///////////////////////////////////////////////// -template <typename BaseElementType> -ListContainer<BaseElementType>::ConstIterator::ConstIterator( - const typename ListContainer<BaseElementType>::Iterator& other) - : PositionInListContainerCharAllocator(other), index_(other.index()) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::ConstIterator::ConstIterator( - ListContainerCharAllocator* container, - size_t vector_ind, - char* item_iter, - size_t index) - : PositionInListContainerCharAllocator(container, vector_ind, item_iter), - index_(index) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::ConstIterator::~ConstIterator() { -} - -template <typename BaseElementType> -const BaseElementType* ListContainer<BaseElementType>::ConstIterator:: -operator->() const { - return reinterpret_cast<const BaseElementType*>(this->item_iterator); -} - -template <typename BaseElementType> -const BaseElementType* ListContainer<BaseElementType>::ConstIterator:: -operator*() const { - return reinterpret_cast<const BaseElementType*>(this->item_iterator); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstIterator -ListContainer<BaseElementType>::ConstIterator:: -operator++(int unused_post_increment) { - ConstIterator tmp = *this; - operator++(); - return tmp; -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstIterator& - ListContainer<BaseElementType>::ConstIterator:: - operator++() { - this->Increment(); - ++index_; - return *this; -} - -template <typename BaseElementType> -size_t ListContainer<BaseElementType>::ConstIterator::index() const { - return index_; -} - -// ListContainer::ReverseIterator -///////////////////////////////////////////////// -template <typename BaseElementType> -ListContainer<BaseElementType>::ReverseIterator::ReverseIterator( - ListContainerCharAllocator* container, - size_t vector_ind, - char* item_iter, - size_t index) - : PositionInListContainerCharAllocator(container, vector_ind, item_iter), - index_(index) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::ReverseIterator::~ReverseIterator() { -} - -template <typename BaseElementType> -BaseElementType* ListContainer<BaseElementType>::ReverseIterator::operator->() - const { - return reinterpret_cast<BaseElementType*>(this->item_iterator); -} - -template <typename BaseElementType> -BaseElementType* ListContainer<BaseElementType>::ReverseIterator::operator*() - const { - return reinterpret_cast<BaseElementType*>(this->item_iterator); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ReverseIterator -ListContainer<BaseElementType>::ReverseIterator:: -operator++(int unused_post_increment) { - ReverseIterator tmp = *this; - operator++(); - return tmp; -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ReverseIterator& - ListContainer<BaseElementType>::ReverseIterator:: - operator++() { - this->ReverseIncrement(); - ++index_; - return *this; -} - -template <typename BaseElementType> -size_t ListContainer<BaseElementType>::ReverseIterator::index() const { - return index_; -} - -// ListContainer::ConstReverseIterator -///////////////////////////////////////////////// -template <typename BaseElementType> -ListContainer<BaseElementType>::ConstReverseIterator::ConstReverseIterator( - const typename ListContainer<BaseElementType>::ReverseIterator& other) - : PositionInListContainerCharAllocator(other), index_(other.index()) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::ConstReverseIterator::ConstReverseIterator( - ListContainerCharAllocator* container, - size_t vector_ind, - char* item_iter, - size_t index) - : PositionInListContainerCharAllocator(container, vector_ind, item_iter), - index_(index) { -} - -template <typename BaseElementType> -ListContainer<BaseElementType>::ConstReverseIterator::~ConstReverseIterator() { -} - -template <typename BaseElementType> -const BaseElementType* ListContainer<BaseElementType>::ConstReverseIterator:: -operator->() const { - return reinterpret_cast<const BaseElementType*>(this->item_iterator); -} - -template <typename BaseElementType> -const BaseElementType* ListContainer<BaseElementType>::ConstReverseIterator:: -operator*() const { - return reinterpret_cast<const BaseElementType*>(this->item_iterator); -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstReverseIterator -ListContainer<BaseElementType>::ConstReverseIterator:: -operator++(int unused_post_increment) { - ConstReverseIterator tmp = *this; - operator++(); - return tmp; -} - -template <typename BaseElementType> -typename ListContainer<BaseElementType>::ConstReverseIterator& - ListContainer<BaseElementType>::ConstReverseIterator:: - operator++() { - this->ReverseIncrement(); - ++index_; - return *this; -} - -template <typename BaseElementType> -size_t ListContainer<BaseElementType>::ConstReverseIterator::index() const { - return index_; -} - -template class ListContainer<SharedQuadState>; -template class ListContainer<DrawQuad>; -template class ListContainer<DisplayItem>; - -} // namespace cc diff --git a/chromium/cc/quads/list_container.h b/chromium/cc/quads/list_container.h deleted file mode 100644 index 8abc33d62eb..00000000000 --- a/chromium/cc/quads/list_container.h +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_QUADS_LIST_CONTAINER_H_ -#define CC_QUADS_LIST_CONTAINER_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "cc/base/cc_export.h" - -namespace cc { -class DisplayItem; -class DrawQuad; -class SharedQuadState; - -// This class is a container type that handles allocating contiguous memory for -// new elements and traversing through elements with either iterator or reverse -// iterator. Since this container hands out raw pointers of its elements, it is -// very important that this container never reallocate its memory so those raw -// pointer will continue to be valid. This class is used to contain -// SharedQuadState or DrawQuad. Since the size of each DrawQuad varies, to hold -// DrawQuads, the allocations size of each element in this class is -// LargestDrawQuadSize while BaseElementType is DrawQuad. -template <class BaseElementType> -class CC_EXPORT ListContainer { - public: - // BaseElementType is the type of raw pointers this class hands out; however, - // its derived classes might require different memory sizes. - // max_size_for_derived_class the largest memory size required for all the - // derived classes to use for allocation. - explicit ListContainer(size_t max_size_for_derived_class); - // This constructor omits input variable for max_size_for_derived_class. This - // is used when there is no derived classes from BaseElementType we need to - // worry about, and allocation size is just sizeof(BaseElementType). - ListContainer(); - // This constructor reserves the requested memory up front so only single - // allocation is needed. When num_of_elements_to_reserve_for is zero, use the - // default size. - ListContainer(size_t max_size_for_derived_class, - size_t num_of_elements_to_reserve_for); - - ~ListContainer(); - - // This class deals only with char* and void*. It does allocation and passing - // out raw pointers, as well as memory deallocation when being destroyed. - class CC_EXPORT ListContainerCharAllocator; - - // This class points to a certain position inside memory of - // ListContainerCharAllocator. It is a base class for ListContainer iterators. - struct CC_EXPORT PositionInListContainerCharAllocator { - ListContainerCharAllocator* ptr_to_container; - size_t vector_index; - char* item_iterator; - - PositionInListContainerCharAllocator( - const PositionInListContainerCharAllocator& other); - - PositionInListContainerCharAllocator(ListContainerCharAllocator* container, - size_t vector_ind, - char* item_iter); - - bool operator==(const PositionInListContainerCharAllocator& other) const; - bool operator!=(const PositionInListContainerCharAllocator& other) const; - - PositionInListContainerCharAllocator Increment(); - PositionInListContainerCharAllocator ReverseIncrement(); - }; - - // Iterator classes that can be used to access data. - ///////////////////////////////////////////////////////////////// - class CC_EXPORT Iterator : public PositionInListContainerCharAllocator { - // This class is only defined to forward iterate through - // ListContainerCharAllocator. - public: - Iterator(ListContainerCharAllocator* container, - size_t vector_ind, - char* item_iter, - size_t index); - ~Iterator(); - BaseElementType* operator->() const; - BaseElementType* operator*() const; - Iterator operator++(int unused_post_increment); - Iterator& operator++(); - - size_t index() const; - - private: - // This is used to track how many increment has happened since begin(). It - // is used to avoid double increment at places an index reference is - // needed. For iterator this means begin() corresponds to index 0 and end() - // corresponds to index |size|. - size_t index_; - }; - - class CC_EXPORT ConstIterator : public PositionInListContainerCharAllocator { - // This class is only defined to forward iterate through - // ListContainerCharAllocator. - public: - ConstIterator(ListContainerCharAllocator* container, - size_t vector_ind, - char* item_iter, - size_t index); - ConstIterator(const Iterator& other); // NOLINT - ~ConstIterator(); - const BaseElementType* operator->() const; - const BaseElementType* operator*() const; - ConstIterator operator++(int unused_post_increment); - ConstIterator& operator++(); - - size_t index() const; - - private: - // This is used to track how many increment has happened since begin(). It - // is used to avoid double increment at places an index reference is - // needed. For iterator this means begin() corresponds to index 0 and end() - // corresponds to index |size|. - size_t index_; - }; - - class CC_EXPORT ReverseIterator - : public PositionInListContainerCharAllocator { - // This class is only defined to reverse iterate through - // ListContainerCharAllocator. - public: - ReverseIterator(ListContainerCharAllocator* container, - size_t vector_ind, - char* item_iter, - size_t index); - ~ReverseIterator(); - BaseElementType* operator->() const; - BaseElementType* operator*() const; - ReverseIterator operator++(int unused_post_increment); - ReverseIterator& operator++(); - - size_t index() const; - - private: - // This is used to track how many increment has happened since rbegin(). It - // is used to avoid double increment at places an index reference is - // needed. For reverse iterator this means rbegin() corresponds to index 0 - // and rend() corresponds to index |size|. - size_t index_; - }; - - class CC_EXPORT ConstReverseIterator - : public PositionInListContainerCharAllocator { - // This class is only defined to reverse iterate through - // ListContainerCharAllocator. - public: - ConstReverseIterator(ListContainerCharAllocator* container, - size_t vector_ind, - char* item_iter, - size_t index); - ConstReverseIterator(const ReverseIterator& other); // NOLINT - ~ConstReverseIterator(); - const BaseElementType* operator->() const; - const BaseElementType* operator*() const; - ConstReverseIterator operator++(int unused_post_increment); - ConstReverseIterator& operator++(); - - size_t index() const; - - private: - // This is used to track how many increment has happened since rbegin(). It - // is used to avoid double increment at places an index reference is - // needed. For reverse iterator this means rbegin() corresponds to index 0 - // and rend() corresponds to index |size|. - size_t index_; - }; - - // When called, all raw pointers that have been handed out are no longer - // valid. Use with caution. - // This function does not deallocate memory. - void EraseAndInvalidateAllPointers(Iterator position); - - ConstReverseIterator crbegin() const; - ConstReverseIterator crend() const; - ConstReverseIterator rbegin() const; - ConstReverseIterator rend() const; - ReverseIterator rbegin(); - ReverseIterator rend(); - ConstIterator cbegin() const; - ConstIterator cend() const; - ConstIterator begin() const; - ConstIterator end() const; - Iterator begin(); - Iterator end(); - - // TODO(weiliangc): front(), back() and ElementAt() function should return - // reference, consistent with container-of-object. - BaseElementType* front(); - BaseElementType* back(); - const BaseElementType* front() const; - const BaseElementType* back() const; - - BaseElementType* ElementAt(size_t index); - const BaseElementType* ElementAt(size_t index) const; - - // Take in derived element type and construct it at location generated by - // Allocate(). - template <typename DerivedElementType> - DerivedElementType* AllocateAndConstruct() { - return new (Allocate(sizeof(DerivedElementType))) DerivedElementType; - } - // Take in derived element type and copy construct it at location generated by - // Allocate(). - template <typename DerivedElementType> - DerivedElementType* AllocateAndCopyFrom(const DerivedElementType* source) { - return new (Allocate(sizeof(DerivedElementType))) - DerivedElementType(*source); - } - // Construct a new element on top of an existing one. - template <typename DerivedElementType> - DerivedElementType* ReplaceExistingElement(Iterator at) { - at->~BaseElementType(); - return new (*at) DerivedElementType(); - } - - size_t size() const; - bool empty() const; - void clear(); - - size_t AvailableSizeWithoutAnotherAllocationForTesting() const; - - private: - // Hands out memory location for an element at the end of data structure. - void* Allocate(size_t size_of_actual_element_in_bytes); - - scoped_ptr<ListContainerCharAllocator> data_; - - DISALLOW_COPY_AND_ASSIGN(ListContainer); -}; - -#if !defined(COMPILER_MSVC) -extern template class ListContainer<SharedQuadState>; -extern template class ListContainer<DrawQuad>; -extern template class ListContainer<DisplayItem>; -#endif -} // namespace cc - -#endif // CC_QUADS_LIST_CONTAINER_H_ diff --git a/chromium/cc/quads/list_container_unittest.cc b/chromium/cc/quads/list_container_unittest.cc deleted file mode 100644 index 5de1ddd1941..00000000000 --- a/chromium/cc/quads/list_container_unittest.cc +++ /dev/null @@ -1,667 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/quads/list_container.h" - -#include <vector> -#include "cc/quads/draw_quad.h" -#include "cc/quads/largest_draw_quad.h" -#include "cc/quads/render_pass_draw_quad.h" -#include "cc/quads/shared_quad_state.h" -#include "cc/quads/stream_video_draw_quad.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace cc { -namespace { - -int kMagicNumberToUseForDrawQuadOne = 42; -int kMagicNumberToUseForDrawQuadTwo = 314; - -bool isConstSharedQuadStatePointer(const SharedQuadState* ptr) { - return true; -} - -bool isConstSharedQuadStatePointer(SharedQuadState* ptr) { - return false; -} - -class SimpleDrawQuad : public DrawQuad { - public: - ~SimpleDrawQuad() override {} - void IterateResources(const ResourceIteratorCallback& callback) override {} - - void set_value(int val) { value = val; } - int get_value() { return value; } - void ExtendValue(base::trace_event::TracedValue* value) const override {} - - private: - int value; -}; - -class SimpleDrawQuadConstructMagicNumberOne : public SimpleDrawQuad { - public: - SimpleDrawQuadConstructMagicNumberOne() : SimpleDrawQuad() { - set_value(kMagicNumberToUseForDrawQuadOne); - } -}; - -class SimpleDrawQuadConstructMagicNumberTwo : public SimpleDrawQuad { - public: - SimpleDrawQuadConstructMagicNumberTwo() : SimpleDrawQuad() { - set_value(kMagicNumberToUseForDrawQuadTwo); - } -}; - -class MockDrawQuad : public SimpleDrawQuadConstructMagicNumberOne { - public: - ~MockDrawQuad() override { Destruct(); } - MOCK_METHOD0(Destruct, void()); -}; - -class MockDrawQuadSubclass : public MockDrawQuad { - public: - MockDrawQuadSubclass() { set_value(kMagicNumberToUseForDrawQuadTwo); } -}; - -const size_t kLargestQuadSize = - std::max(LargestDrawQuadSize(), sizeof(MockDrawQuadSubclass)); - -TEST(ListContainerTest, ConstructorCalledInAllocateAndConstruct) { - ListContainer<DrawQuad> list(kLargestQuadSize); - - size_t size = 2; - SimpleDrawQuadConstructMagicNumberOne* dq_1 = - list.AllocateAndConstruct<SimpleDrawQuadConstructMagicNumberOne>(); - SimpleDrawQuadConstructMagicNumberTwo* dq_2 = - list.AllocateAndConstruct<SimpleDrawQuadConstructMagicNumberTwo>(); - - EXPECT_EQ(size, list.size()); - EXPECT_EQ(dq_1, list.front()); - EXPECT_EQ(dq_2, list.back()); - - EXPECT_EQ(kMagicNumberToUseForDrawQuadOne, dq_1->get_value()); - EXPECT_EQ(kMagicNumberToUseForDrawQuadTwo, dq_2->get_value()); -} - -TEST(ListContainerTest, DestructorCalled) { - ListContainer<DrawQuad> list(kLargestQuadSize); - - size_t size = 1; - MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>(); - - EXPECT_CALL(*dq_1, Destruct()); - EXPECT_EQ(size, list.size()); - EXPECT_EQ(dq_1, list.front()); -} - -TEST(ListContainerTest, DestructorCalledOnceWhenClear) { - ListContainer<DrawQuad> list(kLargestQuadSize); - size_t size = 1; - MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>(); - - EXPECT_EQ(size, list.size()); - EXPECT_EQ(dq_1, list.front()); - - // Make sure destructor is called once during clear, and won't be called - // again. - testing::MockFunction<void()> separator; - { - testing::InSequence s; - EXPECT_CALL(*dq_1, Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(*dq_1, Destruct()).Times(0); - } - - list.clear(); - separator.Call(); -} - -TEST(ListContainerTest, ReplaceExistingElement) { - ListContainer<DrawQuad> list(kLargestQuadSize); - size_t size = 1; - MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>(); - - EXPECT_EQ(size, list.size()); - EXPECT_EQ(dq_1, list.front()); - - // Make sure destructor is called once during clear, and won't be called - // again. - testing::MockFunction<void()> separator; - { - testing::InSequence s; - EXPECT_CALL(*dq_1, Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(*dq_1, Destruct()).Times(0); - } - - list.ReplaceExistingElement<MockDrawQuadSubclass>(list.begin()); - EXPECT_EQ(kMagicNumberToUseForDrawQuadTwo, dq_1->get_value()); - separator.Call(); - - EXPECT_CALL(*dq_1, Destruct()); - list.clear(); -} - -TEST(ListContainerTest, DestructorCalledOnceWhenErase) { - ListContainer<DrawQuad> list(kLargestQuadSize); - size_t size = 1; - MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>(); - - EXPECT_EQ(size, list.size()); - EXPECT_EQ(dq_1, list.front()); - - // Make sure destructor is called once during clear, and won't be called - // again. - testing::MockFunction<void()> separator; - { - testing::InSequence s; - EXPECT_CALL(*dq_1, Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(*dq_1, Destruct()).Times(0); - } - - list.EraseAndInvalidateAllPointers(list.begin()); - separator.Call(); -} - -TEST(ListContainerTest, SimpleIndexAccessSharedQuadState) { - ListContainer<SharedQuadState> list; - - size_t size = 3; - SharedQuadState* sqs_1 = list.AllocateAndConstruct<SharedQuadState>(); - SharedQuadState* sqs_2 = list.AllocateAndConstruct<SharedQuadState>(); - SharedQuadState* sqs_3 = list.AllocateAndConstruct<SharedQuadState>(); - - EXPECT_EQ(size, list.size()); - EXPECT_EQ(sqs_1, list.front()); - EXPECT_EQ(sqs_3, list.back()); - EXPECT_EQ(list.front(), list.ElementAt(0)); - EXPECT_EQ(sqs_2, list.ElementAt(1)); - EXPECT_EQ(list.back(), list.ElementAt(2)); -} - -TEST(ListContainerTest, SimpleInsertionSharedQuadState) { - ListContainer<SharedQuadState> list; - - size_t size = 3; - SharedQuadState* sqs_1 = list.AllocateAndConstruct<SharedQuadState>(); - list.AllocateAndConstruct<SharedQuadState>(); - SharedQuadState* sqs_3 = list.AllocateAndConstruct<SharedQuadState>(); - - EXPECT_EQ(size, list.size()); - EXPECT_EQ(sqs_1, list.front()); - EXPECT_EQ(sqs_3, list.back()); -} - -TEST(ListContainerTest, SimpleInsertionAndClearSharedQuadState) { - ListContainer<SharedQuadState> list; - EXPECT_TRUE(list.empty()); - EXPECT_EQ(0u, list.size()); - - size_t size = 3; - SharedQuadState* sqs_1 = list.AllocateAndConstruct<SharedQuadState>(); - list.AllocateAndConstruct<SharedQuadState>(); - SharedQuadState* sqs_3 = list.AllocateAndConstruct<SharedQuadState>(); - - EXPECT_EQ(size, list.size()); - EXPECT_EQ(sqs_1, list.front()); - EXPECT_EQ(sqs_3, list.back()); - EXPECT_FALSE(list.empty()); - - list.clear(); - EXPECT_TRUE(list.empty()); - EXPECT_EQ(0u, list.size()); -} - -TEST(ListContainerTest, SimpleInsertionClearAndInsertAgainSharedQuadState) { - ListContainer<SharedQuadState> list; - EXPECT_TRUE(list.empty()); - EXPECT_EQ(0u, list.size()); - - size_t size = 2; - SharedQuadState* sqs_front = list.AllocateAndConstruct<SharedQuadState>(); - SharedQuadState* sqs_back = list.AllocateAndConstruct<SharedQuadState>(); - - EXPECT_EQ(size, list.size()); - EXPECT_EQ(sqs_front, list.front()); - EXPECT_EQ(sqs_back, list.back()); - EXPECT_FALSE(list.empty()); - - list.clear(); - EXPECT_TRUE(list.empty()); - EXPECT_EQ(0u, list.size()); - - size = 3; - sqs_front = list.AllocateAndConstruct<SharedQuadState>(); - list.AllocateAndConstruct<SharedQuadState>(); - sqs_back = list.AllocateAndConstruct<SharedQuadState>(); - - EXPECT_EQ(size, list.size()); - EXPECT_EQ(sqs_front, list.front()); - EXPECT_EQ(sqs_back, list.back()); - EXPECT_FALSE(list.empty()); -} - -// This test is used to test when there is more than one allocation needed -// for, ListContainer can still perform like normal vector. -TEST(ListContainerTest, - SimpleInsertionTriggerMoreThanOneAllocationSharedQuadState) { - ListContainer<SharedQuadState> list(sizeof(SharedQuadState), 2); - std::vector<SharedQuadState*> sqs_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>()); - } - EXPECT_EQ(size, list.size()); - - ListContainer<SharedQuadState>::Iterator iter = list.begin(); - for (std::vector<SharedQuadState*>::const_iterator sqs_iter = - sqs_list.begin(); - sqs_iter != sqs_list.end(); - ++sqs_iter) { - EXPECT_EQ(*sqs_iter, *iter); - ++iter; - } -} - -TEST(ListContainerTest, - CorrectAllocationSizeForMoreThanOneAllocationSharedQuadState) { - // Constructor sets the allocation size to 2. Every time ListContainer needs - // to allocate again, it doubles allocation size. In this test, 10 elements is - // needed, thus ListContainerShould allocate spaces 2, 4 and 8 elements. - ListContainer<SharedQuadState> list(sizeof(SharedQuadState), 2); - std::vector<SharedQuadState*> sqs_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - // Before asking for a new element, space available without another - // allocation follows. - switch (i) { - case 2: - case 6: - EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 1: - case 5: - EXPECT_EQ(1u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 0: - case 4: - EXPECT_EQ(2u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 3: - EXPECT_EQ(3u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 9: - EXPECT_EQ(5u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 8: - EXPECT_EQ(6u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 7: - EXPECT_EQ(7u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - default: - break; - } - sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>()); - // After asking for a new element, space available without another - // allocation follows. - switch (i) { - case 1: - case 5: - EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 0: - case 4: - EXPECT_EQ(1u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 3: - EXPECT_EQ(2u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 2: - EXPECT_EQ(3u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 9: - EXPECT_EQ(4u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 8: - EXPECT_EQ(5u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 7: - EXPECT_EQ(6u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - case 6: - EXPECT_EQ(7u, list.AvailableSizeWithoutAnotherAllocationForTesting()); - break; - default: - break; - } - } - EXPECT_EQ(size, list.size()); - - ListContainer<SharedQuadState>::Iterator iter = list.begin(); - for (std::vector<SharedQuadState*>::const_iterator sqs_iter = - sqs_list.begin(); - sqs_iter != sqs_list.end(); - ++sqs_iter) { - EXPECT_EQ(*sqs_iter, *iter); - ++iter; - } -} - -TEST(ListContainerTest, SimpleIterationSharedQuadState) { - ListContainer<SharedQuadState> list; - std::vector<SharedQuadState*> sqs_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>()); - } - EXPECT_EQ(size, list.size()); - - size_t num_iters_in_list = 0; - { - std::vector<SharedQuadState*>::const_iterator sqs_iter = sqs_list.begin(); - for (ListContainer<SharedQuadState>::Iterator iter = list.begin(); - iter != list.end(); - ++iter) { - EXPECT_EQ(*sqs_iter, *iter); - ++num_iters_in_list; - ++sqs_iter; - } - } - - size_t num_iters_in_vector = 0; - { - ListContainer<SharedQuadState>::Iterator iter = list.begin(); - for (std::vector<SharedQuadState*>::const_iterator sqs_iter = - sqs_list.begin(); - sqs_iter != sqs_list.end(); - ++sqs_iter) { - EXPECT_EQ(*sqs_iter, *iter); - ++num_iters_in_vector; - ++iter; - } - } - - EXPECT_EQ(num_iters_in_vector, num_iters_in_list); -} - -TEST(ListContainerTest, SimpleConstIteratorIterationSharedQuadState) { - ListContainer<SharedQuadState> list; - std::vector<const SharedQuadState*> sqs_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>()); - } - EXPECT_EQ(size, list.size()); - - { - std::vector<const SharedQuadState*>::const_iterator sqs_iter = - sqs_list.begin(); - for (ListContainer<SharedQuadState>::ConstIterator iter = list.begin(); - iter != list.end(); - ++iter) { - EXPECT_TRUE(isConstSharedQuadStatePointer(*iter)); - EXPECT_EQ(*sqs_iter, *iter); - ++sqs_iter; - } - } - - { - std::vector<const SharedQuadState*>::const_iterator sqs_iter = - sqs_list.begin(); - for (ListContainer<SharedQuadState>::Iterator iter = list.begin(); - iter != list.end(); - ++iter) { - EXPECT_FALSE(isConstSharedQuadStatePointer(*iter)); - EXPECT_EQ(*sqs_iter, *iter); - ++sqs_iter; - } - } - - { - ListContainer<SharedQuadState>::ConstIterator iter = list.begin(); - for (std::vector<const SharedQuadState*>::const_iterator sqs_iter = - sqs_list.begin(); - sqs_iter != sqs_list.end(); - ++sqs_iter) { - EXPECT_EQ(*sqs_iter, *iter); - ++iter; - } - } -} - -TEST(ListContainerTest, SimpleReverseInsertionSharedQuadState) { - ListContainer<SharedQuadState> list; - std::vector<SharedQuadState*> sqs_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>()); - } - EXPECT_EQ(size, list.size()); - - { - std::vector<SharedQuadState*>::const_reverse_iterator sqs_iter = - sqs_list.rbegin(); - for (ListContainer<SharedQuadState>::ReverseIterator iter = list.rbegin(); - iter != list.rend(); - ++iter) { - EXPECT_EQ(*sqs_iter, *iter); - ++sqs_iter; - } - } - - { - ListContainer<SharedQuadState>::ReverseIterator iter = list.rbegin(); - for (std::vector<SharedQuadState*>::reverse_iterator sqs_iter = - sqs_list.rbegin(); - sqs_iter != sqs_list.rend(); - ++sqs_iter) { - EXPECT_EQ(*sqs_iter, *iter); - ++iter; - } - } -} - -TEST(ListContainerTest, SimpleDeletion) { - ListContainer<DrawQuad> list(kLargestQuadSize); - std::vector<SimpleDrawQuad*> sdq_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - sdq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>()); - sdq_list.back()->set_value(i); - } - EXPECT_EQ(size, list.size()); - - list.EraseAndInvalidateAllPointers(list.begin()); - --size; - EXPECT_EQ(size, list.size()); - int i = 1; - for (ListContainer<DrawQuad>::Iterator iter = list.begin(); - iter != list.end(); - ++iter) { - EXPECT_EQ(i, static_cast<SimpleDrawQuad*>(*iter)->get_value()); - ++i; - } -} - -TEST(ListContainerTest, DeletionAllInAllocation) { - const size_t kReserve = 10; - ListContainer<DrawQuad> list(kLargestQuadSize, kReserve); - std::vector<SimpleDrawQuad*> sdq_list; - // Add enough quads to cause another allocation. - for (size_t i = 0; i < kReserve + 1; ++i) { - sdq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>()); - sdq_list.back()->set_value(static_cast<int>(i)); - } - EXPECT_EQ(kReserve + 1, list.size()); - - // Remove everything in the first allocation. - for (size_t i = 0; i < kReserve; ++i) - list.EraseAndInvalidateAllPointers(list.begin()); - EXPECT_EQ(1u, list.size()); - - // The last quad is left. - SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*list.begin()); - EXPECT_EQ(static_cast<int>(kReserve), quad->get_value()); - - // Remove the quad from the 2nd allocation. - list.EraseAndInvalidateAllPointers(list.begin()); - EXPECT_EQ(0u, list.size()); -} - -TEST(ListContainerTest, DeletionAllInAllocationReversed) { - const size_t kReserve = 10; - ListContainer<DrawQuad> list(kLargestQuadSize, kReserve); - std::vector<SimpleDrawQuad*> sdq_list; - // Add enough quads to cause another allocation. - for (size_t i = 0; i < kReserve + 1; ++i) { - sdq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>()); - sdq_list.back()->set_value(static_cast<int>(i)); - } - EXPECT_EQ(kReserve + 1, list.size()); - - // Remove everything in the 2nd allocation. - auto it = list.begin(); - for (size_t i = 0; i < kReserve; ++i) - ++it; - list.EraseAndInvalidateAllPointers(it); - - // The 2nd-last quad is next, and the rest of the quads exist. - size_t i = kReserve - 1; - for (auto it = list.rbegin(); it != list.rend(); ++it) { - SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*it); - EXPECT_EQ(static_cast<int>(i), quad->get_value()); - --i; - } - - // Can forward iterate too. - i = 0; - for (auto it = list.begin(); it != list.end(); ++it) { - SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*it); - EXPECT_EQ(static_cast<int>(i), quad->get_value()); - ++i; - } - - // Remove the last thing from the 1st allocation. - it = list.begin(); - for (size_t i = 0; i < kReserve - 1; ++i) - ++it; - list.EraseAndInvalidateAllPointers(it); - - // The 2nd-last quad is next, and the rest of the quads exist. - i = kReserve - 2; - for (auto it = list.rbegin(); it != list.rend(); ++it) { - SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*it); - EXPECT_EQ(static_cast<int>(i), quad->get_value()); - --i; - } - - // Can forward iterate too. - i = 0; - for (auto it = list.begin(); it != list.end(); ++it) { - SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*it); - EXPECT_EQ(static_cast<int>(i), quad->get_value()); - ++i; - } -} - -TEST(ListContainerTest, SimpleIterationAndManipulation) { - ListContainer<DrawQuad> list(kLargestQuadSize); - std::vector<SimpleDrawQuad*> sdq_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - SimpleDrawQuad* simple_dq = list.AllocateAndConstruct<SimpleDrawQuad>(); - sdq_list.push_back(simple_dq); - } - EXPECT_EQ(size, list.size()); - - ListContainer<DrawQuad>::Iterator iter = list.begin(); - for (int i = 0; i < 10; ++i) { - static_cast<SimpleDrawQuad*>(*iter)->set_value(i); - ++iter; - } - - int i = 0; - for (std::vector<SimpleDrawQuad*>::const_iterator sdq_iter = sdq_list.begin(); - sdq_iter < sdq_list.end(); - ++sdq_iter) { - EXPECT_EQ(i, (*sdq_iter)->get_value()); - ++i; - } -} - -TEST(ListContainerTest, SimpleManipulationWithIndexSimpleDrawQuad) { - ListContainer<DrawQuad> list(kLargestQuadSize); - std::vector<SimpleDrawQuad*> dq_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - dq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>()); - } - EXPECT_EQ(size, list.size()); - - for (size_t i = 0; i < size; ++i) { - static_cast<SimpleDrawQuad*>(list.ElementAt(i))->set_value(i); - } - - int i = 0; - for (std::vector<SimpleDrawQuad*>::const_iterator dq_iter = dq_list.begin(); - dq_iter != dq_list.end(); - ++dq_iter, ++i) { - EXPECT_EQ(i, (*dq_iter)->get_value()); - } -} - -TEST(ListContainerTest, - SimpleManipulationWithIndexMoreThanOneAllocationSimpleDrawQuad) { - ListContainer<DrawQuad> list(LargestDrawQuadSize(), 2); - std::vector<SimpleDrawQuad*> dq_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - dq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>()); - } - EXPECT_EQ(size, list.size()); - - for (size_t i = 0; i < size; ++i) { - static_cast<SimpleDrawQuad*>(list.ElementAt(i))->set_value(i); - } - - int i = 0; - for (std::vector<SimpleDrawQuad*>::const_iterator dq_iter = dq_list.begin(); - dq_iter != dq_list.end(); - ++dq_iter, ++i) { - EXPECT_EQ(i, (*dq_iter)->get_value()); - } -} - -TEST(ListContainerTest, - SimpleIterationAndReverseIterationWithIndexSharedQuadState) { - ListContainer<SharedQuadState> list; - std::vector<SharedQuadState*> sqs_list; - size_t size = 10; - for (size_t i = 0; i < size; ++i) { - sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>()); - } - EXPECT_EQ(size, list.size()); - - size_t i = 0; - for (ListContainer<SharedQuadState>::Iterator iter = list.begin(); - iter != list.end(); - ++iter) { - EXPECT_EQ(i, iter.index()); - ++i; - } - - i = 0; - for (ListContainer<SharedQuadState>::ReverseIterator iter = list.rbegin(); - iter != list.rend(); - ++iter) { - EXPECT_EQ(i, iter.index()); - ++i; - } -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/quads/picture_draw_quad.cc b/chromium/cc/quads/picture_draw_quad.cc index af6fba12db0..b98fa90b10e 100644 --- a/chromium/cc/quads/picture_draw_quad.cc +++ b/chromium/cc/quads/picture_draw_quad.cc @@ -73,12 +73,6 @@ void PictureDrawQuad::SetAll(const SharedQuadState* shared_quad_state, this->texture_format = texture_format; } -void PictureDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) { - // TODO(danakj): Convert to TextureDrawQuad? - NOTIMPLEMENTED(); -} - const PictureDrawQuad* PictureDrawQuad::MaterialCast(const DrawQuad* quad) { DCHECK(quad->material == DrawQuad::PICTURE_CONTENT); return static_cast<const PictureDrawQuad*>(quad); diff --git a/chromium/cc/quads/picture_draw_quad.h b/chromium/cc/quads/picture_draw_quad.h index 243a2f9d174..9a01a9be029 100644 --- a/chromium/cc/quads/picture_draw_quad.h +++ b/chromium/cc/quads/picture_draw_quad.h @@ -10,6 +10,7 @@ #include "cc/base/cc_export.h" #include "cc/playback/raster_source.h" #include "cc/quads/content_draw_quad_base.h" +#include "cc/resources/resource_provider.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size.h" @@ -52,8 +53,6 @@ class CC_EXPORT PictureDrawQuad : public ContentDrawQuadBase { scoped_refptr<RasterSource> raster_source; ResourceFormat texture_format; - void IterateResources(const ResourceIteratorCallback& callback) override; - static const PictureDrawQuad* MaterialCast(const DrawQuad* quad); private: diff --git a/chromium/cc/quads/render_pass.cc b/chromium/cc/quads/render_pass.cc index 567145a82d6..5c4d98a33c9 100644 --- a/chromium/cc/quads/render_pass.cc +++ b/chromium/cc/quads/render_pass.cc @@ -6,6 +6,7 @@ #include <algorithm> +#include "base/numerics/safe_conversions.h" #include "base/trace_event/trace_event_argument.h" #include "base/values.h" #include "cc/base/math_util.h" @@ -52,8 +53,7 @@ scoped_ptr<RenderPass> RenderPass::Create(size_t shared_quad_state_list_size, } RenderPass::RenderPass() - : id(RenderPassId(-1, -1)), - has_transparent_background(true), + : has_transparent_background(true), quad_list(kDefaultNumQuadsToReserve), shared_quad_state_list(sizeof(SharedQuadState), kDefaultNumSharedQuadStatesToReserve) { @@ -62,16 +62,14 @@ RenderPass::RenderPass() // Each layer usually produces one shared quad state, so the number of layers // is a good hint for what to reserve here. RenderPass::RenderPass(size_t num_layers) - : id(RenderPassId(-1, -1)), - has_transparent_background(true), + : has_transparent_background(true), quad_list(kDefaultNumQuadsToReserve), shared_quad_state_list(sizeof(SharedQuadState), num_layers) { } RenderPass::RenderPass(size_t shared_quad_state_list_size, size_t quad_list_size) - : id(RenderPassId(-1, -1)), - has_transparent_background(true), + : has_transparent_background(true), quad_list(quad_list_size), shared_quad_state_list(sizeof(SharedQuadState), shared_quad_state_list_size) { @@ -148,7 +146,6 @@ void RenderPass::SetNew(RenderPassId id, const gfx::Rect& damage_rect, const gfx::Transform& transform_to_root_target) { DCHECK_GT(id.layer_id, 0); - DCHECK_GE(id.index, 0); DCHECK(damage_rect.IsEmpty() || output_rect.Contains(damage_rect)) << "damage_rect: " << damage_rect.ToString() << " output_rect: " << output_rect.ToString(); @@ -168,7 +165,6 @@ void RenderPass::SetAll(RenderPassId id, const gfx::Transform& transform_to_root_target, bool has_transparent_background) { DCHECK_GT(id.layer_id, 0); - DCHECK_GE(id.index, 0); this->id = id; this->output_rect = output_rect; @@ -185,7 +181,8 @@ void RenderPass::AsValueInto(base::trace_event::TracedValue* value) const { MathUtil::AddToTracedValue("damage_rect", damage_rect, value); value->SetBoolean("has_transparent_background", has_transparent_background); - value->SetInteger("copy_requests", copy_requests.size()); + value->SetInteger("copy_requests", + base::saturated_cast<int>(copy_requests.size())); value->BeginArray("shared_quad_state_list"); for (const auto& shared_quad_state : shared_quad_state_list) { diff --git a/chromium/cc/quads/render_pass.h b/chromium/cc/quads/render_pass.h index 46a8084b387..14caeba7c7a 100644 --- a/chromium/cc/quads/render_pass.h +++ b/chromium/cc/quads/render_pass.h @@ -11,9 +11,10 @@ #include "base/callback.h" #include "base/containers/hash_tables.h" #include "cc/base/cc_export.h" +#include "cc/base/list_container.h" #include "cc/base/scoped_ptr_vector.h" -#include "cc/quads/list_container.h" #include "cc/quads/render_pass_id.h" +#include "cc/surfaces/surface_id.h" #include "skia/ext/refptr.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" @@ -116,6 +117,10 @@ class CC_EXPORT RenderPass { QuadList quad_list; SharedQuadStateList shared_quad_state_list; + // This vector contains the complete set of SurfaceIds referenced by + // DrawQuads in quad_list. + std::vector<SurfaceId> referenced_surfaces; + protected: explicit RenderPass(size_t num_layers); RenderPass(); @@ -136,7 +141,7 @@ namespace BASE_HASH_NAMESPACE { template <> struct hash<cc::RenderPassId> { size_t operator()(cc::RenderPassId key) const { - return base::HashPair(key.layer_id, key.index); + return base::HashPair(key.layer_id, static_cast<int>(key.index)); } }; } // namespace BASE_HASH_NAMESPACE diff --git a/chromium/cc/quads/render_pass_draw_quad.cc b/chromium/cc/quads/render_pass_draw_quad.cc index 963a1906ee7..47c976b96bc 100644 --- a/chromium/cc/quads/render_pass_draw_quad.cc +++ b/chromium/cc/quads/render_pass_draw_quad.cc @@ -12,9 +12,7 @@ namespace cc { -RenderPassDrawQuad::RenderPassDrawQuad() - : render_pass_id(RenderPassId(-1, -1)), - mask_resource_id(static_cast<ResourceProvider::ResourceId>(-1)) { +RenderPassDrawQuad::RenderPassDrawQuad() { } RenderPassDrawQuad::~RenderPassDrawQuad() { @@ -24,14 +22,13 @@ void RenderPassDrawQuad::SetNew(const SharedQuadState* shared_quad_state, const gfx::Rect& rect, const gfx::Rect& visible_rect, RenderPassId render_pass_id, - ResourceProvider::ResourceId mask_resource_id, + ResourceId mask_resource_id, const gfx::Vector2dF& mask_uv_scale, const gfx::Size& mask_texture_size, const FilterOperations& filters, const gfx::Vector2dF& filters_scale, const FilterOperations& background_filters) { DCHECK_GT(render_pass_id.layer_id, 0); - DCHECK_GE(render_pass_id.index, 0); gfx::Rect opaque_rect; bool needs_blending = false; @@ -55,19 +52,19 @@ void RenderPassDrawQuad::SetAll(const SharedQuadState* shared_quad_state, const gfx::Rect& visible_rect, bool needs_blending, RenderPassId render_pass_id, - ResourceProvider::ResourceId mask_resource_id, + ResourceId mask_resource_id, const gfx::Vector2dF& mask_uv_scale, const gfx::Size& mask_texture_size, const FilterOperations& filters, const gfx::Vector2dF& filters_scale, const FilterOperations& background_filters) { DCHECK_GT(render_pass_id.layer_id, 0); - DCHECK_GE(render_pass_id.index, 0); DrawQuad::SetAll(shared_quad_state, DrawQuad::RENDER_PASS, rect, opaque_rect, visible_rect, needs_blending); this->render_pass_id = render_pass_id; - this->mask_resource_id = mask_resource_id; + resources.ids[kMaskResourceIdIndex] = mask_resource_id; + resources.count = mask_resource_id ? 1 : 0; this->mask_uv_scale = mask_uv_scale; this->mask_texture_size = mask_texture_size; this->filters = filters; @@ -75,12 +72,6 @@ void RenderPassDrawQuad::SetAll(const SharedQuadState* shared_quad_state, this->background_filters = background_filters; } -void RenderPassDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) { - if (mask_resource_id) - mask_resource_id = callback.Run(mask_resource_id); -} - gfx::RectF RenderPassDrawQuad::MaskUVRect() const { gfx::RectF mask_uv_rect((mask_uv_scale.x() * rect.x()) / rect.width(), (mask_uv_scale.y() * rect.y()) / rect.height(), @@ -98,13 +89,13 @@ const RenderPassDrawQuad* RenderPassDrawQuad::MaterialCast( void RenderPassDrawQuad::ExtendValue( base::trace_event::TracedValue* value) const { TracedValue::SetIDRef(render_pass_id.AsTracingId(), value, "render_pass_id"); - value->SetInteger("mask_resource_id", mask_resource_id); + value->SetInteger("mask_resource_id", resources.ids[kMaskResourceIdIndex]); MathUtil::AddToTracedValue("mask_texture_size", mask_texture_size, value); MathUtil::AddToTracedValue("mask_uv_scale", mask_uv_scale, value); - value->BeginDictionary("filters"); + value->BeginArray("filters"); filters.AsValueInto(value); - value->EndDictionary(); + value->EndArray(); MathUtil::AddToTracedValue("filters_scale", filters_scale, value); value->BeginDictionary("background_filters"); diff --git a/chromium/cc/quads/render_pass_draw_quad.h b/chromium/cc/quads/render_pass_draw_quad.h index 758b8e85004..c0d6b52bf08 100644 --- a/chromium/cc/quads/render_pass_draw_quad.h +++ b/chromium/cc/quads/render_pass_draw_quad.h @@ -24,7 +24,7 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad { const gfx::Rect& rect, const gfx::Rect& visible_rect, RenderPassId render_pass_id, - ResourceProvider::ResourceId mask_resource_id, + ResourceId mask_resource_id, const gfx::Vector2dF& mask_uv_scale, const gfx::Size& mask_texture_size, const FilterOperations& filters, @@ -37,7 +37,7 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad { const gfx::Rect& visible_rect, bool needs_blending, RenderPassId render_pass_id, - ResourceProvider::ResourceId mask_resource_id, + ResourceId mask_resource_id, const gfx::Vector2dF& mask_uv_scale, const gfx::Size& mask_texture_size, const FilterOperations& filters, @@ -45,7 +45,6 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad { const FilterOperations& background_filters); RenderPassId render_pass_id; - ResourceProvider::ResourceId mask_resource_id; gfx::Vector2dF mask_uv_scale; gfx::Size mask_texture_size; @@ -65,11 +64,15 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad { // Helper function to generate the normalized uv rect. gfx::RectF MaskUVRect() const; - void IterateResources(const ResourceIteratorCallback& callback) override; + ResourceId mask_resource_id() const { + return resources.ids[kMaskResourceIdIndex]; + } static const RenderPassDrawQuad* MaterialCast(const DrawQuad*); private: + static const size_t kMaskResourceIdIndex = 0; + void ExtendValue(base::trace_event::TracedValue* value) const override; }; diff --git a/chromium/cc/quads/render_pass_id.cc b/chromium/cc/quads/render_pass_id.cc index a84582c5ce3..5fea6dc8cb2 100644 --- a/chromium/cc/quads/render_pass_id.cc +++ b/chromium/cc/quads/render_pass_id.cc @@ -9,7 +9,8 @@ namespace cc { void* RenderPassId::AsTracingId() const { static_assert(sizeof(size_t) <= sizeof(void*), // NOLINT "size of size_t should not be greater than that of a pointer"); - return reinterpret_cast<void*>(base::HashPair(layer_id, index)); + return reinterpret_cast<void*>( + base::HashPair(layer_id, static_cast<int>(index))); } } // namespace cc diff --git a/chromium/cc/quads/render_pass_id.h b/chromium/cc/quads/render_pass_id.h index 05541307a07..ebf6387e73c 100644 --- a/chromium/cc/quads/render_pass_id.h +++ b/chromium/cc/quads/render_pass_id.h @@ -14,9 +14,10 @@ namespace cc { class CC_EXPORT RenderPassId { public: int layer_id; - int index; + size_t index; - RenderPassId(int layer_id, int index) : layer_id(layer_id), index(index) {} + RenderPassId() : layer_id(-1), index(0) {} + RenderPassId(int layer_id, size_t index) : layer_id(layer_id), index(index) {} void* AsTracingId() const; bool operator==(const RenderPassId& other) const { diff --git a/chromium/cc/quads/render_pass_unittest.cc b/chromium/cc/quads/render_pass_unittest.cc index e6f39bcab82..5ab8c3170c3 100644 --- a/chromium/cc/quads/render_pass_unittest.cc +++ b/chromium/cc/quads/render_pass_unittest.cc @@ -30,6 +30,7 @@ struct RenderPassSize { gfx::Rect output_rect; gfx::Rect damage_rect; bool has_transparent_background; + std::vector<SurfaceId> referenced_surfaces; ScopedPtrVector<CopyOutputRequest> copy_callbacks; }; @@ -51,14 +52,15 @@ static void CompareRenderPassLists(const RenderPassList& expected_list, EXPECT_EQ(expected->shared_quad_state_list.size(), actual->shared_quad_state_list.size()); EXPECT_EQ(expected->quad_list.size(), actual->quad_list.size()); + EXPECT_EQ(expected->referenced_surfaces, actual->referenced_surfaces); for (auto exp_iter = expected->quad_list.cbegin(), act_iter = actual->quad_list.cbegin(); exp_iter != expected->quad_list.cend(); ++exp_iter, ++act_iter) { EXPECT_EQ(exp_iter->rect.ToString(), act_iter->rect.ToString()); - EXPECT_EQ(exp_iter->shared_quad_state->content_bounds.ToString(), - act_iter->shared_quad_state->content_bounds.ToString()); + EXPECT_EQ(exp_iter->shared_quad_state->quad_layer_bounds.ToString(), + act_iter->shared_quad_state->quad_layer_bounds.ToString()); } } } @@ -104,6 +106,7 @@ TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) { EXPECT_EQ(pass->damage_rect, copy->damage_rect); EXPECT_EQ(pass->has_transparent_background, copy->has_transparent_background); EXPECT_EQ(0u, copy->quad_list.size()); + EXPECT_EQ(0u, copy->referenced_surfaces.size()); // The copy request should not be copied/duplicated. EXPECT_EQ(1u, pass->copy_requests.size()); diff --git a/chromium/cc/quads/shared_quad_state.cc b/chromium/cc/quads/shared_quad_state.cc index 5e46fcc24d7..e09cdaf9f3b 100644 --- a/chromium/cc/quads/shared_quad_state.cc +++ b/chromium/cc/quads/shared_quad_state.cc @@ -28,17 +28,17 @@ void SharedQuadState::CopyFrom(const SharedQuadState* other) { *this = *other; } -void SharedQuadState::SetAll(const gfx::Transform& content_to_target_transform, - const gfx::Size& content_bounds, - const gfx::Rect& visible_content_rect, +void SharedQuadState::SetAll(const gfx::Transform& quad_to_target_transform, + const gfx::Size& quad_layer_bounds, + const gfx::Rect& visible_quad_layer_rect, const gfx::Rect& clip_rect, bool is_clipped, float opacity, SkXfermode::Mode blend_mode, int sorting_context_id) { - this->content_to_target_transform = content_to_target_transform; - this->content_bounds = content_bounds; - this->visible_content_rect = visible_content_rect; + this->quad_to_target_transform = quad_to_target_transform; + this->quad_layer_bounds = quad_layer_bounds; + this->visible_quad_layer_rect = visible_quad_layer_rect; this->clip_rect = clip_rect; this->is_clipped = is_clipped; this->opacity = opacity; @@ -47,10 +47,10 @@ void SharedQuadState::SetAll(const gfx::Transform& content_to_target_transform, } void SharedQuadState::AsValueInto(base::trace_event::TracedValue* value) const { - MathUtil::AddToTracedValue("transform", content_to_target_transform, value); - MathUtil::AddToTracedValue("layer_content_bounds", content_bounds, value); - MathUtil::AddToTracedValue("layer_visible_content_rect", visible_content_rect, - value); + MathUtil::AddToTracedValue("transform", quad_to_target_transform, value); + MathUtil::AddToTracedValue("layer_content_bounds", quad_layer_bounds, value); + MathUtil::AddToTracedValue("layer_visible_content_rect", + visible_quad_layer_rect, value); value->SetBoolean("is_clipped", is_clipped); diff --git a/chromium/cc/quads/shared_quad_state.h b/chromium/cc/quads/shared_quad_state.h index 6f0ef92908d..a66c7bcac2f 100644 --- a/chromium/cc/quads/shared_quad_state.h +++ b/chromium/cc/quads/shared_quad_state.h @@ -32,9 +32,9 @@ class CC_EXPORT SharedQuadState { void CopyFrom(const SharedQuadState* other); - void SetAll(const gfx::Transform& content_to_target_transform, - const gfx::Size& content_bounds, - const gfx::Rect& visible_content_rect, + void SetAll(const gfx::Transform& quad_to_target_transform, + const gfx::Size& layer_bounds, + const gfx::Rect& visible_layer_rect, const gfx::Rect& clip_rect, bool is_clipped, float opacity, @@ -42,12 +42,13 @@ class CC_EXPORT SharedQuadState { int sorting_context_id); void AsValueInto(base::trace_event::TracedValue* dict) const; - // Transforms from quad's original content space to its target content space. - gfx::Transform content_to_target_transform; - // This size lives in the content space for the quad's originating layer. - gfx::Size content_bounds; - // This rect lives in the content space for the quad's originating layer. - gfx::Rect visible_content_rect; + // Transforms quad rects into the target content space. + gfx::Transform quad_to_target_transform; + // The size of the quads' originating layer in the space of the quad rects. + gfx::Size quad_layer_bounds; + // The size of the visible area in the quads' originating layer, in the space + // of the quad rects. + gfx::Rect visible_quad_layer_rect; // This rect lives in the target content space. gfx::Rect clip_rect; bool is_clipped; diff --git a/chromium/cc/quads/solid_color_draw_quad.cc b/chromium/cc/quads/solid_color_draw_quad.cc index 229e98b1426..f122e1c8b4b 100644 --- a/chromium/cc/quads/solid_color_draw_quad.cc +++ b/chromium/cc/quads/solid_color_draw_quad.cc @@ -39,9 +39,6 @@ void SolidColorDrawQuad::SetAll(const SharedQuadState* shared_quad_state, this->force_anti_aliasing_off = force_anti_aliasing_off; } -void SolidColorDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) {} - const SolidColorDrawQuad* SolidColorDrawQuad::MaterialCast( const DrawQuad* quad) { DCHECK(quad->material == DrawQuad::SOLID_COLOR); diff --git a/chromium/cc/quads/solid_color_draw_quad.h b/chromium/cc/quads/solid_color_draw_quad.h index f0f5f5a28b4..8b950411ded 100644 --- a/chromium/cc/quads/solid_color_draw_quad.h +++ b/chromium/cc/quads/solid_color_draw_quad.h @@ -33,8 +33,6 @@ class CC_EXPORT SolidColorDrawQuad : public DrawQuad { SkColor color; bool force_anti_aliasing_off; - void IterateResources(const ResourceIteratorCallback& callback) override; - static const SolidColorDrawQuad* MaterialCast(const DrawQuad*); private: diff --git a/chromium/cc/quads/stream_video_draw_quad.cc b/chromium/cc/quads/stream_video_draw_quad.cc index fb6f728ee2e..c25e5d5869c 100644 --- a/chromium/cc/quads/stream_video_draw_quad.cc +++ b/chromium/cc/quads/stream_video_draw_quad.cc @@ -11,18 +11,24 @@ namespace cc { -StreamVideoDrawQuad::StreamVideoDrawQuad() : resource_id(0) {} +StreamVideoDrawQuad::StreamVideoDrawQuad() { +} void StreamVideoDrawQuad::SetNew(const SharedQuadState* shared_quad_state, const gfx::Rect& rect, const gfx::Rect& opaque_rect, const gfx::Rect& visible_rect, unsigned resource_id, + gfx::Size resource_size_in_pixels, + bool allow_overlay, const gfx::Transform& matrix) { bool needs_blending = false; DrawQuad::SetAll(shared_quad_state, DrawQuad::STREAM_VIDEO_CONTENT, rect, opaque_rect, visible_rect, needs_blending); - this->resource_id = resource_id; + resources.ids[kResourceIdIndex] = resource_id; + overlay_resources.size_in_pixels[kResourceIdIndex] = resource_size_in_pixels; + overlay_resources.allow_overlay[kResourceIdIndex] = allow_overlay; + resources.count = 1; this->matrix = matrix; } @@ -32,18 +38,18 @@ void StreamVideoDrawQuad::SetAll(const SharedQuadState* shared_quad_state, const gfx::Rect& visible_rect, bool needs_blending, unsigned resource_id, + gfx::Size resource_size_in_pixels, + bool allow_overlay, const gfx::Transform& matrix) { DrawQuad::SetAll(shared_quad_state, DrawQuad::STREAM_VIDEO_CONTENT, rect, opaque_rect, visible_rect, needs_blending); - this->resource_id = resource_id; + resources.ids[kResourceIdIndex] = resource_id; + overlay_resources.size_in_pixels[kResourceIdIndex] = resource_size_in_pixels; + overlay_resources.allow_overlay[kResourceIdIndex] = allow_overlay; + resources.count = 1; this->matrix = matrix; } -void StreamVideoDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) { - resource_id = callback.Run(resource_id); -} - const StreamVideoDrawQuad* StreamVideoDrawQuad::MaterialCast( const DrawQuad* quad) { DCHECK(quad->material == DrawQuad::STREAM_VIDEO_CONTENT); @@ -52,8 +58,13 @@ const StreamVideoDrawQuad* StreamVideoDrawQuad::MaterialCast( void StreamVideoDrawQuad::ExtendValue( base::trace_event::TracedValue* value) const { - value->SetInteger("resource_id", resource_id); + value->SetInteger("resource_id", resources.ids[kResourceIdIndex]); MathUtil::AddToTracedValue("matrix", matrix, value); } +StreamVideoDrawQuad::OverlayResources::OverlayResources() { + for (size_t i = 0; i < Resources::kMaxResourceIdCount; ++i) + allow_overlay[i] = false; +} + } // namespace cc diff --git a/chromium/cc/quads/stream_video_draw_quad.h b/chromium/cc/quads/stream_video_draw_quad.h index 45c28f2f957..519c35363ed 100644 --- a/chromium/cc/quads/stream_video_draw_quad.h +++ b/chromium/cc/quads/stream_video_draw_quad.h @@ -21,6 +21,8 @@ class CC_EXPORT StreamVideoDrawQuad : public DrawQuad { const gfx::Rect& opaque_rect, const gfx::Rect& visible_rect, unsigned resource_id, + gfx::Size resource_size_in_pixels, + bool allow_overlay, const gfx::Transform& matrix); void SetAll(const SharedQuadState* shared_quad_state, @@ -29,16 +31,33 @@ class CC_EXPORT StreamVideoDrawQuad : public DrawQuad { const gfx::Rect& visible_rect, bool needs_blending, unsigned resource_id, + gfx::Size resource_size_in_pixels, + bool allow_overlay, const gfx::Transform& matrix); - unsigned resource_id; gfx::Transform matrix; - void IterateResources(const ResourceIteratorCallback& callback) override; + struct OverlayResources { + OverlayResources(); + + gfx::Size size_in_pixels[Resources::kMaxResourceIdCount]; + bool allow_overlay[Resources::kMaxResourceIdCount]; + }; + OverlayResources overlay_resources; static const StreamVideoDrawQuad* MaterialCast(const DrawQuad*); + ResourceId resource_id() const { return resources.ids[kResourceIdIndex]; } + const gfx::Size& resource_size_in_pixels() const { + return overlay_resources.size_in_pixels[kResourceIdIndex]; + } + bool allow_overlay() const { + return overlay_resources.allow_overlay[kResourceIdIndex]; + } + private: + static const size_t kResourceIdIndex = 0; + void ExtendValue(base::trace_event::TracedValue* value) const override; }; diff --git a/chromium/cc/quads/surface_draw_quad.cc b/chromium/cc/quads/surface_draw_quad.cc index 5823558ae68..655158152a6 100644 --- a/chromium/cc/quads/surface_draw_quad.cc +++ b/chromium/cc/quads/surface_draw_quad.cc @@ -35,9 +35,6 @@ void SurfaceDrawQuad::SetAll(const SharedQuadState* shared_quad_state, this->surface_id = surface_id; } -void SurfaceDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) {} - const SurfaceDrawQuad* SurfaceDrawQuad::MaterialCast(const DrawQuad* quad) { DCHECK_EQ(quad->material, DrawQuad::SURFACE_CONTENT); return static_cast<const SurfaceDrawQuad*>(quad); diff --git a/chromium/cc/quads/surface_draw_quad.h b/chromium/cc/quads/surface_draw_quad.h index 36dc8090895..86887cae8b3 100644 --- a/chromium/cc/quads/surface_draw_quad.h +++ b/chromium/cc/quads/surface_draw_quad.h @@ -30,8 +30,6 @@ class CC_EXPORT SurfaceDrawQuad : public DrawQuad { SurfaceId surface_id; - void IterateResources(const ResourceIteratorCallback& callback) override; - static const SurfaceDrawQuad* MaterialCast(const DrawQuad* quad); private: diff --git a/chromium/cc/quads/texture_draw_quad.cc b/chromium/cc/quads/texture_draw_quad.cc index 4b8720a1ed7..c469c875138 100644 --- a/chromium/cc/quads/texture_draw_quad.cc +++ b/chromium/cc/quads/texture_draw_quad.cc @@ -13,8 +13,7 @@ namespace cc { TextureDrawQuad::TextureDrawQuad() - : resource_id(0), - premultiplied_alpha(false), + : premultiplied_alpha(false), background_color(SK_ColorTRANSPARENT), y_flipped(false), nearest_neighbor(false) { @@ -40,7 +39,8 @@ void TextureDrawQuad::SetNew(const SharedQuadState* shared_quad_state, || vertex_opacity[2] != 1.0f || vertex_opacity[3] != 1.0f; DrawQuad::SetAll(shared_quad_state, DrawQuad::TEXTURE_CONTENT, rect, opaque_rect, visible_rect, needs_blending); - this->resource_id = resource_id; + resources.ids[kResourceIdIndex] = resource_id; + resources.count = 1; this->premultiplied_alpha = premultiplied_alpha; this->uv_top_left = uv_top_left; this->uv_bottom_right = uv_bottom_right; @@ -59,6 +59,8 @@ void TextureDrawQuad::SetAll(const SharedQuadState* shared_quad_state, const gfx::Rect& visible_rect, bool needs_blending, unsigned resource_id, + gfx::Size resource_size_in_pixels, + bool allow_overlay, bool premultiplied_alpha, const gfx::PointF& uv_top_left, const gfx::PointF& uv_bottom_right, @@ -68,7 +70,10 @@ void TextureDrawQuad::SetAll(const SharedQuadState* shared_quad_state, bool nearest_neighbor) { DrawQuad::SetAll(shared_quad_state, DrawQuad::TEXTURE_CONTENT, rect, opaque_rect, visible_rect, needs_blending); - this->resource_id = resource_id; + resources.ids[kResourceIdIndex] = resource_id; + overlay_resources.size_in_pixels[kResourceIdIndex] = resource_size_in_pixels; + overlay_resources.allow_overlay[kResourceIdIndex] = allow_overlay; + resources.count = 1; this->premultiplied_alpha = premultiplied_alpha; this->uv_top_left = uv_top_left; this->uv_bottom_right = uv_bottom_right; @@ -81,18 +86,13 @@ void TextureDrawQuad::SetAll(const SharedQuadState* shared_quad_state, this->nearest_neighbor = nearest_neighbor; } -void TextureDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) { - resource_id = callback.Run(resource_id); -} - const TextureDrawQuad* TextureDrawQuad::MaterialCast(const DrawQuad* quad) { DCHECK(quad->material == DrawQuad::TEXTURE_CONTENT); return static_cast<const TextureDrawQuad*>(quad); } void TextureDrawQuad::ExtendValue(base::trace_event::TracedValue* value) const { - value->SetInteger("resource_id", resource_id); + value->SetInteger("resource_id", resources.ids[kResourceIdIndex]); value->SetBoolean("premultiplied_alpha", premultiplied_alpha); MathUtil::AddToTracedValue("uv_top_left", uv_top_left, value); @@ -109,4 +109,9 @@ void TextureDrawQuad::ExtendValue(base::trace_event::TracedValue* value) const { value->SetBoolean("nearest_neighbor", nearest_neighbor); } +TextureDrawQuad::OverlayResources::OverlayResources() { + for (size_t i = 0; i < Resources::kMaxResourceIdCount; ++i) + allow_overlay[i] = false; +} + } // namespace cc diff --git a/chromium/cc/quads/texture_draw_quad.h b/chromium/cc/quads/texture_draw_quad.h index 70641492368..40c7623c5cd 100644 --- a/chromium/cc/quads/texture_draw_quad.h +++ b/chromium/cc/quads/texture_draw_quad.h @@ -35,6 +35,8 @@ class CC_EXPORT TextureDrawQuad : public DrawQuad { const gfx::Rect& visible_rect, bool needs_blending, unsigned resource_id, + gfx::Size resource_size_in_pixels, + bool allow_overlay, bool premultiplied_alpha, const gfx::PointF& uv_top_left, const gfx::PointF& uv_bottom_right, @@ -43,7 +45,6 @@ class CC_EXPORT TextureDrawQuad : public DrawQuad { bool y_flipped, bool nearest_neighbor); - unsigned resource_id; bool premultiplied_alpha; gfx::PointF uv_top_left; gfx::PointF uv_bottom_right; @@ -52,11 +53,33 @@ class CC_EXPORT TextureDrawQuad : public DrawQuad { bool y_flipped; bool nearest_neighbor; - void IterateResources(const ResourceIteratorCallback& callback) override; + struct OverlayResources { + OverlayResources(); + + gfx::Size size_in_pixels[Resources::kMaxResourceIdCount]; + bool allow_overlay[Resources::kMaxResourceIdCount]; + }; + OverlayResources overlay_resources; + + ResourceId resource_id() const { return resources.ids[kResourceIdIndex]; } + const gfx::Size& resource_size_in_pixels() const { + return overlay_resources.size_in_pixels[kResourceIdIndex]; + } + void set_resource_size_in_pixels(const gfx::Size& size_in_pixels) { + overlay_resources.size_in_pixels[kResourceIdIndex] = size_in_pixels; + } + bool allow_overlay() const { + return overlay_resources.allow_overlay[kResourceIdIndex]; + } + void set_allow_overlay(bool allow_overlay) { + overlay_resources.allow_overlay[kResourceIdIndex] = allow_overlay; + } static const TextureDrawQuad* MaterialCast(const DrawQuad*); private: + static const size_t kResourceIdIndex = 0; + void ExtendValue(base::trace_event::TracedValue* value) const override; }; diff --git a/chromium/cc/quads/tile_draw_quad.cc b/chromium/cc/quads/tile_draw_quad.cc index aa8f748d8b8..02c4a1e25a5 100644 --- a/chromium/cc/quads/tile_draw_quad.cc +++ b/chromium/cc/quads/tile_draw_quad.cc @@ -10,8 +10,7 @@ namespace cc { -TileDrawQuad::TileDrawQuad() - : resource_id(0) { +TileDrawQuad::TileDrawQuad() { } TileDrawQuad::~TileDrawQuad() { @@ -35,7 +34,8 @@ void TileDrawQuad::SetNew(const SharedQuadState* shared_quad_state, texture_size, swizzle_contents, nearest_neighbor); - this->resource_id = resource_id; + resources.ids[kResourceIdIndex] = resource_id; + resources.count = 1; } void TileDrawQuad::SetAll(const SharedQuadState* shared_quad_state, @@ -52,12 +52,8 @@ void TileDrawQuad::SetAll(const SharedQuadState* shared_quad_state, opaque_rect, visible_rect, needs_blending, tex_coord_rect, texture_size, swizzle_contents, nearest_neighbor); - this->resource_id = resource_id; -} - -void TileDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) { - resource_id = callback.Run(resource_id); + resources.ids[kResourceIdIndex] = resource_id; + resources.count = 1; } const TileDrawQuad* TileDrawQuad::MaterialCast(const DrawQuad* quad) { @@ -67,7 +63,7 @@ const TileDrawQuad* TileDrawQuad::MaterialCast(const DrawQuad* quad) { void TileDrawQuad::ExtendValue(base::trace_event::TracedValue* value) const { ContentDrawQuadBase::ExtendValue(value); - value->SetInteger("resource_id", resource_id); + value->SetInteger("resource_id", resources.ids[kResourceIdIndex]); } } // namespace cc diff --git a/chromium/cc/quads/tile_draw_quad.h b/chromium/cc/quads/tile_draw_quad.h index b858e148d23..feb9e87c7cc 100644 --- a/chromium/cc/quads/tile_draw_quad.h +++ b/chromium/cc/quads/tile_draw_quad.h @@ -41,13 +41,13 @@ class CC_EXPORT TileDrawQuad : public ContentDrawQuadBase { bool swizzle_contents, bool nearest_neighbor); - unsigned resource_id; - - void IterateResources(const ResourceIteratorCallback& callback) override; - static const TileDrawQuad* MaterialCast(const DrawQuad*); + ResourceId resource_id() const { return resources.ids[kResourceIdIndex]; } + private: + static const size_t kResourceIdIndex = 0; + void ExtendValue(base::trace_event::TracedValue* value) const override; }; diff --git a/chromium/cc/quads/yuv_video_draw_quad.cc b/chromium/cc/quads/yuv_video_draw_quad.cc index 5706f288cd5..f9a878a93e9 100644 --- a/chromium/cc/quads/yuv_video_draw_quad.cc +++ b/chromium/cc/quads/yuv_video_draw_quad.cc @@ -11,11 +11,8 @@ namespace cc { -YUVVideoDrawQuad::YUVVideoDrawQuad() - : y_plane_resource_id(0), - u_plane_resource_id(0), - v_plane_resource_id(0), - a_plane_resource_id(0) {} +YUVVideoDrawQuad::YUVVideoDrawQuad() { +} YUVVideoDrawQuad::~YUVVideoDrawQuad() {} void YUVVideoDrawQuad::SetNew(const SharedQuadState* shared_quad_state, @@ -38,10 +35,11 @@ void YUVVideoDrawQuad::SetNew(const SharedQuadState* shared_quad_state, this->uv_tex_coord_rect = uv_tex_coord_rect; this->ya_tex_size = ya_tex_size; this->uv_tex_size = uv_tex_size; - this->y_plane_resource_id = y_plane_resource_id; - this->u_plane_resource_id = u_plane_resource_id; - this->v_plane_resource_id = v_plane_resource_id; - this->a_plane_resource_id = a_plane_resource_id; + resources.ids[kYPlaneResourceIdIndex] = y_plane_resource_id; + resources.ids[kUPlaneResourceIdIndex] = u_plane_resource_id; + resources.ids[kVPlaneResourceIdIndex] = v_plane_resource_id; + resources.ids[kAPlaneResourceIdIndex] = a_plane_resource_id; + resources.count = a_plane_resource_id ? 4 : 3; this->color_space = color_space; } @@ -65,22 +63,14 @@ void YUVVideoDrawQuad::SetAll(const SharedQuadState* shared_quad_state, this->uv_tex_coord_rect = uv_tex_coord_rect; this->ya_tex_size = ya_tex_size; this->uv_tex_size = uv_tex_size; - this->y_plane_resource_id = y_plane_resource_id; - this->u_plane_resource_id = u_plane_resource_id; - this->v_plane_resource_id = v_plane_resource_id; - this->a_plane_resource_id = a_plane_resource_id; + resources.ids[kYPlaneResourceIdIndex] = y_plane_resource_id; + resources.ids[kUPlaneResourceIdIndex] = u_plane_resource_id; + resources.ids[kVPlaneResourceIdIndex] = v_plane_resource_id; + resources.ids[kAPlaneResourceIdIndex] = a_plane_resource_id; + resources.count = resources.ids[kAPlaneResourceIdIndex] ? 4 : 3; this->color_space = color_space; } -void YUVVideoDrawQuad::IterateResources( - const ResourceIteratorCallback& callback) { - y_plane_resource_id = callback.Run(y_plane_resource_id); - u_plane_resource_id = callback.Run(u_plane_resource_id); - v_plane_resource_id = callback.Run(v_plane_resource_id); - if (a_plane_resource_id) - a_plane_resource_id = callback.Run(a_plane_resource_id); -} - const YUVVideoDrawQuad* YUVVideoDrawQuad::MaterialCast( const DrawQuad* quad) { DCHECK(quad->material == DrawQuad::YUV_VIDEO_CONTENT); @@ -93,10 +83,14 @@ void YUVVideoDrawQuad::ExtendValue( MathUtil::AddToTracedValue("uv_tex_coord_rect", uv_tex_coord_rect, value); MathUtil::AddToTracedValue("ya_tex_size", ya_tex_size, value); MathUtil::AddToTracedValue("uv_tex_size", uv_tex_size, value); - value->SetInteger("y_plane_resource_id", y_plane_resource_id); - value->SetInteger("u_plane_resource_id", u_plane_resource_id); - value->SetInteger("v_plane_resource_id", v_plane_resource_id); - value->SetInteger("a_plane_resource_id", a_plane_resource_id); + value->SetInteger("y_plane_resource_id", + resources.ids[kYPlaneResourceIdIndex]); + value->SetInteger("u_plane_resource_id", + resources.ids[kUPlaneResourceIdIndex]); + value->SetInteger("v_plane_resource_id", + resources.ids[kVPlaneResourceIdIndex]); + value->SetInteger("a_plane_resource_id", + resources.ids[kAPlaneResourceIdIndex]); } } // namespace cc diff --git a/chromium/cc/quads/yuv_video_draw_quad.h b/chromium/cc/quads/yuv_video_draw_quad.h index deeca2c1cbc..53ef5710d20 100644 --- a/chromium/cc/quads/yuv_video_draw_quad.h +++ b/chromium/cc/quads/yuv_video_draw_quad.h @@ -64,17 +64,29 @@ class CC_EXPORT YUVVideoDrawQuad : public DrawQuad { gfx::RectF uv_tex_coord_rect; gfx::Size ya_tex_size; gfx::Size uv_tex_size; - unsigned y_plane_resource_id; - unsigned u_plane_resource_id; - unsigned v_plane_resource_id; - unsigned a_plane_resource_id; ColorSpace color_space; - void IterateResources(const ResourceIteratorCallback& callback) override; - static const YUVVideoDrawQuad* MaterialCast(const DrawQuad*); + ResourceId y_plane_resource_id() const { + return resources.ids[kYPlaneResourceIdIndex]; + } + ResourceId u_plane_resource_id() const { + return resources.ids[kUPlaneResourceIdIndex]; + } + ResourceId v_plane_resource_id() const { + return resources.ids[kVPlaneResourceIdIndex]; + } + ResourceId a_plane_resource_id() const { + return resources.ids[kAPlaneResourceIdIndex]; + } + private: + static const size_t kYPlaneResourceIdIndex = 0; + static const size_t kUPlaneResourceIdIndex = 1; + static const size_t kVPlaneResourceIdIndex = 2; + static const size_t kAPlaneResourceIdIndex = 3; + void ExtendValue(base::trace_event::TracedValue* value) const override; }; diff --git a/chromium/cc/raster/bitmap_tile_task_worker_pool.cc b/chromium/cc/raster/bitmap_tile_task_worker_pool.cc index 1792a2053da..bd6af35215c 100644 --- a/chromium/cc/raster/bitmap_tile_task_worker_pool.cc +++ b/chromium/cc/raster/bitmap_tile_task_worker_pool.cc @@ -12,6 +12,7 @@ #include "cc/debug/traced_value.h" #include "cc/playback/raster_source.h" #include "cc/raster/raster_buffer.h" +#include "cc/resources/platform_color.h" #include "cc/resources/resource.h" namespace cc { @@ -20,21 +21,38 @@ namespace { class RasterBufferImpl : public RasterBuffer { public: RasterBufferImpl(ResourceProvider* resource_provider, - const Resource* resource) - : lock_(resource_provider, resource->id()), resource_(resource) {} + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) + : lock_(resource_provider, resource->id()), + resource_(resource), + resource_has_previous_content_( + resource_content_id && resource_content_id == previous_content_id) { + } // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& raster_dirty_rect, + uint64_t new_content_id, float scale) override { - TileTaskWorkerPool::PlaybackToMemory(lock_.sk_bitmap().getPixels(), - resource_->format(), resource_->size(), - 0, raster_source, rect, scale); + gfx::Rect playback_rect = raster_full_rect; + if (resource_has_previous_content_) { + playback_rect.Intersect(raster_dirty_rect); + } + DCHECK(!playback_rect.IsEmpty()) + << "Why are we rastering a tile that's not dirty?"; + + size_t stride = 0u; + TileTaskWorkerPool::PlaybackToMemory( + lock_.sk_bitmap().getPixels(), resource_->format(), resource_->size(), + stride, raster_source, raster_full_rect, playback_rect, scale); } private: ResourceProvider::ScopedWriteLockSoftware lock_; const Resource* resource_; + bool resource_has_previous_content_; DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); }; @@ -89,7 +107,7 @@ void BitmapTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) { // Mark all task sets as pending. tasks_pending_.set(); - unsigned priority = kTileTaskPriorityBase; + size_t priority = kTileTaskPriorityBase; graph_.Reset(); @@ -161,14 +179,20 @@ void BitmapTileTaskWorkerPool::CheckForCompletedTasks() { completed_tasks_.clear(); } -ResourceFormat BitmapTileTaskWorkerPool::GetResourceFormat() { +ResourceFormat BitmapTileTaskWorkerPool::GetResourceFormat() const { return resource_provider_->best_texture_format(); } +bool BitmapTileTaskWorkerPool::GetResourceRequiresSwizzle() const { + return !PlatformColor::SameComponentOrder(GetResourceFormat()); +} + scoped_ptr<RasterBuffer> BitmapTileTaskWorkerPool::AcquireBufferForRaster( - const Resource* resource) { - return make_scoped_ptr<RasterBuffer>( - new RasterBufferImpl(resource_provider_, resource)); + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) { + return scoped_ptr<RasterBuffer>(new RasterBufferImpl( + resource_provider_, resource, resource_content_id, previous_content_id)); } void BitmapTileTaskWorkerPool::ReleaseBufferForRaster( diff --git a/chromium/cc/raster/bitmap_tile_task_worker_pool.h b/chromium/cc/raster/bitmap_tile_task_worker_pool.h index 4fcfd5a33f9..3df206a09bd 100644 --- a/chromium/cc/raster/bitmap_tile_task_worker_pool.h +++ b/chromium/cc/raster/bitmap_tile_task_worker_pool.h @@ -38,11 +38,14 @@ class CC_EXPORT BitmapTileTaskWorkerPool : public TileTaskWorkerPool, void Shutdown() override; void ScheduleTasks(TileTaskQueue* queue) override; void CheckForCompletedTasks() override; - ResourceFormat GetResourceFormat() override; + ResourceFormat GetResourceFormat() const override; + bool GetResourceRequiresSwizzle() const override; // Overridden from TileTaskClient: scoped_ptr<RasterBuffer> AcquireBufferForRaster( - const Resource* resource) override; + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) override; void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override; protected: diff --git a/chromium/cc/raster/gpu_rasterizer.cc b/chromium/cc/raster/gpu_rasterizer.cc index 17a9322bebe..176889494e7 100644 --- a/chromium/cc/raster/gpu_rasterizer.cc +++ b/chromium/cc/raster/gpu_rasterizer.cc @@ -41,7 +41,8 @@ GpuRasterizer::~GpuRasterizer() { void GpuRasterizer::RasterizeSource( ResourceProvider::ScopedWriteLockGr* write_lock, const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& playback_rect, float scale) { // Play back raster_source into temp SkPicture. SkPictureRecorder recorder; @@ -50,7 +51,8 @@ void GpuRasterizer::RasterizeSource( skia::RefPtr<SkCanvas> canvas = skia::SharePtr( recorder.beginRecording(size.width(), size.height(), NULL, flags)); canvas->save(); - raster_source->PlaybackToCanvas(canvas.get(), rect, scale); + raster_source->PlaybackToCanvas(canvas.get(), raster_full_rect, playback_rect, + scale); canvas->restore(); skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecordingAsPicture()); diff --git a/chromium/cc/raster/gpu_rasterizer.h b/chromium/cc/raster/gpu_rasterizer.h index 443e6efeb85..76e8639869c 100644 --- a/chromium/cc/raster/gpu_rasterizer.h +++ b/chromium/cc/raster/gpu_rasterizer.h @@ -24,7 +24,8 @@ class CC_EXPORT GpuRasterizer { void RasterizeSource(ResourceProvider::ScopedWriteLockGr* write_lock, const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& playback_rect, float scale); ResourceProvider* resource_provider() { return resource_provider_; } diff --git a/chromium/cc/raster/gpu_tile_task_worker_pool.cc b/chromium/cc/raster/gpu_tile_task_worker_pool.cc index 24a4710530e..7c21177d527 100644 --- a/chromium/cc/raster/gpu_tile_task_worker_pool.cc +++ b/chromium/cc/raster/gpu_tile_task_worker_pool.cc @@ -23,14 +23,21 @@ namespace { class RasterBufferImpl : public RasterBuffer { public: - RasterBufferImpl(GpuRasterizer* rasterizer, const Resource* resource) + RasterBufferImpl(GpuRasterizer* rasterizer, + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) : rasterizer_(rasterizer), lock_(rasterizer->resource_provider(), resource->id()), - resource_(resource) {} + resource_has_previous_content_( + resource_content_id && resource_content_id == previous_content_id) { + } // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& raster_dirty_rect, + uint64_t new_content_id, float scale) override { TRACE_EVENT0("cc", "RasterBufferImpl::Playback"); ContextProvider* context_provider = rasterizer_->resource_provider() @@ -44,8 +51,17 @@ class RasterBufferImpl : public RasterBuffer { // Allow this worker thread to bind to context_provider. context_provider->DetachFromThread(); + gfx::Rect playback_rect = raster_full_rect; + if (resource_has_previous_content_) { + playback_rect.Intersect(raster_dirty_rect); + } + DCHECK(!playback_rect.IsEmpty()) + << "Why are we rastering a tile that's not dirty?"; + + // TODO(danakj): Implement partial raster with raster_dirty_rect. // Rasterize source into resource. - rasterizer_->RasterizeSource(&lock_, raster_source, rect, scale); + rasterizer_->RasterizeSource(&lock_, raster_source, raster_full_rect, + playback_rect, scale); // Barrier to sync worker context output to cc context. context_provider->ContextGL()->OrderingBarrierCHROMIUM(); @@ -57,7 +73,7 @@ class RasterBufferImpl : public RasterBuffer { private: GpuRasterizer* rasterizer_; ResourceProvider::ScopedWriteLockGr lock_; - const Resource* resource_; + bool resource_has_previous_content_; DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); }; @@ -121,7 +137,7 @@ void GpuTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) { // Mark all task sets as pending. tasks_pending_.set(); - unsigned priority = kTileTaskPriorityBase; + size_t priority = kTileTaskPriorityBase; graph_.Reset(); @@ -189,8 +205,13 @@ void GpuTileTaskWorkerPool::CheckForCompletedTasks() { completed_tasks_.clear(); } -ResourceFormat GpuTileTaskWorkerPool::GetResourceFormat() { - return rasterizer_->resource_provider()->best_texture_format(); +ResourceFormat GpuTileTaskWorkerPool::GetResourceFormat() const { + return rasterizer_->resource_provider()->best_render_buffer_format(); +} + +bool GpuTileTaskWorkerPool::GetResourceRequiresSwizzle() const { + // This doesn't require a swizzle because we rasterize to the correct format. + return false; } void GpuTileTaskWorkerPool::CompleteTasks(const Task::Vector& tasks) { @@ -207,9 +228,11 @@ void GpuTileTaskWorkerPool::CompleteTasks(const Task::Vector& tasks) { } scoped_ptr<RasterBuffer> GpuTileTaskWorkerPool::AcquireBufferForRaster( - const Resource* resource) { - return make_scoped_ptr<RasterBuffer>( - new RasterBufferImpl(rasterizer_.get(), resource)); + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) { + return scoped_ptr<RasterBuffer>(new RasterBufferImpl( + rasterizer_.get(), resource, resource_content_id, previous_content_id)); } void GpuTileTaskWorkerPool::ReleaseBufferForRaster( diff --git a/chromium/cc/raster/gpu_tile_task_worker_pool.h b/chromium/cc/raster/gpu_tile_task_worker_pool.h index 4e35eaa380a..32a9d232550 100644 --- a/chromium/cc/raster/gpu_tile_task_worker_pool.h +++ b/chromium/cc/raster/gpu_tile_task_worker_pool.h @@ -36,11 +36,14 @@ class CC_EXPORT GpuTileTaskWorkerPool : public TileTaskWorkerPool, void Shutdown() override; void ScheduleTasks(TileTaskQueue* queue) override; void CheckForCompletedTasks() override; - ResourceFormat GetResourceFormat() override; + ResourceFormat GetResourceFormat() const override; + bool GetResourceRequiresSwizzle() const override; // Overridden from TileTaskClient: scoped_ptr<RasterBuffer> AcquireBufferForRaster( - const Resource* resource) override; + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) override; void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override; private: diff --git a/chromium/cc/raster/one_copy_tile_task_worker_pool.cc b/chromium/cc/raster/one_copy_tile_task_worker_pool.cc index d504be8fbf6..78e6b106ce9 100644 --- a/chromium/cc/raster/one_copy_tile_task_worker_pool.cc +++ b/chromium/cc/raster/one_copy_tile_task_worker_pool.cc @@ -10,8 +10,10 @@ #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/math_util.h" #include "cc/debug/traced_value.h" #include "cc/raster/raster_buffer.h" +#include "cc/resources/platform_color.h" #include "cc/resources/resource_pool.h" #include "cc/resources/scoped_resource.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -26,17 +28,32 @@ class RasterBufferImpl : public RasterBuffer { ResourceProvider* resource_provider, ResourcePool* resource_pool, ResourceFormat resource_format, - const Resource* resource) + const Resource* output_resource, + uint64_t previous_content_id) : worker_pool_(worker_pool), resource_provider_(resource_provider), resource_pool_(resource_pool), - resource_(resource), - raster_resource_( - resource_pool->AcquireResource(resource->size(), resource_format)), - lock_(new ResourceProvider::ScopedWriteLockGpuMemoryBuffer( - resource_provider_, - raster_resource_->id())), - sequence_(0) {} + output_resource_(output_resource), + raster_content_id_(0), + sequence_(0) { + if (worker_pool->have_persistent_gpu_memory_buffers() && + previous_content_id) { + raster_resource_ = + resource_pool->TryAcquireResourceWithContentId(previous_content_id); + } + if (raster_resource_) { + raster_content_id_ = previous_content_id; + DCHECK_EQ(resource_format, raster_resource_->format()); + DCHECK_EQ(output_resource->size().ToString(), + raster_resource_->size().ToString()); + } else { + raster_resource_ = resource_pool->AcquireResource(output_resource->size(), + resource_format); + } + + lock_.reset(new ResourceProvider::ScopedWriteLockGpuMemoryBuffer( + resource_provider_, raster_resource_->id())); + } ~RasterBufferImpl() override { // Release write lock in case a copy was never scheduled. @@ -47,26 +64,35 @@ class RasterBufferImpl : public RasterBuffer { if (sequence_) worker_pool_->AdvanceLastIssuedCopyTo(sequence_); - // Return raster resource to pool so it can be used by another RasterBuffer + // Return resources to pool so they can be used by another RasterBuffer // instance. - if (raster_resource_) - resource_pool_->ReleaseResource(raster_resource_.Pass()); + resource_pool_->ReleaseResource(raster_resource_.Pass(), + raster_content_id_); } // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& raster_dirty_rect, + uint64_t new_content_id, float scale) override { + // If there's a raster_content_id_, we are reusing a resource with that + // content id. + bool reusing_raster_resource = raster_content_id_ != 0; sequence_ = worker_pool_->PlaybackAndScheduleCopyOnWorkerThread( - lock_.Pass(), raster_resource_.Pass(), resource_, raster_source, rect, + reusing_raster_resource, lock_.Pass(), raster_resource_.get(), + output_resource_, raster_source, raster_full_rect, raster_dirty_rect, scale); + // Store the content id of the resource to return to the pool. + raster_content_id_ = new_content_id; } private: OneCopyTileTaskWorkerPool* worker_pool_; ResourceProvider* resource_provider_; ResourcePool* resource_pool_; - const Resource* resource_; + const Resource* output_resource_; + uint64_t raster_content_id_; scoped_ptr<ScopedResource> raster_resource_; scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> lock_; CopySequenceNumber sequence_; @@ -74,9 +100,6 @@ class RasterBufferImpl : public RasterBuffer { DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); }; -// Flush interval when performing copy operations. -const int kCopyFlushPeriod = 4; - // Number of in-flight copy operations to allow. const int kMaxCopyOperations = 32; @@ -87,13 +110,18 @@ const int kCheckForCompletedCopyOperationsTickRateMs = 1; // wait for copy operations to complete if needed. const int kFailedAttemptsBeforeWaitIfNeeded = 256; +// 4MiB is the size of 4 512x512 tiles, which has proven to be a good +// default batch size for copy operations. +const int kMaxBytesPerCopyOperation = 1024 * 1024 * 4; + } // namespace OneCopyTileTaskWorkerPool::CopyOperation::CopyOperation( - scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock, - scoped_ptr<ScopedResource> src, - const Resource* dst) - : write_lock(write_lock.Pass()), src(src.Pass()), dst(dst) { + scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> src_write_lock, + const Resource* src, + const Resource* dst, + const gfx::Rect& rect) + : src_write_lock(src_write_lock.Pass()), src(src), dst(dst), rect(rect) { } OneCopyTileTaskWorkerPool::CopyOperation::~CopyOperation() { @@ -105,10 +133,13 @@ scoped_ptr<TileTaskWorkerPool> OneCopyTileTaskWorkerPool::Create( TaskGraphRunner* task_graph_runner, ContextProvider* context_provider, ResourceProvider* resource_provider, - ResourcePool* resource_pool) { + ResourcePool* resource_pool, + int max_copy_texture_chromium_size, + bool have_persistent_gpu_memory_buffers) { return make_scoped_ptr<TileTaskWorkerPool>(new OneCopyTileTaskWorkerPool( task_runner, task_graph_runner, context_provider, resource_provider, - resource_pool)); + resource_pool, max_copy_texture_chromium_size, + have_persistent_gpu_memory_buffers)); } OneCopyTileTaskWorkerPool::OneCopyTileTaskWorkerPool( @@ -116,18 +147,26 @@ OneCopyTileTaskWorkerPool::OneCopyTileTaskWorkerPool( TaskGraphRunner* task_graph_runner, ContextProvider* context_provider, ResourceProvider* resource_provider, - ResourcePool* resource_pool) + ResourcePool* resource_pool, + int max_copy_texture_chromium_size, + bool have_persistent_gpu_memory_buffers) : task_runner_(task_runner), task_graph_runner_(task_graph_runner), namespace_token_(task_graph_runner->GetNamespaceToken()), context_provider_(context_provider), resource_provider_(resource_provider), resource_pool_(resource_pool), + max_bytes_per_copy_operation_( + max_copy_texture_chromium_size + ? std::min(kMaxBytesPerCopyOperation, + max_copy_texture_chromium_size) + : kMaxBytesPerCopyOperation), + have_persistent_gpu_memory_buffers_(have_persistent_gpu_memory_buffers), last_issued_copy_operation_(0), last_flushed_copy_operation_(0), lock_(), copy_operation_count_cv_(&lock_), - scheduled_copy_operation_count_(0), + bytes_scheduled_since_last_flush_(0), issued_copy_operation_count_(0), next_copy_operation_sequence_(1), check_for_completed_copy_operations_pending_(false), @@ -138,7 +177,7 @@ OneCopyTileTaskWorkerPool::OneCopyTileTaskWorkerPool( } OneCopyTileTaskWorkerPool::~OneCopyTileTaskWorkerPool() { - DCHECK_EQ(scheduled_copy_operation_count_, 0u); + DCHECK_EQ(pending_copy_operations_.size(), 0u); } TileTaskRunner* OneCopyTileTaskWorkerPool::AsTileTaskRunner() { @@ -180,7 +219,7 @@ void OneCopyTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) { // Mark all task sets as pending. tasks_pending_.set(); - unsigned priority = kTileTaskPriorityBase; + size_t priority = kTileTaskPriorityBase; graph_.Reset(); @@ -257,17 +296,25 @@ void OneCopyTileTaskWorkerPool::CheckForCompletedTasks() { completed_tasks_.clear(); } -ResourceFormat OneCopyTileTaskWorkerPool::GetResourceFormat() { +ResourceFormat OneCopyTileTaskWorkerPool::GetResourceFormat() const { return resource_provider_->best_texture_format(); } +bool OneCopyTileTaskWorkerPool::GetResourceRequiresSwizzle() const { + return !PlatformColor::SameComponentOrder(GetResourceFormat()); +} + scoped_ptr<RasterBuffer> OneCopyTileTaskWorkerPool::AcquireBufferForRaster( - const Resource* resource) { + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) { + // TODO(danakj): If resource_content_id != 0, we only need to copy/upload + // the dirty rect. DCHECK_EQ(resource->format(), resource_provider_->best_texture_format()); return make_scoped_ptr<RasterBuffer>( new RasterBufferImpl(this, resource_provider_, resource_pool_, - resource_provider_->best_texture_format(), - resource)); + resource_provider_->best_texture_format(), resource, + previous_content_id)); } void OneCopyTileTaskWorkerPool::ReleaseBufferForRaster( @@ -277,74 +324,108 @@ void OneCopyTileTaskWorkerPool::ReleaseBufferForRaster( CopySequenceNumber OneCopyTileTaskWorkerPool::PlaybackAndScheduleCopyOnWorkerThread( - scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock, - scoped_ptr<ScopedResource> src, - const Resource* dst, + bool reusing_raster_resource, + scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> + raster_resource_write_lock, + const Resource* raster_resource, + const Resource* output_resource, const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& raster_dirty_rect, float scale) { - base::AutoLock lock(lock_); - - int failed_attempts = 0; - while ((scheduled_copy_operation_count_ + issued_copy_operation_count_) >= - kMaxCopyOperations) { - // Ignore limit when shutdown is set. - if (shutdown_) - break; - - ++failed_attempts; - - // Schedule a check that will also wait for operations to complete - // after too many failed attempts. - bool wait_if_needed = failed_attempts > kFailedAttemptsBeforeWaitIfNeeded; - - // Schedule a check for completed copy operations if too many operations - // are currently in-flight. - ScheduleCheckForCompletedCopyOperationsWithLockAcquired(wait_if_needed); - - { - TRACE_EVENT0("cc", "WaitingForCopyOperationsToComplete"); - - // Wait for in-flight copy operations to drop below limit. - copy_operation_count_cv_.Wait(); + gfx::GpuMemoryBuffer* gpu_memory_buffer = + raster_resource_write_lock->GetGpuMemoryBuffer(); + if (gpu_memory_buffer) { + void* data = NULL; + bool rv = gpu_memory_buffer->Map(&data); + DCHECK(rv); + int stride; + gpu_memory_buffer->GetStride(&stride); + // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides. + DCHECK_GE(stride, 0); + + gfx::Rect playback_rect = raster_full_rect; + if (reusing_raster_resource) { + playback_rect.Intersect(raster_dirty_rect); } + DCHECK(!playback_rect.IsEmpty()) + << "Why are we rastering a tile that's not dirty?"; + TileTaskWorkerPool::PlaybackToMemory( + data, raster_resource->format(), raster_resource->size(), + static_cast<size_t>(stride), raster_source, raster_full_rect, + playback_rect, scale); + gpu_memory_buffer->Unmap(); } - // Increment |scheduled_copy_operation_count_| before releasing |lock_|. - ++scheduled_copy_operation_count_; - - // There may be more work available, so wake up another worker thread. - copy_operation_count_cv_.Signal(); + base::AutoLock lock(lock_); - { - base::AutoUnlock unlock(lock_); - - gfx::GpuMemoryBuffer* gpu_memory_buffer = write_lock->GetGpuMemoryBuffer(); - if (gpu_memory_buffer) { - void* data = NULL; - bool rv = gpu_memory_buffer->Map(&data); - DCHECK(rv); - int stride; - gpu_memory_buffer->GetStride(&stride); - TileTaskWorkerPool::PlaybackToMemory(data, src->format(), src->size(), - stride, raster_source, rect, scale); - gpu_memory_buffer->Unmap(); + CopySequenceNumber sequence = 0; + int bytes_per_row = (BitsPerPixel(raster_resource->format()) * + raster_resource->size().width()) / + 8; + int chunk_size_in_rows = + std::max(1, max_bytes_per_copy_operation_ / bytes_per_row); + // Align chunk size to 4. Required to support compressed texture formats. + chunk_size_in_rows = MathUtil::RoundUp(chunk_size_in_rows, 4); + int y = 0; + int height = raster_resource->size().height(); + while (y < height) { + int failed_attempts = 0; + while ((pending_copy_operations_.size() + issued_copy_operation_count_) >= + kMaxCopyOperations) { + // Ignore limit when shutdown is set. + if (shutdown_) + break; + + ++failed_attempts; + + // Schedule a check that will also wait for operations to complete + // after too many failed attempts. + bool wait_if_needed = failed_attempts > kFailedAttemptsBeforeWaitIfNeeded; + + // Schedule a check for completed copy operations if too many operations + // are currently in-flight. + ScheduleCheckForCompletedCopyOperationsWithLockAcquired(wait_if_needed); + + { + TRACE_EVENT0("cc", "WaitingForCopyOperationsToComplete"); + + // Wait for in-flight copy operations to drop below limit. + copy_operation_count_cv_.Wait(); + } } - } - - pending_copy_operations_.push_back( - make_scoped_ptr(new CopyOperation(write_lock.Pass(), src.Pass(), dst))); - // Acquire a sequence number for this copy operation. - CopySequenceNumber sequence = next_copy_operation_sequence_++; + // There may be more work available, so wake up another worker thread. + copy_operation_count_cv_.Signal(); - // Post task that will advance last flushed copy operation to |sequence| - // if we have reached the flush period. - if ((sequence % kCopyFlushPeriod) == 0) { - task_runner_->PostTask( - FROM_HERE, - base::Bind(&OneCopyTileTaskWorkerPool::AdvanceLastFlushedCopyTo, - weak_ptr_factory_.GetWeakPtr(), sequence)); + // Copy at most |chunk_size_in_rows|. + int rows_to_copy = std::min(chunk_size_in_rows, height - y); + DCHECK_GT(rows_to_copy, 0); + + // |raster_resource_write_lock| is passed to the first copy operation as it + // needs to be released before we can issue a copy. + pending_copy_operations_.push_back(make_scoped_ptr(new CopyOperation( + raster_resource_write_lock.Pass(), raster_resource, output_resource, + gfx::Rect(0, y, raster_resource->size().width(), rows_to_copy)))); + y += rows_to_copy; + + // Acquire a sequence number for this copy operation. + sequence = next_copy_operation_sequence_++; + + // Increment |bytes_scheduled_since_last_flush_| by the amount of memory + // used for this copy operation. + bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row; + + // Post task that will advance last flushed copy operation to |sequence| + // when |bytes_scheduled_since_last_flush_| has reached + // |max_bytes_per_copy_operation_|. + if (bytes_scheduled_since_last_flush_ >= max_bytes_per_copy_operation_) { + task_runner_->PostTask( + FROM_HERE, + base::Bind(&OneCopyTileTaskWorkerPool::AdvanceLastFlushedCopyTo, + weak_ptr_factory_.GetWeakPtr(), sequence)); + bytes_scheduled_since_last_flush_ = 0; + } } return sequence; @@ -400,11 +481,8 @@ void OneCopyTileTaskWorkerPool::IssueCopyOperations(int64 count) { copy_operations.push_back(pending_copy_operations_.take_front()); } - // Decrement |scheduled_copy_operation_count_| and increment - // |issued_copy_operation_count_| to reflect the transition of copy - // operations from "pending" to "issued" state. - DCHECK_GE(scheduled_copy_operation_count_, copy_operations.size()); - scheduled_copy_operation_count_ -= copy_operations.size(); + // Increment |issued_copy_operation_count_| to reflect the transition of + // copy operations from "pending" to "issued" state. issued_copy_operation_count_ += copy_operations.size(); } @@ -412,15 +490,12 @@ void OneCopyTileTaskWorkerPool::IssueCopyOperations(int64 count) { scoped_ptr<CopyOperation> copy_operation = copy_operations.take_front(); // Remove the write lock. - copy_operation->write_lock.reset(); + copy_operation->src_write_lock.reset(); // Copy contents of source resource to destination resource. resource_provider_->CopyResource(copy_operation->src->id(), - copy_operation->dst->id()); - - // Return source resource to pool where it can be reused once copy - // operation has completed and resource is no longer busy. - resource_pool_->ReleaseResource(copy_operation->src.Pass()); + copy_operation->dst->id(), + copy_operation->rect); } } @@ -496,16 +571,20 @@ OneCopyTileTaskWorkerPool::StateAsValue() const { void OneCopyTileTaskWorkerPool::StagingStateAsValueInto( base::trace_event::TracedValue* staging_state) const { - staging_state->SetInteger("staging_resource_count", - resource_pool_->total_resource_count()); - staging_state->SetInteger("bytes_used_for_staging_resources", - resource_pool_->total_memory_usage_bytes()); - staging_state->SetInteger("pending_copy_count", - resource_pool_->total_resource_count() - - resource_pool_->acquired_resource_count()); - staging_state->SetInteger("bytes_pending_copy", - resource_pool_->total_memory_usage_bytes() - - resource_pool_->acquired_memory_usage_bytes()); + staging_state->SetInteger( + "staging_resource_count", + static_cast<int>(resource_pool_->total_resource_count())); + staging_state->SetInteger( + "bytes_used_for_staging_resources", + static_cast<int>(resource_pool_->total_memory_usage_bytes())); + staging_state->SetInteger( + "pending_copy_count", + static_cast<int>(resource_pool_->total_resource_count() - + resource_pool_->acquired_resource_count())); + staging_state->SetInteger( + "bytes_pending_copy", + static_cast<int>(resource_pool_->total_memory_usage_bytes() - + resource_pool_->acquired_memory_usage_bytes())); } } // namespace cc diff --git a/chromium/cc/raster/one_copy_tile_task_worker_pool.h b/chromium/cc/raster/one_copy_tile_task_worker_pool.h index 35b8873033a..518aaa2d490 100644 --- a/chromium/cc/raster/one_copy_tile_task_worker_pool.h +++ b/chromium/cc/raster/one_copy_tile_task_worker_pool.h @@ -38,7 +38,9 @@ class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool, TaskGraphRunner* task_graph_runner, ContextProvider* context_provider, ResourceProvider* resource_provider, - ResourcePool* resource_pool); + ResourcePool* resource_pool, + int max_copy_texture_chromium_size, + bool have_persistent_gpu_memory_buffers); // Overridden from TileTaskWorkerPool: TileTaskRunner* AsTileTaskRunner() override; @@ -48,47 +50,62 @@ class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool, void Shutdown() override; void ScheduleTasks(TileTaskQueue* queue) override; void CheckForCompletedTasks() override; - ResourceFormat GetResourceFormat() override; + ResourceFormat GetResourceFormat() const override; + bool GetResourceRequiresSwizzle() const override; // Overridden from TileTaskClient: scoped_ptr<RasterBuffer> AcquireBufferForRaster( - const Resource* resource) override; + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) override; void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override; - // Playback raster source and schedule copy of |src| resource to |dst| - // resource. Returns a non-zero sequence number for this copy operation. + // Playback raster source and schedule copy of |raster_resource| resource to + // |output_resource|. Returns a non-zero sequence number for this copy + // operation. CopySequenceNumber PlaybackAndScheduleCopyOnWorkerThread( - scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock, - scoped_ptr<ScopedResource> src, - const Resource* dst, + bool reusing_raster_resource, + scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> + raster_resource_write_lock, + const Resource* raster_resource, + const Resource* output_resource, const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& raster_dirty_rect, float scale); // Issues copy operations until |sequence| has been processed. This will // return immediately if |sequence| has already been processed. void AdvanceLastIssuedCopyTo(CopySequenceNumber sequence); + bool have_persistent_gpu_memory_buffers() const { + return have_persistent_gpu_memory_buffers_; + } + protected: OneCopyTileTaskWorkerPool(base::SequencedTaskRunner* task_runner, TaskGraphRunner* task_graph_runner, ContextProvider* context_provider, ResourceProvider* resource_provider, - ResourcePool* resource_pool); + ResourcePool* resource_pool, + int max_copy_texture_chromium_size, + bool have_persistent_gpu_memory_buffers); private: struct CopyOperation { typedef ScopedPtrDeque<CopyOperation> Deque; - CopyOperation( - scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock, - scoped_ptr<ScopedResource> src, - const Resource* dst); + CopyOperation(scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> + src_write_lock, + const Resource* src, + const Resource* dst, + const gfx::Rect& rect); ~CopyOperation(); - scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock; - scoped_ptr<ScopedResource> src; + scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> src_write_lock; + const Resource* src; const Resource* dst; + const gfx::Rect rect; }; void OnTaskSetFinished(TaskSet task_set); @@ -109,6 +126,8 @@ class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool, ContextProvider* context_provider_; ResourceProvider* resource_provider_; ResourcePool* resource_pool_; + const int max_bytes_per_copy_operation_; + const bool have_persistent_gpu_memory_buffers_; TaskSetCollection tasks_pending_; scoped_refptr<TileTask> task_set_finished_tasks_[kNumberOfTaskSets]; CopySequenceNumber last_issued_copy_operation_; @@ -122,7 +141,7 @@ class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool, base::Lock lock_; // |lock_| must be acquired when accessing the following members. base::ConditionVariable copy_operation_count_cv_; - size_t scheduled_copy_operation_count_; + int bytes_scheduled_since_last_flush_; size_t issued_copy_operation_count_; CopyOperation::Deque pending_copy_operations_; CopySequenceNumber next_copy_operation_sequence_; diff --git a/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.cc b/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.cc index 674e145c534..df79519485d 100644 --- a/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.cc +++ b/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.cc @@ -12,6 +12,7 @@ #include "base/trace_event/trace_event_argument.h" #include "cc/debug/traced_value.h" #include "cc/raster/raster_buffer.h" +#include "cc/resources/platform_color.h" #include "cc/resources/resource.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -36,14 +37,19 @@ class RasterBufferImpl : public RasterBuffer { // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& raster_dirty_rect, + uint64_t new_content_id, float scale) override { if (!memory_) return; - TileTaskWorkerPool::PlaybackToMemory(memory_, resource_->format(), - resource_->size(), stride_, - raster_source, rect, scale); + // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides. + DCHECK_GE(stride_, 0); + TileTaskWorkerPool::PlaybackToMemory( + memory_, resource_->format(), resource_->size(), + static_cast<size_t>(stride_), raster_source, raster_full_rect, + raster_full_rect, scale); } private: @@ -307,12 +313,18 @@ void PixelBufferTileTaskWorkerPool::CheckForCompletedTasks() { completed_raster_tasks_.clear(); } -ResourceFormat PixelBufferTileTaskWorkerPool::GetResourceFormat() { +ResourceFormat PixelBufferTileTaskWorkerPool::GetResourceFormat() const { return resource_provider_->memory_efficient_texture_format(); } +bool PixelBufferTileTaskWorkerPool::GetResourceRequiresSwizzle() const { + return !PlatformColor::SameComponentOrder(GetResourceFormat()); +} + scoped_ptr<RasterBuffer> PixelBufferTileTaskWorkerPool::AcquireBufferForRaster( - const Resource* resource) { + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) { return make_scoped_ptr<RasterBuffer>( new RasterBufferImpl(resource_provider_, resource)); } @@ -424,7 +436,10 @@ void PixelBufferTileTaskWorkerPool::CheckForCompletedUploads() { DCHECK(state_it != raster_task_states_.end()); RasterTaskState& state = *state_it; - bytes_pending_upload_ -= task->resource()->bytes(); + // We can use UncheckedMemorySizeBytes here, since these tasks come from + // tiles, the size of which is controlled by the compositor. + bytes_pending_upload_ -= Resource::UncheckedMemorySizeBytes( + task->resource()->size(), task->resource()->format()); task->WillComplete(); task->CompleteOnOriginThread(this); @@ -493,7 +508,7 @@ void PixelBufferTileTaskWorkerPool::ScheduleMoreTasks() { RasterTaskVector tasks[kNumberOfTaskSets]; - unsigned priority = kTileTaskPriorityBase; + size_t priority = kTileTaskPriorityBase; graph_.Reset(); @@ -530,7 +545,10 @@ void PixelBufferTileTaskWorkerPool::ScheduleMoreTasks() { // but if it's the only task allow it to complete no matter what its size, // to prevent starvation of the task queue. size_t new_bytes_pending_upload = bytes_pending_upload; - new_bytes_pending_upload += task->resource()->bytes(); + // We can use UncheckedMemorySizeBytes here, since these tasks come from + // tiles, the size of which is controlled by the compositor. + new_bytes_pending_upload += Resource::UncheckedMemorySizeBytes( + task->resource()->size(), task->resource()->format()); if (new_bytes_pending_upload > max_bytes_pending_upload_ && bytes_pending_upload) { did_throttle_raster_tasks |= item.task_sets; @@ -611,8 +629,8 @@ void PixelBufferTileTaskWorkerPool::ScheduleMoreTasks() { task_set_finished_tasks_); } -unsigned PixelBufferTileTaskWorkerPool::PendingRasterTaskCount() const { - unsigned num_completed_raster_tasks = +size_t PixelBufferTileTaskWorkerPool::PendingRasterTaskCount() const { + size_t num_completed_raster_tasks = raster_tasks_with_pending_upload_.size() + completed_raster_tasks_.size(); DCHECK_GE(raster_task_states_.size(), num_completed_raster_tasks); return raster_task_states_.size() - num_completed_raster_tasks; @@ -694,7 +712,10 @@ void PixelBufferTileTaskWorkerPool::CheckForCompletedRasterizerTasks() { resource_provider_->BeginSetPixels(raster_task->resource()->id()); has_performed_uploads_since_last_flush_ = true; - bytes_pending_upload_ += raster_task->resource()->bytes(); + // We can use UncheckedMemorySizeBytes here, since these tasks come from + // tiles, the size of which is controlled by the compositor. + bytes_pending_upload_ += Resource::UncheckedMemorySizeBytes( + raster_task->resource()->size(), raster_task->resource()->format()); raster_tasks_with_pending_upload_.push_back(raster_task); state.type = RasterTaskState::UPLOADING; } @@ -705,13 +726,14 @@ scoped_refptr<base::trace_event::ConvertableToTraceFormat> PixelBufferTileTaskWorkerPool::StateAsValue() const { scoped_refptr<base::trace_event::TracedValue> state = new base::trace_event::TracedValue(); - state->SetInteger("completed_count", completed_raster_tasks_.size()); + state->SetInteger("completed_count", + static_cast<int>(completed_raster_tasks_.size())); state->BeginArray("pending_count"); for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) - state->AppendInteger(task_counts_[task_set]); + state->AppendInteger(static_cast<int>(task_counts_[task_set])); state->EndArray(); state->SetInteger("pending_upload_count", - raster_tasks_with_pending_upload_.size()); + static_cast<int>(raster_tasks_with_pending_upload_.size())); state->BeginDictionary("throttle_state"); ThrottleStateAsValueInto(state.get()); state->EndDictionary(); @@ -720,11 +742,13 @@ PixelBufferTileTaskWorkerPool::StateAsValue() const { void PixelBufferTileTaskWorkerPool::ThrottleStateAsValueInto( base::trace_event::TracedValue* throttle_state) const { - throttle_state->SetInteger("bytes_available_for_upload", - max_bytes_pending_upload_ - bytes_pending_upload_); - throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_); + throttle_state->SetInteger( + "bytes_available_for_upload", + static_cast<int>(max_bytes_pending_upload_ - bytes_pending_upload_)); + throttle_state->SetInteger("bytes_pending_upload", + static_cast<int>(bytes_pending_upload_)); throttle_state->SetInteger("scheduled_raster_task_count", - scheduled_raster_task_count_); + static_cast<int>(scheduled_raster_task_count_)); } } // namespace cc diff --git a/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.h b/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.h index e6ddd39312d..2c6aeb98228 100644 --- a/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.h +++ b/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.h @@ -46,11 +46,14 @@ class CC_EXPORT PixelBufferTileTaskWorkerPool : public TileTaskWorkerPool, void Shutdown() override; void ScheduleTasks(TileTaskQueue* queue) override; void CheckForCompletedTasks() override; - ResourceFormat GetResourceFormat() override; + ResourceFormat GetResourceFormat() const override; + bool GetResourceRequiresSwizzle() const override; // Overridden from TileTaskClient: scoped_ptr<RasterBuffer> AcquireBufferForRaster( - const Resource* resource) override; + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) override; void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override; private: @@ -89,7 +92,7 @@ class CC_EXPORT PixelBufferTileTaskWorkerPool : public TileTaskWorkerPool, void CheckForCompletedUploads(); void CheckForCompletedRasterTasks(); void ScheduleMoreTasks(); - unsigned PendingRasterTaskCount() const; + size_t PendingRasterTaskCount() const; TaskSetCollection PendingTasks() const; void CheckForCompletedRasterizerTasks(); diff --git a/chromium/cc/raster/raster_buffer.h b/chromium/cc/raster/raster_buffer.h index 8f3a56200f6..5af4deca25b 100644 --- a/chromium/cc/raster/raster_buffer.h +++ b/chromium/cc/raster/raster_buffer.h @@ -17,7 +17,9 @@ class CC_EXPORT RasterBuffer { virtual ~RasterBuffer(); virtual void Playback(const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& raster_dirty_rect, + uint64_t new_content_id, float scale) = 0; }; diff --git a/chromium/cc/raster/task_graph_runner.h b/chromium/cc/raster/task_graph_runner.h index a54984353b0..bb55afc19ae 100644 --- a/chromium/cc/raster/task_graph_runner.h +++ b/chromium/cc/raster/task_graph_runner.h @@ -53,11 +53,11 @@ struct CC_EXPORT TaskGraph { typedef std::vector<Node> Vector; - Node(Task* task, unsigned priority, size_t dependencies) + Node(Task* task, size_t priority, size_t dependencies) : task(task), priority(priority), dependencies(dependencies) {} Task* task; - unsigned priority; + size_t priority; size_t dependencies; }; @@ -141,11 +141,11 @@ class CC_EXPORT TaskGraphRunner { struct PrioritizedTask { typedef std::vector<PrioritizedTask> Vector; - PrioritizedTask(Task* task, unsigned priority) + PrioritizedTask(Task* task, size_t priority) : task(task), priority(priority) {} Task* task; - unsigned priority; + size_t priority; }; typedef std::vector<const Task*> TaskVector; diff --git a/chromium/cc/raster/texture_compressor_etc1_unittest.cc b/chromium/cc/raster/texture_compressor_etc1_unittest.cc index 98ccd77560f..d0c63f46f63 100644 --- a/chromium/cc/raster/texture_compressor_etc1_unittest.cc +++ b/chromium/cc/raster/texture_compressor_etc1_unittest.cc @@ -4,7 +4,6 @@ #include "cc/raster/texture_compressor.h" -#include "cc/base/util.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { diff --git a/chromium/cc/raster/tile_task_runner.h b/chromium/cc/raster/tile_task_runner.h index 234ca6f04ab..9dffee48c74 100644 --- a/chromium/cc/raster/tile_task_runner.h +++ b/chromium/cc/raster/tile_task_runner.h @@ -21,7 +21,9 @@ class RasterBuffer; class CC_EXPORT TileTaskClient { public: virtual scoped_ptr<RasterBuffer> AcquireBufferForRaster( - const Resource* resource) = 0; + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) = 0; virtual void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) = 0; protected: @@ -161,7 +163,10 @@ class CC_EXPORT TileTaskRunner { virtual void CheckForCompletedTasks() = 0; // Returns the format to use for the tiles. - virtual ResourceFormat GetResourceFormat() = 0; + virtual ResourceFormat GetResourceFormat() const = 0; + + // Determine if the resource requires swizzling. + virtual bool GetResourceRequiresSwizzle() const = 0; protected: virtual ~TileTaskRunner() {} diff --git a/chromium/cc/raster/tile_task_worker_pool.cc b/chromium/cc/raster/tile_task_worker_pool.cc index 477acc31263..d349514c4e8 100644 --- a/chromium/cc/raster/tile_task_worker_pool.cc +++ b/chromium/cc/raster/tile_task_worker_pool.cc @@ -52,14 +52,14 @@ class TaskSetFinishedTaskImpl : public TileTask { // This allows a micro benchmark system to run tasks with highest priority, // since it should finish as quickly as possible. -unsigned TileTaskWorkerPool::kBenchmarkTaskPriority = 0u; +size_t TileTaskWorkerPool::kBenchmarkTaskPriority = 0u; // Task priorities that make sure task set finished tasks run before any // other remaining tasks. This is combined with the task set type to ensure // proper prioritization ordering between task set types. -unsigned TileTaskWorkerPool::kTaskSetFinishedTaskPriorityBase = 1u; +size_t TileTaskWorkerPool::kTaskSetFinishedTaskPriorityBase = 1u; // For correctness, |kTileTaskPriorityBase| must be greater than // |kTaskSetFinishedTaskPriorityBase + kNumberOfTaskSets|. -unsigned TileTaskWorkerPool::kTileTaskPriorityBase = 10u; +size_t TileTaskWorkerPool::kTileTaskPriorityBase = 10u; TileTaskWorkerPool::TileTaskWorkerPool() { } @@ -96,7 +96,7 @@ void TileTaskWorkerPool::ScheduleTasksOnOriginThread(TileTaskClient* client, // static void TileTaskWorkerPool::InsertNodeForTask(TaskGraph* graph, TileTask* task, - unsigned priority, + size_t priority, size_t dependencies) { DCHECK(std::find_if(graph->nodes.begin(), graph->nodes.end(), TaskGraph::Node::TaskComparator(task)) == @@ -109,7 +109,7 @@ void TileTaskWorkerPool::InsertNodesForRasterTask( TaskGraph* graph, RasterTask* raster_task, const ImageDecodeTask::Vector& decode_tasks, - unsigned priority) { + size_t priority) { size_t dependencies = 0u; // Insert image decode tasks. @@ -157,9 +157,10 @@ static bool IsSupportedPlaybackToMemoryFormat(ResourceFormat format) { void TileTaskWorkerPool::PlaybackToMemory(void* memory, ResourceFormat format, const gfx::Size& size, - int stride, + size_t stride, const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, float scale) { DCHECK(IsSupportedPlaybackToMemoryFormat(format)) << format; @@ -178,23 +179,26 @@ void TileTaskWorkerPool::PlaybackToMemory(void* memory, if (!stride) stride = info.minRowBytes(); - DCHECK_GT(stride, 0); + DCHECK_GT(stride, 0u); if (!needs_copy) { skia::RefPtr<SkSurface> surface = skia::AdoptRef( SkSurface::NewRasterDirect(info, memory, stride, &surface_props)); skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas()); - raster_source->PlaybackToCanvas(canvas.get(), rect, scale); + raster_source->PlaybackToCanvas(canvas.get(), canvas_bitmap_rect, + canvas_playback_rect, scale); return; } skia::RefPtr<SkSurface> surface = skia::AdoptRef(SkSurface::NewRaster(info, &surface_props)); skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas()); - raster_source->PlaybackToCanvas(canvas.get(), rect, scale); + raster_source->PlaybackToCanvas(canvas.get(), canvas_bitmap_rect, + canvas_playback_rect, scale); - SkImageInfo dst_info = info; - dst_info.fColorType = buffer_color_type; + SkImageInfo dst_info = + SkImageInfo::Make(info.width(), info.height(), buffer_color_type, + info.alphaType(), info.profileType()); // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the // bitmap data. There will be no need to call SkAlign4 once crbug.com/293728 // is fixed. diff --git a/chromium/cc/raster/tile_task_worker_pool.h b/chromium/cc/raster/tile_task_worker_pool.h index 75916f5dd6f..ff001890507 100644 --- a/chromium/cc/raster/tile_task_worker_pool.h +++ b/chromium/cc/raster/tile_task_worker_pool.h @@ -19,9 +19,9 @@ class RenderingStatsInstrumentation; class CC_EXPORT TileTaskWorkerPool { public: - static unsigned kBenchmarkTaskPriority; - static unsigned kTaskSetFinishedTaskPriorityBase; - static unsigned kTileTaskPriorityBase; + static size_t kBenchmarkTaskPriority; + static size_t kTaskSetFinishedTaskPriorityBase; + static size_t kTileTaskPriorityBase; TileTaskWorkerPool(); virtual ~TileTaskWorkerPool(); @@ -42,7 +42,7 @@ class CC_EXPORT TileTaskWorkerPool { // |priority| values. static void InsertNodeForTask(TaskGraph* graph, TileTask* task, - unsigned priority, + size_t priority, size_t dependencies); // Utility function that can be used to build a task graph. Inserts nodes that @@ -51,16 +51,21 @@ class CC_EXPORT TileTaskWorkerPool { TaskGraph* graph, RasterTask* task, const ImageDecodeTask::Vector& decode_tasks, - unsigned priority); + size_t priority); // Utility function that will create a temporary bitmap and copy pixels to - // |memory| when necessary. + // |memory| when necessary. The |canvas_bitmap_rect| is the rect of the bitmap + // being played back in the pixel space of the source, ie a rect in the source + // that will cover the resulting |memory|. The |canvas_playback_rect| can be a + // smaller contained rect inside the |canvas_bitmap_rect| if the |memory| is + // already partially complete, and only the subrect needs to be played back. static void PlaybackToMemory(void* memory, ResourceFormat format, const gfx::Size& size, - int stride, + size_t stride, const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, float scale); // Type-checking downcast routine. diff --git a/chromium/cc/raster/tile_task_worker_pool_perftest.cc b/chromium/cc/raster/tile_task_worker_pool_perftest.cc index 508f966eeb7..b49c498ac05 100644 --- a/chromium/cc/raster/tile_task_worker_pool_perftest.cc +++ b/chromium/cc/raster/tile_task_worker_pool_perftest.cc @@ -21,6 +21,7 @@ #include "cc/resources/scoped_resource.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/test_context_support.h" #include "cc/test/test_gpu_memory_buffer_manager.h" #include "cc/test/test_shared_bitmap_manager.h" @@ -96,7 +97,6 @@ class PerfContextProvider : public ContextProvider { } void SetupLock() override {} base::Lock* GetLock() override { return &context_lock_; } - bool IsContextLost() override { return false; } void VerifyContexts() override {} void DeleteCachedResources() override {} bool DestroyedOnMainThread() override { return false; } @@ -160,7 +160,8 @@ class PerfRasterTaskImpl : public RasterTask { // Overridden from TileTask: void ScheduleOnOriginThread(TileTaskClient* client) override { - raster_buffer_ = client->AcquireBufferForRaster(resource()); + // No tile ids are given to support partial updates. + raster_buffer_ = client->AcquireBufferForRaster(resource(), 0, 0); } void CompleteOnOriginThread(TileTaskClient* client) override { client->ReleaseBufferForRaster(raster_buffer_.Pass()); @@ -269,7 +270,8 @@ class TileTaskWorkerPoolPerfTest tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create( task_runner_.get(), task_graph_runner_.get(), context_provider_.get(), resource_provider_.get(), - staging_resource_pool_.get()); + staging_resource_pool_.get(), std::numeric_limits<int>::max(), + false); break; case TILE_TASK_WORKER_POOL_TYPE_GPU: Create3dOutputSurfaceAndResourceProvider(); @@ -400,18 +402,16 @@ class TileTaskWorkerPoolPerfTest void Create3dOutputSurfaceAndResourceProvider() { output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass(); CHECK(output_surface_->BindToClient(&output_surface_client_)); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), NULL, - &gpu_memory_buffer_manager_, - NULL, 0, false, 1).Pass(); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), nullptr, &gpu_memory_buffer_manager_); } void CreateSoftwareOutputSurfaceAndResourceProvider() { output_surface_ = FakeOutputSurface::CreateSoftware( make_scoped_ptr(new SoftwareOutputDevice)); CHECK(output_surface_->BindToClient(&output_surface_client_)); - resource_provider_ = - ResourceProvider::Create(output_surface_.get(), &shared_bitmap_manager_, - NULL, NULL, 0, false, 1).Pass(); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), &shared_bitmap_manager_, nullptr); } std::string TestModifierString() const { @@ -481,8 +481,7 @@ class TileTaskWorkerPoolCommonPerfTest : public TileTaskWorkerPoolPerfTestBase, output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass(); CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), NULL, NULL, NULL, 0, - false, 1).Pass(); + FakeResourceProvider::Create(output_surface_.get(), nullptr); } void RunBuildTileTaskQueueTest(const std::string& test_name, diff --git a/chromium/cc/raster/tile_task_worker_pool_unittest.cc b/chromium/cc/raster/tile_task_worker_pool_unittest.cc index 7394af59a90..76e5fe4d56f 100644 --- a/chromium/cc/raster/tile_task_worker_pool_unittest.cc +++ b/chromium/cc/raster/tile_task_worker_pool_unittest.cc @@ -28,6 +28,7 @@ #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_picture_pile_impl.h" +#include "cc/test/fake_resource_provider.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" @@ -39,6 +40,8 @@ namespace cc { namespace { const size_t kMaxTransferBufferUsageBytes = 10000U; +const size_t kMaxBytesPerCopyOperation = 1000U; + // A resource of this dimension^2 * 4 must be greater than the above transfer // buffer constant. const size_t kLargeResourceDimension = 1000U; @@ -66,12 +69,16 @@ class TestRasterTaskImpl : public RasterTask { // Overridden from Task: void RunOnWorkerThread() override { - raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(0, 0, 1, 1), 1.0); + uint64_t new_content_id = 0; + raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(1, 1), + gfx::Rect(1, 1), new_content_id, 1.f); } // Overridden from TileTask: void ScheduleOnOriginThread(TileTaskClient* client) override { - raster_buffer_ = client->AcquireBufferForRaster(resource()); + // The raster buffer has no tile ids associated with it for partial update, + // so doesn't need to provide a valid dirty rect. + raster_buffer_ = client->AcquireBufferForRaster(resource(), 0, 0); } void CompleteOnOriginThread(TileTaskClient* client) override { client->ReleaseBufferForRaster(raster_buffer_.Pass()); @@ -163,7 +170,7 @@ class TileTaskWorkerPoolTest tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create( base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_, context_provider_.get(), resource_provider_.get(), - staging_resource_pool_.get()); + staging_resource_pool_.get(), kMaxBytesPerCopyOperation, false); break; case TILE_TASK_WORKER_POOL_TYPE_GPU: Create3dOutputSurfaceAndResourceProvider(); @@ -287,23 +294,21 @@ class TileTaskWorkerPoolTest private: void Create3dOutputSurfaceAndResourceProvider() { - output_surface_ = FakeOutputSurface::Create3d( - context_provider_, worker_context_provider_).Pass(); + output_surface_ = FakeOutputSurface::Create3d(context_provider_, + worker_context_provider_); CHECK(output_surface_->BindToClient(&output_surface_client_)); TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d(); context3d->set_support_sync_query(true); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), NULL, - &gpu_memory_buffer_manager_, - NULL, 0, false, 1).Pass(); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), nullptr, &gpu_memory_buffer_manager_); } void CreateSoftwareOutputSurfaceAndResourceProvider() { output_surface_ = FakeOutputSurface::CreateSoftware( make_scoped_ptr(new SoftwareOutputDevice)); CHECK(output_surface_->BindToClient(&output_surface_client_)); - resource_provider_ = - ResourceProvider::Create(output_surface_.get(), &shared_bitmap_manager_, - NULL, NULL, 0, false, 1).Pass(); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), &shared_bitmap_manager_, nullptr); } void OnTaskCompleted(scoped_ptr<ScopedResource> resource, @@ -401,7 +406,9 @@ TEST_P(TileTaskWorkerPoolTest, LargeResources) { ScopedResource::Create(resource_provider_.get())); resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); - EXPECT_GE(resource->bytes(), kMaxTransferBufferUsageBytes); + EXPECT_GE(Resource::UncheckedMemorySizeBytes(resource->size(), + resource->format()), + kMaxTransferBufferUsageBytes); } AppendTask(0u, size); @@ -429,6 +436,21 @@ TEST_P(TileTaskWorkerPoolTest, LostContext) { EXPECT_FALSE(completed_tasks()[1].canceled); } +TEST_P(TileTaskWorkerPoolTest, ScheduleEmptyStillTriggersCallback) { + // Don't append any tasks, just call ScheduleTasks. + ScheduleTasks(); + + EXPECT_FALSE(completed_task_sets_[REQUIRED_FOR_ACTIVATION]); + EXPECT_FALSE(completed_task_sets_[REQUIRED_FOR_DRAW]); + EXPECT_FALSE(completed_task_sets_[ALL]); + + RunMessageLoopUntilAllTasksHaveCompleted(); + + EXPECT_TRUE(completed_task_sets_[REQUIRED_FOR_ACTIVATION]); + EXPECT_TRUE(completed_task_sets_[REQUIRED_FOR_DRAW]); + EXPECT_TRUE(completed_task_sets_[ALL]); +} + INSTANTIATE_TEST_CASE_P( TileTaskWorkerPoolTests, TileTaskWorkerPoolTest, diff --git a/chromium/cc/raster/zero_copy_tile_task_worker_pool.cc b/chromium/cc/raster/zero_copy_tile_task_worker_pool.cc index 5a1dc23058b..64fc5f453b3 100644 --- a/chromium/cc/raster/zero_copy_tile_task_worker_pool.cc +++ b/chromium/cc/raster/zero_copy_tile_task_worker_pool.cc @@ -11,6 +11,7 @@ #include "base/trace_event/trace_event_argument.h" #include "cc/debug/traced_value.h" #include "cc/raster/raster_buffer.h" +#include "cc/resources/platform_color.h" #include "cc/resources/resource.h" #include "ui/gfx/gpu_memory_buffer.h" @@ -25,20 +26,25 @@ class RasterBufferImpl : public RasterBuffer { // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, - const gfx::Rect& rect, + const gfx::Rect& raster_full_rect, + const gfx::Rect& raster_dirty_rect, + uint64_t new_content_id, float scale) override { gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_.GetGpuMemoryBuffer(); if (!gpu_memory_buffer) return; - void* data = NULL; bool rv = gpu_memory_buffer->Map(&data); DCHECK(rv); int stride; gpu_memory_buffer->GetStride(&stride); - TileTaskWorkerPool::PlaybackToMemory(data, resource_->format(), - resource_->size(), stride, - raster_source, rect, scale); + // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides. + DCHECK_GE(stride, 0); + // TODO(danakj): Implement partial raster with raster_dirty_rect. + TileTaskWorkerPool::PlaybackToMemory( + data, resource_->format(), resource_->size(), + static_cast<size_t>(stride), raster_source, raster_full_rect, + raster_full_rect, scale); gpu_memory_buffer->Unmap(); } @@ -99,7 +105,7 @@ void ZeroCopyTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) { // Mark all task sets as pending. tasks_pending_.set(); - unsigned priority = kTileTaskPriorityBase; + size_t priority = kTileTaskPriorityBase; graph_.Reset(); @@ -171,12 +177,18 @@ void ZeroCopyTileTaskWorkerPool::CheckForCompletedTasks() { completed_tasks_.clear(); } -ResourceFormat ZeroCopyTileTaskWorkerPool::GetResourceFormat() { +ResourceFormat ZeroCopyTileTaskWorkerPool::GetResourceFormat() const { return resource_provider_->best_texture_format(); } +bool ZeroCopyTileTaskWorkerPool::GetResourceRequiresSwizzle() const { + return !PlatformColor::SameComponentOrder(GetResourceFormat()); +} + scoped_ptr<RasterBuffer> ZeroCopyTileTaskWorkerPool::AcquireBufferForRaster( - const Resource* resource) { + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) { return make_scoped_ptr<RasterBuffer>( new RasterBufferImpl(resource_provider_, resource)); } diff --git a/chromium/cc/raster/zero_copy_tile_task_worker_pool.h b/chromium/cc/raster/zero_copy_tile_task_worker_pool.h index 193eeda373d..7dcdff0a686 100644 --- a/chromium/cc/raster/zero_copy_tile_task_worker_pool.h +++ b/chromium/cc/raster/zero_copy_tile_task_worker_pool.h @@ -38,11 +38,14 @@ class CC_EXPORT ZeroCopyTileTaskWorkerPool : public TileTaskWorkerPool, void Shutdown() override; void ScheduleTasks(TileTaskQueue* queue) override; void CheckForCompletedTasks() override; - ResourceFormat GetResourceFormat() override; + ResourceFormat GetResourceFormat() const override; + bool GetResourceRequiresSwizzle() const override; // Overridden from TileTaskClient: scoped_ptr<RasterBuffer> AcquireBufferForRaster( - const Resource* resource) override; + const Resource* resource, + uint64_t resource_content_id, + uint64_t previous_content_id) override; void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override; protected: diff --git a/chromium/cc/resources/bitmap_content_layer_updater.cc b/chromium/cc/resources/bitmap_content_layer_updater.cc deleted file mode 100644 index 31a62c3d7a9..00000000000 --- a/chromium/cc/resources/bitmap_content_layer_updater.cc +++ /dev/null @@ -1,107 +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/resources/bitmap_content_layer_updater.h" - -#include "cc/debug/devtools_instrumentation.h" -#include "cc/debug/rendering_stats_instrumentation.h" -#include "cc/resources/layer_painter.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/resource_update.h" -#include "cc/resources/resource_update_queue.h" -#include "skia/ext/platform_canvas.h" - -namespace cc { - -BitmapContentLayerUpdater::Resource::Resource( - BitmapContentLayerUpdater* updater, - scoped_ptr<PrioritizedResource> texture) - : LayerUpdater::Resource(texture.Pass()), updater_(updater) {} - -BitmapContentLayerUpdater::Resource::~Resource() {} - -void BitmapContentLayerUpdater::Resource::Update( - ResourceUpdateQueue* queue, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update) { - updater_->UpdateTexture( - queue, texture(), source_rect, dest_offset, partial_update); -} - -scoped_refptr<BitmapContentLayerUpdater> BitmapContentLayerUpdater::Create( - scoped_ptr<LayerPainter> painter, - int layer_id) { - return make_scoped_refptr( - new BitmapContentLayerUpdater(painter.Pass(), - layer_id)); -} - -BitmapContentLayerUpdater::BitmapContentLayerUpdater( - scoped_ptr<LayerPainter> painter, - int layer_id) - : ContentLayerUpdater(painter.Pass(), layer_id) { -} - -BitmapContentLayerUpdater::~BitmapContentLayerUpdater() {} - -scoped_ptr<LayerUpdater::Resource> BitmapContentLayerUpdater::CreateResource( - PrioritizedResourceManager* manager) { - return make_scoped_ptr( - new Resource(this, PrioritizedResource::Create(manager))); -} - -void BitmapContentLayerUpdater::PrepareToUpdate(const gfx::Size& content_size, - const gfx::Rect& paint_rect, - const gfx::Size& tile_size, - float contents_width_scale, - float contents_height_scale) { - if (canvas_size_ != paint_rect.size()) { - devtools_instrumentation::ScopedLayerTask paint_setup( - devtools_instrumentation::kPaintSetup, layer_id_); - canvas_size_ = paint_rect.size(); - bitmap_backing_.allocN32Pixels( - canvas_size_.width(), canvas_size_.height(), layer_is_opaque_); - // TODO(danak): Remove when skia does the check for us: crbug.com/360384 - canvas_ = skia::AdoptRef(new SkCanvas(bitmap_backing_)); - DCHECK_EQ(paint_rect.width(), canvas_->getBaseLayerSize().width()); - DCHECK_EQ(paint_rect.height(), canvas_->getBaseLayerSize().height()); - } - - PaintContents(canvas_.get(), - content_size, - paint_rect, - contents_width_scale, - contents_height_scale); -} - -void BitmapContentLayerUpdater::UpdateTexture(ResourceUpdateQueue* queue, - PrioritizedResource* texture, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update) { - CHECK(canvas_); - ResourceUpdate upload = ResourceUpdate::Create( - texture, &bitmap_backing_, paint_rect(), source_rect, dest_offset); - if (partial_update) - queue->AppendPartialUpload(upload); - else - queue->AppendFullUpload(upload); -} - -void BitmapContentLayerUpdater::ReduceMemoryUsage() { - canvas_.clear(); - canvas_size_ = gfx::Size(); -} - -void BitmapContentLayerUpdater::SetOpaque(bool opaque) { - if (opaque != layer_is_opaque_) { - canvas_.clear(); - canvas_size_ = gfx::Size(); - } - - ContentLayerUpdater::SetOpaque(opaque); -} - -} // namespace cc diff --git a/chromium/cc/resources/bitmap_content_layer_updater.h b/chromium/cc/resources/bitmap_content_layer_updater.h deleted file mode 100644 index 34776002000..00000000000 --- a/chromium/cc/resources/bitmap_content_layer_updater.h +++ /dev/null @@ -1,78 +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. - -#ifndef CC_RESOURCES_BITMAP_CONTENT_LAYER_UPDATER_H_ -#define CC_RESOURCES_BITMAP_CONTENT_LAYER_UPDATER_H_ - -#include "cc/base/cc_export.h" -#include "cc/resources/content_layer_updater.h" -#include "skia/ext/refptr.h" -#include "third_party/skia/include/core/SkBitmap.h" - -class SkCanvas; - -namespace cc { - -class LayerPainter; -class RenderingStatsInstrumenation; - -// This class rasterizes the content_rect into a skia bitmap canvas. It then -// creates a ResourceUpdate with this bitmap canvas and inserts the -// ResourceBundle to the provided ResourceUpdateQueue. Actual texture uploading -// is done by ResourceUpdateController. -class CC_EXPORT BitmapContentLayerUpdater : public ContentLayerUpdater { - public: - class Resource : public LayerUpdater::Resource { - public: - Resource(BitmapContentLayerUpdater* updater, - scoped_ptr<PrioritizedResource> resource); - ~Resource() override; - - void Update(ResourceUpdateQueue* queue, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update) override; - - private: - BitmapContentLayerUpdater* updater_; - - DISALLOW_COPY_AND_ASSIGN(Resource); - }; - - static scoped_refptr<BitmapContentLayerUpdater> Create( - scoped_ptr<LayerPainter> painter, - int layer_id); - - scoped_ptr<LayerUpdater::Resource> CreateResource( - PrioritizedResourceManager* manager) override; - void PrepareToUpdate(const gfx::Size& content_size, - const gfx::Rect& paint_rect, - const gfx::Size& tile_size, - float contents_width_scale, - float contents_height_scale) override; - void UpdateTexture(ResourceUpdateQueue* queue, - PrioritizedResource* resource, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update); - void SetOpaque(bool opaque) override; - void ReduceMemoryUsage() override; - - protected: - BitmapContentLayerUpdater( - scoped_ptr<LayerPainter> painter, - int layer_id); - ~BitmapContentLayerUpdater() override; - - SkBitmap bitmap_backing_; - skia::RefPtr<SkCanvas> canvas_; - gfx::Size canvas_size_; - - private: - DISALLOW_COPY_AND_ASSIGN(BitmapContentLayerUpdater); -}; - -} // namespace cc - -#endif // CC_RESOURCES_BITMAP_CONTENT_LAYER_UPDATER_H_ diff --git a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc b/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc deleted file mode 100644 index a78a9df4ded..00000000000 --- a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc +++ /dev/null @@ -1,79 +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/resources/bitmap_skpicture_content_layer_updater.h" - -#include "base/time/time.h" -#include "cc/debug/rendering_stats_instrumentation.h" -#include "cc/resources/layer_painter.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/resource_update_queue.h" -#include "third_party/skia/include/core/SkCanvas.h" - -namespace cc { - -BitmapSkPictureContentLayerUpdater::Resource::Resource( - BitmapSkPictureContentLayerUpdater* updater, - scoped_ptr<PrioritizedResource> texture) - : ContentLayerUpdater::Resource(texture.Pass()), updater_(updater) {} - -void BitmapSkPictureContentLayerUpdater::Resource::Update( - ResourceUpdateQueue* queue, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update) { - SkAlphaType at = - updater_->layer_is_opaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType; - bitmap_.allocPixels(SkImageInfo::Make( - source_rect.width(), source_rect.height(), kN32_SkColorType, at)); - SkCanvas canvas(bitmap_); - updater_->PaintContentsRect(&canvas, source_rect); - - ResourceUpdate upload = ResourceUpdate::Create( - texture(), &bitmap_, source_rect, source_rect, dest_offset); - if (partial_update) - queue->AppendPartialUpload(upload); - else - queue->AppendFullUpload(upload); -} - -scoped_refptr<BitmapSkPictureContentLayerUpdater> -BitmapSkPictureContentLayerUpdater::Create( - scoped_ptr<LayerPainter> painter, - RenderingStatsInstrumentation* stats_instrumentation, - int layer_id) { - return make_scoped_refptr( - new BitmapSkPictureContentLayerUpdater(painter.Pass(), - stats_instrumentation, - layer_id)); -} - -BitmapSkPictureContentLayerUpdater::BitmapSkPictureContentLayerUpdater( - scoped_ptr<LayerPainter> painter, - RenderingStatsInstrumentation* stats_instrumentation, - int layer_id) - : SkPictureContentLayerUpdater(painter.Pass(), layer_id) { -} - -BitmapSkPictureContentLayerUpdater::~BitmapSkPictureContentLayerUpdater() {} - -scoped_ptr<LayerUpdater::Resource> -BitmapSkPictureContentLayerUpdater::CreateResource( - PrioritizedResourceManager* manager) { - return make_scoped_ptr( - new Resource(this, PrioritizedResource::Create(manager))); -} - -void BitmapSkPictureContentLayerUpdater::PaintContentsRect( - SkCanvas* canvas, - const gfx::Rect& source_rect) { - if (!canvas) - return; - // Translate the origin of content_rect to that of source_rect. - canvas->translate(paint_rect().x() - source_rect.x(), - paint_rect().y() - source_rect.y()); - DrawPicture(canvas); -} - -} // namespace cc diff --git a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.h b/chromium/cc/resources/bitmap_skpicture_content_layer_updater.h deleted file mode 100644 index ba22b2e5908..00000000000 --- a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.h +++ /dev/null @@ -1,57 +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. - -#ifndef CC_RESOURCES_BITMAP_SKPICTURE_CONTENT_LAYER_UPDATER_H_ -#define CC_RESOURCES_BITMAP_SKPICTURE_CONTENT_LAYER_UPDATER_H_ - -#include "cc/resources/skpicture_content_layer_updater.h" -#include "third_party/skia/include/core/SkBitmap.h" - -namespace cc { - -// This class records the content_rect into an SkPicture, then software -// rasterizes the SkPicture into bitmaps for each tile. This implements -// LayerTreeSettingSettings::per_tile_painting_enabled. -class BitmapSkPictureContentLayerUpdater : public SkPictureContentLayerUpdater { - public: - class Resource : public ContentLayerUpdater::Resource { - public: - Resource(BitmapSkPictureContentLayerUpdater* updater, - scoped_ptr<PrioritizedResource> texture); - - void Update(ResourceUpdateQueue* queue, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update) override; - - private: - SkBitmap bitmap_; - BitmapSkPictureContentLayerUpdater* updater_; - - DISALLOW_COPY_AND_ASSIGN(Resource); - }; - - static scoped_refptr<BitmapSkPictureContentLayerUpdater> Create( - scoped_ptr<LayerPainter> painter, - RenderingStatsInstrumentation* stats_instrumentation, - int layer_id); - - scoped_ptr<LayerUpdater::Resource> CreateResource( - PrioritizedResourceManager* manager) override; - void PaintContentsRect(SkCanvas* canvas, - const gfx::Rect& source_rect); - - private: - BitmapSkPictureContentLayerUpdater( - scoped_ptr<LayerPainter> painter, - RenderingStatsInstrumentation* stats_instrumentation, - int layer_id); - ~BitmapSkPictureContentLayerUpdater() override; - - DISALLOW_COPY_AND_ASSIGN(BitmapSkPictureContentLayerUpdater); -}; - -} // namespace cc - -#endif // CC_RESOURCES_BITMAP_SKPICTURE_CONTENT_LAYER_UPDATER_H_ diff --git a/chromium/cc/resources/content_layer_updater.cc b/chromium/cc/resources/content_layer_updater.cc deleted file mode 100644 index 7101dd13d84..00000000000 --- a/chromium/cc/resources/content_layer_updater.cc +++ /dev/null @@ -1,118 +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/resources/content_layer_updater.h" - -#include "base/trace_event/trace_event.h" -#include "cc/resources/layer_painter.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkRect.h" -#include "third_party/skia/include/core/SkScalar.h" -#include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/geometry/rect_f.h" -#include "ui/gfx/skia_util.h" - -namespace cc { - -ContentLayerUpdater::ContentLayerUpdater(scoped_ptr<LayerPainter> painter, - int layer_id) - : layer_id_(layer_id), - layer_is_opaque_(false), - layer_fills_bounds_completely_(false), - painter_(painter.Pass()), - background_color_(SK_ColorTRANSPARENT) { -} - -ContentLayerUpdater::~ContentLayerUpdater() {} - -void ContentLayerUpdater::PaintContents(SkCanvas* canvas, - const gfx::Size& layer_content_size, - const gfx::Rect& paint_rect, - float contents_width_scale, - float contents_height_scale) { - TRACE_EVENT0("cc", "ContentLayerUpdater::PaintContents"); - if (!canvas) - return; - canvas->save(); - canvas->translate(SkIntToScalar(-paint_rect.x()), - SkIntToScalar(-paint_rect.y())); - - // The |canvas| backing should be sized to hold the |paint_rect|. - DCHECK_EQ(paint_rect.width(), canvas->getBaseLayerSize().width()); - DCHECK_EQ(paint_rect.height(), canvas->getBaseLayerSize().height()); - - const bool is_scaled = - contents_width_scale != 1.f || contents_height_scale != 1.f; - - if (is_scaled && (layer_is_opaque_ || layer_fills_bounds_completely_)) { - // Even if completely covered, for rasterizations that touch the edge of the - // layer, we also need to raster the background color underneath the last - // texel (since the paint won't cover it). - // - // The final texel of content may only be partially covered by a - // rasterization; this rect represents the content rect that is fully - // covered by content. - const gfx::Rect layer_content_rect = gfx::Rect(layer_content_size); - gfx::Rect deflated_layer_content_rect = layer_content_rect; - deflated_layer_content_rect.Inset(0, 0, 1, 1); - - if (!layer_content_rect.Contains(deflated_layer_content_rect)) { - // Drawing at most 1 x 1 x (canvas width + canvas height) texels is 2-3X - // faster than clearing, so special case this. - DCHECK_LE(paint_rect.right(), layer_content_rect.right()); - DCHECK_LE(paint_rect.bottom(), layer_content_rect.bottom()); - canvas->save(); - canvas->clipRect(gfx::RectToSkRect(layer_content_rect), - SkRegion::kReplace_Op); - canvas->clipRect(gfx::RectToSkRect(deflated_layer_content_rect), - SkRegion::kDifference_Op); - canvas->drawColor(background_color_, SkXfermode::kSrc_Mode); - canvas->restore(); - } - } - - gfx::Rect layer_rect; - if (is_scaled) { - canvas->scale(SkFloatToScalar(contents_width_scale), - SkFloatToScalar(contents_height_scale)); - - // NOTE: this may go beyond the bounds of the layer, but that shouldn't - // cause problems (anything beyond the layer is clipped out). - layer_rect = gfx::ScaleToEnclosingRect( - paint_rect, 1.f / contents_width_scale, 1.f / contents_height_scale); - } else { - layer_rect = paint_rect; - } - - SkRect layer_sk_rect = SkRect::MakeXYWH( - layer_rect.x(), layer_rect.y(), layer_rect.width(), layer_rect.height()); - - canvas->clipRect(layer_sk_rect); - - // If the layer has opaque contents or will fill the bounds completely there - // is no need to clear the canvas before painting. - if (!layer_is_opaque_ && !layer_fills_bounds_completely_) { - TRACE_EVENT0("cc", "Clear"); - canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kSrc_Mode); - } - - painter_->Paint(canvas, layer_rect); - canvas->restore(); - - paint_rect_ = paint_rect; -} - -void ContentLayerUpdater::SetOpaque(bool opaque) { - layer_is_opaque_ = opaque; -} - -void ContentLayerUpdater::SetFillsBoundsCompletely(bool fills_bounds) { - layer_fills_bounds_completely_ = fills_bounds; -} - -void ContentLayerUpdater::SetBackgroundColor(SkColor background_color) { - background_color_ = background_color; -} - -} // namespace cc diff --git a/chromium/cc/resources/content_layer_updater.h b/chromium/cc/resources/content_layer_updater.h deleted file mode 100644 index 0f26b820ff4..00000000000 --- a/chromium/cc/resources/content_layer_updater.h +++ /dev/null @@ -1,66 +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. - -#ifndef CC_RESOURCES_CONTENT_LAYER_UPDATER_H_ -#define CC_RESOURCES_CONTENT_LAYER_UPDATER_H_ - -#include "cc/base/cc_export.h" -#include "cc/resources/layer_updater.h" -#include "ui/gfx/geometry/rect.h" - -class SkCanvas; - -namespace cc { - -class LayerPainter; -class RenderingStatsInstrumentation; - -// Base class for BitmapContentLayerUpdater and -// SkPictureContentLayerUpdater that reduces code duplication between -// their respective PaintContents implementations. -class CC_EXPORT ContentLayerUpdater : public LayerUpdater { - public: - void SetOpaque(bool opaque) override; - void SetFillsBoundsCompletely(bool fills_bounds) override; - void SetBackgroundColor(SkColor background_color) override; - - protected: - ContentLayerUpdater(scoped_ptr<LayerPainter> painter, int layer_id); - ~ContentLayerUpdater() override; - - // Paints the contents. |content_size| size of the underlying layer in - // layer's content space. |paint_rect| bounds to paint in content space of the - // layer. Both |content_size| and |paint_rect| are in pixels. - void PaintContents(SkCanvas* canvas, - const gfx::Size& layer_content_size, - const gfx::Rect& paint_rect, - float contents_width_scale, - float contents_height_scale); - gfx::Rect paint_rect() const { return paint_rect_; } - - bool layer_is_opaque() const { return layer_is_opaque_; } - bool layer_fills_bounds_completely() const { - return layer_fills_bounds_completely_; - } - - SkColor background_color() const { return background_color_; } - - int layer_id_; - - // True when it is known that all output pixels will be opaque. - bool layer_is_opaque_; - // True when it is known that all output pixels will be filled. - bool layer_fills_bounds_completely_; - - private: - gfx::Rect paint_rect_; - scoped_ptr<LayerPainter> painter_; - SkColor background_color_; - - DISALLOW_COPY_AND_ASSIGN(ContentLayerUpdater); -}; - -} // namespace cc - -#endif // CC_RESOURCES_CONTENT_LAYER_UPDATER_H_ diff --git a/chromium/cc/resources/image_layer_updater.cc b/chromium/cc/resources/image_layer_updater.cc deleted file mode 100644 index 0538d96ea36..00000000000 --- a/chromium/cc/resources/image_layer_updater.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2012 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/resources/image_layer_updater.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/resource_update_queue.h" - -namespace cc { - -ImageLayerUpdater::Resource::Resource(ImageLayerUpdater* updater, - scoped_ptr<PrioritizedResource> texture) - : LayerUpdater::Resource(texture.Pass()), updater_(updater) {} - -ImageLayerUpdater::Resource::~Resource() {} - -void ImageLayerUpdater::Resource::Update(ResourceUpdateQueue* queue, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update) { - updater_->UpdateTexture( - queue, texture(), source_rect, dest_offset, partial_update); -} - -// static -scoped_refptr<ImageLayerUpdater> ImageLayerUpdater::Create() { - return make_scoped_refptr(new ImageLayerUpdater()); -} - -scoped_ptr<LayerUpdater::Resource> ImageLayerUpdater::CreateResource( - PrioritizedResourceManager* manager) { - return make_scoped_ptr( - new Resource(this, PrioritizedResource::Create(manager))); -} - -void ImageLayerUpdater::UpdateTexture(ResourceUpdateQueue* queue, - PrioritizedResource* texture, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update) { - // Source rect should never go outside the image pixels, even if this - // is requested because the texture extends outside the image. - gfx::Rect clipped_source_rect = source_rect; - gfx::Rect image_rect = gfx::Rect(0, 0, bitmap_.width(), bitmap_.height()); - clipped_source_rect.Intersect(image_rect); - - gfx::Vector2d clipped_dest_offset = - dest_offset + - gfx::Vector2d(clipped_source_rect.origin() - source_rect.origin()); - - ResourceUpdate upload = ResourceUpdate::Create( - texture, &bitmap_, image_rect, clipped_source_rect, clipped_dest_offset); - if (partial_update) - queue->AppendPartialUpload(upload); - else - queue->AppendFullUpload(upload); -} - -void ImageLayerUpdater::SetBitmap(const SkBitmap& bitmap) { - DCHECK(bitmap.pixelRef()); - bitmap_ = bitmap; -} - -bool ImageLayerUpdater::UsingBitmap(const SkBitmap& bitmap) const { - return bitmap.pixelRef() == bitmap_.pixelRef(); -} - -} // namespace cc diff --git a/chromium/cc/resources/image_layer_updater.h b/chromium/cc/resources/image_layer_updater.h deleted file mode 100644 index 81225ba7b5e..00000000000 --- a/chromium/cc/resources/image_layer_updater.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_IMAGE_LAYER_UPDATER_H_ -#define CC_RESOURCES_IMAGE_LAYER_UPDATER_H_ - -#include "cc/base/cc_export.h" -#include "cc/resources/layer_updater.h" -#include "third_party/skia/include/core/SkBitmap.h" - -namespace cc { - -class ResourceUpdateQueue; - -class CC_EXPORT ImageLayerUpdater : public LayerUpdater { - public: - class Resource : public LayerUpdater::Resource { - public: - Resource(ImageLayerUpdater* updater, - scoped_ptr<PrioritizedResource> texture); - ~Resource() override; - - void Update(ResourceUpdateQueue* queue, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update) override; - - private: - ImageLayerUpdater* updater_; - - DISALLOW_COPY_AND_ASSIGN(Resource); - }; - - static scoped_refptr<ImageLayerUpdater> Create(); - - scoped_ptr<LayerUpdater::Resource> CreateResource( - PrioritizedResourceManager*) override; - - void UpdateTexture(ResourceUpdateQueue* queue, - PrioritizedResource* texture, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update); - - void SetBitmap(const SkBitmap& bitmap); - bool UsingBitmap(const SkBitmap& bitmap) const; - - private: - ImageLayerUpdater() {} - ~ImageLayerUpdater() override {} - - SkBitmap bitmap_; - - DISALLOW_COPY_AND_ASSIGN(ImageLayerUpdater); -}; - -} // namespace cc - -#endif // CC_RESOURCES_IMAGE_LAYER_UPDATER_H_ diff --git a/chromium/cc/resources/layer_painter.h b/chromium/cc/resources/layer_painter.h deleted file mode 100644 index 54dc434671d..00000000000 --- a/chromium/cc/resources/layer_painter.h +++ /dev/null @@ -1,27 +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. - -#ifndef CC_RESOURCES_LAYER_PAINTER_H_ -#define CC_RESOURCES_LAYER_PAINTER_H_ - -#include "cc/base/cc_export.h" - -class SkCanvas; - -namespace gfx { -class Rect; -class RectF; -} - -namespace cc { - -class CC_EXPORT LayerPainter { - public: - virtual ~LayerPainter() {} - virtual void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) = 0; -}; - -} // namespace cc - -#endif // CC_RESOURCES_LAYER_PAINTER_H_ diff --git a/chromium/cc/resources/layer_updater.cc b/chromium/cc/resources/layer_updater.cc deleted file mode 100644 index aa7d1a4622e..00000000000 --- a/chromium/cc/resources/layer_updater.cc +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 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/resources/layer_updater.h" - -#include "cc/resources/prioritized_resource.h" - -namespace cc { - -LayerUpdater::Resource::Resource(scoped_ptr<PrioritizedResource> texture) - : texture_(texture.Pass()) {} - -LayerUpdater::Resource::~Resource() {} - -} // namespace cc diff --git a/chromium/cc/resources/layer_updater.h b/chromium/cc/resources/layer_updater.h deleted file mode 100644 index a5eb0a11da7..00000000000 --- a/chromium/cc/resources/layer_updater.h +++ /dev/null @@ -1,76 +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. - -#ifndef CC_RESOURCES_LAYER_UPDATER_H_ -#define CC_RESOURCES_LAYER_UPDATER_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "cc/base/cc_export.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/vector2d.h" - -namespace cc { - -class PrioritizedResource; -class PrioritizedResourceManager; -class ResourceUpdateQueue; -class TextureManager; - -class CC_EXPORT LayerUpdater : public base::RefCounted<LayerUpdater> { - public: - // Allows updaters to store per-resource update properties. - class CC_EXPORT Resource { - public: - virtual ~Resource(); - - PrioritizedResource* texture() { return texture_.get(); } - // TODO(reveman): partial_update should be a property of this class - // instead of an argument passed to Update(). - virtual void Update(ResourceUpdateQueue* queue, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - bool partial_update) = 0; - - protected: - explicit Resource(scoped_ptr<PrioritizedResource> texture); - - private: - scoped_ptr<PrioritizedResource> texture_; - - DISALLOW_COPY_AND_ASSIGN(Resource); - }; - - LayerUpdater() {} - - virtual scoped_ptr<Resource> CreateResource( - PrioritizedResourceManager* manager) = 0; - virtual void PrepareToUpdate(const gfx::Size& content_size, - const gfx::Rect& paint_rect, - const gfx::Size& tile_size, - float contents_width_scale, - float contents_height_scale) {} - virtual void ReduceMemoryUsage() {} - - // Set true by the layer when it is known that the entire output is going to - // be opaque. - virtual void SetOpaque(bool opaque) {} - // Set true by the layer when it is known that the entire output bounds will - // be rasterized. - virtual void SetFillsBoundsCompletely(bool fills_bounds) {} - virtual void SetBackgroundColor(SkColor background_color) {} - - protected: - virtual ~LayerUpdater() {} - - private: - friend class base::RefCounted<LayerUpdater>; - - DISALLOW_COPY_AND_ASSIGN(LayerUpdater); -}; - -} // namespace cc - -#endif // CC_RESOURCES_LAYER_UPDATER_H_ diff --git a/chromium/cc/resources/memory_history.cc b/chromium/cc/resources/memory_history.cc index 4dc49c881a6..29bad2a30b3 100644 --- a/chromium/cc/resources/memory_history.cc +++ b/chromium/cc/resources/memory_history.cc @@ -19,21 +19,4 @@ void MemoryHistory::SaveEntry(const MemoryHistory::Entry& entry) { ring_buffer_.SaveToBuffer(entry); } -void MemoryHistory::GetMinAndMax(size_t* min, size_t* max) const { - *min = std::numeric_limits<size_t>::max(); - *max = 0; - - for (RingBufferType::Iterator it = ring_buffer_.Begin(); it; ++it) { - size_t bytes_total = it->total_bytes_used; - - if (bytes_total < *min) - *min = bytes_total; - if (bytes_total > *max) - *max = bytes_total; - } - - if (*min > *max) - *min = *max; -} - } // namespace cc diff --git a/chromium/cc/resources/memory_history.h b/chromium/cc/resources/memory_history.h index 570a3d0ca43..15ddc75aa24 100644 --- a/chromium/cc/resources/memory_history.h +++ b/chromium/cc/resources/memory_history.h @@ -26,12 +26,11 @@ class MemoryHistory { had_enough_memory(false) {} size_t total_budget_in_bytes; - size_t total_bytes_used; + int64 total_bytes_used; bool had_enough_memory; }; void SaveEntry(const Entry& entry); - void GetMinAndMax(size_t* min, size_t* max) const; typedef RingBuffer<Entry, 80> RingBufferType; RingBufferType::Iterator Begin() const { return ring_buffer_.Begin(); } diff --git a/chromium/cc/resources/prioritized_resource.cc b/chromium/cc/resources/prioritized_resource.cc deleted file mode 100644 index 968083cb968..00000000000 --- a/chromium/cc/resources/prioritized_resource.cc +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2012 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/resources/prioritized_resource.h" - -#include <algorithm> - -#include "cc/resources/platform_color.h" -#include "cc/resources/prioritized_resource_manager.h" -#include "cc/resources/priority_calculator.h" -#include "cc/trees/proxy.h" - -namespace cc { - -PrioritizedResource::PrioritizedResource(PrioritizedResourceManager* manager, - const gfx::Size& size, - ResourceFormat format) - : size_(size), - format_(format), - bytes_(0), - contents_swizzled_(false), - priority_(PriorityCalculator::LowestPriority()), - is_above_priority_cutoff_(false), - is_self_managed_(false), - backing_(NULL), - manager_(NULL) { - bytes_ = Resource::MemorySizeBytes(size, format); - if (manager) - manager->RegisterTexture(this); -} - -PrioritizedResource::~PrioritizedResource() { - if (manager_) - manager_->UnregisterTexture(this); -} - -void PrioritizedResource::SetTextureManager( - PrioritizedResourceManager* manager) { - if (manager_ == manager) - return; - if (manager_) - manager_->UnregisterTexture(this); - if (manager) - manager->RegisterTexture(this); -} - -void PrioritizedResource::SetDimensions(const gfx::Size& size, - ResourceFormat format) { - if (format_ != format || size_ != size) { - is_above_priority_cutoff_ = false; - format_ = format; - size_ = size; - bytes_ = Resource::MemorySizeBytes(size, format); - DCHECK(manager_ || !backing_); - if (manager_) - manager_->ReturnBackingTexture(this); - } -} - -bool PrioritizedResource::RequestLate() { - if (!manager_) - return false; - return manager_->RequestLate(this); -} - -bool PrioritizedResource::BackingResourceWasEvicted() const { - return backing_ ? backing_->ResourceHasBeenDeleted() : false; -} - -void PrioritizedResource::AcquireBackingTexture( - ResourceProvider* resource_provider) { - DCHECK(is_above_priority_cutoff_); - if (is_above_priority_cutoff_) - manager_->AcquireBackingTextureIfNeeded(this, resource_provider); -} - -void PrioritizedResource::SetPixels(ResourceProvider* resource_provider, - const uint8_t* image, - const gfx::Rect& image_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset) { - DCHECK(is_above_priority_cutoff_); - if (is_above_priority_cutoff_) - AcquireBackingTexture(resource_provider); - DCHECK(backing_); - resource_provider->SetPixels( - resource_id(), image, image_rect, source_rect, dest_offset); - - // The component order may be bgra if we uploaded bgra pixels to rgba - // texture. Mark contents as swizzled if image component order is - // different than texture format. - contents_swizzled_ = !PlatformColor::SameComponentOrder(format_); -} - -void PrioritizedResource::Link(Backing* backing) { - DCHECK(backing); - DCHECK(!backing->owner_); - DCHECK(!backing_); - - backing_ = backing; - backing_->owner_ = this; -} - -void PrioritizedResource::Unlink() { - DCHECK(backing_); - DCHECK(backing_->owner_ == this); - - backing_->owner_ = NULL; - backing_ = NULL; -} - -void PrioritizedResource::SetToSelfManagedMemoryPlaceholder(size_t bytes) { - SetDimensions(gfx::Size(), RGBA_8888); - set_is_self_managed(true); - bytes_ = bytes; -} - -PrioritizedResource::Backing::Backing(unsigned id, - ResourceProvider* resource_provider, - const gfx::Size& size, - ResourceFormat format) - : Resource(id, size, format), - owner_(NULL), - priority_at_last_priority_update_(PriorityCalculator::LowestPriority()), - was_above_priority_cutoff_at_last_priority_update_(false), - in_drawing_impl_tree_(false), - in_parent_compositor_(false), -#if !DCHECK_IS_ON() - resource_has_been_deleted_(false) { -#else - resource_has_been_deleted_(false), - resource_provider_(resource_provider) { -#endif -} - -PrioritizedResource::Backing::~Backing() { - DCHECK(!owner_); - DCHECK(resource_has_been_deleted_); -} - -void PrioritizedResource::Backing::DeleteResource( - ResourceProvider* resource_provider) { - DCHECK(!proxy() || proxy()->IsImplThread()); - DCHECK(!resource_has_been_deleted_); -#if DCHECK_IS_ON() - DCHECK(resource_provider == resource_provider_); -#endif - - resource_provider->DeleteResource(id()); - set_id(0); - resource_has_been_deleted_ = true; -} - -bool PrioritizedResource::Backing::ResourceHasBeenDeleted() const { - DCHECK(!proxy() || proxy()->IsImplThread()); - return resource_has_been_deleted_; -} - -bool PrioritizedResource::Backing::CanBeRecycledIfNotInExternalUse() const { - DCHECK(!proxy() || proxy()->IsImplThread()); - return !was_above_priority_cutoff_at_last_priority_update_ && - !in_drawing_impl_tree_; -} - -void PrioritizedResource::Backing::UpdatePriority() { - DCHECK(!proxy() || - (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked())); - if (owner_) { - priority_at_last_priority_update_ = owner_->request_priority(); - was_above_priority_cutoff_at_last_priority_update_ = - owner_->is_above_priority_cutoff(); - } else { - priority_at_last_priority_update_ = PriorityCalculator::LowestPriority(); - was_above_priority_cutoff_at_last_priority_update_ = false; - } -} - -void PrioritizedResource::Backing::UpdateState( - ResourceProvider* resource_provider) { - DCHECK(!proxy() || - (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked())); - in_drawing_impl_tree_ = !!owner(); - in_parent_compositor_ = resource_provider->InUseByConsumer(id()); - if (!in_drawing_impl_tree_) { - DCHECK_EQ(priority_at_last_priority_update_, - PriorityCalculator::LowestPriority()); - } -} - -void PrioritizedResource::ReturnBackingTexture() { - DCHECK(manager_ || !backing_); - if (manager_) - manager_->ReturnBackingTexture(this); -} - -const Proxy* PrioritizedResource::Backing::proxy() const { - if (!owner_ || !owner_->resource_manager()) - return NULL; - return owner_->resource_manager()->ProxyForDebug(); -} - -} // namespace cc diff --git a/chromium/cc/resources/prioritized_resource.h b/chromium/cc/resources/prioritized_resource.h deleted file mode 100644 index 3b6ecc028e8..00000000000 --- a/chromium/cc/resources/prioritized_resource.h +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_PRIORITIZED_RESOURCE_H_ -#define CC_RESOURCES_PRIORITIZED_RESOURCE_H_ - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "cc/base/cc_export.h" -#include "cc/resources/resource.h" -#include "cc/resources/resource_provider.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gfx/geometry/vector2d.h" - -namespace cc { - -class PrioritizedResourceManager; -class Proxy; - -class CC_EXPORT PrioritizedResource { - public: - static scoped_ptr<PrioritizedResource> Create( - PrioritizedResourceManager* manager, - const gfx::Size& size, - ResourceFormat format) { - return make_scoped_ptr(new PrioritizedResource(manager, size, format)); - } - static scoped_ptr<PrioritizedResource> Create( - PrioritizedResourceManager* manager) { - return make_scoped_ptr( - new PrioritizedResource(manager, gfx::Size(), RGBA_8888)); - } - ~PrioritizedResource(); - - // Texture properties. Changing these causes the backing texture to be lost. - // Setting these to the same value is a no-op. - void SetTextureManager(PrioritizedResourceManager* manager); - PrioritizedResourceManager* resource_manager() { return manager_; } - void SetDimensions(const gfx::Size& size, ResourceFormat format); - ResourceFormat format() const { return format_; } - gfx::Size size() const { return size_; } - size_t bytes() const { return bytes_; } - bool contents_swizzled() const { return contents_swizzled_; } - - // Set priority for the requested texture. - void set_request_priority(int priority) { priority_ = priority; } - int request_priority() const { return priority_; } - - // After PrioritizedResource::PrioritizeTextures() is called, this returns - // if the the request succeeded and this texture can be acquired for use. - bool can_acquire_backing_texture() const { return is_above_priority_cutoff_; } - - // This returns whether we still have a backing texture. This can continue - // to be true even after CanAcquireBackingTexture() becomes false. In this - // case the texture can be used but shouldn't be updated since it will get - // taken away "soon". - bool have_backing_texture() const { return !!backing(); } - - bool BackingResourceWasEvicted() const; - - // If CanAcquireBackingTexture() is true AcquireBackingTexture() will acquire - // a backing texture for use. Call this whenever the texture is actually - // needed. - void AcquireBackingTexture(ResourceProvider* resource_provider); - - // TODO(epenner): Request late is really a hack for when we are totally out of - // memory (all textures are visible) but we can still squeeze into the limit - // by not painting occluded textures. In this case the manager refuses all - // visible textures and RequestLate() will enable CanAcquireBackingTexture() - // on a call-order basis. We might want to just remove this in the future - // (carefully) and just make sure we don't regress OOMs situations. - bool RequestLate(); - - // Update pixels of backing resource from image. This functions will aquire - // the backing if needed. - void SetPixels(ResourceProvider* resource_provider, - const uint8_t* image, - const gfx::Rect& image_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset); - - ResourceProvider::ResourceId resource_id() const { - return backing_ ? backing_->id() : 0; - } - - // Self-managed textures are accounted for when prioritizing other textures, - // but they are not allocated/recycled/deleted, so this needs to be done - // externally. CanAcquireBackingTexture() indicates if the texture would have - // been allowed given its priority. - void set_is_self_managed(bool is_self_managed) { - is_self_managed_ = is_self_managed; - } - bool is_self_managed() { return is_self_managed_; } - void SetToSelfManagedMemoryPlaceholder(size_t bytes); - - void ReturnBackingTexture(); - - private: - friend class PrioritizedResourceManager; - friend class PrioritizedResourceTest; - - class Backing : public Resource { - public: - Backing(unsigned id, - ResourceProvider* resource_provider, - const gfx::Size& size, - ResourceFormat format); - ~Backing(); - void UpdatePriority(); - void UpdateState(ResourceProvider* resource_provider); - - PrioritizedResource* owner() { return owner_; } - bool CanBeRecycledIfNotInExternalUse() const; - int request_priority_at_last_priority_update() const { - return priority_at_last_priority_update_; - } - bool was_above_priority_cutoff_at_last_priority_update() const { - return was_above_priority_cutoff_at_last_priority_update_; - } - bool in_drawing_impl_tree() const { return in_drawing_impl_tree_; } - bool in_parent_compositor() const { return in_parent_compositor_; } - - void DeleteResource(ResourceProvider* resource_provider); - bool ResourceHasBeenDeleted() const; - - private: - const Proxy* proxy() const; - - friend class PrioritizedResource; - friend class PrioritizedResourceManager; - PrioritizedResource* owner_; - int priority_at_last_priority_update_; - bool was_above_priority_cutoff_at_last_priority_update_; - - // Set if this is currently-drawing impl tree. - bool in_drawing_impl_tree_; - // Set if this is in the parent compositor. - bool in_parent_compositor_; - - bool resource_has_been_deleted_; - -#if DCHECK_IS_ON() - ResourceProvider* resource_provider_; -#endif - DISALLOW_COPY_AND_ASSIGN(Backing); - }; - - PrioritizedResource(PrioritizedResourceManager* resource_manager, - const gfx::Size& size, - ResourceFormat format); - - bool is_above_priority_cutoff() { return is_above_priority_cutoff_; } - void set_above_priority_cutoff(bool is_above_priority_cutoff) { - is_above_priority_cutoff_ = is_above_priority_cutoff; - } - void set_manager_internal(PrioritizedResourceManager* manager) { - manager_ = manager; - } - - Backing* backing() const { return backing_; } - void Link(Backing* backing); - void Unlink(); - - gfx::Size size_; - ResourceFormat format_; - size_t bytes_; - bool contents_swizzled_; - - int priority_; - bool is_above_priority_cutoff_; - bool is_self_managed_; - - Backing* backing_; - PrioritizedResourceManager* manager_; - - DISALLOW_COPY_AND_ASSIGN(PrioritizedResource); -}; - -} // namespace cc - -#endif // CC_RESOURCES_PRIORITIZED_RESOURCE_H_ diff --git a/chromium/cc/resources/prioritized_resource_manager.cc b/chromium/cc/resources/prioritized_resource_manager.cc deleted file mode 100644 index 236377b8511..00000000000 --- a/chromium/cc/resources/prioritized_resource_manager.cc +++ /dev/null @@ -1,547 +0,0 @@ -// Copyright 2012 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/resources/prioritized_resource_manager.h" - -#include <algorithm> - -#include "base/trace_event/trace_event.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/priority_calculator.h" -#include "cc/trees/proxy.h" - -namespace cc { - -PrioritizedResourceManager::PrioritizedResourceManager(const Proxy* proxy) - : max_memory_limit_bytes_(DefaultMemoryAllocationLimit()), - external_priority_cutoff_(PriorityCalculator::AllowEverythingCutoff()), - memory_use_bytes_(0), - memory_above_cutoff_bytes_(0), - max_memory_needed_bytes_(0), - memory_available_bytes_(0), - proxy_(proxy), - backings_tail_not_sorted_(false), - memory_visible_bytes_(0), - memory_visible_and_nearby_bytes_(0), - memory_visible_last_pushed_bytes_(0), - memory_visible_and_nearby_last_pushed_bytes_(0) {} - -PrioritizedResourceManager::~PrioritizedResourceManager() { - while (textures_.size() > 0) - UnregisterTexture(*textures_.begin()); - - UnlinkAndClearEvictedBackings(); - DCHECK(evicted_backings_.empty()); - - // Each remaining backing is a leaked opengl texture. There should be none. - DCHECK(backings_.empty()); -} - -size_t PrioritizedResourceManager::MemoryVisibleBytes() const { - DCHECK(proxy_->IsImplThread()); - return memory_visible_last_pushed_bytes_; -} - -size_t PrioritizedResourceManager::MemoryVisibleAndNearbyBytes() const { - DCHECK(proxy_->IsImplThread()); - return memory_visible_and_nearby_last_pushed_bytes_; -} - -void PrioritizedResourceManager::PrioritizeTextures() { - TRACE_EVENT0("cc", "PrioritizedResourceManager::PrioritizeTextures"); - DCHECK(proxy_->IsMainThread()); - - // Sorting textures in this function could be replaced by a slightly - // modified O(n) quick-select to partition textures rather than - // sort them (if performance of the sort becomes an issue). - - TextureVector& sorted_textures = temp_texture_vector_; - sorted_textures.clear(); - - // Copy all textures into a vector, sort them, and collect memory requirements - // statistics. - memory_visible_bytes_ = 0; - memory_visible_and_nearby_bytes_ = 0; - for (TextureSet::iterator it = textures_.begin(); it != textures_.end(); - ++it) { - PrioritizedResource* texture = (*it); - sorted_textures.push_back(texture); - if (PriorityCalculator::priority_is_higher( - texture->request_priority(), - PriorityCalculator::AllowVisibleOnlyCutoff())) - memory_visible_bytes_ += texture->bytes(); - if (PriorityCalculator::priority_is_higher( - texture->request_priority(), - PriorityCalculator::AllowVisibleAndNearbyCutoff())) - memory_visible_and_nearby_bytes_ += texture->bytes(); - } - std::sort(sorted_textures.begin(), sorted_textures.end(), CompareTextures); - - // Compute a priority cutoff based on memory pressure - memory_available_bytes_ = max_memory_limit_bytes_; - priority_cutoff_ = external_priority_cutoff_; - size_t memory_bytes = 0; - for (TextureVector::iterator it = sorted_textures.begin(); - it != sorted_textures.end(); - ++it) { - if ((*it)->is_self_managed()) { - // Account for self-managed memory immediately by reducing the memory - // available (since it never gets acquired). - size_t new_memory_bytes = memory_bytes + (*it)->bytes(); - if (new_memory_bytes > memory_available_bytes_) { - priority_cutoff_ = (*it)->request_priority(); - memory_available_bytes_ = memory_bytes; - break; - } - memory_available_bytes_ -= (*it)->bytes(); - } else { - size_t new_memory_bytes = memory_bytes + (*it)->bytes(); - if (new_memory_bytes > memory_available_bytes_) { - priority_cutoff_ = (*it)->request_priority(); - break; - } - memory_bytes = new_memory_bytes; - } - } - - // Disallow any textures with priority below the external cutoff to have - // backings. - for (TextureVector::iterator it = sorted_textures.begin(); - it != sorted_textures.end(); - ++it) { - PrioritizedResource* texture = (*it); - if (!PriorityCalculator::priority_is_higher(texture->request_priority(), - external_priority_cutoff_) && - texture->have_backing_texture()) - texture->Unlink(); - } - - // Only allow textures if they are higher than the cutoff. All textures - // of the same priority are accepted or rejected together, rather than - // being partially allowed randomly. - max_memory_needed_bytes_ = 0; - memory_above_cutoff_bytes_ = 0; - for (TextureVector::iterator it = sorted_textures.begin(); - it != sorted_textures.end(); - ++it) { - PrioritizedResource* resource = *it; - bool is_above_priority_cutoff = PriorityCalculator::priority_is_higher( - resource->request_priority(), priority_cutoff_); - resource->set_above_priority_cutoff(is_above_priority_cutoff); - if (!resource->is_self_managed()) { - max_memory_needed_bytes_ += resource->bytes(); - if (is_above_priority_cutoff) - memory_above_cutoff_bytes_ += resource->bytes(); - } - } - sorted_textures.clear(); - - DCHECK_LE(memory_above_cutoff_bytes_, memory_available_bytes_); - DCHECK_LE(MemoryAboveCutoffBytes(), MaxMemoryLimitBytes()); -} - -void PrioritizedResourceManager::PushTexturePrioritiesToBackings() { - TRACE_EVENT0("cc", - "PrioritizedResourceManager::PushTexturePrioritiesToBackings"); - DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked()); - - AssertInvariants(); - for (BackingList::iterator it = backings_.begin(); it != backings_.end(); - ++it) - (*it)->UpdatePriority(); - SortBackings(); - AssertInvariants(); - - // Push memory requirements to the impl thread structure. - memory_visible_last_pushed_bytes_ = memory_visible_bytes_; - memory_visible_and_nearby_last_pushed_bytes_ = - memory_visible_and_nearby_bytes_; -} - -void PrioritizedResourceManager::UpdateBackingsState( - ResourceProvider* resource_provider) { - TRACE_EVENT0("cc", - "PrioritizedResourceManager::UpdateBackingsInDrawingImplTree"); - DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked()); - - AssertInvariants(); - for (BackingList::iterator it = backings_.begin(); it != backings_.end(); - ++it) { - PrioritizedResource::Backing* backing = (*it); - backing->UpdateState(resource_provider); - } - SortBackings(); - AssertInvariants(); -} - -void PrioritizedResourceManager::SortBackings() { - TRACE_EVENT0("cc", "PrioritizedResourceManager::SortBackings"); - DCHECK(proxy_->IsImplThread()); - - // Put backings in eviction/recycling order. - backings_.sort(CompareBackings); - backings_tail_not_sorted_ = false; -} - -void PrioritizedResourceManager::ClearPriorities() { - DCHECK(proxy_->IsMainThread()); - for (TextureSet::iterator it = textures_.begin(); it != textures_.end(); - ++it) { - // TODO(reveman): We should remove this and just set all priorities to - // PriorityCalculator::lowestPriority() once we have priorities for all - // textures (we can't currently calculate distances for off-screen - // textures). - (*it)->set_request_priority( - PriorityCalculator::LingeringPriority((*it)->request_priority())); - } -} - -bool PrioritizedResourceManager::RequestLate(PrioritizedResource* texture) { - DCHECK(proxy_->IsMainThread()); - - // This is already above cutoff, so don't double count it's memory below. - if (texture->is_above_priority_cutoff()) - return true; - - // Allow textures that have priority equal to the cutoff, but not strictly - // lower. - if (PriorityCalculator::priority_is_lower(texture->request_priority(), - priority_cutoff_)) - return false; - - // Disallow textures that do not have a priority strictly higher than the - // external cutoff. - if (!PriorityCalculator::priority_is_higher(texture->request_priority(), - external_priority_cutoff_)) - return false; - - size_t new_memory_bytes = memory_above_cutoff_bytes_ + texture->bytes(); - if (new_memory_bytes > memory_available_bytes_) - return false; - - memory_above_cutoff_bytes_ = new_memory_bytes; - texture->set_above_priority_cutoff(true); - return true; -} - -void PrioritizedResourceManager::AcquireBackingTextureIfNeeded( - PrioritizedResource* texture, - ResourceProvider* resource_provider) { - DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked()); - DCHECK(!texture->is_self_managed()); - DCHECK(texture->is_above_priority_cutoff()); - if (texture->backing() || !texture->is_above_priority_cutoff()) - return; - - // Find a backing below, by either recycling or allocating. - PrioritizedResource::Backing* backing = NULL; - - // First try to recycle - for (BackingList::iterator it = backings_.begin(); it != backings_.end(); - ++it) { - if (!(*it)->CanBeRecycledIfNotInExternalUse()) - break; - if (resource_provider->InUseByConsumer((*it)->id())) - continue; - if ((*it)->size() == texture->size() && - (*it)->format() == texture->format()) { - backing = (*it); - backings_.erase(it); - break; - } - } - - // Otherwise reduce memory and just allocate a new backing texures. - if (!backing) { - EvictBackingsToReduceMemory(memory_available_bytes_ - texture->bytes(), - PriorityCalculator::AllowEverythingCutoff(), - EVICT_ONLY_RECYCLABLE, - DO_NOT_UNLINK_BACKINGS, - resource_provider); - backing = - CreateBacking(texture->size(), texture->format(), resource_provider); - } - - // Move the used backing to the end of the eviction list, and note that - // the tail is not sorted. - if (backing->owner()) - backing->owner()->Unlink(); - texture->Link(backing); - backings_.push_back(backing); - backings_tail_not_sorted_ = true; - - // Update the backing's priority from its new owner. - backing->UpdatePriority(); -} - -bool PrioritizedResourceManager::EvictBackingsToReduceMemory( - size_t limit_bytes, - int priority_cutoff, - EvictionPolicy eviction_policy, - UnlinkPolicy unlink_policy, - ResourceProvider* resource_provider) { - DCHECK(proxy_->IsImplThread()); - if (unlink_policy == UNLINK_BACKINGS) - DCHECK(proxy_->IsMainThreadBlocked()); - if (MemoryUseBytes() <= limit_bytes && - PriorityCalculator::AllowEverythingCutoff() == priority_cutoff) - return false; - - // Destroy backings until we are below the limit, - // or until all backings remaining are above the cutoff. - bool evicted_anything = false; - while (backings_.size() > 0) { - PrioritizedResource::Backing* backing = backings_.front(); - if (MemoryUseBytes() <= limit_bytes && - PriorityCalculator::priority_is_higher( - backing->request_priority_at_last_priority_update(), - priority_cutoff)) - break; - if (eviction_policy == EVICT_ONLY_RECYCLABLE && - !backing->CanBeRecycledIfNotInExternalUse()) - break; - if (unlink_policy == UNLINK_BACKINGS && backing->owner()) - backing->owner()->Unlink(); - EvictFirstBackingResource(resource_provider); - evicted_anything = true; - } - return evicted_anything; -} - -void PrioritizedResourceManager::ReduceWastedMemory( - ResourceProvider* resource_provider) { - // We currently collect backings from deleted textures for later recycling. - // However, if we do that forever we will always use the max limit even if - // we really need very little memory. This should probably be solved by - // reducing the limit externally, but until then this just does some "clean - // up" of unused backing textures (any more than 10%). - size_t wasted_memory = 0; - for (BackingList::iterator it = backings_.begin(); it != backings_.end(); - ++it) { - if ((*it)->owner()) - break; - if ((*it)->in_parent_compositor()) - continue; - wasted_memory += (*it)->bytes(); - } - size_t wasted_memory_to_allow = memory_available_bytes_ / 10; - // If the external priority cutoff indicates that unused memory should be - // freed, then do not allow any memory for texture recycling. - if (external_priority_cutoff_ != PriorityCalculator::AllowEverythingCutoff()) - wasted_memory_to_allow = 0; - if (wasted_memory > wasted_memory_to_allow) - EvictBackingsToReduceMemory(MemoryUseBytes() - - (wasted_memory - wasted_memory_to_allow), - PriorityCalculator::AllowEverythingCutoff(), - EVICT_ONLY_RECYCLABLE, - DO_NOT_UNLINK_BACKINGS, - resource_provider); -} - -void PrioritizedResourceManager::ReduceMemory( - ResourceProvider* resource_provider) { - DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked()); - EvictBackingsToReduceMemory(memory_available_bytes_, - PriorityCalculator::AllowEverythingCutoff(), - EVICT_ANYTHING, - UNLINK_BACKINGS, - resource_provider); - DCHECK_LE(MemoryUseBytes(), memory_available_bytes_); - - ReduceWastedMemory(resource_provider); -} - -void PrioritizedResourceManager::ClearAllMemory( - ResourceProvider* resource_provider) { - DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked()); - if (!resource_provider) { - DCHECK(backings_.empty()); - return; - } - EvictBackingsToReduceMemory(0, - PriorityCalculator::AllowEverythingCutoff(), - EVICT_ANYTHING, - DO_NOT_UNLINK_BACKINGS, - resource_provider); -} - -bool PrioritizedResourceManager::ReduceMemoryOnImplThread( - size_t limit_bytes, - int priority_cutoff, - ResourceProvider* resource_provider) { - DCHECK(proxy_->IsImplThread()); - DCHECK(resource_provider); - - // If we are in the process of uploading a new frame then the backings at the - // very end of the list are not sorted by priority. Sort them before doing the - // eviction. - if (backings_tail_not_sorted_) - SortBackings(); - return EvictBackingsToReduceMemory(limit_bytes, - priority_cutoff, - EVICT_ANYTHING, - DO_NOT_UNLINK_BACKINGS, - resource_provider); -} - -void PrioritizedResourceManager::UnlinkAndClearEvictedBackings() { - DCHECK(proxy_->IsMainThread()); - base::AutoLock scoped_lock(evicted_backings_lock_); - for (BackingList::const_iterator it = evicted_backings_.begin(); - it != evicted_backings_.end(); - ++it) { - PrioritizedResource::Backing* backing = (*it); - if (backing->owner()) - backing->owner()->Unlink(); - delete backing; - } - evicted_backings_.clear(); -} - -bool PrioritizedResourceManager::LinkedEvictedBackingsExist() const { - DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked()); - base::AutoLock scoped_lock(evicted_backings_lock_); - for (BackingList::const_iterator it = evicted_backings_.begin(); - it != evicted_backings_.end(); - ++it) { - if ((*it)->owner()) - return true; - } - return false; -} - -void PrioritizedResourceManager::RegisterTexture(PrioritizedResource* texture) { - DCHECK(proxy_->IsMainThread()); - DCHECK(texture); - DCHECK(!texture->resource_manager()); - DCHECK(!texture->backing()); - DCHECK(!ContainsKey(textures_, texture)); - - texture->set_manager_internal(this); - textures_.insert(texture); -} - -void PrioritizedResourceManager::UnregisterTexture( - PrioritizedResource* texture) { - DCHECK(proxy_->IsMainThread() || - (proxy_->IsImplThread() && proxy_->IsMainThreadBlocked())); - DCHECK(texture); - DCHECK(ContainsKey(textures_, texture)); - - ReturnBackingTexture(texture); - texture->set_manager_internal(NULL); - textures_.erase(texture); - texture->set_above_priority_cutoff(false); -} - -void PrioritizedResourceManager::ReturnBackingTexture( - PrioritizedResource* texture) { - DCHECK(proxy_->IsMainThread() || - (proxy_->IsImplThread() && proxy_->IsMainThreadBlocked())); - if (texture->backing()) - texture->Unlink(); -} - -PrioritizedResource::Backing* PrioritizedResourceManager::CreateBacking( - const gfx::Size& size, - ResourceFormat format, - ResourceProvider* resource_provider) { - DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked()); - DCHECK(resource_provider); - ResourceProvider::ResourceId resource_id = - resource_provider->CreateManagedResource( - size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, - ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); - PrioritizedResource::Backing* backing = new PrioritizedResource::Backing( - resource_id, resource_provider, size, format); - memory_use_bytes_ += backing->bytes(); - return backing; -} - -void PrioritizedResourceManager::EvictFirstBackingResource( - ResourceProvider* resource_provider) { - DCHECK(proxy_->IsImplThread()); - DCHECK(resource_provider); - DCHECK(!backings_.empty()); - PrioritizedResource::Backing* backing = backings_.front(); - - // Note that we create a backing and its resource at the same time, but we - // delete the backing structure and its resource in two steps. This is because - // we can delete the resource while the main thread is running, but we cannot - // unlink backings while the main thread is running. - backing->DeleteResource(resource_provider); - memory_use_bytes_ -= backing->bytes(); - backings_.pop_front(); - base::AutoLock scoped_lock(evicted_backings_lock_); - evicted_backings_.push_back(backing); -} - -void PrioritizedResourceManager::AssertInvariants() { -#if DCHECK_IS_ON() - DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked()); - - // If we hit any of these asserts, there is a bug in this class. To see - // where the bug is, call this function at the beginning and end of - // every public function. - - // Backings/textures must be doubly-linked and only to other backings/textures - // in this manager. - for (BackingList::iterator it = backings_.begin(); it != backings_.end(); - ++it) { - if ((*it)->owner()) { - DCHECK(ContainsKey(textures_, (*it)->owner())); - DCHECK((*it)->owner()->backing() == (*it)); - } - } - for (TextureSet::iterator it = textures_.begin(); it != textures_.end(); - ++it) { - PrioritizedResource* texture = (*it); - PrioritizedResource::Backing* backing = texture->backing(); - base::AutoLock scoped_lock(evicted_backings_lock_); - if (backing) { - if (backing->ResourceHasBeenDeleted()) { - DCHECK(std::find(backings_.begin(), backings_.end(), backing) == - backings_.end()); - DCHECK(std::find(evicted_backings_.begin(), - evicted_backings_.end(), - backing) != evicted_backings_.end()); - } else { - DCHECK(std::find(backings_.begin(), backings_.end(), backing) != - backings_.end()); - DCHECK(std::find(evicted_backings_.begin(), - evicted_backings_.end(), - backing) == evicted_backings_.end()); - } - DCHECK(backing->owner() == texture); - } - } - - // At all times, backings that can be evicted must always come before - // backings that can't be evicted in the backing texture list (otherwise - // ReduceMemory will not find all textures available for eviction/recycling). - bool reached_unrecyclable = false; - PrioritizedResource::Backing* previous_backing = NULL; - for (BackingList::iterator it = backings_.begin(); it != backings_.end(); - ++it) { - PrioritizedResource::Backing* backing = *it; - if (previous_backing && - (!backings_tail_not_sorted_ || - !backing->was_above_priority_cutoff_at_last_priority_update())) - DCHECK(CompareBackings(previous_backing, backing)); - if (!backing->CanBeRecycledIfNotInExternalUse()) - reached_unrecyclable = true; - if (reached_unrecyclable) - DCHECK(!backing->CanBeRecycledIfNotInExternalUse()); - else - DCHECK(backing->CanBeRecycledIfNotInExternalUse()); - previous_backing = backing; - } -#endif // DCHECK_IS_ON() -} - -const Proxy* PrioritizedResourceManager::ProxyForDebug() const { - return proxy_; -} - -} // namespace cc diff --git a/chromium/cc/resources/prioritized_resource_manager.h b/chromium/cc/resources/prioritized_resource_manager.h deleted file mode 100644 index b7583f4315f..00000000000 --- a/chromium/cc/resources/prioritized_resource_manager.h +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_PRIORITIZED_RESOURCE_MANAGER_H_ -#define CC_RESOURCES_PRIORITIZED_RESOURCE_MANAGER_H_ - -#include <list> -#include <vector> - -#include "base/basictypes.h" -#include "base/containers/hash_tables.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" -#include "cc/base/cc_export.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/priority_calculator.h" -#include "cc/resources/resource.h" -#include "ui/gfx/geometry/size.h" - -namespace cc { - -class Proxy; - -class CC_EXPORT PrioritizedResourceManager { - public: - static scoped_ptr<PrioritizedResourceManager> Create(const Proxy* proxy) { - return make_scoped_ptr(new PrioritizedResourceManager(proxy)); - } - scoped_ptr<PrioritizedResource> CreateTexture( - const gfx::Size& size, ResourceFormat format) { - return make_scoped_ptr(new PrioritizedResource(this, size, format)); - } - ~PrioritizedResourceManager(); - - typedef std::list<PrioritizedResource::Backing*> BackingList; - - // TODO(epenner): (http://crbug.com/137094) This 64MB default is a straggler - // from the old texture manager and is just to give us a default memory - // allocation before we get a callback from the GPU memory manager. We - // should probaby either: - // - wait for the callback before rendering anything instead - // - push this into the GPU memory manager somehow. - static size_t DefaultMemoryAllocationLimit() { return 64 * 1024 * 1024; } - - // MemoryUseBytes() describes the number of bytes used by existing allocated - // textures. - size_t MemoryUseBytes() const { return memory_use_bytes_; } - // MemoryAboveCutoffBytes() describes the number of bytes that - // would be used if all textures that are above the cutoff were allocated. - // MemoryUseBytes() <= MemoryAboveCutoffBytes() should always be true. - size_t MemoryAboveCutoffBytes() const { return memory_above_cutoff_bytes_; } - // MaxMemoryNeededBytes() describes the number of bytes that would be used - // by textures if there were no limit on memory usage. - size_t MaxMemoryNeededBytes() const { return max_memory_needed_bytes_; } - size_t MemoryForSelfManagedTextures() const { - return max_memory_limit_bytes_ - memory_available_bytes_; - } - - void SetMaxMemoryLimitBytes(size_t bytes) { max_memory_limit_bytes_ = bytes; } - size_t MaxMemoryLimitBytes() const { return max_memory_limit_bytes_; } - - // Sepecify a external priority cutoff. Only textures that have a strictly - // higher priority than this cutoff will be allowed. - void SetExternalPriorityCutoff(int priority_cutoff) { - external_priority_cutoff_ = priority_cutoff; - } - int ExternalPriorityCutoff() const { - return external_priority_cutoff_; - } - - // Return the amount of texture memory required at particular cutoffs. - size_t MemoryVisibleBytes() const; - size_t MemoryVisibleAndNearbyBytes() const; - - void PrioritizeTextures(); - void ClearPriorities(); - - // Delete contents textures' backing resources until they use only - // limit_bytes bytes. This may be called on the impl thread while the main - // thread is running. Returns true if resources are indeed evicted as a - // result of this call. - bool ReduceMemoryOnImplThread(size_t limit_bytes, - int priority_cutoff, - ResourceProvider* resource_provider); - - // Returns true if there exist any textures that are linked to backings that - // have had their resources evicted. Only when we commit a tree that has no - // textures linked to evicted backings may we allow drawing. After an - // eviction, this will not become true until unlinkAndClearEvictedBackings - // is called. - bool LinkedEvictedBackingsExist() const; - - // Unlink the list of contents textures' backings from their owning textures - // and delete the evicted backings' structures. This is called just before - // updating layers, and is only ever called on the main thread. - void UnlinkAndClearEvictedBackings(); - - bool RequestLate(PrioritizedResource* texture); - - void ReduceWastedMemory(ResourceProvider* resource_provider); - void ReduceMemory(ResourceProvider* resource_provider); - void ClearAllMemory(ResourceProvider* resource_provider); - - void AcquireBackingTextureIfNeeded(PrioritizedResource* texture, - ResourceProvider* resource_provider); - - void RegisterTexture(PrioritizedResource* texture); - void UnregisterTexture(PrioritizedResource* texture); - void ReturnBackingTexture(PrioritizedResource* texture); - - // Update all backings' priorities from their owning texture. - void PushTexturePrioritiesToBackings(); - - // Mark all textures' backings as being in the drawing impl tree. - void UpdateBackingsState(ResourceProvider* resource_provider); - - const Proxy* ProxyForDebug() const; - - private: - friend class PrioritizedResourceTest; - - enum EvictionPolicy { - EVICT_ONLY_RECYCLABLE, - EVICT_ANYTHING, - }; - enum UnlinkPolicy { - DO_NOT_UNLINK_BACKINGS, - UNLINK_BACKINGS, - }; - - // Compare textures. Highest priority first. - static inline bool CompareTextures(PrioritizedResource* a, - PrioritizedResource* b) { - if (a->request_priority() == b->request_priority()) - return a < b; - return PriorityCalculator::priority_is_higher(a->request_priority(), - b->request_priority()); - } - // Compare backings. Lowest priority first. - static inline bool CompareBackings(PrioritizedResource::Backing* a, - PrioritizedResource::Backing* b) { - // Make textures that can be recycled appear first. - if (a->CanBeRecycledIfNotInExternalUse() != - b->CanBeRecycledIfNotInExternalUse()) - return (a->CanBeRecycledIfNotInExternalUse() > - b->CanBeRecycledIfNotInExternalUse()); - // Then sort by being above or below the priority cutoff. - if (a->was_above_priority_cutoff_at_last_priority_update() != - b->was_above_priority_cutoff_at_last_priority_update()) - return (a->was_above_priority_cutoff_at_last_priority_update() < - b->was_above_priority_cutoff_at_last_priority_update()); - // Then sort by priority (note that backings that no longer have owners will - // always have the lowest priority). - if (a->request_priority_at_last_priority_update() != - b->request_priority_at_last_priority_update()) - return PriorityCalculator::priority_is_lower( - a->request_priority_at_last_priority_update(), - b->request_priority_at_last_priority_update()); - // Then sort by being in the impl tree versus being completely - // unreferenced. - if (a->in_drawing_impl_tree() != b->in_drawing_impl_tree()) - return (a->in_drawing_impl_tree() < b->in_drawing_impl_tree()); - // Finally, prefer to evict textures in the parent compositor because - // they will otherwise take another roundtrip to the parent compositor - // before they are evicted. - if (a->in_parent_compositor() != b->in_parent_compositor()) - return (a->in_parent_compositor() > b->in_parent_compositor()); - return a < b; - } - - explicit PrioritizedResourceManager(const Proxy* proxy); - - bool EvictBackingsToReduceMemory(size_t limit_bytes, - int priority_cutoff, - EvictionPolicy eviction_policy, - UnlinkPolicy unlink_policy, - ResourceProvider* resource_provider); - PrioritizedResource::Backing* CreateBacking( - const gfx::Size& size, - ResourceFormat format, - ResourceProvider* resource_provider); - void EvictFirstBackingResource(ResourceProvider* resource_provider); - void SortBackings(); - - void AssertInvariants(); - - size_t max_memory_limit_bytes_; - // The priority cutoff based on memory pressure. This is not a strict - // cutoff -- RequestLate allows textures with priority equal to this - // cutoff to be allowed. - int priority_cutoff_; - // The priority cutoff based on external memory policy. This is a strict - // cutoff -- no textures with priority equal to this cutoff will be allowed. - int external_priority_cutoff_; - size_t memory_use_bytes_; - size_t memory_above_cutoff_bytes_; - size_t max_memory_needed_bytes_; - size_t memory_available_bytes_; - - typedef base::hash_set<PrioritizedResource*> TextureSet; - typedef std::vector<PrioritizedResource*> TextureVector; - - const Proxy* proxy_; - - TextureSet textures_; - // This list is always sorted in eviction order, with the exception the - // newly-allocated or recycled textures at the very end of the tail that - // are not sorted by priority. - BackingList backings_; - bool backings_tail_not_sorted_; - - // The list of backings that have been evicted, but may still be linked - // to textures. This can be accessed concurrently by the main and impl - // threads, and may only be accessed while holding evicted_backings_lock_. - mutable base::Lock evicted_backings_lock_; - BackingList evicted_backings_; - - TextureVector temp_texture_vector_; - - // Statistics about memory usage at priority cutoffs, computed at - // PrioritizeTextures. - size_t memory_visible_bytes_; - size_t memory_visible_and_nearby_bytes_; - - // Statistics copied at the time of PushTexturePrioritiesToBackings. - size_t memory_visible_last_pushed_bytes_; - size_t memory_visible_and_nearby_last_pushed_bytes_; - - DISALLOW_COPY_AND_ASSIGN(PrioritizedResourceManager); -}; - -} // namespace cc - -#endif // CC_RESOURCES_PRIORITIZED_RESOURCE_MANAGER_H_ diff --git a/chromium/cc/resources/prioritized_resource_unittest.cc b/chromium/cc/resources/prioritized_resource_unittest.cc deleted file mode 100644 index f08af8b752e..00000000000 --- a/chromium/cc/resources/prioritized_resource_unittest.cc +++ /dev/null @@ -1,1117 +0,0 @@ -// Copyright 2012 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/resources/prioritized_resource.h" - -#include <vector> - -#include "cc/resources/prioritized_resource_manager.h" -#include "cc/resources/resource.h" -#include "cc/resources/resource_provider.h" -#include "cc/test/fake_output_surface.h" -#include "cc/test/fake_output_surface_client.h" -#include "cc/test/fake_proxy.h" -#include "cc/test/test_shared_bitmap_manager.h" -#include "cc/test/tiled_layer_test_common.h" -#include "cc/trees/single_thread_proxy.h" // For DebugScopedSetImplThread -#include "testing/gtest/include/gtest/gtest.h" - -namespace cc { - -class PrioritizedResourceTest : public testing::Test { - public: - PrioritizedResourceTest() - : texture_size_(256, 256), - texture_format_(RGBA_8888), - output_surface_(FakeOutputSurface::Create3d()) { - DebugScopedSetImplThread impl_thread(&proxy_); - CHECK(output_surface_->BindToClient(&output_surface_client_)); - shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1); - } - - ~PrioritizedResourceTest() override { - DebugScopedSetImplThread impl_thread(&proxy_); - resource_provider_ = nullptr; - } - - size_t TexturesMemorySize(size_t texture_count) { - return Resource::MemorySizeBytes(texture_size_, texture_format_) * - texture_count; - } - - scoped_ptr<PrioritizedResourceManager> CreateManager(size_t max_textures) { - scoped_ptr<PrioritizedResourceManager> manager = - PrioritizedResourceManager::Create(&proxy_); - manager->SetMaxMemoryLimitBytes(TexturesMemorySize(max_textures)); - return manager.Pass(); - } - - bool ValidateTexture(PrioritizedResource* texture, - bool request_late) { - ResourceManagerAssertInvariants(texture->resource_manager()); - if (request_late) - texture->RequestLate(); - ResourceManagerAssertInvariants(texture->resource_manager()); - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - bool success = texture->can_acquire_backing_texture(); - if (success) - texture->AcquireBackingTexture(resource_provider()); - return success; - } - - void PrioritizeTexturesAndBackings( - PrioritizedResourceManager* resource_manager) { - resource_manager->PrioritizeTextures(); - ResourceManagerUpdateBackingsPriorities(resource_manager); - } - - void ResourceManagerUpdateBackingsPriorities( - PrioritizedResourceManager* resource_manager) { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->PushTexturePrioritiesToBackings(); - } - - ResourceProvider* resource_provider() { return resource_provider_.get(); } - - void ResourceManagerAssertInvariants( - PrioritizedResourceManager* resource_manager) { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->AssertInvariants(); - } - - bool TextureBackingIsAbovePriorityCutoff(PrioritizedResource* texture) { - return texture->backing()-> - was_above_priority_cutoff_at_last_priority_update(); - } - - size_t EvictedBackingCount(PrioritizedResourceManager* resource_manager) { - return resource_manager->evicted_backings_.size(); - } - - std::vector<unsigned> BackingResources( - PrioritizedResourceManager* resource_manager) { - std::vector<unsigned> resources; - for (PrioritizedResourceManager::BackingList::iterator it = - resource_manager->backings_.begin(); - it != resource_manager->backings_.end(); - ++it) - resources.push_back((*it)->id()); - return resources; - } - - protected: - FakeProxy proxy_; - const gfx::Size texture_size_; - const ResourceFormat texture_format_; - FakeOutputSurfaceClient output_surface_client_; - scoped_ptr<OutputSurface> output_surface_; - scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; - scoped_ptr<ResourceProvider> resource_provider_; -}; - -namespace { - -TEST_F(PrioritizedResourceTest, RequestTextureExceedingMaxLimit) { - const size_t kMaxTextures = 8; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - - // Create textures for double our memory limit. - scoped_ptr<PrioritizedResource> textures[kMaxTextures * 2]; - - for (size_t i = 0; i < kMaxTextures * 2; ++i) - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - - // Set decreasing priorities - for (size_t i = 0; i < kMaxTextures * 2; ++i) - textures[i]->set_request_priority(100 + i); - - // Only lower half should be available. - PrioritizeTexturesAndBackings(resource_manager.get()); - EXPECT_TRUE(ValidateTexture(textures[0].get(), false)); - EXPECT_TRUE(ValidateTexture(textures[7].get(), false)); - EXPECT_FALSE(ValidateTexture(textures[8].get(), false)); - EXPECT_FALSE(ValidateTexture(textures[15].get(), false)); - - // Set increasing priorities - for (size_t i = 0; i < kMaxTextures * 2; ++i) - textures[i]->set_request_priority(100 - i); - - // Only upper half should be available. - PrioritizeTexturesAndBackings(resource_manager.get()); - EXPECT_FALSE(ValidateTexture(textures[0].get(), false)); - EXPECT_FALSE(ValidateTexture(textures[7].get(), false)); - EXPECT_TRUE(ValidateTexture(textures[8].get(), false)); - EXPECT_TRUE(ValidateTexture(textures[15].get(), false)); - - EXPECT_EQ(TexturesMemorySize(kMaxTextures), - resource_manager->MemoryAboveCutoffBytes()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - EXPECT_EQ(TexturesMemorySize(2*kMaxTextures), - resource_manager->MaxMemoryNeededBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) { - const size_t kMaxTextures = 8; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - } - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100 + i); - - // Set max limit to 8 textures - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(8)); - PrioritizeTexturesAndBackings(resource_manager.get()); - for (size_t i = 0; i < kMaxTextures; ++i) - ValidateTexture(textures[i].get(), false); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - - EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - - // Set max limit to 5 textures - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(5)); - PrioritizeTexturesAndBackings(resource_manager.get()); - for (size_t i = 0; i < kMaxTextures; ++i) - EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 5); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - - EXPECT_EQ(TexturesMemorySize(5), resource_manager->MemoryAboveCutoffBytes()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - EXPECT_EQ(TexturesMemorySize(kMaxTextures), - resource_manager->MaxMemoryNeededBytes()); - - // Set max limit to 4 textures - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(4)); - PrioritizeTexturesAndBackings(resource_manager.get()); - for (size_t i = 0; i < kMaxTextures; ++i) - EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - - EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - EXPECT_EQ(TexturesMemorySize(kMaxTextures), - resource_manager->MaxMemoryNeededBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, ReduceWastedMemory) { - const size_t kMaxTextures = 20; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - } - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100 + i); - - // Set the memory limit to the max number of textures. - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures)); - PrioritizeTexturesAndBackings(resource_manager.get()); - - // Create backings and textures for all of the textures. - for (size_t i = 0; i < kMaxTextures; ++i) { - ValidateTexture(textures[i].get(), false); - - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - uint8_t image[4] = {0}; - textures[i]->SetPixels(resource_provider_.get(), - image, - gfx::Rect(1, 1), - gfx::Rect(1, 1), - gfx::Vector2d()); - } - } - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - - // 20 textures have backings allocated. - EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); - - // Destroy one texture, not enough is wasted to cause cleanup. - textures[0] = nullptr; - PrioritizeTexturesAndBackings(resource_manager.get()); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->UpdateBackingsState(resource_provider()); - resource_manager->ReduceWastedMemory(resource_provider()); - } - EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); - - // Destroy half the textures, leaving behind the backings. Now a cleanup - // should happen. - for (size_t i = 0; i < kMaxTextures / 2; ++i) - textures[i] = nullptr; - PrioritizeTexturesAndBackings(resource_manager.get()); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->UpdateBackingsState(resource_provider()); - resource_manager->ReduceWastedMemory(resource_provider()); - } - EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, InUseNotWastedMemory) { - const size_t kMaxTextures = 20; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - } - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100 + i); - - // Set the memory limit to the max number of textures. - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures)); - PrioritizeTexturesAndBackings(resource_manager.get()); - - // Create backings and textures for all of the textures. - for (size_t i = 0; i < kMaxTextures; ++i) { - ValidateTexture(textures[i].get(), false); - - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - uint8_t image[4] = {0}; - textures[i]->SetPixels(resource_provider_.get(), - image, - gfx::Rect(1, 1), - gfx::Rect(1, 1), - gfx::Vector2d()); - } - } - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - - // 20 textures have backings allocated. - EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); - - // Send half the textures to a parent compositor. - ResourceProvider::ResourceIdArray to_send; - TransferableResourceArray transferable; - for (size_t i = 0; i < kMaxTextures / 2; ++i) - to_send.push_back(textures[i]->resource_id()); - resource_provider_->PrepareSendToParent(to_send, &transferable); - - // Destroy half the textures, leaving behind the backings. The backings are - // sent to a parent compositor though, so they should not be considered wasted - // and a cleanup should not happen. - for (size_t i = 0; i < kMaxTextures / 2; ++i) - textures[i] = nullptr; - PrioritizeTexturesAndBackings(resource_manager.get()); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->UpdateBackingsState(resource_provider()); - resource_manager->ReduceWastedMemory(resource_provider()); - } - EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); - - // Receive the textures back from the parent compositor. Now a cleanup should - // happen. - ReturnedResourceArray returns; - TransferableResource::ReturnResources(transferable, &returns); - resource_provider_->ReceiveReturnsFromParent(returns); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->UpdateBackingsState(resource_provider()); - resource_manager->ReduceWastedMemory(resource_provider()); - } - EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) { - const size_t kMaxTextures = 8; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - } - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100 + i); - - // Set the cutoff to drop two textures. Try to request_late on all textures, - // and make sure that request_late doesn't work on a texture with equal - // priority to the cutoff. - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(8)); - resource_manager->SetExternalPriorityCutoff(106); - PrioritizeTexturesAndBackings(resource_manager.get()); - for (size_t i = 0; i < kMaxTextures; ++i) - EXPECT_EQ(ValidateTexture(textures[i].get(), true), i < 6); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - EXPECT_EQ(TexturesMemorySize(6), resource_manager->MemoryAboveCutoffBytes()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - - // Set the cutoff to drop two more textures. - resource_manager->SetExternalPriorityCutoff(104); - PrioritizeTexturesAndBackings(resource_manager.get()); - for (size_t i = 0; i < kMaxTextures; ++i) - EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes()); - - // Do a one-time eviction for one more texture based on priority cutoff - resource_manager->UnlinkAndClearEvictedBackings(); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemoryOnImplThread( - TexturesMemorySize(8), 104, resource_provider()); - EXPECT_EQ(0u, EvictedBackingCount(resource_manager.get())); - resource_manager->ReduceMemoryOnImplThread( - TexturesMemorySize(8), 103, resource_provider()); - EXPECT_EQ(1u, EvictedBackingCount(resource_manager.get())); - } - resource_manager->UnlinkAndClearEvictedBackings(); - EXPECT_EQ(TexturesMemorySize(3), resource_manager->MemoryUseBytes()); - - // Re-allocate the the texture after the one-time drop. - PrioritizeTexturesAndBackings(resource_manager.get()); - for (size_t i = 0; i < kMaxTextures; ++i) - EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, EvictingTexturesInParent) { - const size_t kMaxTextures = 8; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - unsigned texture_resource_ids[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - textures[i]->set_request_priority(100 + i); - } - - PrioritizeTexturesAndBackings(resource_manager.get()); - for (size_t i = 0; i < kMaxTextures; ++i) { - EXPECT_TRUE(ValidateTexture(textures[i].get(), true)); - - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - uint8_t image[4] = {0}; - textures[i]->SetPixels(resource_provider_.get(), - image, - gfx::Rect(1, 1), - gfx::Rect(1, 1), - gfx::Vector2d()); - } - } - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes()); - - for (size_t i = 0; i < 8; ++i) - texture_resource_ids[i] = textures[i]->resource_id(); - - // Evict four textures. It will be the last four. - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemoryOnImplThread( - TexturesMemorySize(4), 200, resource_provider()); - - EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get())); - - // The last four backings are evicted. - std::vector<unsigned> remaining = BackingResources(resource_manager.get()); - EXPECT_TRUE(std::find(remaining.begin(), - remaining.end(), - texture_resource_ids[0]) != remaining.end()); - EXPECT_TRUE(std::find(remaining.begin(), - remaining.end(), - texture_resource_ids[1]) != remaining.end()); - EXPECT_TRUE(std::find(remaining.begin(), - remaining.end(), - texture_resource_ids[2]) != remaining.end()); - EXPECT_TRUE(std::find(remaining.begin(), - remaining.end(), - texture_resource_ids[3]) != remaining.end()); - } - resource_manager->UnlinkAndClearEvictedBackings(); - EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes()); - - // Re-allocate the the texture after the eviction. - PrioritizeTexturesAndBackings(resource_manager.get()); - for (size_t i = 0; i < kMaxTextures; ++i) { - EXPECT_TRUE(ValidateTexture(textures[i].get(), true)); - - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - uint8_t image[4] = {0}; - textures[i]->SetPixels(resource_provider_.get(), - image, - gfx::Rect(1, 1), - gfx::Rect(1, 1), - gfx::Vector2d()); - } - } - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemory(resource_provider()); - } - EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes()); - - // Send the last two of the textures to a parent compositor. - ResourceProvider::ResourceIdArray to_send; - TransferableResourceArray transferable; - for (size_t i = 6; i < 8; ++i) - to_send.push_back(textures[i]->resource_id()); - resource_provider_->PrepareSendToParent(to_send, &transferable); - - // Set the last two textures to be tied for prioity with the two - // before them. Being sent to the parent will break the tie. - textures[4]->set_request_priority(100 + 4); - textures[5]->set_request_priority(100 + 5); - textures[6]->set_request_priority(100 + 4); - textures[7]->set_request_priority(100 + 5); - - for (size_t i = 0; i < 8; ++i) - texture_resource_ids[i] = textures[i]->resource_id(); - - // Drop all the textures. Now we have backings that can be recycled. - for (size_t i = 0; i < 8; ++i) - textures[0] = nullptr; - PrioritizeTexturesAndBackings(resource_manager.get()); - - // The next commit finishes. - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->UpdateBackingsState(resource_provider()); - } - - // Evict four textures. It would be the last four again, except that 2 of them - // are sent to the parent, so they are evicted last. - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ReduceMemoryOnImplThread( - TexturesMemorySize(4), 200, resource_provider()); - - EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get())); - // The last 2 backings remain this time. - std::vector<unsigned> remaining = BackingResources(resource_manager.get()); - EXPECT_TRUE(std::find(remaining.begin(), - remaining.end(), - texture_resource_ids[6]) == remaining.end()); - EXPECT_TRUE(std::find(remaining.begin(), - remaining.end(), - texture_resource_ids[7]) == remaining.end()); - } - resource_manager->UnlinkAndClearEvictedBackings(); - EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, ResourceManagerPartialUpdateTextures) { - const size_t kMaxTextures = 4; - const size_t kNumTextures = 4; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - scoped_ptr<PrioritizedResource> textures[kNumTextures]; - scoped_ptr<PrioritizedResource> more_textures[kNumTextures]; - - for (size_t i = 0; i < kNumTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - more_textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - } - - for (size_t i = 0; i < kNumTextures; ++i) - textures[i]->set_request_priority(200 + i); - PrioritizeTexturesAndBackings(resource_manager.get()); - - // Allocate textures which are currently high priority. - EXPECT_TRUE(ValidateTexture(textures[0].get(), false)); - EXPECT_TRUE(ValidateTexture(textures[1].get(), false)); - EXPECT_TRUE(ValidateTexture(textures[2].get(), false)); - EXPECT_TRUE(ValidateTexture(textures[3].get(), false)); - - EXPECT_TRUE(textures[0]->have_backing_texture()); - EXPECT_TRUE(textures[1]->have_backing_texture()); - EXPECT_TRUE(textures[2]->have_backing_texture()); - EXPECT_TRUE(textures[3]->have_backing_texture()); - - for (size_t i = 0; i < kNumTextures; ++i) - more_textures[i]->set_request_priority(100 + i); - PrioritizeTexturesAndBackings(resource_manager.get()); - - // Textures are now below cutoff. - EXPECT_FALSE(ValidateTexture(textures[0].get(), false)); - EXPECT_FALSE(ValidateTexture(textures[1].get(), false)); - EXPECT_FALSE(ValidateTexture(textures[2].get(), false)); - EXPECT_FALSE(ValidateTexture(textures[3].get(), false)); - - // But they are still valid to use. - EXPECT_TRUE(textures[0]->have_backing_texture()); - EXPECT_TRUE(textures[1]->have_backing_texture()); - EXPECT_TRUE(textures[2]->have_backing_texture()); - EXPECT_TRUE(textures[3]->have_backing_texture()); - - // Higher priority textures are finally needed. - EXPECT_TRUE(ValidateTexture(more_textures[0].get(), false)); - EXPECT_TRUE(ValidateTexture(more_textures[1].get(), false)); - EXPECT_TRUE(ValidateTexture(more_textures[2].get(), false)); - EXPECT_TRUE(ValidateTexture(more_textures[3].get(), false)); - - // Lower priority have been fully evicted. - EXPECT_FALSE(textures[0]->have_backing_texture()); - EXPECT_FALSE(textures[1]->have_backing_texture()); - EXPECT_FALSE(textures[2]->have_backing_texture()); - EXPECT_FALSE(textures[3]->have_backing_texture()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, ResourceManagerPrioritiesAreEqual) { - const size_t kMaxTextures = 16; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - } - - // All 16 textures have the same priority except 2 higher priority. - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100); - textures[0]->set_request_priority(99); - textures[1]->set_request_priority(99); - - // Set max limit to 8 textures - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(8)); - PrioritizeTexturesAndBackings(resource_manager.get()); - - // The two high priority textures should be available, others should not. - for (size_t i = 0; i < 2; ++i) - EXPECT_TRUE(ValidateTexture(textures[i].get(), false)); - for (size_t i = 2; i < kMaxTextures; ++i) - EXPECT_FALSE(ValidateTexture(textures[i].get(), false)); - EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryAboveCutoffBytes()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - - // Manually reserving textures should only succeed on the higher priority - // textures, and on remaining textures up to the memory limit. - for (size_t i = 0; i < 8; i++) - EXPECT_TRUE(ValidateTexture(textures[i].get(), true)); - for (size_t i = 9; i < kMaxTextures; i++) - EXPECT_FALSE(ValidateTexture(textures[i].get(), true)); - EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, ResourceManagerDestroyedFirst) { - scoped_ptr<PrioritizedResourceManager> resource_manager = CreateManager(1); - scoped_ptr<PrioritizedResource> texture = - resource_manager->CreateTexture(texture_size_, texture_format_); - - // Texture is initially invalid, but it will become available. - EXPECT_FALSE(texture->have_backing_texture()); - - texture->set_request_priority(100); - PrioritizeTexturesAndBackings(resource_manager.get()); - - EXPECT_TRUE(ValidateTexture(texture.get(), false)); - EXPECT_TRUE(texture->can_acquire_backing_texture()); - EXPECT_TRUE(texture->have_backing_texture()); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); - } - resource_manager = nullptr; - - EXPECT_FALSE(texture->can_acquire_backing_texture()); - EXPECT_FALSE(texture->have_backing_texture()); -} - -TEST_F(PrioritizedResourceTest, TextureMovedToNewManager) { - scoped_ptr<PrioritizedResourceManager> resource_manager_one = - CreateManager(1); - scoped_ptr<PrioritizedResourceManager> resource_manager_two = - CreateManager(1); - scoped_ptr<PrioritizedResource> texture = - resource_manager_one->CreateTexture(texture_size_, texture_format_); - - // Texture is initially invalid, but it will become available. - EXPECT_FALSE(texture->have_backing_texture()); - - texture->set_request_priority(100); - PrioritizeTexturesAndBackings(resource_manager_one.get()); - - EXPECT_TRUE(ValidateTexture(texture.get(), false)); - EXPECT_TRUE(texture->can_acquire_backing_texture()); - EXPECT_TRUE(texture->have_backing_texture()); - - texture->SetTextureManager(NULL); - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager_one->ClearAllMemory(resource_provider()); - } - resource_manager_one = nullptr; - - EXPECT_FALSE(texture->can_acquire_backing_texture()); - EXPECT_FALSE(texture->have_backing_texture()); - - texture->SetTextureManager(resource_manager_two.get()); - - PrioritizeTexturesAndBackings(resource_manager_two.get()); - - EXPECT_TRUE(ValidateTexture(texture.get(), false)); - EXPECT_TRUE(texture->can_acquire_backing_texture()); - EXPECT_TRUE(texture->have_backing_texture()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager_two->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, - RenderSurfacesReduceMemoryAvailableOutsideRootSurface) { - const size_t kMaxTextures = 8; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - - // Half of the memory is taken by surfaces (with high priority place-holder) - scoped_ptr<PrioritizedResource> render_surface_place_holder = - resource_manager->CreateTexture(texture_size_, texture_format_); - render_surface_place_holder->SetToSelfManagedMemoryPlaceholder( - TexturesMemorySize(4)); - render_surface_place_holder->set_request_priority( - PriorityCalculator::RenderSurfacePriority()); - - // Create textures to fill our memory limit. - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - } - - // Set decreasing non-visible priorities outside root surface. - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100 + i); - - // Only lower half should be available. - PrioritizeTexturesAndBackings(resource_manager.get()); - EXPECT_TRUE(ValidateTexture(textures[0].get(), false)); - EXPECT_TRUE(ValidateTexture(textures[3].get(), false)); - EXPECT_FALSE(ValidateTexture(textures[4].get(), false)); - EXPECT_FALSE(ValidateTexture(textures[7].get(), false)); - - // Set increasing non-visible priorities outside root surface. - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100 - i); - - // Only upper half should be available. - PrioritizeTexturesAndBackings(resource_manager.get()); - EXPECT_FALSE(ValidateTexture(textures[0].get(), false)); - EXPECT_FALSE(ValidateTexture(textures[3].get(), false)); - EXPECT_TRUE(ValidateTexture(textures[4].get(), false)); - EXPECT_TRUE(ValidateTexture(textures[7].get(), false)); - - EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes()); - EXPECT_EQ(TexturesMemorySize(4), - resource_manager->MemoryForSelfManagedTextures()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - EXPECT_EQ(TexturesMemorySize(8), - resource_manager->MaxMemoryNeededBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, - RenderSurfacesReduceMemoryAvailableForRequestLate) { - const size_t kMaxTextures = 8; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - - // Half of the memory is taken by surfaces (with high priority place-holder) - scoped_ptr<PrioritizedResource> render_surface_place_holder = - resource_manager->CreateTexture(texture_size_, texture_format_); - render_surface_place_holder->SetToSelfManagedMemoryPlaceholder( - TexturesMemorySize(4)); - render_surface_place_holder->set_request_priority( - PriorityCalculator::RenderSurfacePriority()); - - // Create textures to fill our memory limit. - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - } - - // Set equal priorities. - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100); - - // The first four to be requested late will be available. - PrioritizeTexturesAndBackings(resource_manager.get()); - for (unsigned i = 0; i < kMaxTextures; ++i) - EXPECT_FALSE(ValidateTexture(textures[i].get(), false)); - for (unsigned i = 0; i < kMaxTextures; i += 2) - EXPECT_TRUE(ValidateTexture(textures[i].get(), true)); - for (unsigned i = 1; i < kMaxTextures; i += 2) - EXPECT_FALSE(ValidateTexture(textures[i].get(), true)); - - EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes()); - EXPECT_EQ(TexturesMemorySize(4), - resource_manager->MemoryForSelfManagedTextures()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - EXPECT_EQ(TexturesMemorySize(8), - resource_manager->MaxMemoryNeededBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, - WhenRenderSurfaceNotAvailableTexturesAlsoNotAvailable) { - const size_t kMaxTextures = 8; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - - // Half of the memory is taken by surfaces (with high priority place-holder) - scoped_ptr<PrioritizedResource> render_surface_place_holder = - resource_manager->CreateTexture(texture_size_, texture_format_); - render_surface_place_holder->SetToSelfManagedMemoryPlaceholder( - TexturesMemorySize(4)); - render_surface_place_holder->set_request_priority( - PriorityCalculator::RenderSurfacePriority()); - - // Create textures to fill our memory limit. - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - - // Set 6 visible textures in the root surface, and 2 in a child surface. - for (size_t i = 0; i < 6; ++i) { - textures[i]-> - set_request_priority(PriorityCalculator::VisiblePriority(true)); - } - for (size_t i = 6; i < 8; ++i) { - textures[i]-> - set_request_priority(PriorityCalculator::VisiblePriority(false)); - } - - PrioritizeTexturesAndBackings(resource_manager.get()); - - // Unable to request_late textures in the child surface. - EXPECT_FALSE(ValidateTexture(textures[6].get(), true)); - EXPECT_FALSE(ValidateTexture(textures[7].get(), true)); - - // Root surface textures are valid. - for (size_t i = 0; i < 6; ++i) - EXPECT_TRUE(ValidateTexture(textures[i].get(), false)); - - EXPECT_EQ(TexturesMemorySize(6), resource_manager->MemoryAboveCutoffBytes()); - EXPECT_EQ(TexturesMemorySize(2), - resource_manager->MemoryForSelfManagedTextures()); - EXPECT_LE(resource_manager->MemoryUseBytes(), - resource_manager->MemoryAboveCutoffBytes()); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, RequestLateBackingsSorting) { - const size_t kMaxTextures = 8; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures)); - - // Create textures to fill our memory limit. - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - - // Set equal priorities, and allocate backings for all textures. - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100); - PrioritizeTexturesAndBackings(resource_manager.get()); - for (unsigned i = 0; i < kMaxTextures; ++i) - EXPECT_TRUE(ValidateTexture(textures[i].get(), false)); - - // Drop the memory limit and prioritize (none will be above the threshold, - // but they still have backings because ReduceMemory hasn't been called). - resource_manager->SetMaxMemoryLimitBytes( - TexturesMemorySize(kMaxTextures / 2)); - PrioritizeTexturesAndBackings(resource_manager.get()); - - // Push half of them back over the limit. - for (size_t i = 0; i < kMaxTextures; i += 2) - EXPECT_TRUE(textures[i]->RequestLate()); - - // Push the priorities to the backings array and sort the backings array - ResourceManagerUpdateBackingsPriorities(resource_manager.get()); - - // Assert that the backings list be sorted with the below-limit backings - // before the above-limit backings. - ResourceManagerAssertInvariants(resource_manager.get()); - - // Make sure that we have backings for all of the textures. - for (size_t i = 0; i < kMaxTextures; ++i) - EXPECT_TRUE(textures[i]->have_backing_texture()); - - // Make sure that only the request_late textures are above the priority - // cutoff - for (size_t i = 0; i < kMaxTextures; i += 2) - EXPECT_TRUE(TextureBackingIsAbovePriorityCutoff(textures[i].get())); - for (size_t i = 1; i < kMaxTextures; i += 2) - EXPECT_FALSE(TextureBackingIsAbovePriorityCutoff(textures[i].get())); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -TEST_F(PrioritizedResourceTest, ClearUploadsToEvictedResources) { - const size_t kMaxTextures = 4; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures)); - - // Create textures to fill our memory limit. - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - - // Set equal priorities, and allocate backings for all textures. - for (size_t i = 0; i < kMaxTextures; ++i) - textures[i]->set_request_priority(100); - PrioritizeTexturesAndBackings(resource_manager.get()); - for (unsigned i = 0; i < kMaxTextures; ++i) - EXPECT_TRUE(ValidateTexture(textures[i].get(), false)); - - ResourceUpdateQueue queue; - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - for (size_t i = 0; i < kMaxTextures; ++i) { - const ResourceUpdate upload = ResourceUpdate::Create( - textures[i].get(), NULL, gfx::Rect(), gfx::Rect(), gfx::Vector2d()); - queue.AppendFullUpload(upload); - } - - // Make sure that we have backings for all of the textures. - for (size_t i = 0; i < kMaxTextures; ++i) - EXPECT_TRUE(textures[i]->have_backing_texture()); - - queue.ClearUploadsToEvictedResources(); - EXPECT_EQ(4u, queue.FullUploadSize()); - - resource_manager->ReduceMemoryOnImplThread( - TexturesMemorySize(1), - PriorityCalculator::AllowEverythingCutoff(), - resource_provider()); - queue.ClearUploadsToEvictedResources(); - EXPECT_EQ(1u, queue.FullUploadSize()); - - resource_manager->ReduceMemoryOnImplThread( - 0, PriorityCalculator::AllowEverythingCutoff(), resource_provider()); - queue.ClearUploadsToEvictedResources(); - EXPECT_EQ(0u, queue.FullUploadSize()); -} - -TEST_F(PrioritizedResourceTest, UsageStatistics) { - const size_t kMaxTextures = 5; - scoped_ptr<PrioritizedResourceManager> resource_manager = - CreateManager(kMaxTextures); - scoped_ptr<PrioritizedResource> textures[kMaxTextures]; - - for (size_t i = 0; i < kMaxTextures; ++i) { - textures[i] = - resource_manager->CreateTexture(texture_size_, texture_format_); - } - - textures[0]-> - set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1); - textures[1]-> - set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff()); - textures[2]->set_request_priority( - PriorityCalculator::AllowVisibleAndNearbyCutoff() - 1); - textures[3]-> - set_request_priority(PriorityCalculator::AllowVisibleAndNearbyCutoff()); - textures[4]->set_request_priority( - PriorityCalculator::AllowVisibleAndNearbyCutoff() + 1); - - // Set max limit to 2 textures. - resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(2)); - PrioritizeTexturesAndBackings(resource_manager.get()); - - // The first two textures should be available, others should not. - for (size_t i = 0; i < 2; ++i) - EXPECT_TRUE(ValidateTexture(textures[i].get(), false)); - for (size_t i = 2; i < kMaxTextures; ++i) - EXPECT_FALSE(ValidateTexture(textures[i].get(), false)); - - // Validate the statistics. - { - DebugScopedSetImplThread impl_thread(&proxy_); - EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes()); - EXPECT_EQ(TexturesMemorySize(1), resource_manager->MemoryVisibleBytes()); - EXPECT_EQ(TexturesMemorySize(3), - resource_manager->MemoryVisibleAndNearbyBytes()); - } - - // Re-prioritize the textures, but do not push the values to backings. - textures[0]-> - set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1); - textures[1]-> - set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1); - textures[2]-> - set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1); - textures[3]->set_request_priority( - PriorityCalculator::AllowVisibleAndNearbyCutoff() - 1); - textures[4]-> - set_request_priority(PriorityCalculator::AllowVisibleAndNearbyCutoff()); - resource_manager->PrioritizeTextures(); - - // Verify that we still see the old values. - { - DebugScopedSetImplThread impl_thread(&proxy_); - EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes()); - EXPECT_EQ(TexturesMemorySize(1), resource_manager->MemoryVisibleBytes()); - EXPECT_EQ(TexturesMemorySize(3), - resource_manager->MemoryVisibleAndNearbyBytes()); - } - - // Push priorities to backings, and verify we see the new values. - { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->PushTexturePrioritiesToBackings(); - EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes()); - EXPECT_EQ(TexturesMemorySize(3), resource_manager->MemoryVisibleBytes()); - EXPECT_EQ(TexturesMemorySize(4), - resource_manager->MemoryVisibleAndNearbyBytes()); - } - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager->ClearAllMemory(resource_provider()); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/resources/priority_calculator.cc b/chromium/cc/resources/priority_calculator.cc deleted file mode 100644 index 5f5916fda9c..00000000000 --- a/chromium/cc/resources/priority_calculator.cc +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2012 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/resources/priority_calculator.h" - -#include <algorithm> - -#include "ui/gfx/geometry/rect.h" - -namespace cc { - -static const int kNothingPriorityCutoff = -3; - -static const int kMostHighPriority = -2; - -static const int kUIDrawsToRootSurfacePriority = -1; -static const int kVisibleDrawsToRootSurfacePriority = 0; -static const int kRenderSurfacesPriority = 1; -static const int kUIDoesNotDrawToRootSurfacePriority = 2; -static const int kVisibleDoesNotDrawToRootSurfacePriority = 3; - -static const int kVisibleOnlyPriorityCutoff = 4; - -// The lower digits are how far from being visible the texture is, -// in pixels. -static const int kNotVisibleBasePriority = 1000000; -static const int kNotVisibleLimitPriority = 1900000; - -// Arbitrarily define "nearby" to be 2000 pixels. A better estimate -// would be percent-of-viewport or percent-of-screen. -static const int kVisibleAndNearbyPriorityCutoff = - kNotVisibleBasePriority + 2000; - -// Small animated layers are treated as though they are 512 pixels -// from being visible. -static const int kSmallAnimatedLayerPriority = kNotVisibleBasePriority + 512; - -static const int kLingeringBasePriority = 2000000; -static const int kLingeringLimitPriority = 2900000; - -static const int kMostLowPriority = 3000000; - -static const int kEverythingPriorityCutoff = 3000001; - -// static -int PriorityCalculator::UIPriority(bool draws_to_root_surface) { - return draws_to_root_surface ? kUIDrawsToRootSurfacePriority - : kUIDoesNotDrawToRootSurfacePriority; -} - -// static -int PriorityCalculator::VisiblePriority(bool draws_to_root_surface) { - return draws_to_root_surface ? kVisibleDrawsToRootSurfacePriority - : kVisibleDoesNotDrawToRootSurfacePriority; -} - -// static -int PriorityCalculator::RenderSurfacePriority() { - return kRenderSurfacesPriority; -} - -// static -int PriorityCalculator::LingeringPriority(int previous_priority) { - // TODO(reveman): We should remove this once we have priorities for all - // textures (we can't currently calculate distances for off-screen textures). - return std::min(kLingeringLimitPriority, - std::max(kLingeringBasePriority, previous_priority + 1)); -} - -// static -int PriorityCalculator::PriorityFromDistance(const gfx::Rect& visible_rect, - const gfx::Rect& texture_rect, - bool draws_to_root_surface) { - int distance = visible_rect.ManhattanInternalDistance(texture_rect); - if (!distance) - return VisiblePriority(draws_to_root_surface); - return std::min(kNotVisibleLimitPriority, kNotVisibleBasePriority + distance); -} - -// static -int PriorityCalculator::SmallAnimatedLayerMinPriority() { - return kSmallAnimatedLayerPriority; -} - -// static -int PriorityCalculator::HighestPriority() { - return kMostHighPriority; -} - -// static -int PriorityCalculator::LowestPriority() { - return kMostLowPriority; -} - -// static -int PriorityCalculator::AllowNothingCutoff() { - return kNothingPriorityCutoff; -} - -// static -int PriorityCalculator::AllowVisibleOnlyCutoff() { - return kVisibleOnlyPriorityCutoff; -} - -// static -int PriorityCalculator::AllowVisibleAndNearbyCutoff() { - return kVisibleAndNearbyPriorityCutoff; -} - -// static -int PriorityCalculator::AllowEverythingCutoff() { - return kEverythingPriorityCutoff; -} - -} // namespace cc diff --git a/chromium/cc/resources/priority_calculator.h b/chromium/cc/resources/priority_calculator.h deleted file mode 100644 index 502bd2734f8..00000000000 --- a/chromium/cc/resources/priority_calculator.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_PRIORITY_CALCULATOR_H_ -#define CC_RESOURCES_PRIORITY_CALCULATOR_H_ - -#include "base/basictypes.h" -#include "cc/base/cc_export.h" - -namespace gfx { class Rect; } - -namespace cc { - -class CC_EXPORT PriorityCalculator { - public: - PriorityCalculator() {} - - static int UIPriority(bool draws_to_root_surface); - static int VisiblePriority(bool draws_to_root_surface); - static int RenderSurfacePriority(); - static int LingeringPriority(int previous_priority); - static int PriorityFromDistance(const gfx::Rect& visible_rect, - const gfx::Rect& texture_rect, - bool draws_to_root_surface); - static int SmallAnimatedLayerMinPriority(); - - static int HighestPriority(); - static int LowestPriority(); - static inline bool priority_is_lower(int a, int b) { return a > b; } - static inline bool priority_is_higher(int a, int b) { return a < b; } - static inline int max_priority(int a, int b) { - return priority_is_higher(a, b) ? a : b; - } - - static int AllowNothingCutoff(); - static int AllowVisibleOnlyCutoff(); - static int AllowVisibleAndNearbyCutoff(); - static int AllowEverythingCutoff(); - - private: - DISALLOW_COPY_AND_ASSIGN(PriorityCalculator); -}; - -} // namespace cc - -#endif // CC_RESOURCES_PRIORITY_CALCULATOR_H_ diff --git a/chromium/cc/resources/resource.cc b/chromium/cc/resources/resource.cc deleted file mode 100644 index 9bbcd4f498b..00000000000 --- a/chromium/cc/resources/resource.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 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/resources/resource.h" - -namespace cc { - -size_t Resource::bytes() const { - if (size_.IsEmpty()) - return 0; - - return MemorySizeBytes(size_, format_); -} - - -} // namespace cc diff --git a/chromium/cc/resources/resource.h b/chromium/cc/resources/resource.h index edafaefcfa3..f9138fbb876 100644 --- a/chromium/cc/resources/resource.h +++ b/chromium/cc/resources/resource.h @@ -5,6 +5,7 @@ #ifndef CC_RESOURCES_RESOURCE_H_ #define CC_RESOURCES_RESOURCE_H_ +#include "base/numerics/safe_math.h" #include "cc/base/cc_export.h" #include "cc/resources/resource_provider.h" #include "ui/gfx/geometry/size.h" @@ -13,32 +14,56 @@ namespace cc { class CC_EXPORT Resource { public: - Resource() : id_(0) {} + Resource() : id_(0), format_(RGBA_8888) {} Resource(unsigned id, const gfx::Size& size, ResourceFormat format) : id_(id), size_(size), format_(format) {} - ResourceProvider::ResourceId id() const { return id_; } + ResourceId id() const { return id_; } gfx::Size size() const { return size_; } ResourceFormat format() const { return format_; } - size_t bytes() const; - inline static size_t MemorySizeBytes(const gfx::Size& size, + // Return true if the call to UncheckedMemorySizeBytes would return a value + // that fits in a size_t. + static bool VerifySizeInBytes(const gfx::Size& size, ResourceFormat format) { + base::CheckedNumeric<size_t> checked_value = BitsPerPixel(format); + checked_value *= size.width(); + checked_value *= size.height(); + if (!checked_value.IsValid()) + return false; + size_t value = checked_value.ValueOrDie(); + if ((value % 8) != 0) + return false; + return true; + } + + static size_t CheckedMemorySizeBytes(const gfx::Size& size, ResourceFormat format) { - DCHECK_EQ(0u, (BitsPerPixel(format) * size.width() * size.height()) % 8); - return (BitsPerPixel(format) * size.width() * size.height()) / 8; + DCHECK(VerifySizeInBytes(size, format)); + base::CheckedNumeric<size_t> checked_value = BitsPerPixel(format); + checked_value *= size.width(); + checked_value *= size.height(); + checked_value /= 8; + return checked_value.ValueOrDie(); + } + + inline static size_t UncheckedMemorySizeBytes(const gfx::Size& size, + ResourceFormat format) { + DCHECK(VerifySizeInBytes(size, format)); + return static_cast<size_t>(BitsPerPixel(format)) * size.width() * + size.height() / 8; } protected: - void set_id(ResourceProvider::ResourceId id) { id_ = id; } + void set_id(ResourceId id) { id_ = id; } void set_dimensions(const gfx::Size& size, ResourceFormat format) { size_ = size; format_ = format; } private: - ResourceProvider::ResourceId id_; + ResourceId id_; gfx::Size size_; ResourceFormat format_; diff --git a/chromium/cc/resources/resource_pool.cc b/chromium/cc/resources/resource_pool.cc index 22847809ba3..7b65d344ab3 100644 --- a/chromium/cc/resources/resource_pool.cc +++ b/chromium/cc/resources/resource_pool.cc @@ -21,7 +21,8 @@ ResourcePool::ResourcePool(ResourceProvider* resource_provider, GLenum target) ResourcePool::~ResourcePool() { while (!busy_resources_.empty()) { - DidFinishUsingResource(busy_resources_.front()); + auto const& front = busy_resources_.front(); + DidFinishUsingResource(front.resource, front.content_id); busy_resources_.pop_front(); } @@ -37,7 +38,7 @@ scoped_ptr<ScopedResource> ResourcePool::AcquireResource( for (ResourceList::iterator it = unused_resources_.begin(); it != unused_resources_.end(); ++it) { - ScopedResource* resource = *it; + ScopedResource* resource = it->resource; DCHECK(resource_provider_->CanLockForWrite(resource->id())); if (resource->format() != format) @@ -46,7 +47,8 @@ scoped_ptr<ScopedResource> ResourcePool::AcquireResource( continue; unused_resources_.erase(it); - unused_memory_usage_bytes_ -= resource->bytes(); + unused_memory_usage_bytes_ -= + Resource::UncheckedMemorySizeBytes(size, format); return make_scoped_ptr(resource); } @@ -54,13 +56,36 @@ scoped_ptr<ScopedResource> ResourcePool::AcquireResource( ScopedResource::Create(resource_provider_); resource->AllocateManaged(size, target_, format); - memory_usage_bytes_ += resource->bytes(); + DCHECK(Resource::VerifySizeInBytes(resource->size(), resource->format())); + memory_usage_bytes_ += + Resource::UncheckedMemorySizeBytes(resource->size(), resource->format()); ++resource_count_; return resource.Pass(); } -void ResourcePool::ReleaseResource(scoped_ptr<ScopedResource> resource) { - busy_resources_.push_back(resource.release()); +scoped_ptr<ScopedResource> ResourcePool::TryAcquireResourceWithContentId( + uint64_t content_id) { + DCHECK(content_id); + + auto it = std::find_if(unused_resources_.begin(), unused_resources_.end(), + [content_id](const PoolResource& pool_resource) { + return pool_resource.content_id == content_id; + }); + if (it == unused_resources_.end()) + return nullptr; + + ScopedResource* resource = it->resource; + DCHECK(resource_provider_->CanLockForWrite(resource->id())); + + unused_resources_.erase(it); + unused_memory_usage_bytes_ -= + Resource::UncheckedMemorySizeBytes(resource->size(), resource->format()); + return make_scoped_ptr(resource); +} + +void ResourcePool::ReleaseResource(scoped_ptr<ScopedResource> resource, + uint64_t content_id) { + busy_resources_.push_back(PoolResource(resource.release(), content_id)); } void ResourcePool::SetResourceUsageLimits(size_t max_memory_usage_bytes, @@ -85,12 +110,11 @@ void ResourcePool::ReduceResourceUsage() { // can't be locked for write might also not be truly free-able. // We can free the resource here but it doesn't mean that the // memory is necessarily returned to the OS. - ScopedResource* resource = unused_resources_.front(); + ScopedResource* resource = unused_resources_.front().resource; unused_resources_.pop_front(); - memory_usage_bytes_ -= resource->bytes(); - unused_memory_usage_bytes_ -= resource->bytes(); - --resource_count_; - delete resource; + unused_memory_usage_bytes_ -= Resource::UncheckedMemorySizeBytes( + resource->size(), resource->format()); + DeleteResource(resource); } } @@ -104,17 +128,29 @@ bool ResourcePool::ResourceUsageTooHigh() { return false; } +void ResourcePool::DeleteResource(ScopedResource* resource) { + size_t resource_bytes = + Resource::UncheckedMemorySizeBytes(resource->size(), resource->format()); + memory_usage_bytes_ -= resource_bytes; + --resource_count_; + delete resource; +} + void ResourcePool::CheckBusyResources(bool wait_if_needed) { ResourceList::iterator it = busy_resources_.begin(); while (it != busy_resources_.end()) { - ScopedResource* resource = *it; + ScopedResource* resource = it->resource; if (wait_if_needed) resource_provider_->WaitReadLockIfNeeded(resource->id()); if (resource_provider_->CanLockForWrite(resource->id())) { - DidFinishUsingResource(resource); + DidFinishUsingResource(resource, it->content_id); + it = busy_resources_.erase(it); + } else if (resource_provider_->IsLost(resource->id())) { + // Remove lost resources from pool. + DeleteResource(resource); it = busy_resources_.erase(it); } else { ++it; @@ -122,9 +158,11 @@ void ResourcePool::CheckBusyResources(bool wait_if_needed) { } } -void ResourcePool::DidFinishUsingResource(ScopedResource* resource) { - unused_memory_usage_bytes_ += resource->bytes(); - unused_resources_.push_back(resource); +void ResourcePool::DidFinishUsingResource(ScopedResource* resource, + uint64_t content_id) { + unused_memory_usage_bytes_ += + Resource::UncheckedMemorySizeBytes(resource->size(), resource->format()); + unused_resources_.push_back(PoolResource(resource, content_id)); } } // namespace cc diff --git a/chromium/cc/resources/resource_pool.h b/chromium/cc/resources/resource_pool.h index f79455905dd..88816aa73d4 100644 --- a/chromium/cc/resources/resource_pool.h +++ b/chromium/cc/resources/resource_pool.h @@ -5,7 +5,7 @@ #ifndef CC_RESOURCES_RESOURCE_POOL_H_ #define CC_RESOURCES_RESOURCE_POOL_H_ -#include <list> +#include <deque> #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" @@ -27,7 +27,9 @@ class CC_EXPORT ResourcePool { scoped_ptr<ScopedResource> AcquireResource(const gfx::Size& size, ResourceFormat format); - void ReleaseResource(scoped_ptr<ScopedResource>); + scoped_ptr<ScopedResource> TryAcquireResourceWithContentId(uint64 content_id); + void ReleaseResource(scoped_ptr<ScopedResource> resource, + uint64_t content_id); void SetResourceUsageLimits(size_t max_memory_usage_bytes, size_t max_unused_memory_usage_bytes, @@ -55,7 +57,8 @@ class CC_EXPORT ResourcePool { bool ResourceUsageTooHigh(); private: - void DidFinishUsingResource(ScopedResource* resource); + void DidFinishUsingResource(ScopedResource* resource, uint64_t content_id); + void DeleteResource(ScopedResource* resource); ResourceProvider* resource_provider_; const GLenum target_; @@ -66,7 +69,13 @@ class CC_EXPORT ResourcePool { size_t unused_memory_usage_bytes_; size_t resource_count_; - typedef std::list<ScopedResource*> ResourceList; + struct PoolResource { + PoolResource(ScopedResource* resource, uint64_t content_id) + : resource(resource), content_id(content_id) {} + ScopedResource* resource; + uint64_t content_id; + }; + typedef std::deque<PoolResource> ResourceList; ResourceList unused_resources_; ResourceList busy_resources_; diff --git a/chromium/cc/resources/resource_pool_unittest.cc b/chromium/cc/resources/resource_pool_unittest.cc new file mode 100644 index 00000000000..96e7591ab8c --- /dev/null +++ b/chromium/cc/resources/resource_pool_unittest.cc @@ -0,0 +1,141 @@ +// Copyright 2015 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/resources/resource_pool.h" + +#include "cc/resources/scoped_resource.h" +#include "cc/test/fake_output_surface.h" +#include "cc/test/fake_output_surface_client.h" +#include "cc/test/fake_resource_provider.h" +#include "cc/test/test_shared_bitmap_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +class ResourcePoolTest : public testing::Test { + public: + void SetUp() override { + output_surface_ = FakeOutputSurface::Create3d(); + ASSERT_TRUE(output_surface_->BindToClient(&output_surface_client_)); + shared_bitmap_manager_.reset(new TestSharedBitmapManager()); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), shared_bitmap_manager_.get()); + resource_pool_ = + ResourcePool::Create(resource_provider_.get(), GL_TEXTURE_2D); + } + + protected: + FakeOutputSurfaceClient output_surface_client_; + scoped_ptr<FakeOutputSurface> output_surface_; + scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; + scoped_ptr<ResourceProvider> resource_provider_; + scoped_ptr<ResourcePool> resource_pool_; +}; + +TEST_F(ResourcePoolTest, AcquireRelease) { + gfx::Size size(100, 100); + ResourceFormat format = RGBA_8888; + scoped_ptr<ScopedResource> resource = + resource_pool_->AcquireResource(size, format); + EXPECT_EQ(size, resource->size()); + EXPECT_EQ(format, resource->format()); + EXPECT_TRUE(resource_provider_->CanLockForWrite(resource->id())); + + resource_pool_->ReleaseResource(resource.Pass(), 0u); +} + +TEST_F(ResourcePoolTest, AccountingSingleResource) { + // Limits high enough to not be hit by this test. + size_t bytes_limit = 10 * 1024 * 1024; + size_t count_limit = 100; + resource_pool_->SetResourceUsageLimits(bytes_limit, bytes_limit, count_limit); + + gfx::Size size(100, 100); + ResourceFormat format = RGBA_8888; + size_t resource_bytes = Resource::UncheckedMemorySizeBytes(size, format); + scoped_ptr<ScopedResource> resource = + resource_pool_->AcquireResource(size, format); + + EXPECT_EQ(resource_bytes, resource_pool_->total_memory_usage_bytes()); + EXPECT_EQ(resource_bytes, resource_pool_->acquired_memory_usage_bytes()); + EXPECT_EQ(1u, resource_pool_->total_resource_count()); + EXPECT_EQ(1u, resource_pool_->acquired_resource_count()); + EXPECT_EQ(0u, resource_pool_->busy_resource_count()); + + resource_pool_->ReleaseResource(resource.Pass(), 0u); + EXPECT_EQ(resource_bytes, resource_pool_->total_memory_usage_bytes()); + EXPECT_EQ(1u, resource_pool_->total_resource_count()); + EXPECT_EQ(1u, resource_pool_->busy_resource_count()); + + bool wait_if_needed = false; + resource_pool_->CheckBusyResources(wait_if_needed); + EXPECT_EQ(resource_bytes, resource_pool_->total_memory_usage_bytes()); + EXPECT_EQ(0u, resource_pool_->acquired_memory_usage_bytes()); + EXPECT_EQ(1u, resource_pool_->total_resource_count()); + EXPECT_EQ(0u, resource_pool_->acquired_resource_count()); + EXPECT_EQ(0u, resource_pool_->busy_resource_count()); + + resource_pool_->SetResourceUsageLimits(0u, 0u, 0u); + resource_pool_->ReduceResourceUsage(); + EXPECT_EQ(0u, resource_pool_->total_memory_usage_bytes()); + EXPECT_EQ(0u, resource_pool_->acquired_memory_usage_bytes()); + EXPECT_EQ(0u, resource_pool_->total_resource_count()); + EXPECT_EQ(0u, resource_pool_->acquired_resource_count()); + EXPECT_EQ(0u, resource_pool_->busy_resource_count()); +} + +TEST_F(ResourcePoolTest, SimpleResourceReuse) { + // Limits high enough to not be hit by this test. + size_t bytes_limit = 10 * 1024 * 1024; + size_t count_limit = 100; + resource_pool_->SetResourceUsageLimits(bytes_limit, bytes_limit, count_limit); + + gfx::Size size(100, 100); + ResourceFormat format = RGBA_8888; + bool wait_if_needed = false; + + scoped_ptr<ScopedResource> resource = + resource_pool_->AcquireResource(size, format); + resource_pool_->ReleaseResource(resource.Pass(), 0u); + resource_pool_->CheckBusyResources(wait_if_needed); + EXPECT_EQ(1u, resource_provider_->num_resources()); + + // Same size/format should re-use resource. + resource = resource_pool_->AcquireResource(size, format); + EXPECT_EQ(1u, resource_provider_->num_resources()); + resource_pool_->ReleaseResource(resource.Pass(), 0u); + resource_pool_->CheckBusyResources(wait_if_needed); + EXPECT_EQ(1u, resource_provider_->num_resources()); + + // Different size/format should alloate new resource. + resource = resource_pool_->AcquireResource(gfx::Size(50, 50), LUMINANCE_8); + EXPECT_EQ(2u, resource_provider_->num_resources()); + resource_pool_->ReleaseResource(resource.Pass(), 0u); + resource_pool_->CheckBusyResources(wait_if_needed); + EXPECT_EQ(2u, resource_provider_->num_resources()); +} + +TEST_F(ResourcePoolTest, LostResource) { + // Limits high enough to not be hit by this test. + size_t bytes_limit = 10 * 1024 * 1024; + size_t count_limit = 100; + resource_pool_->SetResourceUsageLimits(bytes_limit, bytes_limit, count_limit); + + gfx::Size size(100, 100); + ResourceFormat format = RGBA_8888; + bool wait_if_needed = false; + + scoped_ptr<ScopedResource> resource = + resource_pool_->AcquireResource(size, format); + EXPECT_EQ(1u, resource_provider_->num_resources()); + + resource_provider_->LoseResourceForTesting(resource->id()); + resource_pool_->ReleaseResource(resource.Pass(), 0u); + resource_pool_->CheckBusyResources(wait_if_needed); + EXPECT_EQ(0u, resource_provider_->num_resources()); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/resources/resource_provider.cc b/chromium/cc/resources/resource_provider.cc index eb774fe10b3..9f680669c08 100644 --- a/chromium/cc/resources/resource_provider.cc +++ b/chromium/cc/resources/resource_provider.cc @@ -9,15 +9,15 @@ #include "base/containers/hash_tables.h" #include "base/metrics/histogram.h" +#include "base/numerics/safe_math.h" #include "base/stl_util.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/trace_event/trace_event.h" -#include "cc/base/util.h" +#include "cc/base/math_util.h" #include "cc/resources/platform_color.h" #include "cc/resources/returned_resource.h" #include "cc/resources/shared_bitmap_manager.h" -#include "cc/resources/texture_uploader.h" #include "cc/resources/transferable_resource.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -27,7 +27,6 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrContext.h" #include "third_party/skia/include/gpu/GrTextureProvider.h" -#include "ui/gfx/frame_time.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/gpu_memory_buffer.h" @@ -49,6 +48,8 @@ class IdAllocator { ids_(new GLuint[id_allocation_chunk_size]), next_id_index_(id_allocation_chunk_size) { DCHECK(id_allocation_chunk_size_); + DCHECK_LE(id_allocation_chunk_size_, + static_cast<size_t>(std::numeric_limits<int>::max())); } GLES2Interface* gl_; @@ -59,10 +60,6 @@ class IdAllocator { namespace { -// Measured in seconds. -const double kSoftwareUploadTickRate = 0.000250; -const double kTextureUploadTickRate = 0.004; - GLenum TextureToStorageFormat(ResourceFormat format) { GLenum storage_format = GL_RGBA8_OES; switch (format) { @@ -119,10 +116,11 @@ GrPixelConfig ToGrPixelConfig(ResourceFormat format) { gfx::GpuMemoryBuffer::Format ToGpuMemoryBufferFormat(ResourceFormat format) { switch (format) { case RGBA_8888: - return gfx::GpuMemoryBuffer::Format::RGBA_8888; + return gfx::GpuMemoryBuffer::RGBA_8888; case BGRA_8888: - return gfx::GpuMemoryBuffer::Format::BGRA_8888; + return gfx::GpuMemoryBuffer::BGRA_8888; case RGBA_4444: + return gfx::GpuMemoryBuffer::RGBA_4444; case ALPHA_8: case LUMINANCE_8: case RGB_565: @@ -131,7 +129,7 @@ gfx::GpuMemoryBuffer::Format ToGpuMemoryBufferFormat(ResourceFormat format) { break; } NOTREACHED(); - return gfx::GpuMemoryBuffer::Format::RGBA_8888; + return gfx::GpuMemoryBuffer::RGBA_8888; } class ScopedSetActiveTexture { @@ -161,14 +159,15 @@ class TextureIdAllocator : public IdAllocator { size_t texture_id_allocation_chunk_size) : IdAllocator(gl, texture_id_allocation_chunk_size) {} ~TextureIdAllocator() override { - gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_, - ids_.get() + next_id_index_); + gl_->DeleteTextures( + static_cast<int>(id_allocation_chunk_size_ - next_id_index_), + ids_.get() + next_id_index_); } // Overridden from IdAllocator: GLuint NextId() override { if (next_id_index_ == id_allocation_chunk_size_) { - gl_->GenTextures(id_allocation_chunk_size_, ids_.get()); + gl_->GenTextures(static_cast<int>(id_allocation_chunk_size_), ids_.get()); next_id_index_ = 0; } @@ -184,14 +183,15 @@ class BufferIdAllocator : public IdAllocator { BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size) : IdAllocator(gl, buffer_id_allocation_chunk_size) {} ~BufferIdAllocator() override { - gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_, - ids_.get() + next_id_index_); + gl_->DeleteBuffers( + static_cast<int>(id_allocation_chunk_size_ - next_id_index_), + ids_.get() + next_id_index_); } // Overridden from IdAllocator: GLuint NextId() override { if (next_id_index_ == id_allocation_chunk_size_) { - gl_->GenBuffers(id_allocation_chunk_size_, ids_.get()); + gl_->GenBuffers(static_cast<int>(id_allocation_chunk_size_), ids_.get()); next_id_index_ = 0; } @@ -273,7 +273,6 @@ ResourceProvider::Resource::Resource(GLuint texture_id, allocated(false), read_lock_fences_enabled(false), has_shared_bitmap_id(false), - allow_overlay(false), read_lock_fence(NULL), size(size), origin(origin), @@ -317,7 +316,6 @@ ResourceProvider::Resource::Resource(uint8_t* pixels, allocated(false), read_lock_fences_enabled(false), has_shared_bitmap_id(!!bitmap), - allow_overlay(false), read_lock_fence(NULL), size(size), origin(origin), @@ -362,7 +360,6 @@ ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id, allocated(false), read_lock_fences_enabled(false), has_shared_bitmap_id(true), - allow_overlay(false), read_lock_fence(NULL), size(size), origin(origin), @@ -395,25 +392,15 @@ scoped_ptr<ResourceProvider> ResourceProvider::Create( BlockingTaskRunner* blocking_main_thread_task_runner, int highp_threshold_min, bool use_rgba_4444_texture_format, - size_t id_allocation_chunk_size) { - ContextProvider* context_provider = output_surface->context_provider(); - GLES2Interface* gl = - context_provider ? context_provider->ContextGL() : nullptr; - ResourceType default_resource_type = - gl ? RESOURCE_TYPE_GL_TEXTURE : RESOURCE_TYPE_BITMAP; - + size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers) { scoped_ptr<ResourceProvider> resource_provider(new ResourceProvider( output_surface, shared_bitmap_manager, gpu_memory_buffer_manager, blocking_main_thread_task_runner, highp_threshold_min, - default_resource_type, use_rgba_4444_texture_format, - id_allocation_chunk_size)); - - if (gl) - resource_provider->InitializeGL(); - else - resource_provider->InitializeSoftware(); - - return resource_provider.Pass(); + use_rgba_4444_texture_format, id_allocation_chunk_size, + use_persistent_map_for_gpu_memory_buffers)); + resource_provider->Initialize(); + return resource_provider; } ResourceProvider::~ResourceProvider() { @@ -426,7 +413,6 @@ ResourceProvider::~ResourceProvider() { if (default_resource_type_ != RESOURCE_TYPE_GL_TEXTURE) { // We are not in GL mode, but double check before returning. DCHECK(!gl); - DCHECK(!texture_uploader_); return; } @@ -439,7 +425,6 @@ ResourceProvider::~ResourceProvider() { } #endif // DCHECK_IS_ON() - texture_uploader_ = nullptr; texture_id_allocator_ = nullptr; buffer_id_allocator_ = nullptr; gl->Finish(); @@ -456,16 +441,16 @@ bool ResourceProvider::IsLost(ResourceId id) { return resource->lost; } -bool ResourceProvider::AllowOverlay(ResourceId id) { +void ResourceProvider::LoseResourceForTesting(ResourceId id) { Resource* resource = GetResource(id); - return resource->allow_overlay; + DCHECK(resource); + resource->lost = true; } -ResourceProvider::ResourceId ResourceProvider::CreateResource( - const gfx::Size& size, - GLint wrap_mode, - TextureHint hint, - ResourceFormat format) { +ResourceId ResourceProvider::CreateResource(const gfx::Size& size, + GLint wrap_mode, + TextureHint hint, + ResourceFormat format) { DCHECK(!size.IsEmpty()); switch (default_resource_type_) { case RESOURCE_TYPE_GL_TEXTURE: @@ -484,12 +469,11 @@ ResourceProvider::ResourceId ResourceProvider::CreateResource( return 0; } -ResourceProvider::ResourceId ResourceProvider::CreateManagedResource( - const gfx::Size& size, - GLenum target, - GLint wrap_mode, - TextureHint hint, - ResourceFormat format) { +ResourceId ResourceProvider::CreateManagedResource(const gfx::Size& size, + GLenum target, + GLint wrap_mode, + TextureHint hint, + ResourceFormat format) { DCHECK(!size.IsEmpty()); switch (default_resource_type_) { case RESOURCE_TYPE_GL_TEXTURE: @@ -508,13 +492,12 @@ ResourceProvider::ResourceId ResourceProvider::CreateManagedResource( return 0; } -ResourceProvider::ResourceId ResourceProvider::CreateGLTexture( - const gfx::Size& size, - GLenum target, - GLenum texture_pool, - GLint wrap_mode, - TextureHint hint, - ResourceFormat format) { +ResourceId ResourceProvider::CreateGLTexture(const gfx::Size& size, + GLenum target, + GLenum texture_pool, + GLint wrap_mode, + TextureHint hint, + ResourceFormat format) { DCHECK_LE(size.width(), max_texture_size_); DCHECK_LE(size.height(), max_texture_size_); DCHECK(thread_checker_.CalledOnValidThread()); @@ -527,8 +510,8 @@ ResourceProvider::ResourceId ResourceProvider::CreateGLTexture( return id; } -ResourceProvider::ResourceId ResourceProvider::CreateBitmap( - const gfx::Size& size, GLint wrap_mode) { +ResourceId ResourceProvider::CreateBitmap(const gfx::Size& size, + GLint wrap_mode) { DCHECK(thread_checker_.CalledOnValidThread()); scoped_ptr<SharedBitmap> bitmap = @@ -544,7 +527,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateBitmap( return id; } -ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface( +ResourceId ResourceProvider::CreateResourceFromIOSurface( const gfx::Size& size, unsigned io_surface_id) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -564,9 +547,10 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface( return id; } -ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( +ResourceId ResourceProvider::CreateResourceFromTextureMailbox( const TextureMailbox& mailbox, - scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) { + scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl, + bool read_lock_fences_enabled) { DCHECK(thread_checker_.CalledOnValidThread()); // Just store the information. Mailbox will be consumed in LockForRead(). ResourceId id = next_id_++; @@ -583,7 +567,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( uint8_t* pixels = shared_bitmap->pixels(); DCHECK(pixels); resource = InsertResource( - id, Resource(pixels, shared_bitmap, mailbox.shared_memory_size(), + id, Resource(pixels, shared_bitmap, mailbox.size_in_pixels(), Resource::EXTERNAL, GL_LINEAR, GL_CLAMP_TO_EDGE)); } resource->allocated = true; @@ -591,10 +575,17 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( resource->release_callback_impl = base::Bind(&SingleReleaseCallbackImpl::Run, base::Owned(release_callback_impl.release())); - resource->allow_overlay = mailbox.allow_overlay(); + resource->read_lock_fences_enabled = read_lock_fences_enabled; return id; } +ResourceId ResourceProvider::CreateResourceFromTextureMailbox( + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) { + return CreateResourceFromTextureMailbox(mailbox, release_callback_impl.Pass(), + false); +} + void ResourceProvider::DeleteResource(ResourceId id) { DCHECK(thread_checker_.CalledOnValidThread()); ResourceMap::iterator it = resources_.find(id); @@ -604,7 +595,8 @@ void ResourceProvider::DeleteResource(ResourceId id) { DCHECK_EQ(resource->imported_count, 0); DCHECK(resource->pending_set_pixels || !resource->locked_for_write); - if (resource->exported_count > 0 || resource->lock_for_read_count > 0) { + if (resource->exported_count > 0 || resource->lock_for_read_count > 0 || + !ReadLockFenceHasPassed(resource)) { resource->marked_for_deletion = true; return; } else { @@ -698,54 +690,6 @@ ResourceProvider::ResourceType ResourceProvider::GetResourceType( return GetResource(id)->type; } -void ResourceProvider::SetPixels(ResourceId id, - const uint8_t* image, - const gfx::Rect& image_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset) { - Resource* resource = GetResource(id); - DCHECK(!resource->locked_for_write); - DCHECK(!resource->lock_for_read_count); - DCHECK(resource->origin == Resource::INTERNAL); - DCHECK_EQ(resource->exported_count, 0); - DCHECK(ReadLockFenceHasPassed(resource)); - LazyAllocate(resource); - - if (resource->type == RESOURCE_TYPE_GL_TEXTURE) { - DCHECK(resource->gl_id); - DCHECK(!resource->pending_set_pixels); - DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - DCHECK(texture_uploader_.get()); - gl->BindTexture(GL_TEXTURE_2D, resource->gl_id); - texture_uploader_->Upload(image, - image_rect, - source_rect, - dest_offset, - resource->format, - resource->size); - } else { - DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type); - DCHECK(resource->allocated); - DCHECK_EQ(RGBA_8888, resource->format); - DCHECK(source_rect.x() >= image_rect.x()); - DCHECK(source_rect.y() >= image_rect.y()); - DCHECK(source_rect.right() <= image_rect.right()); - DCHECK(source_rect.bottom() <= image_rect.bottom()); - SkImageInfo source_info = - SkImageInfo::MakeN32Premul(source_rect.width(), source_rect.height()); - size_t image_row_bytes = image_rect.width() * 4; - gfx::Vector2d source_offset = source_rect.origin() - image_rect.origin(); - image += source_offset.y() * image_row_bytes + source_offset.x() * 4; - - ScopedWriteLockSoftware lock(this, id); - SkCanvas dest(lock.sk_bitmap()); - dest.writePixels(source_info, image, image_row_bytes, dest_offset.x(), - dest_offset.y()); - } -} - void ResourceProvider::CopyToResource(ResourceId id, const uint8_t* image, const gfx::Size& image_size) { @@ -777,15 +721,16 @@ void ResourceProvider::CopyToResource(ResourceId id, DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); GLES2Interface* gl = ContextGL(); DCHECK(gl); - DCHECK(texture_uploader_.get()); gl->BindTexture(GL_TEXTURE_2D, resource->gl_id); if (resource->format == ETC1) { - size_t num_bytes = static_cast<size_t>(image_size.width()) * - image_size.height() * BitsPerPixel(ETC1) / 8; + base::CheckedNumeric<int> num_bytes = BitsPerPixel(ETC1); + num_bytes *= image_size.width(); + num_bytes *= image_size.height(); + num_bytes /= 8; gl->CompressedTexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(ETC1), image_size.width(), image_size.height(), 0, - num_bytes, image); + num_bytes.ValueOrDie(), image); } else { gl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_size.width(), image_size.height(), GLDataFormat(resource->format), @@ -794,65 +739,6 @@ void ResourceProvider::CopyToResource(ResourceId id, } } -size_t ResourceProvider::NumBlockingUploads() { - if (!texture_uploader_) - return 0; - - return texture_uploader_->NumBlockingUploads(); -} - -void ResourceProvider::MarkPendingUploadsAsNonBlocking() { - if (!texture_uploader_) - return; - - texture_uploader_->MarkPendingUploadsAsNonBlocking(); -} - -size_t ResourceProvider::EstimatedUploadsPerTick() { - if (!texture_uploader_) - return 1u; - - double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond(); - size_t textures_per_tick = floor( - kTextureUploadTickRate * textures_per_second); - return textures_per_tick ? textures_per_tick : 1u; -} - -void ResourceProvider::FlushUploads() { - if (!texture_uploader_) - return; - - texture_uploader_->Flush(); -} - -void ResourceProvider::ReleaseCachedData() { - if (!texture_uploader_) - return; - - texture_uploader_->ReleaseCachedQueries(); -} - -base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime( - size_t uploads_per_tick) { - if (lost_output_surface_) - return base::TimeTicks(); - - // Software resource uploads happen on impl thread, so don't bother batching - // them up and trying to wait for them to complete. - if (!texture_uploader_) { - return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds( - base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate); - } - - base::TimeDelta upload_one_texture_time = - base::TimeDelta::FromMicroseconds( - base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) / - uploads_per_tick; - - size_t total_uploads = NumBlockingUploads() + uploads_per_tick; - return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads; -} - ResourceProvider::Resource* ResourceProvider::InsertResource( ResourceId id, const Resource& resource) { @@ -961,9 +847,15 @@ void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) { resource->locked_for_write = false; } +void ResourceProvider::EnableReadLockFencesForTesting(ResourceId id) { + Resource* resource = GetResource(id); + DCHECK(resource); + resource->read_lock_fences_enabled = true; +} + ResourceProvider::ScopedReadLockGL::ScopedReadLockGL( ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id) + ResourceId resource_id) : resource_provider_(resource_provider), resource_id_(resource_id), resource_(resource_provider->LockForRead(resource_id)) { @@ -976,7 +868,7 @@ ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() { ResourceProvider::ScopedSamplerGL::ScopedSamplerGL( ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, GLenum filter) : ScopedReadLockGL(resource_provider, resource_id), unit_(GL_TEXTURE0), @@ -985,7 +877,7 @@ ResourceProvider::ScopedSamplerGL::ScopedSamplerGL( ResourceProvider::ScopedSamplerGL::ScopedSamplerGL( ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, GLenum unit, GLenum filter) : ScopedReadLockGL(resource_provider, resource_id), @@ -998,7 +890,7 @@ ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() { ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL( ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id) + ResourceId resource_id) : resource_provider_(resource_provider), resource_(resource_provider->LockForWrite(resource_id)) { resource_provider_->LazyAllocate(resource_); @@ -1020,9 +912,8 @@ void ResourceProvider::PopulateSkBitmapWithResource( ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware( ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id) - : resource_provider_(resource_provider), - resource_id_(resource_id) { + ResourceId resource_id) + : resource_provider_(resource_provider), resource_id_(resource_id) { const Resource* resource = resource_provider->LockForRead(resource_id); wrap_mode_ = resource->wrap_mode; ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource); @@ -1034,7 +925,7 @@ ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() { ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware( ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id) + ResourceId resource_id) : resource_provider_(resource_provider), resource_(resource_provider->LockForWrite(resource_id)) { ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_); @@ -1048,7 +939,7 @@ ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id) + ResourceId resource_id) : resource_provider_(resource_provider), resource_(resource_provider->LockForWrite(resource_id)), gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_), @@ -1066,6 +957,8 @@ ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: if (!gpu_memory_buffer_) return; + resource_provider_->LazyCreate(resource_); + if (!resource_->image_id) { GLES2Interface* gl = resource_provider_->ContextGL(); DCHECK(gl); @@ -1094,19 +987,22 @@ ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: gfx::GpuMemoryBuffer* ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() { - if (!gpu_memory_buffer_) { - scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer = - gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( - size_, ToGpuMemoryBufferFormat(format_), gfx::GpuMemoryBuffer::MAP); - gpu_memory_buffer_ = gpu_memory_buffer.release(); - } - + if (gpu_memory_buffer_) + return gpu_memory_buffer_; + gfx::GpuMemoryBuffer::Usage usage = + resource_provider_->use_persistent_map_for_gpu_memory_buffers() + ? gfx::GpuMemoryBuffer::PERSISTENT_MAP + : gfx::GpuMemoryBuffer::MAP; + scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer = + gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( + size_, ToGpuMemoryBufferFormat(format_), usage); + gpu_memory_buffer_ = gpu_memory_buffer.release(); return gpu_memory_buffer_; } ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr( ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id) + ResourceId resource_id) : resource_provider_(resource_provider), resource_(resource_provider->LockForWrite(resource_id)) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -1137,24 +1033,17 @@ void ResourceProvider::ScopedWriteLockGr::InitSkSurface( bool use_worker_context = true; class GrContext* gr_context = resource_provider_->GrContext(use_worker_context); - skia::RefPtr<GrTexture> gr_texture = - skia::AdoptRef(gr_context->textureProvider()->wrapBackendTexture(desc)); - if (gr_texture) { - uint32_t flags = use_distance_field_text - ? SkSurfaceProps::kUseDistanceFieldFonts_Flag - : 0; - // Use unknown pixel geometry to disable LCD text. - SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry); - if (can_use_lcd_text) { - // LegacyFontHost will get LCD text and skia figures out what type to use. - surface_props = - SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType); - } - sk_surface_ = skia::AdoptRef(SkSurface::NewRenderTargetDirect( - gr_texture->asRenderTarget(), &surface_props)); - return; + uint32_t flags = + use_distance_field_text ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0; + // Use unknown pixel geometry to disable LCD text. + SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry); + if (can_use_lcd_text) { + // LegacyFontHost will get LCD text and skia figures out what type to use. + surface_props = + SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType); } - sk_surface_.clear(); + sk_surface_ = skia::AdoptRef( + SkSurface::NewWrappedRenderTarget(gr_context, desc, &surface_props)); } void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() { @@ -1196,9 +1085,9 @@ ResourceProvider::ResourceProvider( gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, BlockingTaskRunner* blocking_main_thread_task_runner, int highp_threshold_min, - ResourceType default_resource_type, bool use_rgba_4444_texture_format, - size_t id_allocation_chunk_size) + size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers) : output_surface_(output_surface), shared_bitmap_manager_(shared_bitmap_manager), gpu_memory_buffer_manager_(gpu_memory_buffer_manager), @@ -1207,7 +1096,7 @@ ResourceProvider::ResourceProvider( highp_threshold_min_(highp_threshold_min), next_id_(1), next_child_(1), - default_resource_type_(default_resource_type), + default_resource_type_(RESOURCE_TYPE_BITMAP), use_texture_storage_ext_(false), use_texture_format_bgra_(false), use_texture_usage_hint_(false), @@ -1215,32 +1104,35 @@ ResourceProvider::ResourceProvider( yuv_resource_format_(LUMINANCE_8), max_texture_size_(0), best_texture_format_(RGBA_8888), + best_render_buffer_format_(RGBA_8888), use_rgba_4444_texture_format_(use_rgba_4444_texture_format), id_allocation_chunk_size_(id_allocation_chunk_size), - use_sync_query_(false) { + use_sync_query_(false), + use_persistent_map_for_gpu_memory_buffers_( + use_persistent_map_for_gpu_memory_buffers) { DCHECK(output_surface_->HasClient()); DCHECK(id_allocation_chunk_size_); } -void ResourceProvider::InitializeSoftware() { +void ResourceProvider::Initialize() { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK_EQ(default_resource_type_, RESOURCE_TYPE_BITMAP); - // Pick an arbitrary limit here similar to what hardware might. - max_texture_size_ = 16 * 1024; - best_texture_format_ = RGBA_8888; -} -void ResourceProvider::InitializeGL() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK_EQ(default_resource_type_, RESOURCE_TYPE_GL_TEXTURE); - DCHECK(!texture_uploader_); + GLES2Interface* gl = ContextGL(); + if (!gl) { + default_resource_type_ = RESOURCE_TYPE_BITMAP; + // Pick an arbitrary limit here similar to what hardware might. + max_texture_size_ = 16 * 1024; + best_texture_format_ = RGBA_8888; + return; + } + DCHECK(!texture_id_allocator_); DCHECK(!buffer_id_allocator_); const ContextProvider::Capabilities& caps = output_surface_->context_provider()->ContextCapabilities(); - bool use_bgra = caps.gpu.texture_format_bgra8888; + default_resource_type_ = RESOURCE_TYPE_GL_TEXTURE; use_texture_storage_ext_ = caps.gpu.texture_storage; use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888; use_texture_usage_hint_ = caps.gpu.texture_usage; @@ -1248,13 +1140,13 @@ void ResourceProvider::InitializeGL() { yuv_resource_format_ = caps.gpu.texture_rg ? RED_8 : LUMINANCE_8; use_sync_query_ = caps.gpu.sync_query; - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - - texture_uploader_ = TextureUploader::Create(gl); max_texture_size_ = 0; // Context expects cleared value. gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_); - best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra); + best_texture_format_ = + PlatformColor::BestTextureFormat(use_texture_format_bgra_); + + best_render_buffer_format_ = + PlatformColor::BestTextureFormat(caps.gpu.render_buffer_format_bgra8888); texture_id_allocator_.reset( new TextureIdAllocator(gl, id_allocation_chunk_size_)); @@ -1386,12 +1278,12 @@ void ResourceProvider::ReceiveFromChild( resource->mailbox = TextureMailbox(it->mailbox_holder.mailbox, it->mailbox_holder.texture_target, it->mailbox_holder.sync_point); + resource->read_lock_fences_enabled = it->read_lock_fences_enabled; } resource->child_id = child; // Don't allocate a texture for a child. resource->allocated = true; resource->imported_count = 1; - resource->allow_overlay = it->allow_overlay; child_info.parent_to_child_map[local_id] = it->id; child_info.child_to_parent_map[it->id] = local_id; } @@ -1442,14 +1334,6 @@ void ResourceProvider::ReceiveReturnsFromParent( if (resource->exported_count) continue; - // Need to wait for the current read lock fence to pass before we can - // recycle this resource. - if (resource->read_lock_fences_enabled) { - if (current_read_lock_fence_.get()) - current_read_lock_fence_->Set(); - resource->read_lock_fence = current_read_lock_fence_; - } - if (returned.sync_point) { DCHECK(!resource->has_shared_bitmap_id); if (resource->origin == Resource::INTERNAL) { @@ -1494,8 +1378,8 @@ void ResourceProvider::TransferResource(GLES2Interface* gl, resource->mailbox_holder.texture_target = source->target; resource->filter = source->filter; resource->size = source->size; + resource->read_lock_fences_enabled = source->read_lock_fences_enabled; resource->is_repeated = (source->wrap_mode == GL_REPEAT); - resource->allow_overlay = source->allow_overlay; if (source->type == RESOURCE_TYPE_BITMAP) { resource->mailbox_holder.mailbox = source->shared_bitmap_id; @@ -1506,6 +1390,7 @@ void ResourceProvider::TransferResource(GLES2Interface* gl, DCHECK(source->origin == Resource::INTERNAL); if (source->image_id) { DCHECK(source->dirty_image); + gl->BindTexture(resource->mailbox_holder.texture_target, source->gl_id); BindImageForSampling(source); } // This is a resource allocated by the compositor, we need to produce it. @@ -1566,13 +1451,21 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild( (resource.type == RESOURCE_TYPE_GL_TEXTURE && lost_output_surface_); if (resource.exported_count > 0 || resource.lock_for_read_count > 0) { if (style != FOR_SHUTDOWN) { - // Defer this until we receive the resource back from the parent or - // the read lock is released. + // Defer this resource deletion. resource.marked_for_deletion = true; continue; } - - // We still have an exported_count, so we'll have to lose it. + // We can't postpone the deletion, so we'll have to lose it. + is_lost = true; + } else if (!ReadLockFenceHasPassed(&resource)) { + // TODO(dcastagna): see if it's possible to use this logic for + // the branch above too, where the resource is locked or still exported. + if (style != FOR_SHUTDOWN && !child_info->marked_for_deletion) { + // Defer this resource deletion. + resource.marked_for_deletion = true; + continue; + } + // We can't postpone the deletion, so we'll have to lose it. is_lost = true; } @@ -1639,11 +1532,11 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) { gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, resource->gl_pixel_buffer_id); unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8; - gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, - resource->size.height() * - RoundUp(bytes_per_pixel * resource->size.width(), 4u), - NULL, - GL_DYNAMIC_DRAW); + gl->BufferData( + GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, + resource->size.height() * + MathUtil::RoundUp(bytes_per_pixel * resource->size.width(), 4u), + NULL, GL_DYNAMIC_DRAW); gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); } @@ -1913,21 +1806,20 @@ void ResourceProvider::LazyAllocate(Resource* resource) { resource->allocated = true; GLES2Interface* gl = ContextGL(); gfx::Size& size = resource->size; - DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); ResourceFormat format = resource->format; - gl->BindTexture(GL_TEXTURE_2D, resource->gl_id); + gl->BindTexture(resource->target, resource->gl_id); if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format, use_texture_format_bgra_) && (resource->hint & TEXTURE_HINT_IMMUTABLE)) { GLenum storage_format = TextureToStorageFormat(format); - gl->TexStorage2DEXT(GL_TEXTURE_2D, 1, storage_format, size.width(), + gl->TexStorage2DEXT(resource->target, 1, storage_format, size.width(), size.height()); } else { // ETC1 does not support preallocation. if (format != ETC1) { - gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), size.width(), - size.height(), 0, GLDataFormat(format), GLDataType(format), - NULL); + gl->TexImage2D(resource->target, 0, GLInternalFormat(format), + size.width(), size.height(), 0, GLDataFormat(format), + GLDataType(format), NULL); } } } @@ -1945,7 +1837,9 @@ void ResourceProvider::BindImageForSampling(Resource* resource) { resource->dirty_image = false; } -void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) { +void ResourceProvider::CopyResource(ResourceId source_id, + ResourceId dest_id, + const gfx::Rect& rect) { TRACE_EVENT0("cc", "ResourceProvider::CopyResource"); Resource* source_resource = GetResource(source_id); @@ -1953,8 +1847,7 @@ void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) { DCHECK(source_resource->origin == Resource::INTERNAL); DCHECK_EQ(source_resource->exported_count, 0); DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, source_resource->type); - DCHECK(source_resource->allocated); - LazyCreate(source_resource); + LazyAllocate(source_resource); Resource* dest_resource = GetResource(dest_id); DCHECK(!dest_resource->locked_for_write); @@ -1967,6 +1860,7 @@ void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) { DCHECK_EQ(source_resource->type, dest_resource->type); DCHECK_EQ(source_resource->format, dest_resource->format); DCHECK(source_resource->size == dest_resource->size); + DCHECK(gfx::Rect(dest_resource->size).Contains(rect)); GLES2Interface* gl = ContextGL(); DCHECK(gl); @@ -1991,7 +1885,9 @@ void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) { DCHECK(!dest_resource->image_id); dest_resource->allocated = true; gl->CopySubTextureCHROMIUM(dest_resource->target, source_resource->gl_id, - dest_resource->gl_id, 0, 0); + dest_resource->gl_id, rect.x(), rect.y(), rect.x(), + rect.y(), rect.width(), rect.height(), + false, false, false); if (source_resource->gl_read_lock_query_id) { // End query and create a read lock fence that will prevent access to // source resource until CopySubTextureCHROMIUM command has completed. diff --git a/chromium/cc/resources/resource_provider.h b/chromium/cc/resources/resource_provider.h index f7baac1e3bb..fbed140aa00 100644 --- a/chromium/cc/resources/resource_provider.h +++ b/chromium/cc/resources/resource_provider.h @@ -18,6 +18,7 @@ #include "base/memory/scoped_ptr.h" #include "base/threading/thread_checker.h" #include "cc/base/cc_export.h" +#include "cc/base/resource_id.h" #include "cc/output/context_provider.h" #include "cc/output/output_surface.h" #include "cc/resources/release_callback_impl.h" @@ -53,7 +54,6 @@ class BlockingTaskRunner; class IdAllocator; class SharedBitmap; class SharedBitmapManager; -class TextureUploader; // This class is not thread-safe and can only be called from the thread it was // created on (in practice, the impl thread). @@ -62,7 +62,6 @@ class CC_EXPORT ResourceProvider { struct Resource; public: - typedef unsigned ResourceId; typedef std::vector<ResourceId> ResourceIdArray; typedef base::hash_set<ResourceId> ResourceIdSet; typedef base::hash_map<ResourceId, ResourceId> ResourceIdMap; @@ -85,7 +84,8 @@ class CC_EXPORT ResourceProvider { BlockingTaskRunner* blocking_main_thread_task_runner, int highp_threshold_min, bool use_rgba_4444_texture_format, - size_t id_allocation_chunk_size); + size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers); virtual ~ResourceProvider(); void DidLoseOutputSurface() { lost_output_surface_ = true; } @@ -95,15 +95,23 @@ class CC_EXPORT ResourceProvider { return use_rgba_4444_texture_format_ ? RGBA_4444 : best_texture_format_; } ResourceFormat best_texture_format() const { return best_texture_format_; } + ResourceFormat best_render_buffer_format() const { + return best_render_buffer_format_; + } ResourceFormat yuv_resource_format() const { return yuv_resource_format_; } bool use_sync_query() const { return use_sync_query_; } + bool use_persistent_map_for_gpu_memory_buffers() const { + return use_persistent_map_for_gpu_memory_buffers_; + } size_t num_resources() const { return resources_.size(); } // Checks whether a resource is in use by a consumer. bool InUseByConsumer(ResourceId id); bool IsLost(ResourceId id); - bool AllowOverlay(ResourceId id); + + void LoseResourceForTesting(ResourceId id); + void EnableReadLockFencesForTesting(ResourceId id); // Producer interface. @@ -142,28 +150,19 @@ class CC_EXPORT ResourceProvider { const TextureMailbox& mailbox, scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl); + ResourceId CreateResourceFromTextureMailbox( + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl, + bool read_lock_fences_enabled); + void DeleteResource(ResourceId id); // Update pixels from image, copying source_rect (in image) to dest_offset (in // the resource). - // NOTE: DEPRECATED. Use CopyToResource() instead. - void SetPixels(ResourceId id, - const uint8_t* image, - const gfx::Rect& image_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset); void CopyToResource(ResourceId id, const uint8_t* image, const gfx::Size& image_size); - // Check upload status. - size_t NumBlockingUploads(); - void MarkPendingUploadsAsNonBlocking(); - size_t EstimatedUploadsPerTick(); - void FlushUploads(); - void ReleaseCachedData(); - base::TimeTicks EstimatedUploadCompletionTime(size_t uploads_per_tick); - // Only flush the command buffer if supported. // Returns true if the shallow flush occurred, false otherwise. bool ShallowFlushIfSupported(); @@ -220,7 +219,7 @@ class CC_EXPORT ResourceProvider { class CC_EXPORT ScopedReadLockGL { public: ScopedReadLockGL(ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id); + ResourceId resource_id); virtual ~ScopedReadLockGL(); unsigned texture_id() const { return resource_->gl_id; } @@ -228,7 +227,7 @@ class CC_EXPORT ResourceProvider { protected: ResourceProvider* resource_provider_; - ResourceProvider::ResourceId resource_id_; + ResourceId resource_id_; private: const ResourceProvider::Resource* resource_; @@ -239,10 +238,10 @@ class CC_EXPORT ResourceProvider { class CC_EXPORT ScopedSamplerGL : public ScopedReadLockGL { public: ScopedSamplerGL(ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, GLenum filter); ScopedSamplerGL(ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, GLenum unit, GLenum filter); ~ScopedSamplerGL() override; @@ -259,7 +258,7 @@ class CC_EXPORT ResourceProvider { class CC_EXPORT ScopedWriteLockGL { public: ScopedWriteLockGL(ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id); + ResourceId resource_id); ~ScopedWriteLockGL(); unsigned texture_id() const { return texture_id_; } @@ -275,7 +274,7 @@ class CC_EXPORT ResourceProvider { class CC_EXPORT ScopedReadLockSoftware { public: ScopedReadLockSoftware(ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id); + ResourceId resource_id); ~ScopedReadLockSoftware(); const SkBitmap* sk_bitmap() const { @@ -288,7 +287,7 @@ class CC_EXPORT ResourceProvider { private: ResourceProvider* resource_provider_; - ResourceProvider::ResourceId resource_id_; + ResourceId resource_id_; SkBitmap sk_bitmap_; GLint wrap_mode_; @@ -298,7 +297,7 @@ class CC_EXPORT ResourceProvider { class CC_EXPORT ScopedWriteLockSoftware { public: ScopedWriteLockSoftware(ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id); + ResourceId resource_id); ~ScopedWriteLockSoftware(); SkBitmap& sk_bitmap() { return sk_bitmap_; } @@ -316,7 +315,7 @@ class CC_EXPORT ResourceProvider { class CC_EXPORT ScopedWriteLockGpuMemoryBuffer { public: ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id); + ResourceId resource_id); ~ScopedWriteLockGpuMemoryBuffer(); gfx::GpuMemoryBuffer* GetGpuMemoryBuffer(); @@ -336,7 +335,7 @@ class CC_EXPORT ResourceProvider { class CC_EXPORT ScopedWriteLockGr { public: ScopedWriteLockGr(ResourceProvider* resource_provider, - ResourceProvider::ResourceId resource_id); + ResourceId resource_id); ~ScopedWriteLockGr(); void InitSkSurface(bool use_distance_field_text, @@ -424,8 +423,10 @@ class CC_EXPORT ResourceProvider { // Indicates if we can currently lock this resource for write. bool CanLockForWrite(ResourceId id); - // Copy pixels from source to destination. - void CopyResource(ResourceId source_id, ResourceId dest_id); + // Copy |rect| pixels from source to destination. + void CopyResource(ResourceId source_id, + ResourceId dest_id, + const gfx::Rect& rect); void WaitSyncPointIfNeeded(ResourceId id); @@ -437,6 +438,17 @@ class CC_EXPORT ResourceProvider { void ValidateResource(ResourceId id) const; + protected: + ResourceProvider(OutputSurface* output_surface, + SharedBitmapManager* shared_bitmap_manager, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + BlockingTaskRunner* blocking_main_thread_task_runner, + int highp_threshold_min, + bool use_rgba_4444_texture_format, + size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers); + void Initialize(); + private: struct Resource { enum Origin { INTERNAL, EXTERNAL, DELEGATED }; @@ -486,7 +498,6 @@ class CC_EXPORT ResourceProvider { bool allocated : 1; bool read_lock_fences_enabled : 1; bool has_shared_bitmap_id : 1; - bool allow_overlay : 1; scoped_refptr<Fence> read_lock_fence; gfx::Size size; Origin origin; @@ -524,18 +535,6 @@ class CC_EXPORT ResourceProvider { resource->read_lock_fence->HasPassed(); } - ResourceProvider(OutputSurface* output_surface, - SharedBitmapManager* shared_bitmap_manager, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - BlockingTaskRunner* blocking_main_thread_task_runner, - int highp_threshold_min, - ResourceType default_resource_type, - bool use_rgba_4444_texture_format, - size_t id_allocation_chunk_size); - - void InitializeSoftware(); - void InitializeGL(); - Resource* InsertResource(ResourceId id, const Resource& resource); Resource* GetResource(ResourceId id); const Resource* LockForRead(ResourceId id); @@ -582,15 +581,15 @@ class CC_EXPORT ResourceProvider { int next_child_; ChildMap children_; - const ResourceType default_resource_type_; + ResourceType default_resource_type_; bool use_texture_storage_ext_; bool use_texture_format_bgra_; bool use_texture_usage_hint_; bool use_compressed_texture_etc1_; ResourceFormat yuv_resource_format_; - scoped_ptr<TextureUploader> texture_uploader_; int max_texture_size_; ResourceFormat best_texture_format_; + ResourceFormat best_render_buffer_format_; base::ThreadChecker thread_checker_; @@ -602,6 +601,7 @@ class CC_EXPORT ResourceProvider { scoped_ptr<IdAllocator> buffer_id_allocator_; bool use_sync_query_; + bool use_persistent_map_for_gpu_memory_buffers_; // Fence used for CopyResource if CHROMIUM_sync_query is not supported. scoped_refptr<SynchronousFence> synchronous_fence_; @@ -610,7 +610,7 @@ class CC_EXPORT ResourceProvider { // TODO(epenner): Move these format conversions to resource_format.h // once that builds on mac (npapi.h currently #includes OpenGL.h). -inline unsigned BitsPerPixel(ResourceFormat format) { +inline int BitsPerPixel(ResourceFormat format) { switch (format) { case BGRA_8888: case RGBA_8888: diff --git a/chromium/cc/resources/resource_provider_unittest.cc b/chromium/cc/resources/resource_provider_unittest.cc index 3ca1ab41dd7..136855847db 100644 --- a/chromium/cc/resources/resource_provider_unittest.cc +++ b/chromium/cc/resources/resource_provider_unittest.cc @@ -350,7 +350,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { void GetResourcePixels(ResourceProvider* resource_provider, ResourceProviderContext* context, - ResourceProvider::ResourceId id, + ResourceId id, const gfx::Size& size, ResourceFormat format, uint8_t* pixels) { @@ -418,22 +418,14 @@ class ResourceProviderTest shared_bitmap_manager_.reset(new TestSharedBitmapManager); gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager); - resource_provider_ = - ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - main_thread_task_runner_.get(), - 0, - false, - 1); - child_resource_provider_ = - ResourceProvider::Create(child_output_surface_.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - main_thread_task_runner_.get(), - 0, - false, - 1); + resource_provider_ = ResourceProvider::Create( + output_surface_.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, + false, 1, false); + child_resource_provider_ = ResourceProvider::Create( + child_output_surface_.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, + false, 1, false); } ResourceProviderTest() : ResourceProviderTest(true) {} @@ -449,7 +441,7 @@ class ResourceProviderTest } static void SetResourceFilter(ResourceProvider* resource_provider, - ResourceProvider::ResourceId id, + ResourceId id, GLenum filter) { ResourceProvider::ScopedSamplerGL sampler( resource_provider, id, GL_TEXTURE_2D, filter); @@ -457,10 +449,10 @@ class ResourceProviderTest ResourceProviderContext* context() { return context3d_; } - ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point, - bool* lost_resource, - bool* release_called, - uint32* sync_point) { + ResourceId CreateChildMailbox(uint32* release_sync_point, + bool* lost_resource, + bool* release_called, + uint32* sync_point) { if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { unsigned texture = child_context_->createTexture(); gpu::Mailbox gpu_mailbox; @@ -518,7 +510,7 @@ void CheckCreateResource(ResourceProvider::ResourceType expected_default_type, size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id = resource_provider->CreateResource( + ResourceId id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources())); if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) @@ -543,80 +535,13 @@ TEST_P(ResourceProviderTest, Basic) { CheckCreateResource(GetParam(), resource_provider_.get(), context()); } -TEST_P(ResourceProviderTest, Upload) { - gfx::Size size(2, 2); - ResourceFormat format = RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(16U, pixel_size); - - ResourceProvider::ResourceId id = resource_provider_->CreateResource( - size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); - - uint8_t image[16] = { 0 }; - gfx::Rect image_rect(size); - resource_provider_->SetPixels( - id, image, image_rect, image_rect, gfx::Vector2d()); - - for (uint8_t i = 0; i < pixel_size; ++i) - image[i] = i; - - uint8_t result[16] = { 0 }; - { - gfx::Rect source_rect(0, 0, 1, 1); - gfx::Vector2d dest_offset(0, 0); - resource_provider_->SetPixels( - id, image, image_rect, source_rect, dest_offset); - - uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - GetResourcePixels( - resource_provider_.get(), context(), id, size, format, result); - EXPECT_EQ(0, memcmp(expected, result, pixel_size)); - } - { - gfx::Rect source_rect(0, 0, 1, 1); - gfx::Vector2d dest_offset(1, 1); - resource_provider_->SetPixels( - id, image, image_rect, source_rect, dest_offset); - - uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 }; - GetResourcePixels( - resource_provider_.get(), context(), id, size, format, result); - EXPECT_EQ(0, memcmp(expected, result, pixel_size)); - } - { - gfx::Rect source_rect(1, 0, 1, 1); - gfx::Vector2d dest_offset(0, 1); - resource_provider_->SetPixels( - id, image, image_rect, source_rect, dest_offset); - - uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 }; - GetResourcePixels( - resource_provider_.get(), context(), id, size, format, result); - EXPECT_EQ(0, memcmp(expected, result, pixel_size)); - } - { - gfx::Rect offset_image_rect(gfx::Point(100, 100), size); - gfx::Rect source_rect(100, 100, 1, 1); - gfx::Vector2d dest_offset(1, 0); - resource_provider_->SetPixels( - id, image, offset_image_rect, source_rect, dest_offset); - - uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 }; - GetResourcePixels( - resource_provider_.get(), context(), id, size, format, result); - EXPECT_EQ(0, memcmp(expected, result, pixel_size)); - } - - resource_provider_->DeleteResource(id); -} - TEST_P(ResourceProviderTest, SimpleUpload) { gfx::Size size(2, 2); ResourceFormat format = RGBA_8888; size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(16U, pixel_size); - ResourceProvider::ResourceId id = resource_provider_->CreateResource( + ResourceId id = resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t image[16] = {0}; @@ -650,17 +575,17 @@ TEST_P(ResourceProviderTest, TransferGLResources) { size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + ResourceId id1 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data1[4] = { 1, 2, 3, 4 }; child_resource_provider_->CopyToResource(id1, data1, size); - ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( + ResourceId id2 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data2[4] = { 5, 5, 5, 5 }; child_resource_provider_->CopyToResource(id2, data2, size); - ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource( + ResourceId id3 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); { ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( @@ -675,11 +600,10 @@ TEST_P(ResourceProviderTest, TransferGLResources) { child_context_->produceTextureDirectCHROMIUM( external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name); const GLuint external_sync_point = child_context_->insertSyncPoint(); - ResourceProvider::ResourceId id4 = - child_resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox( - external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point), - SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback))); + ResourceId id4 = child_resource_provider_->CreateResourceFromTextureMailbox( + TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES, + external_sync_point), + SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback))); ReturnedResourceArray returned_to_child; int child_id = @@ -737,10 +661,10 @@ TEST_P(ResourceProviderTest, TransferGLResources) { EXPECT_EQ(4u, resource_provider_->num_resources()); ResourceProvider::ResourceIdMap resource_map = resource_provider_->GetChildToParentMap(child_id); - ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; - ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; - ResourceProvider::ResourceId mapped_id3 = resource_map[id3]; - ResourceProvider::ResourceId mapped_id4 = resource_map[id4]; + ResourceId mapped_id1 = resource_map[id1]; + ResourceId mapped_id2 = resource_map[id2]; + ResourceId mapped_id3 = resource_map[id3]; + ResourceId mapped_id4 = resource_map[id4]; EXPECT_NE(0u, mapped_id1); EXPECT_NE(0u, mapped_id2); EXPECT_NE(0u, mapped_id3); @@ -909,12 +833,12 @@ TEST_P(ResourceProviderTestNoSyncPoint, TransferGLResources) { size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + ResourceId id1 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data1[4] = {1, 2, 3, 4}; child_resource_provider_->CopyToResource(id1, data1, size); - ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( + ResourceId id2 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); { // Ensure locking the memory buffer doesn't create an unnecessary sync @@ -932,11 +856,10 @@ TEST_P(ResourceProviderTestNoSyncPoint, TransferGLResources) { child_context_->produceTextureDirectCHROMIUM( external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name); const GLuint external_sync_point = child_context_->insertSyncPoint(); - ResourceProvider::ResourceId id3 = - child_resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES, - external_sync_point), - SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback))); + ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox( + TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES, + external_sync_point), + SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback))); ReturnedResourceArray returned_to_child; int child_id = @@ -976,7 +899,7 @@ TEST_P(ResourceProviderTestNoSyncPoint, TransferGLResources) { resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); ASSERT_EQ(3u, returned_to_child.size()); - std::map<ResourceProvider::ResourceId, unsigned int> returned_sync_points; + std::map<ResourceId, unsigned int> returned_sync_points; for (const auto& returned : returned_to_child) returned_sync_points[returned.id] = returned.sync_point; @@ -1010,7 +933,7 @@ TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) { gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; - ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + ResourceId id1 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data1[4] = {1, 2, 3, 4}; child_resource_provider_->CopyToResource(id1, data1, size); @@ -1055,33 +978,94 @@ TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) { resource_provider_->DestroyChild(child_id); } -TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) { - // Overlays only supported on the GL path. +class TestFence : public ResourceProvider::Fence { + public: + TestFence() {} + + void Set() override {} + bool HasPassed() override { return passed; } + void Wait() override {} + + bool passed = false; + + private: + ~TestFence() override {} +}; + +TEST_P(ResourceProviderTest, ReadLockFenceStopsReturnToChildOrDelete) { if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) return; + gfx::Size size(1, 1); + ResourceFormat format = RGBA_8888; - uint32 sync_point = 0; - TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); - mailbox.set_allow_overlay(true); - scoped_ptr<SingleReleaseCallbackImpl> release_callback = - SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); - ResourceProvider::ResourceId id1 = - child_resource_provider_->CreateResourceFromTextureMailbox( - mailbox, release_callback.Pass()); + ResourceId id1 = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + uint8_t data1[4] = {1, 2, 3, 4}; + child_resource_provider_->CopyToResource(id1, data1, size); + child_resource_provider_->EnableReadLockFencesForTesting(id1); + ReturnedResourceArray returned_to_child; + int child_id = + resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); - mailbox2.set_allow_overlay(false); - scoped_ptr<SingleReleaseCallbackImpl> release_callback2 = - SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); - ResourceProvider::ResourceId id2 = - child_resource_provider_->CreateResourceFromTextureMailbox( - mailbox2, release_callback2.Pass()); + // Transfer some resources to the parent. + ResourceProvider::ResourceIdArray resource_ids_to_transfer; + resource_ids_to_transfer.push_back(id1); + TransferableResourceArray list; + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); + ASSERT_EQ(1u, list.size()); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); + EXPECT_TRUE(list[0].read_lock_fences_enabled); + + resource_provider_->ReceiveFromChild(child_id, list); + + scoped_refptr<TestFence> fence(new TestFence); + resource_provider_->SetReadLockFence(fence.get()); + { + unsigned parent_id = list.front().id; + resource_provider_->WaitSyncPointIfNeeded(parent_id); + ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), + parent_id); + } + resource_provider_->DeclareUsedResourcesFromChild( + child_id, ResourceProvider::ResourceIdSet()); + EXPECT_EQ(0u, returned_to_child.size()); + + resource_provider_->DeclareUsedResourcesFromChild( + child_id, ResourceProvider::ResourceIdSet()); + EXPECT_EQ(0u, returned_to_child.size()); + fence->passed = true; + + resource_provider_->DeclareUsedResourcesFromChild( + child_id, ResourceProvider::ResourceIdSet()); + EXPECT_EQ(1u, returned_to_child.size()); + + child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); + child_resource_provider_->DeleteResource(id1); + EXPECT_EQ(0u, child_resource_provider_->num_resources()); +} + +TEST_P(ResourceProviderTest, ReadLockFenceDestroyChild) { + if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) + return; + gfx::Size size(1, 1); + ResourceFormat format = RGBA_8888; + + ResourceId id1 = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + uint8_t data[4] = {1, 2, 3, 4}; + child_resource_provider_->CopyToResource(id1, data, size); + child_resource_provider_->EnableReadLockFencesForTesting(id1); + + ResourceId id2 = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + child_resource_provider_->CopyToResource(id2, data, size); ReturnedResourceArray returned_to_child; int child_id = resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - // Transfer some resources to the parent. + // Transfer resources to the parent. ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); @@ -1089,21 +1073,93 @@ TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) { child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); ASSERT_EQ(2u, list.size()); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); + resource_provider_->ReceiveFromChild(child_id, list); - EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id)); - EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id)); - resource_provider_->DeclareUsedResourcesFromChild( - child_id, ResourceProvider::ResourceIdSet()); + scoped_refptr<TestFence> fence(new TestFence); + resource_provider_->SetReadLockFence(fence.get()); + { + for (size_t i = 0; i < list.size(); i++) { + unsigned parent_id = list[i].id; + resource_provider_->WaitSyncPointIfNeeded(parent_id); + ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), + parent_id); + } + } + EXPECT_EQ(0u, returned_to_child.size()); + + EXPECT_EQ(2u, resource_provider_->num_resources()); + resource_provider_->DestroyChild(child_id); + + EXPECT_EQ(0u, resource_provider_->num_resources()); EXPECT_EQ(2u, returned_to_child.size()); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); + // id1 should be lost and id2 should not. + EXPECT_EQ(returned_to_child[0].lost, returned_to_child[0].id == id1); + EXPECT_EQ(returned_to_child[1].lost, returned_to_child[1].id == id1); + + child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); child_resource_provider_->DeleteResource(id1); child_resource_provider_->DeleteResource(id2); EXPECT_EQ(0u, child_resource_provider_->num_resources()); +} - resource_provider_->DestroyChild(child_id); +TEST_P(ResourceProviderTest, ReadLockFenceContextLost) { + if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) + return; + gfx::Size size(1, 1); + ResourceFormat format = RGBA_8888; + + ResourceId id1 = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + uint8_t data[4] = {1, 2, 3, 4}; + child_resource_provider_->CopyToResource(id1, data, size); + child_resource_provider_->EnableReadLockFencesForTesting(id1); + + ResourceId id2 = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + child_resource_provider_->CopyToResource(id2, data, size); + + ReturnedResourceArray returned_to_child; + int child_id = + resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); + + // Transfer resources to the parent. + ResourceProvider::ResourceIdArray resource_ids_to_transfer; + resource_ids_to_transfer.push_back(id1); + resource_ids_to_transfer.push_back(id2); + TransferableResourceArray list; + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); + ASSERT_EQ(2u, list.size()); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); + + resource_provider_->ReceiveFromChild(child_id, list); + + scoped_refptr<TestFence> fence(new TestFence); + resource_provider_->SetReadLockFence(fence.get()); + { + for (size_t i = 0; i < list.size(); i++) { + unsigned parent_id = list[i].id; + resource_provider_->WaitSyncPointIfNeeded(parent_id); + ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), + parent_id); + } + } + EXPECT_EQ(0u, returned_to_child.size()); + + EXPECT_EQ(2u, resource_provider_->num_resources()); + resource_provider_->DidLoseOutputSurface(); + resource_provider_ = nullptr; + + EXPECT_EQ(2u, returned_to_child.size()); + + EXPECT_TRUE(returned_to_child[0].lost); + EXPECT_TRUE(returned_to_child[1].lost); } TEST_P(ResourceProviderTest, TransferSoftwareResources) { @@ -1115,12 +1171,12 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) { size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + ResourceId id1 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data1[4] = { 1, 2, 3, 4 }; child_resource_provider_->CopyToResource(id1, data1, size); - ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( + ResourceId id2 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data2[4] = { 5, 5, 5, 5 }; child_resource_provider_->CopyToResource(id2, data2, size); @@ -1128,11 +1184,10 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) { scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap( shared_bitmap_manager_.get(), gfx::Size(1, 1), 0)); SharedBitmap* shared_bitmap_ptr = shared_bitmap.get(); - ResourceProvider::ResourceId id3 = - child_resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)), - SingleReleaseCallbackImpl::Create(base::Bind( - &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap)))); + ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox( + TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)), + SingleReleaseCallbackImpl::Create(base::Bind( + &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap)))); ReturnedResourceArray returned_to_child; int child_id = @@ -1165,9 +1220,9 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) { EXPECT_EQ(3u, resource_provider_->num_resources()); ResourceProvider::ResourceIdMap resource_map = resource_provider_->GetChildToParentMap(child_id); - ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; - ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; - ResourceProvider::ResourceId mapped_id3 = resource_map[id3]; + ResourceId mapped_id1 = resource_map[id1]; + ResourceId mapped_id2 = resource_map[id2]; + ResourceId mapped_id3 = resource_map[id3]; EXPECT_NE(0u, mapped_id1); EXPECT_NE(0u, mapped_id2); EXPECT_NE(0u, mapped_id3); @@ -1216,11 +1271,11 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) { EXPECT_EQ(0u, returned_to_child[0].sync_point); EXPECT_EQ(0u, returned_to_child[1].sync_point); EXPECT_EQ(0u, returned_to_child[2].sync_point); - std::set<ResourceProvider::ResourceId> expected_ids; + std::set<ResourceId> expected_ids; expected_ids.insert(id1); expected_ids.insert(id2); expected_ids.insert(id3); - std::set<ResourceProvider::ResourceId> returned_ids; + std::set<ResourceId> returned_ids; for (unsigned i = 0; i < 3; i++) returned_ids.insert(returned_to_child[i].id); EXPECT_EQ(expected_ids, returned_ids); @@ -1285,11 +1340,11 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) { EXPECT_EQ(0u, returned_to_child[0].sync_point); EXPECT_EQ(0u, returned_to_child[1].sync_point); EXPECT_EQ(0u, returned_to_child[2].sync_point); - std::set<ResourceProvider::ResourceId> expected_ids; + std::set<ResourceId> expected_ids; expected_ids.insert(id1); expected_ids.insert(id2); expected_ids.insert(id3); - std::set<ResourceProvider::ResourceId> returned_ids; + std::set<ResourceId> returned_ids; for (unsigned i = 0; i < 3; i++) returned_ids.insert(returned_to_child[i].id); EXPECT_EQ(expected_ids, returned_ids); @@ -1310,21 +1365,16 @@ TEST_P(ResourceProviderTest, TransferGLToSoftware) { FakeOutputSurface::Create3d(child_context_owned.Pass())); CHECK(child_output_surface->BindToClient(&child_output_surface_client)); - scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create( + child_output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource( + ResourceId id1 = child_resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data1[4] = { 1, 2, 3, 4 }; child_resource_provider->CopyToResource(id1, data1, size); @@ -1351,7 +1401,7 @@ TEST_P(ResourceProviderTest, TransferGLToSoftware) { EXPECT_EQ(returned_to_child[0].id, id1); ResourceProvider::ResourceIdMap resource_map = resource_provider_->GetChildToParentMap(child_id); - ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; + ResourceId mapped_id1 = resource_map[id1]; EXPECT_EQ(0u, mapped_id1); resource_provider_->DestroyChild(child_id); @@ -1370,7 +1420,7 @@ TEST_P(ResourceProviderTest, TransferInvalidSoftware) { size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + ResourceId id1 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data1[4] = { 1, 2, 3, 4 }; child_resource_provider_->CopyToResource(id1, data1, size); @@ -1396,7 +1446,7 @@ TEST_P(ResourceProviderTest, TransferInvalidSoftware) { ResourceProvider::ResourceIdMap resource_map = resource_provider_->GetChildToParentMap(child_id); - ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; + ResourceId mapped_id1 = resource_map[id1]; EXPECT_NE(0u, mapped_id1); { ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(), @@ -1417,12 +1467,12 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) { size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + ResourceId id1 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data1[4] = { 1, 2, 3, 4 }; child_resource_provider_->CopyToResource(id1, data1, size); - ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( + ResourceId id2 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data2[4] = {5, 5, 5, 5}; child_resource_provider_->CopyToResource(id2, data2, size); @@ -1456,8 +1506,8 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) { EXPECT_EQ(2u, resource_provider_->num_resources()); ResourceProvider::ResourceIdMap resource_map = resource_provider_->GetChildToParentMap(child_id); - ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; - ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; + ResourceId mapped_id1 = resource_map[id1]; + ResourceId mapped_id2 = resource_map[id2]; EXPECT_NE(0u, mapped_id1); EXPECT_NE(0u, mapped_id2); EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); @@ -1513,12 +1563,12 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + ResourceId id1 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data1[4] = {1, 2, 3, 4}; child_resource_provider_->CopyToResource(id1, data1, size); - ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( + ResourceId id2 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data2[4] = {5, 5, 5, 5}; child_resource_provider_->CopyToResource(id2, data2, size); @@ -1552,8 +1602,8 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { EXPECT_EQ(2u, resource_provider_->num_resources()); ResourceProvider::ResourceIdMap resource_map = resource_provider_->GetChildToParentMap(child_id); - ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; - ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; + ResourceId mapped_id1 = resource_map[id1]; + ResourceId mapped_id2 = resource_map[id2]; EXPECT_NE(0u, mapped_id1); EXPECT_NE(0u, mapped_id2); EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); @@ -1626,7 +1676,7 @@ TEST_P(ResourceProviderTest, DeleteTransferredResources) { size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id = child_resource_provider_->CreateResource( + ResourceId id = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data[4] = { 1, 2, 3, 4 }; child_resource_provider_->CopyToResource(id, data, size); @@ -1677,7 +1727,7 @@ TEST_P(ResourceProviderTest, UnuseTransferredResources) { size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id = child_resource_provider_->CreateResource( + ResourceId id = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); uint8_t data[4] = {1, 2, 3, 4}; child_resource_provider_->CopyToResource(id, data, size); @@ -1705,7 +1755,7 @@ TEST_P(ResourceProviderTest, UnuseTransferredResources) { { // Parent transfers to top-level. ASSERT_TRUE(map.find(id) != map.end()); - ResourceProvider::ResourceId parent_id = map.find(id)->second; + ResourceId parent_id = map.find(id)->second; ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(parent_id); resource_provider_->PrepareSendToParent(resource_ids_to_transfer, @@ -1743,14 +1793,14 @@ TEST_P(ResourceProviderTest, UnuseTransferredResources) { // in the parent. EXPECT_TRUE(returned_to_child.empty()); ASSERT_TRUE(map.find(id) != map.end()); - ResourceProvider::ResourceId parent_id = map.find(id)->second; + ResourceId parent_id = map.find(id)->second; EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id)); } { sent_to_top_level.clear(); // Parent transfers again to top-level. ASSERT_TRUE(map.find(id) != map.end()); - ResourceProvider::ResourceId parent_id = map.find(id)->second; + ResourceId parent_id = map.find(id)->second; ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(parent_id); resource_provider_->PrepareSendToParent(resource_ids_to_transfer, @@ -1766,7 +1816,7 @@ TEST_P(ResourceProviderTest, UnuseTransferredResources) { // declared used in the parent. EXPECT_TRUE(returned_to_child.empty()); ASSERT_TRUE(map.find(id) != map.end()); - ResourceProvider::ResourceId parent_id = map.find(id)->second; + ResourceId parent_id = map.find(id)->second; EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id)); } { @@ -1800,12 +1850,8 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { scoped_ptr<ResourceProvider> child_resource_provider( ResourceProvider::Create(child_output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + shared_bitmap_manager.get(), NULL, NULL, 0, + false, 1, false)); scoped_ptr<TextureStateTrackingContext> parent_context_owned( new TextureStateTrackingContext); @@ -1818,12 +1864,8 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { scoped_ptr<ResourceProvider> parent_resource_provider( ResourceProvider::Create(parent_output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + shared_bitmap_manager.get(), NULL, NULL, 0, + false, 1, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -1833,7 +1875,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id = child_resource_provider->CreateResource( + ResourceId id = child_resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); @@ -1915,7 +1957,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { } ResourceProvider::ResourceIdMap resource_map = parent_resource_provider->GetChildToParentMap(child_id); - ResourceProvider::ResourceId mapped_id = resource_map[id]; + ResourceId mapped_id = resource_map[id]; EXPECT_NE(0u, mapped_id); // The texture is set to |parent_filter| in the parent. @@ -1997,10 +2039,9 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) { &release_sync_point, &lost_resource, &main_thread_task_runner); - ResourceProvider::ResourceId resource = - resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), - SingleReleaseCallbackImpl::Create(callback)); + ResourceId resource = resource_provider_->CreateResourceFromTextureMailbox( + TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), + SingleReleaseCallbackImpl::Create(callback)); EXPECT_EQ(1u, context()->NumTextures()); EXPECT_EQ(0u, release_sync_point); { @@ -2107,10 +2148,8 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) { TEST_P(ResourceProviderTest, LostResourceInParent) { gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; - ResourceProvider::ResourceId resource = - child_resource_provider_->CreateResource( - size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, - format); + ResourceId resource = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); child_resource_provider_->AllocateForTesting(resource); // Expect a GL resource to be lost. bool should_lose_resource = @@ -2164,10 +2203,8 @@ TEST_P(ResourceProviderTest, LostResourceInParent) { TEST_P(ResourceProviderTest, LostResourceInGrandParent) { gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; - ResourceProvider::ResourceId resource = - child_resource_provider_->CreateResource( - size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, - format); + ResourceId resource = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); child_resource_provider_->AllocateForTesting(resource); ReturnedResourceArray returned_to_child; @@ -2192,7 +2229,7 @@ TEST_P(ResourceProviderTest, LostResourceInGrandParent) { { ResourceProvider::ResourceIdMap resource_map = resource_provider_->GetChildToParentMap(child_id); - ResourceProvider::ResourceId parent_resource = resource_map[resource]; + ResourceId parent_resource = resource_map[resource]; EXPECT_NE(0u, parent_resource); // Transfer to a grandparent. @@ -2245,8 +2282,8 @@ TEST_P(ResourceProviderTest, LostMailboxInParent) { bool lost_resource = false; bool release_called = false; uint32 sync_point = 0; - ResourceProvider::ResourceId resource = CreateChildMailbox( - &release_sync_point, &lost_resource, &release_called, &sync_point); + ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource, + &release_called, &sync_point); ReturnedResourceArray returned_to_child; int child_id = @@ -2298,8 +2335,8 @@ TEST_P(ResourceProviderTest, LostMailboxInGrandParent) { bool lost_resource = false; bool release_called = false; uint32 sync_point = 0; - ResourceProvider::ResourceId resource = CreateChildMailbox( - &release_sync_point, &lost_resource, &release_called, &sync_point); + ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource, + &release_called, &sync_point); ReturnedResourceArray returned_to_child; int child_id = @@ -2323,7 +2360,7 @@ TEST_P(ResourceProviderTest, LostMailboxInGrandParent) { { ResourceProvider::ResourceIdMap resource_map = resource_provider_->GetChildToParentMap(child_id); - ResourceProvider::ResourceId parent_resource = resource_map[resource]; + ResourceId parent_resource = resource_map[resource]; EXPECT_NE(0u, parent_resource); // Transfer to a grandparent. @@ -2388,8 +2425,8 @@ TEST_P(ResourceProviderTest, ShutdownWithExportedResource) { bool lost_resource = false; bool release_called = false; uint32 sync_point = 0; - ResourceProvider::ResourceId resource = CreateChildMailbox( - &release_sync_point, &lost_resource, &release_called, &sync_point); + ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource, + &release_called, &sync_point); // Transfer the resource, so we can't release it properly on shutdown. ResourceProvider::ResourceIdArray resource_ids_to_transfer; @@ -2458,20 +2495,15 @@ TEST_P(ResourceProviderTest, ScopedSampler) { FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; int texture_id = 1; - ResourceProvider::ResourceId id = resource_provider->CreateResource( + ResourceId id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); // Check that the texture gets created with the right sampler settings. @@ -2545,21 +2577,16 @@ TEST_P(ResourceProviderTest, ManagedResource) { FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; int texture_id = 1; // Check that the texture gets created with the right sampler settings. - ResourceProvider::ResourceId id = resource_provider->CreateManagedResource( + ResourceId id = resource_provider->CreateManagedResource( size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); @@ -2597,14 +2624,9 @@ TEST_P(ResourceProviderTest, TextureWrapMode) { FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -2613,7 +2635,7 @@ TEST_P(ResourceProviderTest, TextureWrapMode) { for (int texture_id = 1; texture_id <= 2; ++texture_id) { GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT; // Check that the texture gets created with the right sampler settings. - ResourceProvider::ResourceId id = resource_provider->CreateGLTexture( + ResourceId id = resource_provider->CreateGLTexture( size, GL_TEXTURE_2D, texture_pool, wrap_mode, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); @@ -2652,14 +2674,9 @@ TEST_P(ResourceProviderTest, TextureHint) { FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -2673,13 +2690,9 @@ TEST_P(ResourceProviderTest, TextureHint) { }; for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) { // Check that the texture gets created with the right sampler settings. - ResourceProvider::ResourceId id = - resource_provider->CreateGLTexture(size, - GL_TEXTURE_2D, - texture_pool, - GL_CLAMP_TO_EDGE, - hints[texture_id - 1], - format); + ResourceId id = resource_provider->CreateGLTexture( + size, GL_TEXTURE_2D, texture_pool, GL_CLAMP_TO_EDGE, + hints[texture_id - 1], format); EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); @@ -2725,14 +2738,10 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) { new SoftwareOutputDevice))); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - main_thread_task_runner_.get(), - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, + false, 1, false)); uint32 release_sync_point = 0; bool lost_resource = false; @@ -2744,9 +2753,8 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) { &main_thread_task_runner)); TextureMailbox mailbox(shared_bitmap.get(), size); - ResourceProvider::ResourceId id = - resource_provider->CreateResourceFromTextureMailbox( - mailbox, callback.Pass()); + ResourceId id = resource_provider->CreateResourceFromTextureMailbox( + mailbox, callback.Pass()); EXPECT_NE(0u, id); { @@ -2780,14 +2788,9 @@ class ResourceProviderTestTextureMailboxGLFilters FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager, - gpu_memory_buffer_manager, - main_thread_task_runner, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager, gpu_memory_buffer_manager, + main_thread_task_runner, 0, false, 1, false)); unsigned texture_id = 1; uint32 sync_point = 30; @@ -2813,9 +2816,8 @@ class ResourceProviderTestTextureMailboxGLFilters TextureMailbox mailbox(gpu_mailbox, target, sync_point); mailbox.set_nearest_neighbor(mailbox_nearest_neighbor); - ResourceProvider::ResourceId id = - resource_provider->CreateResourceFromTextureMailbox(mailbox, - callback.Pass()); + ResourceId id = resource_provider->CreateResourceFromTextureMailbox( + mailbox, callback.Pass()); EXPECT_NE(0u, id); Mock::VerifyAndClearExpectations(context); @@ -2929,14 +2931,9 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); uint32 sync_point = 30; unsigned target = GL_TEXTURE_EXTERNAL_OES; @@ -2954,9 +2951,8 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { TextureMailbox mailbox(gpu_mailbox, target, sync_point); - ResourceProvider::ResourceId id = - resource_provider->CreateResourceFromTextureMailbox( - mailbox, callback.Pass()); + ResourceId id = resource_provider->CreateResourceFromTextureMailbox( + mailbox, callback.Pass()); EXPECT_NE(0u, id); Mock::VerifyAndClearExpectations(context); @@ -3004,14 +3000,9 @@ TEST_P(ResourceProviderTest, FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); uint32 sync_point = 30; unsigned target = GL_TEXTURE_2D; @@ -3029,9 +3020,8 @@ TEST_P(ResourceProviderTest, TextureMailbox mailbox(gpu_mailbox, target, sync_point); - ResourceProvider::ResourceId id = - resource_provider->CreateResourceFromTextureMailbox(mailbox, - callback.Pass()); + ResourceId id = resource_provider->CreateResourceFromTextureMailbox( + mailbox, callback.Pass()); EXPECT_NE(0u, id); Mock::VerifyAndClearExpectations(context); @@ -3063,14 +3053,9 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) { FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); uint32 sync_point = 0; unsigned target = GL_TEXTURE_2D; @@ -3088,9 +3073,8 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) { TextureMailbox mailbox(gpu_mailbox, target, sync_point); - ResourceProvider::ResourceId id = - resource_provider->CreateResourceFromTextureMailbox(mailbox, - callback.Pass()); + ResourceId id = resource_provider->CreateResourceFromTextureMailbox( + mailbox, callback.Pass()); EXPECT_NE(0u, id); Mock::VerifyAndClearExpectations(context); @@ -3189,19 +3173,14 @@ TEST_P(ResourceProviderTest, TextureAllocation) { FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); gfx::Size size(2, 2); gfx::Vector2d offset(0, 0); ResourceFormat format = RGBA_8888; - ResourceProvider::ResourceId id = 0; + ResourceId id = 0; uint8_t pixels[16] = { 0 }; int texture_id = 123; @@ -3268,14 +3247,9 @@ TEST_P(ResourceProviderTest, TextureAllocationHint) { FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); gfx::Size size(2, 2); @@ -3289,7 +3263,7 @@ TEST_P(ResourceProviderTest, TextureAllocationHint) { for (size_t i = 0; i < arraysize(formats); ++i) { for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) { // Lazy allocation. Don't allocate when creating the resource. - ResourceProvider::ResourceId id = resource_provider->CreateResource( + ResourceId id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]); EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); @@ -3328,14 +3302,9 @@ TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) { FakeOutputSurface::Create3d(context_owned.Pass())); CHECK(output_surface->BindToClient(&output_surface_client)); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); gfx::Size size(2, 2); const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888}; @@ -3349,7 +3318,7 @@ TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) { for (size_t i = 0; i < arraysize(formats); ++i) { for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) { // Lazy allocation. Don't allocate when creating the resource. - ResourceProvider::ResourceId id = resource_provider->CreateResource( + ResourceId id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]); EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); @@ -3384,17 +3353,12 @@ TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) { gfx::Size size(2, 2); ResourceFormat format = RGBA_8888; - ResourceProvider::ResourceId id = 0; + ResourceId id = 0; int texture_id = 123; - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); @@ -3431,17 +3395,12 @@ TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) { gfx::Size size(2, 2); ResourceFormat format = RGBA_8888; - ResourceProvider::ResourceId id = 0; + ResourceId id = 0; int texture_id = 123; - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); @@ -3478,17 +3437,12 @@ TEST_P(ResourceProviderTest, PixelBufferLostContext) { gfx::Size size(2, 2); ResourceFormat format = RGBA_8888; - ResourceProvider::ResourceId id = 0; + ResourceId id = 0; int texture_id = 123; - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id)); @@ -3522,22 +3476,23 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { const int kHeight = 2; gfx::Size size(kWidth, kHeight); ResourceFormat format = RGBA_8888; - ResourceProvider::ResourceId id = 0; + ResourceId id = 0; const unsigned kTextureId = 123u; const unsigned kImageId = 234u; - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + EXPECT_CALL(*context, NextTextureId()) + .WillOnce(Return(kTextureId)) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)) + .Times(1) + .RetiresOnSaturation(); EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA)) .WillOnce(Return(kImageId)) .RetiresOnSaturation(); @@ -3547,11 +3502,8 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { EXPECT_TRUE(lock.GetGpuMemoryBuffer()); } - EXPECT_CALL(*context, NextTextureId()) - .WillOnce(Return(kTextureId)) - .RetiresOnSaturation(); - // Once in CreateTextureId and once in BindForSampling - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2) + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)) + .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) .Times(1) @@ -3607,24 +3559,25 @@ TEST_P(ResourceProviderTest, CopyResource_GLTexture) { const int kHeight = 2; gfx::Size size(kWidth, kHeight); ResourceFormat format = RGBA_8888; - ResourceProvider::ResourceId source_id = 0; - ResourceProvider::ResourceId dest_id = 0; + ResourceId source_id = 0; + ResourceId dest_id = 0; const unsigned kSourceTextureId = 123u; const unsigned kDestTextureId = 321u; const unsigned kImageId = 234u; - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); source_id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + EXPECT_CALL(*context, NextTextureId()) + .WillOnce(Return(kSourceTextureId)) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId)) + .Times(1) + .RetiresOnSaturation(); EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA)) .WillOnce(Return(kImageId)) .RetiresOnSaturation(); @@ -3648,16 +3601,13 @@ TEST_P(ResourceProviderTest, CopyResource_GLTexture) { GL_UNSIGNED_BYTE, nullptr)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*context, NextTextureId()) - .WillOnce(Return(kSourceTextureId)) - .RetiresOnSaturation(); EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId)) - .Times(2) + .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) .Times(1) .RetiresOnSaturation(); - resource_provider->CopyResource(source_id, dest_id); + resource_provider->CopyResource(source_id, dest_id, gfx::Rect(size)); Mock::VerifyAndClearExpectations(context); EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)) @@ -3688,17 +3638,12 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { CHECK(output_surface->BindToClient(&output_surface_client)); gfx::Size size(4, 4); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); int texture_id = 123; - ResourceProvider::ResourceId id = resource_provider->CreateResource( + ResourceId id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1); EXPECT_NE(0u, id); EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); @@ -3724,18 +3669,13 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) { CHECK(output_surface->BindToClient(&output_surface_client)); gfx::Size size(4, 4); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false)); int texture_id = 123; uint8_t pixels[8]; - ResourceProvider::ResourceId id = resource_provider->CreateResource( + ResourceId id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1); EXPECT_NE(0u, id); EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); @@ -3785,16 +3725,11 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) { { size_t kTextureAllocationChunkSize = 1; - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - kTextureAllocationChunkSize)); - - ResourceProvider::ResourceId id = resource_provider->CreateResource( + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, + kTextureAllocationChunkSize, false)); + + ResourceId id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); resource_provider->AllocateForTesting(id); @@ -3806,16 +3741,11 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) { { size_t kTextureAllocationChunkSize = 8; - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - kTextureAllocationChunkSize)); - - ResourceProvider::ResourceId id = resource_provider->CreateResource( + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, + kTextureAllocationChunkSize, false)); + + ResourceId id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); resource_provider->AllocateForTesting(id); diff --git a/chromium/cc/resources/resource_update.cc b/chromium/cc/resources/resource_update.cc deleted file mode 100644 index 2fe8fe5eebe..00000000000 --- a/chromium/cc/resources/resource_update.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 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/resources/resource_update.h" - -#include "base/logging.h" - -namespace cc { - -ResourceUpdate ResourceUpdate::Create(PrioritizedResource* resource, - const SkBitmap* bitmap, - const gfx::Rect& content_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset) { - CHECK(content_rect.Contains(source_rect)); - ResourceUpdate update; - update.texture = resource; - update.bitmap = bitmap; - update.content_rect = content_rect; - update.source_rect = source_rect; - update.dest_offset = dest_offset; - return update; -} - -ResourceUpdate::ResourceUpdate() - : texture(NULL), - bitmap(NULL) {} - -ResourceUpdate::~ResourceUpdate() {} - -} // namespace cc diff --git a/chromium/cc/resources/resource_update.h b/chromium/cc/resources/resource_update.h deleted file mode 100644 index d49114171d4..00000000000 --- a/chromium/cc/resources/resource_update.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_RESOURCE_UPDATE_H_ -#define CC_RESOURCES_RESOURCE_UPDATE_H_ - -#include "cc/base/cc_export.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/vector2d.h" - -class SkBitmap; - -namespace cc { - -class PrioritizedResource; - -struct CC_EXPORT ResourceUpdate { - static ResourceUpdate Create(PrioritizedResource* resource, - const SkBitmap* bitmap, - const gfx::Rect& content_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset); - - ResourceUpdate(); - virtual ~ResourceUpdate(); - - PrioritizedResource* texture; - const SkBitmap* bitmap; - gfx::Rect content_rect; - gfx::Rect source_rect; - gfx::Vector2d dest_offset; -}; - -} // namespace cc - -#endif // CC_RESOURCES_RESOURCE_UPDATE_H_ diff --git a/chromium/cc/resources/resource_update_controller.cc b/chromium/cc/resources/resource_update_controller.cc deleted file mode 100644 index bd6d21df612..00000000000 --- a/chromium/cc/resources/resource_update_controller.cc +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2012 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/resources/resource_update_controller.h" - -#include "base/bind.h" -#include "base/location.h" -#include "base/single_thread_task_runner.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/resource_provider.h" -#include "ui/gfx/frame_time.h" - -namespace { - -// Number of partial updates we allow. -const size_t kPartialTextureUpdatesMax = 12; - -// Measured in seconds. -const double kUploaderBusyTickRate = 0.001; - -// Number of blocking update intervals to allow. -const size_t kMaxBlockingUpdateIntervals = 4; - -} // namespace - -namespace cc { - -size_t ResourceUpdateController::MaxPartialTextureUpdates() { - return kPartialTextureUpdatesMax; -} - -size_t ResourceUpdateController::MaxFullUpdatesPerTick( - ResourceProvider* resource_provider) { - return resource_provider->EstimatedUploadsPerTick(); -} - -ResourceUpdateController::ResourceUpdateController( - ResourceUpdateControllerClient* client, - base::SingleThreadTaskRunner* task_runner, - scoped_ptr<ResourceUpdateQueue> queue, - ResourceProvider* resource_provider) - : client_(client), - queue_(queue.Pass()), - resource_provider_(resource_provider), - texture_updates_per_tick_(MaxFullUpdatesPerTick(resource_provider)), - first_update_attempt_(true), - task_runner_(task_runner), - task_posted_(false), - ready_to_finalize_(false), - weak_factory_(this) {} - -ResourceUpdateController::~ResourceUpdateController() {} - -void ResourceUpdateController::PerformMoreUpdates( - base::TimeTicks time_limit) { - time_limit_ = time_limit; - - // Update already in progress or we are already done. - if (task_posted_ || ready_to_finalize_) - return; - - // Call UpdateMoreTexturesNow() directly unless it's the first update - // attempt. This ensures that we empty the update queue in a finite - // amount of time. - if (!first_update_attempt_) - UpdateMoreTexturesNow(); - - // Post a 0-delay task when no updates were left. When it runs, - // ReadyToFinalizeTextureUpdates() will be called. - if (!UpdateMoreTexturesIfEnoughTimeRemaining()) { - task_posted_ = true; - task_runner_->PostTask( - FROM_HERE, - base::Bind(&ResourceUpdateController::OnTimerFired, - weak_factory_.GetWeakPtr())); - } - - first_update_attempt_ = false; -} - -void ResourceUpdateController::DiscardUploadsToEvictedResources() { - queue_->ClearUploadsToEvictedResources(); -} - -void ResourceUpdateController::UpdateTexture(ResourceUpdate update) { - update.bitmap->lockPixels(); - update.texture->SetPixels( - resource_provider_, - static_cast<const uint8_t*>(update.bitmap->getPixels()), - update.content_rect, - update.source_rect, - update.dest_offset); - update.bitmap->unlockPixels(); -} - -void ResourceUpdateController::Finalize() { - while (queue_->FullUploadSize()) - UpdateTexture(queue_->TakeFirstFullUpload()); - - while (queue_->PartialUploadSize()) - UpdateTexture(queue_->TakeFirstPartialUpload()); - - resource_provider_->FlushUploads(); -} - -void ResourceUpdateController::OnTimerFired() { - task_posted_ = false; - if (!UpdateMoreTexturesIfEnoughTimeRemaining()) { - ready_to_finalize_ = true; - client_->ReadyToFinalizeTextureUpdates(); - } -} - -base::TimeTicks ResourceUpdateController::UpdateMoreTexturesCompletionTime() { - return resource_provider_->EstimatedUploadCompletionTime( - texture_updates_per_tick_); -} - -size_t ResourceUpdateController::UpdateMoreTexturesSize() const { - return texture_updates_per_tick_; -} - -size_t ResourceUpdateController::MaxBlockingUpdates() const { - return UpdateMoreTexturesSize() * kMaxBlockingUpdateIntervals; -} - -bool ResourceUpdateController::UpdateMoreTexturesIfEnoughTimeRemaining() { - while (resource_provider_->NumBlockingUploads() < MaxBlockingUpdates()) { - if (!queue_->FullUploadSize()) - return false; - - if (!time_limit_.is_null()) { - base::TimeTicks completion_time = UpdateMoreTexturesCompletionTime(); - if (completion_time > time_limit_) - return true; - } - - UpdateMoreTexturesNow(); - } - - task_posted_ = true; - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&ResourceUpdateController::OnTimerFired, - weak_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(kUploaderBusyTickRate * 1000)); - return true; -} - -void ResourceUpdateController::UpdateMoreTexturesNow() { - size_t uploads = std::min( - queue_->FullUploadSize(), UpdateMoreTexturesSize()); - - if (!uploads) - return; - - while (queue_->FullUploadSize() && uploads--) - UpdateTexture(queue_->TakeFirstFullUpload()); - - resource_provider_->FlushUploads(); -} - -} // namespace cc diff --git a/chromium/cc/resources/resource_update_controller.h b/chromium/cc/resources/resource_update_controller.h deleted file mode 100644 index 1946df47c16..00000000000 --- a/chromium/cc/resources/resource_update_controller.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_RESOURCE_UPDATE_CONTROLLER_H_ -#define CC_RESOURCES_RESOURCE_UPDATE_CONTROLLER_H_ - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "cc/base/cc_export.h" -#include "cc/resources/resource_update_queue.h" - -namespace base { class SingleThreadTaskRunner; } - -namespace cc { - -class ResourceProvider; - -class ResourceUpdateControllerClient { - public: - virtual void ReadyToFinalizeTextureUpdates() = 0; - - protected: - virtual ~ResourceUpdateControllerClient() {} -}; - -class CC_EXPORT ResourceUpdateController { - public: - static scoped_ptr<ResourceUpdateController> Create( - ResourceUpdateControllerClient* client, - base::SingleThreadTaskRunner* task_runner, - scoped_ptr<ResourceUpdateQueue> queue, - ResourceProvider* resource_provider) { - return make_scoped_ptr(new ResourceUpdateController( - client, task_runner, queue.Pass(), resource_provider)); - } - static size_t MaxPartialTextureUpdates(); - - virtual ~ResourceUpdateController(); - - // Discard uploads to textures that were evicted on the impl thread. - void DiscardUploadsToEvictedResources(); - - void PerformMoreUpdates(base::TimeTicks time_limit); - void Finalize(); - - - // Virtual for testing. - virtual size_t UpdateMoreTexturesSize() const; - virtual base::TimeTicks UpdateMoreTexturesCompletionTime(); - - protected: - ResourceUpdateController(ResourceUpdateControllerClient* client, - base::SingleThreadTaskRunner* task_runner, - scoped_ptr<ResourceUpdateQueue> queue, - ResourceProvider* resource_provider); - - private: - static size_t MaxFullUpdatesPerTick(ResourceProvider* resource_provider); - - size_t MaxBlockingUpdates() const; - - void UpdateTexture(ResourceUpdate update); - - // This returns true when there were textures left to update. - bool UpdateMoreTexturesIfEnoughTimeRemaining(); - void UpdateMoreTexturesNow(); - void OnTimerFired(); - - ResourceUpdateControllerClient* client_; - scoped_ptr<ResourceUpdateQueue> queue_; - ResourceProvider* resource_provider_; - base::TimeTicks time_limit_; - size_t texture_updates_per_tick_; - bool first_update_attempt_; - base::SingleThreadTaskRunner* task_runner_; - bool task_posted_; - bool ready_to_finalize_; - base::WeakPtrFactory<ResourceUpdateController> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ResourceUpdateController); -}; - -} // namespace cc - -#endif // CC_RESOURCES_RESOURCE_UPDATE_CONTROLLER_H_ diff --git a/chromium/cc/resources/resource_update_controller_unittest.cc b/chromium/cc/resources/resource_update_controller_unittest.cc deleted file mode 100644 index 1aa0902d469..00000000000 --- a/chromium/cc/resources/resource_update_controller_unittest.cc +++ /dev/null @@ -1,516 +0,0 @@ -// Copyright 2012 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/resources/resource_update_controller.h" - -#include "base/test/test_simple_task_runner.h" -#include "cc/resources/prioritized_resource_manager.h" -#include "cc/test/fake_output_surface.h" -#include "cc/test/fake_output_surface_client.h" -#include "cc/test/fake_proxy.h" -#include "cc/test/scheduler_test_common.h" -#include "cc/test/test_shared_bitmap_manager.h" -#include "cc/test/test_web_graphics_context_3d.h" -#include "cc/test/tiled_layer_test_common.h" -#include "cc/trees/single_thread_proxy.h" // For DebugScopedSetImplThread -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/khronos/GLES2/gl2ext.h" - -using testing::Test; - -namespace cc { -namespace { - -const int kFlushPeriodFull = 4; -const int kFlushPeriodPartial = kFlushPeriodFull; - -class ResourceUpdateControllerTest; - -class WebGraphicsContext3DForUploadTest : public TestWebGraphicsContext3D { - public: - explicit WebGraphicsContext3DForUploadTest(ResourceUpdateControllerTest* test) - : test_(test) {} - - void flush() override; - void shallowFlushCHROMIUM() override; - void texSubImage2D(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void* pixels) override; - - void getQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* value) override; - - private: - ResourceUpdateControllerTest* test_; -}; - -class ResourceUpdateControllerTest : public Test { - public: - ResourceUpdateControllerTest() - : proxy_(), - queue_(make_scoped_ptr(new ResourceUpdateQueue)), - resource_manager_(PrioritizedResourceManager::Create(&proxy_)), - query_results_available_(0), - full_upload_count_expected_(0), - partial_count_expected_(0), - total_upload_count_expected_(0), - max_upload_count_per_update_(0), - num_consecutive_flushes_(0), - num_dangling_uploads_(0), - num_total_uploads_(0), - num_total_flushes_(0) {} - - ~ResourceUpdateControllerTest() override { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - resource_manager_->ClearAllMemory(resource_provider_.get()); - } - - public: - void OnFlush() { - // Check for back-to-back flushes. - EXPECT_EQ(0, num_consecutive_flushes_) << "Back-to-back flushes detected."; - - num_dangling_uploads_ = 0; - num_consecutive_flushes_++; - num_total_flushes_++; - } - - void OnUpload() { - // Check for too many consecutive uploads - if (num_total_uploads_ < full_upload_count_expected_) { - EXPECT_LT(num_dangling_uploads_, kFlushPeriodFull) - << "Too many consecutive full uploads detected."; - } else { - EXPECT_LT(num_dangling_uploads_, kFlushPeriodPartial) - << "Too many consecutive partial uploads detected."; - } - - num_consecutive_flushes_ = 0; - num_dangling_uploads_++; - num_total_uploads_++; - } - - bool IsQueryResultAvailable() { - if (!query_results_available_) - return false; - - query_results_available_--; - return true; - } - - protected: - void SetUp() override { - bitmap_.allocN32Pixels(300, 150); - - for (int i = 0; i < 4; i++) { - textures_[i] = PrioritizedResource::Create(resource_manager_.get(), - gfx::Size(300, 150), - RGBA_8888); - textures_[i]-> - set_request_priority(PriorityCalculator::VisiblePriority(true)); - } - resource_manager_->PrioritizeTextures(); - - output_surface_ = FakeOutputSurface::Create3d( - scoped_ptr<TestWebGraphicsContext3D>( - new WebGraphicsContext3DForUploadTest(this))); - CHECK(output_surface_->BindToClient(&output_surface_client_)); - - shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1); - } - - void AppendFullUploadsOfIndexedTextureToUpdateQueue(int count, - int texture_index) { - full_upload_count_expected_ += count; - total_upload_count_expected_ += count; - - const gfx::Rect rect(0, 0, 300, 150); - const ResourceUpdate upload = ResourceUpdate::Create( - textures_[texture_index].get(), &bitmap_, rect, rect, gfx::Vector2d()); - for (int i = 0; i < count; i++) - queue_->AppendFullUpload(upload); - } - - void AppendFullUploadsToUpdateQueue(int count) { - AppendFullUploadsOfIndexedTextureToUpdateQueue(count, 0); - } - - void AppendPartialUploadsOfIndexedTextureToUpdateQueue(int count, - int texture_index) { - partial_count_expected_ += count; - total_upload_count_expected_ += count; - - const gfx::Rect rect(0, 0, 100, 100); - const ResourceUpdate upload = ResourceUpdate::Create( - textures_[texture_index].get(), &bitmap_, rect, rect, gfx::Vector2d()); - for (int i = 0; i < count; i++) - queue_->AppendPartialUpload(upload); - } - - void AppendPartialUploadsToUpdateQueue(int count) { - AppendPartialUploadsOfIndexedTextureToUpdateQueue(count, 0); - } - - void SetMaxUploadCountPerUpdate(int count) { - max_upload_count_per_update_ = count; - } - - void UpdateTextures() { - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - scoped_ptr<ResourceUpdateController> update_controller = - ResourceUpdateController::Create(NULL, - proxy_.ImplThreadTaskRunner(), - queue_.Pass(), - resource_provider_.get()); - update_controller->Finalize(); - } - - void MakeQueryResultAvailable() { query_results_available_++; } - - protected: - // Classes required to interact and test the ResourceUpdateController - FakeProxy proxy_; - FakeOutputSurfaceClient output_surface_client_; - scoped_ptr<OutputSurface> output_surface_; - scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; - scoped_ptr<ResourceProvider> resource_provider_; - scoped_ptr<ResourceUpdateQueue> queue_; - scoped_ptr<PrioritizedResource> textures_[4]; - scoped_ptr<PrioritizedResourceManager> resource_manager_; - SkBitmap bitmap_; - int query_results_available_; - - // Properties / expectations of this test - int full_upload_count_expected_; - int partial_count_expected_; - int total_upload_count_expected_; - int max_upload_count_per_update_; - - // Dynamic properties of this test - int num_consecutive_flushes_; - int num_dangling_uploads_; - int num_total_uploads_; - int num_total_flushes_; -}; - -void WebGraphicsContext3DForUploadTest::flush() { test_->OnFlush(); } - -void WebGraphicsContext3DForUploadTest::shallowFlushCHROMIUM() { - test_->OnFlush(); -} - -void WebGraphicsContext3DForUploadTest::texSubImage2D(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void* pixels) { - test_->OnUpload(); -} - -void WebGraphicsContext3DForUploadTest::getQueryObjectuivEXT(GLuint id, - GLenum pname, - GLuint* params) { - if (pname == GL_QUERY_RESULT_AVAILABLE_EXT) - *params = test_->IsQueryResultAvailable(); -} - -// ZERO UPLOADS TESTS -TEST_F(ResourceUpdateControllerTest, ZeroUploads) { - AppendFullUploadsToUpdateQueue(0); - AppendPartialUploadsToUpdateQueue(0); - UpdateTextures(); - - EXPECT_EQ(0, num_total_flushes_); - EXPECT_EQ(0, num_total_uploads_); -} - -// ONE UPLOAD TESTS -TEST_F(ResourceUpdateControllerTest, OneFullUpload) { - AppendFullUploadsToUpdateQueue(1); - AppendPartialUploadsToUpdateQueue(0); - UpdateTextures(); - - EXPECT_EQ(1, num_total_flushes_); - EXPECT_EQ(1, num_total_uploads_); - EXPECT_EQ(0, num_dangling_uploads_) - << "Last upload wasn't followed by a flush."; -} - -TEST_F(ResourceUpdateControllerTest, OnePartialUpload) { - AppendFullUploadsToUpdateQueue(0); - AppendPartialUploadsToUpdateQueue(1); - UpdateTextures(); - - EXPECT_EQ(1, num_total_flushes_); - EXPECT_EQ(1, num_total_uploads_); - EXPECT_EQ(0, num_dangling_uploads_) - << "Last upload wasn't followed by a flush."; -} - -TEST_F(ResourceUpdateControllerTest, OneFullOnePartialUpload) { - AppendFullUploadsToUpdateQueue(1); - AppendPartialUploadsToUpdateQueue(1); - UpdateTextures(); - - EXPECT_EQ(1, num_total_flushes_); - EXPECT_EQ(2, num_total_uploads_); - EXPECT_EQ(0, num_dangling_uploads_) - << "Last upload wasn't followed by a flush."; -} - -// This class of tests upload a number of textures that is a multiple -// of the flush period. -const int full_upload_flush_multipler = 7; -const int full_count = full_upload_flush_multipler * kFlushPeriodFull; - -const int partial_upload_flush_multipler = 11; -const int partial_count = - partial_upload_flush_multipler * kFlushPeriodPartial; - -TEST_F(ResourceUpdateControllerTest, ManyFullUploads) { - AppendFullUploadsToUpdateQueue(full_count); - AppendPartialUploadsToUpdateQueue(0); - UpdateTextures(); - - EXPECT_EQ(full_upload_flush_multipler, num_total_flushes_); - EXPECT_EQ(full_count, num_total_uploads_); - EXPECT_EQ(0, num_dangling_uploads_) - << "Last upload wasn't followed by a flush."; -} - -TEST_F(ResourceUpdateControllerTest, ManyPartialUploads) { - AppendFullUploadsToUpdateQueue(0); - AppendPartialUploadsToUpdateQueue(partial_count); - UpdateTextures(); - - EXPECT_EQ(partial_upload_flush_multipler, num_total_flushes_); - EXPECT_EQ(partial_count, num_total_uploads_); - EXPECT_EQ(0, num_dangling_uploads_) - << "Last upload wasn't followed by a flush."; -} - -TEST_F(ResourceUpdateControllerTest, ManyFullManyPartialUploads) { - AppendFullUploadsToUpdateQueue(full_count); - AppendPartialUploadsToUpdateQueue(partial_count); - UpdateTextures(); - - EXPECT_EQ(full_upload_flush_multipler + partial_upload_flush_multipler, - num_total_flushes_); - EXPECT_EQ(full_count + partial_count, num_total_uploads_); - EXPECT_EQ(0, num_dangling_uploads_) - << "Last upload wasn't followed by a flush."; -} - -class FakeResourceUpdateControllerClient - : public ResourceUpdateControllerClient { - public: - FakeResourceUpdateControllerClient() { Reset(); } - void Reset() { ready_to_finalize_called_ = false; } - bool ReadyToFinalizeCalled() const { return ready_to_finalize_called_; } - - void ReadyToFinalizeTextureUpdates() override { - ready_to_finalize_called_ = true; - } - - protected: - bool ready_to_finalize_called_; -}; - -class FakeResourceUpdateController : public ResourceUpdateController { - public: - static scoped_ptr<FakeResourceUpdateController> Create( - ResourceUpdateControllerClient* client, - base::TestSimpleTaskRunner* task_runner, - scoped_ptr<ResourceUpdateQueue> queue, - ResourceProvider* resource_provider) { - return make_scoped_ptr(new FakeResourceUpdateController( - client, task_runner, queue.Pass(), resource_provider)); - } - - void SetNow(base::TimeTicks time) { now_ = time; } - base::TimeTicks Now() const { return now_; } - void SetUpdateTextureTime(base::TimeDelta time) { - update_textures_time_ = time; - } - base::TimeTicks UpdateMoreTexturesCompletionTime() override { - size_t total_updates = - resource_provider_->NumBlockingUploads() + update_more_textures_size_; - return now_ + total_updates * update_textures_time_; - } - void SetUpdateMoreTexturesSize(size_t size) { - update_more_textures_size_ = size; - } - size_t UpdateMoreTexturesSize() const override { - return update_more_textures_size_; - } - - protected: - FakeResourceUpdateController(ResourceUpdateControllerClient* client, - base::TestSimpleTaskRunner* task_runner, - scoped_ptr<ResourceUpdateQueue> queue, - ResourceProvider* resource_provider) - : ResourceUpdateController( - client, task_runner, queue.Pass(), resource_provider), - resource_provider_(resource_provider), - update_more_textures_size_(0) {} - - ResourceProvider* resource_provider_; - base::TimeTicks now_; - base::TimeDelta update_textures_time_; - size_t update_more_textures_size_; -}; - -static void RunPendingTask(base::TestSimpleTaskRunner* task_runner, - FakeResourceUpdateController* controller) { - EXPECT_TRUE(task_runner->HasPendingTask()); - controller->SetNow(controller->Now() + task_runner->NextPendingTaskDelay()); - task_runner->RunPendingTasks(); -} - -TEST_F(ResourceUpdateControllerTest, UpdateMoreTextures) { - FakeResourceUpdateControllerClient client; - scoped_refptr<base::TestSimpleTaskRunner> task_runner = - new base::TestSimpleTaskRunner; - - SetMaxUploadCountPerUpdate(1); - AppendFullUploadsToUpdateQueue(3); - AppendPartialUploadsToUpdateQueue(0); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - scoped_ptr<FakeResourceUpdateController> controller( - FakeResourceUpdateController::Create(&client, - task_runner.get(), - queue_.Pass(), - resource_provider_.get())); - - controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1)); - controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100)); - controller->SetUpdateMoreTexturesSize(1); - // Not enough time for any updates. - controller->PerformMoreUpdates(controller->Now() + - base::TimeDelta::FromMilliseconds(90)); - EXPECT_FALSE(task_runner->HasPendingTask()); - - controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100)); - controller->SetUpdateMoreTexturesSize(1); - // Only enough time for 1 update. - controller->PerformMoreUpdates(controller->Now() + - base::TimeDelta::FromMilliseconds(120)); - EXPECT_FALSE(task_runner->HasPendingTask()); - EXPECT_EQ(1, num_total_uploads_); - - // Complete one upload. - MakeQueryResultAvailable(); - - controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100)); - controller->SetUpdateMoreTexturesSize(1); - // Enough time for 2 updates. - controller->PerformMoreUpdates(controller->Now() + - base::TimeDelta::FromMilliseconds(220)); - RunPendingTask(task_runner.get(), controller.get()); - EXPECT_FALSE(task_runner->HasPendingTask()); - EXPECT_TRUE(client.ReadyToFinalizeCalled()); - EXPECT_EQ(3, num_total_uploads_); -} - -TEST_F(ResourceUpdateControllerTest, NoMoreUpdates) { - FakeResourceUpdateControllerClient client; - scoped_refptr<base::TestSimpleTaskRunner> task_runner = - new base::TestSimpleTaskRunner; - - SetMaxUploadCountPerUpdate(1); - AppendFullUploadsToUpdateQueue(2); - AppendPartialUploadsToUpdateQueue(0); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - scoped_ptr<FakeResourceUpdateController> controller( - FakeResourceUpdateController::Create(&client, - task_runner.get(), - queue_.Pass(), - resource_provider_.get())); - - controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1)); - controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100)); - controller->SetUpdateMoreTexturesSize(1); - // Enough time for 3 updates but only 2 necessary. - controller->PerformMoreUpdates(controller->Now() + - base::TimeDelta::FromMilliseconds(310)); - RunPendingTask(task_runner.get(), controller.get()); - EXPECT_FALSE(task_runner->HasPendingTask()); - EXPECT_TRUE(client.ReadyToFinalizeCalled()); - EXPECT_EQ(2, num_total_uploads_); - - client.Reset(); - controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100)); - controller->SetUpdateMoreTexturesSize(1); - // Enough time for updates but no more updates left. - controller->PerformMoreUpdates(controller->Now() + - base::TimeDelta::FromMilliseconds(310)); - - // ReadyToFinalizeTextureUpdates should only be called once. - EXPECT_FALSE(task_runner->HasPendingTask()); - EXPECT_FALSE(client.ReadyToFinalizeCalled()); - EXPECT_EQ(2, num_total_uploads_); -} - -TEST_F(ResourceUpdateControllerTest, UpdatesCompleteInFiniteTime) { - FakeResourceUpdateControllerClient client; - scoped_refptr<base::TestSimpleTaskRunner> task_runner = - new base::TestSimpleTaskRunner; - - SetMaxUploadCountPerUpdate(1); - AppendFullUploadsToUpdateQueue(2); - AppendPartialUploadsToUpdateQueue(0); - - DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); - scoped_ptr<FakeResourceUpdateController> controller( - FakeResourceUpdateController::Create(&client, - task_runner.get(), - queue_.Pass(), - resource_provider_.get())); - - controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1)); - controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(500)); - controller->SetUpdateMoreTexturesSize(1); - - for (int i = 0; i < 100; i++) { - if (client.ReadyToFinalizeCalled()) - break; - - // Not enough time for any updates. - controller->PerformMoreUpdates(controller->Now() + - base::TimeDelta::FromMilliseconds(400)); - - if (task_runner->HasPendingTask()) - RunPendingTask(task_runner.get(), controller.get()); - } - - EXPECT_FALSE(task_runner->HasPendingTask()); - EXPECT_TRUE(client.ReadyToFinalizeCalled()); - EXPECT_EQ(2, num_total_uploads_); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/resources/resource_update_queue.cc b/chromium/cc/resources/resource_update_queue.cc deleted file mode 100644 index 31727cd808c..00000000000 --- a/chromium/cc/resources/resource_update_queue.cc +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2012 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/resources/resource_update_queue.h" - -#include "cc/resources/prioritized_resource.h" - -namespace cc { - -ResourceUpdateQueue::ResourceUpdateQueue() {} - -ResourceUpdateQueue::~ResourceUpdateQueue() {} - -void ResourceUpdateQueue::AppendFullUpload(const ResourceUpdate& upload) { - full_entries_.push_back(upload); -} - -void ResourceUpdateQueue::AppendPartialUpload(const ResourceUpdate& upload) { - partial_entries_.push_back(upload); -} - -void ResourceUpdateQueue::ClearUploadsToEvictedResources() { - ClearUploadsToEvictedResources(&full_entries_); - ClearUploadsToEvictedResources(&partial_entries_); -} - -void ResourceUpdateQueue::ClearUploadsToEvictedResources( - std::deque<ResourceUpdate>* entry_queue) { - std::deque<ResourceUpdate> temp; - entry_queue->swap(temp); - while (temp.size()) { - ResourceUpdate upload = temp.front(); - temp.pop_front(); - if (!upload.texture->BackingResourceWasEvicted()) - entry_queue->push_back(upload); - } -} - -ResourceUpdate ResourceUpdateQueue::TakeFirstFullUpload() { - ResourceUpdate first = full_entries_.front(); - full_entries_.pop_front(); - return first; -} - -ResourceUpdate ResourceUpdateQueue::TakeFirstPartialUpload() { - ResourceUpdate first = partial_entries_.front(); - partial_entries_.pop_front(); - return first; -} - -bool ResourceUpdateQueue::HasMoreUpdates() const { - return !full_entries_.empty() || !partial_entries_.empty(); -} - -} // namespace cc diff --git a/chromium/cc/resources/resource_update_queue.h b/chromium/cc/resources/resource_update_queue.h deleted file mode 100644 index de455ce43fe..00000000000 --- a/chromium/cc/resources/resource_update_queue.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_RESOURCE_UPDATE_QUEUE_H_ -#define CC_RESOURCES_RESOURCE_UPDATE_QUEUE_H_ - -#include <deque> -#include "base/basictypes.h" -#include "cc/base/cc_export.h" -#include "cc/resources/resource_update.h" - -namespace cc { - -class CC_EXPORT ResourceUpdateQueue { - public: - ResourceUpdateQueue(); - virtual ~ResourceUpdateQueue(); - - void AppendFullUpload(const ResourceUpdate& upload); - void AppendPartialUpload(const ResourceUpdate& upload); - - void ClearUploadsToEvictedResources(); - - ResourceUpdate TakeFirstFullUpload(); - ResourceUpdate TakeFirstPartialUpload(); - - size_t FullUploadSize() const { return full_entries_.size(); } - size_t PartialUploadSize() const { return partial_entries_.size(); } - - bool HasMoreUpdates() const; - - private: - void ClearUploadsToEvictedResources(std::deque<ResourceUpdate>* entry_queue); - std::deque<ResourceUpdate> full_entries_; - std::deque<ResourceUpdate> partial_entries_; - - DISALLOW_COPY_AND_ASSIGN(ResourceUpdateQueue); -}; - -} // namespace cc - -#endif // CC_RESOURCES_RESOURCE_UPDATE_QUEUE_H_ diff --git a/chromium/cc/resources/returned_resource.h b/chromium/cc/resources/returned_resource.h index e2008b415a3..767d16f8dee 100644 --- a/chromium/cc/resources/returned_resource.h +++ b/chromium/cc/resources/returned_resource.h @@ -9,12 +9,13 @@ #include "base/basictypes.h" #include "cc/base/cc_export.h" +#include "cc/base/resource_id.h" namespace cc { struct CC_EXPORT ReturnedResource { ReturnedResource() : id(0), sync_point(0), count(0), lost(false) {} - unsigned id; + ResourceId id; unsigned sync_point; int count; bool lost; diff --git a/chromium/cc/resources/scoped_resource_unittest.cc b/chromium/cc/resources/scoped_resource_unittest.cc index b95d814914e..197fa1f3b8d 100644 --- a/chromium/cc/resources/scoped_resource_unittest.cc +++ b/chromium/cc/resources/scoped_resource_unittest.cc @@ -7,8 +7,8 @@ #include "cc/output/renderer.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/test_shared_bitmap_manager.h" -#include "cc/test/tiled_layer_test_common.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -21,14 +21,8 @@ TEST(ScopedResourceTest, NewScopedResource) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); scoped_ptr<ScopedResource> texture = ScopedResource::Create(resource_provider.get()); @@ -37,7 +31,8 @@ TEST(ScopedResourceTest, NewScopedResource) { // New scoped textures do not have a size yet. EXPECT_EQ(gfx::Size(), texture->size()); - EXPECT_EQ(0u, texture->bytes()); + EXPECT_EQ(0u, Resource::UncheckedMemorySizeBytes(texture->size(), + texture->format())); } TEST(ScopedResourceTest, CreateScopedResource) { @@ -47,14 +42,8 @@ TEST(ScopedResourceTest, CreateScopedResource) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); scoped_ptr<ScopedResource> texture = ScopedResource::Create(resource_provider.get()); texture->Allocate(gfx::Size(30, 30), ResourceProvider::TEXTURE_HINT_IMMUTABLE, @@ -62,7 +51,8 @@ TEST(ScopedResourceTest, CreateScopedResource) { // The texture has an allocated byte-size now. size_t expected_bytes = 30 * 30 * 4; - EXPECT_EQ(expected_bytes, texture->bytes()); + EXPECT_EQ(expected_bytes, Resource::UncheckedMemorySizeBytes( + texture->size(), texture->format())); EXPECT_LT(0u, texture->id()); EXPECT_EQ(static_cast<unsigned>(RGBA_8888), texture->format()); @@ -76,14 +66,8 @@ TEST(ScopedResourceTest, ScopedResourceIsDeleted) { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); - scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1)); + scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create( + output_surface.get(), shared_bitmap_manager.get()); { scoped_ptr<ScopedResource> texture = ScopedResource::Create(resource_provider.get()); diff --git a/chromium/cc/resources/skpicture_content_layer_updater.cc b/chromium/cc/resources/skpicture_content_layer_updater.cc deleted file mode 100644 index c54f5dcaa7c..00000000000 --- a/chromium/cc/resources/skpicture_content_layer_updater.cc +++ /dev/null @@ -1,50 +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/resources/skpicture_content_layer_updater.h" - -#include "base/trace_event/trace_event.h" -#include "cc/debug/rendering_stats_instrumentation.h" -#include "cc/resources/layer_painter.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/resource_update_queue.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkPictureRecorder.h" - -namespace cc { - -SkPictureContentLayerUpdater::SkPictureContentLayerUpdater( - scoped_ptr<LayerPainter> painter, - int layer_id) - : ContentLayerUpdater(painter.Pass(), layer_id) { -} - -SkPictureContentLayerUpdater::~SkPictureContentLayerUpdater() {} - -void SkPictureContentLayerUpdater::PrepareToUpdate( - const gfx::Size& content_size, - const gfx::Rect& paint_rect, - const gfx::Size& tile_size, - float contents_width_scale, - float contents_height_scale) { - SkPictureRecorder recorder; - SkCanvas* canvas = - recorder.beginRecording(paint_rect.width(), paint_rect.height(), NULL, 0); - DCHECK_EQ(paint_rect.width(), canvas->getBaseLayerSize().width()); - DCHECK_EQ(paint_rect.height(), canvas->getBaseLayerSize().height()); - PaintContents(canvas, - content_size, - paint_rect, - contents_width_scale, - contents_height_scale); - picture_ = skia::AdoptRef(recorder.endRecordingAsPicture()); -} - -void SkPictureContentLayerUpdater::DrawPicture(SkCanvas* canvas) { - TRACE_EVENT0("cc", "SkPictureContentLayerUpdater::DrawPicture"); - if (picture_) - canvas->drawPicture(picture_.get()); -} - -} // namespace cc diff --git a/chromium/cc/resources/skpicture_content_layer_updater.h b/chromium/cc/resources/skpicture_content_layer_updater.h deleted file mode 100644 index 33480a873c8..00000000000 --- a/chromium/cc/resources/skpicture_content_layer_updater.h +++ /dev/null @@ -1,42 +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. - -#ifndef CC_RESOURCES_SKPICTURE_CONTENT_LAYER_UPDATER_H_ -#define CC_RESOURCES_SKPICTURE_CONTENT_LAYER_UPDATER_H_ - -#include "cc/resources/content_layer_updater.h" -#include "skia/ext/refptr.h" -#include "third_party/skia/include/core/SkPicture.h" - -class SkCanvas; - -namespace cc { - -class LayerPainter; - -// This class records the content_rect into an SkPicture. Subclass provides -// SkCanvas to DrawPicture() for tile updating based on this recorded picture. -class SkPictureContentLayerUpdater : public ContentLayerUpdater { - protected: - SkPictureContentLayerUpdater( - scoped_ptr<LayerPainter> painter, - int layer_id); - ~SkPictureContentLayerUpdater() override; - - void PrepareToUpdate(const gfx::Size& content_size, - const gfx::Rect& paint_rect, - const gfx::Size& tile_size, - float contents_width_scale, - float contents_height_scale) override; - void DrawPicture(SkCanvas* canvas); - - private: - skia::RefPtr<SkPicture> picture_; - - DISALLOW_COPY_AND_ASSIGN(SkPictureContentLayerUpdater); -}; - -} // namespace cc - -#endif // CC_RESOURCES_SKPICTURE_CONTENT_LAYER_UPDATER_H_ diff --git a/chromium/cc/resources/texture_mailbox.cc b/chromium/cc/resources/texture_mailbox.cc index 9bf242e1d7c..7e4dd29708c 100644 --- a/chromium/cc/resources/texture_mailbox.cc +++ b/chromium/cc/resources/texture_mailbox.cc @@ -28,15 +28,28 @@ TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox, nearest_neighbor_(false) { } +TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox, + uint32 target, + uint32 sync_point, + const gfx::Size& size_in_pixels, + bool allow_overlay) + : mailbox_holder_(mailbox, target, sync_point), + shared_bitmap_(nullptr), + size_in_pixels_(size_in_pixels), + allow_overlay_(allow_overlay), + nearest_neighbor_(false) { + DCHECK_IMPLIES(allow_overlay, !size_in_pixels.IsEmpty()); +} + TextureMailbox::TextureMailbox(SharedBitmap* shared_bitmap, - const gfx::Size& size) + const gfx::Size& size_in_pixels) : shared_bitmap_(shared_bitmap), - shared_memory_size_(size), + size_in_pixels_(size_in_pixels), allow_overlay_(false), nearest_neighbor_(false) { // If an embedder of cc gives an invalid TextureMailbox, we should crash // here to identify the offender. - CHECK(SharedBitmap::VerifySizeInBytes(shared_memory_size_)); + CHECK(SharedBitmap::VerifySizeInBytes(size_in_pixels_)); } TextureMailbox::~TextureMailbox() {} @@ -57,7 +70,7 @@ bool TextureMailbox::Equals(const TextureMailbox& other) const { size_t TextureMailbox::SharedMemorySizeInBytes() const { // UncheckedSizeInBytes is okay because we VerifySizeInBytes in the // constructor and the field is immutable. - return SharedBitmap::UncheckedSizeInBytes(shared_memory_size_); + return SharedBitmap::UncheckedSizeInBytes(size_in_pixels_); } } // namespace cc diff --git a/chromium/cc/resources/texture_mailbox.h b/chromium/cc/resources/texture_mailbox.h index cec60cedaca..47e71acb199 100644 --- a/chromium/cc/resources/texture_mailbox.h +++ b/chromium/cc/resources/texture_mailbox.h @@ -22,7 +22,12 @@ class CC_EXPORT TextureMailbox { TextureMailbox(); explicit TextureMailbox(const gpu::MailboxHolder& mailbox_holder); TextureMailbox(const gpu::Mailbox& mailbox, uint32 target, uint32 sync_point); - TextureMailbox(SharedBitmap* shared_bitmap, const gfx::Size& size); + TextureMailbox(const gpu::Mailbox& mailbox, + uint32 target, + uint32 sync_point, + const gfx::Size& size_in_pixels, + bool allow_overlay); + TextureMailbox(SharedBitmap* shared_bitmap, const gfx::Size& size_in_pixels); ~TextureMailbox(); @@ -41,20 +46,21 @@ class CC_EXPORT TextureMailbox { } bool allow_overlay() const { return allow_overlay_; } - void set_allow_overlay(bool allow_overlay) { allow_overlay_ = allow_overlay; } bool nearest_neighbor() const { return nearest_neighbor_; } void set_nearest_neighbor(bool nearest_neighbor) { nearest_neighbor_ = nearest_neighbor; } + // This is valid if allow_overlau() or IsSharedMemory() is true. + gfx::Size size_in_pixels() const { return size_in_pixels_; } + SharedBitmap* shared_bitmap() const { return shared_bitmap_; } - gfx::Size shared_memory_size() const { return shared_memory_size_; } size_t SharedMemorySizeInBytes() const; private: gpu::MailboxHolder mailbox_holder_; SharedBitmap* shared_bitmap_; - gfx::Size shared_memory_size_; + gfx::Size size_in_pixels_; bool allow_overlay_; bool nearest_neighbor_; }; diff --git a/chromium/cc/resources/texture_uploader.cc b/chromium/cc/resources/texture_uploader.cc deleted file mode 100644 index 89271bdcb54..00000000000 --- a/chromium/cc/resources/texture_uploader.cc +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/resources/texture_uploader.h" - -#include <algorithm> -#include <vector> - -#include "base/metrics/histogram.h" -#include "base/trace_event/trace_event.h" -#include "cc/base/util.h" -#include "cc/resources/resource.h" -#include "gpu/GLES2/gl2extchromium.h" -#include "gpu/command_buffer/client/gles2_interface.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/vector2d.h" - -using gpu::gles2::GLES2Interface; - -namespace { - -// How many previous uploads to use when predicting future throughput. -static const size_t kUploadHistorySizeMax = 1000; -static const size_t kUploadHistorySizeInitial = 100; - -// Global estimated number of textures per second to maintain estimates across -// subsequent instances of TextureUploader. -// More than one thread will not access this variable, so we do not need to -// synchronize access. -static const double kDefaultEstimatedTexturesPerSecond = 48.0 * 60.0; - -// Flush interval when performing texture uploads. -static const size_t kTextureUploadFlushPeriod = 4; - -} // anonymous namespace - -namespace cc { - -TextureUploader::Query::Query(GLES2Interface* gl) - : gl_(gl), - query_id_(0), - value_(0), - has_value_(false), - is_non_blocking_(false) { - gl_->GenQueriesEXT(1, &query_id_); -} - -TextureUploader::Query::~Query() { gl_->DeleteQueriesEXT(1, &query_id_); } - -void TextureUploader::Query::Begin() { - has_value_ = false; - is_non_blocking_ = false; - gl_->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query_id_); -} - -void TextureUploader::Query::End() { - gl_->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); -} - -bool TextureUploader::Query::IsPending() { - unsigned available = 1; - gl_->GetQueryObjectuivEXT( - query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available); - return !available; -} - -unsigned TextureUploader::Query::Value() { - if (!has_value_) { - gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &value_); - has_value_ = true; - } - return value_; -} - -TextureUploader::TextureUploader(GLES2Interface* gl) - : gl_(gl), - num_blocking_texture_uploads_(0), - sub_image_size_(0), - num_texture_uploads_since_last_flush_(0) { - for (size_t i = kUploadHistorySizeInitial; i > 0; i--) - textures_per_second_history_.insert(kDefaultEstimatedTexturesPerSecond); -} - -TextureUploader::~TextureUploader() {} - -size_t TextureUploader::NumBlockingUploads() { - ProcessQueries(); - return num_blocking_texture_uploads_; -} - -void TextureUploader::MarkPendingUploadsAsNonBlocking() { - for (ScopedPtrDeque<Query>::iterator it = pending_queries_.begin(); - it != pending_queries_.end(); - ++it) { - if ((*it)->is_non_blocking()) - continue; - - num_blocking_texture_uploads_--; - (*it)->mark_as_non_blocking(); - } - - DCHECK(!num_blocking_texture_uploads_); -} - -double TextureUploader::EstimatedTexturesPerSecond() { - ProcessQueries(); - - // Use the median as our estimate. - std::multiset<double>::iterator median = textures_per_second_history_.begin(); - std::advance(median, textures_per_second_history_.size() / 2); - return *median; -} - -void TextureUploader::BeginQuery() { - // Check to see if any of the pending queries are free before allocating a - // new one. If this is not done, queries may be allocated without bound. - // http://crbug.com/398072 - if (available_queries_.empty()) - ProcessQueries(); - - if (available_queries_.empty()) - available_queries_.push_back(Query::Create(gl_)); - - available_queries_.front()->Begin(); -} - -void TextureUploader::EndQuery() { - available_queries_.front()->End(); - pending_queries_.push_back(available_queries_.take_front()); - num_blocking_texture_uploads_++; -} - -void TextureUploader::Upload(const uint8* image, - const gfx::Rect& image_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - ResourceFormat format, - const gfx::Size& size) { - CHECK(image_rect.Contains(source_rect)); - - bool is_full_upload = dest_offset.IsZero() && source_rect.size() == size; - - if (is_full_upload) - BeginQuery(); - - UploadWithMapTexSubImage(image, image_rect, source_rect, dest_offset, format); - - if (is_full_upload) - EndQuery(); - - num_texture_uploads_since_last_flush_++; - if (num_texture_uploads_since_last_flush_ >= kTextureUploadFlushPeriod) - Flush(); -} - -void TextureUploader::Flush() { - if (!num_texture_uploads_since_last_flush_) - return; - - gl_->ShallowFlushCHROMIUM(); - - num_texture_uploads_since_last_flush_ = 0; -} - -void TextureUploader::ReleaseCachedQueries() { - ProcessQueries(); - available_queries_.clear(); -} - -void TextureUploader::UploadWithTexSubImage(const uint8* image, - const gfx::Rect& image_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - ResourceFormat format) { - TRACE_EVENT0("cc", "TextureUploader::UploadWithTexSubImage"); - - // Early-out if this is a no-op, and assert that |image| be valid if this is - // not a no-op. - if (source_rect.IsEmpty()) - return; - DCHECK(image); - - // Offset from image-rect to source-rect. - gfx::Vector2d offset(source_rect.origin() - image_rect.origin()); - - const uint8* pixel_source; - unsigned bytes_per_pixel = BitsPerPixel(format) / 8; - // Use 4-byte row alignment (OpenGL default) for upload performance. - // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. - unsigned upload_image_stride = - RoundUp(bytes_per_pixel * source_rect.width(), 4u); - - if (upload_image_stride == image_rect.width() * bytes_per_pixel && - !offset.x()) { - pixel_source = &image[image_rect.width() * bytes_per_pixel * offset.y()]; - } else { - size_t needed_size = upload_image_stride * source_rect.height(); - if (sub_image_size_ < needed_size) { - sub_image_.reset(new uint8[needed_size]); - sub_image_size_ = needed_size; - } - // Strides not equal, so do a row-by-row memcpy from the - // paint results into a temp buffer for uploading. - for (int row = 0; row < source_rect.height(); ++row) - memcpy(&sub_image_[upload_image_stride * row], - &image[bytes_per_pixel * - (offset.x() + (offset.y() + row) * image_rect.width())], - source_rect.width() * bytes_per_pixel); - - pixel_source = &sub_image_[0]; - } - - gl_->TexSubImage2D(GL_TEXTURE_2D, - 0, - dest_offset.x(), - dest_offset.y(), - source_rect.width(), - source_rect.height(), - GLDataFormat(format), - GLDataType(format), - pixel_source); -} - -void TextureUploader::UploadWithMapTexSubImage(const uint8* image, - const gfx::Rect& image_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - ResourceFormat format) { - TRACE_EVENT0("cc", "TextureUploader::UploadWithMapTexSubImage"); - - // Early-out if this is a no-op, and assert that |image| be valid if this is - // not a no-op. - if (source_rect.IsEmpty()) - return; - DCHECK(image); - // Compressed textures have no implementation of mapTexSubImage. - DCHECK_NE(ETC1, format); - - // Offset from image-rect to source-rect. - gfx::Vector2d offset(source_rect.origin() - image_rect.origin()); - - unsigned bytes_per_pixel = BitsPerPixel(format) / 8; - // Use 4-byte row alignment (OpenGL default) for upload performance. - // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. - unsigned upload_image_stride = - RoundUp(bytes_per_pixel * source_rect.width(), 4u); - - // Upload tile data via a mapped transfer buffer - uint8* pixel_dest = - static_cast<uint8*>(gl_->MapTexSubImage2DCHROMIUM(GL_TEXTURE_2D, - 0, - dest_offset.x(), - dest_offset.y(), - source_rect.width(), - source_rect.height(), - GLDataFormat(format), - GLDataType(format), - GL_WRITE_ONLY)); - - if (!pixel_dest) { - UploadWithTexSubImage(image, image_rect, source_rect, dest_offset, format); - return; - } - - if (upload_image_stride == image_rect.width() * bytes_per_pixel && - !offset.x()) { - memcpy(pixel_dest, - &image[image_rect.width() * bytes_per_pixel * offset.y()], - source_rect.height() * image_rect.width() * bytes_per_pixel); - } else { - // Strides not equal, so do a row-by-row memcpy from the - // paint results into the pixel_dest. - for (int row = 0; row < source_rect.height(); ++row) { - memcpy(&pixel_dest[upload_image_stride * row], - &image[bytes_per_pixel * - (offset.x() + (offset.y() + row) * image_rect.width())], - source_rect.width() * bytes_per_pixel); - } - } - - gl_->UnmapTexSubImage2DCHROMIUM(pixel_dest); -} - -void TextureUploader::ProcessQueries() { - while (!pending_queries_.empty()) { - if (pending_queries_.front()->IsPending()) - break; - - unsigned us_elapsed = pending_queries_.front()->Value(); - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Renderer4.TextureGpuUploadTimeUS", us_elapsed, 0, 100000, 50); - - // Clamp the queries to saner values in case the queries fail. - us_elapsed = std::max(1u, us_elapsed); - us_elapsed = std::min(15000u, us_elapsed); - - if (!pending_queries_.front()->is_non_blocking()) - num_blocking_texture_uploads_--; - - // Remove the min and max value from our history and insert the new one. - double textures_per_second = 1.0 / (us_elapsed * 1e-6); - if (textures_per_second_history_.size() >= kUploadHistorySizeMax) { - textures_per_second_history_.erase(textures_per_second_history_.begin()); - textures_per_second_history_.erase(--textures_per_second_history_.end()); - } - textures_per_second_history_.insert(textures_per_second); - - available_queries_.push_back(pending_queries_.take_front()); - } -} - -} // namespace cc diff --git a/chromium/cc/resources/texture_uploader.h b/chromium/cc/resources/texture_uploader.h deleted file mode 100644 index ae834083e72..00000000000 --- a/chromium/cc/resources/texture_uploader.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_TEXTURE_UPLOADER_H_ -#define CC_RESOURCES_TEXTURE_UPLOADER_H_ - -#include <set> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "cc/base/cc_export.h" -#include "cc/base/scoped_ptr_deque.h" -#include "cc/resources/resource_provider.h" - -namespace gfx { -class Rect; -class Size; -class Vector2d; -} - -namespace gpu { -namespace gles2 { -class GLES2Interface; -} -} - -namespace cc { - -class CC_EXPORT TextureUploader { - public: - static scoped_ptr<TextureUploader> Create(gpu::gles2::GLES2Interface* gl) { - return make_scoped_ptr(new TextureUploader(gl)); - } - ~TextureUploader(); - - size_t NumBlockingUploads(); - void MarkPendingUploadsAsNonBlocking(); - double EstimatedTexturesPerSecond(); - - // Let content_rect be a rectangle, and let content_rect be a sub-rectangle of - // content_rect, expressed in the same coordinate system as content_rect. Let - // image be a buffer for content_rect. This function will copy the region - // corresponding to source_rect to dest_offset in this sub-image. - void Upload(const uint8* image, - const gfx::Rect& content_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - ResourceFormat format, - const gfx::Size& size); - - void Flush(); - void ReleaseCachedQueries(); - - private: - class Query { - public: - static scoped_ptr<Query> Create(gpu::gles2::GLES2Interface* gl) { - return make_scoped_ptr(new Query(gl)); - } - - virtual ~Query(); - - void Begin(); - void End(); - bool IsPending(); - unsigned Value(); - size_t TexturesUploaded(); - void mark_as_non_blocking() { is_non_blocking_ = true; } - bool is_non_blocking() const { return is_non_blocking_; } - - private: - explicit Query(gpu::gles2::GLES2Interface* gl); - - gpu::gles2::GLES2Interface* gl_; - unsigned query_id_; - unsigned value_; - bool has_value_; - bool is_non_blocking_; - - DISALLOW_COPY_AND_ASSIGN(Query); - }; - - explicit TextureUploader(gpu::gles2::GLES2Interface* gl); - - void BeginQuery(); - void EndQuery(); - void ProcessQueries(); - - void UploadWithTexSubImage(const uint8* image, - const gfx::Rect& image_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - ResourceFormat format); - void UploadWithMapTexSubImage(const uint8* image, - const gfx::Rect& image_rect, - const gfx::Rect& source_rect, - const gfx::Vector2d& dest_offset, - ResourceFormat format); - void UploadWithTexImageETC1(const uint8* image, const gfx::Size& size); - - gpu::gles2::GLES2Interface* gl_; - ScopedPtrDeque<Query> pending_queries_; - ScopedPtrDeque<Query> available_queries_; - std::multiset<double> textures_per_second_history_; - size_t num_blocking_texture_uploads_; - - size_t sub_image_size_; - scoped_ptr<uint8[]> sub_image_; - - size_t num_texture_uploads_since_last_flush_; - - DISALLOW_COPY_AND_ASSIGN(TextureUploader); -}; - -} // namespace cc - -#endif // CC_RESOURCES_TEXTURE_UPLOADER_H_ diff --git a/chromium/cc/resources/texture_uploader_unittest.cc b/chromium/cc/resources/texture_uploader_unittest.cc deleted file mode 100644 index b1689627d1f..00000000000 --- a/chromium/cc/resources/texture_uploader_unittest.cc +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/resources/texture_uploader.h" - -#include "cc/base/util.h" -#include "cc/resources/prioritized_resource.h" -#include "gpu/command_buffer/client/gles2_interface_stub.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" - -namespace cc { -namespace { - -class TextureUploadTestContext : public gpu::gles2::GLES2InterfaceStub { - public: - TextureUploadTestContext() : result_available_(0), unpack_alignment_(4) {} - - void PixelStorei(GLenum pname, GLint param) override { - switch (pname) { - case GL_UNPACK_ALIGNMENT: - // Param should be a power of two <= 8. - EXPECT_EQ(0, param & (param - 1)); - EXPECT_GE(8, param); - switch (param) { - case 1: - case 2: - case 4: - case 8: - unpack_alignment_ = param; - break; - default: - break; - } - break; - default: - break; - } - } - - void GetQueryObjectuivEXT(GLuint, GLenum type, GLuint* value) override { - switch (type) { - case GL_QUERY_RESULT_AVAILABLE_EXT: - *value = result_available_; - break; - default: - *value = 0; - break; - } - } - - void TexSubImage2D(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void* pixels) override { - EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); - EXPECT_EQ(0, level); - EXPECT_LE(0, width); - EXPECT_LE(0, height); - EXPECT_LE(0, xoffset); - EXPECT_LE(0, yoffset); - EXPECT_LE(0, width); - EXPECT_LE(0, height); - - // Check for allowed format/type combination. - unsigned int bytes_per_pixel = 0; - switch (format) { - case GL_ALPHA: - EXPECT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); - bytes_per_pixel = 1; - break; - case GL_RGB: - EXPECT_NE(static_cast<unsigned>(GL_UNSIGNED_SHORT_4_4_4_4), type); - EXPECT_NE(static_cast<unsigned>(GL_UNSIGNED_SHORT_5_5_5_1), type); - switch (type) { - case GL_UNSIGNED_BYTE: - bytes_per_pixel = 3; - break; - case GL_UNSIGNED_SHORT_5_6_5: - bytes_per_pixel = 2; - break; - } - break; - case GL_RGBA: - EXPECT_NE(static_cast<unsigned>(GL_UNSIGNED_SHORT_5_6_5), type); - switch (type) { - case GL_UNSIGNED_BYTE: - bytes_per_pixel = 4; - break; - case GL_UNSIGNED_SHORT_4_4_4_4: - bytes_per_pixel = 2; - break; - case GL_UNSIGNED_SHORT_5_5_5_1: - bytes_per_pixel = 2; - break; - } - break; - case GL_LUMINANCE: - EXPECT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); - bytes_per_pixel = 1; - break; - case GL_LUMINANCE_ALPHA: - EXPECT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); - bytes_per_pixel = 2; - break; - case GL_RED_EXT: - EXPECT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); - bytes_per_pixel = 1; - break; - case GL_RG_EXT: - EXPECT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); - bytes_per_pixel = 2; - break; - } - - // If NULL, we aren't checking texture contents. - if (pixels == NULL) - return; - - const uint8* bytes = static_cast<const uint8*>(pixels); - // We'll expect the first byte of every row to be 0x1, and the last byte to - // be 0x2. - const unsigned int stride = - RoundUp(bytes_per_pixel * width, unpack_alignment_); - for (GLsizei row = 0; row < height; ++row) { - const uint8* row_bytes = - bytes + (xoffset * bytes_per_pixel + (yoffset + row) * stride); - EXPECT_EQ(0x1, row_bytes[0]); - EXPECT_EQ(0x2, row_bytes[width * bytes_per_pixel - 1]); - } - } - - void SetResultAvailable(unsigned result_available) { - result_available_ = result_available; - } - - private: - unsigned result_available_; - unsigned unpack_alignment_; - - DISALLOW_COPY_AND_ASSIGN(TextureUploadTestContext); -}; - -void UploadTexture(TextureUploader* uploader, - ResourceFormat format, - const gfx::Size& size, - const uint8* data) { - uploader->Upload( - data, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(), format, size); -} - -TEST(TextureUploaderTest, NumBlockingUploads) { - TextureUploadTestContext context; - scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context); - - context.SetResultAvailable(0); - EXPECT_EQ(0u, uploader->NumBlockingUploads()); - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); - EXPECT_EQ(1u, uploader->NumBlockingUploads()); - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); - EXPECT_EQ(2u, uploader->NumBlockingUploads()); - - context.SetResultAvailable(1); - EXPECT_EQ(0u, uploader->NumBlockingUploads()); - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); - EXPECT_EQ(0u, uploader->NumBlockingUploads()); - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); - EXPECT_EQ(0u, uploader->NumBlockingUploads()); -} - -TEST(TextureUploaderTest, MarkPendingUploadsAsNonBlocking) { - TextureUploadTestContext context; - scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context); - - context.SetResultAvailable(0); - EXPECT_EQ(0u, uploader->NumBlockingUploads()); - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); - EXPECT_EQ(2u, uploader->NumBlockingUploads()); - - uploader->MarkPendingUploadsAsNonBlocking(); - EXPECT_EQ(0u, uploader->NumBlockingUploads()); - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); - EXPECT_EQ(1u, uploader->NumBlockingUploads()); - - context.SetResultAvailable(1); - EXPECT_EQ(0u, uploader->NumBlockingUploads()); - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); - uploader->MarkPendingUploadsAsNonBlocking(); - EXPECT_EQ(0u, uploader->NumBlockingUploads()); -} - -TEST(TextureUploaderTest, UploadContentsTest) { - TextureUploadTestContext context; - scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context); - - uint8 buffer[256 * 256 * 4]; - - // Upload a tightly packed 256x256 RGBA texture. - memset(buffer, 0, sizeof(buffer)); - for (int i = 0; i < 256; ++i) { - // Mark the beginning and end of each row, for the test. - buffer[i * 4 * 256] = 0x1; - buffer[(i + 1) * 4 * 256 - 1] = 0x2; - } - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(256, 256), buffer); - - // Upload a tightly packed 41x43 RGBA texture. - memset(buffer, 0, sizeof(buffer)); - for (int i = 0; i < 43; ++i) { - // Mark the beginning and end of each row, for the test. - buffer[i * 4 * 41] = 0x1; - buffer[(i + 1) * 4 * 41 - 1] = 0x2; - } - UploadTexture(uploader.get(), RGBA_8888, gfx::Size(41, 43), buffer); - - // Upload a tightly packed 41x86 ALPHA texture. - memset(buffer, 0, sizeof(buffer)); - for (int i = 0; i < 86; ++i) { - // Mark the beginning and end of each row, for the test. - buffer[i * 1 * 41] = 0x1; - buffer[(i + 1) * 41 - 1] = 0x2; - } - UploadTexture(uploader.get(), ALPHA_8, gfx::Size(41, 86), buffer); - - // Upload a tightly packed 82x86 LUMINANCE texture. - memset(buffer, 0, sizeof(buffer)); - for (int i = 0; i < 86; ++i) { - // Mark the beginning and end of each row, for the test. - buffer[i * 1 * 82] = 0x1; - buffer[(i + 1) * 82 - 1] = 0x2; - } - UploadTexture(uploader.get(), LUMINANCE_8, gfx::Size(82, 86), buffer); - - // Upload a tightly packed 82x86 RED texture. - memset(buffer, 0, sizeof(buffer)); - for (int i = 0; i < 86; ++i) { - // Mark the beginning and end of each row, for the test. - buffer[i * 1 * 82] = 0x1; - buffer[(i + 1) * 82 - 1] = 0x2; - } - UploadTexture(uploader.get(), RED_8, gfx::Size(82, 86), buffer); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/resources/transferable_resource.cc b/chromium/cc/resources/transferable_resource.cc index 558d6e87728..89771a78146 100644 --- a/chromium/cc/resources/transferable_resource.cc +++ b/chromium/cc/resources/transferable_resource.cc @@ -11,6 +11,7 @@ TransferableResource::TransferableResource() : id(0), format(RGBA_8888), filter(0), + read_lock_fences_enabled(false), is_repeated(false), is_software(false), allow_overlay(false) { diff --git a/chromium/cc/resources/transferable_resource.h b/chromium/cc/resources/transferable_resource.h index 03b47e616c8..6f38a62f7fc 100644 --- a/chromium/cc/resources/transferable_resource.h +++ b/chromium/cc/resources/transferable_resource.h @@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "cc/base/cc_export.h" +#include "cc/base/resource_id.h" #include "cc/resources/resource_format.h" #include "gpu/command_buffer/common/mailbox_holder.h" #include "ui/gfx/geometry/size.h" @@ -28,11 +29,12 @@ struct CC_EXPORT TransferableResource { static void ReturnResources(const TransferableResourceArray& input, ReturnedResourceArray* output); - unsigned id; + ResourceId id; ResourceFormat format; uint32 filter; gfx::Size size; gpu::MailboxHolder mailbox_holder; + bool read_lock_fences_enabled; bool is_repeated; bool is_software; bool allow_overlay; diff --git a/chromium/cc/resources/ui_resource_bitmap.cc b/chromium/cc/resources/ui_resource_bitmap.cc index e254cf71614..b5a84b93db2 100644 --- a/chromium/cc/resources/ui_resource_bitmap.cc +++ b/chromium/cc/resources/ui_resource_bitmap.cc @@ -54,8 +54,7 @@ UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap) { skia::RefPtr<SkPixelRef> pixel_ref = skia::SharePtr(skbitmap.pixelRef()); const SkImageInfo& info = pixel_ref->info(); - Create(pixel_ref, - gfx::Size(info.fWidth, info.fHeight), + Create(pixel_ref, gfx::Size(info.width(), info.height()), SkColorTypeToUIResourceFormat(skbitmap.colorType())); SetOpaque(skbitmap.isOpaque()); diff --git a/chromium/cc/resources/video_resource_updater.cc b/chromium/cc/resources/video_resource_updater.cc index 06fb6929c95..e973a3d5240 100644 --- a/chromium/cc/resources/video_resource_updater.cc +++ b/chromium/cc/resources/video_resource_updater.cc @@ -8,7 +8,7 @@ #include "base/bind.h" #include "base/trace_event/trace_event.h" -#include "cc/base/util.h" +#include "cc/base/math_util.h" #include "cc/output/gl_renderer.h" #include "cc/resources/resource_provider.h" #include "gpu/GLES2/gl2extchromium.h" @@ -64,13 +64,13 @@ VideoResourceUpdater::PlaneResource::PlaneResource( mailbox(mailbox), ref_count(0), frame_ptr(nullptr), - plane_index(0) { + plane_index(0u) { } bool VideoResourceUpdater::PlaneResourceMatchesUniqueID( const PlaneResource& plane_resource, const media::VideoFrame* video_frame, - int plane_index) { + size_t plane_index) { return plane_resource.frame_ptr == video_frame && plane_resource.plane_index == plane_index && plane_resource.timestamp == video_frame->timestamp(); @@ -78,14 +78,16 @@ bool VideoResourceUpdater::PlaneResourceMatchesUniqueID( void VideoResourceUpdater::SetPlaneResourceUniqueId( const media::VideoFrame* video_frame, - int plane_index, + size_t plane_index, PlaneResource* plane_resource) { plane_resource->frame_ptr = video_frame; plane_resource->plane_index = plane_index; plane_resource->timestamp = video_frame->timestamp(); } -VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE) {} +VideoFrameExternalResources::VideoFrameExternalResources() + : type(NONE), read_lock_fences_enabled(false) { +} VideoFrameExternalResources::~VideoFrameExternalResources() {} @@ -106,10 +108,9 @@ VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size, bool has_mailbox) { // TODO(danakj): Abstract out hw/sw resource create/delete from // ResourceProvider and stop using ResourceProvider in this class. - const ResourceProvider::ResourceId resource_id = - resource_provider_->CreateResource( - plane_size, GL_CLAMP_TO_EDGE, - ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + const ResourceId resource_id = resource_provider_->CreateResource( + plane_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, + format); if (resource_id == 0) return all_resources_.end(); @@ -138,41 +139,15 @@ void VideoResourceUpdater::DeleteResource(ResourceList::iterator resource_it) { VideoFrameExternalResources VideoResourceUpdater:: CreateExternalResourcesFromVideoFrame( const scoped_refptr<media::VideoFrame>& video_frame) { - if (!VerifyFrame(video_frame)) + if (video_frame->format() == media::VideoFrame::UNKNOWN) return VideoFrameExternalResources(); - - if (video_frame->format() == media::VideoFrame::NATIVE_TEXTURE) + DCHECK(video_frame->HasTextures() || video_frame->IsMappable()); + if (video_frame->HasTextures()) return CreateForHardwarePlanes(video_frame); else return CreateForSoftwarePlanes(video_frame); } -bool VideoResourceUpdater::VerifyFrame( - const scoped_refptr<media::VideoFrame>& video_frame) { - switch (video_frame->format()) { - // Acceptable inputs. - case media::VideoFrame::YV12: - case media::VideoFrame::I420: - case media::VideoFrame::YV12A: - case media::VideoFrame::YV16: - case media::VideoFrame::YV12J: - case media::VideoFrame::YV12HD: - case media::VideoFrame::YV24: - case media::VideoFrame::NATIVE_TEXTURE: -#if defined(VIDEO_HOLE) - case media::VideoFrame::HOLE: -#endif // defined(VIDEO_HOLE) - case media::VideoFrame::ARGB: - return true; - - // Unacceptable inputs. ¯\(°_o)/¯ - case media::VideoFrame::UNKNOWN: - case media::VideoFrame::NV12: - break; - } - return false; -} - // For frames that we receive in software format, determine the dimensions of // each plane in the frame. static gfx::Size SoftwarePlaneDimension( @@ -189,10 +164,10 @@ static gfx::Size SoftwarePlaneDimension( VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( const scoped_refptr<media::VideoFrame>& video_frame) { TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); - media::VideoFrame::Format input_frame_format = video_frame->format(); + const media::VideoFrame::Format input_frame_format = video_frame->format(); #if defined(VIDEO_HOLE) - if (input_frame_format == media::VideoFrame::HOLE) { + if (video_frame->storage_type() == media::VideoFrame::STORAGE_HOLE) { VideoFrameExternalResources external_resources; external_resources.type = VideoFrameExternalResources::HOLE; return external_resources; @@ -200,18 +175,12 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( #endif // defined(VIDEO_HOLE) // Only YUV software video frames are supported. - if (input_frame_format != media::VideoFrame::YV12 && - input_frame_format != media::VideoFrame::I420 && - input_frame_format != media::VideoFrame::YV12A && - input_frame_format != media::VideoFrame::YV12J && - input_frame_format != media::VideoFrame::YV12HD && - input_frame_format != media::VideoFrame::YV16 && - input_frame_format != media::VideoFrame::YV24) { - NOTREACHED() << input_frame_format; + if (!media::VideoFrame::IsYuvPlanar(input_frame_format)) { + NOTREACHED() << media::VideoFrame::FormatToString(input_frame_format); return VideoFrameExternalResources(); } - bool software_compositor = context_provider_ == NULL; + const bool software_compositor = context_provider_ == NULL; ResourceFormat output_resource_format = resource_provider_->yuv_resource_format(); @@ -341,8 +310,8 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( size_t bytes_per_pixel = BitsPerPixel(plane_resource.resource_format) / 8; // Use 4-byte row alignment (OpenGL default) for upload performance. // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. - size_t upload_image_stride = - RoundUp<size_t>(bytes_per_pixel * resource_size_pixels.width(), 4u); + size_t upload_image_stride = MathUtil::RoundUp<size_t>( + bytes_per_pixel * resource_size_pixels.width(), 4u); const uint8_t* pixels; if (upload_image_stride == video_stride_pixels * bytes_per_pixel) { @@ -399,27 +368,24 @@ void VideoResourceUpdater::ReturnTexture( VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( const scoped_refptr<media::VideoFrame>& video_frame) { TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForHardwarePlanes"); - media::VideoFrame::Format frame_format = video_frame->format(); - - DCHECK_EQ(frame_format, media::VideoFrame::NATIVE_TEXTURE); + DCHECK(video_frame->HasTextures()); if (!context_provider_) return VideoFrameExternalResources(); - size_t textures = - media::VideoFrame::NumTextures(video_frame->texture_format()); + const size_t textures = media::VideoFrame::NumPlanes(video_frame->format()); DCHECK_GE(textures, 1u); VideoFrameExternalResources external_resources; - switch (video_frame->texture_format()) { - case media::VideoFrame::TEXTURE_RGBA: - case media::VideoFrame::TEXTURE_RGB: + external_resources.read_lock_fences_enabled = true; + switch (video_frame->format()) { + case media::VideoFrame::ARGB: + case media::VideoFrame::XRGB: DCHECK_EQ(1u, textures); switch (video_frame->mailbox_holder(0).texture_target) { case GL_TEXTURE_2D: - if (video_frame->texture_format() == media::VideoFrame::TEXTURE_RGB) - external_resources.type = VideoFrameExternalResources::RGB_RESOURCE; - else - external_resources.type = - VideoFrameExternalResources::RGBA_RESOURCE; + external_resources.type = + (video_frame->format() == media::VideoFrame::XRGB) + ? VideoFrameExternalResources::RGB_RESOURCE + : VideoFrameExternalResources::RGBA_RESOURCE; break; case GL_TEXTURE_EXTERNAL_OES: external_resources.type = @@ -433,9 +399,20 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( return VideoFrameExternalResources(); } break; - case media::VideoFrame::TEXTURE_YUV_420: + case media::VideoFrame::I420: external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; break; +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) + case media::VideoFrame::NV12: +#endif + case media::VideoFrame::YV12: + case media::VideoFrame::YV16: + case media::VideoFrame::YV24: + case media::VideoFrame::YV12A: + case media::VideoFrame::UNKNOWN: + DLOG(ERROR) << "Unsupported Texture format" + << media::VideoFrame::FormatToString(video_frame->format()); + return external_resources; } DCHECK_NE(VideoFrameExternalResources::NONE, external_resources.type); @@ -443,9 +420,9 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i); external_resources.mailboxes.push_back( TextureMailbox(mailbox_holder.mailbox, mailbox_holder.texture_target, - mailbox_holder.sync_point)); - external_resources.mailboxes.back().set_allow_overlay( - video_frame->allow_overlay()); + mailbox_holder.sync_point, video_frame->coded_size(), + video_frame->metadata()->IsTrue( + media::VideoFrameMetadata::ALLOW_OVERLAY))); external_resources.release_callbacks.push_back( base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); } @@ -455,7 +432,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( // static void VideoResourceUpdater::RecycleResource( base::WeakPtr<VideoResourceUpdater> updater, - ResourceProvider::ResourceId resource_id, + ResourceId resource_id, uint32 sync_point, bool lost_resource, BlockingTaskRunner* main_thread_task_runner) { diff --git a/chromium/cc/resources/video_resource_updater.h b/chromium/cc/resources/video_resource_updater.h index 13f81b8f06e..ad3d1abfb33 100644 --- a/chromium/cc/resources/video_resource_updater.h +++ b/chromium/cc/resources/video_resource_updater.h @@ -53,6 +53,7 @@ class CC_EXPORT VideoFrameExternalResources { ResourceType type; std::vector<TextureMailbox> mailboxes; std::vector<ReleaseCallbackImpl> release_callbacks; + bool read_lock_fences_enabled; // TODO(danakj): Remove these too. std::vector<unsigned> software_resources; @@ -88,7 +89,7 @@ class CC_EXPORT VideoResourceUpdater // frame pointer will only be used for pointer comparison, i.e. the // underlying data will not be accessed. const void* frame_ptr; - int plane_index; + size_t plane_index; base::TimeDelta timestamp; PlaneResource(unsigned resource_id, @@ -99,10 +100,10 @@ class CC_EXPORT VideoResourceUpdater static bool PlaneResourceMatchesUniqueID(const PlaneResource& plane_resource, const media::VideoFrame* video_frame, - int plane_index); + size_t plane_index); static void SetPlaneResourceUniqueId(const media::VideoFrame* video_frame, - int plane_index, + size_t plane_index, PlaneResource* plane_resource); // This needs to be a container where iterators can be erased without diff --git a/chromium/cc/resources/video_resource_updater_unittest.cc b/chromium/cc/resources/video_resource_updater_unittest.cc index 10f7fbdbbcf..3e4574d989c 100644 --- a/chromium/cc/resources/video_resource_updater_unittest.cc +++ b/chromium/cc/resources/video_resource_updater_unittest.cc @@ -8,6 +8,7 @@ #include "cc/resources/resource_provider.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_web_graphics_context_3d.h" #include "cc/trees/blocking_task_runner.h" @@ -71,18 +72,11 @@ class VideoResourceUpdaterTest : public testing::Test { CHECK(output_surface_software_->BindToClient(&client_)); shared_bitmap_manager_.reset(new SharedBitmapManagerAllocationCounter()); - resource_provider3d_ = - ResourceProvider::Create(output_surface3d_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1); - - resource_provider_software_ = ResourceProvider::Create( - output_surface_software_.get(), shared_bitmap_manager_.get(), NULL, - NULL, 0, false, 1); + resource_provider3d_ = FakeResourceProvider::Create( + output_surface3d_.get(), shared_bitmap_manager_.get()); + + resource_provider_software_ = FakeResourceProvider::Create( + output_surface_software_.get(), shared_bitmap_manager_.get()); } scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() { @@ -103,8 +97,7 @@ class VideoResourceUpdaterTest : public testing::Test { y_data, // y_data u_data, // u_data v_data, // v_data - base::TimeDelta(), // timestamp, - base::Closure()); // no_longer_needed_cb + base::TimeDelta()); // timestamp } static void ReleaseMailboxCB(unsigned sync_point) {} @@ -119,14 +112,13 @@ class VideoResourceUpdaterTest : public testing::Test { const unsigned sync_point = 7; const unsigned target = GL_TEXTURE_2D; return media::VideoFrame::WrapNativeTexture( + media::VideoFrame::ARGB, gpu::MailboxHolder(mailbox, target, sync_point), base::Bind(&ReleaseMailboxCB), - size, // coded_size - gfx::Rect(size), // visible_rect - size, // natural_size - base::TimeDelta(), // timestamp - false, // allow_overlay - true); // has_alpha + size, // coded_size + gfx::Rect(size), // visible_rect + size, // natural_size + base::TimeDelta()); // timestamp } scoped_refptr<media::VideoFrame> CreateTestYUVHardareVideoFrame() { @@ -148,11 +140,10 @@ class VideoResourceUpdaterTest : public testing::Test { gpu::MailboxHolder(mailbox[media::VideoFrame::kVPlane], target, sync_point), base::Bind(&ReleaseMailboxCB), - size, // coded_size - gfx::Rect(size), // visible_rect - size, // natural_size - base::TimeDelta(), // timestamp - false); // allow_overlay + size, // coded_size + gfx::Rect(size), // visible_rect + size, // natural_size + base::TimeDelta()); // timestamp } WebGraphicsContext3DUploadCounter* context3d_; @@ -318,6 +309,7 @@ TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes) { resources = updater.CreateExternalResourcesFromVideoFrame(video_frame); EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type); + EXPECT_TRUE(resources.read_lock_fences_enabled); EXPECT_EQ(3u, resources.mailboxes.size()); EXPECT_EQ(3u, resources.release_callbacks.size()); EXPECT_EQ(0u, resources.software_resources.size()); diff --git a/chromium/cc/scheduler/begin_frame_source.cc b/chromium/cc/scheduler/begin_frame_source.cc index 48d834359f4..d9cadc83e72 100644 --- a/chromium/cc/scheduler/begin_frame_source.cc +++ b/chromium/cc/scheduler/begin_frame_source.cc @@ -12,7 +12,6 @@ #include "base/trace_event/trace_event_argument.h" #include "cc/scheduler/delay_based_time_source.h" #include "cc/scheduler/scheduler.h" -#include "ui/gfx/frame_time.h" #ifdef NDEBUG #define DEBUG_FRAMES(...) @@ -28,23 +27,23 @@ namespace cc { -// BeginFrameObserverMixIn ----------------------------------------------- -BeginFrameObserverMixIn::BeginFrameObserverMixIn() +// BeginFrameObserverBase ----------------------------------------------- +BeginFrameObserverBase::BeginFrameObserverBase() : last_begin_frame_args_(), dropped_begin_frame_args_(0) { } -const BeginFrameArgs BeginFrameObserverMixIn::LastUsedBeginFrameArgs() const { +const BeginFrameArgs BeginFrameObserverBase::LastUsedBeginFrameArgs() const { return last_begin_frame_args_; } -void BeginFrameObserverMixIn::OnBeginFrame(const BeginFrameArgs& args) { - DEBUG_FRAMES("BeginFrameObserverMixIn::OnBeginFrame", +void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { + DEBUG_FRAMES("BeginFrameObserverBase::OnBeginFrame", "last args", last_begin_frame_args_.AsValue(), "new args", args.AsValue()); DCHECK(args.IsValid()); DCHECK(args.frame_time >= last_begin_frame_args_.frame_time); - bool used = OnBeginFrameMixInDelegate(args); + bool used = OnBeginFrameDerivedImpl(args); if (used) { last_begin_frame_args_ = args; } else { @@ -52,7 +51,7 @@ void BeginFrameObserverMixIn::OnBeginFrame(const BeginFrameArgs& args) { } } -void BeginFrameObserverMixIn::AsValueInto( +void BeginFrameObserverBase::AsValueInto( base::trace_event::TracedValue* dict) const { dict->BeginDictionary("last_begin_frame_args_"); last_begin_frame_args_.AsValueInto(dict); @@ -60,8 +59,8 @@ void BeginFrameObserverMixIn::AsValueInto( dict->SetInteger("dropped_begin_frame_args_", dropped_begin_frame_args_); } -// BeginFrameSourceMixIn ------------------------------------------------------ -BeginFrameSourceMixIn::BeginFrameSourceMixIn() +// BeginFrameSourceBase ------------------------------------------------------ +BeginFrameSourceBase::BeginFrameSourceBase() : observer_(NULL), needs_begin_frames_(false), inside_as_value_into_(false) { @@ -69,12 +68,12 @@ BeginFrameSourceMixIn::BeginFrameSourceMixIn() DCHECK_EQ(inside_as_value_into_, false); } -bool BeginFrameSourceMixIn::NeedsBeginFrames() const { +bool BeginFrameSourceBase::NeedsBeginFrames() const { return needs_begin_frames_; } -void BeginFrameSourceMixIn::SetNeedsBeginFrames(bool needs_begin_frames) { - DEBUG_FRAMES("BeginFrameSourceMixIn::SetNeedsBeginFrames", +void BeginFrameSourceBase::SetNeedsBeginFrames(bool needs_begin_frames) { + DEBUG_FRAMES("BeginFrameSourceBase::SetNeedsBeginFrames", "current state", needs_begin_frames_, "new state", @@ -85,8 +84,8 @@ void BeginFrameSourceMixIn::SetNeedsBeginFrames(bool needs_begin_frames) { } } -void BeginFrameSourceMixIn::AddObserver(BeginFrameObserver* obs) { - DEBUG_FRAMES("BeginFrameSourceMixIn::AddObserver", +void BeginFrameSourceBase::AddObserver(BeginFrameObserver* obs) { + DEBUG_FRAMES("BeginFrameSourceBase::AddObserver", "current observer", observer_, "to add observer", @@ -95,8 +94,8 @@ void BeginFrameSourceMixIn::AddObserver(BeginFrameObserver* obs) { observer_ = obs; } -void BeginFrameSourceMixIn::RemoveObserver(BeginFrameObserver* obs) { - DEBUG_FRAMES("BeginFrameSourceMixIn::RemoveObserver", +void BeginFrameSourceBase::RemoveObserver(BeginFrameObserver* obs) { + DEBUG_FRAMES("BeginFrameSourceBase::RemoveObserver", "current observer", observer_, "to remove observer", @@ -105,8 +104,8 @@ void BeginFrameSourceMixIn::RemoveObserver(BeginFrameObserver* obs) { observer_ = NULL; } -void BeginFrameSourceMixIn::CallOnBeginFrame(const BeginFrameArgs& args) { - DEBUG_FRAMES("BeginFrameSourceMixIn::CallOnBeginFrame", +void BeginFrameSourceBase::CallOnBeginFrame(const BeginFrameArgs& args) { + DEBUG_FRAMES("BeginFrameSourceBase::CallOnBeginFrame", "current observer", observer_, "args", @@ -117,7 +116,7 @@ void BeginFrameSourceMixIn::CallOnBeginFrame(const BeginFrameArgs& args) { } // Tracing support -void BeginFrameSourceMixIn::AsValueInto( +void BeginFrameSourceBase::AsValueInto( base::trace_event::TracedValue* dict) const { // As the observer might try to trace the source, prevent an infinte loop // from occuring. @@ -138,7 +137,7 @@ void BeginFrameSourceMixIn::AsValueInto( dict->SetBoolean("needs_begin_frames", NeedsBeginFrames()); } -// BackToBackBeginFrameSourceMixIn -------------------------------------------- +// BackToBackBeginFrameSource -------------------------------------------- scoped_ptr<BackToBackBeginFrameSource> BackToBackBeginFrameSource::Create( base::SingleThreadTaskRunner* task_runner) { return make_scoped_ptr(new BackToBackBeginFrameSource(task_runner)); @@ -146,7 +145,7 @@ scoped_ptr<BackToBackBeginFrameSource> BackToBackBeginFrameSource::Create( BackToBackBeginFrameSource::BackToBackBeginFrameSource( base::SingleThreadTaskRunner* task_runner) - : BeginFrameSourceMixIn(), + : BeginFrameSourceBase(), task_runner_(task_runner), send_begin_frame_posted_(false), weak_factory_(this) { @@ -159,7 +158,7 @@ BackToBackBeginFrameSource::~BackToBackBeginFrameSource() { } base::TimeTicks BackToBackBeginFrameSource::Now() { - return gfx::FrameTime::Now(); + return base::TimeTicks::Now(); } void BackToBackBeginFrameSource::OnNeedsBeginFramesChange( @@ -201,37 +200,28 @@ void BackToBackBeginFrameSource::DidFinishFrame(size_t remaining_frames) { void BackToBackBeginFrameSource::AsValueInto( base::trace_event::TracedValue* dict) const { dict->SetString("type", "BackToBackBeginFrameSource"); - BeginFrameSourceMixIn::AsValueInto(dict); + BeginFrameSourceBase::AsValueInto(dict); dict->SetBoolean("send_begin_frame_posted_", send_begin_frame_posted_); } // SyntheticBeginFrameSource --------------------------------------------- scoped_ptr<SyntheticBeginFrameSource> SyntheticBeginFrameSource::Create( base::SingleThreadTaskRunner* task_runner, - base::TimeTicks initial_vsync_timebase, base::TimeDelta initial_vsync_interval) { - scoped_refptr<DelayBasedTimeSource> time_source; - if (gfx::FrameTime::TimestampsAreHighRes()) { - time_source = DelayBasedTimeSourceHighRes::Create(initial_vsync_interval, - task_runner); - } else { - time_source = - DelayBasedTimeSource::Create(initial_vsync_interval, task_runner); - } - - return make_scoped_ptr(new SyntheticBeginFrameSource(time_source)); + scoped_ptr<DelayBasedTimeSource> time_source = + DelayBasedTimeSource::Create(initial_vsync_interval, task_runner); + return make_scoped_ptr(new SyntheticBeginFrameSource(time_source.Pass())); } SyntheticBeginFrameSource::SyntheticBeginFrameSource( - scoped_refptr<DelayBasedTimeSource> time_source) - : BeginFrameSourceMixIn(), time_source_(time_source) { + scoped_ptr<DelayBasedTimeSource> time_source) + : BeginFrameSourceBase(), time_source_(time_source.Pass()) { time_source_->SetActive(false); time_source_->SetClient(this); } SyntheticBeginFrameSource::~SyntheticBeginFrameSource() { - if (NeedsBeginFrames()) - time_source_->SetActive(false); + time_source_->SetActive(false); } void SyntheticBeginFrameSource::OnUpdateVSyncParameters( @@ -248,18 +238,19 @@ BeginFrameArgs SyntheticBeginFrameSource::CreateBeginFrameArgs( time_source_->Interval(), type); } -// TimeSourceClient support +// DelayBasedTimeSourceClient support void SyntheticBeginFrameSource::OnTimerTick() { CallOnBeginFrame(CreateBeginFrameArgs(time_source_->LastTickTime(), BeginFrameArgs::NORMAL)); } -// BeginFrameSourceMixIn support +// BeginFrameSourceBase support void SyntheticBeginFrameSource::OnNeedsBeginFramesChange( bool needs_begin_frames) { base::TimeTicks missed_tick_time = time_source_->SetActive(needs_begin_frames); if (!missed_tick_time.is_null()) { + DCHECK(needs_begin_frames); CallOnBeginFrame( CreateBeginFrameArgs(missed_tick_time, BeginFrameArgs::MISSED)); } @@ -269,7 +260,7 @@ void SyntheticBeginFrameSource::OnNeedsBeginFramesChange( void SyntheticBeginFrameSource::AsValueInto( base::trace_event::TracedValue* dict) const { dict->SetString("type", "SyntheticBeginFrameSource"); - BeginFrameSourceMixIn::AsValueInto(dict); + BeginFrameSourceBase::AsValueInto(dict); dict->BeginDictionary("time_source"); time_source_->AsValueInto(dict); @@ -282,7 +273,7 @@ scoped_ptr<BeginFrameSourceMultiplexer> BeginFrameSourceMultiplexer::Create() { } BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer() - : BeginFrameSourceMixIn(), + : BeginFrameSourceBase(), minimum_interval_(base::TimeDelta()), active_source_(NULL), source_list_() { @@ -290,7 +281,7 @@ BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer() BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer( base::TimeDelta minimum_interval) - : BeginFrameSourceMixIn(), + : BeginFrameSourceBase(), minimum_interval_(minimum_interval), active_source_(NULL), source_list_() { diff --git a/chromium/cc/scheduler/begin_frame_source.h b/chromium/cc/scheduler/begin_frame_source.h index d845dacd8e4..f6f1a789da7 100644 --- a/chromium/cc/scheduler/begin_frame_source.h +++ b/chromium/cc/scheduler/begin_frame_source.h @@ -11,7 +11,6 @@ #include "base/logging.h" #include "base/trace_event/trace_event.h" #include "cc/output/begin_frame_args.h" -#include "cc/output/vsync_parameter_observer.h" #include "cc/scheduler/delay_based_time_source.h" namespace cc { @@ -53,23 +52,23 @@ class CC_EXPORT BeginFrameObserver { virtual void AsValueInto(base::trace_event::TracedValue* dict) const = 0; }; -// Simple mix in which implements a BeginFrameObserver which checks the +// Simple base class which implements a BeginFrameObserver which checks the // incoming values meet the BeginFrameObserver requirements and implements the // required LastUsedBeginFrameArgs behaviour. // -// Users of this mix in should; -// - Implement the OnBeginFrameMixInDelegate function. +// Users of this class should; +// - Implement the OnBeginFrameDerivedImpl function. // - Recommended (but not required) to call -// BeginFrameObserverMixIn::OnValueInto in their overridden OnValueInto +// BeginFrameObserverBase::OnValueInto in their overridden OnValueInto // function. -class CC_EXPORT BeginFrameObserverMixIn : public BeginFrameObserver { +class CC_EXPORT BeginFrameObserverBase : public BeginFrameObserver { public: - BeginFrameObserverMixIn(); + BeginFrameObserverBase(); // BeginFrameObserver // Traces |args| and DCHECK |args| satisfies pre-conditions then calls - // OnBeginFrameMixInDelegate and updates the last_begin_frame_args_ value on + // OnBeginFrameDerivedImpl and updates the last_begin_frame_args_ value on // true. void OnBeginFrame(const BeginFrameArgs& args) override; const BeginFrameArgs LastUsedBeginFrameArgs() const override; @@ -80,10 +79,13 @@ class CC_EXPORT BeginFrameObserverMixIn : public BeginFrameObserver { protected: // Subclasses should override this method! // Return true if the given argument is (or will be) used. - virtual bool OnBeginFrameMixInDelegate(const BeginFrameArgs& args) = 0; + virtual bool OnBeginFrameDerivedImpl(const BeginFrameArgs& args) = 0; BeginFrameArgs last_begin_frame_args_; int64_t dropped_begin_frame_args_; + + private: + DISALLOW_COPY_AND_ASSIGN(BeginFrameObserverBase); }; // Interface for a class which produces BeginFrame calls to a @@ -125,16 +127,16 @@ class CC_EXPORT BeginFrameSource { virtual void AsValueInto(base::trace_event::TracedValue* dict) const = 0; }; -// Simple mix in which implements a BeginFrameSource. +// Simple base class which implements a BeginFrameSource. // Implementation classes should: // - Implement the pure virtual (Set)NeedsBeginFrames methods from // BeginFrameSource. // - Use the CallOnBeginFrame method to call to the observer(s). -// - Recommended (but not required) to call BeginFrameSourceMixIn::AsValueInto +// - Recommended (but not required) to call BeginFrameSourceBase::AsValueInto // in their own AsValueInto implementation. -class CC_EXPORT BeginFrameSourceMixIn : public BeginFrameSource { +class CC_EXPORT BeginFrameSourceBase : public BeginFrameSource { public: - ~BeginFrameSourceMixIn() override {} + ~BeginFrameSourceBase() override {} // BeginFrameSource bool NeedsBeginFrames() const final; @@ -149,7 +151,7 @@ class CC_EXPORT BeginFrameSourceMixIn : public BeginFrameSource { void AsValueInto(base::trace_event::TracedValue* dict) const override; protected: - BeginFrameSourceMixIn(); + BeginFrameSourceBase(); // These methods should be used by subclasses to make the call to the // observers. @@ -164,11 +166,13 @@ class CC_EXPORT BeginFrameSourceMixIn : public BeginFrameSource { private: bool inside_as_value_into_; + + DISALLOW_COPY_AND_ASSIGN(BeginFrameSourceBase); }; // A frame source which calls BeginFrame (at the next possible time) as soon as // remaining frames reaches zero. -class CC_EXPORT BackToBackBeginFrameSource : public BeginFrameSourceMixIn { +class CC_EXPORT BackToBackBeginFrameSource : public BeginFrameSourceBase { public: static scoped_ptr<BackToBackBeginFrameSource> Create( base::SingleThreadTaskRunner* task_runner); @@ -189,54 +193,56 @@ class CC_EXPORT BackToBackBeginFrameSource : public BeginFrameSourceMixIn { bool send_begin_frame_posted_; - // BeginFrameSourceMixIn + // BeginFrameSourceBase void OnNeedsBeginFramesChange(bool needs_begin_frames) override; void BeginFrame(); private: base::WeakPtrFactory<BackToBackBeginFrameSource> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(BackToBackBeginFrameSource); }; // A frame source which is locked to an external parameters provides from a // vsync source and generates BeginFrameArgs for it. -class CC_EXPORT SyntheticBeginFrameSource : public BeginFrameSourceMixIn, - public VSyncParameterObserver, - public TimeSourceClient { +class CC_EXPORT SyntheticBeginFrameSource : public BeginFrameSourceBase, + public DelayBasedTimeSourceClient { public: static scoped_ptr<SyntheticBeginFrameSource> Create( base::SingleThreadTaskRunner* task_runner, - base::TimeTicks initial_vsync_timebase, base::TimeDelta initial_vsync_interval); ~SyntheticBeginFrameSource() override; + void OnUpdateVSyncParameters(base::TimeTicks new_vsync_timebase, + base::TimeDelta new_vsync_interval); + // Tracing void AsValueInto(base::trace_event::TracedValue* dict) const override; - // VSyncParameterObserver - void OnUpdateVSyncParameters(base::TimeTicks new_vsync_timebase, - base::TimeDelta new_vsync_interval) override; - - // TimeSourceClient + // DelayBasedTimeSourceClient void OnTimerTick() override; protected: explicit SyntheticBeginFrameSource( - scoped_refptr<DelayBasedTimeSource> time_source); + scoped_ptr<DelayBasedTimeSource> time_source); BeginFrameArgs CreateBeginFrameArgs(base::TimeTicks frame_time, BeginFrameArgs::BeginFrameArgsType type); - // BeginFrameSourceMixIn + // BeginFrameSourceBase void OnNeedsBeginFramesChange(bool needs_begin_frames) override; - scoped_refptr<DelayBasedTimeSource> time_source_; + scoped_ptr<DelayBasedTimeSource> time_source_; + + private: + DISALLOW_COPY_AND_ASSIGN(SyntheticBeginFrameSource); }; // A "virtual" frame source which lets you switch between multiple other frame // sources while making sure the BeginFrameArgs stays increasing (possibly // enforcing minimum boundry between BeginFrameArgs messages). -class CC_EXPORT BeginFrameSourceMultiplexer : public BeginFrameSourceMixIn, +class CC_EXPORT BeginFrameSourceMultiplexer : public BeginFrameSourceBase, public BeginFrameObserver { public: static scoped_ptr<BeginFrameSourceMultiplexer> Create(); @@ -259,7 +265,7 @@ class CC_EXPORT BeginFrameSourceMultiplexer : public BeginFrameSourceMixIn, // BeginFrameSource void DidFinishFrame(size_t remaining_frames) override; - // BeginFrameSourceMixIn + // BeginFrameSourceBase void OnNeedsBeginFramesChange(bool needs_begin_frames) override; // Tracing @@ -276,6 +282,9 @@ class CC_EXPORT BeginFrameSourceMultiplexer : public BeginFrameSourceMixIn, BeginFrameSource* active_source_; std::set<BeginFrameSource*> source_list_; + + private: + DISALLOW_COPY_AND_ASSIGN(BeginFrameSourceMultiplexer); }; } // namespace cc diff --git a/chromium/cc/scheduler/begin_frame_source_unittest.cc b/chromium/cc/scheduler/begin_frame_source_unittest.cc index 22126bead45..1f85622878e 100644 --- a/chromium/cc/scheduler/begin_frame_source_unittest.cc +++ b/chromium/cc/scheduler/begin_frame_source_unittest.cc @@ -170,16 +170,16 @@ const BeginFrameArgs MockBeginFrameObserver::kDefaultBeginFrameArgs = -1, -1); -// BeginFrameObserverMixIn testing --------------------------------------- -class MockMinimalBeginFrameObserverMixIn : public BeginFrameObserverMixIn { +// BeginFrameObserverBase testing --------------------------------------- +class MockMinimalBeginFrameObserverBase : public BeginFrameObserverBase { public: - MOCK_METHOD1(OnBeginFrameMixInDelegate, bool(const BeginFrameArgs&)); + MOCK_METHOD1(OnBeginFrameDerivedImpl, bool(const BeginFrameArgs&)); int64_t dropped_begin_frame_args() const { return dropped_begin_frame_args_; } }; -TEST(BeginFrameObserverMixInTest, OnBeginFrameImplementation) { +TEST(BeginFrameObserverBaseTest, OnBeginFrameImplementation) { using ::testing::Return; - MockMinimalBeginFrameObserverMixIn obs; + MockMinimalBeginFrameObserverBase obs; ::testing::InSequence ordered; // These calls should be ordered // Initial conditions @@ -192,7 +192,7 @@ TEST(BeginFrameObserverMixInTest, OnBeginFrameImplementation) { BeginFrameArgs args1 = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 100, 200, 300); - EXPECT_CALL(obs, OnBeginFrameMixInDelegate(args1)).WillOnce(Return(true)); + EXPECT_CALL(obs, OnBeginFrameDerivedImpl(args1)).WillOnce(Return(true)); obs.OnBeginFrame(args1); EXPECT_EQ(args1, obs.LastUsedBeginFrameArgs()); EXPECT_EQ(0, obs.dropped_begin_frame_args()); @@ -208,21 +208,21 @@ TEST(BeginFrameObserverMixInTest, OnBeginFrameImplementation) { // Returning false shouldn't update the LastUsedBeginFrameArgs value. BeginFrameArgs args2 = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 200, 300, 400); - EXPECT_CALL(obs, OnBeginFrameMixInDelegate(args2)).WillOnce(Return(false)); + EXPECT_CALL(obs, OnBeginFrameDerivedImpl(args2)).WillOnce(Return(false)); obs.OnBeginFrame(args2); EXPECT_EQ(args1, obs.LastUsedBeginFrameArgs()); EXPECT_EQ(1, obs.dropped_begin_frame_args()); BeginFrameArgs args3 = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 150, 300, 400); - EXPECT_CALL(obs, OnBeginFrameMixInDelegate(args3)).WillOnce(Return(true)); + EXPECT_CALL(obs, OnBeginFrameDerivedImpl(args3)).WillOnce(Return(true)); obs.OnBeginFrame(args3); EXPECT_EQ(args3, obs.LastUsedBeginFrameArgs()); EXPECT_EQ(1, obs.dropped_begin_frame_args()); } // BeginFrameSource testing ---------------------------------------------- -TEST(BeginFrameSourceMixInTest, ObserverManipulation) { +TEST(BeginFrameSourceBaseTest, ObserverManipulation) { MockBeginFrameObserver obs; MockBeginFrameObserver otherObs; FakeBeginFrameSource source; @@ -251,7 +251,7 @@ TEST(BeginFrameSourceMixInTest, ObserverManipulation) { source.RemoveObserver(&otherObs); } -TEST(BeginFrameSourceMixInTest, Observer) { +TEST(BeginFrameSourceBaseTest, Observer) { FakeBeginFrameSource source; MockBeginFrameObserver obs; source.AddObserver(&obs); @@ -266,12 +266,12 @@ TEST(BeginFrameSourceMixInTest, Observer) { SEND_BEGIN_FRAME_USED(source, 700, 900, 300); } -TEST(BeginFrameSourceMixInTest, NoObserver) { +TEST(BeginFrameSourceBaseTest, NoObserver) { FakeBeginFrameSource source; SEND_BEGIN_FRAME_DROP(source, 100, 200, 300); } -TEST(BeginFrameSourceMixInTest, NeedsBeginFrames) { +TEST(BeginFrameSourceBaseTest, NeedsBeginFrames) { FakeBeginFrameSource source; EXPECT_FALSE(source.NeedsBeginFrames()); source.SetNeedsBeginFrames(true); @@ -280,7 +280,7 @@ TEST(BeginFrameSourceMixInTest, NeedsBeginFrames) { EXPECT_FALSE(source.NeedsBeginFrames()); } -class LoopingBeginFrameObserver : public BeginFrameObserverMixIn { +class LoopingBeginFrameObserver : public BeginFrameObserverBase { public: BeginFrameSource* source_; @@ -292,13 +292,13 @@ class LoopingBeginFrameObserver : public BeginFrameObserverMixIn { } protected: - // BeginFrameObserverMixIn - bool OnBeginFrameMixInDelegate(const BeginFrameArgs& args) override { + // BeginFrameObserverBase + bool OnBeginFrameDerivedImpl(const BeginFrameArgs& args) override { return true; } }; -TEST(BeginFrameSourceMixInTest, DetectAsValueIntoLoop) { +TEST(BeginFrameSourceBaseTest, DetectAsValueIntoLoop) { LoopingBeginFrameObserver obs; FakeBeginFrameSource source; @@ -314,20 +314,21 @@ TEST(BeginFrameSourceMixInTest, DetectAsValueIntoLoop) { class TestBackToBackBeginFrameSource : public BackToBackBeginFrameSource { public: static scoped_ptr<TestBackToBackBeginFrameSource> Create( - scoped_refptr<TestNowSource> now_src, + base::SimpleTestTickClock* now_src, base::SingleThreadTaskRunner* task_runner) { return make_scoped_ptr( new TestBackToBackBeginFrameSource(now_src, task_runner)); } protected: - TestBackToBackBeginFrameSource(scoped_refptr<TestNowSource> now_src, + TestBackToBackBeginFrameSource(base::SimpleTestTickClock* now_src, base::SingleThreadTaskRunner* task_runner) : BackToBackBeginFrameSource(task_runner), now_src_(now_src) {} - base::TimeTicks Now() override { return now_src_->Now(); } + base::TimeTicks Now() override { return now_src_->NowTicks(); } - scoped_refptr<TestNowSource> now_src_; + // Not owned. + base::SimpleTestTickClock* now_src_; }; class BackToBackBeginFrameSourceTest : public ::testing::Test { @@ -335,18 +336,19 @@ class BackToBackBeginFrameSourceTest : public ::testing::Test { static const int64_t kDeadline; static const int64_t kInterval; - scoped_refptr<TestNowSource> now_src_; + scoped_ptr<base::SimpleTestTickClock> now_src_; scoped_refptr<OrderedSimpleTaskRunner> task_runner_; scoped_ptr<TestBackToBackBeginFrameSource> source_; scoped_ptr<MockBeginFrameObserver> obs_; void SetUp() override { - now_src_ = TestNowSource::Create(1000); + now_src_.reset(new base::SimpleTestTickClock()); + now_src_->Advance(base::TimeDelta::FromMicroseconds(1000)); task_runner_ = - make_scoped_refptr(new OrderedSimpleTaskRunner(now_src_, false)); + make_scoped_refptr(new OrderedSimpleTaskRunner(now_src_.get(), false)); task_runner_->SetRunTaskLimit(1); - source_ = - TestBackToBackBeginFrameSource::Create(now_src_, task_runner_.get()); + source_ = TestBackToBackBeginFrameSource::Create(now_src_.get(), + task_runner_.get()); obs_ = make_scoped_ptr(new ::testing::StrictMock<MockBeginFrameObserver>()); source_->AddObserver(obs_.get()); } @@ -367,7 +369,7 @@ TEST_F(BackToBackBeginFrameSourceTest, SetNeedsBeginFramesSendsBeginFrame) { task_runner_->RunUntilIdle(); EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval); - now_src_->AdvanceNowMicroseconds(100); + now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); task_runner_->RunUntilIdle(); } @@ -390,7 +392,7 @@ TEST_F(BackToBackBeginFrameSourceTest, source_->SetNeedsBeginFrames(true); task_runner_->RunUntilIdle(); - now_src_->AdvanceNowMicroseconds(100); + now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); source_->SetNeedsBeginFrames(false); @@ -404,14 +406,14 @@ TEST_F(BackToBackBeginFrameSourceTest, source_->SetNeedsBeginFrames(true); task_runner_->RunUntilIdle(); - now_src_->AdvanceNowMicroseconds(100); + now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->SetNeedsBeginFrames(false); - now_src_->AdvanceNowMicroseconds(10); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); source_->DidFinishFrame(0); - now_src_->AdvanceNowMicroseconds(10); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); source_->SetNeedsBeginFrames(false); - now_src_->AdvanceNowMicroseconds(10); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); source_->SetNeedsBeginFrames(true); EXPECT_BEGIN_FRAME_USED(*obs_, 1130, 1130 + kDeadline, kInterval); @@ -425,13 +427,13 @@ TEST_F(BackToBackBeginFrameSourceTest, source_->SetNeedsBeginFrames(true); task_runner_->RunUntilIdle(); - now_src_->AdvanceNowMicroseconds(100); + now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); - now_src_->AdvanceNowMicroseconds(10); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); source_->SetNeedsBeginFrames(false); - now_src_->AdvanceNowMicroseconds(10); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); source_->SetNeedsBeginFrames(true); - now_src_->AdvanceNowMicroseconds(10); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); EXPECT_BEGIN_FRAME_USED(*obs_, 1130, 1130 + kDeadline, kInterval); EXPECT_TRUE(task_runner_->HasPendingTasks()); @@ -449,7 +451,7 @@ TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameRemainingFrames) { source_->SetNeedsBeginFrames(true); task_runner_->RunUntilIdle(); - now_src_->AdvanceNowMicroseconds(100); + now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(3); EXPECT_FALSE(task_runner_->HasPendingTasks()); @@ -469,14 +471,14 @@ TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameMultipleCallsIdempotent) { EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); task_runner_->RunUntilIdle(); - now_src_->AdvanceNowMicroseconds(100); + now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); source_->DidFinishFrame(0); source_->DidFinishFrame(0); EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval); task_runner_->RunUntilIdle(); - now_src_->AdvanceNowMicroseconds(100); + now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); source_->DidFinishFrame(0); source_->DidFinishFrame(0); @@ -489,9 +491,9 @@ TEST_F(BackToBackBeginFrameSourceTest, DelayInPostedTaskProducesCorrectFrame) { source_->SetNeedsBeginFrames(true); task_runner_->RunUntilIdle(); - now_src_->AdvanceNowMicroseconds(100); + now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); - now_src_->AdvanceNowMicroseconds(50); + now_src_->Advance(base::TimeDelta::FromMicroseconds(50)); EXPECT_BEGIN_FRAME_USED(*obs_, 1150, 1150 + kDeadline, kInterval); EXPECT_TRUE(task_runner_->HasPendingTasks()); @@ -501,17 +503,19 @@ TEST_F(BackToBackBeginFrameSourceTest, DelayInPostedTaskProducesCorrectFrame) { // SyntheticBeginFrameSource testing ------------------------------------------ class SyntheticBeginFrameSourceTest : public ::testing::Test { public: - scoped_refptr<TestNowSource> now_src_; + scoped_ptr<base::SimpleTestTickClock> now_src_; scoped_refptr<OrderedSimpleTaskRunner> task_runner_; scoped_ptr<TestSyntheticBeginFrameSource> source_; scoped_ptr<MockBeginFrameObserver> obs_; void SetUp() override { - now_src_ = TestNowSource::Create(1000); + now_src_.reset(new base::SimpleTestTickClock()); + now_src_->Advance(base::TimeDelta::FromMicroseconds(1000)); task_runner_ = - make_scoped_refptr(new OrderedSimpleTaskRunner(now_src_, false)); + make_scoped_refptr(new OrderedSimpleTaskRunner(now_src_.get(), false)); source_ = TestSyntheticBeginFrameSource::Create( - now_src_, task_runner_.get(), base::TimeDelta::FromMicroseconds(10000)); + now_src_.get(), task_runner_.get(), + base::TimeDelta::FromMicroseconds(10000)); obs_ = make_scoped_ptr(new MockBeginFrameObserver()); source_->AddObserver(obs_.get()); } @@ -521,7 +525,7 @@ class SyntheticBeginFrameSourceTest : public ::testing::Test { TEST_F(SyntheticBeginFrameSourceTest, SetNeedsBeginFramesCallsOnBeginFrameWithMissedTick) { - now_src_->SetNowMicroseconds(10010); + now_src_->Advance(base::TimeDelta::FromMicroseconds(9010)); EXPECT_CALL((*obs_), OnBeginFrame(CreateBeginFrameArgsForTesting( BEGINFRAME_FROM_HERE, 10000, 20000, 10000, BeginFrameArgs::MISSED))); @@ -535,7 +539,7 @@ TEST_F(SyntheticBeginFrameSourceTest, EXPECT_EQ(10000, task_runner_->NextTaskTime().ToInternalValue()); EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000); - now_src_->SetNowMicroseconds(10010); + now_src_->Advance(base::TimeDelta::FromMicroseconds(9010)); task_runner_->RunPendingTasks(); } diff --git a/chromium/cc/scheduler/begin_frame_tracker.cc b/chromium/cc/scheduler/begin_frame_tracker.cc new file mode 100644 index 00000000000..3b526ccad00 --- /dev/null +++ b/chromium/cc/scheduler/begin_frame_tracker.cc @@ -0,0 +1,123 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/scheduler/begin_frame_tracker.h" + +namespace cc { + +BeginFrameTracker::BeginFrameTracker(const tracked_objects::Location& location) + : location_(location), + location_string_(location.ToString()), + current_updated_at_(), + current_args_(), + current_finished_at_(base::TraceTicks::FromInternalValue(-1)) { +} + +BeginFrameTracker::~BeginFrameTracker() { +} + +void BeginFrameTracker::Start(BeginFrameArgs new_args) { + // Trace the frame time being passed between BeginFrameTrackers. + TRACE_EVENT_FLOW_STEP0( + TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", + new_args.frame_time.ToInternalValue(), location_string_); + + // Trace this specific begin frame tracker Start/Finish times. + TRACE_EVENT_ASYNC_BEGIN2( + TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), + location_string_.c_str(), new_args.frame_time.ToInternalValue(), + "new args", new_args.AsValue(), "current args", current_args_.AsValue()); + + // Check the new BeginFrameArgs are valid and monotonically increasing. + DCHECK(new_args.IsValid()); + DCHECK_LE(current_args_.frame_time, new_args.frame_time); + + DCHECK(HasFinished()) + << "Tried to start a new frame before finishing an existing frame."; + current_updated_at_ = base::TraceTicks::Now(); + current_args_ = new_args; + current_finished_at_ = base::TraceTicks(); + + // TODO(mithro): Add UMA tracking of delta between current_updated_at_ time + // and the new_args.frame_time argument. This will give us how long after a + // BeginFrameArgs message was created before we started processing it. +} + +const BeginFrameArgs& BeginFrameTracker::Current() const { + DCHECK(!HasFinished()) + << "Tried to use BeginFrameArgs after marking the frame finished."; + DCHECK(current_args_.IsValid()) + << "Tried to use BeginFrameArgs before starting a frame!"; + return current_args_; +} + +void BeginFrameTracker::Finish() { + DCHECK(!HasFinished()) << "Tried to finish an already finished frame"; + current_finished_at_ = base::TraceTicks::Now(); + TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), + location_string_.c_str(), + current_args_.frame_time.ToInternalValue()); +} + +const BeginFrameArgs& BeginFrameTracker::Last() const { + DCHECK(current_args_.IsValid()) + << "Tried to use last BeginFrameArgs before starting a frame!"; + DCHECK(HasFinished()) + << "Tried to use last BeginFrameArgs before the frame is finished."; + return current_args_; +} + +base::TimeDelta BeginFrameTracker::Interval() const { + base::TimeDelta interval = current_args_.interval; + // Normal interval will be ~16ms, 200Hz (5ms) screens are the fastest + // easily available so anything less than that is likely an error. + if (interval < base::TimeDelta::FromMilliseconds(1)) { + interval = BeginFrameArgs::DefaultInterval(); + } + return interval; +} + +void BeginFrameTracker::AsValueInto( + base::TimeTicks now, + base::trace_event::TracedValue* state) const { + state->SetInteger("updated_at_us", (current_updated_at_ - base::TraceTicks()) + .InMicroseconds()); + state->SetInteger("finished_at_us", (current_finished_at_ - + base::TraceTicks()).InMicroseconds()); + if (HasFinished()) { + state->SetString("state", "FINISHED"); + state->BeginDictionary("current_args_"); + } else { + state->SetString("state", "USING"); + state->BeginDictionary("last_args_"); + } + current_args_.AsValueInto(state); + state->EndDictionary(); + + base::TimeTicks frame_time = current_args_.frame_time; + base::TimeTicks deadline = current_args_.deadline; + base::TimeDelta interval = current_args_.interval; + state->BeginDictionary("major_timestamps_in_ms"); + state->SetDouble("0_interval", interval.InMillisecondsF()); + state->SetDouble("1_now_to_deadline", (deadline - now).InMillisecondsF()); + state->SetDouble("2_frame_time_to_now", (now - frame_time).InMillisecondsF()); + state->SetDouble("3_frame_time_to_deadline", + (deadline - frame_time).InMillisecondsF()); + state->SetDouble("4_now", (now - base::TimeTicks()).InMillisecondsF()); + state->SetDouble("5_frame_time", + (frame_time - base::TimeTicks()).InMillisecondsF()); + state->SetDouble("6_deadline", + (deadline - base::TimeTicks()).InMillisecondsF()); + state->EndDictionary(); +} + +const BeginFrameArgs& BeginFrameTracker::DangerousMethodCurrentOrLast() const { + if (!HasFinished()) { + return Current(); + } else { + return Last(); + } +} + +} // namespace cc diff --git a/chromium/cc/scheduler/begin_frame_tracker.h b/chromium/cc/scheduler/begin_frame_tracker.h new file mode 100644 index 00000000000..617f52b1324 --- /dev/null +++ b/chromium/cc/scheduler/begin_frame_tracker.h @@ -0,0 +1,97 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_SCHEDULER_BEGIN_FRAME_TRACKER_H_ +#define CC_SCHEDULER_BEGIN_FRAME_TRACKER_H_ + +#include <set> +#include <string> + +#include "base/location.h" +#include "base/trace_event/trace_event.h" +#include "base/trace_event/trace_event_argument.h" +#include "cc/output/begin_frame_args.h" + +#define BEGINFRAMETRACKER_FROM_HERE FROM_HERE_WITH_EXPLICIT_FUNCTION("") + +namespace cc { + +// Microclass to trace and check properties for correct BeginFrameArgs (BFA) +// usage and provide a few helper methods. +// +// With DCHECKs enable, this class checks the following "invariants"; +// * BFA are monotonically increasing. +// * BFA is valid. +// * The BFA is only used inside a given period. +// * A new BFA isn't used before the last BFA is finished with. +// +// With the tracing category "cc.debug.scheduler.frames" enabled the tracker +// will output the following trace information; +// * Time period for which the BFA is in usage. +// * The flow of BFA as they are passed between tracking objects. +// +// TODO(mithro): Record stats about the BeginFrameArgs +class CC_EXPORT BeginFrameTracker { + public: + explicit BeginFrameTracker(const tracked_objects::Location& location); + ~BeginFrameTracker(); + + // The Start and Finish methods manage the period that a BFA should be + // accessed for. This allows tight control over the BFA and prevents + // accidental usage in the wrong period when code is split across multiple + // locations. + + // Start using a new BFA value and check invariant properties. + // **Must** only be called after finishing with any previous BFA. + void Start(BeginFrameArgs new_args); + // Finish using the current BFA. + // **Must** only be called while still using a BFA. + void Finish(); + + // The two accessors methods allow access to the BFA stored inside the + // tracker. They are mutually exclusive, at any time it is only valid to call + // one or the other. This makes sure you understand exactly which BFA you are + // intending to use and verifies that is the case. + + // Get the current BFA object. + // **Must** only be called between the start and finish methods calls. + const BeginFrameArgs& Current() const; + // Get the last used BFA. + // **Must** only be called when **not** between the start and finish method + // calls. + const BeginFrameArgs& Last() const; + + // Helper method to try and return a valid interval property. Defaults to + // BFA::DefaultInterval() is no other interval can be found. Can be called at + // any time. + base::TimeDelta Interval() const; + + void AsValueInto(base::TimeTicks now, + base::trace_event::TracedValue* dict) const; + + // The following methods violate principles of how BeginFrameArgs should be + // used. These methods should only be used when there is no other choice. + bool DangerousMethodHasStarted() const { + return !current_updated_at_.is_null(); + } + bool DangerousMethodHasFinished() const { return HasFinished(); } + const BeginFrameArgs& DangerousMethodCurrentOrLast() const; + + private: + // Return if currently not between the start/end period. This method should + // be used extremely sparingly and normal indicates incorrect management of + // the BFA object. Can be called at any time. + bool HasFinished() const { return !current_finished_at_.is_null(); } + + const tracked_objects::Location location_; + const std::string location_string_; + + base::TraceTicks current_updated_at_; + BeginFrameArgs current_args_; + base::TraceTicks current_finished_at_; +}; + +} // namespace cc + +#endif // CC_SCHEDULER_BEGIN_FRAME_TRACKER_H_ diff --git a/chromium/cc/scheduler/compositor_timing_history.cc b/chromium/cc/scheduler/compositor_timing_history.cc new file mode 100644 index 00000000000..b46c8a15cbe --- /dev/null +++ b/chromium/cc/scheduler/compositor_timing_history.cc @@ -0,0 +1,217 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/scheduler/compositor_timing_history.h" + +#include "base/metrics/histogram.h" +#include "base/trace_event/trace_event.h" +#include "cc/debug/rendering_stats_instrumentation.h" + +// The estimates that affect the compositors deadline use the 100th percentile +// to avoid missing the Browser's deadline. +// The estimates related to main-thread responsiveness affect whether +// we attempt to recovery latency or not and use the 50th percentile. +// TODO(brianderson): Fine tune the percentiles below. +const size_t kDurationHistorySize = 60; +const double kBeginMainFrameToCommitEstimationPercentile = 50.0; +const double kCommitToReadyToActivateEstimationPercentile = 50.0; +const double kPrepareTilesEstimationPercentile = 100.0; +const double kActivateEstimationPercentile = 100.0; +const double kDrawEstimationPercentile = 100.0; + +namespace cc { + +CompositorTimingHistory::CompositorTimingHistory( + RenderingStatsInstrumentation* rendering_stats_instrumentation) + : enabled_(false), + begin_main_frame_to_commit_duration_history_(kDurationHistorySize), + commit_to_ready_to_activate_duration_history_(kDurationHistorySize), + prepare_tiles_duration_history_(kDurationHistorySize), + activate_duration_history_(kDurationHistorySize), + draw_duration_history_(kDurationHistorySize), + rendering_stats_instrumentation_(rendering_stats_instrumentation) { +} + +CompositorTimingHistory::~CompositorTimingHistory() { +} + +void CompositorTimingHistory::AsValueInto( + base::trace_event::TracedValue* state) const { + state->SetDouble("begin_main_frame_to_commit_duration_estimate_ms", + BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); + state->SetDouble("commit_to_ready_to_activate_duration_estimate_ms", + CommitToReadyToActivateDurationEstimate().InMillisecondsF()); + state->SetDouble("prepare_tiles_duration_estimate_ms", + PrepareTilesDurationEstimate().InMillisecondsF()); + state->SetDouble("activate_duration_estimate_ms", + ActivateDurationEstimate().InMillisecondsF()); + state->SetDouble("draw_duration_estimate_ms", + DrawDurationEstimate().InMillisecondsF()); +} + +base::TimeTicks CompositorTimingHistory::Now() const { + return base::TimeTicks::Now(); +} + +void CompositorTimingHistory::SetRecordingEnabled(bool enabled) { + enabled_ = enabled; +} + +base::TimeDelta +CompositorTimingHistory::BeginMainFrameToCommitDurationEstimate() const { + return begin_main_frame_to_commit_duration_history_.Percentile( + kBeginMainFrameToCommitEstimationPercentile); +} + +base::TimeDelta +CompositorTimingHistory::CommitToReadyToActivateDurationEstimate() const { + return commit_to_ready_to_activate_duration_history_.Percentile( + kCommitToReadyToActivateEstimationPercentile); +} + +base::TimeDelta CompositorTimingHistory::PrepareTilesDurationEstimate() const { + return prepare_tiles_duration_history_.Percentile( + kPrepareTilesEstimationPercentile); +} + +base::TimeDelta CompositorTimingHistory::ActivateDurationEstimate() const { + return activate_duration_history_.Percentile(kActivateEstimationPercentile); +} + +base::TimeDelta CompositorTimingHistory::DrawDurationEstimate() const { + return draw_duration_history_.Percentile(kDrawEstimationPercentile); +} + +void CompositorTimingHistory::WillBeginMainFrame() { + DCHECK_EQ(base::TimeTicks(), begin_main_frame_sent_time_); + begin_main_frame_sent_time_ = Now(); +} + +void CompositorTimingHistory::BeginMainFrameAborted() { + DidCommit(); +} + +void CompositorTimingHistory::DidCommit() { + DCHECK_NE(base::TimeTicks(), begin_main_frame_sent_time_); + + commit_time_ = Now(); + + base::TimeDelta begin_main_frame_to_commit_duration = + commit_time_ - begin_main_frame_sent_time_; + + // Before adding the new data point to the timing history, see what we would + // have predicted for this frame. This allows us to keep track of the accuracy + // of our predictions. + rendering_stats_instrumentation_->AddBeginMainFrameToCommitDuration( + begin_main_frame_to_commit_duration, + BeginMainFrameToCommitDurationEstimate()); + + if (enabled_) { + begin_main_frame_to_commit_duration_history_.InsertSample( + begin_main_frame_to_commit_duration); + } + + begin_main_frame_sent_time_ = base::TimeTicks(); +} + +void CompositorTimingHistory::WillPrepareTiles() { + DCHECK_EQ(base::TimeTicks(), start_prepare_tiles_time_); + start_prepare_tiles_time_ = Now(); +} + +void CompositorTimingHistory::DidPrepareTiles() { + DCHECK_NE(base::TimeTicks(), start_prepare_tiles_time_); + + if (enabled_) { + base::TimeDelta prepare_tiles_duration = Now() - start_prepare_tiles_time_; + prepare_tiles_duration_history_.InsertSample(prepare_tiles_duration); + } + + start_prepare_tiles_time_ = base::TimeTicks(); +} + +void CompositorTimingHistory::ReadyToActivate() { + // We only care about the first ready to activate signal + // after a commit. + if (commit_time_ == base::TimeTicks()) + return; + + base::TimeDelta time_since_commit = Now() - commit_time_; + + // Before adding the new data point to the timing history, see what we would + // have predicted for this frame. This allows us to keep track of the accuracy + // of our predictions. + rendering_stats_instrumentation_->AddCommitToActivateDuration( + time_since_commit, CommitToReadyToActivateDurationEstimate()); + + if (enabled_) { + commit_to_ready_to_activate_duration_history_.InsertSample( + time_since_commit); + } + + commit_time_ = base::TimeTicks(); +} + +void CompositorTimingHistory::WillActivate() { + DCHECK_EQ(base::TimeTicks(), start_activate_time_); + start_activate_time_ = Now(); +} + +void CompositorTimingHistory::DidActivate() { + DCHECK_NE(base::TimeTicks(), start_activate_time_); + if (enabled_) { + base::TimeDelta activate_duration = Now() - start_activate_time_; + activate_duration_history_.InsertSample(activate_duration); + } + start_activate_time_ = base::TimeTicks(); +} + +void CompositorTimingHistory::WillDraw() { + DCHECK_EQ(base::TimeTicks(), start_draw_time_); + start_draw_time_ = Now(); +} + +void CompositorTimingHistory::DidDraw() { + DCHECK_NE(base::TimeTicks(), start_draw_time_); + base::TimeDelta draw_duration = Now() - start_draw_time_; + + // Before adding the new data point to the timing history, see what we would + // have predicted for this frame. This allows us to keep track of the accuracy + // of our predictions. + base::TimeDelta draw_duration_estimate = DrawDurationEstimate(); + rendering_stats_instrumentation_->AddDrawDuration(draw_duration, + draw_duration_estimate); + + AddDrawDurationUMA(draw_duration, draw_duration_estimate); + + if (enabled_) { + draw_duration_history_.InsertSample(draw_duration); + } + + start_draw_time_ = base::TimeTicks(); +} + +void CompositorTimingHistory::AddDrawDurationUMA( + base::TimeDelta draw_duration, + base::TimeDelta draw_duration_estimate) { + base::TimeDelta draw_duration_overestimate; + base::TimeDelta draw_duration_underestimate; + if (draw_duration > draw_duration_estimate) + draw_duration_underestimate = draw_duration - draw_duration_estimate; + else + draw_duration_overestimate = draw_duration_estimate - draw_duration; + UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration", draw_duration, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMilliseconds(100), 50); + UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate", + draw_duration_underestimate, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMilliseconds(100), 50); + UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate", + draw_duration_overestimate, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMilliseconds(100), 50); +} + +} // namespace cc diff --git a/chromium/cc/scheduler/compositor_timing_history.h b/chromium/cc/scheduler/compositor_timing_history.h new file mode 100644 index 00000000000..d64c38f1cbe --- /dev/null +++ b/chromium/cc/scheduler/compositor_timing_history.h @@ -0,0 +1,75 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_SCHEDULER_COMPOSITOR_TIMING_HISTORY_H_ +#define CC_SCHEDULER_COMPOSITOR_TIMING_HISTORY_H_ + +#include "cc/base/rolling_time_delta_history.h" + +namespace base { +namespace trace_event { +class TracedValue; +} // namespace trace_event +} // namespace base + +namespace cc { + +class RenderingStatsInstrumentation; + +class CC_EXPORT CompositorTimingHistory { + public: + explicit CompositorTimingHistory( + RenderingStatsInstrumentation* rendering_stats_instrumentation); + virtual ~CompositorTimingHistory(); + + void AsValueInto(base::trace_event::TracedValue* state) const; + + virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() const; + virtual base::TimeDelta CommitToReadyToActivateDurationEstimate() const; + virtual base::TimeDelta PrepareTilesDurationEstimate() const; + virtual base::TimeDelta ActivateDurationEstimate() const; + virtual base::TimeDelta DrawDurationEstimate() const; + + void SetRecordingEnabled(bool enabled); + + void WillBeginMainFrame(); + void BeginMainFrameAborted(); + void DidCommit(); + void WillPrepareTiles(); + void DidPrepareTiles(); + void ReadyToActivate(); + void WillActivate(); + void DidActivate(); + void WillDraw(); + void DidDraw(); + + protected: + virtual base::TimeTicks Now() const; + + void AddDrawDurationUMA(base::TimeDelta draw_duration, + base::TimeDelta draw_duration_estimate); + + bool enabled_; + + RollingTimeDeltaHistory begin_main_frame_to_commit_duration_history_; + RollingTimeDeltaHistory commit_to_ready_to_activate_duration_history_; + RollingTimeDeltaHistory prepare_tiles_duration_history_; + RollingTimeDeltaHistory activate_duration_history_; + RollingTimeDeltaHistory draw_duration_history_; + + base::TimeTicks begin_main_frame_sent_time_; + base::TimeTicks commit_time_; + base::TimeTicks start_prepare_tiles_time_; + base::TimeTicks start_activate_time_; + base::TimeTicks start_draw_time_; + + RenderingStatsInstrumentation* rendering_stats_instrumentation_; + + private: + DISALLOW_COPY_AND_ASSIGN(CompositorTimingHistory); +}; + +} // namespace cc + +#endif // CC_SCHEDULER_COMPOSITOR_TIMING_HISTORY_H_ diff --git a/chromium/cc/scheduler/compositor_timing_history_unittest.cc b/chromium/cc/scheduler/compositor_timing_history_unittest.cc new file mode 100644 index 00000000000..6045e3a960a --- /dev/null +++ b/chromium/cc/scheduler/compositor_timing_history_unittest.cc @@ -0,0 +1,140 @@ +// Copyright 2015 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/scheduler/compositor_timing_history.h" + +#include "cc/debug/rendering_stats_instrumentation.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +class CompositorTimingHistoryTest; + +class TestCompositorTimingHistory : public CompositorTimingHistory { + public: + TestCompositorTimingHistory(CompositorTimingHistoryTest* test, + RenderingStatsInstrumentation* rendering_stats) + : CompositorTimingHistory(rendering_stats), test_(test) {} + + protected: + base::TimeTicks Now() const override; + + CompositorTimingHistoryTest* test_; + + private: + DISALLOW_COPY_AND_ASSIGN(TestCompositorTimingHistory); +}; + +class CompositorTimingHistoryTest : public testing::Test { + public: + CompositorTimingHistoryTest() + : rendering_stats_(RenderingStatsInstrumentation::Create()), + timing_history_(this, rendering_stats_.get()) { + AdvanceNowBy(base::TimeDelta::FromMilliseconds(1)); + timing_history_.SetRecordingEnabled(true); + } + + void AdvanceNowBy(base::TimeDelta delta) { now_ += delta; } + + base::TimeTicks Now() { return now_; } + + protected: + scoped_ptr<RenderingStatsInstrumentation> rendering_stats_; + TestCompositorTimingHistory timing_history_; + base::TimeTicks now_; +}; + +base::TimeTicks TestCompositorTimingHistory::Now() const { + return test_->Now(); +} + +TEST_F(CompositorTimingHistoryTest, AllSequentialCommit) { + base::TimeDelta one_second = base::TimeDelta::FromSeconds(1); + + base::TimeDelta begin_main_frame_to_commit_duration = + base::TimeDelta::FromMilliseconds(1); + base::TimeDelta prepare_tiles_duration = base::TimeDelta::FromMilliseconds(2); + base::TimeDelta prepare_tiles_end_to_ready_to_activate_duration = + base::TimeDelta::FromMilliseconds(1); + base::TimeDelta commit_to_ready_to_activate_duration = + base::TimeDelta::FromMilliseconds(3); + base::TimeDelta activate_duration = base::TimeDelta::FromMilliseconds(4); + base::TimeDelta draw_duration = base::TimeDelta::FromMilliseconds(5); + + timing_history_.WillBeginMainFrame(); + AdvanceNowBy(begin_main_frame_to_commit_duration); + // timing_history_.BeginMainFrameAborted(); + timing_history_.DidCommit(); + timing_history_.WillPrepareTiles(); + AdvanceNowBy(prepare_tiles_duration); + timing_history_.DidPrepareTiles(); + AdvanceNowBy(prepare_tiles_end_to_ready_to_activate_duration); + timing_history_.ReadyToActivate(); + // Do not count idle time between notification and actual activation. + AdvanceNowBy(one_second); + timing_history_.WillActivate(); + AdvanceNowBy(activate_duration); + timing_history_.DidActivate(); + // Do not count idle time between activate and draw. + AdvanceNowBy(one_second); + timing_history_.WillDraw(); + AdvanceNowBy(draw_duration); + timing_history_.DidDraw(); + + EXPECT_EQ(begin_main_frame_to_commit_duration, + timing_history_.BeginMainFrameToCommitDurationEstimate()); + EXPECT_EQ(commit_to_ready_to_activate_duration, + timing_history_.CommitToReadyToActivateDurationEstimate()); + EXPECT_EQ(prepare_tiles_duration, + timing_history_.PrepareTilesDurationEstimate()); + EXPECT_EQ(activate_duration, timing_history_.ActivateDurationEstimate()); + EXPECT_EQ(draw_duration, timing_history_.DrawDurationEstimate()); +} + +TEST_F(CompositorTimingHistoryTest, AllSequentialBeginMainFrameAborted) { + base::TimeDelta one_second = base::TimeDelta::FromSeconds(1); + + base::TimeDelta begin_main_frame_to_commit_duration = + base::TimeDelta::FromMilliseconds(1); + base::TimeDelta prepare_tiles_duration = base::TimeDelta::FromMilliseconds(2); + base::TimeDelta prepare_tiles_end_to_ready_to_activate_duration = + base::TimeDelta::FromMilliseconds(1); + base::TimeDelta commit_to_ready_to_activate_duration = + base::TimeDelta::FromMilliseconds(3); + base::TimeDelta activate_duration = base::TimeDelta::FromMilliseconds(4); + base::TimeDelta draw_duration = base::TimeDelta::FromMilliseconds(5); + + timing_history_.WillBeginMainFrame(); + AdvanceNowBy(begin_main_frame_to_commit_duration); + // BeginMainFrameAborted counts as a commit complete. + timing_history_.BeginMainFrameAborted(); + timing_history_.WillPrepareTiles(); + AdvanceNowBy(prepare_tiles_duration); + timing_history_.DidPrepareTiles(); + AdvanceNowBy(prepare_tiles_end_to_ready_to_activate_duration); + timing_history_.ReadyToActivate(); + // Do not count idle time between notification and actual activation. + AdvanceNowBy(one_second); + timing_history_.WillActivate(); + AdvanceNowBy(activate_duration); + timing_history_.DidActivate(); + // Do not count idle time between activate and draw. + AdvanceNowBy(one_second); + timing_history_.WillDraw(); + AdvanceNowBy(draw_duration); + timing_history_.DidDraw(); + + EXPECT_EQ(begin_main_frame_to_commit_duration, + timing_history_.BeginMainFrameToCommitDurationEstimate()); + EXPECT_EQ(commit_to_ready_to_activate_duration, + timing_history_.CommitToReadyToActivateDurationEstimate()); + EXPECT_EQ(prepare_tiles_duration, + timing_history_.PrepareTilesDurationEstimate()); + EXPECT_EQ(activate_duration, timing_history_.ActivateDurationEstimate()); + EXPECT_EQ(draw_duration, timing_history_.DrawDurationEstimate()); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/scheduler/delay_based_time_source.cc b/chromium/cc/scheduler/delay_based_time_source.cc index ef43524a878..8e633ef5215 100644 --- a/chromium/cc/scheduler/delay_based_time_source.cc +++ b/chromium/cc/scheduler/delay_based_time_source.cc @@ -37,67 +37,43 @@ static const double kPhaseChangeThreshold = 0.25; // The following methods correspond to the DelayBasedTimeSource that uses // the base::TimeTicks::Now as the timebase. -scoped_refptr<DelayBasedTimeSourceHighRes> DelayBasedTimeSourceHighRes::Create( - base::TimeDelta interval, - base::SingleThreadTaskRunner* task_runner) { - return make_scoped_refptr( - new DelayBasedTimeSourceHighRes(interval, task_runner)); -} - -DelayBasedTimeSourceHighRes::DelayBasedTimeSourceHighRes( - base::TimeDelta interval, - base::SingleThreadTaskRunner* task_runner) - : DelayBasedTimeSource(interval, task_runner) { -} - -DelayBasedTimeSourceHighRes::~DelayBasedTimeSourceHighRes() {} - -base::TimeTicks DelayBasedTimeSourceHighRes::Now() const { - return base::TimeTicks::Now(); -} - -// The following methods correspond to the DelayBasedTimeSource that uses -// the base::TimeTicks::Now as the timebase. -scoped_refptr<DelayBasedTimeSource> DelayBasedTimeSource::Create( - base::TimeDelta interval, - base::SingleThreadTaskRunner* task_runner) { - return make_scoped_refptr(new DelayBasedTimeSource(interval, task_runner)); -} - DelayBasedTimeSource::DelayBasedTimeSource( base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner) - : client_(NULL), - last_tick_time_(base::TimeTicks() - interval), - current_parameters_(interval, base::TimeTicks()), - next_parameters_(interval, base::TimeTicks()), + : client_(nullptr), active_(false), + timebase_(base::TimeTicks()), + interval_(interval), + last_tick_time_(base::TimeTicks() - interval), + next_tick_time_(base::TimeTicks()), task_runner_(task_runner), weak_factory_(this) { - DCHECK_GT(interval.ToInternalValue(), 0); + DCHECK_GT(interval, base::TimeDelta()); } DelayBasedTimeSource::~DelayBasedTimeSource() {} base::TimeTicks DelayBasedTimeSource::SetActive(bool active) { TRACE_EVENT1("cc", "DelayBasedTimeSource::SetActive", "active", active); + if (active == active_) return base::TimeTicks(); + active_ = active; if (!active_) { - weak_factory_.InvalidateWeakPtrs(); + next_tick_time_ = base::TimeTicks(); + tick_closure_.Cancel(); return base::TimeTicks(); } - PostNextTickTask(Now()); + ResetTickTask(Now()); // Determine if there was a tick that was missed while not active. - base::TimeTicks last_tick_time_if_always_active = - current_parameters_.tick_target - current_parameters_.interval; - base::TimeTicks new_tick_time_threshold = - last_tick_time_ + current_parameters_.interval / kDoubleTickDivisor; - if (last_tick_time_if_always_active > new_tick_time_threshold) { + base::TimeTicks last_tick_time_if_always_active = next_tick_time_ - interval_; + base::TimeTicks last_tick_time_threshold = + last_tick_time_ + interval_ / kDoubleTickDivisor; + if (last_tick_time_if_always_active > last_tick_time_threshold) { last_tick_time_ = last_tick_time_if_always_active; return last_tick_time_; } @@ -105,6 +81,10 @@ base::TimeTicks DelayBasedTimeSource::SetActive(bool active) { return base::TimeTicks(); } +base::TimeDelta DelayBasedTimeSource::Interval() const { + return interval_; +} + bool DelayBasedTimeSource::Active() const { return active_; } base::TimeTicks DelayBasedTimeSource::LastTickTime() const { @@ -112,13 +92,13 @@ base::TimeTicks DelayBasedTimeSource::LastTickTime() const { } base::TimeTicks DelayBasedTimeSource::NextTickTime() const { - return Active() ? current_parameters_.tick_target : base::TimeTicks(); + return next_tick_time_; } -void DelayBasedTimeSource::OnTimerFired() { +void DelayBasedTimeSource::OnTimerTick() { DCHECK(active_); - last_tick_time_ = current_parameters_.tick_target; + last_tick_time_ = next_tick_time_; PostNextTickTask(Now()); @@ -127,31 +107,34 @@ void DelayBasedTimeSource::OnTimerFired() { client_->OnTimerTick(); } -void DelayBasedTimeSource::SetClient(TimeSourceClient* client) { +void DelayBasedTimeSource::SetClient(DelayBasedTimeSourceClient* client) { client_ = client; } void DelayBasedTimeSource::SetTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) { - DCHECK_GT(interval.ToInternalValue(), 0); - next_parameters_.interval = interval; - next_parameters_.tick_target = timebase; - - if (!active_) { - // If we aren't active, there's no need to reset the timer. - return; - } + DCHECK_GT(interval, base::TimeDelta()); // If the change in interval is larger than the change threshold, // request an immediate reset. - double interval_delta = - std::abs((interval - current_parameters_.interval).InSecondsF()); + double interval_delta = std::abs((interval - interval_).InSecondsF()); + // Comparing with next_tick_time_ is the right thing to do because we want to + // know if we want to cancel the existing tick task and schedule a new one. + // Also next_tick_time_ = timebase_ mod interval_. + double timebase_delta = std::abs((timebase - next_tick_time_).InSecondsF()); + + interval_ = interval; + timebase_ = timebase; + + // If we aren't active, there's no need to reset the timer. + if (!active_) + return; + double interval_change = interval_delta / interval.InSecondsF(); if (interval_change > kIntervalChangeThreshold) { TRACE_EVENT_INSTANT0("cc", "DelayBasedTimeSource::IntervalChanged", TRACE_EVENT_SCOPE_THREAD); - SetActive(false); - SetActive(true); + ResetTickTask(Now()); return; } @@ -161,16 +144,13 @@ void DelayBasedTimeSource::SetTimebaseAndInterval(base::TimeTicks timebase, // fmod just happens to return something near zero. Assuming the timebase // is very recent though, which it should be, we'll still be ok because the // old clock and new clock just happen to line up. - double target_delta = - std::abs((timebase - current_parameters_.tick_target).InSecondsF()); double phase_change = - fmod(target_delta, interval.InSecondsF()) / interval.InSecondsF(); + fmod(timebase_delta, interval.InSecondsF()) / interval.InSecondsF(); if (phase_change > kPhaseChangeThreshold && phase_change < (1.0 - kPhaseChangeThreshold)) { TRACE_EVENT_INSTANT0("cc", "DelayBasedTimeSource::PhaseChanged", TRACE_EVENT_SCOPE_THREAD); - SetActive(false); - SetActive(true); + ResetTickTask(Now()); return; } } @@ -233,47 +213,41 @@ base::TimeTicks DelayBasedTimeSource::Now() const { // is not reset. // now=37 tick_target=16.667 new_target=50.000 --> // tick(), PostDelayedTask(floor(50.000-37)) --> PostDelayedTask(13) -base::TimeTicks DelayBasedTimeSource::NextTickTarget(base::TimeTicks now) { - base::TimeTicks new_tick_target = now.SnappedToNextTick( - next_parameters_.tick_target, next_parameters_.interval); - DCHECK(now <= new_tick_target) +base::TimeTicks DelayBasedTimeSource::NextTickTarget( + base::TimeTicks now) const { + base::TimeTicks next_tick_target = + now.SnappedToNextTick(timebase_, interval_); + DCHECK(now <= next_tick_target) << "now = " << now.ToInternalValue() - << "; new_tick_target = " << new_tick_target.ToInternalValue() - << "; new_interval = " << next_parameters_.interval.InMicroseconds() - << "; tick_target = " << next_parameters_.tick_target.ToInternalValue(); + << "; new_tick_target = " << next_tick_target.ToInternalValue() + << "; new_interval = " << interval_.InMicroseconds() + << "; new_timbase = " << timebase_.ToInternalValue(); // Avoid double ticks when: // 1) Turning off the timer and turning it right back on. // 2) Jittery data is passed to SetTimebaseAndInterval(). - if (new_tick_target - last_tick_time_ <= - next_parameters_.interval / kDoubleTickDivisor) - new_tick_target += next_parameters_.interval; + if (next_tick_target - last_tick_time_ <= interval_ / kDoubleTickDivisor) + next_tick_target += interval_; - return new_tick_target; + return next_tick_target; } void DelayBasedTimeSource::PostNextTickTask(base::TimeTicks now) { - base::TimeTicks new_tick_target = NextTickTarget(now); - + next_tick_time_ = NextTickTarget(now); + DCHECK(next_tick_time_ >= now); // Post another task *before* the tick and update state - base::TimeDelta delay; - if (now <= new_tick_target) - delay = new_tick_target - now; - task_runner_->PostDelayedTask(FROM_HERE, - base::Bind(&DelayBasedTimeSource::OnTimerFired, - weak_factory_.GetWeakPtr()), - delay); - - next_parameters_.tick_target = new_tick_target; - current_parameters_ = next_parameters_; + base::TimeDelta delay = next_tick_time_ - now; + task_runner_->PostDelayedTask(FROM_HERE, tick_closure_.callback(), delay); } -std::string DelayBasedTimeSource::TypeString() const { - return "DelayBasedTimeSource"; +void DelayBasedTimeSource::ResetTickTask(base::TimeTicks now) { + tick_closure_.Reset(base::Bind(&DelayBasedTimeSource::OnTimerTick, + weak_factory_.GetWeakPtr())); + PostNextTickTask(now); } -std::string DelayBasedTimeSourceHighRes::TypeString() const { - return "DelayBasedTimeSourceHighRes"; +std::string DelayBasedTimeSource::TypeString() const { + return "DelayBasedTimeSource"; } void DelayBasedTimeSource::AsValueInto( @@ -281,20 +255,8 @@ void DelayBasedTimeSource::AsValueInto( state->SetString("type", TypeString()); state->SetDouble("last_tick_time_us", LastTickTime().ToInternalValue()); state->SetDouble("next_tick_time_us", NextTickTime().ToInternalValue()); - - state->BeginDictionary("current_parameters"); - state->SetDouble("interval_us", - current_parameters_.interval.InMicroseconds()); - state->SetDouble("tick_target_us", - current_parameters_.tick_target.ToInternalValue()); - state->EndDictionary(); - - state->BeginDictionary("next_parameters"); - state->SetDouble("interval_us", next_parameters_.interval.InMicroseconds()); - state->SetDouble("tick_target_us", - next_parameters_.tick_target.ToInternalValue()); - state->EndDictionary(); - + state->SetDouble("interval_us", interval_.InMicroseconds()); + state->SetDouble("timebase_us", timebase_.ToInternalValue()); state->SetBoolean("active", active_); } diff --git a/chromium/cc/scheduler/delay_based_time_source.h b/chromium/cc/scheduler/delay_based_time_source.h index 4d7276c97c8..cd474a5c807 100644 --- a/chromium/cc/scheduler/delay_based_time_source.h +++ b/chromium/cc/scheduler/delay_based_time_source.h @@ -7,6 +7,7 @@ #include <string> +#include "base/cancelable_callback.h" #include "base/memory/weak_ptr.h" #include "base/values.h" #include "cc/base/cc_export.h" @@ -19,101 +20,78 @@ class SingleThreadTaskRunner; } namespace cc { - -class CC_EXPORT TimeSourceClient { +class CC_EXPORT DelayBasedTimeSourceClient { public: virtual void OnTimerTick() = 0; protected: - virtual ~TimeSourceClient() {} + virtual ~DelayBasedTimeSourceClient() {} }; // This timer implements a time source that achieves the specified interval // in face of millisecond-precision delayed callbacks and random queueing // delays. DelayBasedTimeSource uses base::TimeTicks::Now as its timebase. -class CC_EXPORT DelayBasedTimeSource - : public base::RefCounted<DelayBasedTimeSource> { +class CC_EXPORT DelayBasedTimeSource { public: - static scoped_refptr<DelayBasedTimeSource> Create( - base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner); + static scoped_ptr<DelayBasedTimeSource> Create( + base::TimeDelta interval, + base::SingleThreadTaskRunner* task_runner) { + return make_scoped_ptr(new DelayBasedTimeSource(interval, task_runner)); + } + + virtual ~DelayBasedTimeSource(); + + void SetClient(DelayBasedTimeSourceClient* client); - virtual void SetClient(TimeSourceClient* client); + void SetTimebaseAndInterval(base::TimeTicks timebase, + base::TimeDelta interval); - // TimeSource implementation - virtual void SetTimebaseAndInterval(base::TimeTicks timebase, - base::TimeDelta interval); - base::TimeDelta Interval() const { return next_parameters_.interval; } + base::TimeDelta Interval() const; - virtual base::TimeTicks SetActive(bool active); - virtual bool Active() const; + // Returns the time for the last missed tick. + base::TimeTicks SetActive(bool active); + bool Active() const; // Get the last and next tick times. NextTickTime() returns null when // inactive. - virtual base::TimeTicks LastTickTime() const; - virtual base::TimeTicks NextTickTime() const; - - // Virtual for testing. - virtual base::TimeTicks Now() const; + base::TimeTicks LastTickTime() const; + base::TimeTicks NextTickTime() const; virtual void AsValueInto(base::trace_event::TracedValue* dict) const; protected: DelayBasedTimeSource(base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner); - virtual ~DelayBasedTimeSource(); + // Virtual for testing. + virtual base::TimeTicks Now() const; virtual std::string TypeString() const; - base::TimeTicks NextTickTarget(base::TimeTicks now); - void PostNextTickTask(base::TimeTicks now); - void OnTimerFired(); + private: + base::TimeTicks NextTickTarget(base::TimeTicks now) const; - struct Parameters { - Parameters(base::TimeDelta interval, base::TimeTicks tick_target) - : interval(interval), tick_target(tick_target) {} - base::TimeDelta interval; - base::TimeTicks tick_target; - }; + void PostNextTickTask(base::TimeTicks now); + void ResetTickTask(base::TimeTicks now); - TimeSourceClient* client_; - base::TimeTicks last_tick_time_; + void OnTimerTick(); - // current_parameters_ should only be written by PostNextTickTask. - // next_parameters_ will take effect on the next call to PostNextTickTask. - // Maintaining a pending set of parameters allows NextTickTime() to always - // reflect the actual time we expect OnTimerFired to be called. - Parameters current_parameters_; - Parameters next_parameters_; + DelayBasedTimeSourceClient* client_; bool active_; - base::SingleThreadTaskRunner* task_runner_; - base::WeakPtrFactory<DelayBasedTimeSource> weak_factory_; + base::TimeTicks timebase_; + base::TimeDelta interval_; - private: - friend class base::RefCounted<DelayBasedTimeSource>; - DISALLOW_COPY_AND_ASSIGN(DelayBasedTimeSource); -}; - -// DelayBasedTimeSource that once used base::TimeTicks::HighResNow as its time -// source, but is now a no-op. -// TODO(brianderson): Remove along with gfx::/FrameTime.http://crbug.com/447329 -class DelayBasedTimeSourceHighRes : public DelayBasedTimeSource { - public: - static scoped_refptr<DelayBasedTimeSourceHighRes> Create( - base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner); + base::TimeTicks last_tick_time_; + base::TimeTicks next_tick_time_; - base::TimeTicks Now() const override; + base::CancelableClosure tick_closure_; - protected: - DelayBasedTimeSourceHighRes(base::TimeDelta interval, - base::SingleThreadTaskRunner* task_runner); - ~DelayBasedTimeSourceHighRes() override; + base::SingleThreadTaskRunner* task_runner_; - std::string TypeString() const override; + base::WeakPtrFactory<DelayBasedTimeSource> weak_factory_; - private: - DISALLOW_COPY_AND_ASSIGN(DelayBasedTimeSourceHighRes); + DISALLOW_COPY_AND_ASSIGN(DelayBasedTimeSource); }; } // namespace cc diff --git a/chromium/cc/scheduler/delay_based_time_source_unittest.cc b/chromium/cc/scheduler/delay_based_time_source_unittest.cc index f721b11ff7f..948e0205bbf 100644 --- a/chromium/cc/scheduler/delay_based_time_source_unittest.cc +++ b/chromium/cc/scheduler/delay_based_time_source_unittest.cc @@ -20,8 +20,8 @@ base::TimeDelta Interval() { TEST(DelayBasedTimeSourceTest, TaskPostedAndTickCalled) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); @@ -38,8 +38,8 @@ TEST(DelayBasedTimeSourceTest, TaskPostedAndTickCalled) { TEST(DelayBasedTimeSourceTest, TickNotCalledWithTaskPosted) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -52,8 +52,8 @@ TEST(DelayBasedTimeSourceTest, TickNotCalledWithTaskPosted) { TEST(DelayBasedTimeSourceTest, StartTwiceEnqueuesOneTask) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -66,8 +66,8 @@ TEST(DelayBasedTimeSourceTest, StartTwiceEnqueuesOneTask) { TEST(DelayBasedTimeSourceTest, StartWhenRunningDoesntTick) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -83,8 +83,8 @@ TEST(DelayBasedTimeSourceTest, StartWhenRunningDoesntTick) { TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenExactlyOnRequestedTime) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -104,8 +104,8 @@ TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenExactlyOnRequestedTime) { TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenSlightlyAfterRequestedTime) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -127,8 +127,8 @@ TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenExactlyTwiceAfterRequestedTime) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -149,8 +149,8 @@ TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenSlightlyAfterTwiceRequestedTime) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -171,8 +171,8 @@ TEST(DelayBasedTimeSourceTest, TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenHalfAfterRequestedTime) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -193,8 +193,8 @@ TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenHalfAfterRequestedTime) { TEST(DelayBasedTimeSourceTest, SaneHandlingOfJitteryTimebase) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -224,8 +224,8 @@ TEST(DelayBasedTimeSourceTest, SaneHandlingOfJitteryTimebase) { TEST(DelayBasedTimeSourceTest, HandlesSignificantTimebaseChangesImmediately) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -268,8 +268,8 @@ TEST(DelayBasedTimeSourceTest, HandlesSignificantTimebaseChangesImmediately) { TEST(DelayBasedTimeSourceTest, HanldlesSignificantIntervalChangesImmediately) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -310,8 +310,8 @@ TEST(DelayBasedTimeSourceTest, HanldlesSignificantIntervalChangesImmediately) { TEST(DelayBasedTimeSourceTest, JitteryRuntimeWithFutureTimebases) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -421,8 +421,8 @@ TEST(DelayBasedTimeSourceTest, AchievesTargetRateWithNoNoise) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); @@ -446,8 +446,8 @@ TEST(DelayBasedTimeSourceTest, AchievesTargetRateWithNoNoise) { TEST(DelayBasedTimeSourceTest, TestDeactivateWhilePending) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); timer->SetActive(true); // Should post a task. @@ -461,8 +461,8 @@ TEST(DelayBasedTimeSourceTest, TestDeactivateWhilePending) { TEST(DelayBasedTimeSourceTest, TestDeactivateAndReactivateBeforeNextTickTime) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); @@ -486,8 +486,8 @@ TEST(DelayBasedTimeSourceTest, TestDeactivateAndReactivateBeforeNextTickTime) { TEST(DelayBasedTimeSourceTest, TestDeactivateAndReactivateAfterNextTickTime) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); @@ -511,8 +511,8 @@ TEST(DelayBasedTimeSourceTest, TestDeactivateAndReactivateAfterNextTickTime) { TEST(DelayBasedTimeSourceTest, TestReturnValueWhenTimerIsDeActivated) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; - FakeTimeSourceClient client; - scoped_refptr<FakeDelayBasedTimeSource> timer = + FakeDelayBasedTimeSourceClient client; + scoped_ptr<FakeDelayBasedTimeSource> timer = FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); timer->SetClient(&client); diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc index d2520335c0c..2b668e83011 100644 --- a/chromium/cc/scheduler/scheduler.cc +++ b/chromium/cc/scheduler/scheduler.cc @@ -14,104 +14,79 @@ #include "base/trace_event/trace_event_argument.h" #include "cc/debug/devtools_instrumentation.h" #include "cc/debug/traced_value.h" +#include "cc/scheduler/compositor_timing_history.h" #include "cc/scheduler/delay_based_time_source.h" -#include "ui/gfx/frame_time.h" namespace cc { -BeginFrameSource* SchedulerFrameSourcesConstructor::ConstructPrimaryFrameSource( - Scheduler* scheduler) { - if (scheduler->settings_.use_external_begin_frame_source) { - TRACE_EVENT1("cc", - "Scheduler::Scheduler()", - "PrimaryFrameSource", - "ExternalBeginFrameSource"); - DCHECK(scheduler->primary_frame_source_internal_) - << "Need external BeginFrameSource"; - return scheduler->primary_frame_source_internal_.get(); - } else { - TRACE_EVENT1("cc", - "Scheduler::Scheduler()", - "PrimaryFrameSource", - "SyntheticBeginFrameSource"); - scoped_ptr<SyntheticBeginFrameSource> synthetic_source = - SyntheticBeginFrameSource::Create(scheduler->task_runner_.get(), - scheduler->Now(), - BeginFrameArgs::DefaultInterval()); - - DCHECK(!scheduler->vsync_observer_); - scheduler->vsync_observer_ = synthetic_source.get(); - - DCHECK(!scheduler->primary_frame_source_internal_); - scheduler->primary_frame_source_internal_ = synthetic_source.Pass(); - return scheduler->primary_frame_source_internal_.get(); +scoped_ptr<Scheduler> Scheduler::Create( + SchedulerClient* client, + const SchedulerSettings& settings, + int layer_tree_host_id, + base::SingleThreadTaskRunner* task_runner, + BeginFrameSource* external_frame_source, + scoped_ptr<CompositorTimingHistory> compositor_timing_history) { + scoped_ptr<SyntheticBeginFrameSource> synthetic_frame_source; + if (!settings.use_external_begin_frame_source) { + synthetic_frame_source = SyntheticBeginFrameSource::Create( + task_runner, BeginFrameArgs::DefaultInterval()); } -} - -BeginFrameSource* -SchedulerFrameSourcesConstructor::ConstructUnthrottledFrameSource( - Scheduler* scheduler) { - TRACE_EVENT1("cc", "Scheduler::Scheduler()", "UnthrottledFrameSource", - "BackToBackBeginFrameSource"); - DCHECK(!scheduler->unthrottled_frame_source_internal_); - scheduler->unthrottled_frame_source_internal_ = - BackToBackBeginFrameSource::Create(scheduler->task_runner_.get()); - return scheduler->unthrottled_frame_source_internal_.get(); + scoped_ptr<BackToBackBeginFrameSource> unthrottled_frame_source = + BackToBackBeginFrameSource::Create(task_runner); + return make_scoped_ptr(new Scheduler( + client, settings, layer_tree_host_id, task_runner, external_frame_source, + synthetic_frame_source.Pass(), unthrottled_frame_source.Pass(), + compositor_timing_history.Pass())); } Scheduler::Scheduler( SchedulerClient* client, - const SchedulerSettings& scheduler_settings, + const SchedulerSettings& settings, int layer_tree_host_id, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - scoped_ptr<BeginFrameSource> external_begin_frame_source, - SchedulerFrameSourcesConstructor* frame_sources_constructor) - : frame_source_(), - primary_frame_source_(NULL), - primary_frame_source_internal_(external_begin_frame_source.Pass()), - vsync_observer_(NULL), - authoritative_vsync_interval_(base::TimeDelta()), - last_vsync_timebase_(base::TimeTicks()), - throttle_frame_production_(false), - settings_(scheduler_settings), + base::SingleThreadTaskRunner* task_runner, + BeginFrameSource* external_frame_source, + scoped_ptr<SyntheticBeginFrameSource> synthetic_frame_source, + scoped_ptr<BackToBackBeginFrameSource> unthrottled_frame_source, + scoped_ptr<CompositorTimingHistory> compositor_timing_history) + : settings_(settings), client_(client), layer_tree_host_id_(layer_tree_host_id), task_runner_(task_runner), + external_frame_source_(external_frame_source), + synthetic_frame_source_(synthetic_frame_source.Pass()), + unthrottled_frame_source_(unthrottled_frame_source.Pass()), + frame_source_(BeginFrameSourceMultiplexer::Create()), + throttle_frame_production_(false), + compositor_timing_history_(compositor_timing_history.Pass()), begin_impl_frame_deadline_mode_( SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE), - state_machine_(scheduler_settings), + begin_impl_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), + state_machine_(settings), inside_process_scheduled_actions_(false), inside_action_(SchedulerStateMachine::ACTION_NONE), weak_factory_(this) { - TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), - "Scheduler::Scheduler", - "settings", - settings_.AsValue()); + TRACE_EVENT1("cc", "Scheduler::Scheduler", "settings", settings_.AsValue()); DCHECK(client_); DCHECK(!state_machine_.BeginFrameNeeded()); + DCHECK_IMPLIES(settings_.use_external_begin_frame_source, + external_frame_source_); + DCHECK_IMPLIES(!settings_.use_external_begin_frame_source, + synthetic_frame_source_); + DCHECK(unthrottled_frame_source_); begin_retro_frame_closure_ = base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); begin_impl_frame_deadline_closure_ = base::Bind( &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); - advance_commit_state_closure_ = base::Bind( - &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); - frame_source_ = BeginFrameSourceMultiplexer::Create(); frame_source_->AddObserver(this); + frame_source_->AddSource(primary_frame_source()); + primary_frame_source()->SetClientReady(); - // Primary frame source - primary_frame_source_ = - frame_sources_constructor->ConstructPrimaryFrameSource(this); - frame_source_->AddSource(primary_frame_source_); - primary_frame_source_->SetClientReady(); + frame_source_->AddSource(unthrottled_frame_source_.get()); + unthrottled_frame_source_->SetClientReady(); - // Unthrottled frame source - unthrottled_frame_source_ = - frame_sources_constructor->ConstructUnthrottledFrameSource(this); - frame_source_->AddSource(unthrottled_frame_source_); - - SetThrottleFrameProduction(scheduler_settings.throttle_frame_production); + SetThrottleFrameProduction(settings_.throttle_frame_production); } Scheduler::~Scheduler() { @@ -121,7 +96,7 @@ Scheduler::~Scheduler() { } base::TimeTicks Scheduler::Now() const { - base::TimeTicks now = gfx::FrameTime::Now(); + base::TimeTicks now = base::TimeTicks::Now(); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"), "Scheduler::Now", "now", @@ -140,8 +115,8 @@ void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, last_vsync_timebase_ = timebase; - if (vsync_observer_) - vsync_observer_->OnUpdateVSyncParameters(timebase, interval); + if (synthetic_frame_source_) + synthetic_frame_source_->OnUpdateVSyncParameters(timebase, interval); } void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { @@ -156,6 +131,7 @@ void Scheduler::SetCanStart() { void Scheduler::SetVisible(bool visible) { state_machine_.SetVisible(visible); + UpdateCompositorTimingHistoryRecordingEnabled(); ProcessScheduledActions(); } @@ -165,6 +141,7 @@ void Scheduler::SetCanDraw(bool can_draw) { } void Scheduler::NotifyReadyToActivate() { + compositor_timing_history_->ReadyToActivate(); state_machine_.NotifyReadyToActivate(); ProcessScheduledActions(); } @@ -178,9 +155,9 @@ void Scheduler::NotifyReadyToDraw() { void Scheduler::SetThrottleFrameProduction(bool throttle) { throttle_frame_production_ = throttle; if (throttle) { - frame_source_->SetActiveSource(primary_frame_source_); + frame_source_->SetActiveSource(primary_frame_source()); } else { - frame_source_->SetActiveSource(unthrottled_frame_source_); + frame_source_->SetActiveSource(unthrottled_frame_source_.get()); } ProcessScheduledActions(); } @@ -226,6 +203,7 @@ void Scheduler::DidSwapBuffers() { } void Scheduler::DidSwapBuffersComplete() { + DCHECK_GT(state_machine_.pending_swaps(), 0) << AsValue()->ToString(); state_machine_.DidSwapBuffersComplete(); ProcessScheduledActions(); } @@ -241,14 +219,24 @@ void Scheduler::NotifyReadyToCommit() { ProcessScheduledActions(); } +void Scheduler::DidCommit() { + compositor_timing_history_->DidCommit(); +} + void Scheduler::BeginMainFrameAborted(CommitEarlyOutReason reason) { TRACE_EVENT1("cc", "Scheduler::BeginMainFrameAborted", "reason", CommitEarlyOutReasonToString(reason)); + compositor_timing_history_->BeginMainFrameAborted(); state_machine_.BeginMainFrameAborted(reason); ProcessScheduledActions(); } +void Scheduler::WillPrepareTiles() { + compositor_timing_history_->WillPrepareTiles(); +} + void Scheduler::DidPrepareTiles() { + compositor_timing_history_->DidPrepareTiles(); state_machine_.DidPrepareTiles(); } @@ -257,6 +245,7 @@ void Scheduler::DidLoseOutputSurface() { begin_retro_frame_args_.clear(); begin_retro_frame_task_.Cancel(); state_machine_.DidLoseOutputSurface(); + UpdateCompositorTimingHistoryRecordingEnabled(); ProcessScheduledActions(); } @@ -265,6 +254,7 @@ void Scheduler::DidCreateAndInitializeOutputSurface() { DCHECK(!frame_source_->NeedsBeginFrames()); DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); state_machine_.DidCreateAndInitializeOutputSurface(); + UpdateCompositorTimingHistoryRecordingEnabled(); ProcessScheduledActions(); } @@ -273,20 +263,8 @@ void Scheduler::NotifyBeginMainFrameStarted() { state_machine_.NotifyBeginMainFrameStarted(); } -base::TimeTicks Scheduler::AnticipatedDrawTime() const { - if (!frame_source_->NeedsBeginFrames() || - begin_impl_frame_args_.interval <= base::TimeDelta()) - return base::TimeTicks(); - - base::TimeTicks now = Now(); - base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, - begin_impl_frame_args_.deadline); - int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); - return timebase + (begin_impl_frame_args_.interval * intervals); -} - base::TimeTicks Scheduler::LastBeginImplFrameTime() { - return begin_impl_frame_args_.frame_time; + return begin_impl_frame_tracker_.Current().frame_time; } void Scheduler::SetupNextBeginFrameIfNeeded() { @@ -296,53 +274,37 @@ void Scheduler::SetupNextBeginFrameIfNeeded() { if (state_machine_.BeginFrameNeeded()) { // Call SetNeedsBeginFrames(true) as soon as possible. frame_source_->SetNeedsBeginFrames(true); + devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, + true); } else if (state_machine_.begin_impl_frame_state() == SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) { // Call SetNeedsBeginFrames(false) in between frames only. frame_source_->SetNeedsBeginFrames(false); client_->SendBeginMainFrameNotExpectedSoon(); + devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, + false); } } PostBeginRetroFrameIfNeeded(); } -// We may need to poll when we can't rely on BeginFrame to advance certain -// state or to avoid deadlock. -void Scheduler::SetupPollingMechanisms() { - // At this point we'd prefer to advance through the commit flow by - // drawing a frame, however it's possible that the frame rate controller - // will not give us a BeginFrame until the commit completes. See - // crbug.com/317430 for an example of a swap ack being held on commit. Thus - // we set a repeating timer to poll on ProcessScheduledActions until we - // successfully reach BeginFrame. Synchronous compositor does not use - // frame rate controller or have the circular wait in the bug. - if (IsBeginMainFrameSentOrStarted() && - !settings_.using_synchronous_renderer_compositor) { - if (advance_commit_state_task_.IsCancelled() && - begin_impl_frame_args_.IsValid()) { - // Since we'd rather get a BeginImplFrame by the normal mechanism, we - // set the interval to twice the interval from the previous frame. - advance_commit_state_task_.Reset(advance_commit_state_closure_); - task_runner_->PostDelayedTask(FROM_HERE, - advance_commit_state_task_.callback(), - begin_impl_frame_args_.interval * 2); - } - } else { - advance_commit_state_task_.Cancel(); - } -} - // BeginFrame is the mechanism that tells us that now is a good time to start // making a frame. Usually this means that user input for the frame is complete. // If the scheduler is busy, we queue the BeginFrame to be handled later as // a BeginRetroFrame. -bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) { +bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); + // Trace this begin frame time through the Chrome stack + TRACE_EVENT_FLOW_BEGIN0( + TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", + args.frame_time.ToInternalValue()); + // TODO(brianderson): Adjust deadline in the DisplayScheduler. BeginFrameArgs adjusted_args(args); adjusted_args.deadline -= EstimatedParentDrawTime(); + adjusted_args.on_critical_path = !ImplLatencyTakesPriority(); // Deliver BeginFrames to children. // TODO(brianderson): Move this responsibility to the DisplayScheduler. @@ -389,8 +351,10 @@ void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) { authoritative_vsync_interval_ = interval; - if (vsync_observer_) - vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval); + if (synthetic_frame_source_) { + synthetic_frame_source_->OnUpdateVSyncParameters(last_vsync_timebase_, + interval); + } } void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { @@ -434,7 +398,7 @@ void Scheduler::BeginRetroFrame() { while (!begin_retro_frame_args_.empty()) { const BeginFrameArgs& args = begin_retro_frame_args_.front(); - base::TimeTicks expiration_time = args.frame_time + args.interval; + base::TimeTicks expiration_time = args.deadline; if (now <= expiration_time) break; TRACE_EVENT_INSTANT2( @@ -493,18 +457,21 @@ void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), "MainThreadLatency", main_thread_is_in_high_latency_mode); - advance_commit_state_task_.Cancel(); - - begin_impl_frame_args_ = args; - begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); + BeginFrameArgs adjusted_args = args; + adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); - if (!state_machine_.impl_latency_takes_priority() && - main_thread_is_in_high_latency_mode && - CanCommitAndActivateBeforeDeadline()) { + if (ShouldRecoverMainLatency(adjusted_args)) { + TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", + TRACE_EVENT_SCOPE_THREAD); state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); + } else if (ShouldRecoverImplLatency(adjusted_args)) { + TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", + TRACE_EVENT_SCOPE_THREAD); + frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); + return; } - BeginImplFrame(); + BeginImplFrame(adjusted_args); // The deadline will be scheduled in ProcessScheduledActions. state_machine_.OnBeginImplFrameDeadlinePending(); @@ -514,8 +481,7 @@ void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", args.AsValue()); - begin_impl_frame_args_ = args; - BeginImplFrame(); + BeginImplFrame(args); FinishImplFrame(); } @@ -525,21 +491,22 @@ void Scheduler::FinishImplFrame() { client_->DidFinishImplFrame(); frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); + begin_impl_frame_tracker_.Finish(); } // BeginImplFrame starts a compositor frame that will wait up until a deadline // for a BeginMainFrame+activation to complete before it times out and draws // any asynchronous animation and scroll/pinch updates. -void Scheduler::BeginImplFrame() { +void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { DCHECK_EQ(state_machine_.begin_impl_frame_state(), SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); DCHECK(!BeginImplFrameDeadlinePending()); DCHECK(state_machine_.HasInitializedOutputSurface()); - DCHECK(advance_commit_state_task_.IsCancelled()); + begin_impl_frame_tracker_.Start(args); state_machine_.OnBeginImplFrame(); devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); - client_->WillBeginImplFrame(begin_impl_frame_args_); + client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); ProcessScheduledActions(); } @@ -553,7 +520,6 @@ void Scheduler::ScheduleBeginImplFrameDeadline() { begin_impl_frame_deadline_mode_ = state_machine_.CurrentBeginImplFrameDeadlineMode(); - base::TimeTicks deadline; switch (begin_impl_frame_deadline_mode_) { case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE: @@ -566,14 +532,14 @@ void Scheduler::ScheduleBeginImplFrameDeadline() { break; case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR: // We are animating on the impl thread but we can wait for some time. - deadline = begin_impl_frame_args_.deadline; + deadline = begin_impl_frame_tracker_.Current().deadline; break; case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE: // We are blocked for one reason or another and we should wait. // TODO(brianderson): Handle long deadlines (that are past the next // frame's frame time) properly instead of using this hack. - deadline = - begin_impl_frame_args_.frame_time + begin_impl_frame_args_.interval; + deadline = begin_impl_frame_tracker_.Current().frame_time + + begin_impl_frame_tracker_.Current().interval; break; case SchedulerStateMachine:: BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW: @@ -630,16 +596,17 @@ void Scheduler::OnBeginImplFrameDeadline() { FinishImplFrame(); } - -void Scheduler::PollToAdvanceCommitState() { - TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState"); - advance_commit_state_task_.Cancel(); - ProcessScheduledActions(); -} - void Scheduler::DrawAndSwapIfPossible() { + compositor_timing_history_->WillDraw(); DrawResult result = client_->ScheduledActionDrawAndSwapIfPossible(); state_machine_.DidDrawIfPossibleCompleted(result); + compositor_timing_history_->DidDraw(); +} + +void Scheduler::DrawAndSwapForced() { + compositor_timing_history_->WillDraw(); + client_->ScheduledActionDrawAndSwapForced(); + compositor_timing_history_->DidDraw(); } void Scheduler::SetDeferCommits(bool defer_commits) { @@ -665,9 +632,6 @@ void Scheduler::ProcessScheduledActions() { "SchedulerStateMachine", "state", AsValue()); - VLOG(2) << "Scheduler::ProcessScheduledActions: " - << SchedulerStateMachine::ActionToString(action) << " " - << state_machine_.GetStatesForDebugging(); state_machine_.UpdateState(action); base::AutoReset<SchedulerStateMachine::Action> mark_inside_action(&inside_action_, action); @@ -678,6 +642,7 @@ void Scheduler::ProcessScheduledActions() { client_->ScheduledActionAnimate(); break; case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: + compositor_timing_history_->WillBeginMainFrame(); client_->ScheduledActionSendBeginMainFrame(); break; case SchedulerStateMachine::ACTION_COMMIT: { @@ -690,7 +655,9 @@ void Scheduler::ProcessScheduledActions() { break; } case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE: + compositor_timing_history_->WillActivate(); client_->ScheduledActionActivateSyncTree(); + compositor_timing_history_->DidActivate(); break; case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: { // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is @@ -702,7 +669,7 @@ void Scheduler::ProcessScheduledActions() { break; } case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: - client_->ScheduledActionDrawAndSwapForced(); + DrawAndSwapForced(); break; case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: // No action is actually performed, but this allows the state machine to @@ -721,12 +688,7 @@ void Scheduler::ProcessScheduledActions() { } } while (action != SchedulerStateMachine::ACTION_NONE); - SetupPollingMechanisms(); - - client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); - ScheduleBeginImplFrameDeadlineIfNeeded(); - SetupNextBeginFrameIfNeeded(); } @@ -739,6 +701,8 @@ scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue() } void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { + base::TimeTicks now = Now(); + state->BeginDictionary("state_machine"); state_machine_.AsValueInto(state); state->EndDictionary(); @@ -755,71 +719,92 @@ void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { } state->BeginDictionary("scheduler_state"); - state->SetDouble("time_until_anticipated_draw_time_ms", - (AnticipatedDrawTime() - Now()).InMillisecondsF()); state->SetDouble("estimated_parent_draw_time_ms", estimated_parent_draw_time_.InMillisecondsF()); state->SetBoolean("last_set_needs_begin_frame_", frame_source_->NeedsBeginFrames()); - state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); - state->SetBoolean("begin_retro_frame_task_", + state->SetInteger("begin_retro_frame_args", + static_cast<int>(begin_retro_frame_args_.size())); + state->SetBoolean("begin_retro_frame_task", !begin_retro_frame_task_.IsCancelled()); - state->SetBoolean("begin_impl_frame_deadline_task_", + state->SetBoolean("begin_impl_frame_deadline_task", !begin_impl_frame_deadline_task_.IsCancelled()); - state->SetBoolean("advance_commit_state_task_", - !advance_commit_state_task_.IsCancelled()); + state->SetString("inside_action", + SchedulerStateMachine::ActionToString(inside_action_)); + state->BeginDictionary("begin_impl_frame_args"); - begin_impl_frame_args_.AsValueInto(state); + begin_impl_frame_tracker_.AsValueInto(now, state); state->EndDictionary(); - base::TimeTicks now = Now(); - base::TimeTicks frame_time = begin_impl_frame_args_.frame_time; - base::TimeTicks deadline = begin_impl_frame_args_.deadline; - base::TimeDelta interval = begin_impl_frame_args_.interval; - state->BeginDictionary("major_timestamps_in_ms"); - state->SetDouble("0_interval", interval.InMillisecondsF()); - state->SetDouble("1_now_to_deadline", (deadline - now).InMillisecondsF()); - state->SetDouble("2_frame_time_to_now", (now - frame_time).InMillisecondsF()); - state->SetDouble("3_frame_time_to_deadline", - (deadline - frame_time).InMillisecondsF()); - state->SetDouble("4_now", (now - base::TimeTicks()).InMillisecondsF()); - state->SetDouble("5_frame_time", - (frame_time - base::TimeTicks()).InMillisecondsF()); - state->SetDouble("6_deadline", - (deadline - base::TimeTicks()).InMillisecondsF()); + state->SetString("begin_impl_frame_deadline_mode_", + SchedulerStateMachine::BeginImplFrameDeadlineModeToString( + begin_impl_frame_deadline_mode_)); state->EndDictionary(); + state->BeginDictionary("compositor_timing_history"); + compositor_timing_history_->AsValueInto(state); state->EndDictionary(); +} - state->BeginDictionary("client_state"); - state->SetDouble("draw_duration_estimate_ms", - client_->DrawDurationEstimate().InMillisecondsF()); - state->SetDouble( - "begin_main_frame_to_commit_duration_estimate_ms", - client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); - state->SetDouble( - "commit_to_activate_duration_estimate_ms", - client_->CommitToActivateDurationEstimate().InMillisecondsF()); - state->EndDictionary(); +void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { + compositor_timing_history_->SetRecordingEnabled( + state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); } -bool Scheduler::CanCommitAndActivateBeforeDeadline() const { +bool Scheduler::ShouldRecoverMainLatency(const BeginFrameArgs& args) const { + DCHECK(!settings_.using_synchronous_renderer_compositor); + + if (!state_machine_.MainThreadIsInHighLatencyMode()) + return false; + + // When prioritizing impl thread latency, we currently put the + // main thread in a high latency mode. Don't try to fight it. + if (state_machine_.impl_latency_takes_priority()) + return false; + + return CanCommitAndActivateBeforeDeadline(args); +} + +bool Scheduler::ShouldRecoverImplLatency(const BeginFrameArgs& args) const { + DCHECK(!settings_.using_synchronous_renderer_compositor); + + // If we are swap throttled at the BeginFrame, that means the impl thread is + // very likely in a high latency mode. + bool impl_thread_is_likely_high_latency = state_machine_.SwapThrottled(); + if (!impl_thread_is_likely_high_latency) + return false; + + // The deadline may be in the past if our draw time is too long. + bool can_draw_before_deadline = args.frame_time < args.deadline; + + // When prioritizing impl thread latency, the deadline doesn't wait + // for the main thread. + if (state_machine_.impl_latency_takes_priority()) + return can_draw_before_deadline; + + // If we only have impl-side updates, the deadline doesn't wait for + // the main thread. + if (state_machine_.OnlyImplSideUpdatesExpected()) + return can_draw_before_deadline; + + // If we get here, we know the main thread is in a low-latency mode relative + // to the impl thread. In this case, only try to also recover impl thread + // latency if both the main and impl threads can run serially before the + // deadline. + return CanCommitAndActivateBeforeDeadline(args); +} + +bool Scheduler::CanCommitAndActivateBeforeDeadline( + const BeginFrameArgs& args) const { // Check if the main thread computation and commit can be finished before the // impl thread's deadline. base::TimeTicks estimated_draw_time = - begin_impl_frame_args_.frame_time + - client_->BeginMainFrameToCommitDurationEstimate() + - client_->CommitToActivateDurationEstimate(); - - TRACE_EVENT2( - TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), - "CanCommitAndActivateBeforeDeadline", - "time_left_after_drawing_ms", - (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), - "state", - AsValue()); - - return estimated_draw_time < begin_impl_frame_args_.deadline; + args.frame_time + + compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() + + compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + + compositor_timing_history_->ActivateDurationEstimate(); + + return estimated_draw_time < args.deadline; } bool Scheduler::IsBeginMainFrameSentOrStarted() const { diff --git a/chromium/cc/scheduler/scheduler.h b/chromium/cc/scheduler/scheduler.h index 13daf008cc3..d6fc074c541 100644 --- a/chromium/cc/scheduler/scheduler.h +++ b/chromium/cc/scheduler/scheduler.h @@ -14,8 +14,8 @@ #include "base/time/time.h" #include "cc/base/cc_export.h" #include "cc/output/begin_frame_args.h" -#include "cc/output/vsync_parameter_observer.h" #include "cc/scheduler/begin_frame_source.h" +#include "cc/scheduler/begin_frame_tracker.h" #include "cc/scheduler/delay_based_time_source.h" #include "cc/scheduler/draw_result.h" #include "cc/scheduler/scheduler_settings.h" @@ -30,6 +30,8 @@ class SingleThreadTaskRunner; namespace cc { +class CompositorTimingHistory; + class SchedulerClient { public: virtual void WillBeginImplFrame(const BeginFrameArgs& args) = 0; @@ -42,10 +44,6 @@ class SchedulerClient { virtual void ScheduledActionBeginOutputSurfaceCreation() = 0; virtual void ScheduledActionPrepareTiles() = 0; virtual void ScheduledActionInvalidateOutputSurface() = 0; - virtual void DidAnticipatedDrawTimeChange(base::TimeTicks time) = 0; - virtual base::TimeDelta DrawDurationEstimate() = 0; - virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() = 0; - virtual base::TimeDelta CommitToActivateDurationEstimate() = 0; virtual void DidFinishImplFrame() = 0; virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) = 0; virtual void SendBeginMainFrameNotExpectedSoon() = 0; @@ -54,45 +52,20 @@ class SchedulerClient { virtual ~SchedulerClient() {} }; -class Scheduler; -// This class exists to allow tests to override the frame source construction. -// A virtual method can't be used as this needs to happen in the constructor -// (see C++ FAQ / Section 23 - http://goo.gl/fnrwom for why). -// This class exists solely long enough to construct the frame sources. -class CC_EXPORT SchedulerFrameSourcesConstructor { - public: - virtual ~SchedulerFrameSourcesConstructor() {} - virtual BeginFrameSource* ConstructPrimaryFrameSource(Scheduler* scheduler); - virtual BeginFrameSource* ConstructUnthrottledFrameSource( - Scheduler* scheduler); - - protected: - SchedulerFrameSourcesConstructor() {} - - friend class Scheduler; -}; - -class CC_EXPORT Scheduler : public BeginFrameObserverMixIn { +class CC_EXPORT Scheduler : public BeginFrameObserverBase { public: static scoped_ptr<Scheduler> Create( SchedulerClient* client, const SchedulerSettings& scheduler_settings, int layer_tree_host_id, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - scoped_ptr<BeginFrameSource> external_begin_frame_source) { - SchedulerFrameSourcesConstructor frame_sources_constructor; - return make_scoped_ptr(new Scheduler(client, - scheduler_settings, - layer_tree_host_id, - task_runner, - external_begin_frame_source.Pass(), - &frame_sources_constructor)); - } + base::SingleThreadTaskRunner* task_runner, + BeginFrameSource* external_frame_source, + scoped_ptr<CompositorTimingHistory> compositor_timing_history); ~Scheduler() override; - // BeginFrameObserverMixin - bool OnBeginFrameMixInDelegate(const BeginFrameArgs& args) override; + // BeginFrameObserverBase + bool OnBeginFrameDerivedImpl(const BeginFrameArgs& args) override; void OnDrawForOutputSurface(); @@ -128,7 +101,9 @@ class CC_EXPORT Scheduler : public BeginFrameObserverMixIn { void NotifyReadyToCommit(); void BeginMainFrameAborted(CommitEarlyOutReason reason); + void DidCommit(); + void WillPrepareTiles(); void DidPrepareTiles(); void DidLoseOutputSurface(); void DidCreateAndInitializeOutputSurface(); @@ -145,14 +120,12 @@ class CC_EXPORT Scheduler : public BeginFrameObserverMixIn { bool PrepareTilesPending() const { return state_machine_.PrepareTilesPending(); } - bool MainThreadIsInHighLatencyMode() const { - return state_machine_.MainThreadIsInHighLatencyMode(); - } bool BeginImplFrameDeadlinePending() const { return !begin_impl_frame_deadline_task_.IsCancelled(); } - - base::TimeTicks AnticipatedDrawTime() const; + bool ImplLatencyTakesPriority() const { + return state_machine_.impl_latency_takes_priority(); + } void NotifyBeginMainFrameStarted(); @@ -176,46 +149,41 @@ class CC_EXPORT Scheduler : public BeginFrameObserverMixIn { Scheduler(SchedulerClient* client, const SchedulerSettings& scheduler_settings, int layer_tree_host_id, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - scoped_ptr<BeginFrameSource> external_begin_frame_source, - SchedulerFrameSourcesConstructor* frame_sources_constructor); + base::SingleThreadTaskRunner* task_runner, + BeginFrameSource* external_frame_source, + scoped_ptr<SyntheticBeginFrameSource> synthetic_frame_source, + scoped_ptr<BackToBackBeginFrameSource> unthrottled_frame_source, + scoped_ptr<CompositorTimingHistory> compositor_timing_history); - // virtual for testing - Don't call these in the constructor or - // destructor! + // Virtual for testing. virtual base::TimeTicks Now() const; - scoped_ptr<BeginFrameSourceMultiplexer> frame_source_; - BeginFrameSource* primary_frame_source_; - BeginFrameSource* unthrottled_frame_source_; + const SchedulerSettings settings_; + SchedulerClient* client_; + int layer_tree_host_id_; + base::SingleThreadTaskRunner* task_runner_; + BeginFrameSource* external_frame_source_; + scoped_ptr<SyntheticBeginFrameSource> synthetic_frame_source_; + scoped_ptr<BackToBackBeginFrameSource> unthrottled_frame_source_; - // Storage when frame sources are internal - scoped_ptr<BeginFrameSource> primary_frame_source_internal_; - scoped_ptr<BeginFrameSource> unthrottled_frame_source_internal_; + scoped_ptr<BeginFrameSourceMultiplexer> frame_source_; + bool throttle_frame_production_; - VSyncParameterObserver* vsync_observer_; base::TimeDelta authoritative_vsync_interval_; base::TimeTicks last_vsync_timebase_; - bool throttle_frame_production_; - - const SchedulerSettings settings_; - SchedulerClient* client_; - int layer_tree_host_id_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - + scoped_ptr<CompositorTimingHistory> compositor_timing_history_; base::TimeDelta estimated_parent_draw_time_; std::deque<BeginFrameArgs> begin_retro_frame_args_; - BeginFrameArgs begin_impl_frame_args_; SchedulerStateMachine::BeginImplFrameDeadlineMode begin_impl_frame_deadline_mode_; + BeginFrameTracker begin_impl_frame_tracker_; base::Closure begin_retro_frame_closure_; base::Closure begin_impl_frame_deadline_closure_; - base::Closure advance_commit_state_closure_; base::CancelableClosure begin_retro_frame_task_; base::CancelableClosure begin_impl_frame_deadline_task_; - base::CancelableClosure advance_commit_state_task_; SchedulerStateMachine state_machine_; bool inside_process_scheduled_actions_; @@ -226,16 +194,19 @@ class CC_EXPORT Scheduler : public BeginFrameObserverMixIn { void ScheduleBeginImplFrameDeadlineIfNeeded(); void SetupNextBeginFrameIfNeeded(); void PostBeginRetroFrameIfNeeded(); - void SetupPollingMechanisms(); void DrawAndSwapIfPossible(); + void DrawAndSwapForced(); void ProcessScheduledActions(); - bool CanCommitAndActivateBeforeDeadline() const; + void UpdateCompositorTimingHistoryRecordingEnabled(); + bool ShouldRecoverMainLatency(const BeginFrameArgs& args) const; + bool ShouldRecoverImplLatency(const BeginFrameArgs& args) const; + bool CanCommitAndActivateBeforeDeadline(const BeginFrameArgs& args) const; void AdvanceCommitStateIfPossible(); bool IsBeginMainFrameSentOrStarted() const; void BeginRetroFrame(); void BeginImplFrameWithDeadline(const BeginFrameArgs& args); void BeginImplFrameSynchronous(const BeginFrameArgs& args); - void BeginImplFrame(); + void BeginImplFrame(const BeginFrameArgs& args); void FinishImplFrame(); void OnBeginImplFrameDeadline(); void PollToAdvanceCommitState(); @@ -248,10 +219,15 @@ class CC_EXPORT Scheduler : public BeginFrameObserverMixIn { return inside_action_ == action; } - base::WeakPtrFactory<Scheduler> weak_factory_; + BeginFrameSource* primary_frame_source() { + if (settings_.use_external_begin_frame_source) { + DCHECK(external_frame_source_); + return external_frame_source_; + } + return synthetic_frame_source_.get(); + } - friend class SchedulerFrameSourcesConstructor; - friend class TestSchedulerFrameSourcesConstructor; + base::WeakPtrFactory<Scheduler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(Scheduler); }; diff --git a/chromium/cc/scheduler/scheduler_settings.cc b/chromium/cc/scheduler/scheduler_settings.cc index c6c8e8eb2db..d1d3a6f46c3 100644 --- a/chromium/cc/scheduler/scheduler_settings.cc +++ b/chromium/cc/scheduler/scheduler_settings.cc @@ -10,13 +10,13 @@ namespace cc { SchedulerSettings::SchedulerSettings() : use_external_begin_frame_source(false), + main_frame_while_swap_throttled_enabled(false), main_frame_before_activation_enabled(false), - impl_side_painting(false), + commit_to_active_tree(false), timeout_and_draw_when_animation_checkerboards(true), - maximum_number_of_failed_draws_before_draw_is_forced_(3), using_synchronous_renderer_compositor(false), throttle_frame_production(true), - main_thread_should_always_be_low_latency(false), + maximum_number_of_failed_draws_before_draw_is_forced(3), background_frame_interval(base::TimeDelta::FromSeconds(1)) { } @@ -28,18 +28,18 @@ SchedulerSettings::AsValue() const { new base::trace_event::TracedValue(); state->SetBoolean("use_external_begin_frame_source", use_external_begin_frame_source); + state->SetBoolean("main_frame_while_swap_throttled_enabled", + main_frame_while_swap_throttled_enabled); state->SetBoolean("main_frame_before_activation_enabled", main_frame_before_activation_enabled); - state->SetBoolean("impl_side_painting", impl_side_painting); + state->SetBoolean("commit_to_active_tree", commit_to_active_tree); state->SetBoolean("timeout_and_draw_when_animation_checkerboards", timeout_and_draw_when_animation_checkerboards); - state->SetInteger("maximum_number_of_failed_draws_before_draw_is_forced_", - maximum_number_of_failed_draws_before_draw_is_forced_); + state->SetInteger("maximum_number_of_failed_draws_before_draw_is_forced", + maximum_number_of_failed_draws_before_draw_is_forced); state->SetBoolean("using_synchronous_renderer_compositor", using_synchronous_renderer_compositor); state->SetBoolean("throttle_frame_production", throttle_frame_production); - state->SetBoolean("main_thread_should_always_be_low_latency", - main_thread_should_always_be_low_latency); state->SetInteger("background_frame_interval", background_frame_interval.InMicroseconds()); return state; diff --git a/chromium/cc/scheduler/scheduler_settings.h b/chromium/cc/scheduler/scheduler_settings.h index 421409ab4dc..e624cf8b939 100644 --- a/chromium/cc/scheduler/scheduler_settings.h +++ b/chromium/cc/scheduler/scheduler_settings.h @@ -24,19 +24,14 @@ class CC_EXPORT SchedulerSettings { ~SchedulerSettings(); bool use_external_begin_frame_source; + bool main_frame_while_swap_throttled_enabled; bool main_frame_before_activation_enabled; - bool impl_side_painting; + bool commit_to_active_tree; bool timeout_and_draw_when_animation_checkerboards; - int maximum_number_of_failed_draws_before_draw_is_forced_; bool using_synchronous_renderer_compositor; bool throttle_frame_production; - // In main thread low latency mode the entire - // BeginMainFrame->Commit->Activation->Draw cycle should complete before - // starting the next cycle. Additionally, BeginMainFrame and Commit are - // completed atomically with no other tasks or actions occuring between them. - bool main_thread_should_always_be_low_latency; - + int maximum_number_of_failed_draws_before_draw_is_forced; base::TimeDelta background_frame_interval; scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const; diff --git a/chromium/cc/scheduler/scheduler_state_machine.cc b/chromium/cc/scheduler/scheduler_state_machine.cc index e303d3ab48a..d83599c8c71 100644 --- a/chromium/cc/scheduler/scheduler_state_machine.cc +++ b/chromium/cc/scheduler/scheduler_state_machine.cc @@ -10,7 +10,6 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "base/values.h" -#include "ui/gfx/frame_time.h" namespace cc { @@ -29,12 +28,13 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) last_frame_number_invalidate_output_surface_performed_(-1), animate_funnel_(false), request_swap_funnel_(false), - send_begin_main_frame_funnel_(false), + send_begin_main_frame_funnel_(true), invalidate_output_surface_funnel_(false), prepare_tiles_funnel_(0), consecutive_checkerboard_animations_(0), max_pending_swaps_(1), pending_swaps_(0), + swaps_with_current_output_surface_(0), needs_redraw_(false), needs_animate_(false), needs_prepare_tiles_(false), @@ -48,7 +48,6 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) did_create_and_initialize_first_output_surface_(false), impl_latency_takes_priority_(false), skip_next_begin_main_frame_to_reduce_latency_(false), - skip_begin_main_frame_to_reduce_latency_(false), continuous_painting_(false), children_need_begin_frames_(false), defer_commits_(false), @@ -218,6 +217,8 @@ void SchedulerStateMachine::AsValueInto( consecutive_checkerboard_animations_); state->SetInteger("max_pending_swaps_", max_pending_swaps_); state->SetInteger("pending_swaps_", pending_swaps_); + state->SetInteger("swaps_with_current_output_surface", + swaps_with_current_output_surface_); state->SetBoolean("needs_redraw", needs_redraw_); state->SetBoolean("needs_animate_", needs_animate_); state->SetBoolean("needs_prepare_tiles", needs_prepare_tiles_); @@ -238,8 +239,6 @@ void SchedulerStateMachine::AsValueInto( impl_latency_takes_priority_); state->SetBoolean("main_thread_is_in_high_latency_mode", MainThreadIsInHighLatencyMode()); - state->SetBoolean("skip_begin_main_frame_to_reduce_latency", - skip_begin_main_frame_to_reduce_latency_); state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", skip_next_begin_main_frame_to_reduce_latency_); state->SetBoolean("continuous_painting", continuous_painting_); @@ -337,7 +336,7 @@ bool SchedulerStateMachine::ShouldDraw() const { return false; // Do not queue too many swaps. - if (pending_swaps_ >= max_pending_swaps_) + if (SwapThrottled()) return false; // Except for the cases above, do not draw outside of the BeginImplFrame @@ -402,15 +401,31 @@ bool SchedulerStateMachine::CouldSendBeginMainFrame() const { return true; } +bool SchedulerStateMachine::SendingBeginMainFrameMightCauseDeadlock() const { + // NPAPI is the only case where the UI thread makes synchronous calls to the + // Renderer main thread. During that synchronous call, we may not get a + // SwapAck for the UI thread, which may prevent BeginMainFrame's from + // completing if there's enough back pressure. If the BeginMainFrame can't + // make progress, the Renderer can't service the UI thread's synchronous call + // and we have deadlock. + // This returns true if there's too much backpressure to finish a commit + // if we were to initiate a BeginMainFrame. + return has_pending_tree_ && active_tree_needs_first_draw_ && SwapThrottled(); +} + bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { if (!CouldSendBeginMainFrame()) return false; - // Do not send begin main frame too many times in a single frame. + // Do not send begin main frame too many times in a single frame or before + // the first BeginFrame. if (send_begin_main_frame_funnel_) return false; // Only send BeginMainFrame when there isn't another commit pending already. + // Other parts of the state machine indirectly defer the BeginMainFrame + // by transitioning to WAITING commit states rather than going + // immediately to IDLE. if (commit_state_ != COMMIT_STATE_IDLE) return false; @@ -421,17 +436,22 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { return false; } - // We should not send BeginMainFrame while we are in - // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new - // user input arriving soon. + // We should not send BeginMainFrame while we are in the idle state since we + // might have new user input arriving soon. It's okay to send BeginMainFrame + // for the synchronous compositor because the main thread is always high + // latency in that case. // TODO(brianderson): Allow sending BeginMainFrame while idle when the main - // thread isn't consuming user input. - if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE && - BeginFrameNeeded()) + // thread isn't consuming user input for non-synchronous compositor. + if (!settings_.using_synchronous_renderer_compositor && + begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE) { return false; + } // We need a new commit for the forced redraw. This honors the // single commit per interval because the result will be swapped to screen. + // TODO(brianderson): Remove this or move it below the + // SendingBeginMainFrameMightCauseDeadlock check since we want to avoid + // ever returning true from this method if we might cause deadlock. if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) return true; @@ -439,15 +459,23 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { if (!HasInitializedOutputSurface()) return false; - // SwapAck throttle the BeginMainFrames unless we just swapped. - // TODO(brianderson): Remove this restriction to improve throughput. - bool just_swapped_in_deadline = - begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE && - did_perform_swap_in_last_draw_; - if (pending_swaps_ >= max_pending_swaps_ && !just_swapped_in_deadline) + // Make sure the BeginMainFrame can finish eventually if we start it. + if (SendingBeginMainFrameMightCauseDeadlock()) return false; - if (skip_begin_main_frame_to_reduce_latency_) + if (!settings_.main_frame_while_swap_throttled_enabled) { + // SwapAck throttle the BeginMainFrames unless we just swapped to + // potentially improve impl-thread latency over main-thread throughput. + // TODO(brianderson): Remove this restriction to improve throughput or + // make it conditional on impl_latency_takes_priority_. + bool just_swapped_in_deadline = + begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE && + did_perform_swap_in_last_draw_; + if (SwapThrottled() && !just_swapped_in_deadline) + return false; + } + + if (skip_next_begin_main_frame_to_reduce_latency_) return false; return true; @@ -463,9 +491,10 @@ bool SchedulerStateMachine::ShouldCommit() const { return false; } - // Prioritize drawing the previous commit before finishing the next commit. - if (active_tree_needs_first_draw_) - return false; + // If we only have an active tree, it is incorrect to replace it + // before we've drawn it. + DCHECK_IMPLIES(settings_.commit_to_active_tree, + !active_tree_needs_first_draw_); return true; } @@ -608,17 +637,12 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) { if (commit_has_no_updates || settings_.main_frame_before_activation_enabled) { commit_state_ = COMMIT_STATE_IDLE; - } else if (settings_.impl_side_painting) { - commit_state_ = COMMIT_STATE_WAITING_FOR_ACTIVATION; } else { - commit_state_ = settings_.main_thread_should_always_be_low_latency - ? COMMIT_STATE_WAITING_FOR_DRAW - : COMMIT_STATE_IDLE; + commit_state_ = COMMIT_STATE_WAITING_FOR_ACTIVATION; } - // If we are impl-side-painting but the commit was aborted, then we behave - // mostly as if we are not impl-side-painting since there is no pending tree. - has_pending_tree_ = settings_.impl_side_painting && !commit_has_no_updates; + // If the commit was aborted, then there is no pending tree. + has_pending_tree_ = !commit_has_no_updates; // Update state related to forced draws. if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) { @@ -657,7 +681,7 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) { void SchedulerStateMachine::UpdateStateOnActivation() { if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION) { - commit_state_ = settings_.main_thread_should_always_be_low_latency + commit_state_ = settings_.commit_to_active_tree ? COMMIT_STATE_WAITING_FOR_DRAW : COMMIT_STATE_IDLE; } @@ -833,10 +857,6 @@ void SchedulerStateMachine::OnBeginImplFrame() { // "Drain" the PrepareTiles funnel. if (prepare_tiles_funnel_ > 0) prepare_tiles_funnel_--; - - skip_begin_main_frame_to_reduce_latency_ = - skip_next_begin_main_frame_to_reduce_latency_; - skip_next_begin_main_frame_to_reduce_latency_ = false; } void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { @@ -860,6 +880,13 @@ void SchedulerStateMachine::OnBeginImplFrameDeadline() { void SchedulerStateMachine::OnBeginImplFrameIdle() { begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; + + skip_next_begin_main_frame_to_reduce_latency_ = false; + + // If we're entering a state where we won't get BeginFrames set all the + // funnels so that we don't perform any actions that we shouldn't. + if (!BeginFrameNeeded()) + send_begin_main_frame_funnel_ = true; } SchedulerStateMachine::BeginImplFrameDeadlineMode @@ -873,7 +900,7 @@ SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { return BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW; } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; - } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) { + } else if (needs_redraw_ && !SwapThrottled()) { // We have an animation or fast input path on the impl thread that wants // to draw, so don't wait too long for a new active tree. // If we are swap throttled we should wait until we are unblocked. @@ -888,7 +915,6 @@ SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() const { - // TODO(brianderson): This should take into account multiple commit sources. if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) return false; @@ -897,7 +923,7 @@ bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() return true; // SwapAck throttle the deadline since we wont draw and swap anyway. - if (pending_swaps_ >= max_pending_swaps_) + if (SwapThrottled()) return false; if (active_tree_needs_first_draw_) @@ -962,7 +988,15 @@ bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const { return active_tree_needs_first_draw_; } -void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } +bool SchedulerStateMachine::SwapThrottled() const { + return pending_swaps_ >= max_pending_swaps_; +} + +void SchedulerStateMachine::SetVisible(bool visible) { + visible_ = visible; + // TODO(sunnyps): Change the funnel to a bool to avoid hacks like this. + prepare_tiles_funnel_ = 0; +} void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } @@ -973,10 +1007,16 @@ void SchedulerStateMachine::SetNeedsAnimate() { } void SchedulerStateMachine::SetWaitForReadyToDraw() { - DCHECK(settings_.impl_side_painting); wait_for_active_tree_ready_to_draw_ = true; } +bool SchedulerStateMachine::OnlyImplSideUpdatesExpected() const { + bool has_impl_updates = needs_redraw_ || needs_animate_; + bool main_updates_expected = + needs_commit_ || commit_state_ != COMMIT_STATE_IDLE || has_pending_tree_; + return has_impl_updates && !main_updates_expected; +} + void SchedulerStateMachine::SetNeedsPrepareTiles() { if (!needs_prepare_tiles_) { TRACE_EVENT0("cc", "SchedulerStateMachine::SetNeedsPrepareTiles"); @@ -990,6 +1030,8 @@ void SchedulerStateMachine::SetMaxSwapsPending(int max) { void SchedulerStateMachine::DidSwapBuffers() { pending_swaps_++; + swaps_with_current_output_surface_++; + DCHECK_LE(pending_swaps_, max_pending_swaps_); did_perform_swap_in_last_draw_ = true; @@ -997,7 +1039,6 @@ void SchedulerStateMachine::DidSwapBuffers() { } void SchedulerStateMachine::DidSwapBuffersComplete() { - DCHECK_GT(pending_swaps_, 0); pending_swaps_--; } @@ -1032,7 +1073,7 @@ void SchedulerStateMachine::DidDrawIfPossibleCompleted(DrawResult result) { consecutive_checkerboard_animations_++; if (settings_.timeout_and_draw_when_animation_checkerboards && consecutive_checkerboard_animations_ >= - settings_.maximum_number_of_failed_draws_before_draw_is_forced_) { + settings_.maximum_number_of_failed_draws_before_draw_is_forced) { consecutive_checkerboard_animations_ = 0; // We need to force a draw, but it doesn't make sense to do this until // we've committed and have new textures. @@ -1057,10 +1098,10 @@ void SchedulerStateMachine::NotifyReadyToCommit() { DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED) << AsValue()->ToString(); commit_state_ = COMMIT_STATE_READY_TO_COMMIT; - // In main thread low latency mode, commit should happen right after + // In commit_to_active_tree mode, commit should happen right after // BeginFrame, meaning when this function is called, next action should be // commit. - if (settings_.main_thread_should_always_be_low_latency) + if (settings_.commit_to_active_tree) DCHECK(ShouldCommit()); } @@ -1115,6 +1156,7 @@ void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() { } did_create_and_initialize_first_output_surface_ = true; pending_swaps_ = 0; + swaps_with_current_output_surface_ = 0; } void SchedulerStateMachine::NotifyBeginMainFrameStarted() { @@ -1137,17 +1179,4 @@ bool SchedulerStateMachine::HasInitializedOutputSurface() const { return false; } -std::string SchedulerStateMachine::GetStatesForDebugging() const { - return base::StringPrintf("%c %d %d %d %c %c %c %d %d", - needs_commit_ ? 'T' : 'F', - static_cast<int>(output_surface_state_), - static_cast<int>(begin_impl_frame_state_), - static_cast<int>(commit_state_), - has_pending_tree_ ? 'T' : 'F', - pending_tree_is_ready_for_activation_ ? 'T' : 'F', - active_tree_needs_first_draw_ ? 'T' : 'F', - max_pending_swaps_, - pending_swaps_); -} - } // namespace cc diff --git a/chromium/cc/scheduler/scheduler_state_machine.h b/chromium/cc/scheduler/scheduler_state_machine.h index cf29ca9b6a5..cf1ab8c5568 100644 --- a/chromium/cc/scheduler/scheduler_state_machine.h +++ b/chromium/cc/scheduler/scheduler_state_machine.h @@ -145,6 +145,8 @@ class CC_EXPORT SchedulerStateMachine { // impl thread to draw, it is in a high latency mode. bool MainThreadIsInHighLatencyMode() const; + bool SwapThrottled() const; + // Indicates whether the LayerTreeHostImpl is visible. void SetVisible(bool visible); bool visible() const { return visible_; } @@ -157,6 +159,8 @@ class CC_EXPORT SchedulerStateMachine { void SetNeedsAnimate(); bool needs_animate() const { return needs_animate_; } + bool OnlyImplSideUpdatesExpected() const; + // Indicates that prepare-tiles is required. This guarantees another // PrepareTiles will occur shortly (even if no redraw is required). void SetNeedsPrepareTiles(); @@ -179,6 +183,8 @@ class CC_EXPORT SchedulerStateMachine { // Notification from the OutputSurface that a swap has been consumed. void DidSwapBuffersComplete(); + int pending_swaps() const { return pending_swaps_; } + // Indicates whether to prioritize impl thread latency (i.e., animation // smoothness) over new content activation. void SetImplLatencyTakesPriority(bool impl_latency_takes_priority); @@ -193,6 +199,7 @@ class CC_EXPORT SchedulerStateMachine { // updates from the main thread to the impl, or to push deltas from the impl // thread to main. void SetNeedsCommit(); + bool needs_commit() const { return needs_commit_; } // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME // from NextAction. @@ -208,6 +215,7 @@ class CC_EXPORT SchedulerStateMachine { // Allow access of the can_start_ state in tests. bool CanStartForTesting() const { return can_start_; } + // Indicates production should be skipped to recover latency. void SetSkipNextBeginMainFrameToReduceLatency(); // Indicates whether drawing would, at this time, make sense. @@ -245,10 +253,6 @@ class CC_EXPORT SchedulerStateMachine { void SetDeferCommits(bool defer_commits); - // TODO(zmo): This is temporary for debugging crbug.com/393331. - // We should remove it afterwards. - std::string GetStatesForDebugging() const; - void SetChildrenNeedBeginFrames(bool children_need_begin_frames); bool children_need_begin_frames() const { return children_need_begin_frames_; @@ -268,6 +272,9 @@ class CC_EXPORT SchedulerStateMachine { // True if we need to force activations to make forward progress. bool PendingActivationsShouldBeForced() const; + // TODO(brianderson): Remove this once NPAPI support is removed. + bool SendingBeginMainFrameMightCauseDeadlock() const; + bool ShouldAnimate() const; bool ShouldBeginOutputSurfaceCreation() const; bool ShouldDraw() const; @@ -317,6 +324,7 @@ class CC_EXPORT SchedulerStateMachine { int consecutive_checkerboard_animations_; int max_pending_swaps_; int pending_swaps_; + int swaps_with_current_output_surface_; bool needs_redraw_; bool needs_animate_; bool needs_prepare_tiles_; @@ -330,7 +338,6 @@ class CC_EXPORT SchedulerStateMachine { bool did_create_and_initialize_first_output_surface_; bool impl_latency_takes_priority_; bool skip_next_begin_main_frame_to_reduce_latency_; - bool skip_begin_main_frame_to_reduce_latency_; bool continuous_painting_; bool children_need_begin_frames_; bool defer_commits_; diff --git a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc index 7b332a3fbf3..da40cc15017 100644 --- a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc @@ -202,14 +202,15 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) { state.SetNeedsRedraw(false); state.SetVisible(true); - EXPECT_FALSE(state.BeginFrameNeeded()); - EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - EXPECT_FALSE(state.BeginFrameNeeded()); - state.OnBeginImplFrame(); + EXPECT_FALSE(state.NeedsCommit()); + state.OnBeginImplFrame(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + EXPECT_FALSE(state.NeedsCommit()); } // If commit requested but can_start is still false, do nothing. @@ -220,13 +221,15 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) { state.SetVisible(true); state.SetNeedsCommit(); - EXPECT_FALSE(state.BeginFrameNeeded()); - EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - EXPECT_FALSE(state.BeginFrameNeeded()); + EXPECT_TRUE(state.NeedsCommit()); + state.OnBeginImplFrame(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + EXPECT_TRUE(state.NeedsCommit()); } // If commit requested, begin a main frame. @@ -240,16 +243,19 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) { state.SetVisible(true); state.SetNeedsCommit(); - EXPECT_TRUE(state.BeginFrameNeeded()); - // Expect nothing to happen until after OnBeginImplFrame. + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); - EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); + EXPECT_TRUE(state.NeedsCommit()); + EXPECT_TRUE(state.BeginFrameNeeded()); state.OnBeginImplFrame(); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); + EXPECT_FALSE(state.NeedsCommit()); } // If commit requested and can't draw, still begin a main frame. @@ -264,26 +270,15 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) { state.SetNeedsCommit(); state.SetCanDraw(false); - EXPECT_TRUE(state.BeginFrameNeeded()); - // Expect nothing to happen until after OnBeginImplFrame. + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); - EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); + EXPECT_TRUE(state.BeginFrameNeeded()); state.OnBeginImplFrame(); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - } - - // Begin the frame, make sure needs_commit and commit_state update correctly. - { - StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.UpdateState(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); EXPECT_COMMIT_STATE( SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); @@ -293,7 +288,6 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) { // Explicitly test main_frame_before_activation_enabled = true TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) { SchedulerSettings scheduler_settings; - scheduler_settings.impl_side_painting = true; scheduler_settings.main_frame_before_activation_enabled = true; StateMachine state(scheduler_settings); state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE); @@ -331,10 +325,11 @@ TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) { state.NotifyReadyToCommit(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - // Verify NotifyReadyToActivate unblocks activation, draw, and - // commit in that order. + // Verify NotifyReadyToActivate unblocks activation, commit, and + // draw in that order. state.NotifyReadyToActivate(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately()); @@ -344,7 +339,6 @@ TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) { SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); state.DidSwapBuffers(); state.DidSwapBuffersComplete(); - EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); } @@ -450,7 +444,7 @@ TEST(SchedulerStateMachineTest, TEST(SchedulerStateMachineTest, TestFailedDrawsEventuallyForceDrawAfterNextCommit) { SchedulerSettings scheduler_settings; - scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = 1; + scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced = 1; StateMachine state(scheduler_settings); SET_UP_STATE(state) @@ -486,6 +480,12 @@ TEST(SchedulerStateMachineTest, EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); EXPECT_TRUE(state.RedrawPending()); + // Activate so we're ready for a new main frame. + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + EXPECT_TRUE(state.RedrawPending()); + // The redraw should be forced at the end of the next BeginImplFrame. state.OnBeginImplFrame(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); @@ -502,9 +502,8 @@ TEST(SchedulerStateMachineTest, TEST(SchedulerStateMachineTest, TestFailedDrawsDoNotRestartForcedDraw) { SchedulerSettings scheduler_settings; int draw_limit = 1; - scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = + scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced = draw_limit; - scheduler_settings.impl_side_painting = true; StateMachine state(scheduler_settings); SET_UP_STATE(state) @@ -788,6 +787,8 @@ TEST(SchedulerStateMachineTest, state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); state.OnBeginImplFrameDeadline(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); @@ -842,9 +843,11 @@ TEST(SchedulerStateMachineTest, TestSetNeedsCommitIsNotLost) { SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING); EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT); - // Finish the commit, then make sure we start the next commit immediately - // and draw on the next BeginImplFrame. + // Finish the commit and activate, then make sure we start the next commit + // immediately and draw on the next BeginImplFrame. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); @@ -885,6 +888,10 @@ TEST(SchedulerStateMachineTest, TestFullCycle) { // Commit. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); + + // Activate. + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); EXPECT_TRUE(state.active_tree_needs_first_draw()); EXPECT_TRUE(state.needs_redraw()); @@ -906,70 +913,67 @@ TEST(SchedulerStateMachineTest, TestFullCycle) { EXPECT_FALSE(state.needs_redraw()); } -TEST(SchedulerStateMachineTest, TestFullCycleWithMainThreadLowLatencyMode) { - SchedulerSettings scheduler_settings; - scheduler_settings.main_thread_should_always_be_low_latency = true; - StateMachine state(scheduler_settings); +TEST(SchedulerStateMachineTest, CommitWithoutDrawWithPendingTree) { + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); SET_UP_STATE(state) // Start clean and set commit. state.SetNeedsCommit(); - // Begin the frame. + // Make a main frame, commit and activate it. But don't draw it. state.OnBeginImplFrame(); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_COMMIT_STATE( - SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); - EXPECT_FALSE(state.NeedsCommit()); - EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - - // Tell the scheduler the frame finished. state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); - EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT); - - // Commit. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); - EXPECT_TRUE(state.active_tree_needs_first_draw()); - EXPECT_TRUE(state.needs_redraw()); - - // Now commit should wait for draw. - EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW); - - // Swap throttled. Do not draw. - state.DidSwapBuffers(); - state.OnBeginImplFrameDeadline(); - EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); - EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - state.DidSwapBuffersComplete(); + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); - // Haven't draw since last commit, do not begin new main frame. + // Try to make a new main frame before drawing. Since we will commit it to a + // pending tree and not clobber the active tree, we're able to start a new + // begin frame and commit it. state.SetNeedsCommit(); state.OnBeginImplFrame(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); - EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - - // At BeginImplFrame deadline, draw. - state.OnBeginImplFrameDeadline(); EXPECT_ACTION_UPDATE_STATE( - SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); - state.DidSwapBuffers(); - state.DidDrawIfPossibleCompleted(DRAW_SUCCESS); - state.DidSwapBuffersComplete(); + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); + state.NotifyBeginMainFrameStarted(); + state.NotifyReadyToCommit(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); +} - // Now will be able to start main frame. - EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); - EXPECT_FALSE(state.needs_redraw()); +TEST(SchedulerStateMachineTest, DontCommitWithoutDrawWithoutPendingTree) { + SchedulerSettings scheduler_settings; + scheduler_settings.commit_to_active_tree = true; + StateMachine state(scheduler_settings); + SET_UP_STATE(state) + + // Start clean and set commit. + state.SetNeedsCommit(); + + // Make a main frame, commit and activate it. But don't draw it. + state.OnBeginImplFrame(); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); + state.NotifyBeginMainFrameStarted(); + state.NotifyReadyToCommit(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); + + // Try to make a new main frame before drawing, but since we would clobber the + // active tree, we will not do so. + state.SetNeedsCommit(); + state.OnBeginImplFrame(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); } -TEST(SchedulerStateMachineTest, - TestFullCycleWithMainThreadLowLatencyMode_ImplSidePaint) { +TEST(SchedulerStateMachineTest, TestFullCycleWithCommitToActive) { SchedulerSettings scheduler_settings; - scheduler_settings.main_thread_should_always_be_low_latency = true; - scheduler_settings.impl_side_painting = true; + scheduler_settings.commit_to_active_tree = true; StateMachine state(scheduler_settings); SET_UP_STATE(state) @@ -1074,8 +1078,10 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) { state.NotifyReadyToCommit(); EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT); - // First commit. + // First commit and activate. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); EXPECT_TRUE(state.active_tree_needs_first_draw()); EXPECT_TRUE(state.needs_redraw()); @@ -1272,8 +1278,6 @@ TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) { TEST(SchedulerStateMachineTest, TestContextLostWhenIdleAndCommitRequestedWhileRecreating) { SchedulerSettings default_scheduler_settings; - // We use impl side painting because it's the more complicated version. - default_scheduler_settings.impl_side_painting = true; StateMachine state(default_scheduler_settings); SET_UP_STATE(state) @@ -1424,10 +1428,12 @@ TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) { state.SetNeedsRedraw(true); EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); - // Finish the frame, and commit. + // Finish the frame, commit and activate. state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); // We will abort the draw when the output surface is lost if we are // waiting for the first draw to unblock the main thread. @@ -1486,10 +1492,12 @@ TEST(SchedulerStateMachineTest, state.SetNeedsCommit(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - // Finish the frame, and commit. + // Finish the frame, and commit and activate. state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); EXPECT_TRUE(state.active_tree_needs_first_draw()); // Because the output surface is missing, we expect the draw to abort. @@ -1528,6 +1536,9 @@ TEST(SchedulerStateMachineTest, state.NotifyReadyToCommit(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( @@ -1557,9 +1568,8 @@ TEST(SchedulerStateMachineTest, DontDrawBeforeCommitAfterLostOutputSurface) { TEST(SchedulerStateMachineTest, TestPendingActivationsShouldBeForcedAfterLostOutputSurface) { - SchedulerSettings settings; - settings.impl_side_painting = true; - StateMachine state(settings); + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); SET_UP_STATE(state) state.SetCommitState( @@ -1632,6 +1642,9 @@ TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) { state.NotifyReadyToCommit(); EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT); state.UpdateState(state.NextAction()); + state.NotifyReadyToActivate(); + EXPECT_ACTION(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); + state.UpdateState(state.NextAction()); EXPECT_TRUE(state.active_tree_needs_first_draw()); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); @@ -1685,9 +1698,8 @@ TEST(SchedulerStateMachineTest, ReportIfNotDrawing) { TEST(SchedulerStateMachineTest, TestTriggerDeadlineImmediatelyAfterAbortedCommit) { - SchedulerSettings settings; - settings.impl_side_painting = true; - StateMachine state(settings); + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); SET_UP_STATE(state) // This test mirrors what happens during the first frame of a scroll gesture. @@ -1739,9 +1751,8 @@ void FinishPreviousCommitAndDrawWithoutExitingDeadline( } TEST(SchedulerStateMachineTest, TestImplLatencyTakesPriority) { - SchedulerSettings settings; - settings.impl_side_painting = true; - StateMachine state(settings); + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); SET_UP_STATE(state) // This test ensures that impl-draws are prioritized over main thread updates @@ -1813,9 +1824,8 @@ TEST(SchedulerStateMachineTest, } TEST(SchedulerStateMachineTest, TestTriggerDeadlineImmediatelyWhenInvisible) { - SchedulerSettings settings; - settings.impl_side_painting = true; - StateMachine state(settings); + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); SET_UP_STATE(state) state.SetNeedsCommit(); @@ -1832,9 +1842,8 @@ TEST(SchedulerStateMachineTest, TestTriggerDeadlineImmediatelyWhenInvisible) { } TEST(SchedulerStateMachineTest, TestSetNeedsAnimate) { - SchedulerSettings settings; - settings.impl_side_painting = true; - StateMachine state(settings); + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); SET_UP_STATE(state) // Test requesting an animation that, when run, causes us to draw. @@ -1852,9 +1861,8 @@ TEST(SchedulerStateMachineTest, TestSetNeedsAnimate) { } TEST(SchedulerStateMachineTest, TestAnimateBeforeCommit) { - SchedulerSettings settings; - settings.impl_side_painting = true; - StateMachine state(settings); + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); SET_UP_STATE(state) // Check that animations are updated before we start a commit. @@ -1876,9 +1884,8 @@ TEST(SchedulerStateMachineTest, TestAnimateBeforeCommit) { } TEST(SchedulerStateMachineTest, TestAnimateAfterCommitBeforeDraw) { - SchedulerSettings settings; - settings.impl_side_painting = true; - StateMachine state(settings); + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); SET_UP_STATE(state) // Check that animations are updated before we start a commit. @@ -1905,9 +1912,8 @@ TEST(SchedulerStateMachineTest, TestAnimateAfterCommitBeforeDraw) { } TEST(SchedulerStateMachineTest, TestSetNeedsAnimateAfterAnimate) { - SchedulerSettings settings; - settings.impl_side_painting = true; - StateMachine state(settings); + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); SET_UP_STATE(state) // Test requesting an animation after we have already animated during this diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc index d2b12d768a5..42a23d423e6 100644 --- a/chromium/cc/scheduler/scheduler_unittest.cc +++ b/chromium/cc/scheduler/scheduler_unittest.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" +#include "base/numerics/safe_conversions.h" #include "base/run_loop.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" @@ -59,17 +60,11 @@ class FakeSchedulerClient : public SchedulerClient { draw_will_happen_ = true; swap_will_happen_if_draw_happens_ = true; num_draws_ = 0; - log_anticipated_draw_time_change_ = false; begin_frame_args_sent_to_children_ = BeginFrameArgs(); } void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; } - // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it - // for tests that do. - void set_log_anticipated_draw_time_change(bool log) { - log_anticipated_draw_time_change_ = log; - } bool needs_begin_frames() { return scheduler_->frame_source().NeedsBeginFrames(); } @@ -84,7 +79,7 @@ class FakeSchedulerClient : public SchedulerClient { int ActionIndex(const char* action) const { for (size_t i = 0; i < actions_.size(); i++) if (!strcmp(actions_[i], action)) - return i; + return base::checked_cast<int>(i); return -1; } @@ -132,7 +127,10 @@ class FakeSchedulerClient : public SchedulerClient { PushAction("ScheduledActionDrawAndSwapForced"); return DRAW_SUCCESS; } - void ScheduledActionCommit() override { PushAction("ScheduledActionCommit"); } + void ScheduledActionCommit() override { + PushAction("ScheduledActionCommit"); + scheduler_->DidCommit(); + } void ScheduledActionActivateSyncTree() override { PushAction("ScheduledActionActivateSyncTree"); } @@ -141,22 +139,13 @@ class FakeSchedulerClient : public SchedulerClient { } void ScheduledActionPrepareTiles() override { PushAction("ScheduledActionPrepareTiles"); + scheduler_->WillPrepareTiles(); + scheduler_->DidPrepareTiles(); } void ScheduledActionInvalidateOutputSurface() override { actions_.push_back("ScheduledActionInvalidateOutputSurface"); states_.push_back(scheduler_->AsValue()); } - void DidAnticipatedDrawTimeChange(base::TimeTicks) override { - if (log_anticipated_draw_time_change_) - PushAction("DidAnticipatedDrawTimeChange"); - } - base::TimeDelta DrawDurationEstimate() override { return base::TimeDelta(); } - base::TimeDelta BeginMainFrameToCommitDurationEstimate() override { - return base::TimeDelta(); - } - base::TimeDelta CommitToActivateDurationEstimate() override { - return base::TimeDelta(); - } void SendBeginFramesToChildren(const BeginFrameArgs& args) override { begin_frame_args_sent_to_children_ = args; @@ -194,7 +183,6 @@ class FakeSchedulerClient : public SchedulerClient { bool swap_will_happen_if_draw_happens_; bool automatic_swap_ack_; int num_draws_; - bool log_anticipated_draw_time_change_; BeginFrameArgs begin_frame_args_sent_to_children_; base::TimeTicks posted_begin_impl_frame_deadline_; std::vector<const char*> actions_; @@ -203,32 +191,7 @@ class FakeSchedulerClient : public SchedulerClient { TestScheduler* scheduler_; }; -class SchedulerClientWithFixedEstimates : public FakeSchedulerClient { - public: - SchedulerClientWithFixedEstimates( - base::TimeDelta draw_duration, - base::TimeDelta begin_main_frame_to_commit_duration, - base::TimeDelta commit_to_activate_duration) - : draw_duration_(draw_duration), - begin_main_frame_to_commit_duration_( - begin_main_frame_to_commit_duration), - commit_to_activate_duration_(commit_to_activate_duration) {} - - base::TimeDelta DrawDurationEstimate() override { return draw_duration_; } - base::TimeDelta BeginMainFrameToCommitDurationEstimate() override { - return begin_main_frame_to_commit_duration_; - } - base::TimeDelta CommitToActivateDurationEstimate() override { - return commit_to_activate_duration_; - } - - private: - base::TimeDelta draw_duration_; - base::TimeDelta begin_main_frame_to_commit_duration_; - base::TimeDelta commit_to_activate_duration_; -}; - -class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn { +class FakeExternalBeginFrameSource : public BeginFrameSourceBase { public: explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client) : client_(client) {} @@ -253,11 +216,13 @@ class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn { class SchedulerTest : public testing::Test { public: SchedulerTest() - : now_src_(TestNowSource::Create()), - task_runner_(new OrderedSimpleTaskRunner(now_src_, true)), + : now_src_(new base::SimpleTestTickClock()), + task_runner_(new OrderedSimpleTaskRunner(now_src_.get(), true)), fake_external_begin_frame_source_(nullptr) { - // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval() - now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100)); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10000)); + // A bunch of tests require NowTicks() + // to be > BeginFrameArgs::DefaultInterval() + now_src_->Advance(base::TimeDelta::FromMilliseconds(100)); // Fail if we need to run 100 tasks in a row. task_runner_->SetRunTaskLimit(100); } @@ -266,18 +231,27 @@ class SchedulerTest : public testing::Test { protected: TestScheduler* CreateScheduler() { - scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source; if (scheduler_settings_.use_external_begin_frame_source) { - fake_external_begin_frame_source.reset( + fake_external_begin_frame_source_.reset( new FakeExternalBeginFrameSource(client_.get())); - fake_external_begin_frame_source_ = - fake_external_begin_frame_source.get(); } - scheduler_ = TestScheduler::Create(now_src_, client_.get(), - scheduler_settings_, 0, task_runner_, - fake_external_begin_frame_source.Pass()); + + scoped_ptr<FakeCompositorTimingHistory> fake_compositor_timing_history = + FakeCompositorTimingHistory::Create(); + fake_compositor_timing_history_ = fake_compositor_timing_history.get(); + + scheduler_ = TestScheduler::Create( + now_src_.get(), client_.get(), scheduler_settings_, 0, + task_runner_.get(), fake_external_begin_frame_source_.get(), + fake_compositor_timing_history.Pass()); DCHECK(scheduler_); client_->set_scheduler(scheduler_.get()); + + // Use large estimates by default to avoid latency recovery + // in most tests. + base::TimeDelta slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration); + return scheduler_.get(); } @@ -300,7 +274,7 @@ class SchedulerTest : public testing::Test { } OrderedSimpleTaskRunner& task_runner() { return *task_runner_; } - TestNowSource* now_src() { return now_src_.get(); } + base::SimpleTestTickClock* now_src() { return now_src_.get(); } // As this function contains EXPECT macros, to allow debugging it should be // called inside EXPECT_SCOPED like so; @@ -336,7 +310,8 @@ class SchedulerTest : public testing::Test { AdvanceFrame(); scheduler_->NotifyBeginMainFrameStarted(); - scheduler_->NotifyReadyToCommitThenActivateIfNeeded(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); EXPECT_FALSE(scheduler_->CommitPending()); @@ -400,39 +375,37 @@ class SchedulerTest : public testing::Test { } } - void SendNextBeginFrame() { + BeginFrameArgs SendNextBeginFrame() { DCHECK(scheduler_->settings().use_external_begin_frame_source); // Creep the time forward so that any BeginFrameArgs is not equal to the // last one otherwise we violate the BeginFrameSource contract. - now_src_->AdvanceNow(BeginFrameArgs::DefaultInterval()); - fake_external_begin_frame_source_->TestOnBeginFrame( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src())); + now_src_->Advance(BeginFrameArgs::DefaultInterval()); + BeginFrameArgs args = + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); + fake_external_begin_frame_source_->TestOnBeginFrame(args); + return args; } FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { - return fake_external_begin_frame_source_; + return fake_external_begin_frame_source_.get(); } - void MainFrameInHighLatencyMode( - int64 begin_main_frame_to_commit_estimate_in_ms, - int64 commit_to_activate_estimate_in_ms, - bool impl_latency_takes_priority, - bool should_send_begin_main_frame); + void CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame); + void ImplFrameSkippedAfterLateSwapAck(bool swap_ack_before_deadline); + void ImplFrameIsNotSkippedAfterLateSwapAck(); void BeginFramesNotFromClient(bool use_external_begin_frame_source, bool throttle_frame_production); void BeginFramesNotFromClient_SwapThrottled( bool use_external_begin_frame_source, bool throttle_frame_production); - void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency( - bool impl_side_painting); - void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting); - scoped_refptr<TestNowSource> now_src_; + scoped_ptr<base::SimpleTestTickClock> now_src_; scoped_refptr<OrderedSimpleTaskRunner> task_runner_; - FakeExternalBeginFrameSource* fake_external_begin_frame_source_; + scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_; SchedulerSettings scheduler_settings_; scoped_ptr<FakeSchedulerClient> client_; scoped_ptr<TestScheduler> scheduler_; + FakeCompositorTimingHistory* fake_compositor_timing_history_; }; TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) { @@ -484,13 +457,15 @@ TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) { TEST_F(SchedulerTest, SendBeginFramesToChildrenDeadlineNotAdjusted) { // Set up client with specified estimates. - SchedulerClientWithFixedEstimates* client = - new SchedulerClientWithFixedEstimates( - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMilliseconds(2), - base::TimeDelta::FromMilliseconds(4)); scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(true); + + fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( + base::TimeDelta::FromMilliseconds(2)); + fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( + base::TimeDelta::FromMilliseconds(4)); + fake_compositor_timing_history_->SetDrawDurationEstimate( + base::TimeDelta::FromMilliseconds(1)); EXPECT_FALSE(client_->needs_begin_frames()); scheduler_->SetChildrenNeedBeginFrames(true); @@ -569,6 +544,12 @@ TEST_F(SchedulerTest, RequestCommit) { EXPECT_TRUE(client_->needs_begin_frames()); client_->Reset(); + // NotifyReadyToActivate should trigger the activation. + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + EXPECT_TRUE(client_->needs_begin_frames()); + client_->Reset(); + // BeginImplFrame should prepare the draw. EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); @@ -579,7 +560,7 @@ TEST_F(SchedulerTest, RequestCommit) { // BeginImplFrame deadline should draw. task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); + EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); EXPECT_TRUE(client_->needs_begin_frames()); client_->Reset(); @@ -684,6 +665,13 @@ TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); + + // Activate it. + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + client_->Reset(); + task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); @@ -708,6 +696,10 @@ TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); @@ -728,8 +720,6 @@ class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient { SchedulerClientThatsetNeedsDrawInsideDraw() : FakeSchedulerClient(), request_redraws_(false) {} - void ScheduledActionSendBeginMainFrame() override {} - void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; } DrawResult ScheduledActionDrawAndSwapIfPossible() override { @@ -745,9 +735,6 @@ class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient { return DRAW_SUCCESS; } - void ScheduledActionCommit() override {} - void DidAnticipatedDrawTimeChange(base::TimeTicks) override {} - private: bool request_redraws_; }; @@ -842,7 +829,6 @@ class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient { SchedulerClientThatSetNeedsCommitInsideDraw() : set_needs_commit_on_next_draw_(false) {} - void ScheduledActionSendBeginMainFrame() override {} DrawResult ScheduledActionDrawAndSwapIfPossible() override { // Only SetNeedsCommit the first time this is called if (set_needs_commit_on_next_draw_) { @@ -857,9 +843,6 @@ class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient { return DRAW_SUCCESS; } - void ScheduledActionCommit() override {} - void DidAnticipatedDrawTimeChange(base::TimeTicks) override {} - void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; } private: @@ -890,6 +873,7 @@ TEST_F(SchedulerTest, RequestCommitInsideDraw) { EXPECT_TRUE(client->needs_begin_frames()); scheduler_->NotifyBeginMainFrameStarted(); scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); EXPECT_SCOPED(AdvanceFrame()); task_runner().RunPendingTasks(); // Run posted deadline. @@ -1110,6 +1094,7 @@ TEST_F(SchedulerTest, PrepareTilesOncePerFrame) { EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); EXPECT_TRUE(scheduler_->PrepareTilesPending()); + scheduler_->WillPrepareTiles(); scheduler_->DidPrepareTiles(); // An explicit PrepareTiles. EXPECT_FALSE(scheduler_->PrepareTilesPending()); @@ -1141,10 +1126,10 @@ TEST_F(SchedulerTest, PrepareTilesOncePerFrame) { EXPECT_FALSE(scheduler_->RedrawPending()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles // If we get another DidPrepareTiles within the same frame, we should // not PrepareTiles on the next frame. + scheduler_->WillPrepareTiles(); scheduler_->DidPrepareTiles(); // An explicit PrepareTiles. scheduler_->SetNeedsPrepareTiles(); scheduler_->SetNeedsRedraw(); @@ -1168,6 +1153,7 @@ TEST_F(SchedulerTest, PrepareTilesOncePerFrame) { // frame. This verifies we don't alternate calling PrepareTiles once and // twice. EXPECT_TRUE(scheduler_->PrepareTilesPending()); + scheduler_->WillPrepareTiles(); scheduler_->DidPrepareTiles(); // An explicit PrepareTiles. EXPECT_FALSE(scheduler_->PrepareTilesPending()); scheduler_->SetNeedsPrepareTiles(); @@ -1207,7 +1193,40 @@ TEST_F(SchedulerTest, PrepareTilesOncePerFrame) { EXPECT_FALSE(scheduler_->RedrawPending()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles +} + +TEST_F(SchedulerTest, PrepareTilesFunnelResetOnVisibilityChange) { + scoped_ptr<SchedulerClientNeedsPrepareTilesInDraw> client = + make_scoped_ptr(new SchedulerClientNeedsPrepareTilesInDraw); + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(client.Pass(), true); + + // Simulate a few visibility changes and associated PrepareTiles. + for (int i = 0; i < 10; i++) { + scheduler_->SetVisible(false); + scheduler_->WillPrepareTiles(); + scheduler_->DidPrepareTiles(); + + scheduler_->SetVisible(true); + scheduler_->WillPrepareTiles(); + scheduler_->DidPrepareTiles(); + } + + client_->Reset(); + scheduler_->SetNeedsRedraw(); + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + + client_->Reset(); + AdvanceFrame(); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + + client_->Reset(); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2); + EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2); } TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) { @@ -1228,7 +1247,6 @@ TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) { SchedulerClientNeedsPrepareTilesInDraw* client = new SchedulerClientNeedsPrepareTilesInDraw; scheduler_settings_.use_external_begin_frame_source = true; - scheduler_settings_.impl_side_painting = true; SetUpScheduler(make_scoped_ptr(client).Pass(), true); // SetNeedsCommit should begin the frame on the next BeginImplFrame. @@ -1270,7 +1288,6 @@ TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) { SchedulerClientNeedsPrepareTilesInDraw* client = new SchedulerClientNeedsPrepareTilesInDraw; scheduler_settings_.use_external_begin_frame_source = true; - scheduler_settings_.impl_side_painting = true; SetUpScheduler(make_scoped_ptr(client).Pass(), true); // SetNeedsCommit should begin the frame on the next BeginImplFrame. @@ -1310,133 +1327,757 @@ TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) { EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); } -void SchedulerTest::MainFrameInHighLatencyMode( - int64 begin_main_frame_to_commit_estimate_in_ms, - int64 commit_to_activate_estimate_in_ms, - bool impl_latency_takes_priority, - bool should_send_begin_main_frame) { - // Set up client with specified estimates (draw duration is set to 1). - SchedulerClientWithFixedEstimates* client = - new SchedulerClientWithFixedEstimates( - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMilliseconds( - begin_main_frame_to_commit_estimate_in_ms), - base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms)); - - scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); - - scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority); - +void SchedulerTest::CheckMainFrameSkippedAfterLateCommit( + bool expect_send_begin_main_frame) { // Impl thread hits deadline before commit finishes. scheduler_->SetNeedsCommit(); EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); EXPECT_SCOPED(AdvanceFrame()); EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); - task_runner().RunPendingTasks(); // Run posted deadline. + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); scheduler_->NotifyBeginMainFrameStarted(); scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); + EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); + EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); + EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5); EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); - EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame")); - client->Reset(); + client_->Reset(); scheduler_->SetNeedsCommit(); EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); EXPECT_SCOPED(AdvanceFrame()); EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); - task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(), - should_send_begin_main_frame); - EXPECT_EQ(client->HasAction("ScheduledActionSendBeginMainFrame"), - should_send_begin_main_frame); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_EQ(expect_send_begin_main_frame, + scheduler_->MainThreadIsInHighLatencyMode()); + EXPECT_EQ(expect_send_begin_main_frame, + client_->HasAction("ScheduledActionSendBeginMainFrame")); +} + +TEST_F(SchedulerTest, MainFrameSkippedAfterLateCommit) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + + bool expect_send_begin_main_frame = false; + EXPECT_SCOPED( + CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); } TEST_F(SchedulerTest, - SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) { - // Set up client so that estimates indicate that we can commit and activate - // before the deadline (~8ms by default). - EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false)); + MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + scheduler_->SetImplLatencyTakesPriority(true); + + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + + bool expect_send_begin_main_frame = true; + EXPECT_SCOPED( + CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); } -TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) { - // Set up client so that estimates indicate that the commit cannot finish - // before the deadline (~8ms by default). - EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true)); +TEST_F(SchedulerTest, + MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( + slow_duration); + + bool expect_send_begin_main_frame = true; + EXPECT_SCOPED( + CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); } -TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) { - // Set up client so that estimates indicate that the activate cannot finish - // before the deadline (~8ms by default). - EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); +TEST_F(SchedulerTest, + MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( + slow_duration); + + bool expect_send_begin_main_frame = true; + EXPECT_SCOPED( + CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); } -TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { - // Set up client so that estimates indicate that we can commit and activate - // before the deadline (~8ms by default), but also enable impl latency takes - // priority mode. - EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); +TEST_F(SchedulerTest, + MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration); + + bool expect_send_begin_main_frame = true; + EXPECT_SCOPED( + CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); } -TEST_F(SchedulerTest, PollForCommitCompletion) { - // Since we are simulating a long commit, set up a client with draw duration - // estimates that prevent skipping main frames to get to low latency mode. - SchedulerClientWithFixedEstimates* client = - new SchedulerClientWithFixedEstimates( - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMilliseconds(32), - base::TimeDelta::FromMilliseconds(32)); +TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong) { scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(true); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration); + + bool expect_send_begin_main_frame = true; + EXPECT_SCOPED( + CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); +} - client->set_log_anticipated_draw_time_change(true); +void SchedulerTest::ImplFrameSkippedAfterLateSwapAck( + bool swap_ack_before_deadline) { + // To get into a high latency state, this test disables automatic swap acks. + scheduler_->SetMaxSwapsPending(1); + client_->SetAutomaticSwapAck(false); - BeginFrameArgs frame_args = - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); - frame_args.interval = base::TimeDelta::FromMilliseconds(1000); + // Draw and swap for first BeginFrame + client_->Reset(); + scheduler_->SetNeedsCommit(); + scheduler_->SetNeedsRedraw(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4); + EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4); + EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 4); + + client_->Reset(); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); + EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); + + // Verify we skip every other frame if the swap ack consistently + // comes back late. + for (int i = 0; i < 10; i++) { + // Not calling scheduler_->DidSwapBuffersComplete() until after next + // BeginImplFrame puts the impl thread in high latency mode. + client_->Reset(); + scheduler_->SetNeedsCommit(); + scheduler_->SetNeedsRedraw(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + // Verify that we skip the BeginImplFrame + EXPECT_NO_ACTION(client_); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + + // Verify that we do not perform any actions after we are no longer + // swap throttled. + client_->Reset(); + if (swap_ack_before_deadline) { + // It shouldn't matter if the swap ack comes back before the deadline... + scheduler_->DidSwapBuffersComplete(); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + } else { + // ... or after the deadline. + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + scheduler_->DidSwapBuffersComplete(); + } + EXPECT_NO_ACTION(client_); + + // Verify that we start the next BeginImplFrame and continue normally + // after having just skipped a BeginImplFrame. + client_->Reset(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); + + client_->Reset(); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); + EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); + } +} + +TEST_F(SchedulerTest, + ImplFrameSkippedAfterLateSwapAck_FastEstimates_SwapAckThenDeadline) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + + bool swap_ack_before_deadline = true; + EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline)); +} + +TEST_F(SchedulerTest, + ImplFrameSkippedAfterLateSwapAck_FastEstimates_DeadlineThenSwapAck) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + + bool swap_ack_before_deadline = false; + EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline)); +} + +TEST_F(SchedulerTest, + ImplFrameSkippedAfterLateSwapAck_ImplLatencyTakesPriority) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + // Even if every estimate related to the main thread is slow, we should + // still expect to recover impl thread latency if the draw is fast and we + // are in impl latency takes priority. + scheduler_->SetImplLatencyTakesPriority(true); + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration); + + bool swap_ack_before_deadline = false; + EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline)); +} + +TEST_F(SchedulerTest, + ImplFrameSkippedAfterLateSwapAck_OnlyImplSideUpdatesExpected) { + // This tests that we recover impl thread latency when there are no commits. + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + // To get into a high latency state, this test disables automatic swap acks. + scheduler_->SetMaxSwapsPending(1); + client_->SetAutomaticSwapAck(false); + + // Even if every estimate related to the main thread is slow, we should + // still expect to recover impl thread latency if there are no commits from + // the main thread. + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration); + + // Draw and swap for first BeginFrame + client_->Reset(); + scheduler_->SetNeedsRedraw(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); + EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); + EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 3); + + client_->Reset(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); + + // Verify we skip every other frame if the swap ack consistently + // comes back late. + for (int i = 0; i < 10; i++) { + // Not calling scheduler_->DidSwapBuffersComplete() until after next + // BeginImplFrame puts the impl thread in high latency mode. + client_->Reset(); + scheduler_->SetNeedsRedraw(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + // Verify that we skip the BeginImplFrame + EXPECT_NO_ACTION(client_); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); - // At this point, we've drawn a frame. Start another commit, but hold off on - // the NotifyReadyToCommit for now. + // Verify that we do not perform any actions after we are no longer + // swap throttled. + client_->Reset(); + scheduler_->DidSwapBuffersComplete(); + EXPECT_NO_ACTION(client_); + + // Verify that we start the next BeginImplFrame and continue normally + // after having just skipped a BeginImplFrame. + client_->Reset(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); + + client_->Reset(); + // Deadline should be immediate. + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner().RunUntilTime(now_src_->NowTicks()); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); + } +} + +void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() { + // To get into a high latency state, this test disables automatic swap acks. + scheduler_->SetMaxSwapsPending(1); + client_->SetAutomaticSwapAck(false); + + // Draw and swap for first BeginFrame + client_->Reset(); + scheduler_->SetNeedsCommit(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); + EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); + + client_->Reset(); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); + EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); + + // Verify impl thread consistently operates in high latency mode + // without skipping any frames. + for (int i = 0; i < 10; i++) { + // Not calling scheduler_->DidSwapBuffersComplete() until after next frame + // puts the impl thread in high latency mode. + client_->Reset(); + scheduler_->SetNeedsCommit(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + + client_->Reset(); + scheduler_->DidSwapBuffersComplete(); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + + // Verify that we don't skip the actions of the BeginImplFrame + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 5); + EXPECT_ACTION("ScheduledActionCommit", client_, 1, 5); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 2, 5); + EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5); + } +} + +TEST_F(SchedulerTest, + ImplFrameIsNotSkippedAfterLateSwapAck_CommitEstimateTooLong) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( + slow_duration); + EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); +} + +TEST_F(SchedulerTest, + ImplFrameIsNotSkippedAfterLateSwapAck_ReadyToActivateEstimateTooLong) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( + slow_duration); + EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); +} + +TEST_F(SchedulerTest, + ImplFrameIsNotSkippedAfterLateSwapAck_ActivateEstimateTooLong) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration); + EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); +} + +TEST_F(SchedulerTest, + ImplFrameIsNotSkippedAfterLateSwapAck_DrawEstimateTooLong) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration); + EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); +} + +TEST_F(SchedulerTest, + MainFrameThenImplFrameSkippedAfterLateCommitAndLateSwapAck) { + // Set up client with custom estimates. + // This test starts off with expensive estimates to prevent latency recovery + // initially, then lowers the estimates to enable it once both the main + // and impl threads are in a high latency mode. + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + auto slow_duration = base::TimeDelta::FromSeconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration); + + // To get into a high latency state, this test disables automatic swap acks. + scheduler_->SetMaxSwapsPending(1); + client_->SetAutomaticSwapAck(false); + + // Impl thread hits deadline before commit finishes to make + // MainThreadIsInHighLatencyMode true + client_->Reset(); + scheduler_->SetNeedsCommit(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); + EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); + + EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); + EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); + EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5); + + // Draw and swap for first commit, start second commit. + client_->Reset(); + scheduler_->SetNeedsCommit(); + EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); + + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6); + EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6); + + // Don't call scheduler_->DidSwapBuffersComplete() until after next frame + // to put the impl thread in a high latency mode. + client_->Reset(); + scheduler_->SetNeedsCommit(); + EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); + EXPECT_TRUE(scheduler_->SwapThrottled()); + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); + // Note: BeginMainFrame and swap are skipped here because of + // swap ack backpressure, not because of latency recovery. + EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame")); + EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); + EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); + + // Lower estimates so that the scheduler will attempt latency recovery. + auto fast_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); + + // Now that both threads are in a high latency mode, make sure we + // skip the BeginMainFrame, then the BeginImplFrame, but not both + // at the same time. + + // Verify we skip BeginMainFrame first. + client_->Reset(); + // Previous commit request is still outstanding. + EXPECT_TRUE(scheduler_->NeedsCommit()); + EXPECT_TRUE(scheduler_->SwapThrottled()); + SendNextBeginFrame(); + EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); + scheduler_->DidSwapBuffersComplete(); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3); + + // Verify we skip the BeginImplFrame second. + client_->Reset(); + // Previous commit request is still outstanding. + EXPECT_TRUE(scheduler_->NeedsCommit()); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + scheduler_->DidSwapBuffersComplete(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + + EXPECT_NO_ACTION(client_); + + // Then verify we operate in a low latency mode. + client_->Reset(); + // Previous commit request is still outstanding. + EXPECT_TRUE(scheduler_->NeedsCommit()); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + SendNextBeginFrame(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + scheduler_->DidSwapBuffersComplete(); + EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); + + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6); + EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6); + EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6); +} + +TEST_F( + SchedulerTest, + Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { + // NPAPI plugins on Windows block the Browser UI thread on the Renderer main + // thread. This prevents the scheduler from receiving any pending swap acks. + + scheduler_settings_.use_external_begin_frame_source = true; + scheduler_settings_.main_frame_while_swap_throttled_enabled = true; + SetUpScheduler(true); + + // Disables automatic swap acks so this test can force swap ack throttling + // to simulate a blocked Browser ui thread. + scheduler_->SetMaxSwapsPending(1); + client_->SetAutomaticSwapAck(false); + + // Get a new active tree in main-thread high latency mode and put us + // in a swap throttled state. + client_->Reset(); EXPECT_FALSE(scheduler_->CommitPending()); scheduler_->SetNeedsCommit(); - fake_external_begin_frame_source()->TestOnBeginFrame(frame_args); + scheduler_->SetNeedsRedraw(); + EXPECT_SCOPED(AdvanceFrame()); EXPECT_TRUE(scheduler_->CommitPending()); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); + EXPECT_FALSE(scheduler_->CommitPending()); + EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 7); + EXPECT_ACTION("WillBeginImplFrame", client_, 1, 7); + EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 7); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 7); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 7); + EXPECT_ACTION("ScheduledActionCommit", client_, 5, 7); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 6, 7); - // Draw and swap the frame, but don't ack the swap to simulate the Browser - // blocking on the renderer. + // Make sure that we can finish the next commit even while swap throttled. + client_->Reset(); + EXPECT_FALSE(scheduler_->CommitPending()); + scheduler_->SetNeedsCommit(); + EXPECT_SCOPED(AdvanceFrame()); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 5); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); + EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); + EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 5); + + // Make sure we do not send a BeginMainFrame while swap throttled and + // we have both a pending tree and an active tree. + client_->Reset(); + EXPECT_FALSE(scheduler_->CommitPending()); + scheduler_->SetNeedsCommit(); + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_FALSE(scheduler_->CommitPending()); task_runner().RunPendingTasks(); // Run posted deadline. + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); +} + +TEST_F(SchedulerTest, + Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull) { + // NPAPI plugins on Windows block the Browser UI thread on the Renderer main + // thread. This prevents the scheduler from receiving any pending swap acks. + + // This particular test makes sure we do not send a BeginMainFrame while + // swap trottled and we have a pending tree and active tree that + // still needs to be drawn for the first time. + + scheduler_settings_.use_external_begin_frame_source = true; + scheduler_settings_.main_frame_while_swap_throttled_enabled = true; + scheduler_settings_.main_frame_before_activation_enabled = true; + SetUpScheduler(true); + + // Disables automatic swap acks so this test can force swap ack throttling + // to simulate a blocked Browser ui thread. + scheduler_->SetMaxSwapsPending(1); + client_->SetAutomaticSwapAck(false); + + // Start a new commit in main-thread high latency mode and hold off on + // activation. + client_->Reset(); + EXPECT_FALSE(scheduler_->CommitPending()); + scheduler_->SetNeedsCommit(); + scheduler_->SetNeedsRedraw(); + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_TRUE(scheduler_->CommitPending()); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - scheduler_->DidSwapBuffers(); - - // Spin the event loop a few times and make sure we get more - // DidAnticipateDrawTimeChange calls every time. - int actions_so_far = client->num_actions_(); - - // Does three iterations to make sure that the timer is properly repeating. - for (int i = 0; i < 3; ++i) { - EXPECT_EQ((frame_args.interval * 2).InMicroseconds(), - task_runner().DelayToNextTaskTime().InMicroseconds()) - << scheduler_->AsValue()->ToString(); - task_runner().RunPendingTasks(); - EXPECT_GT(client->num_actions_(), actions_so_far); - EXPECT_STREQ(client->Action(client->num_actions_() - 1), - "DidAnticipatedDrawTimeChange"); - actions_so_far = client->num_actions_(); - } + scheduler_->DidSwapBuffersComplete(); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + EXPECT_FALSE(scheduler_->CommitPending()); + EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6); + EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6); + EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6); + EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6); - // Do the same thing after BeginMainFrame starts but still before activation. + // Start another commit while we still have aa pending tree. + // Enter a swap throttled state. + client_->Reset(); + EXPECT_FALSE(scheduler_->CommitPending()); + scheduler_->SetNeedsCommit(); + scheduler_->SetNeedsRedraw(); + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_TRUE(scheduler_->CommitPending()); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); scheduler_->NotifyBeginMainFrameStarted(); - for (int i = 0; i < 3; ++i) { - EXPECT_EQ((frame_args.interval * 2).InMicroseconds(), - task_runner().DelayToNextTaskTime().InMicroseconds()) - << scheduler_->AsValue()->ToString(); - task_runner().RunPendingTasks(); - EXPECT_GT(client->num_actions_(), actions_so_far); - EXPECT_STREQ(client->Action(client->num_actions_() - 1), - "DidAnticipatedDrawTimeChange"); - actions_so_far = client->num_actions_(); - } + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); + + // Can't commit yet because there's still a pending tree. + client_->Reset(); + scheduler_->NotifyReadyToCommit(); + EXPECT_NO_ACTION(client_); + + // Activate the pending tree, which also unblocks the commit immediately. + client_->Reset(); + scheduler_->NotifyReadyToActivate(); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2); + EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2); + + // Make sure we do not send a BeginMainFrame while swap throttled and + // we have both a pending tree and an active tree that still needs + // it's first draw. + client_->Reset(); + EXPECT_FALSE(scheduler_->CommitPending()); + scheduler_->SetNeedsCommit(); + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_FALSE(scheduler_->CommitPending()); + task_runner().RunPendingTasks(); // Run posted deadline. + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); +} + +TEST_F( + SchedulerTest, + CommitMakesProgressWhenIdleAndHasPendingTreeAndActiveTreeNeedsFirstDraw) { + // This verifies we don't block commits longer than we need to + // for performance reasons - not deadlock reasons. + + // Since we are simulating a long commit, set up a client with draw duration + // estimates that prevent skipping main frames to get to low latency mode. + scheduler_settings_.use_external_begin_frame_source = true; + scheduler_settings_.main_frame_while_swap_throttled_enabled = true; + scheduler_settings_.main_frame_before_activation_enabled = true; + SetUpScheduler(true); + + // Disables automatic swap acks so this test can force swap ack throttling + // to simulate a blocked Browser ui thread. + scheduler_->SetMaxSwapsPending(1); + client_->SetAutomaticSwapAck(false); + + // Start a new commit in main-thread high latency mode and hold off on + // activation. + client_->Reset(); + EXPECT_FALSE(scheduler_->CommitPending()); + scheduler_->SetNeedsCommit(); + scheduler_->SetNeedsRedraw(); + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_TRUE(scheduler_->CommitPending()); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + scheduler_->DidSwapBuffersComplete(); + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + EXPECT_FALSE(scheduler_->CommitPending()); + EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6); + EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6); + EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6); + EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6); + + // Start another commit while we still have an active tree. + client_->Reset(); + EXPECT_FALSE(scheduler_->CommitPending()); + scheduler_->SetNeedsCommit(); + scheduler_->SetNeedsRedraw(); + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_TRUE(scheduler_->CommitPending()); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + scheduler_->DidSwapBuffersComplete(); + scheduler_->NotifyBeginMainFrameStarted(); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); + + // Can't commit yet because there's still a pending tree. + client_->Reset(); + scheduler_->NotifyReadyToCommit(); + EXPECT_NO_ACTION(client_); + + // Activate the pending tree, which also unblocks the commit immediately + // while we are in an idle state. + client_->Reset(); + scheduler_->NotifyReadyToActivate(); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2); + EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2); } TEST_F(SchedulerTest, BeginRetroFrame) { @@ -1480,6 +2121,12 @@ TEST_F(SchedulerTest, BeginRetroFrame) { EXPECT_TRUE(client_->needs_begin_frames()); client_->Reset(); + // NotifyReadyToActivate should trigger the activation. + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + EXPECT_TRUE(client_->needs_begin_frames()); + client_->Reset(); + // BeginImplFrame should prepare the draw. task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); @@ -1538,13 +2185,19 @@ TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) { EXPECT_TRUE(client_->needs_begin_frames()); client_->Reset(); - // NotifyReadyToCommit should trigger the pending commit and draw. + // NotifyReadyToCommit should trigger the pending commit. scheduler_->NotifyBeginMainFrameStarted(); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); EXPECT_TRUE(client_->needs_begin_frames()); client_->Reset(); + // NotifyReadyToActivate should trigger the activation and draw. + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + EXPECT_TRUE(client_->needs_begin_frames()); + client_->Reset(); + // Swapping will put us into a swap throttled state. // Run posted deadline. task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); @@ -1568,9 +2221,9 @@ TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) { // Let time pass sufficiently beyond the regular deadline but not beyond the // late deadline. - now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() - - base::TimeDelta::FromMicroseconds(1)); - task_runner().RunUntilTime(now_src()->Now()); + now_src()->Advance(BeginFrameArgs::DefaultInterval() - + base::TimeDelta::FromMicroseconds(1)); + task_runner().RunUntilTime(now_src()->NowTicks()); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); // Take us out of a swap throttled state. @@ -1581,7 +2234,7 @@ TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) { client_->Reset(); // Verify that the deadline was rescheduled. - task_runner().RunUntilTime(now_src()->Now()); + task_runner().RunUntilTime(now_src()->NowTicks()); EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); EXPECT_TRUE(client_->needs_begin_frames()); @@ -1606,16 +2259,19 @@ TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) { scheduler_->NotifyBeginMainFrameStarted(); client_->Reset(); - SendNextBeginFrame(); + BeginFrameArgs retro_frame_args = SendNextBeginFrame(); // This BeginFrame is queued up as a retro frame. EXPECT_NO_ACTION(client_); // The previous deadline is still pending. EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); - // This commit should schedule the (previous) deadline to trigger immediately. + // This main frame activating should schedule the (previous) deadline to + // trigger immediately. scheduler_->NotifyReadyToCommit(); - EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); + scheduler_->NotifyReadyToActivate(); + EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2); client_->Reset(); // The deadline task should trigger causing a draw. @@ -1630,10 +2286,8 @@ TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) { scheduler_->SetNeedsRedraw(); EXPECT_NO_ACTION(client_); - // Let's advance sufficiently past the next frame's deadline. - now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() - - BeginFrameArgs::DefaultEstimatedParentDrawTime() + - base::TimeDelta::FromMicroseconds(1)); + // Let's advance to the retro frame's deadline. + now_src()->Advance(retro_frame_args.deadline - now_src()->NowTicks()); // The retro frame hasn't expired yet. task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)); @@ -1648,7 +2302,7 @@ TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) { EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); } -TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooLate) { +TEST_F(SchedulerTest, RetroFrameExpiresOnTime) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); @@ -1666,16 +2320,19 @@ TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooLate) { scheduler_->NotifyBeginMainFrameStarted(); client_->Reset(); - SendNextBeginFrame(); + BeginFrameArgs retro_frame_args = SendNextBeginFrame(); // This BeginFrame is queued up as a retro frame. EXPECT_NO_ACTION(client_); // The previous deadline is still pending. EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); - // This commit should schedule the (previous) deadline to trigger immediately. + // This main frame activating should schedule the (previous) deadline to + // trigger immediately. scheduler_->NotifyReadyToCommit(); - EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); + scheduler_->NotifyReadyToActivate(); + EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2); client_->Reset(); // The deadline task should trigger causing a draw. @@ -1690,14 +2347,64 @@ TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooLate) { scheduler_->SetNeedsRedraw(); EXPECT_NO_ACTION(client_); - // Let's advance sufficiently past the next frame's deadline. - now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() + - base::TimeDelta::FromMicroseconds(1)); + // Let's advance sufficiently past the retro frame's deadline. + now_src()->Advance(retro_frame_args.deadline - now_src()->NowTicks() + + base::TimeDelta::FromMicroseconds(1)); // The retro frame should've expired. EXPECT_NO_ACTION(client_); } +TEST_F(SchedulerTest, MissedFrameDoesNotExpireTooEarly) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + scheduler_->SetNeedsCommit(); + EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + + BeginFrameArgs missed_frame_args = + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); + missed_frame_args.type = BeginFrameArgs::MISSED; + + // Advance to the deadline. + now_src()->Advance(missed_frame_args.deadline - now_src()->NowTicks()); + + // Missed frame is handled because it's on time. + client_->Reset(); + fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args); + EXPECT_TRUE( + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false))); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); +} + +TEST_F(SchedulerTest, MissedFrameExpiresOnTime) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + scheduler_->SetNeedsCommit(); + EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + + BeginFrameArgs missed_frame_args = + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); + missed_frame_args.type = BeginFrameArgs::MISSED; + + // Advance sufficiently past the deadline. + now_src()->Advance(missed_frame_args.deadline - now_src()->NowTicks() + + base::TimeDelta::FromMicroseconds(1)); + + // Missed frame is dropped because it's too late. + client_->Reset(); + fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args); + EXPECT_FALSE( + task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false))); + EXPECT_NO_ACTION(client_); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); +} + void SchedulerTest::BeginFramesNotFromClient( bool use_external_begin_frame_source, bool throttle_frame_production) { @@ -1732,6 +2439,11 @@ void SchedulerTest::BeginFramesNotFromClient( EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); client_->Reset(); + // NotifyReadyToActivate should trigger the activation. + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + client_->Reset(); + // BeginImplFrame should prepare the draw. task_runner().RunPendingTasks(); // Run posted BeginFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); @@ -1807,12 +2519,17 @@ void SchedulerTest::BeginFramesNotFromClient_SwapThrottled( EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); - // NotifyReadyToCommit should trigger the pending commit and draw. + // NotifyReadyToCommit should trigger the pending commit. scheduler_->NotifyBeginMainFrameStarted(); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); client_->Reset(); + // NotifyReadyToActivate should trigger the activation and draw. + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + client_->Reset(); + // Swapping will put us into a swap throttled state. // Run posted deadline. task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); @@ -1833,9 +2550,9 @@ void SchedulerTest::BeginFramesNotFromClient_SwapThrottled( // Let time pass sufficiently beyond the regular deadline but not beyond the // late deadline. - now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() - - base::TimeDelta::FromMicroseconds(1)); - task_runner().RunUntilTime(now_src()->Now()); + now_src()->Advance(BeginFrameArgs::DefaultInterval() - + base::TimeDelta::FromMicroseconds(1)); + task_runner().RunUntilTime(now_src()->NowTicks()); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); // Take us out of a swap throttled state. @@ -1847,9 +2564,9 @@ void SchedulerTest::BeginFramesNotFromClient_SwapThrottled( // Verify that the deadline was rescheduled. // We can't use RunUntilTime(now) here because the next frame is also // scheduled if throttle_frame_production = false. - base::TimeTicks before_deadline = now_src()->Now(); + base::TimeTicks before_deadline = now_src()->NowTicks(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - base::TimeTicks after_deadline = now_src()->Now(); + base::TimeTicks after_deadline = now_src()->NowTicks(); EXPECT_EQ(after_deadline, before_deadline); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); @@ -1916,7 +2633,8 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) { client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(); scheduler_->NotifyReadyToCommit(); - EXPECT_ACTION("ScheduledActionCommit", client_, 0, 1); + EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2); client_->Reset(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); @@ -1925,9 +2643,8 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) { EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); } -void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency( - bool impl_side_painting) { - scheduler_settings_.impl_side_painting = impl_side_painting; +TEST_F(SchedulerTest, + DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); @@ -1958,7 +2675,7 @@ void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency( // BeginImplFrame is not started. client_->Reset(); - task_runner().RunUntilTime(now_src()->Now() + + task_runner().RunUntilTime(now_src()->NowTicks() + base::TimeDelta::FromMilliseconds(10)); EXPECT_NO_ACTION(client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); @@ -1966,31 +2683,12 @@ void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency( client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(); scheduler_->NotifyReadyToCommit(); - if (impl_side_painting) { - EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3); - EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3); - EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3); - } else { - EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2); - EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 2); - } -} - -TEST_F(SchedulerTest, - DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) { - bool impl_side_painting = false; - DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting); + EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3); + EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3); } -TEST_F(SchedulerTest, - DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) { - bool impl_side_painting = true; - DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting); -} - -void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit( - bool impl_side_painting) { - scheduler_settings_.impl_side_painting = impl_side_painting; +TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); @@ -2011,14 +2709,10 @@ void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit( client_->Reset(); scheduler_->DidLoseOutputSurface(); - // SetNeedsBeginFrames(false) is not called until the end of the frame. - if (impl_side_painting) { - // Sync tree should be forced to activate. - EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); - } else { - EXPECT_NO_ACTION(client_); - } + // Sync tree should be forced to activate. + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + // SetNeedsBeginFrames(false) is not called until the end of the frame. client_->Reset(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); @@ -2026,14 +2720,6 @@ void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit( EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); } -TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) { - DidLoseOutputSurfaceAfterReadyToCommit(false); -} - -TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) { - DidLoseOutputSurfaceAfterReadyToCommit(true); -} - TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); @@ -2101,6 +2787,12 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) { EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); EXPECT_TRUE(client_->needs_begin_frames()); + // NotifyReadyToActivate should trigger the activation. + client_->Reset(); + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + EXPECT_TRUE(client_->needs_begin_frames()); + client_->Reset(); EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty()); scheduler_->DidLoseOutputSurface(); @@ -2155,6 +2847,12 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) { EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); EXPECT_TRUE(client_->needs_begin_frames()); + // NotifyReadyToActivate should trigger the activation. + client_->Reset(); + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + EXPECT_TRUE(client_->needs_begin_frames()); + // BeginImplFrame should prepare the draw. client_->Reset(); task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. @@ -2206,6 +2904,12 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) { EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); + // NotifyReadyToActivate should trigger the activation. + client_->Reset(); + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); + client_->Reset(); scheduler_->DidLoseOutputSurface(); // SetNeedsBeginFrames(false) is not called until the end of the frame. @@ -2239,6 +2943,10 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) { EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); client_->Reset(); + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + + client_->Reset(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); @@ -2252,7 +2960,6 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) { } TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) { - scheduler_settings_.impl_side_painting = true; scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); @@ -2413,12 +3120,14 @@ TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) { EXPECT_SCOPED(AdvanceFrame()); scheduler_->NotifyBeginMainFrameStarted(); scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); task_runner().RunPendingTasks(); - EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5); - EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 5); - EXPECT_ACTION("ScheduledActionCommit", client_, 2, 5); - EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5); - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6); + EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6); + EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6); client_->Reset(); // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) @@ -2437,7 +3146,6 @@ TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) { TEST_F(SchedulerTest, SynchronousCompositorAnimation) { scheduler_settings_.using_synchronous_renderer_compositor = true; scheduler_settings_.use_external_begin_frame_source = true; - scheduler_settings_.impl_side_painting = true; SetUpScheduler(true); scheduler_->SetNeedsAnimate(); @@ -2490,7 +3198,6 @@ TEST_F(SchedulerTest, SynchronousCompositorAnimation) { TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) { scheduler_settings_.using_synchronous_renderer_compositor = true; scheduler_settings_.use_external_begin_frame_source = true; - scheduler_settings_.impl_side_painting = true; SetUpScheduler(true); scheduler_->SetNeedsRedraw(); @@ -2513,7 +3220,6 @@ TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) { TEST_F(SchedulerTest, SynchronousCompositorCommit) { scheduler_settings_.using_synchronous_renderer_compositor = true; scheduler_settings_.use_external_begin_frame_source = true; - scheduler_settings_.impl_side_painting = true; SetUpScheduler(true); scheduler_->SetNeedsCommit(); @@ -2571,7 +3277,6 @@ TEST_F(SchedulerTest, SynchronousCompositorCommit) { TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) { scheduler_settings_.using_synchronous_renderer_compositor = true; scheduler_settings_.use_external_begin_frame_source = true; - scheduler_settings_.impl_side_painting = true; SetUpScheduler(true); scheduler_->SetNeedsCommit(); @@ -2625,17 +3330,11 @@ class SchedulerClientSetNeedsPrepareTilesOnDraw : public FakeSchedulerClient { scheduler_->SetNeedsPrepareTiles(); return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible(); } - - void ScheduledActionPrepareTiles() override { - FakeSchedulerClient::ScheduledActionPrepareTiles(); - scheduler_->DidPrepareTiles(); - } }; TEST_F(SchedulerTest, SynchronousCompositorPrepareTilesOnDraw) { scheduler_settings_.using_synchronous_renderer_compositor = true; scheduler_settings_.use_external_begin_frame_source = true; - scheduler_settings_.impl_side_painting = true; scoped_ptr<FakeSchedulerClient> client = make_scoped_ptr(new SchedulerClientSetNeedsPrepareTilesOnDraw); @@ -2680,21 +3379,80 @@ TEST_F(SchedulerTest, SynchronousCompositorPrepareTilesOnDraw) { client_->Reset(); } -TEST_F(SchedulerTest, AuthoritativeVSyncInterval) { +TEST_F(SchedulerTest, SynchronousCompositorSendBeginMainFrameWhileIdle) { + scheduler_settings_.using_synchronous_renderer_compositor = true; + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); - base::TimeDelta initial_interval = - scheduler_->begin_impl_frame_args().interval; + scheduler_->SetNeedsRedraw(); + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + client_->Reset(); + + // Next vsync. + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); + EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3); + client_->Reset(); + + // Android onDraw. + scheduler_->SetNeedsRedraw(); + scheduler_->OnDrawForOutputSurface(); + EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(scheduler_->PrepareTilesPending()); + client_->Reset(); + + // Simulate SetNeedsCommit due to input event. + scheduler_->SetNeedsCommit(); + EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_); + client_->Reset(); + + scheduler_->NotifyBeginMainFrameStarted(); + scheduler_->NotifyReadyToCommit(); + EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); + client_->Reset(); + + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + client_->Reset(); + + // Next vsync. + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); + EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3); + client_->Reset(); + + // Android onDraw. + scheduler_->SetNeedsRedraw(); + scheduler_->OnDrawForOutputSurface(); + EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(scheduler_->PrepareTilesPending()); + client_->Reset(); + + // Simulate SetNeedsCommit due to input event. + scheduler_->SetNeedsCommit(); + EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_); + client_->Reset(); +} + +TEST_F(SchedulerTest, AuthoritativeVSyncInterval) { + SetUpScheduler(true); + base::TimeDelta initial_interval = scheduler_->BeginImplFrameInterval(); base::TimeDelta authoritative_interval = base::TimeDelta::FromMilliseconds(33); scheduler_->SetNeedsCommit(); EXPECT_SCOPED(AdvanceFrame()); - EXPECT_EQ(initial_interval, scheduler_->begin_impl_frame_args().interval); + EXPECT_EQ(initial_interval, scheduler_->BeginImplFrameInterval()); scheduler_->NotifyBeginMainFrameStarted(); scheduler_->NotifyReadyToCommit(); + scheduler_->NotifyReadyToActivate(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); scheduler_->SetAuthoritativeVSyncInterval(authoritative_interval); @@ -2703,9 +3461,41 @@ TEST_F(SchedulerTest, AuthoritativeVSyncInterval) { // At the next BeginFrame, authoritative interval is used instead of previous // interval. - EXPECT_NE(initial_interval, scheduler_->begin_impl_frame_args().interval); - EXPECT_EQ(authoritative_interval, - scheduler_->begin_impl_frame_args().interval); + EXPECT_NE(initial_interval, scheduler_->BeginImplFrameInterval()); + EXPECT_EQ(authoritative_interval, scheduler_->BeginImplFrameInterval()); +} + +TEST_F(SchedulerTest, ImplLatencyTakesPriority) { + SetUpScheduler(true); + scheduler_->SetImplLatencyTakesPriority(true); + EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority()); + + scheduler_->SetImplLatencyTakesPriority(false); + EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority()); +} + +TEST_F(SchedulerTest, BeginFrameArgs_OnCriticalPath) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + scheduler_->SetImplLatencyTakesPriority(false); + scheduler_->SetChildrenNeedBeginFrames(true); + + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); + EXPECT_TRUE(client_->begin_frame_args_sent_to_children().on_critical_path); +} + +TEST_F(SchedulerTest, BeginFrameArgs_NotOnCriticalPath) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + scheduler_->SetImplLatencyTakesPriority(true); + scheduler_->SetChildrenNeedBeginFrames(true); + + EXPECT_SCOPED(AdvanceFrame()); + EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); + EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); } } // namespace diff --git a/chromium/cc/surfaces/BUILD.gn b/chromium/cc/surfaces/BUILD.gn index e43d4e5741f..0f2c9509f4b 100644 --- a/chromium/cc/surfaces/BUILD.gn +++ b/chromium/cc/surfaces/BUILD.gn @@ -18,6 +18,8 @@ component("surfaces") { "display.cc", "display.h", "display_client.h", + "display_scheduler.cc", + "display_scheduler.h", "onscreen_display_client.cc", "onscreen_display_client.h", "surface.cc", @@ -45,6 +47,7 @@ component("surfaces") { "//base", "//base/third_party/dynamic_annotations", "//cc", + "//gpu/command_buffer/client:gles2_interface", "//skia", "//ui/events:events_base", "//ui/gfx", diff --git a/chromium/cc/surfaces/OWNERS b/chromium/cc/surfaces/OWNERS index 023e5fc459f..5e473090ed6 100644 --- a/chromium/cc/surfaces/OWNERS +++ b/chromium/cc/surfaces/OWNERS @@ -1 +1 @@ -jamesr@chromium.org +jbauman@chromium.org diff --git a/chromium/cc/surfaces/display.cc b/chromium/cc/surfaces/display.cc index e2b81728393..37a9756950c 100644 --- a/chromium/cc/surfaces/display.cc +++ b/chromium/cc/surfaces/display.cc @@ -15,10 +15,11 @@ #include "cc/output/software_renderer.h" #include "cc/output/texture_mailbox_deleter.h" #include "cc/surfaces/display_client.h" +#include "cc/surfaces/display_scheduler.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_aggregator.h" #include "cc/surfaces/surface_manager.h" -#include "cc/trees/blocking_task_runner.h" +#include "gpu/command_buffer/client/gles2_interface.h" namespace cc { @@ -33,10 +34,9 @@ Display::Display(DisplayClient* client, gpu_memory_buffer_manager_(gpu_memory_buffer_manager), settings_(settings), device_scale_factor_(1.f), - blocking_main_thread_task_runner_( - BlockingTaskRunner::Create(base::ThreadTaskRunnerHandle::Get())), - texture_mailbox_deleter_( - new TextureMailboxDeleter(base::ThreadTaskRunnerHandle::Get())) { + swapped_since_resize_(false), + scheduler_(nullptr), + texture_mailbox_deleter_(new TextureMailboxDeleter(nullptr)) { manager_->AddObserver(this); } @@ -51,15 +51,23 @@ Display::~Display() { } } -bool Display::Initialize(scoped_ptr<OutputSurface> output_surface) { +bool Display::Initialize(scoped_ptr<OutputSurface> output_surface, + DisplayScheduler* scheduler) { output_surface_ = output_surface.Pass(); + scheduler_ = scheduler; return output_surface_->BindToClient(this); } void Display::SetSurfaceId(SurfaceId id, float device_scale_factor) { + if (current_surface_id_ == id && device_scale_factor_ == device_scale_factor) + return; + current_surface_id_ = id; device_scale_factor_ = device_scale_factor; - client_->DisplayDamaged(); + + UpdateRootSurfaceResourcesLocked(); + if (scheduler_) + scheduler_->EntireDisplayDamaged(id); } void Display::Resize(const gfx::Size& size) { @@ -67,21 +75,34 @@ void Display::Resize(const gfx::Size& size) { return; // Need to ensure all pending swaps have executed before the window is // resized, or D3D11 will scale the swap output. - if (renderer_ && settings_.finish_rendering_on_resize) - renderer_->Finish(); + if (settings_.finish_rendering_on_resize) { + if (!swapped_since_resize_ && scheduler_) + scheduler_->ForceImmediateSwapIfPossible(); + if (swapped_since_resize_ && output_surface_ && + output_surface_->context_provider()) + output_surface_->context_provider()->ContextGL()->ShallowFinishCHROMIUM(); + } + swapped_since_resize_ = false; current_surface_size_ = size; - client_->DisplayDamaged(); + if (scheduler_) + scheduler_->EntireDisplayDamaged(current_surface_id_); +} + +void Display::SetExternalClip(const gfx::Rect& clip) { + external_clip_ = clip; } void Display::InitializeRenderer() { if (resource_provider_) return; + // Display does not use GpuMemoryBuffers, so persistent map is not relevant. + bool use_persistent_map_for_gpu_memory_buffers = false; scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create( output_surface_.get(), bitmap_manager_, gpu_memory_buffer_manager_, - blocking_main_thread_task_runner_.get(), settings_.highp_threshold_min, - settings_.use_rgba_4444_textures, - settings_.texture_id_allocation_chunk_size); + nullptr, settings_.highp_threshold_min, settings_.use_rgba_4444_textures, + settings_.texture_id_allocation_chunk_size, + use_persistent_map_for_gpu_memory_buffers); if (!resource_provider) return; @@ -105,10 +126,21 @@ void Display::InitializeRenderer() { } void Display::DidLoseOutputSurface() { + if (scheduler_) + scheduler_->OutputSurfaceLost(); + // WARNING: The client may delete the Display in this method call. Do not + // make any additional references to members after this call. client_->OutputSurfaceLost(); } -bool Display::Draw() { +void Display::UpdateRootSurfaceResourcesLocked() { + Surface* surface = manager_->GetSurfaceForId(current_surface_id_); + bool root_surface_resources_locked = !surface || !surface->GetEligibleFrame(); + if (scheduler_) + scheduler_->SetRootSurfaceResourcesLocked(root_surface_resources_locked); +} + +bool Display::DrawAndSwap() { if (current_surface_id_.is_null()) return false; @@ -116,15 +148,12 @@ bool Display::Draw() { if (!output_surface_) return false; - // TODO(skyostil): We should hold a BlockingTaskRunner::CapturePostTasks - // while Aggregate is called to immediately run release callbacks afterward. scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(current_surface_id_); if (!frame) return false; - TRACE_EVENT0("cc", "Display::Draw"); - benchmark_instrumentation::IssueDisplayRenderingStatsEvent(); + TRACE_EVENT0("cc", "Display::DrawAndSwap"); // Run callbacks early to allow pipelining. for (const auto& id_entry : aggregator_->previous_contained_surfaces()) { @@ -154,9 +183,18 @@ bool Display::Draw() { bool should_draw = !frame->metadata.latency_info.empty() || have_copy_requests || (have_damage && !avoid_swap); + // If the surface is suspended then the resources to be used by the draw are + // likely destroyed. + if (output_surface_->SurfaceIsSuspendForRecycle()) { + TRACE_EVENT_INSTANT0("cc", "Surface is suspended for recycle.", + TRACE_EVENT_SCOPE_THREAD); + should_draw = false; + } + if (should_draw) { gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_); - gfx::Rect device_clip_rect = device_viewport_rect; + gfx::Rect device_clip_rect = + external_clip_.IsEmpty() ? device_viewport_rect : external_clip_; bool disable_picture_quad_image_filtering = false; renderer_->DecideRenderPassAllocationsForFrame( @@ -167,6 +205,15 @@ bool Display::Draw() { } if (should_draw && !avoid_swap) { + swapped_since_resize_ = true; + for (auto& latency : frame->metadata.latency_info) { + TRACE_EVENT_FLOW_STEP0( + "input,benchmark", + "LatencyInfo.Flow", + TRACE_ID_DONT_MANGLE(latency.trace_id), + "Display::DrawAndSwap"); + } + benchmark_instrumentation::IssueDisplayRenderingStatsEvent(); renderer_->SwapBuffers(frame->metadata); } else { stored_latency_info_.insert(stored_latency_info_.end(), @@ -180,11 +227,13 @@ bool Display::Draw() { } void Display::DidSwapBuffers() { - client_->DidSwapBuffers(); + if (scheduler_) + scheduler_->DidSwapBuffers(); } void Display::DidSwapBuffersComplete() { - client_->DidSwapBuffersComplete(); + if (scheduler_) + scheduler_->DidSwapBuffersComplete(); } void Display::CommitVSyncParameters(base::TimeTicks timebase, @@ -234,27 +283,25 @@ void Display::OnSurfaceDamaged(SurfaceId surface_id, bool* changed) { if (surface) { const CompositorFrame* current_frame = surface->GetEligibleFrame(); if (!current_frame || !current_frame->delegated_frame_data || - !current_frame->delegated_frame_data->resource_list.size()) + !current_frame->delegated_frame_data->resource_list.size()) { aggregator_->ReleaseResources(surface_id); + } } - client_->DisplayDamaged(); + if (scheduler_) + scheduler_->SurfaceDamaged(surface_id); *changed = true; } else if (surface_id == current_surface_id_) { - client_->DisplayDamaged(); + if (scheduler_) + scheduler_->SurfaceDamaged(surface_id); *changed = true; } + + if (surface_id == current_surface_id_) + UpdateRootSurfaceResourcesLocked(); } SurfaceId Display::CurrentSurfaceId() { return current_surface_id_; } -int Display::GetMaxFramesPending() { - int max_frames_pending = - output_surface_ ? output_surface_->capabilities().max_frames_pending : 0; - if (max_frames_pending <= 0) - max_frames_pending = OutputSurface::DEFAULT_MAX_FRAMES_PENDING; - return max_frames_pending; -} - } // namespace cc diff --git a/chromium/cc/surfaces/display.h b/chromium/cc/surfaces/display.h index 22874a02c01..b849b461afb 100644 --- a/chromium/cc/surfaces/display.h +++ b/chromium/cc/surfaces/display.h @@ -11,6 +11,7 @@ #include "cc/output/output_surface_client.h" #include "cc/output/renderer.h" #include "cc/resources/returned_resource.h" +#include "cc/surfaces/display_scheduler.h" #include "cc/surfaces/surface_aggregator.h" #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_manager.h" @@ -27,7 +28,6 @@ class Size; namespace cc { -class BlockingTaskRunner; class DirectRenderer; class DisplayClient; class OutputSurface; @@ -43,7 +43,8 @@ class TextureMailboxDeleter; // A Display produces a surface that can be used to draw to a physical display // (OutputSurface). The client is responsible for creating and sizing the // surface IDs used to draw into the display and deciding when to draw. -class CC_SURFACES_EXPORT Display : public OutputSurfaceClient, +class CC_SURFACES_EXPORT Display : public DisplaySchedulerClient, + public OutputSurfaceClient, public RendererClient, public SurfaceDamageObserver { public: @@ -54,16 +55,19 @@ class CC_SURFACES_EXPORT Display : public OutputSurfaceClient, const RendererSettings& settings); ~Display() override; - bool Initialize(scoped_ptr<OutputSurface> output_surface); + bool Initialize(scoped_ptr<OutputSurface> output_surface, + DisplayScheduler* scheduler); // device_scale_factor is used to communicate to the external window system // what scale this was rendered at. void SetSurfaceId(SurfaceId id, float device_scale_factor); void Resize(const gfx::Size& new_size); - bool Draw(); + void SetExternalClip(const gfx::Rect& clip); SurfaceId CurrentSurfaceId(); - int GetMaxFramesPending(); + + // DisplaySchedulerClient implementation. + bool DrawAndSwap() override; // OutputSurfaceClient implementation. void CommitVSyncParameters(base::TimeTicks timebase, @@ -92,6 +96,7 @@ class CC_SURFACES_EXPORT Display : public OutputSurfaceClient, private: void InitializeRenderer(); + void UpdateRootSurfaceResourcesLocked(); DisplayClient* client_; SurfaceManager* manager_; @@ -101,11 +106,13 @@ class CC_SURFACES_EXPORT Display : public OutputSurfaceClient, SurfaceId current_surface_id_; gfx::Size current_surface_size_; float device_scale_factor_; + bool swapped_since_resize_; + gfx::Rect external_clip_; scoped_ptr<OutputSurface> output_surface_; + DisplayScheduler* scheduler_; scoped_ptr<ResourceProvider> resource_provider_; scoped_ptr<SurfaceAggregator> aggregator_; scoped_ptr<DirectRenderer> renderer_; - scoped_ptr<BlockingTaskRunner> blocking_main_thread_task_runner_; scoped_ptr<TextureMailboxDeleter> texture_mailbox_deleter_; std::vector<ui::LatencyInfo> stored_latency_info_; diff --git a/chromium/cc/surfaces/display_client.h b/chromium/cc/surfaces/display_client.h index 71ee43439d0..61ea4d39970 100644 --- a/chromium/cc/surfaces/display_client.h +++ b/chromium/cc/surfaces/display_client.h @@ -14,9 +14,6 @@ struct ManagedMemoryPolicy; class DisplayClient { public: - virtual void DisplayDamaged() = 0; - virtual void DidSwapBuffers() = 0; - virtual void DidSwapBuffersComplete() = 0; virtual void CommitVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval) = 0; virtual void OutputSurfaceLost() = 0; diff --git a/chromium/cc/surfaces/display_scheduler.cc b/chromium/cc/surfaces/display_scheduler.cc new file mode 100644 index 00000000000..3810e148864 --- /dev/null +++ b/chromium/cc/surfaces/display_scheduler.cc @@ -0,0 +1,286 @@ +// Copyright 2015 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/surfaces/display_scheduler.h" + +#include <vector> + +#include "base/stl_util.h" +#include "base/trace_event/trace_event.h" +#include "cc/output/output_surface.h" + +namespace cc { + +DisplayScheduler::DisplayScheduler(DisplaySchedulerClient* client, + BeginFrameSource* begin_frame_source, + base::SingleThreadTaskRunner* task_runner, + int max_pending_swaps) + : client_(client), + begin_frame_source_(begin_frame_source), + task_runner_(task_runner), + output_surface_lost_(false), + root_surface_resources_locked_(true), + inside_begin_frame_deadline_interval_(false), + needs_draw_(false), + entire_display_damaged_(false), + all_active_child_surfaces_ready_to_draw_(false), + pending_swaps_(0), + max_pending_swaps_(max_pending_swaps), + root_surface_damaged_(false), + expect_damage_from_root_surface_(false), + weak_ptr_factory_(this) { + begin_frame_source_->AddObserver(this); + begin_frame_deadline_closure_ = base::Bind( + &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); +} + +DisplayScheduler::~DisplayScheduler() { + begin_frame_source_->RemoveObserver(this); +} + +// If we try to draw when the root surface resources are locked, the +// draw will fail. +void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) { + root_surface_resources_locked_ = locked; + ScheduleBeginFrameDeadline(); +} + +// This is used to force an immediate swap before a resize. +void DisplayScheduler::ForceImmediateSwapIfPossible() { + bool in_begin = inside_begin_frame_deadline_interval_; + AttemptDrawAndSwap(); + if (in_begin) + begin_frame_source_->DidFinishFrame(0); +} + +// Notification that there was a resize or the root surface changed and +// that we should just draw immediately. +void DisplayScheduler::EntireDisplayDamaged(SurfaceId root_surface_id) { + TRACE_EVENT0("cc", "DisplayScheduler::EntireDisplayDamaged"); + needs_draw_ = true; + entire_display_damaged_ = true; + root_surface_id_ = root_surface_id; + + begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_); + ScheduleBeginFrameDeadline(); +} + +// Indicates that there was damage to one of the surfaces. +// Has some logic to wait for multiple active surfaces before +// triggering the deadline. +void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) { + TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", + surface_id.id); + + needs_draw_ = true; + + if (surface_id == root_surface_id_) { + root_surface_damaged_ = true; + } else { + child_surface_ids_damaged_.insert(surface_id); + + // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. + all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( + child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_); + } + + begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_); + ScheduleBeginFrameDeadline(); +} + +void DisplayScheduler::OutputSurfaceLost() { + TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); + output_surface_lost_ = true; + begin_frame_source_->SetNeedsBeginFrames(false); + ScheduleBeginFrameDeadline(); +} + +void DisplayScheduler::DrawAndSwap() { + TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap"); + DCHECK_LT(pending_swaps_, max_pending_swaps_); + DCHECK(!output_surface_lost_); + + bool success = client_->DrawAndSwap(); + if (!success) + return; + + child_surface_ids_to_expect_damage_from_ = + base::STLSetIntersection<std::vector<SurfaceId>>( + child_surface_ids_damaged_, child_surface_ids_damaged_prev_); + + child_surface_ids_damaged_prev_.swap(child_surface_ids_damaged_); + child_surface_ids_damaged_.clear(); + + needs_draw_ = false; + entire_display_damaged_ = false; + all_active_child_surfaces_ready_to_draw_ = + child_surface_ids_to_expect_damage_from_.empty(); + + expect_damage_from_root_surface_ = root_surface_damaged_; + root_surface_damaged_ = false; +} + +bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { + base::TimeTicks now = base::TimeTicks::Now(); + TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), + "now", now); + + // If we get another BeginFrame before the previous deadline, + // synchronously trigger the previous deadline before progressing. + if (inside_begin_frame_deadline_interval_) { + OnBeginFrameDeadline(); + } + + // Schedule the deadline. + current_begin_frame_args_ = args; + current_begin_frame_args_.deadline -= + BeginFrameArgs::DefaultEstimatedParentDrawTime(); + inside_begin_frame_deadline_interval_ = true; + ScheduleBeginFrameDeadline(); + + return true; +} + +base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() { + if (output_surface_lost_) { + TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD); + return base::TimeTicks(); + } + + if (pending_swaps_ >= max_pending_swaps_) { + TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD); + return current_begin_frame_args_.deadline; + } + + if (!needs_draw_) { + TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD); + return current_begin_frame_args_.frame_time + + current_begin_frame_args_.interval; + } + + if (root_surface_resources_locked_) { + TRACE_EVENT_INSTANT0("cc", "Root surface resources locked", + TRACE_EVENT_SCOPE_THREAD); + return current_begin_frame_args_.frame_time + + current_begin_frame_args_.interval; + } + + // TODO(mithro): Be smarter about resize deadlines. + if (entire_display_damaged_) { + TRACE_EVENT_INSTANT0("cc", "Entire display damaged", + TRACE_EVENT_SCOPE_THREAD); + return base::TimeTicks(); + } + + bool root_ready_to_draw = + !expect_damage_from_root_surface_ || root_surface_damaged_; + + if (all_active_child_surfaces_ready_to_draw_ && root_ready_to_draw) { + TRACE_EVENT_INSTANT0("cc", "All active surfaces ready", + TRACE_EVENT_SCOPE_THREAD); + return base::TimeTicks(); + } + + // Use an earlier deadline if we are only waiting for the root surface + // in case our expect_damage_from_root_surface heuristic is incorrect. + // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort + // logic. + if (all_active_child_surfaces_ready_to_draw_ && + expect_damage_from_root_surface_) { + TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface", + TRACE_EVENT_SCOPE_THREAD); + // This adjusts the deadline by DefaultEstimatedParentDrawTime for + // a second time. The first one represented the Surfaces draw to display + // latency. This one represents root surface commit+raster+draw latency. + // We treat the root surface differently since it lives on the same thread + // as Surfaces and waiting for it too long may push out the Surfaces draw. + // If we also assume the root surface is fast to start a commit after the + // beginning of a frame, it'll have a chance to lock its resources, which + // will cause us to wait for it to unlock its resources above. + // TODO(mithro): Replace hard coded estimates. + return current_begin_frame_args_.deadline - + BeginFrameArgs::DefaultEstimatedParentDrawTime(); + } + + TRACE_EVENT_INSTANT0("cc", "More damage expected soon", + TRACE_EVENT_SCOPE_THREAD); + return current_begin_frame_args_.deadline; +} + +void DisplayScheduler::ScheduleBeginFrameDeadline() { + TRACE_EVENT0("cc", "DisplayScheduler::ScheduleBeginFrameDeadline"); + + // We need to wait for the next BeginFrame before scheduling a deadline. + if (!inside_begin_frame_deadline_interval_) { + TRACE_EVENT_INSTANT0("cc", "Waiting for next BeginFrame", + TRACE_EVENT_SCOPE_THREAD); + DCHECK(begin_frame_deadline_task_.IsCancelled()); + return; + } + + // Determine the deadline we want to use. + base::TimeTicks desired_deadline = DesiredBeginFrameDeadlineTime(); + + // Avoid re-scheduling the deadline if it's already correctly scheduled. + if (!begin_frame_deadline_task_.IsCancelled() && + desired_deadline == begin_frame_deadline_task_time_) { + TRACE_EVENT_INSTANT0("cc", "Using existing deadline", + TRACE_EVENT_SCOPE_THREAD); + return; + } + + // Schedule the deadline. + begin_frame_deadline_task_time_ = desired_deadline; + begin_frame_deadline_task_.Cancel(); + begin_frame_deadline_task_.Reset(begin_frame_deadline_closure_); + + base::TimeDelta delta = + std::max(base::TimeDelta(), desired_deadline - base::TimeTicks::Now()); + task_runner_->PostDelayedTask(FROM_HERE, + begin_frame_deadline_task_.callback(), delta); + TRACE_EVENT2("cc", "Using new deadline", "delta", delta.ToInternalValue(), + "desired_deadline", desired_deadline); +} + +void DisplayScheduler::AttemptDrawAndSwap() { + inside_begin_frame_deadline_interval_ = false; + begin_frame_deadline_task_.Cancel(); + begin_frame_deadline_task_time_ = base::TimeTicks(); + + if (needs_draw_ && !output_surface_lost_) { + if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_) + DrawAndSwap(); + } else { + // We are going idle, so reset expectations. + child_surface_ids_to_expect_damage_from_.clear(); + child_surface_ids_damaged_prev_.clear(); + child_surface_ids_damaged_.clear(); + all_active_child_surfaces_ready_to_draw_ = true; + expect_damage_from_root_surface_ = false; + + begin_frame_source_->SetNeedsBeginFrames(false); + } +} + +void DisplayScheduler::OnBeginFrameDeadline() { + TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); + + AttemptDrawAndSwap(); + begin_frame_source_->DidFinishFrame(0); +} + +void DisplayScheduler::DidSwapBuffers() { + pending_swaps_++; + TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffers", "pending_frames", + pending_swaps_); +} + +void DisplayScheduler::DidSwapBuffersComplete() { + pending_swaps_--; + TRACE_EVENT1("cc", "DisplayScheduler::DidSwapBuffersComplete", + "pending_frames", pending_swaps_); + ScheduleBeginFrameDeadline(); +} + +} // namespace cc diff --git a/chromium/cc/surfaces/display_scheduler.h b/chromium/cc/surfaces/display_scheduler.h new file mode 100644 index 00000000000..bc509c7b1ca --- /dev/null +++ b/chromium/cc/surfaces/display_scheduler.h @@ -0,0 +1,93 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_SURFACES_DISPLAY_SCHEDULER_H_ +#define CC_SURFACES_DISPLAY_SCHEDULER_H_ + +#include "base/cancelable_callback.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/single_thread_task_runner.h" +#include "cc/scheduler/begin_frame_source.h" +#include "cc/surfaces/surface_id.h" +#include "cc/surfaces/surfaces_export.h" + +namespace cc { + +class OutputSurface; +class BeginFrameSource; + +// TODO(brianderson): Reconcile with SurfacesScheduler crbug.com/476676 +class CC_SURFACES_EXPORT DisplaySchedulerClient { + public: + virtual ~DisplaySchedulerClient() {} + + virtual bool DrawAndSwap() = 0; +}; + +class CC_SURFACES_EXPORT DisplayScheduler : public BeginFrameObserverBase { + public: + DisplayScheduler(DisplaySchedulerClient* client, + BeginFrameSource* begin_frame_source, + base::SingleThreadTaskRunner* task_runner, + int max_pending_swaps); + ~DisplayScheduler() override; + + void SetRootSurfaceResourcesLocked(bool locked); + void ForceImmediateSwapIfPossible(); + virtual void EntireDisplayDamaged(SurfaceId root_surface_id); + virtual void SurfaceDamaged(SurfaceId surface_id); + + virtual void DidSwapBuffers(); + void DidSwapBuffersComplete(); + + void OutputSurfaceLost(); + + // BeginFrameObserverBase implementation + bool OnBeginFrameDerivedImpl(const BeginFrameArgs& args) override; + + protected: + base::TimeTicks DesiredBeginFrameDeadlineTime(); + virtual void ScheduleBeginFrameDeadline(); + void AttemptDrawAndSwap(); + void OnBeginFrameDeadline(); + void DrawAndSwap(); + + DisplaySchedulerClient* client_; + BeginFrameSource* begin_frame_source_; + base::SingleThreadTaskRunner* task_runner_; + + BeginFrameArgs current_begin_frame_args_; + base::Closure begin_frame_deadline_closure_; + base::CancelableClosure begin_frame_deadline_task_; + base::TimeTicks begin_frame_deadline_task_time_; + + bool output_surface_lost_; + bool root_surface_resources_locked_; + + bool inside_begin_frame_deadline_interval_; + bool needs_draw_; + bool entire_display_damaged_; + bool all_active_child_surfaces_ready_to_draw_; + + int pending_swaps_; + int max_pending_swaps_; + + SurfaceId root_surface_id_; + bool root_surface_damaged_; + bool expect_damage_from_root_surface_; + + std::set<SurfaceId> child_surface_ids_damaged_; + std::set<SurfaceId> child_surface_ids_damaged_prev_; + std::vector<SurfaceId> child_surface_ids_to_expect_damage_from_; + + base::WeakPtrFactory<DisplayScheduler> weak_ptr_factory_; + + private: + DISALLOW_COPY_AND_ASSIGN(DisplayScheduler); +}; + +} // namespace cc + +#endif // CC_SURFACES_DISPLAY_SCHEDULER_H_ diff --git a/chromium/cc/surfaces/display_scheduler_unittest.cc b/chromium/cc/surfaces/display_scheduler_unittest.cc new file mode 100644 index 00000000000..43a0c9a5cba --- /dev/null +++ b/chromium/cc/surfaces/display_scheduler_unittest.cc @@ -0,0 +1,347 @@ +// Copyright 2015 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/surfaces/display_scheduler.h" + +#include "base/logging.h" +#include "base/test/null_task_runner.h" +#include "base/test/simple_test_tick_clock.h" +#include "base/trace_event/trace_event.h" +#include "cc/output/begin_frame_args.h" +#include "cc/surfaces/display.h" +#include "cc/test/scheduler_test_common.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +const int kMaxPendingSwaps = 1; + +class FakeDisplaySchedulerClient : public DisplaySchedulerClient { + public: + FakeDisplaySchedulerClient() : draw_and_swap_count_(0) {} + + ~FakeDisplaySchedulerClient() override {} + + bool DrawAndSwap() override { + draw_and_swap_count_++; + return true; + } + + void Reset() { draw_and_swap_count_ = 0; } + + int draw_and_swap_count() const { return draw_and_swap_count_; } + + protected: + int draw_and_swap_count_; +}; + +class TestDisplayScheduler : public DisplayScheduler { + public: + TestDisplayScheduler(DisplaySchedulerClient* client, + BeginFrameSource* begin_frame_source, + base::SingleThreadTaskRunner* task_runner, + int max_pending_swaps) + : DisplayScheduler(client, + begin_frame_source, + task_runner, + max_pending_swaps), + scheduler_begin_frame_deadline_count_(0) {} + + base::TimeTicks DesiredBeginFrameDeadlineTimeForTest() { + return DesiredBeginFrameDeadlineTime(); + } + + void BeginFrameDeadlineForTest() { OnBeginFrameDeadline(); } + + void ScheduleBeginFrameDeadline() override { + scheduler_begin_frame_deadline_count_++; + DisplayScheduler::ScheduleBeginFrameDeadline(); + } + + int scheduler_begin_frame_deadline_count() { + return scheduler_begin_frame_deadline_count_; + } + + protected: + int scheduler_begin_frame_deadline_count_; +}; + +class DisplaySchedulerTest : public testing::Test { + public: + DisplaySchedulerTest() + : now_src_(new base::SimpleTestTickClock()), + task_runner_(new base::NullTaskRunner), + client_(new FakeDisplaySchedulerClient), + scheduler_(new TestDisplayScheduler(client_.get(), + &fake_begin_frame_source_, + task_runner_.get(), + kMaxPendingSwaps)) { + now_src_->Advance(base::TimeDelta::FromMicroseconds(10000)); + } + + ~DisplaySchedulerTest() override {} + + void SetUp() override { scheduler_->SetRootSurfaceResourcesLocked(false); } + + void BeginFrameForTest() { + base::TimeTicks frame_time = now_src_->NowTicks(); + base::TimeDelta interval = BeginFrameArgs::DefaultInterval(); + base::TimeTicks deadline = frame_time + interval; + fake_begin_frame_source_.TestOnBeginFrame( + BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline, + interval, BeginFrameArgs::NORMAL)); + } + + protected: + base::SimpleTestTickClock& now_src() { return *now_src_; } + FakeDisplaySchedulerClient& client() { return *client_; } + DisplayScheduler& scheduler() { return *scheduler_; } + + FakeBeginFrameSource fake_begin_frame_source_; + + scoped_ptr<base::SimpleTestTickClock> now_src_; + scoped_refptr<base::NullTaskRunner> task_runner_; + scoped_ptr<FakeDisplaySchedulerClient> client_; + scoped_ptr<TestDisplayScheduler> scheduler_; +}; + +TEST_F(DisplaySchedulerTest, EntireDisplayDamagedDrawsImmediately) { + SurfaceId root_surface_id(1); + BeginFrameForTest(); + EXPECT_LT(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->EntireDisplayDamaged(root_surface_id); + EXPECT_GE(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); +} + +TEST_F(DisplaySchedulerTest, SurfaceDamaged) { + SurfaceId root_surface_id(0); + SurfaceId sid1(1); + SurfaceId sid2(2); + + // Set the root surface + scheduler_->EntireDisplayDamaged(root_surface_id); + + // Get scheduler to detect surface 1 as active by drawing + // two frames in a row with damage from surface 1. + BeginFrameForTest(); + scheduler_->SurfaceDamaged(sid1); + scheduler_->BeginFrameDeadlineForTest(); + BeginFrameForTest(); + scheduler_->SurfaceDamaged(sid1); + scheduler_->BeginFrameDeadlineForTest(); + + // Damage only from surface 2 (inactive) does not trigger deadline early. + BeginFrameForTest(); + scheduler_->SurfaceDamaged(sid2); + EXPECT_LT(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + + // Damage from surface 1 triggers deadline early. + scheduler_->SurfaceDamaged(sid1); + EXPECT_GE(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->BeginFrameDeadlineForTest(); + + // Make both surface 1 and 2 active. + BeginFrameForTest(); + scheduler_->SurfaceDamaged(sid2); + scheduler_->SurfaceDamaged(sid1); + scheduler_->BeginFrameDeadlineForTest(); + + // Deadline doesn't trigger early until surface 1 and 2 are both damaged. + BeginFrameForTest(); + EXPECT_LT(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->SurfaceDamaged(sid1); + EXPECT_LT(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->SurfaceDamaged(sid2); + EXPECT_GE(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->BeginFrameDeadlineForTest(); + + // Make the system idle + BeginFrameForTest(); + scheduler_->BeginFrameDeadlineForTest(); + BeginFrameForTest(); + scheduler_->BeginFrameDeadlineForTest(); + + // Deadline should trigger early if child surfaces are idle and + // we get damage on the root surface. + BeginFrameForTest(); + EXPECT_LT(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->SurfaceDamaged(root_surface_id); + EXPECT_GE(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->BeginFrameDeadlineForTest(); +} + +TEST_F(DisplaySchedulerTest, OutputSurfaceLost) { + SurfaceId sid1(1); + + // DrawAndSwap normally. + BeginFrameForTest(); + EXPECT_LT(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + EXPECT_EQ(0, client_->draw_and_swap_count()); + scheduler_->SurfaceDamaged(sid1); + scheduler_->BeginFrameDeadlineForTest(); + EXPECT_EQ(1, client_->draw_and_swap_count()); + + // Deadline triggers immediately on OutputSurfaceLost. + BeginFrameForTest(); + EXPECT_LT(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->OutputSurfaceLost(); + EXPECT_GE(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + + // Deadline does not DrawAndSwap after OutputSurfaceLost. + EXPECT_EQ(1, client_->draw_and_swap_count()); + scheduler_->SurfaceDamaged(sid1); + scheduler_->BeginFrameDeadlineForTest(); + EXPECT_EQ(1, client_->draw_and_swap_count()); +} + +TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) { + SurfaceId sid1(1); + base::TimeTicks late_deadline; + + // DrawAndSwap normally. + BeginFrameForTest(); + EXPECT_LT(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + EXPECT_EQ(0, client_->draw_and_swap_count()); + scheduler_->SurfaceDamaged(sid1); + scheduler_->BeginFrameDeadlineForTest(); + EXPECT_EQ(1, client_->draw_and_swap_count()); + + // Deadline triggers late while root resources are locked. + late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval(); + BeginFrameForTest(); + scheduler_->SurfaceDamaged(sid1); + EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->SetRootSurfaceResourcesLocked(true); + EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + + // Deadline does not DrawAndSwap while root resources are locked. + EXPECT_EQ(1, client_->draw_and_swap_count()); + scheduler_->SurfaceDamaged(sid1); + scheduler_->BeginFrameDeadlineForTest(); + EXPECT_EQ(1, client_->draw_and_swap_count()); + + // Deadline triggers normally when root resources are unlocked. + late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval(); + BeginFrameForTest(); + scheduler_->SurfaceDamaged(sid1); + EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + scheduler_->SetRootSurfaceResourcesLocked(false); + EXPECT_EQ(base::TimeTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + + EXPECT_EQ(1, client_->draw_and_swap_count()); + scheduler_->BeginFrameDeadlineForTest(); + EXPECT_EQ(2, client_->draw_and_swap_count()); +} + +TEST_F(DisplaySchedulerTest, DidSwapBuffers) { + SurfaceId sid1(1); + SurfaceId sid2(2); + base::TimeTicks expected_deadline; + + // Get scheduler to detect surface 1 and 2 as active. + BeginFrameForTest(); + scheduler_->SurfaceDamaged(sid1); + scheduler_->SurfaceDamaged(sid2); + scheduler_->BeginFrameDeadlineForTest(); + BeginFrameForTest(); + scheduler_->SurfaceDamaged(sid1); + scheduler_->SurfaceDamaged(sid2); + scheduler_->BeginFrameDeadlineForTest(); + + // DrawAndSwap normally. + BeginFrameForTest(); + EXPECT_LT(now_src().NowTicks(), + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + EXPECT_EQ(2, client_->draw_and_swap_count()); + scheduler_->SurfaceDamaged(sid1); + scheduler_->SurfaceDamaged(sid2); + scheduler_->BeginFrameDeadlineForTest(); + EXPECT_EQ(3, client_->draw_and_swap_count()); + scheduler_->DidSwapBuffers(); + + // Deadline triggers normally when swap throttled. + expected_deadline = + fake_begin_frame_source_.TestLastUsedBeginFrameArgs().deadline - + BeginFrameArgs::DefaultEstimatedParentDrawTime(); + BeginFrameForTest(); + // Damage surface 1, but not surface 2 so we avoid triggering deadline + // early because all surfaces are ready. + scheduler_->SurfaceDamaged(sid1); + EXPECT_EQ(expected_deadline, + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + + // Don't draw and swap in deadline while swap throttled. + EXPECT_EQ(3, client_->draw_and_swap_count()); + scheduler_->BeginFrameDeadlineForTest(); + EXPECT_EQ(3, client_->draw_and_swap_count()); + + // Deadline triggers normally once not swap throttled. + // Damage from previous BeginFrame should cary over, so don't damage again. + expected_deadline = + fake_begin_frame_source_.TestLastUsedBeginFrameArgs().deadline - + BeginFrameArgs::DefaultEstimatedParentDrawTime(); + scheduler_->DidSwapBuffersComplete(); + BeginFrameForTest(); + EXPECT_EQ(expected_deadline, + scheduler_->DesiredBeginFrameDeadlineTimeForTest()); + // Still waiting for surface 2. Once it updates, deadline should trigger + // immediately again. + scheduler_->SurfaceDamaged(sid2); + EXPECT_EQ(scheduler_->DesiredBeginFrameDeadlineTimeForTest(), + base::TimeTicks()); + // Draw and swap now that we aren't throttled. + EXPECT_EQ(3, client_->draw_and_swap_count()); + scheduler_->BeginFrameDeadlineForTest(); + EXPECT_EQ(4, client_->draw_and_swap_count()); +} + +// This test verfies that we try to reschedule the deadline +// after any event that may change what deadline we want. +TEST_F(DisplaySchedulerTest, ScheduleBeginFrameDeadline) { + SurfaceId root_surface_id(1); + SurfaceId sid1(2); + int count = 1; + EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); + + BeginFrameForTest(); + EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); + + scheduler_->BeginFrameDeadlineForTest(); + scheduler_->DidSwapBuffers(); + BeginFrameForTest(); + EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); + + scheduler_->DidSwapBuffersComplete(); + EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); + + scheduler_->EntireDisplayDamaged(root_surface_id); + EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); + + scheduler_->SurfaceDamaged(sid1); + EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); + + scheduler_->SetRootSurfaceResourcesLocked(true); + EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); + + scheduler_->OutputSurfaceLost(); + EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/surfaces/display_unittest.cc b/chromium/cc/surfaces/display_unittest.cc index 7b012440907..93ff0f85af1 100644 --- a/chromium/cc/surfaces/display_unittest.cc +++ b/chromium/cc/surfaces/display_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/test/null_task_runner.h" #include "cc/output/compositor_frame.h" #include "cc/output/copy_output_result.h" #include "cc/output/delegated_frame_data.h" @@ -15,10 +16,13 @@ #include "cc/surfaces/surface_id_allocator.h" #include "cc/surfaces/surface_manager.h" #include "cc/test/fake_output_surface.h" +#include "cc/test/scheduler_test_common.h" #include "cc/test/test_shared_bitmap_manager.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::AnyNumber; + namespace cc { namespace { @@ -29,16 +33,23 @@ class EmptySurfaceFactoryClient : public SurfaceFactoryClient { class DisplayTest : public testing::Test { public: - DisplayTest() : factory_(&manager_, &empty_client_) {} + DisplayTest() + : factory_(&manager_, &empty_client_), + task_runner_(new base::NullTaskRunner) {} - void SetUp() override { - output_surface_ = FakeOutputSurface::CreateSoftware( - make_scoped_ptr(new SoftwareOutputDevice)); + protected: + void SetUpContext(scoped_ptr<TestWebGraphicsContext3D> context) { + if (context) { + output_surface_ = FakeOutputSurface::Create3d( + TestContextProvider::Create(context.Pass())); + } else { + output_surface_ = FakeOutputSurface::CreateSoftware( + make_scoped_ptr(new SoftwareOutputDevice)); + } shared_bitmap_manager_.reset(new TestSharedBitmapManager); output_surface_ptr_ = output_surface_.get(); } - protected: void SubmitFrame(RenderPassList* pass_list, SurfaceId surface_id) { scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); pass_list->swap(frame_data->render_pass_list); @@ -55,23 +66,52 @@ class DisplayTest : public testing::Test { SurfaceFactory factory_; scoped_ptr<FakeOutputSurface> output_surface_; FakeOutputSurface* output_surface_ptr_; + FakeBeginFrameSource fake_begin_frame_source_; + scoped_refptr<base::NullTaskRunner> task_runner_; scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; }; class TestDisplayClient : public DisplayClient { public: - TestDisplayClient() : damaged(false), swapped(false) {} + TestDisplayClient() {} ~TestDisplayClient() override {} - void DisplayDamaged() override { damaged = true; } - void DidSwapBuffers() override { swapped = true; } - void DidSwapBuffersComplete() override {} void CommitVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval) override {} void OutputSurfaceLost() override {} void SetMemoryPolicy(const ManagedMemoryPolicy& policy) override {} +}; + +class TestDisplayScheduler : public DisplayScheduler { + public: + TestDisplayScheduler(DisplaySchedulerClient* client, + BeginFrameSource* begin_frame_source, + base::NullTaskRunner* task_runner) + : DisplayScheduler(client, begin_frame_source, task_runner, 1), + damaged(false), + entire_display_damaged(false), + swapped(false) {} + + ~TestDisplayScheduler() override {} + + void EntireDisplayDamaged(SurfaceId root_surface_id) override { + entire_display_damaged = true; + } + + void SurfaceDamaged(SurfaceId surface_id) override { + damaged = true; + needs_draw_ = true; + } + + void DidSwapBuffers() override { swapped = true; } + + void ResetDamageForTest() { + damaged = false; + entire_display_damaged = false; + } bool damaged; + bool entire_display_damaged; bool swapped; }; @@ -81,22 +121,29 @@ void CopyCallback(bool* called, scoped_ptr<CopyOutputResult> result) { // Check that frame is damaged and swapped only under correct conditions. TEST_F(DisplayTest, DisplayDamaged) { + SetUpContext(nullptr); TestDisplayClient client; RendererSettings settings; settings.partial_swap_enabled = true; + settings.finish_rendering_on_resize = true; Display display(&client, &manager_, shared_bitmap_manager_.get(), nullptr, settings); - display.Initialize(output_surface_.Pass()); + TestDisplayScheduler scheduler(&display, &fake_begin_frame_source_, + task_runner_.get()); + display.Initialize(output_surface_.Pass(), &scheduler); SurfaceId surface_id(7u); - EXPECT_FALSE(client.damaged); + EXPECT_FALSE(scheduler.damaged); + EXPECT_FALSE(scheduler.entire_display_damaged); display.SetSurfaceId(surface_id, 1.f); - EXPECT_TRUE(client.damaged); + EXPECT_FALSE(scheduler.damaged); + EXPECT_TRUE(scheduler.entire_display_damaged); - client.damaged = false; + scheduler.ResetDamageForTest(); display.Resize(gfx::Size(100, 100)); - EXPECT_TRUE(client.damaged); + EXPECT_FALSE(scheduler.damaged); + EXPECT_TRUE(scheduler.entire_display_damaged); factory_.Create(surface_id); @@ -108,14 +155,15 @@ TEST_F(DisplayTest, DisplayDamaged) { pass->id = RenderPassId(1, 1); pass_list.push_back(pass.Pass()); - client.damaged = false; + scheduler.ResetDamageForTest(); SubmitFrame(&pass_list, surface_id); - EXPECT_TRUE(client.damaged); + EXPECT_TRUE(scheduler.damaged); + EXPECT_FALSE(scheduler.entire_display_damaged); - EXPECT_FALSE(client.swapped); + EXPECT_FALSE(scheduler.swapped); EXPECT_EQ(0u, output_surface_ptr_->num_sent_frames()); - display.Draw(); - EXPECT_TRUE(client.swapped); + display.DrawAndSwap(); + EXPECT_TRUE(scheduler.swapped); EXPECT_EQ(1u, output_surface_ptr_->num_sent_frames()); SoftwareFrameData* software_data = output_surface_ptr_->last_sent_frame().software_frame_data.get(); @@ -132,13 +180,14 @@ TEST_F(DisplayTest, DisplayDamaged) { pass->id = RenderPassId(1, 1); pass_list.push_back(pass.Pass()); - client.damaged = false; + scheduler.ResetDamageForTest(); SubmitFrame(&pass_list, surface_id); - EXPECT_TRUE(client.damaged); + EXPECT_TRUE(scheduler.damaged); + EXPECT_FALSE(scheduler.entire_display_damaged); - client.swapped = false; - display.Draw(); - EXPECT_TRUE(client.swapped); + scheduler.swapped = false; + display.DrawAndSwap(); + EXPECT_TRUE(scheduler.swapped); EXPECT_EQ(2u, output_surface_ptr_->num_sent_frames()); software_data = output_surface_ptr_->last_sent_frame().software_frame_data.get(); @@ -156,13 +205,14 @@ TEST_F(DisplayTest, DisplayDamaged) { pass->id = RenderPassId(1, 1); pass_list.push_back(pass.Pass()); - client.damaged = false; + scheduler.ResetDamageForTest(); SubmitFrame(&pass_list, surface_id); - EXPECT_TRUE(client.damaged); + EXPECT_TRUE(scheduler.damaged); + EXPECT_FALSE(scheduler.entire_display_damaged); - client.swapped = false; - display.Draw(); - EXPECT_TRUE(client.swapped); + scheduler.swapped = false; + display.DrawAndSwap(); + EXPECT_TRUE(scheduler.swapped); EXPECT_EQ(2u, output_surface_ptr_->num_sent_frames()); } @@ -174,13 +224,14 @@ TEST_F(DisplayTest, DisplayDamaged) { pass->id = RenderPassId(1, 1); pass_list.push_back(pass.Pass()); - client.damaged = false; + scheduler.ResetDamageForTest(); SubmitFrame(&pass_list, surface_id); - EXPECT_TRUE(client.damaged); + EXPECT_TRUE(scheduler.damaged); + EXPECT_FALSE(scheduler.entire_display_damaged); - client.swapped = false; - display.Draw(); - EXPECT_TRUE(client.swapped); + scheduler.swapped = false; + display.DrawAndSwap(); + EXPECT_TRUE(scheduler.swapped); EXPECT_EQ(2u, output_surface_ptr_->num_sent_frames()); } @@ -195,13 +246,14 @@ TEST_F(DisplayTest, DisplayDamaged) { pass->id = RenderPassId(1, 1); pass_list.push_back(pass.Pass()); - client.damaged = false; + scheduler.ResetDamageForTest(); SubmitFrame(&pass_list, surface_id); - EXPECT_TRUE(client.damaged); + EXPECT_TRUE(scheduler.damaged); + EXPECT_FALSE(scheduler.entire_display_damaged); - client.swapped = false; - display.Draw(); - EXPECT_TRUE(client.swapped); + scheduler.swapped = false; + display.DrawAndSwap(); + EXPECT_TRUE(scheduler.swapped); EXPECT_EQ(3u, output_surface_ptr_->num_sent_frames()); EXPECT_TRUE(copy_called); } @@ -214,7 +266,7 @@ TEST_F(DisplayTest, DisplayDamaged) { pass->id = RenderPassId(1, 1); pass_list.push_back(pass.Pass()); - client.damaged = false; + scheduler.ResetDamageForTest(); scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); pass_list.swap(frame_data->render_pass_list); @@ -224,14 +276,122 @@ TEST_F(DisplayTest, DisplayDamaged) { factory_.SubmitFrame(surface_id, frame.Pass(), SurfaceFactory::DrawCallback()); - EXPECT_TRUE(client.damaged); + EXPECT_TRUE(scheduler.damaged); + EXPECT_FALSE(scheduler.entire_display_damaged); - client.swapped = false; - display.Draw(); - EXPECT_TRUE(client.swapped); + scheduler.swapped = false; + display.DrawAndSwap(); + EXPECT_TRUE(scheduler.swapped); EXPECT_EQ(4u, output_surface_ptr_->num_sent_frames()); } + // Resize should cause a swap if no frame was swapped at the previous size. + { + scheduler.swapped = false; + display.Resize(gfx::Size(200, 200)); + EXPECT_FALSE(scheduler.swapped); + EXPECT_EQ(4u, output_surface_ptr_->num_sent_frames()); + + pass = RenderPass::Create(); + pass->output_rect = gfx::Rect(0, 0, 200, 200); + pass->damage_rect = gfx::Rect(10, 10, 10, 10); + pass->id = RenderPassId(1, 1); + + pass_list.push_back(pass.Pass()); + scheduler.ResetDamageForTest(); + scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); + pass_list.swap(frame_data->render_pass_list); + + scoped_ptr<CompositorFrame> frame(new CompositorFrame); + frame->delegated_frame_data = frame_data.Pass(); + + factory_.SubmitFrame(surface_id, frame.Pass(), + SurfaceFactory::DrawCallback()); + EXPECT_TRUE(scheduler.damaged); + EXPECT_FALSE(scheduler.entire_display_damaged); + + scheduler.swapped = false; + display.Resize(gfx::Size(100, 100)); + EXPECT_TRUE(scheduler.swapped); + EXPECT_EQ(5u, output_surface_ptr_->num_sent_frames()); + } + + factory_.Destroy(surface_id); +} + +class MockedContext : public TestWebGraphicsContext3D { + public: + MOCK_METHOD0(shallowFinishCHROMIUM, void()); +}; + +TEST_F(DisplayTest, Finish) { + scoped_ptr<MockedContext> context(new MockedContext()); + MockedContext* context_ptr = context.get(); + SetUpContext(context.Pass()); + + EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0); + TestDisplayClient client; + RendererSettings settings; + settings.partial_swap_enabled = true; + settings.finish_rendering_on_resize = true; + Display display(&client, &manager_, shared_bitmap_manager_.get(), nullptr, + settings); + + TestDisplayScheduler scheduler(&display, &fake_begin_frame_source_, + task_runner_.get()); + display.Initialize(output_surface_.Pass(), &scheduler); + + SurfaceId surface_id(7u); + display.SetSurfaceId(surface_id, 1.f); + + display.Resize(gfx::Size(100, 100)); + factory_.Create(surface_id); + + { + RenderPassList pass_list; + scoped_ptr<RenderPass> pass = RenderPass::Create(); + pass->output_rect = gfx::Rect(0, 0, 100, 100); + pass->damage_rect = gfx::Rect(10, 10, 1, 1); + pass->id = RenderPassId(1, 1); + pass_list.push_back(pass.Pass()); + + SubmitFrame(&pass_list, surface_id); + } + + display.DrawAndSwap(); + + // First resize and draw shouldn't finish. + testing::Mock::VerifyAndClearExpectations(context_ptr); + + EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()); + display.Resize(gfx::Size(150, 150)); + testing::Mock::VerifyAndClearExpectations(context_ptr); + + // Another resize without a swap doesn't need to finish. + EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0); + display.Resize(gfx::Size(200, 200)); + testing::Mock::VerifyAndClearExpectations(context_ptr); + + EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0); + { + RenderPassList pass_list; + scoped_ptr<RenderPass> pass = RenderPass::Create(); + pass->output_rect = gfx::Rect(0, 0, 200, 200); + pass->damage_rect = gfx::Rect(10, 10, 1, 1); + pass->id = RenderPassId(1, 1); + pass_list.push_back(pass.Pass()); + + SubmitFrame(&pass_list, surface_id); + } + + display.DrawAndSwap(); + + testing::Mock::VerifyAndClearExpectations(context_ptr); + + EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()); + display.Resize(gfx::Size(250, 250)); + testing::Mock::VerifyAndClearExpectations(context_ptr); + factory_.Destroy(surface_id); } diff --git a/chromium/cc/surfaces/onscreen_display_client.cc b/chromium/cc/surfaces/onscreen_display_client.cc index c9f1f7f4a3e..2bd58fe4ca1 100644 --- a/chromium/cc/surfaces/onscreen_display_client.cc +++ b/chromium/cc/surfaces/onscreen_display_client.cc @@ -6,6 +6,8 @@ #include "base/trace_event/trace_event.h" #include "cc/output/output_surface.h" +#include "cc/scheduler/begin_frame_source.h" +#include "cc/surfaces/display_scheduler.h" #include "cc/surfaces/surface_display_output_surface.h" #include "cc/surfaces/surface_factory.h" #include "cc/surfaces/surface_manager.h" @@ -26,42 +28,46 @@ OnscreenDisplayClient::OnscreenDisplayClient( gpu_memory_buffer_manager, settings)), task_runner_(task_runner), - scheduled_draw_(false), output_surface_lost_(false), - deferred_draw_(false), - pending_frames_(0), - weak_ptr_factory_(this) { + disable_gpu_vsync_(settings.disable_gpu_vsync) { } OnscreenDisplayClient::~OnscreenDisplayClient() { } bool OnscreenDisplayClient::Initialize() { - return display_->Initialize(output_surface_.Pass()); + int max_frames_pending = + output_surface_ ? output_surface_->capabilities().max_frames_pending : 0; + if (max_frames_pending <= 0) + max_frames_pending = OutputSurface::DEFAULT_MAX_FRAMES_PENDING; + + BeginFrameSource* frame_source; + if (disable_gpu_vsync_) { + unthrottled_frame_source_ = + BackToBackBeginFrameSource::Create(task_runner_.get()); + frame_source = unthrottled_frame_source_.get(); + } else { + synthetic_frame_source_ = SyntheticBeginFrameSource::Create( + task_runner_.get(), BeginFrameArgs::DefaultInterval()); + frame_source = synthetic_frame_source_.get(); + } + + scheduler_.reset(new DisplayScheduler( + display_.get(), frame_source, task_runner_.get(), max_frames_pending)); + + return display_->Initialize(output_surface_.Pass(), scheduler_.get()); } void OnscreenDisplayClient::CommitVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval) { - surface_display_output_surface_->ReceivedVSyncParameters(timebase, interval); -} - -void OnscreenDisplayClient::DisplayDamaged() { - if (scheduled_draw_ || deferred_draw_) - return; - TRACE_EVENT0("content", "OnscreenDisplayClient::DisplayDamaged"); - if (pending_frames_ >= display_->GetMaxFramesPending()) { - deferred_draw_ = true; - } else { - ScheduleDraw(); + if (interval == base::TimeDelta()) { + // TODO(brianderson): We should not be receiving 0 intervals. + interval = BeginFrameArgs::DefaultInterval(); } -} -void OnscreenDisplayClient::ScheduleDraw() { - DCHECK(!deferred_draw_); - DCHECK(!scheduled_draw_); - scheduled_draw_ = true; - task_runner_->PostTask(FROM_HERE, base::Bind(&OnscreenDisplayClient::Draw, - weak_ptr_factory_.GetWeakPtr())); + surface_display_output_surface_->ReceivedVSyncParameters(timebase, interval); + if (synthetic_frame_source_.get()) + synthetic_frame_source_->OnUpdateVSyncParameters(timebase, interval); } void OnscreenDisplayClient::OutputSurfaceLost() { @@ -69,26 +75,6 @@ void OnscreenDisplayClient::OutputSurfaceLost() { surface_display_output_surface_->DidLoseOutputSurface(); } -void OnscreenDisplayClient::Draw() { - TRACE_EVENT0("content", "OnscreenDisplayClient::Draw"); - if (output_surface_lost_) - return; - scheduled_draw_ = false; - display_->Draw(); -} - -void OnscreenDisplayClient::DidSwapBuffers() { - pending_frames_++; -} - -void OnscreenDisplayClient::DidSwapBuffersComplete() { - pending_frames_--; - if ((pending_frames_ < display_->GetMaxFramesPending()) && deferred_draw_) { - deferred_draw_ = false; - ScheduleDraw(); - } -} - void OnscreenDisplayClient::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { surface_display_output_surface_->SetMemoryPolicy(policy); } diff --git a/chromium/cc/surfaces/onscreen_display_client.h b/chromium/cc/surfaces/onscreen_display_client.h index c699d99e197..c2f69f1bf2c 100644 --- a/chromium/cc/surfaces/onscreen_display_client.h +++ b/chromium/cc/surfaces/onscreen_display_client.h @@ -14,8 +14,12 @@ #include "cc/surfaces/display.h" #include "cc/surfaces/surfaces_export.h" +class VSyncParameterObserver; + namespace cc { +class BeginFrameSource; class ContextProvider; +class DisplayScheduler; class SurfaceManager; class SurfaceDisplayOutputSurface; @@ -40,9 +44,6 @@ class CC_SURFACES_EXPORT OnscreenDisplayClient } // DisplayClient implementation. - void DisplayDamaged() override; - void DidSwapBuffers() override; - void DidSwapBuffersComplete() override; void CommitVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval) override; void OutputSurfaceLost() override; @@ -50,24 +51,18 @@ class CC_SURFACES_EXPORT OnscreenDisplayClient bool output_surface_lost() { return output_surface_lost_; } - private: - void ScheduleDraw(); - void Draw(); - protected: scoped_ptr<OutputSurface> output_surface_; scoped_ptr<Display> display_; + scoped_ptr<SyntheticBeginFrameSource> synthetic_frame_source_; + scoped_ptr<BackToBackBeginFrameSource> unthrottled_frame_source_; + scoped_ptr<DisplayScheduler> scheduler_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; SurfaceDisplayOutputSurface* surface_display_output_surface_; - bool scheduled_draw_; bool output_surface_lost_; - // True if a draw should be scheduled, but it's hit the limit on max frames - // pending. - bool deferred_draw_; - int pending_frames_; - - base::WeakPtrFactory<OnscreenDisplayClient> weak_ptr_factory_; + bool disable_gpu_vsync_; + private: DISALLOW_COPY_AND_ASSIGN(OnscreenDisplayClient); }; diff --git a/chromium/cc/surfaces/surface.cc b/chromium/cc/surfaces/surface.cc index 97575813f48..16987cb84e4 100644 --- a/chromium/cc/surfaces/surface.cc +++ b/chromium/cc/surfaces/surface.cc @@ -21,8 +21,8 @@ static const int kFrameIndexStart = 2; Surface::Surface(SurfaceId id, SurfaceFactory* factory) : surface_id_(id), factory_(factory->AsWeakPtr()), - frame_index_(kFrameIndexStart) { -} + frame_index_(kFrameIndexStart), + destroyed_(false) {} Surface::~Surface() { ClearCopyRequests(); @@ -60,6 +60,16 @@ void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame, !current_frame_->delegated_frame_data->render_pass_list.empty()) ++frame_index_; + std::vector<SurfaceId> new_referenced_surfaces; + if (current_frame_) { + for (auto& render_pass : + current_frame_->delegated_frame_data->render_pass_list) { + new_referenced_surfaces.insert(new_referenced_surfaces.end(), + render_pass->referenced_surfaces.begin(), + render_pass->referenced_surfaces.end()); + } + } + if (previous_frame) { ReturnedResourceArray previous_resources; TransferableResource::ReturnResources( @@ -71,10 +81,18 @@ void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame, draw_callback_.Run(SurfaceDrawStatus::DRAW_SKIPPED); draw_callback_ = callback; - if (current_frame_) { + bool referenced_surfaces_changed = + (referenced_surfaces_ != new_referenced_surfaces); + referenced_surfaces_ = new_referenced_surfaces; + std::vector<uint32_t> satisfies_sequences; + if (current_frame_) + current_frame_->metadata.satisfies_sequences.swap(satisfies_sequences); + if (referenced_surfaces_changed || !satisfies_sequences.empty()) { + // Notify the manager that sequences were satisfied either if some new + // sequences were satisfied, or if the set of referenced surfaces changed + // to force a GC to happen. factory_->manager()->DidSatisfySequences( - SurfaceIdAllocator::NamespaceForId(surface_id_), - ¤t_frame_->metadata.satisfies_sequences); + SurfaceIdAllocator::NamespaceForId(surface_id_), &satisfies_sequences); } } @@ -134,11 +152,15 @@ void Surface::AddDestructionDependency(SurfaceSequence sequence) { } void Surface::SatisfyDestructionDependencies( - base::hash_set<SurfaceSequence>* sequences) { + base::hash_set<SurfaceSequence>* sequences, + base::hash_set<uint32_t>* valid_id_namespaces) { destruction_dependencies_.erase( - std::remove_if( - destruction_dependencies_.begin(), destruction_dependencies_.end(), - [sequences](SurfaceSequence seq) { return !!sequences->erase(seq); }), + std::remove_if(destruction_dependencies_.begin(), + destruction_dependencies_.end(), + [sequences, valid_id_namespaces](SurfaceSequence seq) { + return (!!sequences->erase(seq) || + !valid_id_namespaces->count(seq.id_namespace)); + }), destruction_dependencies_.end()); } diff --git a/chromium/cc/surfaces/surface.h b/chromium/cc/surfaces/surface.h index 8e6d7a46cbf..d9099f3122b 100644 --- a/chromium/cc/surfaces/surface.h +++ b/chromium/cc/surfaces/surface.h @@ -67,11 +67,19 @@ class CC_SURFACES_EXPORT Surface { // Satisfy all destruction dependencies that are contained in sequences, and // remove them from sequences. void SatisfyDestructionDependencies( - base::hash_set<SurfaceSequence>* sequences); + base::hash_set<SurfaceSequence>* sequences, + base::hash_set<uint32_t>* valid_id_namespaces); size_t GetDestructionDependencyCount() const { return destruction_dependencies_.size(); } + const std::vector<SurfaceId>& referenced_surfaces() const { + return referenced_surfaces_; + } + + bool destroyed() const { return destroyed_; } + void set_destroyed(bool destroyed) { destroyed_ = destroyed; } + private: void ClearCopyRequests(); @@ -80,8 +88,11 @@ class CC_SURFACES_EXPORT Surface { // TODO(jamesr): Support multiple frames in flight. scoped_ptr<CompositorFrame> current_frame_; int frame_index_; + bool destroyed_; std::vector<SurfaceSequence> destruction_dependencies_; + std::vector<SurfaceId> referenced_surfaces_; + DrawCallback draw_callback_; DISALLOW_COPY_AND_ASSIGN(Surface); diff --git a/chromium/cc/surfaces/surface_aggregator.cc b/chromium/cc/surfaces/surface_aggregator.cc index 941e2d89fab..ddfac7670b4 100644 --- a/chromium/cc/surfaces/surface_aggregator.cc +++ b/chromium/cc/surfaces/surface_aggregator.cc @@ -131,72 +131,6 @@ int SurfaceAggregator::ChildIdForSurface(Surface* surface) { } } -static ResourceProvider::ResourceId ResourceRemapHelper( - const ResourceProvider::ResourceIdMap& child_to_parent_map, - ResourceProvider::ResourceId id) { - ResourceProvider::ResourceIdMap::const_iterator it = - child_to_parent_map.find(id); - DCHECK(it != child_to_parent_map.end()); - - DCHECK_EQ(it->first, id); - ResourceProvider::ResourceId remapped_id = it->second; - return remapped_id; -} - -static ResourceProvider::ResourceId ValidateResourceHelper( - bool* invalid_frame, - const ResourceProvider::ResourceIdMap& child_to_parent_map, - ResourceProvider::ResourceIdSet* resources_in_frame, - ResourceProvider::ResourceId id) { - ResourceProvider::ResourceIdMap::const_iterator it = - child_to_parent_map.find(id); - if (it == child_to_parent_map.end()) { - *invalid_frame = true; - return id; - } - resources_in_frame->insert(id); - return id; -} - -bool SurfaceAggregator::ValidateResources( - Surface* surface, - const DelegatedFrameData* frame_data) { - if (!provider_) // TODO(jamesr): hack for unit tests that don't set up rp - return false; - - int child_id = ChildIdForSurface(surface); - if (surface->factory()) - surface->factory()->RefResources(frame_data->resource_list); - provider_->ReceiveFromChild(child_id, frame_data->resource_list); - - ResourceProvider::ResourceIdSet referenced_resources; - size_t reserve_size = frame_data->resource_list.size(); -#if defined(COMPILER_MSVC) - referenced_resources.reserve(reserve_size); -#elif defined(COMPILER_GCC) - // Pre-standard hash-tables only implement resize, which behaves similarly - // to reserve for these keys. Resizing to 0 may also be broken (particularly - // on stlport). - // TODO(jbauman): Replace with reserve when C++11 is supported everywhere. - if (reserve_size) - referenced_resources.resize(reserve_size); -#endif - - bool invalid_frame = false; - DrawQuad::ResourceIteratorCallback remap = - base::Bind(&ValidateResourceHelper, &invalid_frame, - base::ConstRef(provider_->GetChildToParentMap(child_id)), - &referenced_resources); - for (const auto& render_pass : frame_data->render_pass_list) { - for (const auto& quad : render_pass->quad_list) - quad->IterateResources(remap); - } - - if (!invalid_frame) - provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources); - - return invalid_frame; -} gfx::Rect SurfaceAggregator::DamageRectForSurface(const Surface* surface, const RenderPass& source, @@ -236,8 +170,7 @@ void SurfaceAggregator::HandleSurfaceQuad( surface->TakeCopyOutputRequests(©_requests); const RenderPassList& render_pass_list = frame_data->render_pass_list; - bool invalid_frame = ValidateResources(surface, frame_data); - if (invalid_frame) { + if (!valid_surfaces_.count(surface->surface_id())) { for (auto& request : copy_requests) { request.second->SendEmptyResult(); delete request.second; @@ -246,18 +179,15 @@ void SurfaceAggregator::HandleSurfaceQuad( } SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; - DrawQuad::ResourceIteratorCallback remap; - if (provider_) { - int child_id = ChildIdForSurface(surface); - remap = - base::Bind(&ResourceRemapHelper, - base::ConstRef(provider_->GetChildToParentMap(child_id))); - } + // TODO(vmpstr): provider check is a hack for unittests that don't set up a + // resource provider. + ResourceProvider::ResourceIdMap empty_map; + const ResourceProvider::ResourceIdMap& child_to_parent_map = + provider_ ? provider_->GetChildToParentMap(ChildIdForSurface(surface)) + : empty_map; + bool merge_pass = + surface_quad->shared_quad_state->opacity == 1.f && copy_requests.empty(); - bool merge_pass = surface_quad->opacity() == 1.f && copy_requests.empty(); - - gfx::Rect surface_damage = DamageRectForSurface( - surface, *render_pass_list.back(), surface_quad->visible_rect); const RenderPassList& referenced_passes = render_pass_list; size_t passes_to_copy = merge_pass ? referenced_passes.size() - 1 : referenced_passes.size(); @@ -280,41 +210,44 @@ void SurfaceAggregator::HandleSurfaceQuad( // transform of the surface quad into account to update their transform to // the root surface. copy_pass->transform_to_root_target.ConcatTransform( - surface_quad->quadTransform()); + surface_quad->shared_quad_state->quad_to_target_transform); copy_pass->transform_to_root_target.ConcatTransform(target_transform); copy_pass->transform_to_root_target.ConcatTransform( dest_pass->transform_to_root_target); - CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, remap, - gfx::Transform(), ClipData(), copy_pass.get(), surface_id); - - if (j == referenced_passes.size() - 1) - surface_damage = gfx::UnionRects(surface_damage, copy_pass->damage_rect); + CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, + child_to_parent_map, gfx::Transform(), ClipData(), + copy_pass.get(), surface_id); dest_pass_list_->push_back(copy_pass.Pass()); } + gfx::Transform surface_transform = + surface_quad->shared_quad_state->quad_to_target_transform; + surface_transform.ConcatTransform(target_transform); + const RenderPass& last_pass = *render_pass_list.back(); if (merge_pass) { // TODO(jamesr): Clean up last pass special casing. const QuadList& quads = last_pass.quad_list; - gfx::Transform surface_transform = surface_quad->quadTransform(); - surface_transform.ConcatTransform(target_transform); - // Intersect the transformed visible rect and the clip rect to create a // smaller cliprect for the quad. ClipData surface_quad_clip_rect( - true, MathUtil::MapEnclosingClippedRect(surface_quad->quadTransform(), - surface_quad->visible_rect)); - if (surface_quad->isClipped()) - surface_quad_clip_rect.rect.Intersect(surface_quad->clipRect()); + true, MathUtil::MapEnclosingClippedRect( + surface_quad->shared_quad_state->quad_to_target_transform, + surface_quad->visible_rect)); + if (surface_quad->shared_quad_state->is_clipped) { + surface_quad_clip_rect.rect.Intersect( + surface_quad->shared_quad_state->clip_rect); + } ClipData quads_clip = CalculateClipRect(clip_rect, surface_quad_clip_rect, target_transform); - CopyQuadsToPass(quads, last_pass.shared_quad_state_list, remap, - surface_transform, quads_clip, dest_pass, surface_id); + CopyQuadsToPass(quads, last_pass.shared_quad_state_list, + child_to_parent_map, surface_transform, quads_clip, + dest_pass, surface_id); } else { RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id); @@ -336,10 +269,7 @@ void SurfaceAggregator::HandleSurfaceQuad( gfx::Vector2dF(), FilterOperations()); } - dest_pass->damage_rect = - gfx::UnionRects(dest_pass->damage_rect, - MathUtil::MapEnclosingClippedRect( - surface_quad->quadTransform(), surface_damage)); + referenced_surfaces_.erase(it); } @@ -358,7 +288,7 @@ void SurfaceAggregator::CopySharedQuadState( // target space of the pass. This will be identity except when copying the // root draw pass from a surface into a pass when the surface draw quad's // transform is not identity. - copy_shared_quad_state->content_to_target_transform.ConcatTransform( + copy_shared_quad_state->quad_to_target_transform.ConcatTransform( target_transform); ClipData new_clip_rect = CalculateClipRect( @@ -371,7 +301,7 @@ void SurfaceAggregator::CopySharedQuadState( void SurfaceAggregator::CopyQuadsToPass( const QuadList& source_quad_list, const SharedQuadStateList& source_shared_quad_state_list, - const DrawQuad::ResourceIteratorCallback& remap, + const ResourceProvider::ResourceIdMap& child_to_parent_map, const gfx::Transform& target_transform, const ClipData& clip_rect, RenderPass* dest_pass, @@ -404,27 +334,24 @@ void SurfaceAggregator::CopyQuadsToPass( RenderPassId remapped_pass_id = RemapPassId(original_pass_id, surface_id); - gfx::Rect pass_damage; - for (const auto* pass : *dest_pass_list_) { - if (pass->id == remapped_pass_id) { - pass_damage = pass->damage_rect; - break; - } - } - dest_quad = dest_pass->CopyFromAndAppendRenderPassDrawQuad( pass_quad, dest_pass->shared_quad_state_list.back(), remapped_pass_id); - dest_pass->damage_rect = - gfx::UnionRects(dest_pass->damage_rect, - MathUtil::MapEnclosingClippedRect( - dest_quad->quadTransform(), pass_damage)); } else { dest_quad = dest_pass->CopyFromAndAppendDrawQuad( quad, dest_pass->shared_quad_state_list.back()); } - if (!remap.is_null()) - dest_quad->IterateResources(remap); + if (!child_to_parent_map.empty()) { + for (ResourceId& resource_id : dest_quad->resources) { + ResourceProvider::ResourceIdMap::const_iterator it = + child_to_parent_map.find(resource_id); + DCHECK(it != child_to_parent_map.end()); + + DCHECK_EQ(it->first, resource_id); + ResourceId remapped_id = it->second; + resource_id = remapped_id; + } + } } } } @@ -437,19 +364,16 @@ void SurfaceAggregator::CopyPasses(const DelegatedFrameData* frame_data, surface->TakeCopyOutputRequests(©_requests); const RenderPassList& source_pass_list = frame_data->render_pass_list; - bool invalid_frame = ValidateResources(surface, frame_data); - DCHECK(!invalid_frame); - if (invalid_frame) + DCHECK(valid_surfaces_.count(surface->surface_id())); + if (!valid_surfaces_.count(surface->surface_id())) return; - DrawQuad::ResourceIteratorCallback remap; - if (provider_) { - int child_id = ChildIdForSurface(surface); - remap = - base::Bind(&ResourceRemapHelper, - base::ConstRef(provider_->GetChildToParentMap(child_id))); - } - + // TODO(vmpstr): provider check is a hack for unittests that don't set up a + // resource provider. + ResourceProvider::ResourceIdMap empty_map; + const ResourceProvider::ResourceIdMap& child_to_parent_map = + provider_ ? provider_->GetChildToParentMap(ChildIdForSurface(surface)) + : empty_map; for (size_t i = 0; i < source_pass_list.size(); ++i) { const RenderPass& source = *source_pass_list[i]; @@ -462,17 +386,13 @@ void SurfaceAggregator::CopyPasses(const DelegatedFrameData* frame_data, RenderPassId remapped_pass_id = RemapPassId(source.id, surface->surface_id()); - gfx::Rect damage_rect = - (i < source_pass_list.size() - 1) - ? gfx::Rect() - : DamageRectForSurface(surface, source, source.output_rect); - copy_pass->SetAll(remapped_pass_id, source.output_rect, damage_rect, + copy_pass->SetAll(remapped_pass_id, source.output_rect, gfx::Rect(), source.transform_to_root_target, source.has_transparent_background); - CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, remap, - gfx::Transform(), ClipData(), copy_pass.get(), - surface->surface_id()); + CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, + child_to_parent_map, gfx::Transform(), ClipData(), + copy_pass.get(), surface->surface_id()); dest_pass_list_->push_back(copy_pass.Pass()); } @@ -495,6 +415,104 @@ void SurfaceAggregator::RemoveUnreferencedChildren() { } } +// Validate the resources of the current surface and its descendants, and +// calculate their combined damage rect. +gfx::Rect SurfaceAggregator::ValidateAndCalculateDamageRect( + SurfaceId surface_id) { + if (referenced_surfaces_.count(surface_id)) + return gfx::Rect(); + Surface* surface = manager_->GetSurfaceForId(surface_id); + if (!surface) + return gfx::Rect(); + const CompositorFrame* surface_frame = surface->GetEligibleFrame(); + if (!surface_frame) + return gfx::Rect(); + const DelegatedFrameData* frame_data = + surface_frame->delegated_frame_data.get(); + if (!frame_data) + return gfx::Rect(); + int child_id = 0; + // TODO(jbauman): hack for unit tests that don't set up rp + if (provider_) { + child_id = ChildIdForSurface(surface); + if (surface->factory()) + surface->factory()->RefResources(frame_data->resource_list); + provider_->ReceiveFromChild(child_id, frame_data->resource_list); + } + + ResourceProvider::ResourceIdSet referenced_resources; + size_t reserve_size = frame_data->resource_list.size(); +#if defined(COMPILER_MSVC) + referenced_resources.reserve(reserve_size); +#elif defined(COMPILER_GCC) + // Pre-standard hash-tables only implement resize, which behaves similarly + // to reserve for these keys. Resizing to 0 may also be broken (particularly + // on stlport). + // TODO(jbauman): Replace with reserve when C++11 is supported everywhere. + if (reserve_size) + referenced_resources.resize(reserve_size); +#endif + + bool invalid_frame = false; + ResourceProvider::ResourceIdMap empty_map; + const ResourceProvider::ResourceIdMap& child_to_parent_map = + provider_ ? provider_->GetChildToParentMap(child_id) : empty_map; + + // Each pair in the vector is a child surface and the transform from its + // target to the root target of this surface. + std::vector<std::pair<SurfaceId, gfx::Transform>> child_surfaces; + for (const auto& render_pass : frame_data->render_pass_list) { + for (const auto& quad : render_pass->quad_list) { + if (quad->material == DrawQuad::SURFACE_CONTENT) { + const SurfaceDrawQuad* surface_quad = + SurfaceDrawQuad::MaterialCast(quad); + gfx::Transform target_to_surface_transform( + surface_quad->shared_quad_state->quad_to_target_transform, + render_pass->transform_to_root_target); + child_surfaces.push_back(std::make_pair(surface_quad->surface_id, + target_to_surface_transform)); + } + + if (!provider_) + continue; + for (ResourceId resource_id : quad->resources) { + if (!child_to_parent_map.count(resource_id)) { + invalid_frame = true; + break; + } + referenced_resources.insert(resource_id); + } + } + } + + if (invalid_frame) + return gfx::Rect(); + valid_surfaces_.insert(surface->surface_id()); + + if (provider_) + provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources); + + gfx::Rect damage_rect; + if (!frame_data->render_pass_list.empty()) { + damage_rect = + DamageRectForSurface(surface, *frame_data->render_pass_list.back(), + frame_data->render_pass_list.back()->output_rect); + } + + // Avoid infinite recursion by adding current surface to + // referenced_surfaces_. + SurfaceSet::iterator it = + referenced_surfaces_.insert(surface->surface_id()).first; + for (const auto& surface_info : child_surfaces) { + gfx::Rect surface_damage = + ValidateAndCalculateDamageRect(surface_info.first); + damage_rect.Union( + MathUtil::MapEnclosingClippedRect(surface_info.second, surface_damage)); + } + referenced_surfaces_.erase(it); + return damage_rect; +} + scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) { Surface* surface = manager_->GetSurfaceForId(surface_id); DCHECK(surface); @@ -509,18 +527,21 @@ scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) { DCHECK(root_surface_frame->delegated_frame_data); - SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; - dest_resource_list_ = &frame->delegated_frame_data->resource_list; dest_pass_list_ = &frame->delegated_frame_data->render_pass_list; - CopyPasses(root_surface_frame->delegated_frame_data.get(), surface); + valid_surfaces_.clear(); + gfx::Rect damage_rect = ValidateAndCalculateDamageRect(surface_id); + SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; + CopyPasses(root_surface_frame->delegated_frame_data.get(), surface); referenced_surfaces_.erase(it); + DCHECK(referenced_surfaces_.empty()); if (dest_pass_list_->empty()) return nullptr; + dest_pass_list_->back()->damage_rect = damage_rect; dest_pass_list_ = NULL; RemoveUnreferencedChildren(); diff --git a/chromium/cc/surfaces/surface_aggregator.h b/chromium/cc/surfaces/surface_aggregator.h index 8ceb4eb471e..17ea4c43125 100644 --- a/chromium/cc/surfaces/surface_aggregator.h +++ b/chromium/cc/surfaces/surface_aggregator.h @@ -64,21 +64,21 @@ class CC_SURFACES_EXPORT SurfaceAggregator { const gfx::Transform& target_transform, const ClipData& clip_rect, RenderPass* dest_render_pass); - void CopyQuadsToPass(const QuadList& source_quad_list, - const SharedQuadStateList& source_shared_quad_state_list, - const DrawQuad::ResourceIteratorCallback& remap, - const gfx::Transform& target_transform, - const ClipData& clip_rect, - RenderPass* dest_pass, - SurfaceId surface_id); + void CopyQuadsToPass( + const QuadList& source_quad_list, + const SharedQuadStateList& source_shared_quad_state_list, + const base::hash_map<ResourceId, ResourceId>& resource_to_child_map, + const gfx::Transform& target_transform, + const ClipData& clip_rect, + RenderPass* dest_pass, + SurfaceId surface_id); + gfx::Rect ValidateAndCalculateDamageRect(SurfaceId surface_id); void CopyPasses(const DelegatedFrameData* frame_data, Surface* surface); // Remove Surfaces that were referenced before but aren't currently // referenced from the ResourceProvider. void RemoveUnreferencedChildren(); - bool ValidateResources(Surface* surface, - const DelegatedFrameData* frame_data); int ChildIdForSurface(Surface* surface); gfx::Rect DamageRectForSurface(const Surface* surface, const RenderPass& source, @@ -110,6 +110,9 @@ class CC_SURFACES_EXPORT SurfaceAggregator { SurfaceIndexMap previous_contained_surfaces_; SurfaceIndexMap contained_surfaces_; + // After surface validation, every Surface in this set is valid. + base::hash_set<SurfaceId> valid_surfaces_; + // This is the pass list for the aggregated frame. RenderPassList* dest_pass_list_; diff --git a/chromium/cc/surfaces/surface_aggregator_perftest.cc b/chromium/cc/surfaces/surface_aggregator_perftest.cc index 87a8932132c..b5fddf51dc6 100644 --- a/chromium/cc/surfaces/surface_aggregator_perftest.cc +++ b/chromium/cc/surfaces/surface_aggregator_perftest.cc @@ -13,6 +13,7 @@ #include "cc/surfaces/surface_manager.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/test_shared_bitmap_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" @@ -33,9 +34,8 @@ class SurfaceAggregatorPerfTest : public testing::Test { output_surface_->BindToClient(&output_surface_client_); shared_bitmap_manager_.reset(new TestSharedBitmapManager); - resource_provider_ = ResourceProvider::Create( - output_surface_.get(), shared_bitmap_manager_.get(), nullptr, nullptr, - 0, false, 1); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), shared_bitmap_manager_.get()); aggregator_.reset( new SurfaceAggregator(&manager_, resource_provider_.get())); } @@ -70,8 +70,8 @@ class SurfaceAggregatorPerfTest : public testing::Test { bool flipped = false; bool nearest_neighbor = false; quad->SetAll(sqs, rect, opaque_rect, visible_rect, needs_blending, j, - premultiplied_alpha, uv_top_left, uv_bottom_right, - background_color, vertex_opacity, flipped, + gfx::Size(), false, premultiplied_alpha, uv_top_left, + uv_bottom_right, background_color, vertex_opacity, flipped, nearest_neighbor); } sqs = pass->CreateAndAppendSharedQuadState(); diff --git a/chromium/cc/surfaces/surface_aggregator_test_helpers.cc b/chromium/cc/surfaces/surface_aggregator_test_helpers.cc index b21b37e28d6..f7da1a25c84 100644 --- a/chromium/cc/surfaces/surface_aggregator_test_helpers.cc +++ b/chromium/cc/surfaces/surface_aggregator_test_helpers.cc @@ -26,22 +26,17 @@ void AddTestSurfaceQuad(TestRenderPass* pass, const gfx::Size& surface_size, float opacity, SurfaceId surface_id) { - gfx::Transform content_to_target_transform; - gfx::Size content_bounds = surface_size; - gfx::Rect visible_content_rect = gfx::Rect(surface_size); + gfx::Transform layer_to_target_transform; + gfx::Size layer_bounds = surface_size; + gfx::Rect visible_layer_rect = gfx::Rect(surface_size); gfx::Rect clip_rect = gfx::Rect(surface_size); bool is_clipped = false; SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode; SharedQuadState* shared_quad_state = pass->CreateAndAppendSharedQuadState(); - shared_quad_state->SetAll(content_to_target_transform, - content_bounds, - visible_content_rect, - clip_rect, - is_clipped, - opacity, - blend_mode, - 0); + shared_quad_state->SetAll(layer_to_target_transform, layer_bounds, + visible_layer_rect, clip_rect, is_clipped, opacity, + blend_mode, 0); SurfaceDrawQuad* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); diff --git a/chromium/cc/surfaces/surface_aggregator_test_helpers.h b/chromium/cc/surfaces/surface_aggregator_test_helpers.h index 05c83440616..6d00c4f70f6 100644 --- a/chromium/cc/surfaces/surface_aggregator_test_helpers.h +++ b/chromium/cc/surfaces/surface_aggregator_test_helpers.h @@ -55,11 +55,7 @@ struct Quad { RenderPassId render_pass_id; private: - Quad() - : material(DrawQuad::INVALID), - opacity(1.f), - color(SK_ColorWHITE), - render_pass_id(-1, -1) {} + Quad() : material(DrawQuad::INVALID), opacity(1.f), color(SK_ColorWHITE) {} }; struct Pass { diff --git a/chromium/cc/surfaces/surface_aggregator_unittest.cc b/chromium/cc/surfaces/surface_aggregator_unittest.cc index 40a3d572bda..e4ade82116e 100644 --- a/chromium/cc/surfaces/surface_aggregator_unittest.cc +++ b/chromium/cc/surfaces/surface_aggregator_unittest.cc @@ -19,6 +19,7 @@ #include "cc/surfaces/surface_manager.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/render_pass_test_common.h" #include "cc/test/render_pass_test_utils.h" #include "cc/test/test_shared_bitmap_manager.h" @@ -689,9 +690,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) { void AddSolidColorQuadWithBlendMode(const gfx::Size& size, RenderPass* pass, const SkXfermode::Mode blend_mode) { - const gfx::Transform content_to_target_transform; - const gfx::Size content_bounds(size); - const gfx::Rect visible_content_rect(size); + const gfx::Transform layer_to_target_transform; + const gfx::Size layer_bounds(size); + const gfx::Rect visible_layer_rect(size); const gfx::Rect clip_rect(size); bool is_clipped = false; @@ -699,21 +700,13 @@ void AddSolidColorQuadWithBlendMode(const gfx::Size& size, bool force_anti_aliasing_off = false; SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); - sqs->SetAll(content_to_target_transform, - content_bounds, - visible_content_rect, - clip_rect, - is_clipped, - opacity, - blend_mode, - 0); + sqs->SetAll(layer_to_target_transform, layer_bounds, visible_layer_rect, + clip_rect, is_clipped, opacity, blend_mode, 0); SolidColorDrawQuad* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - color_quad->SetNew(pass->shared_quad_state_list.back(), - visible_content_rect, - visible_content_rect, - SK_ColorGREEN, + color_quad->SetNew(pass->shared_quad_state_list.back(), visible_layer_rect, + visible_layer_rect, SK_ColorGREEN, force_anti_aliasing_off); } @@ -888,12 +881,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { child_nonroot_pass->transform_to_root_target.Translate(8, 0); SharedQuadState* child_nonroot_pass_sqs = child_nonroot_pass->shared_quad_state_list.front(); - child_nonroot_pass_sqs->content_to_target_transform.Translate(5, 0); + child_nonroot_pass_sqs->quad_to_target_transform.Translate(5, 0); RenderPass* child_root_pass = child_pass_list.at(1u); SharedQuadState* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front(); - child_root_pass_sqs->content_to_target_transform.Translate(8, 0); + child_root_pass_sqs->quad_to_target_transform.Translate(8, 0); child_root_pass_sqs->is_clipped = true; child_root_pass_sqs->clip_rect = gfx::Rect(0, 0, 5, 5); @@ -926,7 +919,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { gfx::Rect(0, 1, 100, 7); SharedQuadState* middle_root_pass_sqs = middle_root_pass->shared_quad_state_list.front(); - middle_root_pass_sqs->content_to_target_transform.Scale(2, 3); + middle_root_pass_sqs->quad_to_target_transform.Scale(2, 3); scoped_ptr<DelegatedFrameData> middle_frame_data(new DelegatedFrameData); middle_pass_list.swap(middle_frame_data->render_pass_list); @@ -955,10 +948,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { root_pass_list.at(0) ->shared_quad_state_list.front() - ->content_to_target_transform.Translate(0, 7); + ->quad_to_target_transform.Translate(0, 7); root_pass_list.at(0) ->shared_quad_state_list.ElementAt(1) - ->content_to_target_transform.Translate(0, 10); + ->quad_to_target_transform.Translate(0, 10); root_pass_list.at(0)->quad_list.ElementAt(1)->visible_rect = gfx::Rect(0, 0, 8, 100); @@ -1004,7 +997,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { gfx::Transform expected_aggregated_first_pass_sqs_transform; expected_aggregated_first_pass_sqs_transform.Translate(5, 0); EXPECT_EQ(expected_aggregated_first_pass_sqs_transform.ToString(), - aggregated_first_pass_sqs->content_to_target_transform.ToString()); + aggregated_first_pass_sqs->quad_to_target_transform.ToString()); // The first pass's transform to the root target should include the aggregated // transform, including the transform from the child pass to the root. @@ -1035,7 +1028,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { iter != aggregated_pass_list[1]->quad_list.cend(); ++iter) { EXPECT_EQ(expected_root_pass_quad_transforms[iter.index()].ToString(), - iter->quadTransform().ToString()) + iter->shared_quad_state->quad_to_target_transform.ToString()) << iter.index(); } @@ -1056,12 +1049,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { // Tests that damage rects are aggregated correctly when surfaces change. TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { - SurfaceId child_surface_id = allocator_.GenerateId(); - factory_.Create(child_surface_id); - RenderPassId child_pass_id = RenderPassId(1, 1); - test::Quad child_quads[] = {test::Quad::RenderPassQuad(child_pass_id)}; + test::Quad child_quads[] = {test::Quad::RenderPassQuad(RenderPassId(1, 1))}; test::Pass child_passes[] = { - test::Pass(child_quads, arraysize(child_quads), child_pass_id)}; + test::Pass(child_quads, arraysize(child_quads), RenderPassId(1, 1))}; RenderPassList child_pass_list; AddPasses(&child_pass_list, @@ -1072,7 +1062,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { RenderPass* child_root_pass = child_pass_list.at(0u); SharedQuadState* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front(); - child_root_pass_sqs->content_to_target_transform.Translate(8, 0); + child_root_pass_sqs->quad_to_target_transform.Translate(8, 0); scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData); child_pass_list.swap(child_frame_data->render_pass_list); @@ -1080,16 +1070,47 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); child_frame->delegated_frame_data = child_frame_data.Pass(); + SurfaceId child_surface_id = allocator_.GenerateId(); + factory_.Create(child_surface_id); factory_.SubmitFrame(child_surface_id, child_frame.Pass(), SurfaceFactory::DrawCallback()); - RenderPassId pass_id(5, 10); - test::Quad first_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)}; - test::Quad root_quads[] = {test::Quad::RenderPassQuad(pass_id)}; + test::Quad parent_surface_quads[] = { + test::Quad::SurfaceQuad(child_surface_id, 1.f)}; + test::Pass parent_surface_passes[] = { + test::Pass(parent_surface_quads, arraysize(parent_surface_quads), + RenderPassId(1, 1))}; + + RenderPassList parent_surface_pass_list; + AddPasses(&parent_surface_pass_list, + gfx::Rect(SurfaceSize()), + parent_surface_passes, + arraysize(parent_surface_passes)); + + // Parent surface is only used to test if the transform is applied correctly + // to the child surface's damage. + scoped_ptr<DelegatedFrameData> parent_surface_frame_data( + new DelegatedFrameData); + parent_surface_pass_list.swap(parent_surface_frame_data->render_pass_list); + + scoped_ptr<CompositorFrame> parent_surface_frame(new CompositorFrame); + parent_surface_frame->delegated_frame_data = parent_surface_frame_data.Pass(); + + SurfaceId parent_surface_id = allocator_.GenerateId(); + factory_.Create(parent_surface_id); + factory_.SubmitFrame(parent_surface_id, parent_surface_frame.Pass(), + SurfaceFactory::DrawCallback()); + + test::Quad root_surface_quads[] = { + test::Quad::SurfaceQuad(parent_surface_id, 1.f)}; + test::Quad root_render_pass_quads[] = { + test::Quad::RenderPassQuad(RenderPassId(1, 1))}; test::Pass root_passes[] = { - test::Pass(first_quads, arraysize(first_quads), pass_id), - test::Pass(root_quads, arraysize(root_quads))}; + test::Pass(root_surface_quads, arraysize(root_surface_quads), + RenderPassId(1, 1)), + test::Pass(root_render_pass_quads, arraysize(root_render_pass_quads), + RenderPassId(2, 1))}; RenderPassList root_pass_list; AddPasses(&root_pass_list, @@ -1099,7 +1120,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { root_pass_list.at(0) ->shared_quad_state_list.front() - ->content_to_target_transform.Translate(0, 10); + ->quad_to_target_transform.Translate(0, 10); root_pass_list.at(0)->damage_rect = gfx::Rect(5, 5, 10, 10); root_pass_list.at(1)->damage_rect = gfx::Rect(5, 5, 100, 100); @@ -1137,7 +1158,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { RenderPass* child_root_pass = child_pass_list.at(0u); SharedQuadState* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front(); - child_root_pass_sqs->content_to_target_transform.Translate(8, 0); + child_root_pass_sqs->quad_to_target_transform.Translate(8, 0); child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10); scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData); @@ -1177,7 +1198,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { root_pass_list.at(0) ->shared_quad_state_list.front() - ->content_to_target_transform.Translate(0, 10); + ->quad_to_target_transform.Translate(0, 10); root_pass_list.at(0)->damage_rect = gfx::Rect(0, 0, 1, 1); scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData); @@ -1199,7 +1220,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { root_pass_list.at(0) ->shared_quad_state_list.front() - ->content_to_target_transform.Translate(0, 10); + ->quad_to_target_transform.Translate(0, 10); root_pass_list.at(0)->damage_rect = gfx::Rect(1, 1, 1, 1); scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData); @@ -1280,13 +1301,8 @@ class SurfaceAggregatorWithResourcesTest : public testing::Test { output_surface_->BindToClient(&output_surface_client_); shared_bitmap_manager_.reset(new TestSharedBitmapManager); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), shared_bitmap_manager_.get()); aggregator_.reset( new SurfaceAggregator(&manager_, resource_provider_.get())); @@ -1320,7 +1336,7 @@ class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient { DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient); }; -void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids, +void SubmitFrameWithResources(ResourceId* resource_ids, size_t num_resource_ids, bool valid, SurfaceId child_id, @@ -1356,19 +1372,10 @@ void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids, const float vertex_opacity[4] = {0.f, 0.f, 1.f, 1.f}; bool flipped = false; bool nearest_neighbor = false; - quad->SetAll(sqs, - rect, - opaque_rect, - visible_rect, - needs_blending, - resource_ids[i], - premultiplied_alpha, - uv_top_left, - uv_bottom_right, - background_color, - vertex_opacity, - flipped, - nearest_neighbor); + quad->SetAll(sqs, rect, opaque_rect, visible_rect, needs_blending, + resource_ids[i], gfx::Size(), false, premultiplied_alpha, + uv_top_left, uv_bottom_right, background_color, vertex_opacity, + flipped, nearest_neighbor); } frame_data->render_pass_list.push_back(pass.Pass()); scoped_ptr<CompositorFrame> frame(new CompositorFrame); @@ -1383,7 +1390,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) { SurfaceId surface_id(7u); factory.Create(surface_id); - ResourceProvider::ResourceId ids[] = {11, 12, 13}; + ResourceId ids[] = {11, 12, 13}; SubmitFrameWithResources(ids, arraysize(ids), true, SurfaceId(), &factory, surface_id); @@ -1397,7 +1404,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) { frame = aggregator_->Aggregate(surface_id); ASSERT_EQ(3u, client.returned_resources().size()); - ResourceProvider::ResourceId returned_ids[3]; + ResourceId returned_ids[3]; for (size_t i = 0; i < 3; ++i) { returned_ids[i] = client.returned_resources()[i].id; } @@ -1447,10 +1454,10 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) { SurfaceId surface_id2(8u); factory.Create(surface_id2); - ResourceProvider::ResourceId ids[] = {11, 12, 13}; + ResourceId ids[] = {11, 12, 13}; SubmitFrameWithResources(ids, arraysize(ids), true, SurfaceId(), &factory, surface_id); - ResourceProvider::ResourceId ids2[] = {14, 15, 16}; + ResourceId ids2[] = {14, 15, 16}; SubmitFrameWithResources(ids2, arraysize(ids2), true, SurfaceId(), &factory, surface_id2); @@ -1465,7 +1472,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) { // surface_id wasn't referenced, so its resources should be returned. ASSERT_EQ(3u, client.returned_resources().size()); - ResourceProvider::ResourceId returned_ids[3]; + ResourceId returned_ids[3]; for (size_t i = 0; i < 3; ++i) { returned_ids[i] = client.returned_resources()[i].id; } @@ -1488,15 +1495,15 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) { SurfaceId child_surface_id(9u); factory.Create(child_surface_id); - ResourceProvider::ResourceId ids[] = {14, 15, 16}; + ResourceId ids[] = {14, 15, 16}; SubmitFrameWithResources(ids, arraysize(ids), true, SurfaceId(), &factory, child_surface_id); - ResourceProvider::ResourceId ids2[] = {17, 18, 19}; + ResourceId ids2[] = {17, 18, 19}; SubmitFrameWithResources(ids2, arraysize(ids2), false, child_surface_id, &factory, middle_surface_id); - ResourceProvider::ResourceId ids3[] = {20, 21, 22}; + ResourceId ids3[] = {20, 21, 22}; SubmitFrameWithResources(ids3, arraysize(ids3), true, middle_surface_id, &factory, root_surface_id); diff --git a/chromium/cc/surfaces/surface_display_output_surface.cc b/chromium/cc/surfaces/surface_display_output_surface.cc index e1f90da7614..e21d15d8afb 100644 --- a/chromium/cc/surfaces/surface_display_output_surface.cc +++ b/chromium/cc/surfaces/surface_display_output_surface.cc @@ -59,14 +59,14 @@ void SurfaceDisplayOutputSurface::SwapBuffers(CompositorFrame* frame) { display_client_->display()->SetSurfaceId(surface_id_, frame->metadata.device_scale_factor); + client_->DidSwapBuffers(); + scoped_ptr<CompositorFrame> frame_copy(new CompositorFrame()); frame->AssignTo(frame_copy.get()); factory_.SubmitFrame( surface_id_, frame_copy.Pass(), base::Bind(&SurfaceDisplayOutputSurface::SwapBuffersComplete, base::Unretained(this))); - - client_->DidSwapBuffers(); } bool SurfaceDisplayOutputSurface::BindToClient(OutputSurfaceClient* client) { diff --git a/chromium/cc/surfaces/surface_display_output_surface_unittest.cc b/chromium/cc/surfaces/surface_display_output_surface_unittest.cc index ed801e91474..922dd9e8d5f 100644 --- a/chromium/cc/surfaces/surface_display_output_surface_unittest.cc +++ b/chromium/cc/surfaces/surface_display_output_surface_unittest.cc @@ -47,7 +47,8 @@ class FakeOnscreenDisplayClient : public OnscreenDisplayClient { class SurfaceDisplayOutputSurfaceTest : public testing::Test { public: SurfaceDisplayOutputSurfaceTest() - : task_runner_(new OrderedSimpleTaskRunner()), + : now_src_(new base::SimpleTestTickClock()), + task_runner_(new OrderedSimpleTaskRunner(now_src_.get(), true)), allocator_(0), display_size_(1920, 1080), display_rect_(display_size_), @@ -98,6 +99,7 @@ class SurfaceDisplayOutputSurfaceTest : public testing::Test { } protected: + scoped_ptr<base::SimpleTestTickClock> now_src_; scoped_refptr<OrderedSimpleTaskRunner> task_runner_; SurfaceIdAllocator allocator_; @@ -130,6 +132,21 @@ TEST_F(SurfaceDisplayOutputSurfaceTest, NoDamageDoesNotTriggerSwapBuffers) { EXPECT_EQ(1u, output_surface_->num_sent_frames()); } +TEST_F(SurfaceDisplayOutputSurfaceTest, SuspendedDoesNotTriggerSwapBuffers) { + SwapBuffersWithDamage(display_rect_); + EXPECT_EQ(1u, output_surface_->num_sent_frames()); + output_surface_->set_suspended_for_recycle(true); + task_runner_->RunUntilIdle(); + EXPECT_EQ(1u, output_surface_->num_sent_frames()); + SwapBuffersWithDamage(display_rect_); + task_runner_->RunUntilIdle(); + EXPECT_EQ(1u, output_surface_->num_sent_frames()); + output_surface_->set_suspended_for_recycle(false); + SwapBuffersWithDamage(display_rect_); + task_runner_->RunUntilIdle(); + EXPECT_EQ(2u, output_surface_->num_sent_frames()); +} + TEST_F(SurfaceDisplayOutputSurfaceTest, LockingResourcesDoesNotIndirectlyCauseDamage) { surface_display_output_surface_.ForceReclaimResources(); diff --git a/chromium/cc/surfaces/surface_factory_unittest.cc b/chromium/cc/surfaces/surface_factory_unittest.cc index b9c6bf5c207..c2951aead48 100644 --- a/chromium/cc/surfaces/surface_factory_unittest.cc +++ b/chromium/cc/surfaces/surface_factory_unittest.cc @@ -5,6 +5,7 @@ #include "base/bind.h" #include "cc/output/compositor_frame.h" #include "cc/output/delegated_frame_data.h" +#include "cc/resources/resource_provider.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_factory.h" #include "cc/surfaces/surface_factory_client.h" @@ -48,7 +49,7 @@ class SurfaceFactoryTest : public testing::Test { factory_.Destroy(surface_id_); } - void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids, + void SubmitFrameWithResources(ResourceId* resource_ids, size_t num_resource_ids) { scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); for (size_t i = 0u; i < num_resource_ids; ++i) { @@ -63,7 +64,7 @@ class SurfaceFactoryTest : public testing::Test { SurfaceFactory::DrawCallback()); } - void UnrefResources(ResourceProvider::ResourceId* ids_to_unref, + void UnrefResources(ResourceId* ids_to_unref, int* counts_to_unref, size_t num_ids_to_unref) { ReturnedResourceArray unref_array; @@ -76,10 +77,9 @@ class SurfaceFactoryTest : public testing::Test { factory_.UnrefResources(unref_array); } - void CheckReturnedResourcesMatchExpected( - ResourceProvider::ResourceId* expected_returned_ids, - int* expected_returned_counts, - size_t expected_resources) { + void CheckReturnedResourcesMatchExpected(ResourceId* expected_returned_ids, + int* expected_returned_counts, + size_t expected_resources) { const ReturnedResourceArray& actual_resources = client_.returned_resources(); ASSERT_EQ(expected_resources, actual_resources.size()); @@ -107,7 +107,7 @@ class SurfaceFactoryTest : public testing::Test { // Tests submitting a frame with resources followed by one with no resources // with no resource provider action in between. TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) { - ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3}; + ResourceId first_frame_ids[] = {1, 2, 3}; SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids)); // All of the resources submitted in the first frame are still in use at this @@ -120,7 +120,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) { // available to be returned. SubmitFrameWithResources(NULL, 0); - ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3}; + ResourceId expected_returned_ids[] = {1, 2, 3}; int expected_returned_counts[] = {1, 1, 1}; CheckReturnedResourcesMatchExpected(expected_returned_ids, expected_returned_counts, @@ -130,7 +130,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) { // Tests submitting a frame with resources followed by one with no resources // with the resource provider holding everything alive. TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) { - ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3}; + ResourceId first_frame_ids[] = {1, 2, 3}; SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids)); // All of the resources submitted in the first frame are still in use at this @@ -152,7 +152,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) { int release_counts[] = {1, 1, 1}; UnrefResources(first_frame_ids, release_counts, arraysize(first_frame_ids)); - ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3}; + ResourceId expected_returned_ids[] = {1, 2, 3}; int expected_returned_counts[] = {1, 1, 1}; CheckReturnedResourcesMatchExpected(expected_returned_ids, expected_returned_counts, @@ -162,7 +162,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) { // Tests referencing a resource, unref'ing it to zero, then using it again // before returning it to the client. TEST_F(SurfaceFactoryTest, ResourceReusedBeforeReturn) { - ResourceProvider::ResourceId first_frame_ids[] = {7}; + ResourceId first_frame_ids[] = {7}; SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids)); // This removes all references to resource id 7. @@ -189,14 +189,14 @@ TEST_F(SurfaceFactoryTest, ResourceReusedBeforeReturn) { // Tests having resources referenced multiple times, as if referenced by // multiple providers. TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) { - ResourceProvider::ResourceId first_frame_ids[] = {3, 4}; + ResourceId first_frame_ids[] = {3, 4}; SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids)); // Ref resources from the first frame twice. RefCurrentFrameResources(); RefCurrentFrameResources(); - ResourceProvider::ResourceId second_frame_ids[] = {4, 5}; + ResourceId second_frame_ids[] = {4, 5}; SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids)); // Ref resources from the second frame 3 times. @@ -217,7 +217,7 @@ TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) { // 5 -> 3 { SCOPED_TRACE("unref all 3"); - ResourceProvider::ResourceId ids_to_unref[] = {3, 4, 5}; + ResourceId ids_to_unref[] = {3, 4, 5}; int counts[] = {1, 1, 1}; UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref)); @@ -226,7 +226,7 @@ TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) { UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref)); - ResourceProvider::ResourceId expected_returned_ids[] = {3}; + ResourceId expected_returned_ids[] = {3}; int expected_returned_counts[] = {1}; CheckReturnedResourcesMatchExpected(expected_returned_ids, expected_returned_counts, @@ -238,11 +238,11 @@ TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) { // 5 -> 1 { SCOPED_TRACE("unref 4 and 5"); - ResourceProvider::ResourceId ids_to_unref[] = {4, 5}; + ResourceId ids_to_unref[] = {4, 5}; int counts[] = {1, 1}; UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref)); - ResourceProvider::ResourceId expected_returned_ids[] = {5}; + ResourceId expected_returned_ids[] = {5}; int expected_returned_counts[] = {1}; CheckReturnedResourcesMatchExpected(expected_returned_ids, expected_returned_counts, @@ -253,11 +253,11 @@ TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) { // the returned count is correct. { SCOPED_TRACE("unref only 4"); - ResourceProvider::ResourceId ids_to_unref[] = {4}; + ResourceId ids_to_unref[] = {4}; int counts[] = {2}; UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref)); - ResourceProvider::ResourceId expected_returned_ids[] = {4}; + ResourceId expected_returned_ids[] = {4}; int expected_returned_counts[] = {2}; CheckReturnedResourcesMatchExpected(expected_returned_ids, expected_returned_counts, @@ -266,7 +266,7 @@ TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) { } TEST_F(SurfaceFactoryTest, ResourceLifetime) { - ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3}; + ResourceId first_frame_ids[] = {1, 2, 3}; SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids)); // All of the resources submitted in the first frame are still in use at this @@ -278,12 +278,12 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) { // The second frame references some of the same resources, but some different // ones. We expect to receive back resource 1 with a count of 1 since it was // only referenced by the first frame. - ResourceProvider::ResourceId second_frame_ids[] = {2, 3, 4}; + ResourceId second_frame_ids[] = {2, 3, 4}; SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids)); { SCOPED_TRACE("second frame"); - ResourceProvider::ResourceId expected_returned_ids[] = {1}; + ResourceId expected_returned_ids[] = {1}; int expected_returned_counts[] = {1}; CheckReturnedResourcesMatchExpected(expected_returned_ids, expected_returned_counts, @@ -294,12 +294,12 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) { // receive back all resources from the first and second frames. Resource IDs 2 // and 3 will have counts of 2, since they were used in both frames, and // resource ID 4 will have a count of 1. - ResourceProvider::ResourceId third_frame_ids[] = {10, 11, 12, 13}; + ResourceId third_frame_ids[] = {10, 11, 12, 13}; SubmitFrameWithResources(third_frame_ids, arraysize(third_frame_ids)); { SCOPED_TRACE("third frame"); - ResourceProvider::ResourceId expected_returned_ids[] = {2, 3, 4}; + ResourceId expected_returned_ids[] = {2, 3, 4}; int expected_returned_counts[] = {2, 2, 1}; CheckReturnedResourcesMatchExpected(expected_returned_ids, expected_returned_counts, @@ -309,7 +309,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) { // Simulate a ResourceProvider taking a ref on all of the resources. RefCurrentFrameResources(); - ResourceProvider::ResourceId fourth_frame_ids[] = {12, 13}; + ResourceId fourth_frame_ids[] = {12, 13}; SubmitFrameWithResources(fourth_frame_ids, arraysize(fourth_frame_ids)); EXPECT_EQ(0u, client_.returned_resources().size()); @@ -323,14 +323,14 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) { // Release resources associated with the first RefCurrentFrameResources() call // first. { - ResourceProvider::ResourceId ids_to_unref[] = {10, 11, 12, 13}; + ResourceId ids_to_unref[] = {10, 11, 12, 13}; int counts[] = {1, 1, 1, 1}; UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref)); } { SCOPED_TRACE("fourth frame, first unref"); - ResourceProvider::ResourceId expected_returned_ids[] = {10, 11}; + ResourceId expected_returned_ids[] = {10, 11}; int expected_returned_counts[] = {1, 1}; CheckReturnedResourcesMatchExpected(expected_returned_ids, expected_returned_counts, @@ -338,7 +338,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) { } { - ResourceProvider::ResourceId ids_to_unref[] = {12, 13}; + ResourceId ids_to_unref[] = {12, 13}; int counts[] = {1, 1}; UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref)); } @@ -352,7 +352,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) { { SCOPED_TRACE("fourth frame, second unref"); - ResourceProvider::ResourceId expected_returned_ids[] = {12, 13}; + ResourceId expected_returned_ids[] = {12, 13}; int expected_returned_counts[] = {2, 2}; CheckReturnedResourcesMatchExpected(expected_returned_ids, expected_returned_counts, @@ -410,6 +410,8 @@ TEST_F(SurfaceFactoryTest, DestroySequence) { SurfaceId id2(5); factory_.Create(id2); + manager_.RegisterSurfaceIdNamespace(0); + // Check that waiting before the sequence is satisfied works. manager_.GetSurfaceForId(id2) ->AddDestructionDependency(SurfaceSequence(0, 4)); @@ -434,5 +436,77 @@ TEST_F(SurfaceFactoryTest, DestroySequence) { DCHECK(!manager_.GetSurfaceForId(id2)); } +// Tests that Surface ID namespace invalidation correctly allows +// Sequences to be ignored. +TEST_F(SurfaceFactoryTest, InvalidIdNamespace) { + uint32_t id_namespace = 9u; + SurfaceId id(5); + factory_.Create(id); + + manager_.RegisterSurfaceIdNamespace(id_namespace); + manager_.GetSurfaceForId(id) + ->AddDestructionDependency(SurfaceSequence(id_namespace, 4)); + factory_.Destroy(id); + + // Verify the dependency has prevented the surface from getting destroyed. + EXPECT_TRUE(manager_.GetSurfaceForId(id)); + + manager_.InvalidateSurfaceIdNamespace(id_namespace); + + // Verify that the invalidated namespace caused the unsatisfied sequence + // to be ignored. + EXPECT_FALSE(manager_.GetSurfaceForId(id)); +} + +TEST_F(SurfaceFactoryTest, DestroyCycle) { + SurfaceId id2(5); + factory_.Create(id2); + + manager_.RegisterSurfaceIdNamespace(0); + + manager_.GetSurfaceForId(id2) + ->AddDestructionDependency(SurfaceSequence(0, 4)); + + // Give id2 a frame that references surface_id_. + { + scoped_ptr<RenderPass> render_pass(RenderPass::Create()); + render_pass->referenced_surfaces.push_back(surface_id_); + scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); + frame_data->render_pass_list.push_back(render_pass.Pass()); + scoped_ptr<CompositorFrame> frame(new CompositorFrame); + frame->delegated_frame_data = frame_data.Pass(); + factory_.SubmitFrame(id2, frame.Pass(), SurfaceFactory::DrawCallback()); + } + factory_.Destroy(id2); + + // Give surface_id_ a frame that references id2. + { + scoped_ptr<RenderPass> render_pass(RenderPass::Create()); + render_pass->referenced_surfaces.push_back(id2); + scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); + frame_data->render_pass_list.push_back(render_pass.Pass()); + scoped_ptr<CompositorFrame> frame(new CompositorFrame); + frame->delegated_frame_data = frame_data.Pass(); + factory_.SubmitFrame(surface_id_, frame.Pass(), + SurfaceFactory::DrawCallback()); + } + factory_.Destroy(surface_id_); + EXPECT_TRUE(manager_.GetSurfaceForId(id2)); + // surface_id_ should be retained by reference from id2. + EXPECT_TRUE(manager_.GetSurfaceForId(surface_id_)); + + // Satisfy last destruction dependency for id2. + std::vector<uint32_t> to_satisfy; + to_satisfy.push_back(4); + manager_.DidSatisfySequences(0, &to_satisfy); + + // id2 and surface_id_ are in a reference cycle that has no surface + // sequences holding on to it, so they should be destroyed. + EXPECT_TRUE(!manager_.GetSurfaceForId(id2)); + EXPECT_TRUE(!manager_.GetSurfaceForId(surface_id_)); + + surface_id_ = SurfaceId(); +} + } // namespace } // namespace cc diff --git a/chromium/cc/surfaces/surface_id_allocator.cc b/chromium/cc/surfaces/surface_id_allocator.cc index af9e91bd5c2..04f60d9fad7 100644 --- a/chromium/cc/surfaces/surface_id_allocator.cc +++ b/chromium/cc/surfaces/surface_id_allocator.cc @@ -4,10 +4,23 @@ #include "cc/surfaces/surface_id_allocator.h" +#include "cc/surfaces/surface_manager.h" + namespace cc { SurfaceIdAllocator::SurfaceIdAllocator(uint32_t id_namespace) - : id_namespace_(id_namespace), next_id_(1u) { + : id_namespace_(id_namespace), next_id_(1u), manager_(nullptr) { +} + +void SurfaceIdAllocator::RegisterSurfaceIdNamespace(SurfaceManager* manager) { + DCHECK(!manager_); + manager_ = manager; + manager_->RegisterSurfaceIdNamespace(id_namespace_); +} + +SurfaceIdAllocator::~SurfaceIdAllocator() { + if (manager_) + manager_->InvalidateSurfaceIdNamespace(id_namespace_); } SurfaceId SurfaceIdAllocator::GenerateId() { diff --git a/chromium/cc/surfaces/surface_id_allocator.h b/chromium/cc/surfaces/surface_id_allocator.h index 96a241f299f..31b1e8717d1 100644 --- a/chromium/cc/surfaces/surface_id_allocator.h +++ b/chromium/cc/surfaces/surface_id_allocator.h @@ -10,22 +10,34 @@ namespace cc { +class SurfaceManager; + // This is a helper class for generating surface IDs within a specified // namespace. This is not threadsafe, to use from multiple threads wrap this // class in a mutex. class CC_SURFACES_EXPORT SurfaceIdAllocator { public: explicit SurfaceIdAllocator(uint32_t id_namespace); + ~SurfaceIdAllocator(); SurfaceId GenerateId(); static uint32_t NamespaceForId(SurfaceId id); + // This needs to be called before any sequences with this allocator's + // namespace will be used to enforce destruction dependencies. + // When this SurfaceIdAllocator is destroyed, its namespace is + // automatically invalidated and any remaining sequences with that + // namespace will be ignored. This method does not need to be called in + // contexts where there is no SurfaceManager (e.g. a renderer process). + void RegisterSurfaceIdNamespace(SurfaceManager* manager); + uint32_t id_namespace() const { return id_namespace_; } private: const uint32_t id_namespace_; uint32_t next_id_; + SurfaceManager* manager_; DISALLOW_COPY_AND_ASSIGN(SurfaceIdAllocator); }; diff --git a/chromium/cc/surfaces/surface_manager.cc b/chromium/cc/surfaces/surface_manager.cc index 117d82ab659..9ced46e41ba 100644 --- a/chromium/cc/surfaces/surface_manager.cc +++ b/chromium/cc/surfaces/surface_manager.cc @@ -40,8 +40,9 @@ void SurfaceManager::DeregisterSurface(SurfaceId surface_id) { void SurfaceManager::Destroy(scoped_ptr<Surface> surface) { DCHECK(thread_checker_.CalledOnValidThread()); + surface->set_destroyed(true); surfaces_to_destroy_.push_back(surface.release()); - SearchForSatisfaction(); + GarbageCollectSurfaces(); } void SurfaceManager::DidSatisfySequences(uint32_t id_namespace, @@ -53,14 +54,60 @@ void SurfaceManager::DidSatisfySequences(uint32_t id_namespace, satisfied_sequences_.insert(SurfaceSequence(id_namespace, *it)); } sequence->clear(); - SearchForSatisfaction(); + GarbageCollectSurfaces(); } -void SurfaceManager::SearchForSatisfaction() { +void SurfaceManager::RegisterSurfaceIdNamespace(uint32_t id_namespace) { + bool inserted = valid_surface_id_namespaces_.insert(id_namespace).second; + DCHECK(inserted); +} + +void SurfaceManager::InvalidateSurfaceIdNamespace(uint32_t id_namespace) { + valid_surface_id_namespaces_.erase(id_namespace); + GarbageCollectSurfaces(); +} + +void SurfaceManager::GarbageCollectSurfaces() { + // Simple mark and sweep GC. + // TODO(jbauman): Reduce the amount of work when nothing needs to be + // destroyed. + std::vector<SurfaceId> live_surfaces; + std::set<SurfaceId> live_surfaces_set; + + // GC roots are surfaces that have not been destroyed, or have not had all + // their destruction dependencies satisfied. + for (auto& map_entry : surface_map_) { + map_entry.second->SatisfyDestructionDependencies( + &satisfied_sequences_, &valid_surface_id_namespaces_); + if (!map_entry.second->destroyed() || + map_entry.second->GetDestructionDependencyCount()) { + live_surfaces_set.insert(map_entry.first); + live_surfaces.push_back(map_entry.first); + } + } + + // Mark all surfaces reachable from live surfaces by adding them to + // live_surfaces and live_surfaces_set. + for (size_t i = 0; i < live_surfaces.size(); i++) { + Surface* surf = surface_map_[live_surfaces[i]]; + DCHECK(surf); + + for (SurfaceId id : surf->referenced_surfaces()) { + if (live_surfaces_set.count(id)) + continue; + + Surface* surf2 = GetSurfaceForId(id); + if (surf2) { + live_surfaces.push_back(id); + live_surfaces_set.insert(id); + } + } + } + + // Destroy all remaining unreachable surfaces. for (SurfaceDestroyList::iterator dest_it = surfaces_to_destroy_.begin(); dest_it != surfaces_to_destroy_.end();) { - (*dest_it)->SatisfyDestructionDependencies(&satisfied_sequences_); - if (!(*dest_it)->GetDestructionDependencyCount()) { + if (!live_surfaces_set.count((*dest_it)->surface_id())) { scoped_ptr<Surface> surf(*dest_it); DeregisterSurface(surf->surface_id()); dest_it = surfaces_to_destroy_.erase(dest_it); diff --git a/chromium/cc/surfaces/surface_manager.h b/chromium/cc/surfaces/surface_manager.h index d7d78c42e28..8430ea619ab 100644 --- a/chromium/cc/surfaces/surface_manager.h +++ b/chromium/cc/surfaces/surface_manager.h @@ -49,12 +49,18 @@ class CC_SURFACES_EXPORT SurfaceManager { void DidSatisfySequences(uint32_t id_namespace, std::vector<uint32_t>* sequence); + void RegisterSurfaceIdNamespace(uint32_t id_namespace); + + // Invalidate a namespace that might still have associated sequences, + // possibly because a renderer process has crashed. + void InvalidateSurfaceIdNamespace(uint32_t id_namespace); + private: - void SearchForSatisfaction(); + void GarbageCollectSurfaces(); typedef base::hash_map<SurfaceId, Surface*> SurfaceMap; SurfaceMap surface_map_; - ObserverList<SurfaceDamageObserver> observer_list_; + base::ObserverList<SurfaceDamageObserver> observer_list_; base::ThreadChecker thread_checker_; // List of surfaces to be destroyed, along with what sequences they're still @@ -66,6 +72,11 @@ class CC_SURFACES_EXPORT SurfaceManager { // waited on. base::hash_set<SurfaceSequence> satisfied_sequences_; + // Set of valid surface ID namespaces. When a namespace is removed from + // this set, any remaining sequences with that namespace are considered + // satisfied. + base::hash_set<uint32_t> valid_surface_id_namespaces_; + DISALLOW_COPY_AND_ASSIGN(SurfaceManager); }; diff --git a/chromium/cc/surfaces/surface_resource_holder.cc b/chromium/cc/surfaces/surface_resource_holder.cc index 50d31a584ee..c257b6082eb 100644 --- a/chromium/cc/surfaces/surface_resource_holder.cc +++ b/chromium/cc/surfaces/surface_resource_holder.cc @@ -49,7 +49,7 @@ void SurfaceResourceHolder::UnrefResources( for (ReturnedResourceArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { - ResourceProvider::ResourceId id = it->id; + unsigned id = it->id; ResourceIdCountMap::iterator count_it = resource_id_use_count_map_.find(id); if (count_it == resource_id_use_count_map_.end()) continue; diff --git a/chromium/cc/surfaces/surface_resource_holder.h b/chromium/cc/surfaces/surface_resource_holder.h index 20c9f291848..95cdb827c07 100644 --- a/chromium/cc/surfaces/surface_resource_holder.h +++ b/chromium/cc/surfaces/surface_resource_holder.h @@ -7,8 +7,9 @@ #include "base/containers/hash_tables.h" #include "base/macros.h" -#include "cc/resources/resource_provider.h" +#include "cc/base/resource_id.h" #include "cc/resources/returned_resource.h" +#include "cc/resources/transferable_resource.h" #include "cc/surfaces/surfaces_export.h" namespace cc { @@ -39,8 +40,7 @@ class CC_SURFACES_EXPORT SurfaceResourceHolder { // Keeps track of the number of users currently in flight for each resource // ID we've received from the client. When this counter hits zero for a // particular resource, that ID is available to return to the client. - typedef base::hash_map<ResourceProvider::ResourceId, ResourceRefs> - ResourceIdCountMap; + typedef base::hash_map<ResourceId, ResourceRefs> ResourceIdCountMap; ResourceIdCountMap resource_id_use_count_map_; DISALLOW_COPY_AND_ASSIGN(SurfaceResourceHolder); diff --git a/chromium/cc/surfaces/surfaces_pixeltest.cc b/chromium/cc/surfaces/surfaces_pixeltest.cc index 528684b2c85..bf8ad57fb91 100644 --- a/chromium/cc/surfaces/surfaces_pixeltest.cc +++ b/chromium/cc/surfaces/surfaces_pixeltest.cc @@ -41,21 +41,15 @@ SharedQuadState* CreateAndAppendTestSharedQuadState( RenderPass* render_pass, const gfx::Transform& transform, const gfx::Size& size) { - const gfx::Size content_bounds = size; - const gfx::Rect visible_content_rect = gfx::Rect(size); + const gfx::Size layer_bounds = size; + const gfx::Rect visible_layer_rect = gfx::Rect(size); const gfx::Rect clip_rect = gfx::Rect(size); bool is_clipped = false; float opacity = 1.f; const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode; SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState(); - shared_state->SetAll(transform, - content_bounds, - visible_content_rect, - clip_rect, - is_clipped, - opacity, - blend_mode, - 0); + shared_state->SetAll(transform, layer_bounds, visible_layer_rect, clip_rect, + is_clipped, opacity, blend_mode, 0); return shared_state; } diff --git a/chromium/cc/tiles/layer_tiling_data.cc b/chromium/cc/tiles/layer_tiling_data.cc deleted file mode 100644 index 494ded8456d..00000000000 --- a/chromium/cc/tiles/layer_tiling_data.cc +++ /dev/null @@ -1,116 +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/tiles/layer_tiling_data.h" - -#include <vector> - -#include "base/logging.h" -#include "cc/base/region.h" -#include "cc/base/simple_enclosed_region.h" - -namespace cc { - -scoped_ptr<LayerTilingData> LayerTilingData::Create(const gfx::Size& tile_size, - BorderTexelOption border) { - return make_scoped_ptr(new LayerTilingData(tile_size, border)); -} - -LayerTilingData::LayerTilingData(const gfx::Size& tile_size, - BorderTexelOption border) - : tiling_data_(tile_size, gfx::Size(), border == HAS_BORDER_TEXELS) { - SetTileSize(tile_size); -} - -LayerTilingData::~LayerTilingData() {} - -void LayerTilingData::SetTileSize(const gfx::Size& size) { - if (tile_size() == size) - return; - - reset(); - - tiling_data_.SetMaxTextureSize(size); -} - -gfx::Size LayerTilingData::tile_size() const { - return tiling_data_.max_texture_size(); -} - -void LayerTilingData::SetBorderTexelOption( - BorderTexelOption border_texel_option) { - bool border_texels = border_texel_option == HAS_BORDER_TEXELS; - if (has_border_texels() == border_texels) - return; - - reset(); - tiling_data_.SetHasBorderTexels(border_texels); -} - -const LayerTilingData& LayerTilingData::operator= - (const LayerTilingData & tiler) { - tiling_data_ = tiler.tiling_data_; - - return *this; -} - -void LayerTilingData::AddTile(scoped_ptr<Tile> tile, int i, int j) { - DCHECK(!TileAt(i, j)); - tile->move_to(i, j); - tiles_.add(std::make_pair(i, j), tile.Pass()); -} - -scoped_ptr<LayerTilingData::Tile> LayerTilingData::TakeTile(int i, int j) { - return tiles_.take_and_erase(std::make_pair(i, j)); -} - -LayerTilingData::Tile* LayerTilingData::TileAt(int i, int j) const { - return tiles_.get(std::make_pair(i, j)); -} - -void LayerTilingData::ContentRectToTileIndices(const gfx::Rect& content_rect, - int* left, - int* top, - int* right, - int* bottom) const { - // An empty rect doesn't result in an empty set of tiles, so don't pass an - // empty rect. - // TODO(enne): Possibly we should fill a vector of tiles instead, since the - // normal use of this function is to enumerate some tiles. - DCHECK(!content_rect.IsEmpty()); - - *left = tiling_data_.TileXIndexFromSrcCoord(content_rect.x()); - *top = tiling_data_.TileYIndexFromSrcCoord(content_rect.y()); - *right = tiling_data_.TileXIndexFromSrcCoord(content_rect.right() - 1); - *bottom = tiling_data_.TileYIndexFromSrcCoord(content_rect.bottom() - 1); -} - -gfx::Rect LayerTilingData::TileRect(const Tile* tile) const { - gfx::Rect tile_rect = tiling_data_.TileBoundsWithBorder(tile->i(), tile->j()); - tile_rect.set_size(tile_size()); - return tile_rect; -} - -void LayerTilingData::SetTilingSize(const gfx::Size& tiling_size) { - tiling_data_.SetTilingSize(tiling_size); - if (tiling_size.IsEmpty()) { - tiles_.clear(); - return; - } - - // Any tiles completely outside our new bounds are invalid and should be - // dropped. - int left, top, right, bottom; - ContentRectToTileIndices( - gfx::Rect(tiling_size), &left, &top, &right, &bottom); - std::vector<TileMapKey> invalid_tile_keys; - for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { - if (it->first.first > right || it->first.second > bottom) - invalid_tile_keys.push_back(it->first); - } - for (size_t i = 0; i < invalid_tile_keys.size(); ++i) - tiles_.erase(invalid_tile_keys[i]); -} - -} // namespace cc diff --git a/chromium/cc/tiles/layer_tiling_data.h b/chromium/cc/tiles/layer_tiling_data.h deleted file mode 100644 index 5e944a569bf..00000000000 --- a/chromium/cc/tiles/layer_tiling_data.h +++ /dev/null @@ -1,102 +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. - -#ifndef CC_TILES_LAYER_TILING_DATA_H_ -#define CC_TILES_LAYER_TILING_DATA_H_ - -#include <utility> - -#include "base/basictypes.h" -#include "base/containers/hash_tables.h" -#include "base/containers/scoped_ptr_hash_map.h" -#include "base/memory/scoped_ptr.h" -#include "cc/base/cc_export.h" -#include "cc/base/simple_enclosed_region.h" -#include "cc/base/tiling_data.h" -#include "ui/gfx/geometry/rect.h" - -namespace cc { - -class CC_EXPORT LayerTilingData { - public: - enum BorderTexelOption { - HAS_BORDER_TEXELS, - NO_BORDER_TEXELS - }; - - ~LayerTilingData(); - - static scoped_ptr<LayerTilingData> Create(const gfx::Size& tile_size, - BorderTexelOption option); - - bool has_empty_bounds() const { return tiling_data_.has_empty_bounds(); } - int num_tiles_x() const { return tiling_data_.num_tiles_x(); } - int num_tiles_y() const { return tiling_data_.num_tiles_y(); } - gfx::Rect tile_bounds(int i, int j) const { - return tiling_data_.TileBounds(i, j); - } - gfx::Vector2d texture_offset(int x_index, int y_index) const { - return tiling_data_.TextureOffset(x_index, y_index); - } - - // Change the tile size. This may invalidate all the existing tiles. - void SetTileSize(const gfx::Size& size); - gfx::Size tile_size() const; - // Change the border texel setting. This may invalidate all existing tiles. - void SetBorderTexelOption(BorderTexelOption option); - bool has_border_texels() const { return !!tiling_data_.border_texels(); } - - bool is_empty() const { return has_empty_bounds() || !tiles().size(); } - - const LayerTilingData& operator=(const LayerTilingData&); - - class Tile { - public: - Tile() : i_(-1), j_(-1) {} - virtual ~Tile() {} - - int i() const { return i_; } - int j() const { return j_; } - void move_to(int i, int j) { - i_ = i; - j_ = j; - } - - private: - int i_; - int j_; - DISALLOW_COPY_AND_ASSIGN(Tile); - }; - typedef std::pair<int, int> TileMapKey; - typedef base::ScopedPtrHashMap<TileMapKey, scoped_ptr<Tile>> TileMap; - - void AddTile(scoped_ptr<Tile> tile, int i, int j); - scoped_ptr<Tile> TakeTile(int i, int j); - Tile* TileAt(int i, int j) const; - const TileMap& tiles() const { return tiles_; } - - void SetTilingSize(const gfx::Size& tiling_size); - gfx::Size tiling_size() const { return tiling_data_.tiling_size(); } - - void ContentRectToTileIndices(const gfx::Rect& rect, - int* left, - int* top, - int* right, - int* bottom) const; - gfx::Rect TileRect(const Tile* tile) const; - - void reset() { tiles_.clear(); } - - protected: - LayerTilingData(const gfx::Size& tile_size, BorderTexelOption option); - - TileMap tiles_; - TilingData tiling_data_; - - DISALLOW_COPY(LayerTilingData); -}; - -} // namespace cc - -#endif // CC_TILES_LAYER_TILING_DATA_H_ diff --git a/chromium/cc/tiles/picture_layer_tiling.cc b/chromium/cc/tiles/picture_layer_tiling.cc index c585e559e8b..ef31f58256b 100644 --- a/chromium/cc/tiles/picture_layer_tiling.cc +++ b/chromium/cc/tiles/picture_layer_tiling.cc @@ -9,7 +9,10 @@ #include <limits> #include <set> +#include "base/containers/hash_tables.h" +#include "base/containers/small_map.h" #include "base/logging.h" +#include "base/numerics/safe_conversions.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/base/math_util.h" @@ -67,7 +70,8 @@ PictureLayerTiling::PictureLayerTiling( has_visible_rect_tiles_(false), has_skewport_rect_tiles_(false), has_soon_border_rect_tiles_(false), - has_eventually_rect_tiles_(false) { + has_eventually_rect_tiles_(false), + all_tiles_done_(true) { DCHECK(!raster_source->IsSolidColor()); gfx::Size content_bounds = gfx::ToCeiledSize( gfx::ScaleSize(raster_source_->GetSize(), contents_scale)); @@ -108,6 +112,7 @@ Tile* PictureLayerTiling::CreateTile(int i, int j) { if (!raster_source_->CoversRect(tile_rect, contents_scale_)) return nullptr; + all_tiles_done_ = false; ScopedTilePtr tile = client_->CreateTile(contents_scale_, tile_rect); Tile* raw_ptr = tile.get(); tile->set_tiling_index(i, j); @@ -120,13 +125,13 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { for (TilingData::Iterator iter(&tiling_data_, live_tiles_rect_, include_borders); iter; ++iter) { - TileMapKey key = iter.index(); + TileMapKey key(iter.index()); TileMap::iterator find = tiles_.find(key); if (find != tiles_.end()) continue; - if (ShouldCreateTileAt(key.first, key.second)) - CreateTile(key.first, key.second); + if (ShouldCreateTileAt(key.index_x, key.index_y)) + CreateTile(key.index_x, key.index_y); } VerifyLiveTilesRect(false); } @@ -150,13 +155,16 @@ void PictureLayerTiling::TakeTilesAndPropertiesFrom( if (tiles_.empty()) { tiles_.swap(pending_twin->tiles_); + all_tiles_done_ = pending_twin->all_tiles_done_; } else { while (!pending_twin->tiles_.empty()) { TileMapKey key = pending_twin->tiles_.begin()->first; tiles_.set(key, pending_twin->tiles_.take_and_erase(key)); } + all_tiles_done_ &= pending_twin->all_tiles_done_; } DCHECK(pending_twin->tiles_.empty()); + pending_twin->all_tiles_done_ = true; if (create_missing_tiles) CreateMissingTilesInLiveTilesRect(); @@ -259,39 +267,53 @@ void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_invalidation, // twin, so it's slated for removal in the future. if (live_tiles_rect_.IsEmpty()) return; - std::vector<TileMapKey> new_tile_keys; + // Pick 16 for the size of the SmallMap before it promotes to a hash_map. + // 4x4 tiles should cover most small invalidations, and walking a vector of + // 16 is fast enough. If an invalidation is huge we will fall back to a + // hash_map instead of a vector in the SmallMap. + base::SmallMap<base::hash_map<TileMapKey, gfx::Rect>, 16> remove_tiles; gfx::Rect expanded_live_tiles_rect = tiling_data_.ExpandRectIgnoringBordersToTileBounds(live_tiles_rect_); for (Region::Iterator iter(layer_invalidation); iter.has_rect(); iter.next()) { gfx::Rect layer_rect = iter.rect(); - gfx::Rect content_rect = + // The pixels which are invalid in content space. + gfx::Rect invalid_content_rect = gfx::ScaleToEnclosingRect(layer_rect, contents_scale_); // Consider tiles inside the live tiles rect even if only their border // pixels intersect the invalidation. But don't consider tiles outside // the live tiles rect with the same conditions, as they won't exist. + gfx::Rect coverage_content_rect = invalid_content_rect; int border_pixels = tiling_data_.border_texels(); - content_rect.Inset(-border_pixels, -border_pixels); + coverage_content_rect.Inset(-border_pixels, -border_pixels); // Avoid needless work by not bothering to invalidate where there aren't // tiles. - content_rect.Intersect(expanded_live_tiles_rect); - if (content_rect.IsEmpty()) + coverage_content_rect.Intersect(expanded_live_tiles_rect); + if (coverage_content_rect.IsEmpty()) continue; // Since the content_rect includes border pixels already, don't include // borders when iterating to avoid double counting them. bool include_borders = false; - for ( - TilingData::Iterator iter(&tiling_data_, content_rect, include_borders); - iter; ++iter) { - if (RemoveTileAt(iter.index_x(), iter.index_y())) { - if (recreate_tiles) - new_tile_keys.push_back(iter.index()); - } + for (TilingData::Iterator iter(&tiling_data_, coverage_content_rect, + include_borders); + iter; ++iter) { + // This also adds the TileMapKey to the map. + remove_tiles[TileMapKey(iter.index())].Union(invalid_content_rect); } } - for (const auto& key : new_tile_keys) - CreateTile(key.first, key.second); + for (const auto& pair : remove_tiles) { + const TileMapKey& key = pair.first; + const gfx::Rect& invalid_content_rect = pair.second; + // TODO(danakj): This old_tile will not exist if we are committing to a + // pending tree since there is no tile there to remove, which prevents + // tiles from knowing the invalidation rect and content id. crbug.com/490847 + ScopedTilePtr old_tile = TakeTileAt(key.index_x, key.index_y); + if (recreate_tiles && old_tile) { + if (Tile* tile = CreateTile(key.index_x, key.index_y)) + tile->SetInvalidated(invalid_content_rect, old_tile->id()); + } + } } bool PictureLayerTiling::ShouldCreateTileAt(int i, int j) const { @@ -489,6 +511,13 @@ gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const { return texture_rect; } +ScopedTilePtr PictureLayerTiling::TakeTileAt(int i, int j) { + TileMap::iterator found = tiles_.find(TileMapKey(i, j)); + if (found == tiles_.end()) + return nullptr; + return tiles_.take_and_erase(found); +} + bool PictureLayerTiling::RemoveTileAt(int i, int j) { TileMap::iterator found = tiles_.find(TileMapKey(i, j)); if (found == tiles_.end()) @@ -500,6 +529,7 @@ bool PictureLayerTiling::RemoveTileAt(int i, int j) { void PictureLayerTiling::Reset() { live_tiles_rect_ = gfx::Rect(); tiles_.clear(); + all_tiles_done_ = true; } gfx::Rect PictureLayerTiling::ComputeSkewport( @@ -566,13 +596,19 @@ bool PictureLayerTiling::ComputeTilePriorityRects( float ideal_contents_scale, double current_frame_time_in_seconds, const Occlusion& occlusion_in_layer_space) { + // If we have, or had occlusions, mark the tiles as 'not done' to ensure that + // we reiterate the tiles for rasterization. + if (occlusion_in_layer_space.HasOcclusion() || + current_occlusion_in_layer_space_.HasOcclusion()) { + set_all_tiles_done(false); + } + if (!NeedsUpdateForFrameAtTimeAndViewport(current_frame_time_in_seconds, viewport_in_layer_space)) { // This should never be zero for the purposes of has_ever_been_updated(). DCHECK_NE(current_frame_time_in_seconds, 0.0); return false; } - gfx::Rect visible_rect_in_content_space = gfx::ScaleToEnclosingRect(viewport_in_layer_space, contents_scale_); @@ -665,8 +701,8 @@ void PictureLayerTiling::SetLiveTilesRect( live_tiles_rect_); iter; ++iter) { TileMapKey key(iter.index()); - if (ShouldCreateTileAt(key.first, key.second)) - CreateTile(key.first, key.second); + if (ShouldCreateTileAt(key.index_x, key.index_y)) + CreateTile(key.index_x, key.index_y); } live_tiles_rect_ = new_live_tiles_rect; @@ -678,19 +714,19 @@ void PictureLayerTiling::VerifyLiveTilesRect(bool is_on_recycle_tree) const { for (auto it = tiles_.begin(); it != tiles_.end(); ++it) { if (!it->second) continue; - DCHECK(it->first.first < tiling_data_.num_tiles_x()) - << this << " " << it->first.first << "," << it->first.second - << " num_tiles_x " << tiling_data_.num_tiles_x() << " live_tiles_rect " + TileMapKey key = it->first; + DCHECK(key.index_x < tiling_data_.num_tiles_x()) + << this << " " << key.index_x << "," << key.index_y << " num_tiles_x " + << tiling_data_.num_tiles_x() << " live_tiles_rect " << live_tiles_rect_.ToString(); - DCHECK(it->first.second < tiling_data_.num_tiles_y()) - << this << " " << it->first.first << "," << it->first.second - << " num_tiles_y " << tiling_data_.num_tiles_y() << " live_tiles_rect " + DCHECK(key.index_y < tiling_data_.num_tiles_y()) + << this << " " << key.index_x << "," << key.index_y << " num_tiles_y " + << tiling_data_.num_tiles_y() << " live_tiles_rect " << live_tiles_rect_.ToString(); - DCHECK(tiling_data_.TileBounds(it->first.first, it->first.second) + DCHECK(tiling_data_.TileBounds(key.index_x, key.index_y) .Intersects(live_tiles_rect_)) - << this << " " << it->first.first << "," << it->first.second - << " tile bounds " - << tiling_data_.TileBounds(it->first.first, it->first.second).ToString() + << this << " " << key.index_x << "," << key.index_y << " tile bounds " + << tiling_data_.TileBounds(key.index_x, key.index_y).ToString() << " live_tiles_rect " << live_tiles_rect_.ToString(); } #endif @@ -845,25 +881,22 @@ TilePriority PictureLayerTiling::ComputePriorityForTile( const Tile* tile, PriorityRectType priority_rect_type) const { // TODO(vmpstr): See if this can be moved to iterators. - TilePriority::PriorityBin max_tile_priority_bin = - client_->GetMaxTilePriorityBin(); - DCHECK_EQ(ComputePriorityRectTypeForTile(tile), priority_rect_type); DCHECK_EQ(TileAt(tile->tiling_i_index(), tile->tiling_j_index()), tile); - TilePriority::PriorityBin priority_bin = max_tile_priority_bin; - + TilePriority::PriorityBin priority_bin = client_->HasValidTilePriorities() + ? TilePriority::NOW + : TilePriority::EVENTUALLY; switch (priority_rect_type) { case VISIBLE_RECT: return TilePriority(resolution_, priority_bin, 0); case PENDING_VISIBLE_RECT: - if (max_tile_priority_bin <= TilePriority::SOON) - return TilePriority(resolution_, TilePriority::SOON, 0); - priority_bin = TilePriority::EVENTUALLY; - break; + if (priority_bin < TilePriority::SOON) + priority_bin = TilePriority::SOON; + return TilePriority(resolution_, priority_bin, 0); case SKEWPORT_RECT: case SOON_BORDER_RECT: - if (max_tile_priority_bin <= TilePriority::SOON) + if (priority_bin < TilePriority::SOON) priority_bin = TilePriority::SOON; break; case EVENTUALLY_RECT: @@ -914,7 +947,7 @@ void PictureLayerTiling::GetAllPrioritizedTilesForTracing( void PictureLayerTiling::AsValueInto( base::trace_event::TracedValue* state) const { - state->SetInteger("num_tiles", tiles_.size()); + state->SetInteger("num_tiles", base::saturated_cast<int>(tiles_.size())); state->SetDouble("content_scale", contents_scale_); MathUtil::AddToTracedValue("visible_rect", current_visible_rect_, state); MathUtil::AddToTracedValue("skewport_rect", current_skewport_rect_, state); diff --git a/chromium/cc/tiles/picture_layer_tiling.h b/chromium/cc/tiles/picture_layer_tiling.h index 33a81879f20..721f9e1e340 100644 --- a/chromium/cc/tiles/picture_layer_tiling.h +++ b/chromium/cc/tiles/picture_layer_tiling.h @@ -45,13 +45,42 @@ class CC_EXPORT PictureLayerTilingClient { virtual const Region* GetPendingInvalidation() = 0; virtual const PictureLayerTiling* GetPendingOrActiveTwinTiling( const PictureLayerTiling* tiling) const = 0; - virtual TilePriority::PriorityBin GetMaxTilePriorityBin() const = 0; + virtual bool HasValidTilePriorities() const = 0; virtual bool RequiresHighResToDraw() const = 0; protected: virtual ~PictureLayerTilingClient() {} }; +struct TileMapKey { + TileMapKey(int x, int y) : index_x(x), index_y(y) {} + explicit TileMapKey(const std::pair<int, int>& index) + : index_x(index.first), index_y(index.second) {} + + bool operator==(const TileMapKey& other) const { + return index_x == other.index_x && index_y == other.index_y; + } + + int index_x; + int index_y; +}; + +} // namespace cc + +namespace BASE_HASH_NAMESPACE { +template <> +struct hash<cc::TileMapKey> { + size_t operator()(const cc::TileMapKey& key) const { + uint16 value1 = static_cast<uint16>(key.index_x); + uint16 value2 = static_cast<uint16>(key.index_y); + uint32 value1_32 = value1; + return (value1_32 << 16) | value2; + } +}; +} // namespace BASE_HASH_NAMESPACE + +namespace cc { + class CC_EXPORT PictureLayerTiling { public: static const int kBorderTexels = 1; @@ -101,6 +130,20 @@ class CC_EXPORT PictureLayerTiling { } bool has_tiles() const { return !tiles_.empty(); } + // all_tiles_done() can return false negatives. + bool all_tiles_done() const { return all_tiles_done_; } + void set_all_tiles_done(bool all_tiles_done) { + all_tiles_done_ = all_tiles_done; + } + + void VerifyNoTileNeedsRaster() const { +#if DCHECK_IS_ON() + for (const auto tile_pair : tiles_) { + DCHECK(!tile_pair.second->draw_info().NeedsRaster() || + IsTileOccluded(tile_pair.second)); + } +#endif // DCHECK_IS_ON() + } // For testing functionality. void CreateAllTilesForTesting() { @@ -132,6 +175,14 @@ class CC_EXPORT PictureLayerTiling { const gfx::Rect& GetCurrentVisibleRectForTesting() const { return current_visible_rect_; } + void SetTilePriorityRectsForTesting( + const gfx::Rect& visible_rect_in_content_space, + const gfx::Rect& skewport, + const gfx::Rect& soon_border_rect, + const gfx::Rect& eventually_rect) { + SetTilePriorityRects(1.0f, visible_rect_in_content_space, skewport, + soon_border_rect, eventually_rect, Occlusion()); + } // Iterate over all tiles to fill content_rect. Even if tiles are invalid // (i.e. no valid resource) this tiling should still iterate over them. @@ -225,7 +276,6 @@ class CC_EXPORT PictureLayerTiling { EVENTUALLY_RECT }; - using TileMapKey = std::pair<int, int>; using TileMap = base::ScopedPtrHashMap<TileMapKey, ScopedTilePtr>; struct FrameVisibleRect { @@ -243,6 +293,7 @@ class CC_EXPORT PictureLayerTiling { void SetLiveTilesRect(const gfx::Rect& live_tiles_rect); void VerifyLiveTilesRect(bool is_on_recycle_tree) const; Tile* CreateTile(int i, int j); + ScopedTilePtr TakeTileAt(int i, int j); // Returns true if the Tile existed and was removed from the tiling. bool RemoveTileAt(int i, int j); bool TilingMatchesTileIndices(const PictureLayerTiling* twin) const; @@ -359,6 +410,7 @@ class CC_EXPORT PictureLayerTiling { bool has_skewport_rect_tiles_; bool has_soon_border_rect_tiles_; bool has_eventually_rect_tiles_; + bool all_tiles_done_; private: DISALLOW_ASSIGN(PictureLayerTiling); diff --git a/chromium/cc/tiles/picture_layer_tiling_perftest.cc b/chromium/cc/tiles/picture_layer_tiling_perftest.cc index 0aae512030e..f27c227edcc 100644 --- a/chromium/cc/tiles/picture_layer_tiling_perftest.cc +++ b/chromium/cc/tiles/picture_layer_tiling_perftest.cc @@ -9,9 +9,11 @@ #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_picture_layer_tiling_client.h" #include "cc/test/fake_picture_pile_impl.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/test_context_provider.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/tiles/picture_layer_tiling.h" +#include "cc/trees/layer_tree_settings.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" @@ -35,13 +37,8 @@ class PictureLayerTilingPerfTest : public testing::Test { CHECK(output_surface_->BindToClient(&output_surface_client_)); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - resource_provider_ = ResourceProvider::Create(output_surface_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1).Pass(); + resource_provider_ = FakeResourceProvider::Create( + output_surface_.get(), shared_bitmap_manager_.get()); } void SetUp() override { diff --git a/chromium/cc/tiles/picture_layer_tiling_set.cc b/chromium/cc/tiles/picture_layer_tiling_set.cc index b794b137ff0..c820e81ce1a 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set.cc +++ b/chromium/cc/tiles/picture_layer_tiling_set.cc @@ -137,8 +137,14 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForCommit( // Invalidate tiles and update them to the new raster source. for (PictureLayerTiling* tiling : tilings_) { + DCHECK_IMPLIES(tree_ == PENDING_TREE, !tiling->has_tiles()); tiling->SetRasterSourceAndResize(raster_source); - tiling->Invalidate(layer_invalidation); + + // We can commit on either active or pending trees, but only active one can + // have tiles at this point. + if (tree_ == ACTIVE_TREE) + tiling->Invalidate(layer_invalidation); + // This is needed for cases where the live tiles rect didn't change but // recordings exist in the raster source that did not exist on the last // raster source. @@ -192,8 +198,7 @@ void PictureLayerTilingSet::CleanUpTilings( float max_acceptable_high_res_scale, const std::vector<PictureLayerTiling*>& needed_tilings, bool should_have_low_res, - PictureLayerTilingSet* twin_set, - PictureLayerTilingSet* recycled_twin_set) { + PictureLayerTilingSet* twin_set) { float twin_low_res_scale = 0.f; if (twin_set) { PictureLayerTiling* tiling = @@ -227,15 +232,6 @@ void PictureLayerTilingSet::CleanUpTilings( } for (auto* tiling : to_remove) { - PictureLayerTiling* recycled_twin_tiling = - recycled_twin_set - ? recycled_twin_set->FindTilingWithScale(tiling->contents_scale()) - : nullptr; - // Remove the tiling from the recycle tree. Note that we ignore resolution, - // since we don't need to maintain high/low res on the recycle set. - if (recycled_twin_tiling) - recycled_twin_set->Remove(recycled_twin_tiling); - DCHECK_NE(HIGH_RESOLUTION, tiling->resolution()); Remove(tiling); } @@ -386,12 +382,11 @@ PictureLayerTilingSet::CoverageIterator::CoverageIterator( : set_(set), contents_scale_(contents_scale), ideal_contents_scale_(ideal_contents_scale), - current_tiling_(-1) { + current_tiling_(std::numeric_limits<size_t>::max()) { missing_region_.Union(content_rect); - for (ideal_tiling_ = 0; - static_cast<size_t>(ideal_tiling_) < set_->tilings_.size(); - ++ideal_tiling_) { + size_t tilings_size = set_->tilings_.size(); + for (ideal_tiling_ = 0; ideal_tiling_ < tilings_size; ++ideal_tiling_) { PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_]; if (tiling->contents_scale() < ideal_contents_scale_) { if (ideal_tiling_ > 0) @@ -400,11 +395,7 @@ PictureLayerTilingSet::CoverageIterator::CoverageIterator( } } - DCHECK_LE(set_->tilings_.size(), - static_cast<size_t>(std::numeric_limits<int>::max())); - - int num_tilings = set_->tilings_.size(); - if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0) + if (ideal_tiling_ == tilings_size && ideal_tiling_ > 0) ideal_tiling_--; ++(*this); @@ -448,20 +439,20 @@ TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const { PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() const { - if (current_tiling_ < 0) + if (current_tiling_ == std::numeric_limits<size_t>::max()) return NULL; - if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size()) + if (current_tiling_ >= set_->tilings_.size()) return NULL; return set_->tilings_[current_tiling_]; } -int PictureLayerTilingSet::CoverageIterator::NextTiling() const { +size_t PictureLayerTilingSet::CoverageIterator::NextTiling() const { // Order returned by this method is: // 1. Ideal tiling index // 2. Tiling index < Ideal in decreasing order (higher res than ideal) // 3. Tiling index > Ideal in increasing order (lower res than ideal) // 4. Tiling index > tilings.size() (invalid index) - if (current_tiling_ < 0) + if (current_tiling_ == std::numeric_limits<size_t>::max()) return ideal_tiling_; else if (current_tiling_ > ideal_tiling_) return current_tiling_ + 1; @@ -473,7 +464,7 @@ int PictureLayerTilingSet::CoverageIterator::NextTiling() const { PictureLayerTilingSet::CoverageIterator& PictureLayerTilingSet::CoverageIterator::operator++() { - bool first_time = current_tiling_ < 0; + bool first_time = current_tiling_ == std::numeric_limits<size_t>::max(); if (!*this && !first_time) return *this; @@ -507,7 +498,7 @@ PictureLayerTilingSet::CoverageIterator::operator++() { } // No more valid tiles, return this checkerboard rect. - if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) + if (current_tiling_ >= set_->tilings_.size()) return *this; } @@ -517,7 +508,7 @@ PictureLayerTilingSet::CoverageIterator::operator++() { region_iter_.next(); // Done, found next checkerboard rect to return. - if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) + if (current_tiling_ >= set_->tilings_.size()) return *this; // Construct a new iterator for the next tiling, but we need to loop @@ -532,8 +523,7 @@ PictureLayerTilingSet::CoverageIterator::operator++() { } PictureLayerTilingSet::CoverageIterator::operator bool() const { - return current_tiling_ < static_cast<int>(set_->tilings_.size()) || - region_iter_.has_rect(); + return current_tiling_ < set_->tilings_.size() || region_iter_.has_rect(); } void PictureLayerTilingSet::AsValueInto( @@ -557,9 +547,10 @@ PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange( // Doesn't seem to be the case right now but if it ever becomes a performance // problem to compute these ranges each time this function is called, we can // compute them only when the tiling set has changed instead. + size_t tilings_size = tilings_.size(); TilingRange high_res_range(0, 0); TilingRange low_res_range(tilings_.size(), tilings_.size()); - for (size_t i = 0; i < tilings_.size(); ++i) { + for (size_t i = 0; i < tilings_size; ++i) { const PictureLayerTiling* tiling = tilings_[i]; if (tiling->resolution() == HIGH_RESOLUTION) high_res_range = TilingRange(i, i + 1); @@ -591,7 +582,7 @@ PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange( range = low_res_range; break; case LOWER_THAN_LOW_RES: - range = TilingRange(low_res_range.end, tilings_.size()); + range = TilingRange(low_res_range.end, tilings_size); break; } diff --git a/chromium/cc/tiles/picture_layer_tiling_set.h b/chromium/cc/tiles/picture_layer_tiling_set.h index 2347d53798d..dcaf77586ff 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set.h +++ b/chromium/cc/tiles/picture_layer_tiling_set.h @@ -31,10 +31,10 @@ class CC_EXPORT PictureLayerTilingSet { LOWER_THAN_LOW_RES }; struct TilingRange { - TilingRange(int start, int end) : start(start), end(end) {} + TilingRange(size_t start, size_t end) : start(start), end(end) {} - int start; - int end; + size_t start; + size_t end; }; static scoped_ptr<PictureLayerTilingSet> Create( @@ -52,8 +52,7 @@ class CC_EXPORT PictureLayerTilingSet { float max_acceptable_high_res_scale, const std::vector<PictureLayerTiling*>& needed_tilings, bool should_have_low_res, - PictureLayerTilingSet* twin_set, - PictureLayerTilingSet* recycled_twin_set); + PictureLayerTilingSet* twin_set); void RemoveNonIdealTilings(); // This function is called on the active tree during activation. @@ -153,14 +152,14 @@ class CC_EXPORT PictureLayerTilingSet { PictureLayerTiling* CurrentTiling() const; private: - int NextTiling() const; + size_t NextTiling() const; const PictureLayerTilingSet* set_; float contents_scale_; float ideal_contents_scale_; PictureLayerTiling::CoverageIterator tiling_iter_; - int current_tiling_; - int ideal_tiling_; + size_t current_tiling_; + size_t ideal_tiling_; Region current_region_; Region missing_region_; diff --git a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc index c04870e3d16..e7593cde80b 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc +++ b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc @@ -12,7 +12,9 @@ #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_picture_layer_tiling_client.h" #include "cc/test/fake_picture_pile_impl.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/test_shared_bitmap_manager.h" +#include "cc/trees/layer_tree_settings.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/size_conversions.h" @@ -86,26 +88,26 @@ TEST(PictureLayerTilingSetTest, TilingRange) { higher_than_high_res_range = set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0, higher_than_high_res_range.start); - EXPECT_EQ(1, higher_than_high_res_range.end); + EXPECT_EQ(0u, higher_than_high_res_range.start); + EXPECT_EQ(1u, higher_than_high_res_range.end); high_res_range = set->GetTilingRange(PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(1, high_res_range.start); - EXPECT_EQ(2, high_res_range.end); + EXPECT_EQ(1u, high_res_range.start); + EXPECT_EQ(2u, high_res_range.end); between_high_and_low_res_range = set->GetTilingRange(PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(2, between_high_and_low_res_range.start); - EXPECT_EQ(3, between_high_and_low_res_range.end); + EXPECT_EQ(2u, between_high_and_low_res_range.start); + EXPECT_EQ(3u, between_high_and_low_res_range.end); low_res_range = set->GetTilingRange(PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(3, low_res_range.start); - EXPECT_EQ(4, low_res_range.end); + EXPECT_EQ(3u, low_res_range.start); + EXPECT_EQ(4u, low_res_range.end); lower_than_low_res_range = set->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(4, lower_than_low_res_range.start); - EXPECT_EQ(5, lower_than_low_res_range.end); + EXPECT_EQ(4u, lower_than_low_res_range.start); + EXPECT_EQ(5u, lower_than_low_res_range.end); scoped_ptr<PictureLayerTilingSet> set_without_low_res = CreateTilingSet(&client); @@ -117,26 +119,26 @@ TEST(PictureLayerTilingSetTest, TilingRange) { higher_than_high_res_range = set_without_low_res->GetTilingRange( PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0, higher_than_high_res_range.start); - EXPECT_EQ(1, higher_than_high_res_range.end); + EXPECT_EQ(0u, higher_than_high_res_range.start); + EXPECT_EQ(1u, higher_than_high_res_range.end); high_res_range = set_without_low_res->GetTilingRange(PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(1, high_res_range.start); - EXPECT_EQ(2, high_res_range.end); + EXPECT_EQ(1u, high_res_range.start); + EXPECT_EQ(2u, high_res_range.end); between_high_and_low_res_range = set_without_low_res->GetTilingRange( PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(2, between_high_and_low_res_range.start); - EXPECT_EQ(4, between_high_and_low_res_range.end); + EXPECT_EQ(2u, between_high_and_low_res_range.start); + EXPECT_EQ(4u, between_high_and_low_res_range.end); low_res_range = set_without_low_res->GetTilingRange(PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(0, low_res_range.end - low_res_range.start); + EXPECT_EQ(0u, low_res_range.end - low_res_range.start); lower_than_low_res_range = set_without_low_res->GetTilingRange( PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(0, lower_than_low_res_range.end - lower_than_low_res_range.start); + EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); scoped_ptr<PictureLayerTilingSet> set_with_only_high_and_low_res = CreateTilingSet(&client); @@ -147,28 +149,28 @@ TEST(PictureLayerTilingSetTest, TilingRange) { higher_than_high_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0, + EXPECT_EQ(0u, higher_than_high_res_range.end - higher_than_high_res_range.start); high_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(0, high_res_range.start); - EXPECT_EQ(1, high_res_range.end); + EXPECT_EQ(0u, high_res_range.start); + EXPECT_EQ(1u, high_res_range.end); between_high_and_low_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(0, between_high_and_low_res_range.end - - between_high_and_low_res_range.start); + EXPECT_EQ(0u, between_high_and_low_res_range.end - + between_high_and_low_res_range.start); low_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(1, low_res_range.start); - EXPECT_EQ(2, low_res_range.end); + EXPECT_EQ(1u, low_res_range.start); + EXPECT_EQ(2u, low_res_range.end); lower_than_low_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(0, lower_than_low_res_range.end - lower_than_low_res_range.start); + EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); scoped_ptr<PictureLayerTilingSet> set_with_only_high_res = CreateTilingSet(&client); @@ -177,26 +179,26 @@ TEST(PictureLayerTilingSetTest, TilingRange) { higher_than_high_res_range = set_with_only_high_res->GetTilingRange( PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0, + EXPECT_EQ(0u, higher_than_high_res_range.end - higher_than_high_res_range.start); high_res_range = set_with_only_high_res->GetTilingRange(PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(0, high_res_range.start); - EXPECT_EQ(1, high_res_range.end); + EXPECT_EQ(0u, high_res_range.start); + EXPECT_EQ(1u, high_res_range.end); between_high_and_low_res_range = set_with_only_high_res->GetTilingRange( PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(0, between_high_and_low_res_range.end - - between_high_and_low_res_range.start); + EXPECT_EQ(0u, between_high_and_low_res_range.end - + between_high_and_low_res_range.start); low_res_range = set_with_only_high_res->GetTilingRange(PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(0, low_res_range.end - low_res_range.start); + EXPECT_EQ(0u, low_res_range.end - low_res_range.start); lower_than_low_res_range = set_with_only_high_res->GetTilingRange( PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(0, lower_than_low_res_range.end - lower_than_low_res_range.start); + EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); } class PictureLayerTilingSetTestWithResources : public testing::Test { @@ -214,13 +216,8 @@ class PictureLayerTilingSetTestWithResources : public testing::Test { scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); scoped_ptr<ResourceProvider> resource_provider = - ResourceProvider::Create(output_surface.get(), - shared_bitmap_manager.get(), - NULL, - NULL, - 0, - false, - 1); + FakeResourceProvider::Create(output_surface.get(), + shared_bitmap_manager.get()); FakePictureLayerTilingClient client(resource_provider.get()); client.SetTileSize(gfx::Size(256, 256)); @@ -334,6 +331,12 @@ TEST(PictureLayerTilingSetTest, TileSizeChange) { EXPECT_EQ(tile_size1, tile->content_rect().size()); // Update to a new source frame with a new tile size. + // Note that setting a new raster source can typically only happen after + // activation, since we can't set the raster source twice on the pending tree + // without activating. For test, just remove and add a new tiling instead. + pending_set->RemoveAllTilings(); + pending_set->AddTiling(1.f, pile); + pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION); pending_client.SetTileSize(tile_size2); pending_set->UpdateTilingsToCurrentRasterSourceForCommit(pile.get(), Region(), 1.f, 1.f); diff --git a/chromium/cc/tiles/picture_layer_tiling_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_unittest.cc index e19f9303014..1c8a3978eb2 100644 --- a/chromium/cc/tiles/picture_layer_tiling_unittest.cc +++ b/chromium/cc/tiles/picture_layer_tiling_unittest.cc @@ -14,6 +14,7 @@ #include "cc/test/test_shared_bitmap_manager.h" #include "cc/tiles/picture_layer_tiling.h" #include "cc/tiles/picture_layer_tiling_set.h" +#include "cc/trees/layer_tree_settings.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/quad_f.h" #include "ui/gfx/geometry/rect_conversions.h" diff --git a/chromium/cc/tiles/tile.cc b/chromium/cc/tiles/tile.cc index da4c08018d5..6052e5e0457 100644 --- a/chromium/cc/tiles/tile.cc +++ b/chromium/cc/tiles/tile.cc @@ -6,6 +6,7 @@ #include <algorithm> +#include "base/numerics/safe_conversions.h" #include "base/trace_event/trace_event_argument.h" #include "cc/base/math_util.h" #include "cc/debug/traced_value.h" @@ -13,7 +14,7 @@ namespace cc { -Tile::Id Tile::s_next_id_ = 0; +Tile::Id Tile::s_next_id_ = 1; Tile::Tile(TileManager* tile_manager, const gfx::Size& desired_texture_size, @@ -34,6 +35,7 @@ Tile::Tile(TileManager* tile_manager, required_for_activation_(false), required_for_draw_(false), id_(s_next_id_++), + invalidated_id_(0), scheduled_priority_(0) { } @@ -61,12 +63,17 @@ void Tile::AsValueInto(base::trace_event::TracedValue* value) const { draw_info().has_resource() || HasRasterTask()); value->SetInteger("scheduled_priority", scheduled_priority_); value->SetBoolean("use_picture_analysis", use_picture_analysis()); - value->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes()); + value->SetInteger("gpu_memory_usage", + base::saturated_cast<int>(GPUMemoryUsageInBytes())); } size_t Tile::GPUMemoryUsageInBytes() const { - if (draw_info_.resource_) - return draw_info_.resource_->bytes(); + if (draw_info_.resource_) { + // We can use UncheckedSizeInBytes, since the tile size is determined by the + // compositor. + return Resource::UncheckedMemorySizeBytes(draw_info_.resource_->size(), + draw_info_.resource_->format()); + } return 0; } diff --git a/chromium/cc/tiles/tile.h b/chromium/cc/tiles/tile.h index 68c4fc13e34..e53c2ac52f8 100644 --- a/chromium/cc/tiles/tile.h +++ b/chromium/cc/tiles/tile.h @@ -68,6 +68,17 @@ class CC_EXPORT Tile { int tiling_i_index() const { return tiling_i_index_; } int tiling_j_index() const { return tiling_j_index_; } + void SetInvalidated(const gfx::Rect& invalid_content_rect, + Id previous_tile_id) { + invalidated_content_rect_ = invalid_content_rect; + invalidated_id_ = previous_tile_id; + } + + Id invalidated_id() const { return invalidated_id_; } + const gfx::Rect& invalidated_content_rect() const { + return invalidated_content_rect_; + } + private: friend class TileManager; friend class FakeTileManager; @@ -103,6 +114,12 @@ class CC_EXPORT Tile { Id id_; static Id s_next_id_; + // The rect bounding the changes in this Tile vs the previous tile it + // replaced. + gfx::Rect invalidated_content_rect_; + // The |id_| of the Tile that was invalidated and replaced by this tile. + Id invalidated_id_; + unsigned scheduled_priority_; scoped_refptr<RasterTask> raster_task_; diff --git a/chromium/cc/tiles/tile_draw_info.cc b/chromium/cc/tiles/tile_draw_info.cc index e523079aac9..6b12e73f5c6 100644 --- a/chromium/cc/tiles/tile_draw_info.cc +++ b/chromium/cc/tiles/tile_draw_info.cc @@ -4,16 +4,25 @@ #include "cc/tiles/tile_draw_info.h" +#include "base/metrics/histogram.h" #include "cc/base/math_util.h" namespace cc { TileDrawInfo::TileDrawInfo() - : mode_(RESOURCE_MODE), solid_color_(SK_ColorWHITE) { + : mode_(RESOURCE_MODE), + solid_color_(SK_ColorWHITE), + contents_swizzled_(false), + was_ever_ready_to_draw_(false), + was_ever_used_to_draw_(false) { } TileDrawInfo::~TileDrawInfo() { DCHECK(!resource_); + if (was_ever_ready_to_draw_) { + UMA_HISTOGRAM_BOOLEAN("Renderer4.ReadyToDrawTileDrawStatus", + was_ever_used_to_draw_); + } } void TileDrawInfo::AsValueInto(base::trace_event::TracedValue* state) const { diff --git a/chromium/cc/tiles/tile_draw_info.h b/chromium/cc/tiles/tile_draw_info.h index f094efd6f38..dcb755ad34e 100644 --- a/chromium/cc/tiles/tile_draw_info.h +++ b/chromium/cc/tiles/tile_draw_info.h @@ -48,7 +48,7 @@ class CC_EXPORT TileDrawInfo { return false; } - ResourceProvider::ResourceId resource_id() const { + ResourceId resource_id() const { DCHECK(mode_ == RESOURCE_MODE); DCHECK(resource_); return resource_->id(); @@ -65,10 +65,7 @@ class CC_EXPORT TileDrawInfo { return solid_color_; } - bool contents_swizzled() const { - DCHECK(resource_); - return !PlatformColor::SameComponentOrder(resource_->format()); - } + bool contents_swizzled() const { return contents_swizzled_; } bool requires_resource() const { return mode_ == RESOURCE_MODE || mode_ == OOM_MODE; @@ -83,6 +80,9 @@ class CC_EXPORT TileDrawInfo { void AsValueInto(base::trace_event::TracedValue* state) const; + void set_was_ever_ready_to_draw() { was_ever_ready_to_draw_ = true; } + void set_was_ever_used_to_draw() { was_ever_used_to_draw_ = true; } + private: friend class Tile; friend class TileManager; @@ -99,6 +99,11 @@ class CC_EXPORT TileDrawInfo { Mode mode_; SkColor solid_color_; scoped_ptr<ScopedResource> resource_; + bool contents_swizzled_; + + // Used for gathering UMA stats. + bool was_ever_ready_to_draw_; + bool was_ever_used_to_draw_; }; } // namespace cc diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc index a67563a4402..23d2eca12bc 100644 --- a/chromium/cc/tiles/tile_manager.cc +++ b/chromium/cc/tiles/tile_manager.cc @@ -12,7 +12,9 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/metrics/histogram.h" +#include "base/numerics/safe_conversions.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/histograms.h" #include "cc/debug/devtools_instrumentation.h" #include "cc/debug/frame_viewer_instrumentation.h" #include "cc/debug/traced_value.h" @@ -29,16 +31,26 @@ namespace { // a tile is of solid color. const bool kUseColorEstimator = true; +DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER( + ScopedRasterTaskTimer, + "Compositing.RasterTask.RasterUs", + "Compositing.RasterTask.RasterPixelsPerMs"); + class RasterTaskImpl : public RasterTask { public: RasterTaskImpl( const Resource* resource, RasterSource* raster_source, const gfx::Rect& content_rect, + const gfx::Rect& invalid_content_rect, float contents_scale, TileResolution tile_resolution, int layer_id, - const void* tile_id, + uint64_t source_prepare_tiles_id, + const void* tile, + uint64_t new_content_id, + uint64_t previous_content_id, + uint64_t resource_content_id, int source_frame_number, bool analyze_picture, const base::Callback<void(const RasterSource::SolidColorAnalysis&, bool)>& @@ -47,17 +59,23 @@ class RasterTaskImpl : public RasterTask { : RasterTask(resource, dependencies), raster_source_(raster_source), content_rect_(content_rect), + invalid_content_rect_(invalid_content_rect), contents_scale_(contents_scale), tile_resolution_(tile_resolution), layer_id_(layer_id), - tile_id_(tile_id), + source_prepare_tiles_id_(source_prepare_tiles_id), + tile_(tile), + new_content_id_(new_content_id), + previous_content_id_(previous_content_id), + resource_content_id_(resource_content_id), source_frame_number_(source_frame_number), analyze_picture_(analyze_picture), reply_(reply) {} // Overridden from Task: void RunOnWorkerThread() override { - TRACE_EVENT0("cc", "RasterizerTaskImpl::RunOnWorkerThread"); + TRACE_EVENT1("cc", "RasterizerTaskImpl::RunOnWorkerThread", + "source_prepare_tiles_id", source_prepare_tiles_id_); DCHECK(raster_source_.get()); DCHECK(raster_buffer_); @@ -74,7 +92,8 @@ class RasterTaskImpl : public RasterTask { // Overridden from TileTask: void ScheduleOnOriginThread(TileTaskClient* client) override { DCHECK(!raster_buffer_); - raster_buffer_ = client->AcquireBufferForRaster(resource()); + raster_buffer_ = client->AcquireBufferForRaster( + resource(), resource_content_id_, previous_content_id_); } void CompleteOnOriginThread(TileTaskClient* client) override { client->ReleaseBufferForRaster(raster_buffer_.Pass()); @@ -90,7 +109,7 @@ class RasterTaskImpl : public RasterTask { private: void Analyze(const RasterSource* raster_source) { frame_viewer_instrumentation::ScopedAnalyzeTask analyze_task( - tile_id_, tile_resolution_, source_frame_number_, layer_id_); + tile_, tile_resolution_, source_frame_number_, layer_id_); DCHECK(raster_source); @@ -102,21 +121,29 @@ class RasterTaskImpl : public RasterTask { void Raster(const RasterSource* raster_source) { frame_viewer_instrumentation::ScopedRasterTask raster_task( - tile_id_, tile_resolution_, source_frame_number_, layer_id_); + tile_, tile_resolution_, source_frame_number_, layer_id_); + ScopedRasterTaskTimer timer; + timer.SetArea(content_rect_.size().GetArea()); DCHECK(raster_source); raster_buffer_->Playback(raster_source_.get(), content_rect_, + invalid_content_rect_, new_content_id_, contents_scale_); } RasterSource::SolidColorAnalysis analysis_; scoped_refptr<RasterSource> raster_source_; gfx::Rect content_rect_; + gfx::Rect invalid_content_rect_; float contents_scale_; TileResolution tile_resolution_; int layer_id_; - const void* tile_id_; + uint64_t source_prepare_tiles_id_; + const void* tile_; + uint64_t new_content_id_; + uint64_t previous_content_id_; + uint64_t resource_content_id_; int source_frame_number_; bool analyze_picture_; const base::Callback<void(const RasterSource::SolidColorAnalysis&, bool)> @@ -129,13 +156,16 @@ class RasterTaskImpl : public RasterTask { class ImageDecodeTaskImpl : public ImageDecodeTask { public: ImageDecodeTaskImpl(SkPixelRef* pixel_ref, + uint64_t source_prepare_tiles_id, const base::Callback<void(bool was_canceled)>& reply) : pixel_ref_(skia::SharePtr(pixel_ref)), + source_prepare_tiles_id_(source_prepare_tiles_id), reply_(reply) {} // Overridden from Task: void RunOnWorkerThread() override { - TRACE_EVENT0("cc", "ImageDecodeTaskImpl::RunOnWorkerThread"); + TRACE_EVENT1("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", + "source_prepare_tiles_id", source_prepare_tiles_id_); devtools_instrumentation::ScopedImageDecodeTask image_decode_task( pixel_ref_.get()); @@ -158,6 +188,7 @@ class ImageDecodeTaskImpl : public ImageDecodeTask { private: skia::RefPtr<SkPixelRef> pixel_ref_; + uint64_t source_prepare_tiles_id_; const base::Callback<void(bool was_canceled)> reply_; DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); @@ -186,8 +217,10 @@ scoped_refptr<base::trace_event::ConvertableToTraceFormat> RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) { scoped_refptr<base::trace_event::TracedValue> state = new base::trace_event::TracedValue(); - state->SetInteger("completed_count", stats.completed_count); - state->SetInteger("canceled_count", stats.canceled_count); + state->SetInteger("completed_count", + base::saturated_cast<int>(stats.completed_count)); + state->SetInteger("canceled_count", + base::saturated_cast<int>(stats.canceled_count)); return state; } @@ -195,47 +228,42 @@ RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) { scoped_ptr<TileManager> TileManager::Create( TileManagerClient* client, base::SequencedTaskRunner* task_runner, - ResourcePool* resource_pool, - TileTaskRunner* tile_task_runner, size_t scheduled_raster_task_limit) { - return make_scoped_ptr(new TileManager(client, task_runner, resource_pool, - tile_task_runner, - scheduled_raster_task_limit)); + return make_scoped_ptr( + new TileManager(client, task_runner, scheduled_raster_task_limit)); } TileManager::TileManager( TileManagerClient* client, const scoped_refptr<base::SequencedTaskRunner>& task_runner, - ResourcePool* resource_pool, - TileTaskRunner* tile_task_runner, size_t scheduled_raster_task_limit) : client_(client), task_runner_(task_runner), - resource_pool_(resource_pool), - tile_task_runner_(tile_task_runner), + resource_pool_(nullptr), + tile_task_runner_(nullptr), scheduled_raster_task_limit_(scheduled_raster_task_limit), all_tiles_that_need_to_be_rasterized_are_scheduled_(true), did_check_for_completed_tasks_since_last_schedule_tasks_(true), did_oom_on_last_assign_(false), - ready_to_activate_check_notifier_( - task_runner_.get(), - base::Bind(&TileManager::CheckIfReadyToActivate, - base::Unretained(this))), - ready_to_draw_check_notifier_( - task_runner_.get(), - base::Bind(&TileManager::CheckIfReadyToDraw, base::Unretained(this))), more_tiles_need_prepare_check_notifier_( task_runner_.get(), base::Bind(&TileManager::CheckIfMoreTilesNeedToBePrepared, base::Unretained(this))), - did_notify_ready_to_activate_(false), - did_notify_ready_to_draw_(false) { - tile_task_runner_->SetClient(this); + signals_check_notifier_(task_runner_.get(), + base::Bind(&TileManager::CheckAndIssueSignals, + base::Unretained(this))), + has_scheduled_tile_tasks_(false), + prepare_tiles_count_(0u) { } TileManager::~TileManager() { - // Reset global state and manage. This should cause - // our memory usage to drop to zero. + FinishTasksAndCleanUp(); +} + +void TileManager::FinishTasksAndCleanUp() { + if (!tile_task_runner_) + return; + global_state_ = GlobalStateThatImpactsTilePriority(); TileTaskQueue empty; @@ -249,6 +277,23 @@ TileManager::~TileManager() { FreeResourcesForReleasedTiles(); CleanUpReleasedTiles(); + + tile_task_runner_ = nullptr; + resource_pool_ = nullptr; + more_tiles_need_prepare_check_notifier_.Cancel(); + signals_check_notifier_.Cancel(); +} + +void TileManager::SetResources(ResourcePool* resource_pool, + TileTaskRunner* tile_task_runner, + size_t scheduled_raster_task_limit) { + DCHECK(!tile_task_runner_); + DCHECK(tile_task_runner); + + scheduled_raster_task_limit_ = scheduled_raster_task_limit; + resource_pool_ = resource_pool; + tile_task_runner_ = tile_task_runner; + tile_task_runner_->SetClient(this); } void TileManager::Release(Tile* tile) { @@ -295,35 +340,58 @@ void TileManager::CleanUpReleasedTiles() { void TileManager::DidFinishRunningTileTasks(TaskSet task_set) { TRACE_EVENT1("cc", "TileManager::DidFinishRunningTileTasks", "task_set", TaskSetName(task_set)); + DCHECK(resource_pool_); + DCHECK(tile_task_runner_); switch (task_set) { case ALL: { + has_scheduled_tile_tasks_ = false; + bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() > global_state_.soft_memory_limit_in_bytes; if (all_tiles_that_need_to_be_rasterized_are_scheduled_ && - !memory_usage_above_limit) + !memory_usage_above_limit) { + // TODO(ericrk): We should find a better way to safely handle re-entrant + // notifications than always having to schedule a new task. + // http://crbug.com/498439 + signals_.all_tile_tasks_completed = true; + signals_check_notifier_.Schedule(); return; + } more_tiles_need_prepare_check_notifier_.Schedule(); return; } case REQUIRED_FOR_ACTIVATION: - ready_to_activate_check_notifier_.Schedule(); + signals_.ready_to_activate = true; + signals_check_notifier_.Schedule(); return; + case REQUIRED_FOR_DRAW: - ready_to_draw_check_notifier_.Schedule(); + signals_.ready_to_draw = true; + signals_check_notifier_.Schedule(); return; } NOTREACHED(); } -void TileManager::PrepareTiles( +bool TileManager::PrepareTiles( const GlobalStateThatImpactsTilePriority& state) { - TRACE_EVENT0("cc", "TileManager::PrepareTiles"); + ++prepare_tiles_count_; + + TRACE_EVENT1("cc", "TileManager::PrepareTiles", "prepare_tiles_id", + prepare_tiles_count_); + + if (!tile_task_runner_) { + TRACE_EVENT_INSTANT0("cc", "PrepareTiles aborted", + TRACE_EVENT_SCOPE_THREAD); + return false; + } + signals_.reset(); global_state_ = state; // We need to call CheckForCompletedTasks() once in-between each call @@ -353,32 +421,30 @@ void TileManager::PrepareTiles( // Schedule tile tasks. ScheduleTasks(tiles_that_need_to_be_rasterized); - did_notify_ready_to_activate_ = false; - did_notify_ready_to_draw_ = false; - TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD, "state", BasicStateAsValue()); TRACE_COUNTER_ID1("cc", "unused_memory_bytes", this, resource_pool_->total_memory_usage_bytes() - resource_pool_->acquired_memory_usage_bytes()); + return true; } -void TileManager::UpdateVisibleTiles( - const GlobalStateThatImpactsTilePriority& state) { - TRACE_EVENT0("cc", "TileManager::UpdateVisibleTiles"); +void TileManager::Flush() { + TRACE_EVENT0("cc", "TileManager::Flush"); + + if (!tile_task_runner_) { + TRACE_EVENT_INSTANT0("cc", "Flush aborted", TRACE_EVENT_SCOPE_THREAD); + return; + } tile_task_runner_->CheckForCompletedTasks(); did_check_for_completed_tasks_since_last_schedule_tasks_ = true; - TRACE_EVENT_INSTANT1( - "cc", - "DidUpdateVisibleTiles", - TRACE_EVENT_SCOPE_THREAD, - "stats", - RasterTaskCompletionStatsAsValue(update_visible_tiles_stats_)); - update_visible_tiles_stats_ = RasterTaskCompletionStats(); + TRACE_EVENT_INSTANT1("cc", "DidFlush", TRACE_EVENT_SCOPE_THREAD, "stats", + RasterTaskCompletionStatsAsValue(flush_stats_)); + flush_stats_ = RasterTaskCompletionStats(); } scoped_refptr<base::trace_event::ConvertableToTraceFormat> @@ -391,7 +457,7 @@ TileManager::BasicStateAsValue() const { void TileManager::BasicStateAsValueInto( base::trace_event::TracedValue* state) const { - state->SetInteger("tile_count", tiles_.size()); + state->SetInteger("tile_count", base::saturated_cast<int>(tiles_.size())); state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_); state->BeginDictionary("global_state"); global_state_.AsValueInto(state); @@ -468,6 +534,9 @@ void TileManager::AssignGpuMemoryToTiles( PrioritizedTileVector* tiles_that_need_to_be_rasterized) { TRACE_EVENT_BEGIN0("cc", "TileManager::AssignGpuMemoryToTiles"); + DCHECK(resource_pool_); + DCHECK(tile_task_runner_); + // Maintain the list of released resources that can potentially be re-used // or deleted. If this operation becomes expensive too, only do this after // some resource(s) was returned. Note that in that case, one also need to @@ -564,6 +633,7 @@ void TileManager::AssignGpuMemoryToTiles( memory_stats_from_last_assign_.total_budget_in_bytes = global_state_.hard_memory_limit_in_bytes; memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes(); + DCHECK_GE(memory_stats_from_last_assign_.total_bytes_used, 0); memory_stats_from_last_assign_.had_enough_memory = had_enough_memory_to_schedule_tiles_needed_now; @@ -577,7 +647,7 @@ void TileManager::AssignGpuMemoryToTiles( void TileManager::FreeResourcesForTile(Tile* tile) { TileDrawInfo& draw_info = tile->draw_info(); if (draw_info.resource_) - resource_pool_->ReleaseResource(draw_info.resource_.Pass()); + resource_pool_->ReleaseResource(draw_info.resource_.Pass(), tile->id()); } void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw( @@ -599,6 +669,11 @@ void TileManager::ScheduleTasks( raster_queue_.Reset(); + // Even when scheduling an empty set of tiles, the TTWP does some work, and + // will always trigger a DidFinishRunningTileTasks notification. Because of + // this we unconditionally set |has_scheduled_tile_tasks_| to true. + has_scheduled_tile_tasks_ = true; + // Build a new task queue containing all task currently needed. Tasks // are added in order of priority, highest priority task first. for (auto& prioritized_tile : tiles_that_need_to_be_rasterized) { @@ -641,19 +716,32 @@ scoped_refptr<ImageDecodeTask> TileManager::CreateImageDecodeTask( Tile* tile, SkPixelRef* pixel_ref) { return make_scoped_refptr(new ImageDecodeTaskImpl( - pixel_ref, + pixel_ref, prepare_tiles_count_, base::Bind(&TileManager::OnImageDecodeTaskCompleted, - base::Unretained(this), - tile->layer_id(), + base::Unretained(this), tile->layer_id(), base::Unretained(pixel_ref)))); } scoped_refptr<RasterTask> TileManager::CreateRasterTask( const PrioritizedTile& prioritized_tile) { Tile* tile = prioritized_tile.tile(); - scoped_ptr<ScopedResource> resource = - resource_pool_->AcquireResource(tile->desired_texture_size(), - tile_task_runner_->GetResourceFormat()); + uint64_t resource_content_id = 0; + scoped_ptr<ScopedResource> resource; + if (tile->invalidated_id()) { + // TODO(danakj): For resources that are in use, we should still grab them + // and copy from them instead of rastering everything. crbug.com/492754 + resource = + resource_pool_->TryAcquireResourceWithContentId(tile->invalidated_id()); + } + if (resource) { + resource_content_id = tile->invalidated_id(); + DCHECK_EQ(tile_task_runner_->GetResourceFormat(), resource->format()); + DCHECK_EQ(tile->desired_texture_size().ToString(), + resource->size().ToString()); + } else { + resource = resource_pool_->AcquireResource( + tile->desired_texture_size(), tile_task_runner_->GetResourceFormat()); + } const ScopedResource* const_resource = resource.get(); // Create and queue all image decode tasks that this tile depends on. @@ -681,9 +769,11 @@ scoped_refptr<RasterTask> TileManager::CreateRasterTask( return make_scoped_refptr(new RasterTaskImpl( const_resource, prioritized_tile.raster_source(), tile->content_rect(), - tile->contents_scale(), prioritized_tile.priority().resolution, - tile->layer_id(), static_cast<const void*>(tile), - tile->source_frame_number(), tile->use_picture_analysis(), + tile->invalidated_content_rect(), tile->contents_scale(), + prioritized_tile.priority().resolution, tile->layer_id(), + prepare_tiles_count_, static_cast<const void*>(tile), tile->id(), + tile->invalidated_id(), resource_content_id, tile->source_frame_number(), + tile->use_picture_analysis(), base::Bind(&TileManager::OnRasterTaskCompleted, base::Unretained(this), tile->id(), base::Passed(&resource)), &decode_tasks)); @@ -722,8 +812,8 @@ void TileManager::OnRasterTaskCompleted( tile->raster_task_ = nullptr; if (was_canceled) { - ++update_visible_tiles_stats_.canceled_count; - resource_pool_->ReleaseResource(resource.Pass()); + ++flush_stats_.canceled_count; + resource_pool_->ReleaseResource(resource.Pass(), tile->invalidated_id()); return; } @@ -736,17 +826,24 @@ void TileManager::UpdateTileDrawInfo( const RasterSource::SolidColorAnalysis& analysis) { TileDrawInfo& draw_info = tile->draw_info(); - ++update_visible_tiles_stats_.completed_count; + ++flush_stats_.completed_count; if (analysis.is_solid_color) { draw_info.set_solid_color(analysis.solid_color); - if (resource) - resource_pool_->ReleaseResource(resource.Pass()); + if (resource) { + // Pass the old tile id here because the tile is solid color so we did not + // raster anything into the tile resource. + resource_pool_->ReleaseResource(resource.Pass(), tile->invalidated_id()); + } } else { DCHECK(resource); draw_info.set_use_resource(); draw_info.resource_ = resource.Pass(); + draw_info.contents_swizzled_ = + tile_task_runner_->GetResourceRequiresSwizzle(); } + DCHECK(draw_info.IsReadyToDraw()); + draw_info.set_was_ever_ready_to_draw(); client_->NotifyTileStateChanged(tile); } @@ -757,6 +854,9 @@ ScopedTilePtr TileManager::CreateTile(const gfx::Size& desired_texture_size, int layer_id, int source_frame_number, int flags) { + // We need to have a tile task worker pool to do anything meaningful with + // tiles. + DCHECK(tile_task_runner_); ScopedTilePtr tile(new Tile(this, desired_texture_size, content_rect, contents_scale, layer_id, source_frame_number, flags)); @@ -798,6 +898,7 @@ bool TileManager::AreRequiredTilesReadyToDraw( #endif return true; } + bool TileManager::IsReadyToActivate() const { TRACE_EVENT0("cc", "TileManager::IsReadyToActivate"); return AreRequiredTilesReadyToDraw( @@ -810,48 +911,43 @@ bool TileManager::IsReadyToDraw() const { RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); } -void TileManager::NotifyReadyToActivate() { - TRACE_EVENT0("cc", "TileManager::NotifyReadyToActivate"); - if (did_notify_ready_to_activate_) - return; - client_->NotifyReadyToActivate(); - did_notify_ready_to_activate_ = true; -} - -void TileManager::NotifyReadyToDraw() { - TRACE_EVENT0("cc", "TileManager::NotifyReadyToDraw"); - if (did_notify_ready_to_draw_) - return; - client_->NotifyReadyToDraw(); - did_notify_ready_to_draw_ = true; -} - -void TileManager::CheckIfReadyToActivate() { - TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate"); - +void TileManager::CheckAndIssueSignals() { + TRACE_EVENT0("cc", "TileManager::CheckAndIssueSignals"); tile_task_runner_->CheckForCompletedTasks(); did_check_for_completed_tasks_since_last_schedule_tasks_ = true; - if (did_notify_ready_to_activate_) - return; - if (!IsReadyToActivate()) - return; - - NotifyReadyToActivate(); -} - -void TileManager::CheckIfReadyToDraw() { - TRACE_EVENT0("cc", "TileManager::CheckIfReadyToDraw"); - - tile_task_runner_->CheckForCompletedTasks(); - did_check_for_completed_tasks_since_last_schedule_tasks_ = true; + // Ready to activate. + if (signals_.ready_to_activate && !signals_.did_notify_ready_to_activate) { + signals_.ready_to_activate = false; + if (IsReadyToActivate()) { + TRACE_EVENT0("cc", + "TileManager::CheckAndIssueSignals - ready to activate"); + signals_.did_notify_ready_to_activate = true; + client_->NotifyReadyToActivate(); + } + } - if (did_notify_ready_to_draw_) - return; - if (!IsReadyToDraw()) - return; + // Ready to draw. + if (signals_.ready_to_draw && !signals_.did_notify_ready_to_draw) { + signals_.ready_to_draw = false; + if (IsReadyToDraw()) { + TRACE_EVENT0("cc", "TileManager::CheckAndIssueSignals - ready to draw"); + signals_.did_notify_ready_to_draw = true; + client_->NotifyReadyToDraw(); + } + } - NotifyReadyToDraw(); + // All tile tasks completed. + if (signals_.all_tile_tasks_completed && + !signals_.did_notify_all_tile_tasks_completed) { + signals_.all_tile_tasks_completed = false; + if (!has_scheduled_tile_tasks_) { + TRACE_EVENT0( + "cc", "TileManager::CheckAndIssueSignals - all tile tasks completed"); + signals_.did_notify_all_tile_tasks_completed = true; + client_->NotifyAllTileTasksCompleted(); + } + } } void TileManager::CheckIfMoreTilesNeedToBePrepared() { @@ -885,6 +981,9 @@ void TileManager::CheckIfMoreTilesNeedToBePrepared() { resource_pool_->ReduceResourceUsage(); + signals_.all_tile_tasks_completed = true; + signals_check_notifier_.Schedule(); + // We don't reserve memory for required-for-activation tiles during // accelerated gestures, so we just postpone activation when we don't // have these tiles, and activate after the accelerated gesture. @@ -919,21 +1018,36 @@ void TileManager::CheckIfMoreTilesNeedToBePrepared() { } DCHECK(IsReadyToActivate()); - ready_to_activate_check_notifier_.Schedule(); + // TODO(ericrk): Investigate why we need to schedule this (not just call it + // inline). http://crbug.com/498439 + signals_.ready_to_activate = true; + signals_check_notifier_.Schedule(); } TileManager::MemoryUsage::MemoryUsage() : memory_bytes_(0), resource_count_(0) { } -TileManager::MemoryUsage::MemoryUsage(int64 memory_bytes, int resource_count) - : memory_bytes_(memory_bytes), resource_count_(resource_count) { +TileManager::MemoryUsage::MemoryUsage(size_t memory_bytes, + size_t resource_count) + : memory_bytes_(static_cast<int64>(memory_bytes)), + resource_count_(static_cast<int>(resource_count)) { + // MemoryUsage is constructed using size_ts, since it deals with memory and + // the inputs are typically size_t. However, during the course of usage (in + // particular operator-=) can cause internal values to become negative. Thus, + // member variables are signed. + DCHECK_LE(memory_bytes, + static_cast<size_t>(std::numeric_limits<int64>::max())); + DCHECK_LE(resource_count, + static_cast<size_t>(std::numeric_limits<int>::max())); } // static TileManager::MemoryUsage TileManager::MemoryUsage::FromConfig( const gfx::Size& size, ResourceFormat format) { - return MemoryUsage(Resource::MemorySizeBytes(size, format), 1); + // We can use UncheckedMemorySizeBytes here since this is used with a tile + // size which is determined by the compositor (it's at most max texture size). + return MemoryUsage(Resource::UncheckedMemorySizeBytes(size, format), 1); } // static @@ -972,4 +1086,17 @@ bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const { resource_count_ > limit.resource_count_; } +TileManager::Signals::Signals() { + reset(); +} + +void TileManager::Signals::reset() { + ready_to_activate = false; + did_notify_ready_to_activate = false; + ready_to_draw = false; + did_notify_ready_to_draw = false; + all_tile_tasks_completed = false; + did_notify_all_tile_tasks_completed = false; +} + } // namespace cc diff --git a/chromium/cc/tiles/tile_manager.h b/chromium/cc/tiles/tile_manager.h index 8611b3a3615..a69e5a27dcf 100644 --- a/chromium/cc/tiles/tile_manager.h +++ b/chromium/cc/tiles/tile_manager.h @@ -43,6 +43,10 @@ class CC_EXPORT TileManagerClient { // Called when all tiles marked as required for draw are ready to draw. virtual void NotifyReadyToDraw() = 0; + // Called when all tile tasks started by the most recent call to PrepareTiles + // are completed. + virtual void NotifyAllTileTasksCompleted() = 0; + // Called when the visible representation of a tile might have changed. Some // examples are: // - Tile version initialized. @@ -102,8 +106,6 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient { static scoped_ptr<TileManager> Create(TileManagerClient* client, base::SequencedTaskRunner* task_runner, - ResourcePool* resource_pool, - TileTaskRunner* tile_task_runner, size_t scheduled_raster_task_limit); ~TileManager() override; @@ -112,9 +114,23 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient { // activation are prepared, or failed to prepare due to OOM. // - Runs client_->NotifyReadyToDraw() when all tiles required draw are // prepared, or failed to prepare due to OOM. - void PrepareTiles(const GlobalStateThatImpactsTilePriority& state); + bool PrepareTiles(const GlobalStateThatImpactsTilePriority& state); + + // Synchronously finish any in progress work, cancel the rest, and clean up as + // much resources as possible. Also, prevents any future work until a + // SetResources call. + void FinishTasksAndCleanUp(); + + // Set the new given resource pool and tile task runner. Note that + // FinishTasksAndCleanUp must be called in between consecutive calls to + // SetResources. + void SetResources(ResourcePool* resource_pool, + TileTaskRunner* tile_task_runner, + size_t scheduled_raster_task_limit); - void UpdateVisibleTiles(const GlobalStateThatImpactsTilePriority& state); + // This causes any completed raster work to finalize, so that tiles get up to + // date draw information. + void Flush(); ScopedTilePtr CreateTile(const gfx::Size& desired_texture_size, const gfx::Rect& content_rect, @@ -179,11 +195,17 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient { CheckIfMoreTilesNeedToBePrepared(); } + void SetMoreTilesNeedToBeRasterizedForTesting() { + all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; + } + + bool HasScheduledTileTasksForTesting() const { + return has_scheduled_tile_tasks_; + } + protected: TileManager(TileManagerClient* client, const scoped_refptr<base::SequencedTaskRunner>& task_runner, - ResourcePool* resource_pool, - TileTaskRunner* tile_task_runner, size_t scheduled_raster_task_limit); void FreeResourcesForReleasedTiles(); @@ -213,7 +235,7 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient { class MemoryUsage { public: MemoryUsage(); - MemoryUsage(int64 memory_bytes, int resource_count); + MemoryUsage(size_t memory_bytes, size_t resource_count); static MemoryUsage FromConfig(const gfx::Size& size, ResourceFormat format); static MemoryUsage FromTile(const Tile* tile); @@ -261,11 +283,8 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient { MemoryUsage* usage); bool TilePriorityViolatesMemoryPolicy(const TilePriority& priority); bool AreRequiredTilesReadyToDraw(RasterTilePriorityQueue::Type type) const; - void NotifyReadyToActivate(); - void NotifyReadyToDraw(); - void CheckIfReadyToActivate(); - void CheckIfReadyToDraw(); void CheckIfMoreTilesNeedToBePrepared(); + void CheckAndIssueSignals(); TileManagerClient* client_; scoped_refptr<base::SequencedTaskRunner> task_runner_; @@ -291,7 +310,7 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient { typedef base::hash_map<int, int> LayerCountMap; LayerCountMap used_layer_counts_; - RasterTaskCompletionStats update_visible_tiles_stats_; + RasterTaskCompletionStats flush_stats_; std::vector<Tile*> released_tiles_; @@ -300,12 +319,26 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient { std::vector<scoped_refptr<RasterTask>> orphan_raster_tasks_; - UniqueNotifier ready_to_activate_check_notifier_; - UniqueNotifier ready_to_draw_check_notifier_; UniqueNotifier more_tiles_need_prepare_check_notifier_; - bool did_notify_ready_to_activate_; - bool did_notify_ready_to_draw_; + struct Signals { + Signals(); + + void reset(); + + bool ready_to_activate; + bool did_notify_ready_to_activate; + bool ready_to_draw; + bool did_notify_ready_to_draw; + bool all_tile_tasks_completed; + bool did_notify_all_tile_tasks_completed; + } signals_; + + UniqueNotifier signals_check_notifier_; + + bool has_scheduled_tile_tasks_; + + uint64_t prepare_tiles_count_; DISALLOW_COPY_AND_ASSIGN(TileManager); }; diff --git a/chromium/cc/tiles/tile_manager_perftest.cc b/chromium/cc/tiles/tile_manager_perftest.cc index 7b75a7a09bb..eea9b94922b 100644 --- a/chromium/cc/tiles/tile_manager_perftest.cc +++ b/chromium/cc/tiles/tile_manager_perftest.cc @@ -16,7 +16,6 @@ #include "cc/test/fake_picture_pile_impl.h" #include "cc/test/fake_tile_manager.h" #include "cc/test/fake_tile_manager_client.h" -#include "cc/test/impl_side_painting_settings.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/test/test_tile_priorities.h" @@ -27,8 +26,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" -#include "ui/gfx/frame_time.h" - namespace cc { namespace { @@ -67,13 +64,16 @@ class FakeTileTaskRunnerImpl : public TileTaskRunner, public TileTaskClient { } completed_tasks_.clear(); } - ResourceFormat GetResourceFormat() override { - return RGBA_8888; + ResourceFormat GetResourceFormat() const override { return RGBA_8888; } + bool GetResourceRequiresSwizzle() const override { + return !PlatformColor::SameComponentOrder(GetResourceFormat()); } // Overridden from TileTaskClient: scoped_ptr<RasterBuffer> AcquireBufferForRaster( - const Resource* resource) override { + const Resource* resource, + uint64_t new_content_id, + uint64_t previous_content_id) override { return nullptr; } void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override {} @@ -91,7 +91,7 @@ class TileManagerPerfTest : public testing::Test { max_tiles_(10000), id_(7), proxy_(base::ThreadTaskRunnerHandle::Get()), - host_impl_(ImplSidePaintingSettings(10000), + host_impl_(LayerTreeSettings(), &proxy_, &shared_bitmap_manager_, &task_graph_runner_), @@ -385,20 +385,18 @@ class TileManagerPerfTest : public testing::Test { int approximate_tile_count_per_layer) { std::vector<FakePictureLayerImpl*> layers = CreateLayers(layer_count, approximate_tile_count_per_layer); + timer_.Reset(); bool resourceless_software_draw = false; do { - BeginFrameArgs args = - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE); - host_impl_.WillBeginImplFrame(args); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); for (const auto& layer : layers) layer->UpdateTiles(resourceless_software_draw); GlobalStateThatImpactsTilePriority global_state(GlobalStateForTest()); tile_manager()->PrepareTiles(global_state); - tile_manager()->UpdateVisibleTiles(global_state); + tile_manager()->Flush(); timer_.NextLap(); - host_impl_.DidFinishImplFrame(); } while (!timer_.HasTimeLimitExpired()); perf_test::PrintResult("prepare_tiles", "", test_name, diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc index bddf29f53b6..4a663cefaf5 100644 --- a/chromium/cc/tiles/tile_manager_unittest.cc +++ b/chromium/cc/tiles/tile_manager_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/run_loop.h" #include "base/thread_task_runner_handle.h" #include "cc/resources/resource_pool.h" #include "cc/test/begin_frame_args_test.h" @@ -13,7 +14,6 @@ #include "cc/test/fake_picture_layer_tiling_client.h" #include "cc/test/fake_picture_pile_impl.h" #include "cc/test/fake_tile_manager.h" -#include "cc/test/impl_side_painting_settings.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/test/test_tile_priorities.h" @@ -23,12 +23,13 @@ #include "cc/tiles/tile_priority.h" #include "cc/tiles/tiling_set_raster_queue_all.h" #include "cc/trees/layer_tree_impl.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { namespace { -class LowResTilingsSettings : public ImplSidePaintingSettings { +class LowResTilingsSettings : public LayerTreeSettings { public: LowResTilingsSettings() { create_low_res_tiling = true; } }; @@ -595,10 +596,7 @@ TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueueInvalidation) { } TEST_F(TileManagerTilePriorityQueueTest, ActivationComesBeforeEventually) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size layer_bounds(1000, 1000); SetupDefaultTrees(layer_bounds); @@ -616,9 +614,7 @@ TEST_F(TileManagerTilePriorityQueueTest, ActivationComesBeforeEventually) { // Set a small viewport, so we have soon and eventually tiles. host_impl_.SetViewportSize(gfx::Size(200, 200)); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); @@ -824,10 +820,7 @@ TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) { TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueueWithOcclusion) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(102, 102); gfx::Size layer_bounds(1000, 1000); @@ -847,9 +840,7 @@ TEST_F(TileManagerTilePriorityQueueTest, static_cast<FakePictureLayerImpl*>(pending_layer_->children()[0]); pending_child_layer->SetDrawsContent(true); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); @@ -963,10 +954,7 @@ TEST_F(TileManagerTilePriorityQueueTest, TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueueWithTransparentLayer) { - base::TimeTicks time_ticks; - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(102, 102); gfx::Size layer_bounds(1000, 1000); @@ -985,17 +973,13 @@ TEST_F(TileManagerTilePriorityQueueTest, // considered to be valid. pending_child_layer->SetDrawsContent(true); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); bool update_lcd_text = false; host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); pending_child_layer->SetOpacity(0.0); - time_ticks += base::TimeDelta::FromMilliseconds(1); - host_impl_.SetCurrentBeginFrameArgs( - CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); // Renew all of the tile priorities. @@ -1405,7 +1389,7 @@ TEST_F(TileManagerTilePriorityQueueTest, ManagedMemoryPolicy policy = host_impl_.ActualManagedMemoryPolicy(); policy.bytes_limit_when_visible = - Resource::MemorySizeBytes(gfx::Size(256, 256), RGBA_8888); + Resource::UncheckedMemorySizeBytes(gfx::Size(256, 256), RGBA_8888); host_impl_.SetMemoryPolicy(policy); EXPECT_FALSE(host_impl_.is_likely_to_require_a_draw()); @@ -1419,7 +1403,118 @@ TEST_F(TileManagerTilePriorityQueueTest, host_impl_.tile_manager()->CheckIfMoreTilesNeedToBePreparedForTesting(); EXPECT_FALSE(host_impl_.is_likely_to_require_a_draw()); - host_impl_.resource_pool()->ReleaseResource(resource.Pass()); + host_impl_.resource_pool()->ReleaseResource(resource.Pass(), 0); +} + +TEST_F(TileManagerTilePriorityQueueTest, RasterQueueAllUsesCorrectTileBounds) { + // Verify that we use the real tile bounds when advancing phases during the + // tile iteration. + gfx::Size layer_bounds(1, 1); + + scoped_refptr<FakePicturePileImpl> pile = + FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds); + + FakePictureLayerTilingClient pending_client; + pending_client.SetTileSize(gfx::Size(64, 64)); + + auto tiling_set = PictureLayerTilingSet::Create( + WhichTree::ACTIVE_TREE, &pending_client, 1.0f, 1.0f, 1000); + pending_client.set_twin_tiling_set(tiling_set.get()); + + auto tiling = tiling_set->AddTiling(1.0f, pile); + + tiling->CreateAllTilesForTesting(); + tiling->set_resolution(HIGH_RESOLUTION); + + // The tile is (0, 0, 1, 1), create an intersecting and non-intersecting + // rectangle to test the advance phase with. The tile size is (64, 64), so + // both rectangles intersect the tile content size, but only one should + // intersect the actual size. + gfx::Rect non_intersecting_rect(2, 2, 10, 10); + gfx::Rect intersecting_rect(0, 0, 10, 10); + { + tiling->SetTilePriorityRectsForTesting( + non_intersecting_rect, // Visible rect. + intersecting_rect, // Skewport rect. + intersecting_rect, // Soon rect. + intersecting_rect); // Eventually rect. + scoped_ptr<TilingSetRasterQueueAll> queue( + new TilingSetRasterQueueAll(tiling_set.get(), false)); + EXPECT_FALSE(queue->IsEmpty()); + } + { + tiling->SetTilePriorityRectsForTesting( + non_intersecting_rect, // Visible rect. + non_intersecting_rect, // Skewport rect. + intersecting_rect, // Soon rect. + intersecting_rect); // Eventually rect. + scoped_ptr<TilingSetRasterQueueAll> queue( + new TilingSetRasterQueueAll(tiling_set.get(), false)); + EXPECT_FALSE(queue->IsEmpty()); + } + { + tiling->SetTilePriorityRectsForTesting( + non_intersecting_rect, // Visible rect. + non_intersecting_rect, // Skewport rect. + non_intersecting_rect, // Soon rect. + intersecting_rect); // Eventually rect. + scoped_ptr<TilingSetRasterQueueAll> queue( + new TilingSetRasterQueueAll(tiling_set.get(), false)); + EXPECT_FALSE(queue->IsEmpty()); + } +} + +class TileManagerTest : public testing::Test { + public: + TileManagerTest() + : host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_) {} + + protected: + // MockLayerTreeHostImpl allows us to intercept tile manager callbacks. + class MockLayerTreeHostImpl : public FakeLayerTreeHostImpl { + public: + MockLayerTreeHostImpl(Proxy* proxy, + SharedBitmapManager* manager, + TaskGraphRunner* task_graph_runner) + : FakeLayerTreeHostImpl(proxy, manager, task_graph_runner) { + InitializeRenderer(FakeOutputSurface::Create3d()); + } + + MOCK_METHOD0(NotifyAllTileTasksCompleted, void()); + }; + + TestSharedBitmapManager shared_bitmap_manager_; + TestTaskGraphRunner task_graph_runner_; + FakeImplProxy proxy_; + MockLayerTreeHostImpl host_impl_; +}; + +// Test to ensure that we call NotifyAllTileTasksCompleted when PrepareTiles is +// called. +TEST_F(TileManagerTest, AllWorkFinishedTest) { + // Check with no tile work enqueued. + { + base::RunLoop run_loop; + EXPECT_FALSE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting()); + EXPECT_CALL(host_impl_, NotifyAllTileTasksCompleted()) + .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); })); + host_impl_.tile_manager()->PrepareTiles(host_impl_.global_tile_state()); + EXPECT_TRUE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting()); + run_loop.Run(); + } + + // Check that the "schedule more work" path also triggers the expected + // callback. + { + base::RunLoop run_loop; + EXPECT_FALSE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting()); + EXPECT_CALL(host_impl_, NotifyAllTileTasksCompleted()) + .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); })); + host_impl_.tile_manager()->PrepareTiles(host_impl_.global_tile_state()); + host_impl_.tile_manager()->SetMoreTilesNeedToBeRasterizedForTesting(); + EXPECT_TRUE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting()); + run_loop.Run(); + } } } // namespace diff --git a/chromium/cc/tiles/tile_priority.cc b/chromium/cc/tiles/tile_priority.cc index cf9872e6dcd..0efe51e5972 100644 --- a/chromium/cc/tiles/tile_priority.cc +++ b/chromium/cc/tiles/tile_priority.cc @@ -4,6 +4,7 @@ #include "cc/tiles/tile_priority.h" +#include "base/numerics/safe_conversions.h" #include "base/trace_event/trace_event_argument.h" #include "base/values.h" #include "cc/base/math_util.h" @@ -89,9 +90,12 @@ void GlobalStateThatImpactsTilePriority::AsValueInto( base::trace_event::TracedValue* state) const { state->SetString("memory_limit_policy", TileMemoryLimitPolicyToString(memory_limit_policy)); - state->SetInteger("soft_memory_limit_in_bytes", soft_memory_limit_in_bytes); - state->SetInteger("hard_memory_limit_in_bytes", hard_memory_limit_in_bytes); - state->SetInteger("num_resources_limit", num_resources_limit); + state->SetInteger("soft_memory_limit_in_bytes", + base::saturated_cast<int>(soft_memory_limit_in_bytes)); + state->SetInteger("hard_memory_limit_in_bytes", + base::saturated_cast<int>(hard_memory_limit_in_bytes)); + state->SetInteger("num_resources_limit", + base::saturated_cast<int>(num_resources_limit)); state->SetString("tree_priority", TreePriorityToString(tree_priority)); } diff --git a/chromium/cc/tiles/tiling_set_eviction_queue.cc b/chromium/cc/tiles/tiling_set_eviction_queue.cc index 9329d0db29a..4b314d721b8 100644 --- a/chromium/cc/tiles/tiling_set_eviction_queue.cc +++ b/chromium/cc/tiles/tiling_set_eviction_queue.cc @@ -33,37 +33,39 @@ void TilingSetEvictionQueue::GenerateTilingOrder( // for this class. PictureLayerTilingSet::TilingRange range = tiling_set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - for (int i = range.start; i < range.end; ++i) { - PictureLayerTiling* tiling = tiling_set->tiling_at(i); + for (size_t index = range.start; index < range.end; ++index) { + PictureLayerTiling* tiling = tiling_set->tiling_at(index); if (tiling->has_tiles()) tilings_.push_back(tiling); } range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES); - for (int i = range.end - 1; i >= range.start; --i) { - PictureLayerTiling* tiling = tiling_set->tiling_at(i); + for (size_t i = range.start; i < range.end; ++i) { + size_t index = range.start + (range.end - 1 - i); + PictureLayerTiling* tiling = tiling_set->tiling_at(index); if (tiling->has_tiles()) tilings_.push_back(tiling); } range = tiling_set->GetTilingRange( PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - for (int i = range.end - 1; i >= range.start; --i) { - PictureLayerTiling* tiling = tiling_set->tiling_at(i); + for (size_t i = range.start; i < range.end; ++i) { + size_t index = range.start + (range.end - 1 - i); + PictureLayerTiling* tiling = tiling_set->tiling_at(index); if (tiling->has_tiles()) tilings_.push_back(tiling); } range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOW_RES); - for (int i = range.start; i < range.end; ++i) { - PictureLayerTiling* tiling = tiling_set->tiling_at(i); + for (size_t index = range.start; index < range.end; ++index) { + PictureLayerTiling* tiling = tiling_set->tiling_at(index); if (tiling->has_tiles()) tilings_.push_back(tiling); } range = tiling_set->GetTilingRange(PictureLayerTilingSet::HIGH_RES); - for (int i = range.start; i < range.end; ++i) { - PictureLayerTiling* tiling = tiling_set->tiling_at(i); + for (size_t index = range.start; index < range.end; ++index) { + PictureLayerTiling* tiling = tiling_set->tiling_at(index); if (tiling->has_tiles()) tilings_.push_back(tiling); } @@ -222,9 +224,11 @@ bool TilingSetEvictionQueue::EvictionRectIterator::GetFirstTileAndCheckIfValid( // After the pending visible rect has been processed, we must return false // for pending visible rect tiles as tiling iterators do not ignore those // tiles. - if (priority_rect_type_ > PictureLayerTiling::PENDING_VISIBLE_RECT && - tiling->pending_visible_rect().Intersects(tile->content_rect())) { - return false; + if (priority_rect_type_ > PictureLayerTiling::PENDING_VISIBLE_RECT) { + gfx::Rect tile_rect = tiling->tiling_data()->TileBounds( + tile->tiling_i_index(), tile->tiling_j_index()); + if (tiling->pending_visible_rect().Intersects(tile_rect)) + return false; } (*tilings_)[tiling_index_]->UpdateRequiredStatesOnTile(tile); prioritized_tile_ = (*tilings_)[tiling_index_]->MakePrioritizedTile( diff --git a/chromium/cc/tiles/tiling_set_raster_queue_all.cc b/chromium/cc/tiles/tiling_set_raster_queue_all.cc index ae91f271fc2..1cac85d2ad0 100644 --- a/chromium/cc/tiles/tiling_set_raster_queue_all.cc +++ b/chromium/cc/tiles/tiling_set_raster_queue_all.cc @@ -52,32 +52,36 @@ TilingSetRasterQueueAll::TilingSetRasterQueueAll( } } - bool use_low_res_tiling = low_res_tiling && low_res_tiling->has_tiles(); - if (use_low_res_tiling && prioritize_low_res) { - iterators_[LOW_RES] = - TilingIterator(low_res_tiling, &low_res_tiling->tiling_data_); - stages_->push_back(IterationStage(LOW_RES, TilePriority::NOW)); + bool use_low_res_tiling = low_res_tiling && low_res_tiling->has_tiles() && + !low_res_tiling->all_tiles_done(); + bool use_high_res_tiling = high_res_tiling && high_res_tiling->has_tiles() && + !high_res_tiling->all_tiles_done(); + bool use_active_non_ideal_pending_high_res_tiling = + active_non_ideal_pending_high_res_tiling && + active_non_ideal_pending_high_res_tiling->has_tiles() && + !active_non_ideal_pending_high_res_tiling->all_tiles_done(); + + // Make the tiling iterators. + if (use_low_res_tiling) + MakeTilingIterator(LOW_RES, low_res_tiling); + if (use_high_res_tiling) + MakeTilingIterator(HIGH_RES, high_res_tiling); + if (use_active_non_ideal_pending_high_res_tiling) { + MakeTilingIterator(ACTIVE_NON_IDEAL_PENDING_HIGH_RES, + active_non_ideal_pending_high_res_tiling); } - bool use_high_res_tiling = high_res_tiling && high_res_tiling->has_tiles(); - if (use_high_res_tiling) { - iterators_[HIGH_RES] = - TilingIterator(high_res_tiling, &high_res_tiling->tiling_data_); + // Set up the stages. + if (use_low_res_tiling && prioritize_low_res) + stages_->push_back(IterationStage(LOW_RES, TilePriority::NOW)); + + if (use_high_res_tiling) stages_->push_back(IterationStage(HIGH_RES, TilePriority::NOW)); - } - if (low_res_tiling && !prioritize_low_res) { - iterators_[LOW_RES] = - TilingIterator(low_res_tiling, &low_res_tiling->tiling_data_); + if (low_res_tiling && !prioritize_low_res) stages_->push_back(IterationStage(LOW_RES, TilePriority::NOW)); - } - - if (active_non_ideal_pending_high_res_tiling && - active_non_ideal_pending_high_res_tiling->has_tiles()) { - iterators_[ACTIVE_NON_IDEAL_PENDING_HIGH_RES] = - TilingIterator(active_non_ideal_pending_high_res_tiling, - &active_non_ideal_pending_high_res_tiling->tiling_data_); + if (use_active_non_ideal_pending_high_res_tiling) { stages_->push_back( IterationStage(ACTIVE_NON_IDEAL_PENDING_HIGH_RES, TilePriority::NOW)); stages_->push_back( @@ -101,6 +105,16 @@ TilingSetRasterQueueAll::TilingSetRasterQueueAll( TilingSetRasterQueueAll::~TilingSetRasterQueueAll() { } +void TilingSetRasterQueueAll::MakeTilingIterator(IteratorType type, + PictureLayerTiling* tiling) { + iterators_[type] = TilingIterator(tiling, &tiling->tiling_data_); + if (iterators_[type].done()) { + tiling->set_all_tiles_done(true); + // If we've marked the tiling as done, make sure we're actually done. + tiling->VerifyNoTileNeedsRaster(); + } +} + bool TilingSetRasterQueueAll::IsEmpty() const { return current_stage_ >= stages_->size(); } @@ -152,20 +166,25 @@ TilingSetRasterQueueAll::OnePriorityRectIterator::OnePriorityRectIterator( PictureLayerTiling::PriorityRectType priority_rect_type) : tiling_(tiling), tiling_data_(tiling_data), - priority_rect_type_(priority_rect_type) { + priority_rect_type_(priority_rect_type), + pending_visible_rect_(tiling->pending_visible_rect()) { } template <typename TilingIteratorType> void TilingSetRasterQueueAll::OnePriorityRectIterator::AdvanceToNextTile( TilingIteratorType* iterator) { - bool found_tile = false; - while (!found_tile) { + for (;;) { ++(*iterator); if (!(*iterator)) { current_tile_ = PrioritizedTile(); break; } - found_tile = GetFirstTileAndCheckIfValid(iterator); + Tile* tile = tiling_->TileAt(iterator->index_x(), iterator->index_y()); + if (IsTileValid(tile)) { + tiling_->UpdateRequiredStatesOnTile(tile); + current_tile_ = tiling_->MakePrioritizedTile(tile, priority_rect_type_); + break; + } } } @@ -173,20 +192,28 @@ template <typename TilingIteratorType> bool TilingSetRasterQueueAll::OnePriorityRectIterator:: GetFirstTileAndCheckIfValid(TilingIteratorType* iterator) { Tile* tile = tiling_->TileAt(iterator->index_x(), iterator->index_y()); - if (!tile || !TileNeedsRaster(tile)) { + if (!IsTileValid(tile)) { current_tile_ = PrioritizedTile(); return false; } + tiling_->UpdateRequiredStatesOnTile(tile); + current_tile_ = tiling_->MakePrioritizedTile(tile, priority_rect_type_); + return true; +} + +bool TilingSetRasterQueueAll::OnePriorityRectIterator::IsTileValid( + const Tile* tile) const { + if (!tile || !TileNeedsRaster(tile)) + return false; // After the pending visible rect has been processed, we must return false // for pending visible rect tiles as tiling iterators do not ignore those // tiles. - if (priority_rect_type_ > PictureLayerTiling::PENDING_VISIBLE_RECT && - tiling_->pending_visible_rect().Intersects(tile->content_rect())) { - current_tile_ = PrioritizedTile(); - return false; + if (priority_rect_type_ > PictureLayerTiling::PENDING_VISIBLE_RECT) { + gfx::Rect tile_rect = tiling_->tiling_data()->TileBounds( + tile->tiling_i_index(), tile->tiling_j_index()); + if (pending_visible_rect_.Intersects(tile_rect)) + return false; } - tiling_->UpdateRequiredStatesOnTile(tile); - current_tile_ = tiling_->MakePrioritizedTile(tile, priority_rect_type_); return true; } @@ -222,9 +249,8 @@ TilingSetRasterQueueAll::PendingVisibleTilingIterator:: : OnePriorityRectIterator(tiling, tiling_data, PictureLayerTiling::PENDING_VISIBLE_RECT) { - iterator_ = TilingData::DifferenceIterator(tiling_data_, - tiling_->pending_visible_rect(), - tiling_->current_visible_rect()); + iterator_ = TilingData::DifferenceIterator( + tiling_data_, pending_visible_rect_, tiling_->current_visible_rect()); if (!iterator_) return; if (!GetFirstTileAndCheckIfValid(&iterator_)) @@ -244,8 +270,7 @@ TilingSetRasterQueueAll::SkewportTilingIterator::SkewportTilingIterator( TilingData* tiling_data) : OnePriorityRectIterator(tiling, tiling_data, - PictureLayerTiling::SKEWPORT_RECT), - pending_visible_rect_(tiling->pending_visible_rect()) { + PictureLayerTiling::SKEWPORT_RECT) { if (!tiling_->has_skewport_rect_tiles()) return; iterator_ = TilingData::SpiralDifferenceIterator( @@ -257,23 +282,12 @@ TilingSetRasterQueueAll::SkewportTilingIterator::SkewportTilingIterator( ++(*this); return; } - // TODO(e_hakkinen): This is not needed as GetFirstTileAndCheckIfValid - // does the same checking. - if (current_tile_.tile()->content_rect().Intersects(pending_visible_rect_)) - ++(*this); } TilingSetRasterQueueAll::SkewportTilingIterator& TilingSetRasterQueueAll::SkewportTilingIterator:: operator++() { AdvanceToNextTile(&iterator_); - // TODO(e_hakkinen): This is not needed as GetFirstTileAndCheckIfValid called - // by AdvanceToNextTile does the same checking. - while (!done()) { - if (!current_tile_.tile()->content_rect().Intersects(pending_visible_rect_)) - break; - AdvanceToNextTile(&iterator_); - } return *this; } @@ -283,8 +297,7 @@ TilingSetRasterQueueAll::SoonBorderTilingIterator::SoonBorderTilingIterator( TilingData* tiling_data) : OnePriorityRectIterator(tiling, tiling_data, - PictureLayerTiling::SOON_BORDER_RECT), - pending_visible_rect_(tiling->pending_visible_rect()) { + PictureLayerTiling::SOON_BORDER_RECT) { if (!tiling_->has_soon_border_rect_tiles()) return; iterator_ = TilingData::SpiralDifferenceIterator( @@ -296,23 +309,12 @@ TilingSetRasterQueueAll::SoonBorderTilingIterator::SoonBorderTilingIterator( ++(*this); return; } - // TODO(e_hakkinen): This is not needed as GetFirstTileAndCheckIfValid - // does the same checking. - if (current_tile_.tile()->content_rect().Intersects(pending_visible_rect_)) - ++(*this); } TilingSetRasterQueueAll::SoonBorderTilingIterator& TilingSetRasterQueueAll::SoonBorderTilingIterator:: operator++() { AdvanceToNextTile(&iterator_); - // TODO(e_hakkinen): This is not needed as GetFirstTileAndCheckIfValid called - // by AdvanceToNextTile does the same checking. - while (!done()) { - if (!current_tile_.tile()->content_rect().Intersects(pending_visible_rect_)) - break; - AdvanceToNextTile(&iterator_); - } return *this; } @@ -322,8 +324,7 @@ TilingSetRasterQueueAll::EventuallyTilingIterator::EventuallyTilingIterator( TilingData* tiling_data) : OnePriorityRectIterator(tiling, tiling_data, - PictureLayerTiling::EVENTUALLY_RECT), - pending_visible_rect_(tiling->pending_visible_rect()) { + PictureLayerTiling::EVENTUALLY_RECT) { if (!tiling_->has_eventually_rect_tiles()) return; iterator_ = TilingData::SpiralDifferenceIterator( @@ -335,23 +336,12 @@ TilingSetRasterQueueAll::EventuallyTilingIterator::EventuallyTilingIterator( ++(*this); return; } - // TODO(e_hakkinen): This is not needed as GetFirstTileAndCheckIfValid - // does the same checking. - if (current_tile_.tile()->content_rect().Intersects(pending_visible_rect_)) - ++(*this); } TilingSetRasterQueueAll::EventuallyTilingIterator& TilingSetRasterQueueAll::EventuallyTilingIterator:: operator++() { AdvanceToNextTile(&iterator_); - // TODO(e_hakkinen): This is not needed as GetFirstTileAndCheckIfValid called - // by AdvanceToNextTile does the same checking. - while (!done()) { - if (!current_tile_.tile()->content_rect().Intersects(pending_visible_rect_)) - break; - AdvanceToNextTile(&iterator_); - } return *this; } diff --git a/chromium/cc/tiles/tiling_set_raster_queue_all.h b/chromium/cc/tiles/tiling_set_raster_queue_all.h index 62d22493730..d6f79463fed 100644 --- a/chromium/cc/tiles/tiling_set_raster_queue_all.h +++ b/chromium/cc/tiles/tiling_set_raster_queue_all.h @@ -41,7 +41,7 @@ class CC_EXPORT TilingSetRasterQueueAll { protected: ~OnePriorityRectIterator() = default; - bool TileNeedsRaster(Tile* tile) const { + bool TileNeedsRaster(const Tile* tile) const { return tile->draw_info().NeedsRaster() && !tiling_->IsTileOccluded(tile); } @@ -49,11 +49,13 @@ class CC_EXPORT TilingSetRasterQueueAll { void AdvanceToNextTile(TilingIteratorType* iterator); template <typename TilingIteratorType> bool GetFirstTileAndCheckIfValid(TilingIteratorType* iterator); + bool IsTileValid(const Tile* tile) const; PrioritizedTile current_tile_; PictureLayerTiling* tiling_; TilingData* tiling_data_; PictureLayerTiling::PriorityRectType priority_rect_type_; + gfx::Rect pending_visible_rect_; }; // Iterates over visible rect only, left to right top to bottom order. @@ -90,7 +92,6 @@ class CC_EXPORT TilingSetRasterQueueAll { private: TilingData::SpiralDifferenceIterator iterator_; - gfx::Rect pending_visible_rect_; }; // Iterates over soon border only, spiral around the visible rect. @@ -104,7 +105,6 @@ class CC_EXPORT TilingSetRasterQueueAll { private: TilingData::SpiralDifferenceIterator iterator_; - gfx::Rect pending_visible_rect_; }; // Iterates over eventually rect only, spiral around the soon rect. @@ -118,7 +118,6 @@ class CC_EXPORT TilingSetRasterQueueAll { private: TilingData::SpiralDifferenceIterator iterator_; - gfx::Rect pending_visible_rect_; }; // Iterates over all of the above phases in the following order: visible, @@ -174,6 +173,7 @@ class CC_EXPORT TilingSetRasterQueueAll { NUM_ITERATORS }; + void MakeTilingIterator(IteratorType type, PictureLayerTiling* tiling); void AdvanceToNextStage(); PictureLayerTilingSet* tiling_set_; diff --git a/chromium/cc/tiles/tiling_set_raster_queue_required.cc b/chromium/cc/tiles/tiling_set_raster_queue_required.cc index 07b123484c5..59696e40d22 100644 --- a/chromium/cc/tiles/tiling_set_raster_queue_required.cc +++ b/chromium/cc/tiles/tiling_set_raster_queue_required.cc @@ -41,7 +41,7 @@ TilingSetRasterQueueRequired::TilingSetRasterQueueRequired( // If we don't have a tiling, then this queue will yield no tiles. See // PictureLayerImpl::CanHaveTilings for examples of when a HIGH_RESOLUTION // tiling would not be generated. - if (!tiling) + if (!tiling || tiling->all_tiles_done()) return; if (type == RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION) { diff --git a/chromium/cc/trees/blocking_task_runner.cc b/chromium/cc/trees/blocking_task_runner.cc index 1111e9bf4b7..b0a935e2529 100644 --- a/chromium/cc/trees/blocking_task_runner.cc +++ b/chromium/cc/trees/blocking_task_runner.cc @@ -8,7 +8,6 @@ #include "base/callback.h" #include "base/logging.h" -#include "base/message_loop/message_loop_proxy.h" namespace cc { diff --git a/chromium/cc/trees/damage_tracker.cc b/chromium/cc/trees/damage_tracker.cc index 235dfcfd7ef..de11b47c1a9 100644 --- a/chromium/cc/trees/damage_tracker.cc +++ b/chromium/cc/trees/damage_tracker.cc @@ -288,6 +288,7 @@ void DamageTracker::ExtendDamageForLayer(LayerImpl* layer, gfx::RectF damage_rect = gfx::UnionRects(layer->update_rect(), layer->damage_rect()); + damage_rect.Intersect(gfx::RectF(layer->bounds())); if (layer_is_new || layer->LayerPropertyChanged()) { // If a layer is new or has changed, then its entire layer rect affects the @@ -300,9 +301,8 @@ void DamageTracker::ExtendDamageForLayer(LayerImpl* layer, } else if (!damage_rect.IsEmpty()) { // If the layer properties haven't changed, then the the target surface is // only affected by the layer's damaged area, which could be empty. - gfx::Rect damage_content_rect = layer->LayerRectToContentRect(damage_rect); - gfx::Rect damage_rect_in_target_space = MathUtil::MapEnclosingClippedRect( - layer->draw_transform(), damage_content_rect); + gfx::Rect damage_rect_in_target_space = gfx::ToEnclosingRect( + MathUtil::MapClippedRect(layer->draw_transform(), damage_rect)); target_damage_rect->Union(damage_rect_in_target_space); } } diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc index 2df71ddf2a7..831b1f718ec 100644 --- a/chromium/cc/trees/damage_tracker_unittest.cc +++ b/chromium/cc/trees/damage_tracker_unittest.cc @@ -14,6 +14,7 @@ #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host_common.h" +#include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/effects/SkBlurImageFilter.h" @@ -47,6 +48,7 @@ void ClearDamageForAllSurfaces(LayerImpl* layer) { } void EmulateDrawingOneFrame(LayerImpl* root) { + root->layer_tree_impl()->property_trees()->needs_rebuild = true; // This emulates only steps that are relevant to testing the damage tracker: // 1. computing the render passes and layerlists // 2. updating all damage trackers in the correct order @@ -58,16 +60,17 @@ void EmulateDrawingOneFrame(LayerImpl* root) { // Iterate back-to-front, so that damage correctly propagates from descendant // surfaces to ancestors. - for (int i = render_surface_layer_list.size() - 1; i >= 0; --i) { + size_t render_surface_layer_list_size = render_surface_layer_list.size(); + for (size_t i = 0; i < render_surface_layer_list_size; ++i) { + size_t index = render_surface_layer_list_size - 1 - i; RenderSurfaceImpl* target_surface = - render_surface_layer_list[i]->render_surface(); + render_surface_layer_list[index]->render_surface(); target_surface->damage_tracker()->UpdateDamageTrackingState( - target_surface->layer_list(), - target_surface->OwningLayerId(), + target_surface->layer_list(), target_surface->OwningLayerId(), target_surface->SurfacePropertyChangedOnlyFromDescendant(), target_surface->content_rect(), - render_surface_layer_list[i]->mask_layer(), - render_surface_layer_list[i]->filters()); + render_surface_layer_list[index]->mask_layer(), + render_surface_layer_list[index]->filters()); } root->ResetAllChangeTrackingForSubtree(); @@ -86,14 +89,12 @@ class DamageTrackerTest : public testing::Test { root->SetPosition(gfx::PointF()); root->SetBounds(gfx::Size(500, 500)); - root->SetContentBounds(gfx::Size(500, 500)); root->SetDrawsContent(true); root->SetHasRenderSurface(true); root->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500)); child->SetPosition(gfx::PointF(100.f, 100.f)); child->SetBounds(gfx::Size(30, 30)); - child->SetContentBounds(gfx::Size(30, 30)); child->SetDrawsContent(true); root->AddChild(child.Pass()); @@ -118,14 +119,12 @@ class DamageTrackerTest : public testing::Test { root->SetPosition(gfx::PointF()); root->SetBounds(gfx::Size(500, 500)); - root->SetContentBounds(gfx::Size(500, 500)); root->SetDrawsContent(true); root->SetHasRenderSurface(true); root->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500)); child1->SetPosition(gfx::PointF(100.f, 100.f)); child1->SetBounds(gfx::Size(30, 30)); - child1->SetContentBounds(gfx::Size(30, 30)); // With a child that draws_content, opacity will cause the layer to create // its own RenderSurface. This layer does not draw, but is intended to // create its own RenderSurface. @@ -134,17 +133,14 @@ class DamageTrackerTest : public testing::Test { child2->SetPosition(gfx::PointF(11.f, 11.f)); child2->SetBounds(gfx::Size(18, 18)); - child2->SetContentBounds(gfx::Size(18, 18)); child2->SetDrawsContent(true); grand_child1->SetPosition(gfx::PointF(200.f, 200.f)); grand_child1->SetBounds(gfx::Size(6, 8)); - grand_child1->SetContentBounds(gfx::Size(6, 8)); grand_child1->SetDrawsContent(true); grand_child2->SetPosition(gfx::PointF(190.f, 190.f)); grand_child2->SetBounds(gfx::Size(6, 8)); - grand_child2->SetContentBounds(gfx::Size(6, 8)); grand_child2->SetDrawsContent(true); child1->AddChild(grand_child1.Pass()); @@ -469,7 +465,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) { // Set up the child child->SetPosition(gfx::PointF(0.f, 0.f)); child->SetBounds(gfx::Size(100, 100)); - child->SetContentBounds(gfx::Size(100, 100)); child->SetTransform(transform); EmulateDrawingOneFrame(root.get()); @@ -707,7 +702,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) { LayerImpl::Create(host_impl_.active_tree(), 3); child2->SetPosition(gfx::PointF(400.f, 380.f)); child2->SetBounds(gfx::Size(6, 8)); - child2->SetContentBounds(gfx::Size(6, 8)); child2->SetDrawsContent(true); root->AddChild(child2.Pass()); } @@ -756,7 +750,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForNewUnchangedLayer) { LayerImpl::Create(host_impl_.active_tree(), 3); child2->SetPosition(gfx::PointF(400.f, 380.f)); child2->SetBounds(gfx::Size(6, 8)); - child2->SetContentBounds(gfx::Size(6, 8)); child2->SetDrawsContent(true); child2->ResetAllChangeTrackingForSubtree(); // Sanity check the initial conditions of the test, if these asserts @@ -789,7 +782,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForMultipleLayers) { LayerImpl::Create(host_impl_.active_tree(), 3); child2->SetPosition(gfx::PointF(400.f, 380.f)); child2->SetBounds(gfx::Size(6, 8)); - child2->SetContentBounds(gfx::Size(6, 8)); child2->SetDrawsContent(true); root->AddChild(child2.Pass()); } @@ -1039,7 +1031,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplica) { LayerImpl::Create(host_impl_.active_tree(), 6); grand_child3->SetPosition(gfx::PointF(240.f, 240.f)); grand_child3->SetBounds(gfx::Size(10, 10)); - grand_child3->SetContentBounds(gfx::Size(10, 10)); grand_child3->SetDrawsContent(true); child1->AddChild(grand_child3.Pass()); } @@ -1141,7 +1132,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForMask) { LayerImpl::Create(host_impl_.active_tree(), 3); mask_layer->SetPosition(child->position()); mask_layer->SetBounds(child->bounds()); - mask_layer->SetContentBounds(child->bounds()); child->SetMaskLayer(mask_layer.Pass()); child->SetHasRenderSurface(true); } @@ -1154,7 +1144,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForMask) { LayerImpl::Create(host_impl_.active_tree(), 4); grand_child->SetPosition(gfx::PointF(2.f, 2.f)); grand_child->SetBounds(gfx::Size(2, 2)); - grand_child->SetContentBounds(gfx::Size(2, 2)); grand_child->SetDrawsContent(true); child->AddChild(grand_child.Pass()); } @@ -1243,7 +1232,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplicaMask) { LayerImpl::Create(host_impl_.active_tree(), 7); replica_mask_layer->SetPosition(gfx::PointF()); replica_mask_layer->SetBounds(grand_child1->bounds()); - replica_mask_layer->SetContentBounds(grand_child1->bounds()); grand_child1_replica->SetMaskLayer(replica_mask_layer.Pass()); } LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer(); @@ -1322,7 +1310,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplicaMaskWithTransformOrigin) { replica_mask_layer->SetPosition(gfx::PointF()); // Note: this is not the transform origin being tested. replica_mask_layer->SetBounds(grand_child1->bounds()); - replica_mask_layer->SetContentBounds(grand_child1->bounds()); grand_child1_replica->SetMaskLayer(replica_mask_layer.Pass()); } LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer(); @@ -1456,7 +1443,6 @@ TEST_F(DamageTrackerTest, HugeDamageRect) { // but has a huge negative position. child->SetPosition(gfx::PointF()); child->SetBounds(gfx::Size(kBigNumber + i, kBigNumber + i)); - child->SetContentBounds(gfx::Size(kBigNumber + i, kBigNumber + i)); child->SetTransform(transform); EmulateDrawingOneFrame(root.get()); diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc index b1b4de1dd74..9f63421ed94 100644 --- a/chromium/cc/trees/draw_property_utils.cc +++ b/chromium/cc/trees/draw_property_utils.cc @@ -270,7 +270,7 @@ static bool LayerShouldBeSkipped(LayerType* layer, // Some additional conditions need to be computed at a later point after the // recursion is finished. // - the intersection of render_surface content and layer clip_rect is empty - // - the visible_content_rect is empty + // - the visible_layer_rect is empty // // Note, if the layer should not have been drawn due to being fully // transparent, we would have skipped the entire subtree and never made it @@ -430,6 +430,14 @@ void ComputeTransforms(TransformTree* transform_tree) { transform_tree->set_needs_update(false); } +void ComputeOpacities(OpacityTree* opacity_tree) { + if (!opacity_tree->needs_update()) + return; + for (int i = 1; i < static_cast<int>(opacity_tree->size()); ++i) + opacity_tree->UpdateOpacities(i); + opacity_tree->set_needs_update(false); +} + template <typename LayerType> void ComputeVisibleRectsUsingPropertyTreesInternal( LayerType* root_layer, @@ -439,6 +447,7 @@ void ComputeVisibleRectsUsingPropertyTreesInternal( property_trees->clip_tree.set_needs_update(true); ComputeTransforms(&property_trees->transform_tree); ComputeClips(&property_trees->clip_tree, property_trees->transform_tree); + ComputeOpacities(&property_trees->opacity_tree); const bool subtree_is_visible_from_ancestor = true; std::vector<LayerType*> visible_layer_list; @@ -453,6 +462,8 @@ void ComputeVisibleRectsUsingPropertyTreesInternal( void BuildPropertyTreesAndComputeVisibleRects( Layer* root_layer, const Layer* page_scale_layer, + const Layer* inner_viewport_scroll_layer, + const Layer* outer_viewport_scroll_layer, float page_scale_factor, float device_scale_factor, const gfx::Rect& viewport, @@ -460,7 +471,8 @@ void BuildPropertyTreesAndComputeVisibleRects( PropertyTrees* property_trees, LayerList* update_layer_list) { PropertyTreeBuilder::BuildPropertyTrees( - root_layer, page_scale_layer, page_scale_factor, device_scale_factor, + root_layer, page_scale_layer, inner_viewport_scroll_layer, + outer_viewport_scroll_layer, page_scale_factor, device_scale_factor, viewport, device_transform, property_trees); ComputeVisibleRectsUsingPropertyTrees(root_layer, property_trees, update_layer_list); @@ -469,6 +481,8 @@ void BuildPropertyTreesAndComputeVisibleRects( void BuildPropertyTreesAndComputeVisibleRects( LayerImpl* root_layer, const LayerImpl* page_scale_layer, + const LayerImpl* inner_viewport_scroll_layer, + const LayerImpl* outer_viewport_scroll_layer, float page_scale_factor, float device_scale_factor, const gfx::Rect& viewport, @@ -476,7 +490,8 @@ void BuildPropertyTreesAndComputeVisibleRects( PropertyTrees* property_trees, LayerImplList* update_layer_list) { PropertyTreeBuilder::BuildPropertyTrees( - root_layer, page_scale_layer, page_scale_factor, device_scale_factor, + root_layer, page_scale_layer, inner_viewport_scroll_layer, + outer_viewport_scroll_layer, page_scale_factor, device_scale_factor, viewport, device_transform, property_trees); ComputeVisibleRectsUsingPropertyTrees(root_layer, property_trees, update_layer_list); @@ -501,10 +516,6 @@ gfx::Transform DrawTransformFromPropertyTreesInternal( const LayerType* layer, const TransformTree& tree) { const TransformNode* node = tree.Node(layer->transform_tree_index()); - // TODO(vollick): ultimately we'll need to find this information (whether or - // not we establish a render surface) somewhere other than the layer. - const TransformNode* target_node = - layer->render_surface() ? node : tree.Node(node->data.content_target_id); gfx::Transform xform; const bool owns_non_root_surface = layer->parent() && layer->render_surface(); @@ -518,8 +529,7 @@ gfx::Transform DrawTransformFromPropertyTreesInternal( layer->offset_to_transform_parent().y()); } else { // Surfaces need to apply their sublayer scale. - xform.Scale(target_node->data.sublayer_scale.x(), - target_node->data.sublayer_scale.y()); + xform.Scale(node->data.sublayer_scale.x(), node->data.sublayer_scale.y()); } return xform; } @@ -576,7 +586,7 @@ float DrawOpacityFromPropertyTreesInternal(LayerType layer, float draw_opacity = 1.f; while (node != target_node) { - draw_opacity *= node->data; + draw_opacity *= node->data.opacity; node = tree.parent(node); } return draw_opacity; @@ -592,4 +602,34 @@ float DrawOpacityFromPropertyTrees(const LayerImpl* layer, return DrawOpacityFromPropertyTreesInternal(layer, tree); } +bool CanUseLcdTextFromPropertyTrees(const LayerImpl* layer, + bool layers_always_allowed_lcd_text, + bool can_use_lcd_text, + PropertyTrees* property_trees) { + if (layers_always_allowed_lcd_text) + return true; + if (!can_use_lcd_text) + return false; + if (!layer->contents_opaque()) + return false; + DCHECK(!property_trees->transform_tree.needs_update()); + DCHECK(!property_trees->opacity_tree.needs_update()); + + const OpacityNode* opacity_node = + property_trees->opacity_tree.Node(layer->opacity_tree_index()); + if (opacity_node->data.screen_space_opacity != 1.f) + return false; + const TransformNode* transform_node = + property_trees->transform_tree.Node(layer->transform_tree_index()); + if (!transform_node->data.node_and_ancestors_have_only_integer_translation) + return false; + if (static_cast<int>(layer->offset_to_transform_parent().x()) != + layer->offset_to_transform_parent().x()) + return false; + if (static_cast<int>(layer->offset_to_transform_parent().y()) != + layer->offset_to_transform_parent().y()) + return false; + return true; +} + } // namespace cc diff --git a/chromium/cc/trees/draw_property_utils.h b/chromium/cc/trees/draw_property_utils.h index 893645d7dd9..952bef1a691 100644 --- a/chromium/cc/trees/draw_property_utils.h +++ b/chromium/cc/trees/draw_property_utils.h @@ -33,28 +33,35 @@ ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree); // tree. This must be done prior to calling |ComputeClips|. void CC_EXPORT ComputeTransforms(TransformTree* transform_tree); +// Computes screen space opacity for every node in the opacity tree. +void CC_EXPORT ComputeOpacities(OpacityTree* opacity_tree); + // Computes the visible content rect for every layer under |root_layer|. The // visible content rect is the clipped content space rect that will be used for // recording. -void CC_EXPORT -BuildPropertyTreesAndComputeVisibleRects(Layer* root_layer, - const Layer* page_scale_layer, - float page_scale_factor, - float device_scale_factor, - const gfx::Rect& viewport, - const gfx::Transform& device_transform, - PropertyTrees* property_trees, - LayerList* update_layer_list); - -void CC_EXPORT -BuildPropertyTreesAndComputeVisibleRects(LayerImpl* root_layer, - const LayerImpl* page_scale_layer, - float page_scale_factor, - float device_scale_factor, - const gfx::Rect& viewport, - const gfx::Transform& device_transform, - PropertyTrees* property_trees, - LayerImplList* update_layer_list); +void CC_EXPORT BuildPropertyTreesAndComputeVisibleRects( + Layer* root_layer, + const Layer* page_scale_layer, + const Layer* inner_viewport_scroll_layer, + const Layer* outer_viewport_scroll_layer, + float page_scale_factor, + float device_scale_factor, + const gfx::Rect& viewport, + const gfx::Transform& device_transform, + PropertyTrees* property_trees, + LayerList* update_layer_list); + +void CC_EXPORT BuildPropertyTreesAndComputeVisibleRects( + LayerImpl* root_layer, + const LayerImpl* page_scale_layer, + const LayerImpl* inner_viewport_scroll_layer, + const LayerImpl* outer_viewport_scroll_layer, + float page_scale_factor, + float device_scale_factor, + const gfx::Rect& viewport, + const gfx::Transform& device_transform, + PropertyTrees* property_trees, + LayerImplList* update_layer_list); void CC_EXPORT ComputeVisibleRectsUsingPropertyTrees(Layer* root_layer, @@ -87,6 +94,12 @@ DrawOpacityFromPropertyTrees(const Layer* layer, const OpacityTree& tree); float CC_EXPORT DrawOpacityFromPropertyTrees(const LayerImpl* layer, const OpacityTree& tree); +bool CC_EXPORT +CanUseLcdTextFromPropertyTrees(const LayerImpl* layer, + bool layers_always_allowed_lcd_text, + bool can_use_lcd_text, + PropertyTrees* property_trees); + } // namespace cc #endif // CC_TREES_DRAW_PROPERTY_UTILS_H_ diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index 6c4696ee10b..a348301ba49 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -20,6 +20,7 @@ #include "base/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/animation/animation_host.h" #include "cc/animation/animation_registrar.h" #include "cc/animation/layer_animation_controller.h" #include "cc/base/math_util.h" @@ -35,7 +36,6 @@ #include "cc/layers/layer_iterator.h" #include "cc/layers/painted_scrollbar_layer.h" #include "cc/layers/render_surface.h" -#include "cc/resources/prioritized_resource_manager.h" #include "cc/resources/ui_resource_request.h" #include "cc/scheduler/begin_frame_source.h" #include "cc/trees/draw_property_utils.h" @@ -43,7 +43,6 @@ #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" -#include "cc/trees/occlusion_tracker.h" #include "cc/trees/single_thread_proxy.h" #include "cc/trees/thread_proxy.h" #include "cc/trees/tree_synchronizer.h" @@ -94,6 +93,7 @@ LayerTreeHost::LayerTreeHost(InitParams* params) needs_meta_info_recomputation_(true), client_(params->client), source_frame_number_(0), + meta_information_sequence_number_(1), rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()), output_surface_lost_(true), settings_(*params->settings), @@ -111,7 +111,6 @@ LayerTreeHost::LayerTreeHost(InitParams* params) gpu_rasterization_histogram_recorded_(false), background_color_(SK_ColorWHITE), has_transparent_background_(false), - partial_texture_update_requests_(0), did_complete_scale_animation_(false), in_paint_layer_contents_(false), id_(s_layer_tree_host_sequence_number.GetNext() + 1), @@ -121,8 +120,17 @@ LayerTreeHost::LayerTreeHost(InitParams* params) task_graph_runner_(params->task_graph_runner), surface_id_namespace_(0u), next_surface_sequence_(1u) { - if (settings_.accelerated_animation_enabled) - animation_registrar_ = AnimationRegistrar::Create(); + DCHECK(task_graph_runner_); + + if (settings_.accelerated_animation_enabled) { + if (settings_.use_compositor_animation_timelines) { + animation_host_ = AnimationHost::Create(ThreadInstance::MAIN); + animation_host_->SetMutatorHostClient(this); + } else { + animation_registrar_ = AnimationRegistrar::Create(); + } + } + rendering_stats_instrumentation_->set_record_rendering_stats( debug_state_.RecordRenderingStats()); } @@ -158,14 +166,21 @@ void LayerTreeHost::InitializeProxy(scoped_ptr<Proxy> proxy) { proxy_ = proxy.Pass(); proxy_->Start(); if (settings_.accelerated_animation_enabled) { - animation_registrar_->set_supports_scroll_animations( - proxy_->SupportsImplScrolling()); + if (animation_host_) + animation_host_->SetSupportsScrollAnimations( + proxy_->SupportsImplScrolling()); + else + animation_registrar_->set_supports_scroll_animations( + proxy_->SupportsImplScrolling()); } } LayerTreeHost::~LayerTreeHost() { TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost"); + if (animation_host_) + animation_host_->SetMutatorHostClient(nullptr); + if (root_layer_.get()) root_layer_->SetLayerTreeHost(NULL); @@ -193,13 +208,6 @@ void LayerTreeHost::SetLayerTreeHostClientReady() { proxy_->SetLayerTreeHostClientReady(); } -void LayerTreeHost::DeleteContentsTexturesOnImplThread( - ResourceProvider* resource_provider) { - DCHECK(proxy_->IsImplThread()); - if (contents_texture_manager_) - contents_texture_manager_->ClearAllMemory(resource_provider); -} - void LayerTreeHost::WillBeginMainFrame() { devtools_instrumentation::WillBeginMainThreadFrame(id(), source_frame_number()); @@ -241,32 +249,6 @@ void LayerTreeHost::BeginCommitOnImplThread(LayerTreeHostImpl* host_impl) { void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) { DCHECK(proxy_->IsImplThread()); - // If there are linked evicted backings, these backings' resources may be put - // into the impl tree, so we can't draw yet. Determine this before clearing - // all evicted backings. - bool new_impl_tree_has_no_evicted_resources = false; - if (contents_texture_manager_) { - new_impl_tree_has_no_evicted_resources = - !contents_texture_manager_->LinkedEvictedBackingsExist(); - - // If the memory limit has been increased since this now-finishing - // commit began, and the extra now-available memory would have been used, - // then request another commit. - if (contents_texture_manager_->MaxMemoryLimitBytes() < - host_impl->memory_allocation_limit_bytes() && - contents_texture_manager_->MaxMemoryLimitBytes() < - contents_texture_manager_->MaxMemoryNeededBytes()) { - host_impl->SetNeedsCommit(); - } - - host_impl->set_max_memory_needed_bytes( - contents_texture_manager_->MaxMemoryNeededBytes()); - - contents_texture_manager_->UpdateBackingsState( - host_impl->resource_provider()); - contents_texture_manager_->ReduceMemory(host_impl->resource_provider()); - } - bool is_new_trace; TRACE_EVENT_IS_NEW_TRACE(&is_new_trace); if (is_new_trace && @@ -317,6 +299,8 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) { sync_tree->RegisterSelection(selection_); + // Setting property trees must happen before pushing the page scale. + sync_tree->SetPropertyTrees(property_trees_); sync_tree->PushPageScaleFromMainThread( page_scale_factor_, min_page_scale_factor_, max_page_scale_factor_); sync_tree->elastic_overscroll()->PushFromMainThread(elastic_overscroll_); @@ -350,30 +334,38 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) { DCHECK(!sync_tree->ViewportSizeInvalid()); - if (new_impl_tree_has_no_evicted_resources) { - if (sync_tree->ContentsTexturesPurged()) - sync_tree->ResetContentsTexturesPurged(); - } - sync_tree->set_has_ever_been_drawn(false); - sync_tree->SetPropertyTrees(property_trees_); { TRACE_EVENT0("cc", "LayerTreeHost::PushProperties"); TreeSynchronizer::PushProperties(root_layer(), sync_tree->root_layer()); + + if (animation_host_) { + DCHECK(host_impl->animation_host()); + animation_host_->PushPropertiesTo(host_impl->animation_host()); + } } + // This must happen after synchronizing property trees and after push + // properties, which updates property tree indices. + sync_tree->UpdatePropertyTreeScrollingAndAnimationFromMainThread(); + micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl); } void LayerTreeHost::WillCommit() { + OnCommitForSwapPromises(); client_->WillCommit(); } void LayerTreeHost::UpdateHudLayer() { if (debug_state_.ShowHudInfo()) { - if (!hud_layer_.get()) - hud_layer_ = HeadsUpDisplayLayer::Create(); + if (!hud_layer_.get()) { + LayerSettings hud_layer_settings; + hud_layer_settings.use_compositor_animation_timelines = + settings_.use_compositor_animation_timelines; + hud_layer_ = HeadsUpDisplayLayer::Create(hud_layer_settings); + } if (root_layer_.get() && !hud_layer_->parent()) root_layer_->AddChild(hud_layer_); @@ -406,19 +398,10 @@ void LayerTreeHost::RequestNewOutputSurface() { void LayerTreeHost::DidInitializeOutputSurface() { output_surface_lost_ = false; - - if (!contents_texture_manager_ && !settings_.impl_side_painting) { - contents_texture_manager_ = - PrioritizedResourceManager::Create(proxy_.get()); - surface_memory_placeholder_ = - contents_texture_manager_->CreateTexture(gfx::Size(), RGBA_8888); - } - if (root_layer()) { LayerTreeHostCommon::CallFunctionForSubtree( root_layer(), [](Layer* layer) { layer->OnOutputSurfaceCreated(); }); } - client_->DidInitializeOutputSurface(); } @@ -493,12 +476,6 @@ void LayerTreeHost::SetNeedsUpdateLayers() { } void LayerTreeHost::SetNeedsCommit() { - if (!prepaint_callback_.IsCancelled()) { - TRACE_EVENT_INSTANT0("cc", - "LayerTreeHost::SetNeedsCommit::cancel prepaint", - TRACE_EVENT_SCOPE_THREAD); - prepaint_callback_.Cancel(); - } proxy_->SetNeedsCommit(); NotifySwapPromiseMonitorsOfSetNeedsCommit(); } @@ -543,7 +520,10 @@ void LayerTreeHost::SetNextCommitForcesRedraw() { void LayerTreeHost::SetAnimationEvents( scoped_ptr<AnimationEventsVector> events) { DCHECK(proxy_->IsMainThread()); - animation_registrar_->SetAnimationEvents(events.Pass()); + if (animation_host_) + animation_host_->SetAnimationEvents(events.Pass()); + else + animation_registrar_->SetAnimationEvents(events.Pass()); } void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) { @@ -679,6 +659,16 @@ void LayerTreeHost::NotifyInputThrottledUntilCommit() { proxy_->NotifyInputThrottledUntilCommit(); } +void LayerTreeHost::LayoutAndUpdateLayers() { + DCHECK(!proxy_->HasImplThread()); + // This function is only valid when not using the scheduler. + DCHECK(!settings_.single_thread_proxy_scheduler); + SingleThreadProxy* proxy = static_cast<SingleThreadProxy*>(proxy_.get()); + + SetLayerTreeHostClientReady(); + proxy->LayoutAndUpdateLayers(); +} + void LayerTreeHost::Composite(base::TimeTicks frame_begin_time) { DCHECK(!proxy_->HasImplThread()); // This function is only valid when not using the scheduler. @@ -689,18 +679,13 @@ void LayerTreeHost::Composite(base::TimeTicks frame_begin_time) { proxy->CompositeImmediately(frame_begin_time); } -bool LayerTreeHost::UpdateLayers(ResourceUpdateQueue* queue) { +bool LayerTreeHost::UpdateLayers() { DCHECK(!output_surface_lost_); - if (!root_layer()) return false; - DCHECK(!root_layer()->parent()); - - bool result = UpdateLayers(root_layer(), queue); - + bool result = DoUpdateLayers(root_layer()); micro_benchmark_controller_.DidUpdateLayers(); - return result || next_commit_forces_redraw_; } @@ -725,8 +710,7 @@ static Layer* FindFirstScrollableLayer(Layer* layer) { } void LayerTreeHost::RecordGpuRasterizationHistogram() { - // Gpu rasterization is only supported when impl-side painting is enabled. - if (gpu_rasterization_histogram_recorded_ || !settings_.impl_side_painting) + if (gpu_rasterization_histogram_recorded_) return; // Record how widely gpu rasterization is enabled. @@ -753,10 +737,9 @@ bool LayerTreeHost::UsingSharedMemoryResources() { return GetRendererCapabilities().using_shared_memory_resources; } -bool LayerTreeHost::UpdateLayers(Layer* root_layer, - ResourceUpdateQueue* queue) { - TRACE_EVENT1("cc", "LayerTreeHost::UpdateLayers", - "source_frame_number", source_frame_number()); +bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { + TRACE_EVENT1("cc", "LayerTreeHost::DoUpdateLayers", "source_frame_number", + source_frame_number()); RenderSurfaceLayerList render_surface_layer_list; @@ -781,6 +764,7 @@ bool LayerTreeHost::UpdateLayers(Layer* root_layer, LayerTreeHostCommon::CalcDrawPropsMainInputs inputs( root_layer, device_viewport_size(), gfx::Transform(), device_scale_factor_, page_scale_factor_, page_scale_layer, + inner_viewport_scroll_layer_.get(), outer_viewport_scroll_layer_.get(), elastic_overscroll_, overscroll_elasticity_layer_.get(), GetRendererCapabilities().max_texture_size, settings_.can_use_lcd_text, settings_.layers_always_allowed_lcd_text, can_render_to_separate_surface, @@ -788,79 +772,43 @@ bool LayerTreeHost::UpdateLayers(Layer* root_layer, settings_.verify_property_trees, &render_surface_layer_list, render_surface_layer_list_id, &property_trees_); - // This is a temporary state of affairs until impl-side painting is shipped - // everywhere and main thread property trees can be used in all cases. - // This code here implies that even if verify property trees is on, - // no verification will occur and only property trees will be used on the - // main thread. - if (using_only_property_trees()) { - TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps"); - - LayerTreeHostCommon::PreCalculateMetaInformation(root_layer); - - bool preserves_2d_axis_alignment = false; - gfx::Transform identity_transform; - LayerList update_layer_list; - - LayerTreeHostCommon::UpdateRenderSurfaces( - root_layer, can_render_to_separate_surface, identity_transform, - preserves_2d_axis_alignment); - { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), - "LayerTreeHostCommon::ComputeVisibleRectsWithPropertyTrees"); - BuildPropertyTreesAndComputeVisibleRects( - root_layer, page_scale_layer, page_scale_factor_, - device_scale_factor_, gfx::Rect(device_viewport_size_), - identity_transform, &property_trees_, &update_layer_list); - } + TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps"); - for (const auto& layer : update_layer_list) - layer->SavePaintProperties(); - - base::AutoReset<bool> painting(&in_paint_layer_contents_, true); - bool did_paint_content = false; - for (const auto& layer : update_layer_list) { - // TODO(enne): temporarily clobber draw properties visible rect. - layer->draw_properties().visible_content_rect = - layer->visible_rect_from_property_trees(); - did_paint_content |= layer->Update(queue, nullptr); - content_is_suitable_for_gpu_rasterization_ &= - layer->IsSuitableForGpuRasterization(); - } - return did_paint_content; - } + LayerTreeHostCommon::PreCalculateMetaInformation(root_layer); + + bool preserves_2d_axis_alignment = false; + gfx::Transform identity_transform; + LayerList update_layer_list; + LayerTreeHostCommon::UpdateRenderSurfaces( + root_layer, can_render_to_separate_surface, identity_transform, + preserves_2d_axis_alignment); { - TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps"); - LayerTreeHostCommon::CalculateDrawProperties(&inputs); + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), + "LayerTreeHostCommon::ComputeVisibleRectsWithPropertyTrees"); + BuildPropertyTreesAndComputeVisibleRects( + root_layer, page_scale_layer, inner_viewport_scroll_layer_.get(), + outer_viewport_scroll_layer_.get(), page_scale_factor_, + device_scale_factor_, gfx::Rect(device_viewport_size_), + identity_transform, &property_trees_, &update_layer_list); } - // Reset partial texture update requests. - partial_texture_update_requests_ = 0; + for (const auto& layer : update_layer_list) + layer->SavePaintProperties(); + base::AutoReset<bool> painting(&in_paint_layer_contents_, true); bool did_paint_content = false; - bool need_more_updates = false; - PaintLayerContents(render_surface_layer_list, queue, &did_paint_content, - &need_more_updates); - if (need_more_updates) { - TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::posting prepaint task"); - prepaint_callback_.Reset(base::Bind(&LayerTreeHost::TriggerPrepaint, - base::Unretained(this))); - static base::TimeDelta prepaint_delay = - base::TimeDelta::FromMilliseconds(100); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, prepaint_callback_.callback(), prepaint_delay); + for (const auto& layer : update_layer_list) { + // TODO(enne): temporarily clobber draw properties visible rect. + layer->draw_properties().visible_layer_rect = + layer->visible_rect_from_property_trees(); + did_paint_content |= layer->Update(); + content_is_suitable_for_gpu_rasterization_ &= + layer->IsSuitableForGpuRasterization(); } - return did_paint_content; } -void LayerTreeHost::TriggerPrepaint() { - prepaint_callback_.Cancel(); - TRACE_EVENT0("cc", "LayerTreeHost::TriggerPrepaint"); - SetNeedsCommit(); -} - void LayerTreeHost::ReduceMemoryUsage() { if (!root_layer()) return; @@ -869,154 +817,6 @@ void LayerTreeHost::ReduceMemoryUsage() { root_layer(), [](Layer* layer) { layer->ReduceMemoryUsage(); }); } -void LayerTreeHost::SetPrioritiesForSurfaces(size_t surface_memory_bytes) { - DCHECK(surface_memory_placeholder_); - - // Surfaces have a place holder for their memory since they are managed - // independantly but should still be tracked and reduce other memory usage. - surface_memory_placeholder_->SetTextureManager( - contents_texture_manager_.get()); - surface_memory_placeholder_->set_request_priority( - PriorityCalculator::RenderSurfacePriority()); - surface_memory_placeholder_->SetToSelfManagedMemoryPlaceholder( - surface_memory_bytes); -} - -void LayerTreeHost::SetPrioritiesForLayers( - const RenderSurfaceLayerList& update_list) { - PriorityCalculator calculator; - typedef LayerIterator<Layer> LayerIteratorType; - LayerIteratorType end = LayerIteratorType::End(&update_list); - for (LayerIteratorType it = LayerIteratorType::Begin(&update_list); - it != end; - ++it) { - if (it.represents_itself()) { - it->SetTexturePriorities(calculator); - } else if (it.represents_target_render_surface()) { - if (it->mask_layer()) - it->mask_layer()->SetTexturePriorities(calculator); - if (it->replica_layer() && it->replica_layer()->mask_layer()) - it->replica_layer()->mask_layer()->SetTexturePriorities(calculator); - } - } -} - -void LayerTreeHost::PrioritizeTextures( - const RenderSurfaceLayerList& render_surface_layer_list) { - if (!contents_texture_manager_) - return; - - contents_texture_manager_->ClearPriorities(); - - size_t memory_for_render_surfaces_metric = - CalculateMemoryForRenderSurfaces(render_surface_layer_list); - - SetPrioritiesForLayers(render_surface_layer_list); - SetPrioritiesForSurfaces(memory_for_render_surfaces_metric); - - contents_texture_manager_->PrioritizeTextures(); -} - -size_t LayerTreeHost::CalculateMemoryForRenderSurfaces( - const RenderSurfaceLayerList& update_list) { - size_t readback_bytes = 0; - size_t contents_texture_bytes = 0; - - // Start iteration at 1 to skip the root surface as it does not have a texture - // cost. - for (size_t i = 1; i < update_list.size(); ++i) { - Layer* render_surface_layer = update_list.at(i); - RenderSurface* render_surface = render_surface_layer->render_surface(); - - size_t bytes = - Resource::MemorySizeBytes(render_surface->content_rect().size(), - RGBA_8888); - contents_texture_bytes += bytes; - - if (render_surface_layer->background_filters().IsEmpty() && - render_surface_layer->uses_default_blend_mode()) - continue; - - if (!readback_bytes) { - readback_bytes = Resource::MemorySizeBytes(device_viewport_size_, - RGBA_8888); - } - } - return readback_bytes + contents_texture_bytes; -} - -void LayerTreeHost::PaintMasksForRenderSurface(Layer* render_surface_layer, - ResourceUpdateQueue* queue, - bool* did_paint_content, - bool* need_more_updates) { - // Note: Masks and replicas only exist for layers that own render surfaces. If - // we reach this point in code, we already know that at least something will - // be drawn into this render surface, so the mask and replica should be - // painted. - - Layer* mask_layer = render_surface_layer->mask_layer(); - if (mask_layer) { - *did_paint_content |= mask_layer->Update(queue, NULL); - *need_more_updates |= mask_layer->NeedMoreUpdates(); - } - - Layer* replica_mask_layer = - render_surface_layer->replica_layer() ? - render_surface_layer->replica_layer()->mask_layer() : NULL; - if (replica_mask_layer) { - *did_paint_content |= replica_mask_layer->Update(queue, NULL); - *need_more_updates |= replica_mask_layer->NeedMoreUpdates(); - } -} - -void LayerTreeHost::PaintLayerContents( - const RenderSurfaceLayerList& render_surface_layer_list, - ResourceUpdateQueue* queue, - bool* did_paint_content, - bool* need_more_updates) { - OcclusionTracker<Layer> occlusion_tracker( - root_layer_->render_surface()->content_rect()); - occlusion_tracker.set_minimum_tracking_size( - settings_.minimum_occlusion_tracking_size); - - PrioritizeTextures(render_surface_layer_list); - - in_paint_layer_contents_ = true; - - // Iterates front-to-back to allow for testing occlusion and performing - // culling during the tree walk. - typedef LayerIterator<Layer> LayerIteratorType; - LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list); - for (LayerIteratorType it = - LayerIteratorType::Begin(&render_surface_layer_list); - it != end; - ++it) { - occlusion_tracker.EnterLayer(it); - - if (it.represents_target_render_surface()) { - PaintMasksForRenderSurface( - *it, queue, did_paint_content, need_more_updates); - } else if (it.represents_itself()) { - DCHECK(!it->paint_properties().bounds.IsEmpty()); - *did_paint_content |= it->Update(queue, &occlusion_tracker); - *need_more_updates |= it->NeedMoreUpdates(); - // Note the '&&' with previous is-suitable state. - // This means that once the layer-tree becomes unsuitable for gpu - // rasterization due to some content, it will continue to be unsuitable - // even if that content is replaced by gpu-friendly content. - // This is to avoid switching back-and-forth between gpu and sw - // rasterization which may be both bad for performance and visually - // jarring. - content_is_suitable_for_gpu_rasterization_ &= - it->IsSuitableForGpuRasterization(); - } - - occlusion_tracker.LeaveLayer(it); - } - - in_paint_layer_contents_ = false; -} - void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) { ScopedPtrVector<SwapPromise>::iterator it = info->swap_promises.begin(); for (; it != info->swap_promises.end(); ++it) { @@ -1071,22 +871,12 @@ void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) { ApplyPageScaleDeltaFromImplSide(info->page_scale_delta); elastic_overscroll_ += info->elastic_overscroll_delta; - if (!settings_.use_pinch_virtual_viewport) { - // TODO(miletus): Make sure either this code path is totally gone, - // or revisit the flooring here if the old pinch viewport code path - // is causing problems with fractional scroll offset. - client_->ApplyViewportDeltas( - gfx::ToFlooredVector2d(inner_viewport_scroll_delta + - outer_viewport_scroll_delta), - info->page_scale_delta, info->top_controls_delta); - } else { - // TODO(ccameron): pass the elastic overscroll here so that input events - // may be translated appropriately. - client_->ApplyViewportDeltas( - inner_viewport_scroll_delta, outer_viewport_scroll_delta, - info->elastic_overscroll_delta, info->page_scale_delta, - info->top_controls_delta); - } + // TODO(ccameron): pass the elastic overscroll here so that input events + // may be translated appropriately. + client_->ApplyViewportDeltas( + inner_viewport_scroll_delta, outer_viewport_scroll_delta, + info->elastic_overscroll_delta, info->page_scale_delta, + info->top_controls_delta); } } @@ -1114,31 +904,6 @@ void LayerTreeHost::RateLimit() { client_->RateLimitSharedMainThreadContext(); } -bool LayerTreeHost::AlwaysUsePartialTextureUpdates() { - if (!proxy_->GetRendererCapabilities().allow_partial_texture_updates) - return false; - return !proxy_->HasImplThread(); -} - -size_t LayerTreeHost::MaxPartialTextureUpdates() const { - size_t max_partial_texture_updates = 0; - if (proxy_->GetRendererCapabilities().allow_partial_texture_updates && - !settings_.impl_side_painting) { - max_partial_texture_updates = - std::min(settings_.max_partial_texture_updates, - proxy_->MaxPartialTextureUpdates()); - } - return max_partial_texture_updates; -} - -bool LayerTreeHost::RequestPartialTextureUpdate() { - if (partial_texture_update_requests_ >= MaxPartialTextureUpdates()) - return false; - - partial_texture_update_requests_++; - return true; -} - void LayerTreeHost::SetDeviceScaleFactor(float device_scale_factor) { if (device_scale_factor == device_scale_factor_) return; @@ -1166,11 +931,16 @@ void LayerTreeHost::AnimateLayers(base::TimeTicks monotonic_time) { return; AnimationEventsVector events; - if (animation_registrar_->AnimateLayers(monotonic_time)) { - animation_registrar_->UpdateAnimationState(true, &events); - if (!events.empty()) - property_trees_.needs_rebuild = true; + if (animation_host_) { + if (animation_host_->AnimateLayers(monotonic_time)) + animation_host_->UpdateAnimationState(true, &events); + } else { + if (animation_registrar_->AnimateLayers(monotonic_time)) + animation_registrar_->UpdateAnimationState(true, &events); } + + if (!events.empty()) + property_trees_.needs_rebuild = true; } UIResourceId LayerTreeHost::CreateUIResource(UIResourceClient* client) { @@ -1284,6 +1054,11 @@ void LayerTreeHost::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) { swap_promise_list_.clear(); } +void LayerTreeHost::OnCommitForSwapPromises() { + for (auto* swap_promise : swap_promise_list_) + swap_promise->OnCommit(); +} + void LayerTreeHost::set_surface_id_namespace(uint32_t id_namespace) { surface_id_namespace_ = id_namespace; } @@ -1307,4 +1082,137 @@ void LayerTreeHost::SetAuthoritativeVSyncInterval( proxy_->SetAuthoritativeVSyncInterval(interval); } +void LayerTreeHost::RecordFrameTimingEvents( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) { + client_->RecordFrameTimingEvents(composite_events.Pass(), + main_frame_events.Pass()); +} + +Layer* LayerTreeHost::LayerById(int id) const { + LayerIdMap::const_iterator iter = layer_id_map_.find(id); + return iter != layer_id_map_.end() ? iter->second : NULL; +} + +void LayerTreeHost::RegisterLayer(Layer* layer) { + DCHECK(!LayerById(layer->id())); + DCHECK(!in_paint_layer_contents_); + layer_id_map_[layer->id()] = layer; + if (animation_host_) + animation_host_->RegisterLayer(layer->id(), LayerTreeType::ACTIVE); +} + +void LayerTreeHost::UnregisterLayer(Layer* layer) { + DCHECK(LayerById(layer->id())); + DCHECK(!in_paint_layer_contents_); + if (animation_host_) + animation_host_->UnregisterLayer(layer->id(), LayerTreeType::ACTIVE); + layer_id_map_.erase(layer->id()); +} + +bool LayerTreeHost::IsLayerInTree(int layer_id, LayerTreeType tree_type) const { + return tree_type == LayerTreeType::ACTIVE; +} + +void LayerTreeHost::SetMutatorsNeedCommit() { + SetNeedsCommit(); +} + +void LayerTreeHost::SetLayerFilterMutated(int layer_id, + LayerTreeType tree_type, + const FilterOperations& filters) { + LayerAnimationValueObserver* layer = LayerById(layer_id); + DCHECK(layer); + layer->OnFilterAnimated(filters); +} + +void LayerTreeHost::SetLayerOpacityMutated(int layer_id, + LayerTreeType tree_type, + float opacity) { + LayerAnimationValueObserver* layer = LayerById(layer_id); + DCHECK(layer); + layer->OnOpacityAnimated(opacity); +} + +void LayerTreeHost::SetLayerTransformMutated(int layer_id, + LayerTreeType tree_type, + const gfx::Transform& transform) { + LayerAnimationValueObserver* layer = LayerById(layer_id); + DCHECK(layer); + layer->OnTransformAnimated(transform); +} + +void LayerTreeHost::SetLayerScrollOffsetMutated( + int layer_id, + LayerTreeType tree_type, + const gfx::ScrollOffset& scroll_offset) { + LayerAnimationValueObserver* layer = LayerById(layer_id); + DCHECK(layer); + layer->OnScrollOffsetAnimated(scroll_offset); +} + +gfx::ScrollOffset LayerTreeHost::GetScrollOffsetForAnimation( + int layer_id) const { + LayerAnimationValueProvider* layer = LayerById(layer_id); + DCHECK(layer); + return layer->ScrollOffsetForAnimation(); +} + +bool LayerTreeHost::ScrollOffsetAnimationWasInterrupted( + const Layer* layer) const { + return animation_host_ + ? animation_host_->ScrollOffsetAnimationWasInterrupted(layer->id()) + : false; +} + +bool LayerTreeHost::IsAnimatingFilterProperty(const Layer* layer) const { + return animation_host_ + ? animation_host_->IsAnimatingFilterProperty(layer->id()) + : false; +} + +bool LayerTreeHost::IsAnimatingOpacityProperty(const Layer* layer) const { + return animation_host_ + ? animation_host_->IsAnimatingOpacityProperty(layer->id()) + : false; +} + +bool LayerTreeHost::IsAnimatingTransformProperty(const Layer* layer) const { + return animation_host_ + ? animation_host_->IsAnimatingTransformProperty(layer->id()) + : false; +} + +bool LayerTreeHost::HasPotentiallyRunningOpacityAnimation( + const Layer* layer) const { + return animation_host_ + ? animation_host_->HasPotentiallyRunningOpacityAnimation( + layer->id()) + : false; +} + +bool LayerTreeHost::HasPotentiallyRunningTransformAnimation( + const Layer* layer) const { + return animation_host_ + ? animation_host_->HasPotentiallyRunningTransformAnimation( + layer->id()) + : false; +} + +bool LayerTreeHost::AnimationsPreserveAxisAlignment(const Layer* layer) const { + return animation_host_ + ? animation_host_->AnimationsPreserveAxisAlignment(layer->id()) + : true; +} + +bool LayerTreeHost::HasAnyAnimation(const Layer* layer) const { + return animation_host_ ? animation_host_->HasAnyAnimation(layer->id()) + : false; +} + +bool LayerTreeHost::HasActiveAnimation(const Layer* layer) const { + return animation_host_ ? animation_host_->HasActiveAnimation(layer->id()) + : false; +} + } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index cf47facddd4..4f38352f9c6 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -21,6 +21,7 @@ #include "cc/animation/animation_events.h" #include "cc/base/cc_export.h" #include "cc/base/scoped_ptr_vector.h" +#include "cc/debug/frame_timing_tracker.h" #include "cc/debug/micro_benchmark.h" #include "cc/debug/micro_benchmark_controller.h" #include "cc/input/input_handler.h" @@ -37,6 +38,7 @@ #include "cc/trees/layer_tree_host_client.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_settings.h" +#include "cc/trees/mutator_host_client.h" #include "cc/trees/proxy.h" #include "cc/trees/swap_promise_monitor.h" #include "third_party/skia/include/core/SkColor.h" @@ -48,14 +50,13 @@ class GpuMemoryBufferManager; namespace cc { class AnimationRegistrar; +class AnimationHost; class BeginFrameSource; class HeadsUpDisplayLayer; class Layer; class LayerTreeHostImpl; class LayerTreeHostImplClient; class LayerTreeHostSingleThreadClient; -class PrioritizedResource; -class PrioritizedResourceManager; class PropertyTrees; class Region; class RenderingStatsInstrumentation; @@ -69,7 +70,7 @@ struct PendingPageScaleAnimation; struct RenderingStats; struct ScrollAndScaleSet; -class CC_EXPORT LayerTreeHost { +class CC_EXPORT LayerTreeHost : public MutatorHostClient { public: // TODO(sad): InitParams should be a movable type so that it can be // std::move()d to the Create* functions. @@ -120,8 +121,7 @@ class CC_EXPORT LayerTreeHost { bool output_surface_lost() const { return output_surface_lost_; } void DidCommitAndDrawFrame() { client_->DidCommitAndDrawFrame(); } void DidCompleteSwapBuffers() { client_->DidCompleteSwapBuffers(); } - void DeleteContentsTexturesOnImplThread(ResourceProvider* resource_provider); - bool UpdateLayers(ResourceUpdateQueue* queue); + bool UpdateLayers(); // Called when the compositor completed page scale animation. void DidCompletePageScaleAnimation(); @@ -133,6 +133,7 @@ class CC_EXPORT LayerTreeHost { void NotifyInputThrottledUntilCommit(); + void LayoutAndUpdateLayers(); void Composite(base::TimeTicks frame_begin_time); void FinishAllRendering(); @@ -141,6 +142,14 @@ class CC_EXPORT LayerTreeHost { int source_frame_number() const { return source_frame_number_; } + int meta_information_sequence_number() { + return meta_information_sequence_number_; + } + + void IncrementMetaInformationSequenceNumber() { + meta_information_sequence_number_++; + } + void SetNeedsDisplayOnAllLayers(); void CollectRenderingStats(RenderingStats* stats) const; @@ -218,10 +227,6 @@ class CC_EXPORT LayerTreeHost { has_transparent_background_ = transparent; } - PrioritizedResourceManager* contents_texture_manager() const { - return contents_texture_manager_.get(); - } - void SetVisible(bool visible); bool visible() const { return visible_; } @@ -241,10 +246,6 @@ class CC_EXPORT LayerTreeHost { void RateLimit(); - bool AlwaysUsePartialTextureUpdates(); - size_t MaxPartialTextureUpdates() const; - bool RequestPartialTextureUpdate(); - void SetDeviceScaleFactor(float device_scale_factor); float device_scale_factor() const { return device_scale_factor_; } @@ -255,10 +256,10 @@ class CC_EXPORT LayerTreeHost { HeadsUpDisplayLayer* hud_layer() const { return hud_layer_.get(); } Proxy* proxy() const { return proxy_.get(); } - AnimationRegistrar* animation_registrar() const { return animation_registrar_.get(); } + AnimationHost* animation_host() const { return animation_host_.get(); } bool in_paint_layer_contents() const { return in_paint_layer_contents_; } @@ -315,11 +316,41 @@ class CC_EXPORT LayerTreeHost { return needs_meta_info_recomputation_; } - // If this is true, only property trees will be used for main thread CDP. - // CDP will not be run, and verify_property_trees will be ignored. - bool using_only_property_trees() const { - return settings().impl_side_painting; - } + void RecordFrameTimingEvents( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events); + + Layer* LayerById(int id) const; + void RegisterLayer(Layer* layer); + void UnregisterLayer(Layer* layer); + // LayerTreeMutatorsClient implementation. + bool IsLayerInTree(int layer_id, LayerTreeType tree_type) const override; + void SetMutatorsNeedCommit() override; + void SetLayerFilterMutated(int layer_id, + LayerTreeType tree_type, + const FilterOperations& filters) override; + void SetLayerOpacityMutated(int layer_id, + LayerTreeType tree_type, + float opacity) override; + void SetLayerTransformMutated(int layer_id, + LayerTreeType tree_type, + const gfx::Transform& transform) override; + void SetLayerScrollOffsetMutated( + int layer_id, + LayerTreeType tree_type, + const gfx::ScrollOffset& scroll_offset) override; + void ScrollOffsetAnimationFinished() override {} + gfx::ScrollOffset GetScrollOffsetForAnimation(int layer_id) const override; + + bool ScrollOffsetAnimationWasInterrupted(const Layer* layer) const; + bool IsAnimatingFilterProperty(const Layer* layer) const; + bool IsAnimatingOpacityProperty(const Layer* layer) const; + bool IsAnimatingTransformProperty(const Layer* layer) const; + bool HasPotentiallyRunningOpacityAnimation(const Layer* layer) const; + bool HasPotentiallyRunningTransformAnimation(const Layer* layer) const; + bool AnimationsPreserveAxisAlignment(const Layer* layer) const; + bool HasAnyAnimation(const Layer* layer) const; + bool HasActiveAnimation(const Layer* layer) const; protected: explicit LayerTreeHost(InitParams* params); @@ -349,31 +380,16 @@ class CC_EXPORT LayerTreeHost { MicroBenchmarkController micro_benchmark_controller_; + void OnCommitForSwapPromises(); + private: void InitializeProxy(scoped_ptr<Proxy> proxy); - void PaintLayerContents( - const RenderSurfaceLayerList& render_surface_layer_list, - ResourceUpdateQueue* queue, - bool* did_paint_content, - bool* need_more_updates); - void PaintMasksForRenderSurface(Layer* render_surface_layer, - ResourceUpdateQueue* queue, - bool* did_paint_content, - bool* need_more_updates); - bool UpdateLayers(Layer* root_layer, ResourceUpdateQueue* queue); + bool DoUpdateLayers(Layer* root_layer); void UpdateHudLayer(); - void TriggerPrepaint(); void ReduceMemoryUsage(); - void PrioritizeTextures( - const RenderSurfaceLayerList& render_surface_layer_list); - void SetPrioritiesForSurfaces(size_t surface_memory_bytes); - void SetPrioritiesForLayers(const RenderSurfaceLayerList& update_list); - size_t CalculateMemoryForRenderSurfaces( - const RenderSurfaceLayerList& update_list); - bool AnimateLayersRecursive(Layer* current, base::TimeTicks time); struct UIResourceClientData { @@ -398,12 +414,11 @@ class CC_EXPORT LayerTreeHost { bool needs_full_tree_sync_; bool needs_meta_info_recomputation_; - base::CancelableClosure prepaint_callback_; - LayerTreeHostClient* client_; scoped_ptr<Proxy> proxy_; int source_frame_number_; + int meta_information_sequence_number_; scoped_ptr<RenderingStatsInstrumentation> rendering_stats_instrumentation_; bool output_surface_lost_; @@ -411,9 +426,6 @@ class CC_EXPORT LayerTreeHost { scoped_refptr<Layer> root_layer_; scoped_refptr<HeadsUpDisplayLayer> hud_layer_; - scoped_ptr<PrioritizedResourceManager> contents_texture_manager_; - scoped_ptr<PrioritizedResource> surface_memory_placeholder_; - base::WeakPtr<InputHandler> input_handler_weak_ptr_; base::WeakPtr<TopControlsManager> top_controls_manager_weak_ptr_; @@ -441,10 +453,8 @@ class CC_EXPORT LayerTreeHost { SkColor background_color_; bool has_transparent_background_; - typedef ScopedPtrVector<PrioritizedResource> TextureList; - size_t partial_texture_update_requests_; - scoped_ptr<AnimationRegistrar> animation_registrar_; + scoped_ptr<AnimationHost> animation_host_; scoped_ptr<PendingPageScaleAnimation> pending_page_scale_animation_; @@ -473,6 +483,9 @@ class CC_EXPORT LayerTreeHost { PropertyTrees property_trees_; + typedef base::hash_map<int, Layer*> LayerIdMap; + LayerIdMap layer_id_map_; + uint32_t surface_id_namespace_; uint32_t next_surface_sequence_; diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h index 6b305326ff9..56a128f4bad 100644 --- a/chromium/cc/trees/layer_tree_host_client.h +++ b/chromium/cc/trees/layer_tree_host_client.h @@ -8,6 +8,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" +#include "cc/debug/frame_timing_tracker.h" namespace gfx { class Vector2d; @@ -35,9 +36,6 @@ class LayerTreeHostClient { const gfx::Vector2dF& elastic_overscroll_delta, float page_scale, float top_controls_delta) = 0; - virtual void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, - float page_scale, - float top_controls_delta) = 0; // Request an OutputSurface from the client. When the client has one it should // call LayerTreeHost::SetOutputSurface. This will result in either // DidFailToInitializeOutputSurface or DidInitializeOutputSurface being @@ -49,6 +47,9 @@ class LayerTreeHostClient { virtual void DidCommit() = 0; virtual void DidCommitAndDrawFrame() = 0; virtual void DidCompleteSwapBuffers() = 0; + virtual void RecordFrameTimingEvents( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) = 0; // Called when page scale animation has completed. virtual void DidCompletePageScaleAnimation() = 0; diff --git a/chromium/cc/trees/layer_tree_host_common.cc b/chromium/cc/trees/layer_tree_host_common.cc index 09882856e55..427a3c825e1 100644 --- a/chromium/cc/trees/layer_tree_host_common.cc +++ b/chromium/cc/trees/layer_tree_host_common.cc @@ -302,8 +302,8 @@ void UpdateAccumulatedSurfaceState( current_target->render_surface()->draw_transform(); // If we have unclipped descendants, the draw transform is a translation. - DCHECK(current_target->num_unclipped_descendants() == 0 || - current_draw_transform.IsIdentityOrTranslation()); + DCHECK_IMPLIES(current_target->num_unclipped_descendants(), + current_draw_transform.IsIdentityOrTranslation()); target_rect = gfx::ToEnclosingRect( MathUtil::MapClippedRect(current_draw_transform, target_rect)); @@ -370,14 +370,14 @@ static inline bool LayerClipsSubtree(LayerType* layer) { } template <typename LayerType> -static gfx::Rect CalculateVisibleContentRect( +static gfx::Rect CalculateVisibleLayerRect( LayerType* layer, const gfx::Rect& clip_rect_of_target_surface_in_target_space, const gfx::Rect& layer_rect_in_target_space) { DCHECK(layer->render_target()); // Nothing is visible if the layer bounds are empty. - if (!layer->DrawsContent() || layer->content_bounds().IsEmpty() || + if (!layer->DrawsContent() || layer->bounds().IsEmpty() || layer->drawable_content_rect().IsEmpty()) return gfx::Rect(); @@ -403,10 +403,8 @@ static gfx::Rect CalculateVisibleContentRect( return gfx::Rect(); return CalculateVisibleRectWithCachedLayerRect( - visible_rect_in_target_surface_space, - gfx::Rect(layer->content_bounds()), - layer_rect_in_target_space, - layer->draw_transform()); + visible_rect_in_target_surface_space, gfx::Rect(layer->bounds()), + layer_rect_in_target_space, layer->draw_transform()); } static inline bool TransformToParentIsKnown(LayerImpl* layer) { return true; } @@ -434,7 +432,7 @@ static bool LayerShouldBeSkipped(LayerType* layer, bool layer_is_drawn) { // Some additional conditions need to be computed at a later point after the // recursion is finished. // - the intersection of render_surface content and layer clip_rect is empty - // - the visible_content_rect is empty + // - the visible_layer_rect is empty // // Note, if the layer should not have been drawn due to being fully // transparent, we would have skipped the entire subtree and never made it @@ -712,9 +710,6 @@ gfx::Transform ComputeSizeDeltaCompensation( // Calculate step 1b gfx::Transform container_layer_space_to_container_target_surface_space = container->draw_transform(); - container_layer_space_to_container_target_surface_space.Scale( - container->contents_scale_x(), container->contents_scale_y()); - gfx::Transform container_target_surface_space_to_container_layer_space; if (container_layer_space_to_container_target_surface_space.GetInverse( &container_target_surface_space_to_container_layer_space)) { @@ -911,106 +906,12 @@ gfx::Transform ComputeScrollCompensationMatrixForChildren( template <typename LayerType> static inline void UpdateLayerScaleDrawProperties( LayerType* layer, - float ideal_contents_scale, float maximum_animation_contents_scale, - float starting_animation_contents_scale, - float page_scale_factor, - float device_scale_factor) { - layer->draw_properties().ideal_contents_scale = ideal_contents_scale; + float starting_animation_contents_scale) { layer->draw_properties().maximum_animation_contents_scale = maximum_animation_contents_scale; layer->draw_properties().starting_animation_contents_scale = starting_animation_contents_scale; - layer->draw_properties().page_scale_factor = page_scale_factor; - layer->draw_properties().device_scale_factor = device_scale_factor; -} - -static inline void CalculateContentsScale(LayerImpl* layer, - float contents_scale) { - // LayerImpl has all of its content scales and bounds pushed from the Main - // thread during commit and just uses those values as-is. -} - -static inline void CalculateContentsScale(Layer* layer, float contents_scale) { - layer->CalculateContentsScale(contents_scale, - &layer->draw_properties().contents_scale_x, - &layer->draw_properties().contents_scale_y, - &layer->draw_properties().content_bounds); - - Layer* mask_layer = layer->mask_layer(); - if (mask_layer) { - mask_layer->CalculateContentsScale( - contents_scale, - &mask_layer->draw_properties().contents_scale_x, - &mask_layer->draw_properties().contents_scale_y, - &mask_layer->draw_properties().content_bounds); - } - - Layer* replica_mask_layer = - layer->replica_layer() ? layer->replica_layer()->mask_layer() : NULL; - if (replica_mask_layer) { - replica_mask_layer->CalculateContentsScale( - contents_scale, - &replica_mask_layer->draw_properties().contents_scale_x, - &replica_mask_layer->draw_properties().contents_scale_y, - &replica_mask_layer->draw_properties().content_bounds); - } -} - -static inline void UpdateLayerContentsScale( - LayerImpl* layer, - bool can_adjust_raster_scale, - float ideal_contents_scale, - float device_scale_factor, - float page_scale_factor, - bool animating_transform_to_screen) { - CalculateContentsScale(layer, ideal_contents_scale); -} - -static inline void UpdateLayerContentsScale( - Layer* layer, - bool can_adjust_raster_scale, - float ideal_contents_scale, - float device_scale_factor, - float page_scale_factor, - bool animating_transform_to_screen) { - if (can_adjust_raster_scale) { - float ideal_raster_scale = - ideal_contents_scale / (device_scale_factor * page_scale_factor); - - bool need_to_set_raster_scale = layer->raster_scale_is_unknown(); - - // If we've previously saved a raster_scale but the ideal changes, things - // are unpredictable and we should just use 1. - if (!need_to_set_raster_scale && layer->raster_scale() != 1.f && - ideal_raster_scale != layer->raster_scale()) { - ideal_raster_scale = 1.f; - need_to_set_raster_scale = true; - } - - if (need_to_set_raster_scale) { - bool use_and_save_ideal_scale = - ideal_raster_scale >= 1.f && !animating_transform_to_screen; - if (use_and_save_ideal_scale) - layer->set_raster_scale(ideal_raster_scale); - } - } - - float raster_scale = 1.f; - if (!layer->raster_scale_is_unknown()) - raster_scale = layer->raster_scale(); - - gfx::Size old_content_bounds = layer->content_bounds(); - float old_contents_scale_x = layer->contents_scale_x(); - float old_contents_scale_y = layer->contents_scale_y(); - - float contents_scale = raster_scale * device_scale_factor * page_scale_factor; - CalculateContentsScale(layer, contents_scale); - - if (layer->content_bounds() != old_content_bounds || - layer->contents_scale_x() != old_contents_scale_x || - layer->contents_scale_y() != old_contents_scale_y) - layer->SetNeedsPushProperties(); } static inline void CalculateAnimationContentsScale( @@ -1059,8 +960,7 @@ static inline void CalculateAnimationContentsScale( // scales and translations. We treat all non-translations as potentially // affecting scale. Animations that include non-translation/scale components // will cause the computation of MaximumScale below to fail. - bool layer_is_animating_scale = - !layer->layer_animation_controller()->HasOnlyTranslationTransforms(); + bool layer_is_animating_scale = !layer->HasOnlyTranslationTransforms(); if (!layer_is_animating_scale && !ancestor_is_animating_scale) { *combined_maximum_animation_contents_scale = 0.f; @@ -1097,13 +997,11 @@ static inline void CalculateAnimationContentsScale( float layer_maximum_animated_scale = 0.f; float layer_start_animated_scale = 0.f; - if (!layer->layer_animation_controller()->MaximumTargetScale( - &layer_maximum_animated_scale)) { + if (!layer->MaximumTargetScale(&layer_maximum_animated_scale)) { *combined_maximum_animation_contents_scale = 0.f; return; } - if (!layer->layer_animation_controller()->AnimationStartScale( - &layer_start_animated_scale)) { + if (!layer->AnimationStartScale(&layer_start_animated_scale)) { *combined_starting_animation_contents_scale = 0.f; return; } @@ -1124,8 +1022,8 @@ static inline void MarkLayerWithRenderSurfaceLayerListId( int current_render_surface_layer_list_id) { layer->draw_properties().last_drawn_render_surface_layer_list_id = current_render_surface_layer_list_id; - layer->draw_properties().layer_or_descendant_is_drawn = - !!current_render_surface_layer_list_id; + layer->set_layer_or_descendant_is_drawn( + !!current_render_surface_layer_list_id); } template <typename LayerTypePtr> @@ -1184,7 +1082,7 @@ static inline void RemoveSurfaceForEarlyExit( } struct PreCalculateMetaInformationRecursiveData { - int num_unclipped_descendants; + size_t num_unclipped_descendants; int num_layer_or_descendants_with_copy_request; int num_layer_or_descendants_with_input_handler; @@ -1220,30 +1118,15 @@ static void ValidateRenderSurface(LayerImpl* layer) { static void ValidateRenderSurface(Layer* layer) { } -static void ResetDrawProperties(Layer* layer) { - layer->draw_properties().sorted_for_recursion = false; - layer->draw_properties().has_child_with_a_scroll_parent = false; - layer->draw_properties().layer_or_descendant_is_drawn = false; - layer->draw_properties().visited = false; - if (!HasInvertibleOrAnimatedTransform(layer)) { - // Layers with singular transforms should not be drawn, the whole subtree - // can be skipped. - return; - } - - for (size_t i = 0; i < layer->children().size(); ++i) { - Layer* child_layer = layer->child_at(i); - if (child_layer->scroll_parent()) - layer->draw_properties().has_child_with_a_scroll_parent = true; - ResetDrawProperties(child_layer); - } +static bool IsMetaInformationRecomputationNeeded(Layer* layer) { + return layer->layer_tree_host()->needs_meta_info_recomputation(); } -static void ResetDrawProperties(LayerImpl* layer) { +static void UpdateMetaInformationSequenceNumber(Layer* root_layer) { + root_layer->layer_tree_host()->IncrementMetaInformationSequenceNumber(); } -static bool IsMetaInformationRecomputationNeeded(Layer* layer) { - return layer->layer_tree_host()->needs_meta_info_recomputation(); +static void UpdateMetaInformationSequenceNumber(LayerImpl* root_layer) { } // Recursively walks the layer tree(if needed) to compute any information @@ -1252,6 +1135,12 @@ static void PreCalculateMetaInformationInternal( Layer* layer, PreCalculateMetaInformationRecursiveData* recursive_data) { ValidateRenderSurface(layer); + + layer->set_sorted_for_recursion(false); + layer->draw_properties().has_child_with_a_scroll_parent = false; + layer->set_layer_or_descendant_is_drawn(false); + layer->set_visited(false); + if (!HasInvertibleOrAnimatedTransform(layer)) { // Layers with singular transforms should not be drawn, the whole subtree // can be skipped. @@ -1266,17 +1155,23 @@ static void PreCalculateMetaInformationInternal( if (layer->clip_parent()) recursive_data->num_unclipped_descendants++; + layer->set_num_children_with_scroll_parent(0); for (size_t i = 0; i < layer->children().size(); ++i) { Layer* child_layer = layer->child_at(i); PreCalculateMetaInformationRecursiveData data_for_child; PreCalculateMetaInformationInternal(child_layer, &data_for_child); + if (child_layer->scroll_parent()) { + layer->draw_properties().has_child_with_a_scroll_parent = true; + layer->set_num_children_with_scroll_parent( + layer->num_children_with_scroll_parent() + 1); + } recursive_data->Merge(data_for_child); } if (layer->clip_children()) { - int num_clip_children = layer->clip_children()->size(); + size_t num_clip_children = layer->clip_children()->size(); DCHECK_GE(recursive_data->num_unclipped_descendants, num_clip_children); recursive_data->num_unclipped_descendants -= num_clip_children; } @@ -1308,10 +1203,10 @@ static void PreCalculateMetaInformationInternal( PreCalculateMetaInformationRecursiveData* recursive_data) { ValidateRenderSurface(layer); - layer->draw_properties().sorted_for_recursion = false; + layer->set_sorted_for_recursion(false); layer->draw_properties().has_child_with_a_scroll_parent = false; - layer->draw_properties().layer_or_descendant_is_drawn = false; - layer->draw_properties().visited = false; + layer->set_layer_or_descendant_is_drawn(false); + layer->set_visited(false); if (!HasInvertibleOrAnimatedTransform(layer)) { // Layers with singular transforms should not be drawn, the whole subtree @@ -1334,7 +1229,7 @@ static void PreCalculateMetaInformationInternal( } if (layer->clip_children()) { - int num_clip_children = layer->clip_children()->size(); + size_t num_clip_children = layer->clip_children()->size(); DCHECK_GE(recursive_data->num_unclipped_descendants, num_clip_children); recursive_data->num_unclipped_descendants -= num_clip_children; } @@ -1359,12 +1254,25 @@ void LayerTreeHostCommon::PreCalculateMetaInformation(Layer* root_layer) { PreCalculateMetaInformationInternal(root_layer, &recursive_data); } +void LayerTreeHostCommon::PreCalculateMetaInformationForTesting( + LayerImpl* root_layer) { + PreCalculateMetaInformationRecursiveData recursive_data; + PreCalculateMetaInformationInternal(root_layer, &recursive_data); +} + +void LayerTreeHostCommon::PreCalculateMetaInformationForTesting( + Layer* root_layer) { + UpdateMetaInformationSequenceNumber(root_layer); + PreCalculateMetaInformationRecursiveData recursive_data; + PreCalculateMetaInformationInternal(root_layer, &recursive_data); +} + template <typename LayerType> struct SubtreeGlobals { int max_texture_size; float device_scale_factor; float page_scale_factor; - const LayerType* page_scale_application_layer; + const LayerType* page_scale_layer; gfx::Vector2dF elastic_overscroll; const LayerType* elastic_overscroll_application_layer; bool can_adjust_raster_scales; @@ -1412,7 +1320,7 @@ struct DataForRecursion { bool ancestor_clips_subtree; typename LayerType::RenderSurfaceType* nearest_occlusion_immune_ancestor_surface; - bool in_subtree_of_page_scale_application_layer; + bool in_subtree_of_page_scale_layer; bool subtree_can_use_lcd_text; bool subtree_is_visible_from_ancestor; }; @@ -1460,14 +1368,15 @@ static void AddScrollParentChain(std::vector<LayerType*>* out, // that we will potentionally add to the list. That is, the child of parent // containing |layer|. LayerType* child = GetChildContainingLayer(parent, layer); - if (child->draw_properties().sorted_for_recursion) + if (child->sorted_for_recursion()) return; if (LayerType* scroll_parent = child->scroll_parent()) AddScrollParentChain(out, parent, scroll_parent); out->push_back(child); - child->draw_properties().sorted_for_recursion = true; + bool sorted_for_recursion = true; + child->set_sorted_for_recursion(sorted_for_recursion); } template <typename LayerType> @@ -1479,7 +1388,7 @@ static bool SortChildrenForRecursion(std::vector<LayerType*>* out, LayerType* current = LayerTreeHostCommon::get_layer_as_raw_ptr(parent.children(), i); - if (current->draw_properties().sorted_for_recursion) { + if (current->sorted_for_recursion()) { order_changed = true; continue; } @@ -1518,14 +1427,6 @@ static LayerImplList* GetLayerListForSorting(LayerImplList* layer_list) { return layer_list; } -static inline gfx::Vector2d BoundsDelta(Layer* layer) { - return gfx::Vector2d(); -} - -static inline gfx::Vector2d BoundsDelta(LayerImpl* layer) { - return gfx::ToCeiledVector2d(layer->bounds_delta()); -} - template <typename LayerType, typename GetIndexAndCountType> static void SortLayerListContributions( const LayerType& parent, @@ -1679,18 +1580,18 @@ static void CalculateDrawPropertiesInternal( // It makes no sense to have a non-unit page_scale_factor without specifying // which layer roots the subtree the scale is applied to. - DCHECK(globals.page_scale_application_layer || - (globals.page_scale_factor == 1.f)); + DCHECK(globals.page_scale_layer || (globals.page_scale_factor == 1.f)); - CHECK(!layer->draw_properties().visited); - layer->draw_properties().visited = true; + CHECK(!layer->visited()); + bool visited = true; + layer->set_visited(visited); DataForRecursion<LayerType> data_for_children; typename LayerType::RenderSurfaceType* nearest_occlusion_immune_ancestor_surface = data_from_ancestor.nearest_occlusion_immune_ancestor_surface; - data_for_children.in_subtree_of_page_scale_application_layer = - data_from_ancestor.in_subtree_of_page_scale_application_layer; + data_for_children.in_subtree_of_page_scale_layer = + data_from_ancestor.in_subtree_of_page_scale_layer; data_for_children.subtree_can_use_lcd_text = data_from_ancestor.subtree_can_use_lcd_text; @@ -1826,69 +1727,42 @@ static void CalculateDrawPropertiesInternal( // Compute the 2d scale components of the transform hierarchy up to the target // surface. From there, we can decide on a contents scale for the layer. float layer_scale_factors = globals.device_scale_factor; - if (data_from_ancestor.in_subtree_of_page_scale_application_layer) + if (data_from_ancestor.in_subtree_of_page_scale_layer) layer_scale_factors *= globals.page_scale_factor; gfx::Vector2dF combined_transform_scales = MathUtil::ComputeTransform2dScaleComponents( combined_transform, layer_scale_factors); - float ideal_contents_scale = - globals.can_adjust_raster_scales - ? std::max(combined_transform_scales.x(), - combined_transform_scales.y()) - : layer_scale_factors; - UpdateLayerContentsScale( - layer, - globals.can_adjust_raster_scales, - ideal_contents_scale, - globals.device_scale_factor, - data_from_ancestor.in_subtree_of_page_scale_application_layer - ? globals.page_scale_factor - : 1.f, - animating_transform_to_screen); - - UpdateLayerScaleDrawProperties( - layer, ideal_contents_scale, combined_maximum_animation_contents_scale, - combined_starting_animation_contents_scale, - data_from_ancestor.in_subtree_of_page_scale_application_layer - ? globals.page_scale_factor - : 1.f, - globals.device_scale_factor); + UpdateLayerScaleDrawProperties(layer, + combined_maximum_animation_contents_scale, + combined_starting_animation_contents_scale); LayerType* mask_layer = layer->mask_layer(); if (mask_layer) { - UpdateLayerScaleDrawProperties( - mask_layer, ideal_contents_scale, - combined_maximum_animation_contents_scale, - combined_starting_animation_contents_scale, - data_from_ancestor.in_subtree_of_page_scale_application_layer - ? globals.page_scale_factor - : 1.f, - globals.device_scale_factor); + UpdateLayerScaleDrawProperties(mask_layer, + combined_maximum_animation_contents_scale, + combined_starting_animation_contents_scale); } LayerType* replica_mask_layer = layer->replica_layer() ? layer->replica_layer()->mask_layer() : NULL; if (replica_mask_layer) { - UpdateLayerScaleDrawProperties( - replica_mask_layer, ideal_contents_scale, - combined_maximum_animation_contents_scale, - combined_starting_animation_contents_scale, - data_from_ancestor.in_subtree_of_page_scale_application_layer - ? globals.page_scale_factor - : 1.f, - globals.device_scale_factor); + UpdateLayerScaleDrawProperties(replica_mask_layer, + combined_maximum_animation_contents_scale, + combined_starting_animation_contents_scale); + } + + if (layer == globals.page_scale_layer) { + combined_transform.Scale(globals.page_scale_factor, + globals.page_scale_factor); + data_for_children.in_subtree_of_page_scale_layer = true; } // The draw_transform that gets computed below is effectively the layer's // draw_transform, unless the layer itself creates a render_surface. In that // case, the render_surface re-parents the transforms. layer_draw_properties.target_space_transform = combined_transform; - // M[draw] = M[parent] * LT * S[layer2content] - layer_draw_properties.target_space_transform.Scale( - SK_MScalar1 / layer->contents_scale_x(), - SK_MScalar1 / layer->contents_scale_y()); // The layer's screen_space_transform represents the transform between root // layer's "screen space" and local content space. @@ -1963,8 +1837,7 @@ static void CalculateDrawPropertiesInternal( // space. layer_draw_properties.target_space_transform.MakeIdentity(); layer_draw_properties.target_space_transform.Scale( - combined_transform_scales.x() / layer->contents_scale_x(), - combined_transform_scales.y() / layer->contents_scale_y()); + combined_transform_scales.x(), combined_transform_scales.y()); // Inside the surface's subtree, we scale everything to the owning layer's // scale. The sublayer matrix transforms layer rects into target surface @@ -2016,16 +1889,25 @@ static void CalculateDrawPropertiesInternal( DrawProperties<LayerType>& mask_layer_draw_properties = layer->mask_layer()->draw_properties(); mask_layer_draw_properties.render_target = layer; - mask_layer_draw_properties.visible_content_rect = - gfx::Rect(layer->content_bounds()); + mask_layer_draw_properties.visible_layer_rect = + gfx::Rect(layer->bounds()); + // Temporarily copy the draw transform of the mask's owning layer into the + // mask layer draw properties. This won't actually get used for drawing + // (the render surface uses the mask texture directly), but will get used + // to get the correct contents scale. + // TODO(enne): do something similar for property trees. + mask_layer_draw_properties.target_space_transform = + layer_draw_properties.target_space_transform; } if (layer->replica_layer() && layer->replica_layer()->mask_layer()) { DrawProperties<LayerType>& replica_mask_draw_properties = layer->replica_layer()->mask_layer()->draw_properties(); replica_mask_draw_properties.render_target = layer; - replica_mask_draw_properties.visible_content_rect = - gfx::Rect(layer->content_bounds()); + replica_mask_draw_properties.visible_layer_rect = + gfx::Rect(layer->bounds()); + replica_mask_draw_properties.target_space_transform = + layer_draw_properties.target_space_transform; } // Ignore occlusion from outside the surface when surface contents need to @@ -2064,7 +1946,7 @@ static void CalculateDrawPropertiesInternal( gfx::Rect projected_surface_rect = MathUtil::ProjectEnclosingClippedRect( inverse_surface_draw_transform, surface_clip_rect_in_target_space); - if (layer_draw_properties.num_unclipped_descendants > 0) { + if (layer_draw_properties.num_unclipped_descendants > 0u) { // If we have unclipped descendants, we cannot count on the render // surface's bounds clipping our subtree: the unclipped descendants // could cause us to expand our bounds. In this case, we must rely on @@ -2143,22 +2025,10 @@ static void CalculateDrawPropertiesInternal( layer_draw_properties.can_use_lcd_text = layer_can_use_lcd_text; - gfx::Size content_size_affected_by_delta(layer->content_bounds()); - - // Non-zero BoundsDelta imply the contents_scale of 1.0 - // because BoundsDela is only set on Android where - // ContentScalingLayer is never used. - DCHECK_IMPLIES(!BoundsDelta(layer).IsZero(), - (layer->contents_scale_x() == 1.0 && - layer->contents_scale_y() == 1.0)); - - // Thus we can omit contents scale in the following calculation. - gfx::Vector2d bounds_delta = BoundsDelta(layer); - content_size_affected_by_delta.Enlarge(bounds_delta.x(), bounds_delta.y()); - + // The layer bounds() includes the layer's bounds_delta() which we want + // for the clip rect. gfx::Rect rect_in_target_space = MathUtil::MapEnclosingClippedRect( - layer->draw_transform(), - gfx::Rect(content_size_affected_by_delta)); + layer->draw_transform(), gfx::Rect(layer->bounds())); if (LayerClipsSubtree(layer)) { layer_or_ancestor_clips_descendants = true; @@ -2207,12 +2077,6 @@ static void CalculateDrawPropertiesInternal( size_t layer_list_child_sorting_start_index = descendants.size(); if (!layer->children().empty()) { - if (layer == globals.page_scale_application_layer) { - data_for_children.parent_matrix.Scale( - globals.page_scale_factor, - globals.page_scale_factor); - data_for_children.in_subtree_of_page_scale_application_layer = true; - } if (layer == globals.elastic_overscroll_application_layer) { data_for_children.parent_matrix.Translate( -globals.elastic_overscroll.x(), -globals.elastic_overscroll.y()); @@ -2289,8 +2153,11 @@ static void CalculateDrawPropertiesInternal( render_surface_layer_list->size() - child->draw_properties() .index_of_first_render_surface_layer_list_addition; - layer_draw_properties.layer_or_descendant_is_drawn |= - child->draw_properties().layer_or_descendant_is_drawn; + + if (child->layer_or_descendant_is_drawn()) { + bool layer_or_descendant_is_drawn = true; + layer->set_layer_or_descendant_is_drawn(layer_or_descendant_is_drawn); + } } // Add the unsorted layer list contributions, if necessary. @@ -2336,7 +2203,7 @@ static void CalculateDrawPropertiesInternal( } // Compute the layer's visible content rect (the rect is in content space). - layer_draw_properties.visible_content_rect = CalculateVisibleContentRect( + layer_draw_properties.visible_layer_rect = CalculateVisibleLayerRect( layer, clip_rect_of_target_surface_in_target_space, rect_in_target_space); // Compute the remaining properties for the render surface, if the layer has @@ -2396,9 +2263,8 @@ static void CalculateDrawPropertiesInternal( // layer space which we need to undo and replace with a scale from the // surface's subtree into layer space. gfx::Transform screen_space_transform = layer->screen_space_transform(); - screen_space_transform.Scale( - layer->contents_scale_x() / combined_transform_scales.x(), - layer->contents_scale_y() / combined_transform_scales.y()); + screen_space_transform.Scale(1.0 / combined_transform_scales.x(), + 1.0 / combined_transform_scales.y()); render_surface->SetScreenSpaceTransform(screen_space_transform); if (layer->replica_layer()) { @@ -2485,7 +2351,7 @@ static void ProcessCalcDrawPropsInputs( globals->device_scale_factor = inputs.device_scale_factor * device_transform_scale; globals->page_scale_factor = inputs.page_scale_factor; - globals->page_scale_application_layer = inputs.page_scale_application_layer; + globals->page_scale_layer = inputs.page_scale_layer; globals->elastic_overscroll = inputs.elastic_overscroll; globals->elastic_overscroll_application_layer = inputs.elastic_overscroll_application_layer; @@ -2506,7 +2372,7 @@ static void ProcessCalcDrawPropsInputs( data_for_recursion->ancestor_is_animating_scale = false; data_for_recursion->ancestor_clips_subtree = true; data_for_recursion->nearest_occlusion_immune_ancestor_surface = NULL; - data_for_recursion->in_subtree_of_page_scale_application_layer = false; + data_for_recursion->in_subtree_of_page_scale_layer = false; data_for_recursion->subtree_can_use_lcd_text = inputs.can_use_lcd_text; data_for_recursion->subtree_is_visible_from_ancestor = true; } @@ -2592,51 +2458,59 @@ static bool ApproximatelyEqual(const gfx::Transform& a, return true; } +void VerifyPropertyTreeValuesForLayer(LayerImpl* current_layer, + PropertyTrees* property_trees, + bool layers_always_allowed_lcd_text, + bool can_use_lcd_text) { + const bool visible_rects_match = + ApproximatelyEqual(current_layer->visible_layer_rect(), + current_layer->visible_rect_from_property_trees()); + CHECK(visible_rects_match) + << "expected: " << current_layer->visible_layer_rect().ToString() + << " actual: " + << current_layer->visible_rect_from_property_trees().ToString(); + + const bool draw_transforms_match = + ApproximatelyEqual(current_layer->draw_transform(), + DrawTransformFromPropertyTrees( + current_layer, property_trees->transform_tree)); + CHECK(draw_transforms_match) + << "expected: " << current_layer->draw_transform().ToString() + << " actual: " + << DrawTransformFromPropertyTrees( + current_layer, property_trees->transform_tree).ToString(); + + const bool draw_opacities_match = + current_layer->draw_opacity() == + DrawOpacityFromPropertyTrees(current_layer, property_trees->opacity_tree); + CHECK(draw_opacities_match) + << "expected: " << current_layer->draw_opacity() + << " actual: " << DrawOpacityFromPropertyTrees( + current_layer, property_trees->opacity_tree); + const bool can_use_lcd_text_match = + CanUseLcdTextFromPropertyTrees( + current_layer, layers_always_allowed_lcd_text, can_use_lcd_text, + property_trees) == current_layer->can_use_lcd_text(); + CHECK(can_use_lcd_text_match); +} + void VerifyPropertyTreeValues( LayerTreeHostCommon::CalcDrawPropsMainInputs* inputs) { - LayerIterator<Layer> it, end; - for (it = LayerIterator<Layer>::Begin(inputs->render_surface_layer_list), - end = LayerIterator<Layer>::End(inputs->render_surface_layer_list); - it != end; ++it) { - Layer* current_layer = *it; - if (!it.represents_itself() || !current_layer->DrawsContent()) - continue; - - const bool visible_rects_match = - ApproximatelyEqual(current_layer->visible_content_rect(), - current_layer->visible_rect_from_property_trees()); - CHECK(visible_rects_match) - << "expected: " << current_layer->visible_content_rect().ToString() - << " actual: " - << current_layer->visible_rect_from_property_trees().ToString(); - - const bool draw_transforms_match = ApproximatelyEqual( - current_layer->draw_transform(), - DrawTransformFromPropertyTrees(current_layer, - inputs->property_trees->transform_tree)); - CHECK(draw_transforms_match) - << "expected: " << current_layer->draw_transform().ToString() - << " actual: " - << DrawTransformFromPropertyTrees( - current_layer, inputs->property_trees->transform_tree) - .ToString(); - - const bool draw_opacities_match = - current_layer->draw_opacity() == - DrawOpacityFromPropertyTrees(current_layer, - inputs->property_trees->opacity_tree); - CHECK(draw_opacities_match) - << "expected: " << current_layer->draw_opacity() << " actual: " - << DrawOpacityFromPropertyTrees(current_layer, - inputs->property_trees->opacity_tree); - } } void VerifyPropertyTreeValues( LayerTreeHostCommon::CalcDrawPropsImplInputs* inputs) { - // TODO(enne): need to synchronize compositor thread changes - // for animation and scrolling to the property trees before these - // can be correct. + LayerIterator it, end; + for (it = LayerIterator::Begin(inputs->render_surface_layer_list), + end = LayerIterator::End(inputs->render_surface_layer_list); + it != end; ++it) { + LayerImpl* current_layer = *it; + if (!it.represents_itself() || !current_layer->DrawsContent()) + continue; + VerifyPropertyTreeValuesForLayer(current_layer, inputs->property_trees, + inputs->layers_always_allowed_lcd_text, + inputs->can_use_lcd_text); + } } enum PropertyTreeOption { @@ -2654,6 +2528,7 @@ void CalculateDrawPropertiesAndVerify(LayerTreeHostCommon::CalcDrawPropsInputs< DataForRecursion<LayerType> data_for_recursion; ProcessCalcDrawPropsInputs(*inputs, &globals, &data_for_recursion); + UpdateMetaInformationSequenceNumber(inputs->root_layer); PreCalculateMetaInformationRecursiveData recursive_data; PreCalculateMetaInformationInternal(inputs->root_layer, &recursive_data); @@ -2665,7 +2540,6 @@ void CalculateDrawPropertiesAndVerify(LayerTreeHostCommon::CalcDrawPropsInputs< TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), "LayerTreeHostCommon::CalculateDrawProperties"); } - ResetDrawProperties(inputs->root_layer); std::vector<AccumulatedSurfaceState<LayerType>> accumulated_surface_state; CalculateDrawPropertiesInternal<LayerType>( @@ -2696,8 +2570,10 @@ void CalculateDrawPropertiesAndVerify(LayerTreeHostCommon::CalcDrawPropsInputs< } BuildPropertyTreesAndComputeVisibleRects( - inputs->root_layer, inputs->page_scale_application_layer, - inputs->page_scale_factor, inputs->device_scale_factor, + inputs->root_layer, inputs->page_scale_layer, + inputs->inner_viewport_scroll_layer, + inputs->outer_viewport_scroll_layer, inputs->page_scale_factor, + inputs->device_scale_factor, gfx::Rect(inputs->device_viewport_size), inputs->device_transform, inputs->property_trees, &update_layer_list); @@ -2747,14 +2623,12 @@ void LayerTreeHostCommon::CalculateDrawProperties( CalculateDrawPropertiesAndVerify(inputs, BUILD_PROPERTY_TREES_IF_NEEDED); } -PropertyTrees* GetPropertyTrees(Layer* layer, - PropertyTrees* trees_from_inputs) { +PropertyTrees* GetPropertyTrees(Layer* layer) { return layer->layer_tree_host()->property_trees(); } -PropertyTrees* GetPropertyTrees(LayerImpl* layer, - PropertyTrees* trees_from_inputs) { - return trees_from_inputs; +PropertyTrees* GetPropertyTrees(LayerImpl* layer) { + return layer->layer_tree_impl()->property_trees(); } } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_common.h b/chromium/cc/trees/layer_tree_host_common.h index 7d90445023f..bf62111acbe 100644 --- a/chromium/cc/trees/layer_tree_host_common.h +++ b/chromium/cc/trees/layer_tree_host_common.h @@ -39,7 +39,9 @@ class CC_EXPORT LayerTreeHostCommon { const gfx::Transform& device_transform, float device_scale_factor, float page_scale_factor, - const LayerType* page_scale_application_layer, + const LayerType* page_scale_layer, + const LayerType* inner_viewport_scroll_layer, + const LayerType* outer_viewport_scroll_layer, const gfx::Vector2dF& elastic_overscroll, const LayerType* elastic_overscroll_application_layer, int max_texture_size, @@ -56,7 +58,9 @@ class CC_EXPORT LayerTreeHostCommon { device_transform(device_transform), device_scale_factor(device_scale_factor), page_scale_factor(page_scale_factor), - page_scale_application_layer(page_scale_application_layer), + page_scale_layer(page_scale_layer), + inner_viewport_scroll_layer(inner_viewport_scroll_layer), + outer_viewport_scroll_layer(outer_viewport_scroll_layer), elastic_overscroll(elastic_overscroll), elastic_overscroll_application_layer( elastic_overscroll_application_layer), @@ -76,7 +80,9 @@ class CC_EXPORT LayerTreeHostCommon { gfx::Transform device_transform; float device_scale_factor; float page_scale_factor; - const LayerType* page_scale_application_layer; + const LayerType* page_scale_layer; + const LayerType* inner_viewport_scroll_layer; + const LayerType* outer_viewport_scroll_layer; gfx::Vector2dF elastic_overscroll; const LayerType* elastic_overscroll_application_layer; int max_texture_size; @@ -102,9 +108,6 @@ class CC_EXPORT LayerTreeHostCommon { LayerType* root_layer, const gfx::Size& device_viewport_size, RenderSurfaceLayerListType* render_surface_layer_list); - - private: - PropertyTrees temporary_property_trees; }; typedef CalcDrawPropsInputs<Layer, RenderSurfaceLayerList> @@ -121,6 +124,8 @@ class CC_EXPORT LayerTreeHostCommon { bool* animation_preserves_axis_alignment); static void CalculateDrawProperties(CalcDrawPropsMainInputs* inputs); static void PreCalculateMetaInformation(Layer* root_layer); + static void PreCalculateMetaInformationForTesting(LayerImpl* root_layer); + static void PreCalculateMetaInformationForTesting(Layer* root_layer); typedef CalcDrawPropsInputs<LayerImpl, LayerImplList> CalcDrawPropsImplInputs; typedef CalcDrawPropsInputsForTesting<LayerImpl, LayerImplList> @@ -235,10 +240,8 @@ void LayerTreeHostCommon::CallFunctionForSubtree(LayerType* layer, } } -CC_EXPORT PropertyTrees* GetPropertyTrees(Layer* layer, - PropertyTrees* trees_from_inputs); -CC_EXPORT PropertyTrees* GetPropertyTrees(LayerImpl* layer, - PropertyTrees* trees_from_inputs); +CC_EXPORT PropertyTrees* GetPropertyTrees(Layer* layer); +CC_EXPORT PropertyTrees* GetPropertyTrees(LayerImpl* layer); template <typename LayerType, typename RenderSurfaceLayerListType> LayerTreeHostCommon::CalcDrawPropsInputsForTesting<LayerType, @@ -255,6 +258,8 @@ LayerTreeHostCommon::CalcDrawPropsInputsForTesting<LayerType, 1.f, 1.f, NULL, + NULL, + NULL, gfx::Vector2dF(), NULL, std::numeric_limits<int>::max() / 2, @@ -265,7 +270,7 @@ LayerTreeHostCommon::CalcDrawPropsInputsForTesting<LayerType, true, render_surface_layer_list, 0, - GetPropertyTrees(root_layer, &temporary_property_trees)) { + GetPropertyTrees(root_layer)) { DCHECK(root_layer); DCHECK(render_surface_layer_list); } @@ -284,6 +289,8 @@ LayerTreeHostCommon::CalcDrawPropsInputsForTesting<LayerType, 1.f, 1.f, NULL, + NULL, + NULL, gfx::Vector2dF(), NULL, std::numeric_limits<int>::max() / 2, @@ -294,7 +301,7 @@ LayerTreeHostCommon::CalcDrawPropsInputsForTesting<LayerType, true, render_surface_layer_list, 0, - GetPropertyTrees(root_layer, &temporary_property_trees)) { + GetPropertyTrees(root_layer)) { DCHECK(root_layer); DCHECK(render_surface_layer_list); } diff --git a/chromium/cc/trees/layer_tree_host_common_perftest.cc b/chromium/cc/trees/layer_tree_host_common_perftest.cc index 9a5de06bb0f..49831328d1e 100644 --- a/chromium/cc/trees/layer_tree_host_common_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_common_perftest.cc @@ -77,48 +77,9 @@ class LayerTreeHostCommonPerfTest : public LayerTreeTest { std::string json_; }; -class CalcDrawPropsMainTest : public LayerTreeHostCommonPerfTest { +class CalcDrawPropsTest : public LayerTreeHostCommonPerfTest { public: - void RunCalcDrawProps() { RunTest(false, false, false); } - - void BeginTest() override { - timer_.Reset(); - - do { - bool can_render_to_separate_surface = true; - bool verify_property_trees = false; - int max_texture_size = 8096; - RenderSurfaceLayerList update_list; - PropertyTrees property_trees; - LayerTreeHostCommon::CalcDrawPropsMainInputs inputs( - layer_tree_host()->root_layer(), - layer_tree_host()->device_viewport_size(), gfx::Transform(), - layer_tree_host()->device_scale_factor(), - layer_tree_host()->page_scale_factor(), - layer_tree_host()->overscroll_elasticity_layer(), - layer_tree_host()->elastic_overscroll(), - layer_tree_host()->page_scale_layer(), max_texture_size, - layer_tree_host()->settings().can_use_lcd_text, - layer_tree_host()->settings().layers_always_allowed_lcd_text, - can_render_to_separate_surface, - layer_tree_host() - ->settings() - .layer_transforms_should_scale_layer_contents, - verify_property_trees, &update_list, 0, &property_trees); - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - timer_.NextLap(); - } while (!timer_.HasTimeLimitExpired()); - - EndTest(); - } -}; - -class CalcDrawPropsImplTest : public LayerTreeHostCommonPerfTest { - public: - void RunCalcDrawProps() { - RunTestWithImplSidePainting(); - } + void RunCalcDrawProps() { RunTest(false, false); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -152,6 +113,8 @@ class CalcDrawPropsImplTest : public LayerTreeHostCommonPerfTest { host_impl->DrawTransform(), active_tree->device_scale_factor(), active_tree->current_page_scale_factor(), active_tree->InnerViewportContainerLayer(), + active_tree->InnerViewportScrollLayer(), + active_tree->OuterViewportScrollLayer(), active_tree->elastic_overscroll()->Current(active_tree->IsActiveTree()), active_tree->overscroll_elasticity_layer(), max_texture_size, host_impl->settings().can_use_lcd_text, @@ -163,10 +126,10 @@ class CalcDrawPropsImplTest : public LayerTreeHostCommonPerfTest { } }; -class BspTreePerfTest : public CalcDrawPropsImplTest { +class BspTreePerfTest : public CalcDrawPropsTest { public: BspTreePerfTest() : num_duplicates_(1) {} - void RunSortLayers() { RunTest(false, false, false); } + void RunSortLayers() { RunTest(false, false); } void SetNumberOfDuplicates(int num_duplicates) { num_duplicates_ = num_duplicates; @@ -193,10 +156,8 @@ class BspTreePerfTest : public CalcDrawPropsImplTest { for (LayerImplList::iterator it = base_list.begin(); it != base_list.end(); ++it) { DrawPolygon* draw_polygon = - new DrawPolygon(NULL, - gfx::RectF((*it)->content_bounds()), - (*it)->draw_transform(), - polygon_counter++); + new DrawPolygon(NULL, gfx::RectF((*it)->bounds()), + (*it)->draw_transform(), polygon_counter++); polygon_list.push_back(scoped_ptr<DrawPolygon>(draw_polygon)); } @@ -230,49 +191,25 @@ class BspTreePerfTest : public CalcDrawPropsImplTest { int num_duplicates_; }; -TEST_F(CalcDrawPropsMainTest, TenTen) { - SetTestName("10_10_main_thread"); - ReadTestFile("10_10_layer_tree"); - RunCalcDrawProps(); -} - -TEST_F(CalcDrawPropsMainTest, HeavyPage) { - SetTestName("heavy_page_main_thread"); - ReadTestFile("heavy_layer_tree"); - RunCalcDrawProps(); -} - -TEST_F(CalcDrawPropsMainTest, TouchRegionLight) { - SetTestName("touch_region_light_main_thread"); - ReadTestFile("touch_region_light"); - RunCalcDrawProps(); -} - -TEST_F(CalcDrawPropsMainTest, TouchRegionHeavy) { - SetTestName("touch_region_heavy_main_thread"); - ReadTestFile("touch_region_heavy"); - RunCalcDrawProps(); -} - -TEST_F(CalcDrawPropsImplTest, TenTen) { +TEST_F(CalcDrawPropsTest, TenTen) { SetTestName("10_10"); ReadTestFile("10_10_layer_tree"); RunCalcDrawProps(); } -TEST_F(CalcDrawPropsImplTest, HeavyPage) { +TEST_F(CalcDrawPropsTest, HeavyPage) { SetTestName("heavy_page"); ReadTestFile("heavy_layer_tree"); RunCalcDrawProps(); } -TEST_F(CalcDrawPropsImplTest, TouchRegionLight) { +TEST_F(CalcDrawPropsTest, TouchRegionLight) { SetTestName("touch_region_light"); ReadTestFile("touch_region_light"); RunCalcDrawProps(); } -TEST_F(CalcDrawPropsImplTest, TouchRegionHeavy) { +TEST_F(CalcDrawPropsTest, TouchRegionHeavy) { SetTestName("touch_region_heavy"); ReadTestFile("touch_region_heavy"); RunCalcDrawProps(); diff --git a/chromium/cc/trees/layer_tree_host_common_unittest.cc b/chromium/cc/trees/layer_tree_host_common_unittest.cc index 591f48c4329..43e2bb02123 100644 --- a/chromium/cc/trees/layer_tree_host_common_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_common_unittest.cc @@ -10,7 +10,6 @@ #include "cc/animation/layer_animation_controller.h" #include "cc/animation/transform_operations.h" #include "cc/base/math_util.h" -#include "cc/layers/content_layer.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/layer.h" #include "cc/layers/layer_client.h" @@ -21,9 +20,7 @@ #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" #include "cc/test/animation_test_common.h" -#include "cc/test/fake_content_layer.h" #include "cc/test/fake_content_layer_client.h" -#include "cc/test/fake_content_layer_impl.h" #include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_impl.h" @@ -46,7 +43,8 @@ namespace { class LayerWithForcedDrawsContent : public Layer { public: - LayerWithForcedDrawsContent() {} + explicit LayerWithForcedDrawsContent(const LayerSettings& settings) + : Layer(settings) {} bool DrawsContent() const override; @@ -63,26 +61,20 @@ class MockContentLayerClient : public ContentLayerClient { void PaintContents(SkCanvas* canvas, const gfx::Rect& clip, PaintingControlSetting picture_control) override {} - void PaintContentsToDisplayList( - DisplayItemList* display_list, + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { NOTIMPLEMENTED(); + return nullptr; } bool FillsBoundsCompletely() const override { return false; } }; scoped_refptr<FakePictureLayer> CreateDrawablePictureLayer( + const LayerSettings& settings, ContentLayerClient* delegate) { scoped_refptr<FakePictureLayer> to_return = - FakePictureLayer::Create(delegate); - to_return->SetIsDrawable(true); - return to_return; -} - -scoped_refptr<ContentLayer> CreateDrawableContentLayer( - ContentLayerClient* delegate) { - scoped_refptr<ContentLayer> to_return = ContentLayer::Create(delegate); + FakePictureLayer::Create(settings, delegate); to_return->SetIsDrawable(true); return to_return; } @@ -93,25 +85,37 @@ scoped_refptr<ContentLayer> CreateDrawableContentLayer( EXPECT_FLOAT_EQ(expected, layer->contents_scale_y()); \ } while (false) -#define EXPECT_IDEAL_SCALE_EQ(expected, layer) \ - do { \ - EXPECT_FLOAT_EQ(expected, layer->draw_properties().ideal_contents_scale); \ +#define EXPECT_IDEAL_SCALE_EQ(expected, layer) \ + do { \ + EXPECT_FLOAT_EQ(expected, layer->GetIdealContentsScale()); \ } while (false) +class LayerTreeSettingsScaleContent : public LayerTreeSettings { + public: + LayerTreeSettingsScaleContent() { + layer_transforms_should_scale_layer_contents = true; + } +}; + +class LayerTreeHostCommonScalingTest : public LayerTreeHostCommonTest { + public: + LayerTreeHostCommonScalingTest() + : LayerTreeHostCommonTest(LayerTreeSettingsScaleContent()) {} +}; + TEST_F(LayerTreeHostCommonTest, TransformsForNoOpLayer) { // Sanity check: For layers positioned at zero, with zero size, // and with identity transforms, then the draw transform, // screen space transform, and the hierarchy passed on to children // layers should also be identity transforms. - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grand_child = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings()); parent->AddChild(child); child->AddChild(grand_child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); gfx::Transform identity_matrix; SetLayerPropertiesForTesting(parent.get(), @@ -148,14 +152,13 @@ TEST_F(LayerTreeHostCommonTest, TransformsForNoOpLayer) { } TEST_F(LayerTreeHostCommonTest, DoNotSkipLayersWithHandlers) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grand_child = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings()); parent->AddChild(child); child->AddChild(grand_child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); gfx::Transform identity_matrix; SetLayerPropertiesForTesting(parent.get(), @@ -195,9 +198,9 @@ TEST_F(LayerTreeHostCommonTest, DoNotSkipLayersWithHandlers) { TEST_F(LayerTreeHostCommonTest, TransformsForSingleLayer) { gfx::Transform identity_matrix; - scoped_refptr<Layer> layer = Layer::Create(); + scoped_refptr<Layer> layer = Layer::Create(layer_settings()); - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), @@ -207,8 +210,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleLayer) { false); root->AddChild(layer); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // Case 2: Setting the bounds of the layer should not affect either the draw // transform or the screenspace transform. @@ -319,14 +321,14 @@ TEST_F(LayerTreeHostCommonTest, TransformsAboutScrollOffset) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); gfx::Transform identity_matrix; scoped_ptr<LayerImpl> sublayer_scoped_ptr( LayerImpl::Create(host_impl.active_tree(), 1)); LayerImpl* sublayer = sublayer_scoped_ptr.get(); - sublayer->SetContentsScale(kPageScale * kDeviceScale, - kPageScale * kDeviceScale); SetLayerPropertiesForTesting(sublayer, identity_matrix, gfx::Point3F(), gfx::PointF(), gfx::Size(500, 500), true, false, false); @@ -364,9 +366,12 @@ TEST_F(LayerTreeHostCommonTest, TransformsAboutScrollOffset) { root.get(), kDeviceScale, kPageScale, scroll_layer->parent()); gfx::Transform expected_transform = identity_matrix; gfx::PointF sub_layer_screen_position = kScrollLayerPosition - kScrollDelta; - sub_layer_screen_position.Scale(kPageScale * kDeviceScale); - expected_transform.Translate(MathUtil::Round(sub_layer_screen_position.x()), - MathUtil::Round(sub_layer_screen_position.y())); + expected_transform.Translate(MathUtil::Round(sub_layer_screen_position.x() * + kPageScale * kDeviceScale), + MathUtil::Round(sub_layer_screen_position.y() * + kPageScale * kDeviceScale)); + expected_transform.Scale(kPageScale * kDeviceScale, + kPageScale * kDeviceScale); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, sublayer->draw_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, @@ -384,25 +389,28 @@ TEST_F(LayerTreeHostCommonTest, TransformsAboutScrollOffset) { expected_transform.MakeIdentity(); expected_transform.Translate( MathUtil::Round(kTranslateX * kPageScale * kDeviceScale + - sub_layer_screen_position.x()), + sub_layer_screen_position.x() * kPageScale * + kDeviceScale), MathUtil::Round(kTranslateY * kPageScale * kDeviceScale + - sub_layer_screen_position.y())); + sub_layer_screen_position.y() * kPageScale * + kDeviceScale)); + expected_transform.Scale(kPageScale * kDeviceScale, + kPageScale * kDeviceScale); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, sublayer->draw_transform()); } TEST_F(LayerTreeHostCommonTest, TransformsForSimpleHierarchy) { gfx::Transform identity_matrix; - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grand_child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings()); root->AddChild(parent); parent->AddChild(child); child->AddChild(grand_child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // One-time setup of root layer SetLayerPropertiesForTesting(root.get(), @@ -519,17 +527,16 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSimpleHierarchy) { } TEST_F(LayerTreeHostCommonTest, TransformsForSingleRenderSurface) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> grand_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(parent); parent->AddChild(child); child->AddChild(grand_child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // One-time setup of root layer gfx::Transform identity_matrix; @@ -614,19 +621,18 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleRenderSurface) { } TEST_F(LayerTreeHostCommonTest, TransformsForReplica) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> child_replica = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> child_replica = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> grand_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(parent); parent->AddChild(child); child->AddChild(grand_child); child->SetReplicaLayer(child_replica.get()); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // One-time setup of root layer gfx::Transform identity_matrix; @@ -720,20 +726,20 @@ TEST_F(LayerTreeHostCommonTest, TransformsForRenderSurfaceHierarchy) { // - verifying that each layer has a reference to the correct render surface // and render target values. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); - scoped_refptr<Layer> render_surface2 = Layer::Create(); - scoped_refptr<Layer> child_of_root = Layer::Create(); - scoped_refptr<Layer> child_of_rs1 = Layer::Create(); - scoped_refptr<Layer> child_of_rs2 = Layer::Create(); - scoped_refptr<Layer> replica_of_rs1 = Layer::Create(); - scoped_refptr<Layer> replica_of_rs2 = Layer::Create(); - scoped_refptr<Layer> grand_child_of_root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings()); + scoped_refptr<Layer> child_of_root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child_of_rs1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> child_of_rs2 = Layer::Create(layer_settings()); + scoped_refptr<Layer> replica_of_rs1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> replica_of_rs2 = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child_of_root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> grand_child_of_rs1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> grand_child_of_rs2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(parent); parent->AddChild(render_surface1); parent->AddChild(child_of_root); @@ -746,8 +752,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForRenderSurfaceHierarchy) { render_surface1->SetReplicaLayer(replica_of_rs1.get()); render_surface2->SetReplicaLayer(replica_of_rs2.get()); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // In combination with descendant draws content, opacity != 1 forces the layer // to have a new render surface. @@ -1006,12 +1011,12 @@ TEST_F(LayerTreeHostCommonTest, TransformsForFlatteningLayer) { // Note that the way the code is currently implemented, it is not expected to // use a canonical orthographic projection. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> grand_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> great_grand_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); gfx::Transform rotation_about_y_axis; rotation_about_y_axis.RotateAboutYAxis(30.0); @@ -1047,8 +1052,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForFlatteningLayer) { grand_child->AddChild(great_grand_child); child->SetForceRenderSurface(true); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // No layers in this test should preserve 3d. ASSERT_TRUE(root->should_flatten_transform()); @@ -1102,10 +1106,10 @@ TEST_F(LayerTreeHostCommonTest, TransformsForDegenerateIntermediateLayer) { // implicitly inherited by the rest of the subtree, which then is positioned // incorrectly as a result. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> grand_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); // The child height is zero, but has non-zero width that should be accounted // for while computing draw transforms. @@ -1136,8 +1140,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForDegenerateIntermediateLayer) { child->AddChild(grand_child); child->SetForceRenderSurface(true); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -1155,14 +1158,13 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) { // to child layers instead of applied to the root RenderSurface. const gfx::Transform identity_matrix; scoped_refptr<LayerWithForcedDrawsContent> root = - new LayerWithForcedDrawsContent; + new LayerWithForcedDrawsContent(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - new LayerWithForcedDrawsContent; + new LayerWithForcedDrawsContent(layer_settings()); child->SetScrollClipLayerId(root->id()); root->AddChild(child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); SetLayerPropertiesForTesting(root.get(), identity_matrix, @@ -1191,8 +1193,6 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) { EXPECT_EQ(translate, root->draw_properties().target_space_transform); EXPECT_EQ(translate, child->draw_properties().target_space_transform); EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform()); - EXPECT_EQ(1.f, root->draw_properties().device_scale_factor); - EXPECT_EQ(1.f, child->draw_properties().device_scale_factor); } gfx::Transform scale; @@ -1207,8 +1207,6 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) { EXPECT_EQ(scale, root->draw_properties().target_space_transform); EXPECT_EQ(scale, child->draw_properties().target_space_transform); EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform()); - EXPECT_EQ(2.f, root->draw_properties().device_scale_factor); - EXPECT_EQ(2.f, child->draw_properties().device_scale_factor); } gfx::Transform rotate; @@ -1223,8 +1221,6 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) { EXPECT_EQ(rotate, root->draw_properties().target_space_transform); EXPECT_EQ(rotate, child->draw_properties().target_space_transform); EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform()); - EXPECT_EQ(1.f, root->draw_properties().device_scale_factor); - EXPECT_EQ(1.f, child->draw_properties().device_scale_factor); } gfx::Transform composite; @@ -1261,9 +1257,6 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) { EXPECT_EQ(device_scaled_translate, child->draw_properties().target_space_transform); EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform()); - EXPECT_EQ(device_scale_factor, root->draw_properties().device_scale_factor); - EXPECT_EQ(device_scale_factor, - child->draw_properties().device_scale_factor); } // Verify it composes correctly with page scale. @@ -1274,18 +1267,17 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) { LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( root.get(), root->bounds(), translate, &render_surface_layer_list); inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); + inputs.page_scale_layer = root.get(); inputs.can_adjust_raster_scales = true; inputs.property_trees->needs_rebuild = true; LayerTreeHostCommon::CalculateDrawProperties(&inputs); gfx::Transform page_scaled_translate = translate; page_scaled_translate.Scale(page_scale_factor, page_scale_factor); - EXPECT_EQ(translate, root->draw_properties().target_space_transform); + EXPECT_EQ(page_scaled_translate, + root->draw_properties().target_space_transform); EXPECT_EQ(page_scaled_translate, child->draw_properties().target_space_transform); EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform()); - EXPECT_EQ(1.f, root->draw_properties().device_scale_factor); - EXPECT_EQ(1.f, child->draw_properties().device_scale_factor); } // Verify that it composes correctly with transforms directly on root layer. @@ -1309,13 +1301,12 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) { TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForRenderSurfaceWithClippedLayer) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); const gfx::Transform identity_matrix; SetLayerPropertiesForTesting(parent.get(), @@ -1363,38 +1354,23 @@ TEST_F(LayerTreeHostCommonTest, } TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForTransparentChild) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); - scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); - - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + LayerImpl* parent = root_layer(); + LayerImpl* render_surface1 = AddChild<LayerImpl>(parent); + LayerImpl* child = AddChild<LayerImpl>(render_surface1); + child->SetDrawsContent(true); const gfx::Transform identity_matrix; - SetLayerPropertiesForTesting(render_surface1.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - true, - false); - SetLayerPropertiesForTesting(child.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - true, + SetLayerPropertiesForTesting(render_surface1, identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false, + true); + SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false, false); - - parent->AddChild(render_surface1); - render_surface1->AddChild(child); - render_surface1->SetForceRenderSurface(true); render_surface1->SetOpacity(0.f); - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - parent.get(), parent->bounds(), &render_surface_layer_list); + LayerImplList render_surface_layer_list; + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + parent, parent->bounds(), &render_surface_layer_list); inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawProperties(&inputs); @@ -1409,12 +1385,11 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForTransparentChild) { } TEST_F(LayerTreeHostCommonTest, RenderSurfaceForBlendMode) { - scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); const gfx::Transform identity_matrix; const SkXfermode::Mode blend_mode = SkXfermode::kMultiply_Mode; @@ -1439,14 +1414,13 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceForBlendMode) { } TEST_F(LayerTreeHostCommonTest, ForceRenderSurface) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); render_surface1->SetForceRenderSurface(true); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); const gfx::Transform identity_matrix; SetLayerPropertiesForTesting(parent.get(), @@ -1508,12 +1482,12 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfacesFlattenScreenSpaceTransform) { // Render surfaces act as a flattening point for their subtree, so should // always flatten the target-to-screen space transform seen by descendants. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> grand_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); gfx::Transform rotation_about_y_axis; rotation_about_y_axis.RotateAboutYAxis(30.0); @@ -1538,8 +1512,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfacesFlattenScreenSpaceTransform) { grand_child->SetShouldFlattenTransform(false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // Only grand_child should preserve 3d. EXPECT_TRUE(root->should_flatten_transform()); @@ -1590,20 +1563,19 @@ TEST_F(LayerTreeHostCommonTest, ClipRectCullsRenderSurfaces) { // const gfx::Transform identity_matrix; - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grand_child = Layer::Create(); - scoped_refptr<Layer> great_grand_child = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings()); + scoped_refptr<Layer> great_grand_child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> leaf_node1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> leaf_node2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); parent->AddChild(child); child->AddChild(grand_child); grand_child->AddChild(great_grand_child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); // leaf_node1 ensures that parent and child are kept on the // render_surface_layer_list, even though grand_child and great_grand_child @@ -1691,17 +1663,16 @@ TEST_F(LayerTreeHostCommonTest, ClipRectCullsSurfaceWithoutVisibleContent) { // in the render_surface_layer_list. const gfx::Transform identity_matrix; - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grand_child = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> leaf_node = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); parent->AddChild(child); child->AddChild(grand_child); grand_child->AddChild(leaf_node); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); SetLayerPropertiesForTesting(parent.get(), identity_matrix, @@ -1786,15 +1757,15 @@ TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) { // and propagates the clip to the subtree. const gfx::Transform identity_matrix; - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child1 = Layer::Create(); - scoped_refptr<Layer> child2 = Layer::Create(); - scoped_refptr<Layer> grand_child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> leaf_node1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> leaf_node2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(parent); parent->AddChild(child1); parent->AddChild(child2); @@ -1802,8 +1773,7 @@ TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) { child2->AddChild(leaf_node2); grand_child->AddChild(leaf_node1); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); child2->SetForceRenderSurface(true); @@ -1947,12 +1917,12 @@ TEST_F(LayerTreeHostCommonTest, DrawableContentRectForLayers) { // const gfx::Transform identity_matrix; - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grand_child1 = Layer::Create(); - scoped_refptr<Layer> grand_child2 = Layer::Create(); - scoped_refptr<Layer> grand_child3 = Layer::Create(); - scoped_refptr<Layer> grand_child4 = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child2 = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child3 = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child4 = Layer::Create(layer_settings()); parent->AddChild(child); child->AddChild(grand_child1); @@ -1960,8 +1930,7 @@ TEST_F(LayerTreeHostCommonTest, DrawableContentRectForLayers) { child->AddChild(grand_child3); child->AddChild(grand_child4); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); SetLayerPropertiesForTesting(parent.get(), identity_matrix, @@ -2037,20 +2006,20 @@ TEST_F(LayerTreeHostCommonTest, ClipRectIsPropagatedCorrectlyToSurfaces) { // They may still have a clip rect of their own layer bounds, however, if // masksToBounds was true. const gfx::Transform identity_matrix; - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grand_child1 = Layer::Create(); - scoped_refptr<Layer> grand_child2 = Layer::Create(); - scoped_refptr<Layer> grand_child3 = Layer::Create(); - scoped_refptr<Layer> grand_child4 = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child2 = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child3 = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child4 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> leaf_node1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> leaf_node2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> leaf_node3 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> leaf_node4 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); parent->AddChild(child); child->AddChild(grand_child1); @@ -2058,8 +2027,7 @@ TEST_F(LayerTreeHostCommonTest, ClipRectIsPropagatedCorrectlyToSurfaces) { child->AddChild(grand_child3); child->AddChild(grand_child4); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); // the leaf nodes ensure that these grand_children become render surfaces for // this test. @@ -2175,99 +2143,49 @@ TEST_F(LayerTreeHostCommonTest, ClipRectIsPropagatedCorrectlyToSurfaces) { } TEST_F(LayerTreeHostCommonTest, AnimationsForRenderSurfaceHierarchy) { - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); - scoped_refptr<Layer> render_surface2 = Layer::Create(); - scoped_refptr<Layer> child_of_root = Layer::Create(); - scoped_refptr<Layer> child_of_rs1 = Layer::Create(); - scoped_refptr<Layer> child_of_rs2 = Layer::Create(); - scoped_refptr<Layer> grand_child_of_root = Layer::Create(); - scoped_refptr<LayerWithForcedDrawsContent> grand_child_of_rs1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); - scoped_refptr<LayerWithForcedDrawsContent> grand_child_of_rs2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); - parent->AddChild(render_surface1); - parent->AddChild(child_of_root); - render_surface1->AddChild(child_of_rs1); - render_surface1->AddChild(render_surface2); - render_surface2->AddChild(child_of_rs2); - child_of_root->AddChild(grand_child_of_root); - child_of_rs1->AddChild(grand_child_of_rs1); - child_of_rs2->AddChild(grand_child_of_rs2); - - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); - - // Make our render surfaces. - render_surface1->SetForceRenderSurface(true); - render_surface2->SetForceRenderSurface(true); + LayerImpl* parent = root_layer(); + LayerImpl* render_surface1 = AddChildToRoot<LayerImpl>(); + LayerImpl* child_of_rs1 = AddChild<LayerImpl>(render_surface1); + LayerImpl* grand_child_of_rs1 = AddChild<LayerImpl>(child_of_rs1); + LayerImpl* render_surface2 = AddChild<LayerImpl>(render_surface1); + LayerImpl* child_of_rs2 = AddChild<LayerImpl>(render_surface2); + LayerImpl* grand_child_of_rs2 = AddChild<LayerImpl>(child_of_rs2); + LayerImpl* child_of_root = AddChildToRoot<LayerImpl>(); + LayerImpl* grand_child_of_root = AddChild<LayerImpl>(child_of_root); + + grand_child_of_rs1->SetDrawsContent(true); + grand_child_of_rs2->SetDrawsContent(true); gfx::Transform layer_transform; layer_transform.Translate(1.0, 1.0); - SetLayerPropertiesForTesting(parent.get(), - layer_transform, - gfx::Point3F(0.25f, 0.f, 0.f), - gfx::PointF(2.5f, 0.f), - gfx::Size(10, 10), - true, - false); - SetLayerPropertiesForTesting(render_surface1.get(), - layer_transform, - gfx::Point3F(0.25f, 0.f, 0.f), - gfx::PointF(2.5f, 0.f), - gfx::Size(10, 10), - true, - false); - SetLayerPropertiesForTesting(render_surface2.get(), - layer_transform, - gfx::Point3F(0.25f, 0.f, 0.f), - gfx::PointF(2.5f, 0.f), - gfx::Size(10, 10), - true, - false); - SetLayerPropertiesForTesting(child_of_root.get(), - layer_transform, - gfx::Point3F(0.25f, 0.f, 0.f), - gfx::PointF(2.5f, 0.f), - gfx::Size(10, 10), - true, - false); - SetLayerPropertiesForTesting(child_of_rs1.get(), - layer_transform, - gfx::Point3F(0.25f, 0.f, 0.f), - gfx::PointF(2.5f, 0.f), - gfx::Size(10, 10), - true, - false); - SetLayerPropertiesForTesting(child_of_rs2.get(), - layer_transform, - gfx::Point3F(0.25f, 0.f, 0.f), - gfx::PointF(2.5f, 0.f), - gfx::Size(10, 10), - true, - false); - SetLayerPropertiesForTesting(grand_child_of_root.get(), - layer_transform, - gfx::Point3F(0.25f, 0.f, 0.f), - gfx::PointF(2.5f, 0.f), - gfx::Size(10, 10), - true, - false); - SetLayerPropertiesForTesting(grand_child_of_rs1.get(), - layer_transform, - gfx::Point3F(0.25f, 0.f, 0.f), - gfx::PointF(2.5f, 0.f), - gfx::Size(10, 10), - true, - false); - SetLayerPropertiesForTesting(grand_child_of_rs2.get(), - layer_transform, - gfx::Point3F(0.25f, 0.f, 0.f), - gfx::PointF(2.5f, 0.f), - gfx::Size(10, 10), - true, - false); + SetLayerPropertiesForTesting( + parent, layer_transform, gfx::Point3F(0.25f, 0.f, 0.f), + gfx::PointF(2.5f, 0.f), gfx::Size(10, 10), true, false, true); + SetLayerPropertiesForTesting( + render_surface1, layer_transform, gfx::Point3F(0.25f, 0.f, 0.f), + gfx::PointF(2.5f, 0.f), gfx::Size(10, 10), true, false, true); + SetLayerPropertiesForTesting( + render_surface2, layer_transform, gfx::Point3F(0.25f, 0.f, 0.f), + gfx::PointF(2.5f, 0.f), gfx::Size(10, 10), true, false, true); + SetLayerPropertiesForTesting( + child_of_root, layer_transform, gfx::Point3F(0.25f, 0.f, 0.f), + gfx::PointF(2.5f, 0.f), gfx::Size(10, 10), true, false, false); + SetLayerPropertiesForTesting( + child_of_rs1, layer_transform, gfx::Point3F(0.25f, 0.f, 0.f), + gfx::PointF(2.5f, 0.f), gfx::Size(10, 10), true, false, false); + SetLayerPropertiesForTesting( + child_of_rs2, layer_transform, gfx::Point3F(0.25f, 0.f, 0.f), + gfx::PointF(2.5f, 0.f), gfx::Size(10, 10), true, false, false); + SetLayerPropertiesForTesting( + grand_child_of_root, layer_transform, gfx::Point3F(0.25f, 0.f, 0.f), + gfx::PointF(2.5f, 0.f), gfx::Size(10, 10), true, false, false); + SetLayerPropertiesForTesting( + grand_child_of_rs1, layer_transform, gfx::Point3F(0.25f, 0.f, 0.f), + gfx::PointF(2.5f, 0.f), gfx::Size(10, 10), true, false, false); + SetLayerPropertiesForTesting( + grand_child_of_rs2, layer_transform, gfx::Point3F(0.25f, 0.f, 0.f), + gfx::PointF(2.5f, 0.f), gfx::Size(10, 10), true, false, false); // Put an animated opacity on the render surface. AddOpacityTransitionToController( @@ -2288,7 +2206,7 @@ TEST_F(LayerTreeHostCommonTest, AnimationsForRenderSurfaceHierarchy) { AddAnimatedTransformToController( grand_child_of_rs2->layer_animation_controller(), 10.0, 30, 0); - ExecuteCalculateDrawProperties(parent.get()); + ExecuteCalculateDrawProperties(parent); // Only layers that are associated with render surfaces should have an actual // RenderSurface() value. @@ -2305,17 +2223,17 @@ TEST_F(LayerTreeHostCommonTest, AnimationsForRenderSurfaceHierarchy) { ASSERT_FALSE(grand_child_of_rs2->render_surface()); // Verify all render target accessors - EXPECT_EQ(parent.get(), parent->render_target()); - EXPECT_EQ(parent.get(), child_of_root->render_target()); - EXPECT_EQ(parent.get(), grand_child_of_root->render_target()); + EXPECT_EQ(parent, parent->render_target()); + EXPECT_EQ(parent, child_of_root->render_target()); + EXPECT_EQ(parent, grand_child_of_root->render_target()); - EXPECT_EQ(render_surface1.get(), render_surface1->render_target()); - EXPECT_EQ(render_surface1.get(), child_of_rs1->render_target()); - EXPECT_EQ(render_surface1.get(), grand_child_of_rs1->render_target()); + EXPECT_EQ(render_surface1, render_surface1->render_target()); + EXPECT_EQ(render_surface1, child_of_rs1->render_target()); + EXPECT_EQ(render_surface1, grand_child_of_rs1->render_target()); - EXPECT_EQ(render_surface2.get(), render_surface2->render_target()); - EXPECT_EQ(render_surface2.get(), child_of_rs2->render_target()); - EXPECT_EQ(render_surface2.get(), grand_child_of_rs2->render_target()); + EXPECT_EQ(render_surface2, render_surface2->render_target()); + EXPECT_EQ(render_surface2, child_of_rs2->render_target()); + EXPECT_EQ(render_surface2, grand_child_of_rs2->render_target()); // Verify draw_opacity_is_animating values EXPECT_FALSE(parent->draw_opacity_is_animating()); @@ -2671,20 +2589,42 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectForPerspectiveUnprojection) { EXPECT_EQ(expected, actual); } +TEST_F(LayerTreeHostCommonTest, + VisibleRectsForPositionedRootLayerClippedByViewport) { + scoped_refptr<Layer> root = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); + host()->SetRootLayer(root); + + gfx::Transform identity_matrix; + // Root layer is positioned at (60, 70). The default device viewport size + // is (0, 0, 100x100) in target space. So the root layer's visible rect + // will be clipped by the viewport to be (0, 0, 40x30) in layer's space. + SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), + gfx::PointF(60, 70), gfx::Size(100, 100), true, + false); + ExecuteCalculateDrawProperties(root.get()); + + EXPECT_EQ(gfx::Rect(0, 0, 100, 100), + root->render_surface()->DrawableContentRect()); + // In target space, not clipped. + EXPECT_EQ(gfx::Rect(60, 70, 100, 100), root->drawable_content_rect()); + // In layer space, clipped. + EXPECT_EQ(gfx::Rect(0, 0, 40, 30), root->visible_layer_rect()); +} + TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForSimpleLayers) { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child3 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(child1); root->AddChild(child2); root->AddChild(child3); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; SetLayerPropertiesForTesting(root.get(), @@ -2722,13 +2662,13 @@ TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForSimpleLayers) { root->render_surface()->DrawableContentRect()); EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect()); - // Layers that do not draw content should have empty visible_content_rects. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_content_rect()); + // Layers that do not draw content should have empty visible_layer_rects. + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect()); - // layer visible_content_rects are clipped by their target surface. - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 25, 25), child2->visible_content_rect()); - EXPECT_TRUE(child3->visible_content_rect().IsEmpty()); + // layer visible_layer_rects are clipped by their target surface. + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 25, 25), child2->visible_layer_rect()); + EXPECT_TRUE(child3->visible_layer_rect().IsEmpty()); // layer drawable_content_rects are not clipped. EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->drawable_content_rect()); @@ -2738,21 +2678,20 @@ TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForSimpleLayers) { TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForLayersClippedByLayer) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> grand_child1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> grand_child2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> grand_child3 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(child); child->AddChild(grand_child1); child->AddChild(grand_child2); child->AddChild(grand_child3); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; SetLayerPropertiesForTesting(root.get(), @@ -2801,13 +2740,13 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect()); // Layers that do not draw content should have empty visible content rects. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), child->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), child->visible_layer_rect()); // All grandchild visible content rects should be clipped by child. - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), grand_child1->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 25, 25), grand_child2->visible_content_rect()); - EXPECT_TRUE(grand_child3->visible_content_rect().IsEmpty()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), grand_child1->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 25, 25), grand_child2->visible_layer_rect()); + EXPECT_TRUE(grand_child3->visible_layer_rect().IsEmpty()); // All grandchild DrawableContentRects should also be clipped by child. EXPECT_EQ(gfx::Rect(5, 5, 50, 50), grand_child1->drawable_content_rect()); @@ -2816,15 +2755,14 @@ TEST_F(LayerTreeHostCommonTest, } TEST_F(LayerTreeHostCommonTest, VisibleContentRectWithClippingAndScaling) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> grand_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(child); child->AddChild(grand_child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; gfx::Transform child_scale_matrix; @@ -2840,7 +2778,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectWithClippingAndScaling) { gfx::Size(100, 100), true, false); child->SetMasksToBounds(true); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); // The visible rect is expanded to integer coordinates in target space before // being projected back to layer space, where it is once again expanded to @@ -2850,21 +2788,20 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectWithClippingAndScaling) { TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForLayersInUnclippedRenderSurface) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child3 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(render_surface1); render_surface1->AddChild(child1); render_surface1->AddChild(child2); render_surface1->AddChild(child3); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; SetLayerPropertiesForTesting(root.get(), @@ -2913,8 +2850,8 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect()); // Layers that do not draw content should have empty visible content rects. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_layer_rect()); // An unclipped surface grows its DrawableContentRect to include all drawable // regions of the subtree. @@ -2922,9 +2859,9 @@ TEST_F(LayerTreeHostCommonTest, render_surface1->render_surface()->DrawableContentRect()); // All layers that draw content into the unclipped surface are also unclipped. - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child2->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child3->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child2->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child3->visible_layer_rect()); EXPECT_EQ(gfx::Rect(5, 5, 50, 50), child1->drawable_content_rect()); EXPECT_EQ(gfx::Rect(75, 75, 50, 50), child2->drawable_content_rect()); @@ -2933,19 +2870,18 @@ TEST_F(LayerTreeHostCommonTest, TEST_F(LayerTreeHostCommonTest, VisibleContentRectsForClippedSurfaceWithEmptyClip) { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child3 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(child1); root->AddChild(child2); root->AddChild(child3); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), @@ -2976,20 +2912,19 @@ TEST_F(LayerTreeHostCommonTest, // Visible content rect calculation will check if the target surface is // clipped or not. An empty clip rect does not indicate the render surface // is unclipped. - EXPECT_EQ(empty, child1->visible_content_rect()); - EXPECT_EQ(empty, child2->visible_content_rect()); - EXPECT_EQ(empty, child3->visible_content_rect()); + EXPECT_EQ(empty, child1->visible_layer_rect()); + EXPECT_EQ(empty, child2->visible_layer_rect()); + EXPECT_EQ(empty, child3->visible_layer_rect()); } TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForLayersWithUninvertibleTransform) { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // Case 1: a truly degenerate matrix gfx::Transform identity_matrix; @@ -3013,7 +2948,7 @@ TEST_F(LayerTreeHostCommonTest, ExecuteCalculateDrawProperties(root.get()); - EXPECT_TRUE(child->visible_content_rect().IsEmpty()); + EXPECT_TRUE(child->visible_layer_rect().IsEmpty()); EXPECT_TRUE(child->drawable_content_rect().IsEmpty()); // Case 2: a matrix with flattened z, uninvertible and not visible according @@ -3032,7 +2967,7 @@ TEST_F(LayerTreeHostCommonTest, ExecuteCalculateDrawProperties(root.get()); - EXPECT_TRUE(child->visible_content_rect().IsEmpty()); + EXPECT_TRUE(child->visible_layer_rect().IsEmpty()); EXPECT_TRUE(child->drawable_content_rect().IsEmpty()); // Case 3: a matrix with flattened z, also uninvertible and not visible. @@ -3051,19 +2986,18 @@ TEST_F(LayerTreeHostCommonTest, ExecuteCalculateDrawProperties(root.get()); - EXPECT_TRUE(child->visible_content_rect().IsEmpty()); + EXPECT_TRUE(child->visible_layer_rect().IsEmpty()); EXPECT_TRUE(child->drawable_content_rect().IsEmpty()); } TEST_F(LayerTreeHostCommonTest, SingularTransformDoesNotPreventClearingDrawProperties) { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; gfx::Transform uninvertible_matrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); @@ -3084,7 +3018,7 @@ TEST_F(LayerTreeHostCommonTest, true, false); - child->draw_properties().sorted_for_recursion = true; + child->set_sorted_for_recursion(true); TransformOperations start_transform_operations; start_transform_operations.AppendScale(1.f, 0.f, 0.f); @@ -3099,15 +3033,14 @@ TEST_F(LayerTreeHostCommonTest, ExecuteCalculateDrawProperties(root.get()); - EXPECT_FALSE(child->draw_properties().sorted_for_recursion); + EXPECT_FALSE(child->sorted_for_recursion()); } TEST_F(LayerTreeHostCommonTest, SingularNonAnimatingTransformDoesNotPreventClearingDrawProperties) { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; gfx::Transform uninvertible_matrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); @@ -3121,32 +3054,31 @@ TEST_F(LayerTreeHostCommonTest, true, false); - root->draw_properties().sorted_for_recursion = true; + root->set_sorted_for_recursion(true); EXPECT_FALSE(root->TransformIsAnimating()); ExecuteCalculateDrawProperties(root.get()); - EXPECT_FALSE(root->draw_properties().sorted_for_recursion); + EXPECT_FALSE(root->sorted_for_recursion()); } TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForLayersInClippedRenderSurface) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child3 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(render_surface1); render_surface1->AddChild(child1); render_surface1->AddChild(child2); render_surface1->AddChild(child3); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; SetLayerPropertiesForTesting(root.get(), @@ -3196,8 +3128,8 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect()); // Layers that do not draw content should have empty visible content rects. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_layer_rect()); // A clipped surface grows its DrawableContentRect to include all drawable // regions of the subtree, but also gets clamped by the ancestor's clip. @@ -3206,9 +3138,9 @@ TEST_F(LayerTreeHostCommonTest, // All layers that draw content into the surface have their visible content // rect clipped by the surface clip rect. - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 25, 25), child2->visible_content_rect()); - EXPECT_TRUE(child3->visible_content_rect().IsEmpty()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 25, 25), child2->visible_layer_rect()); + EXPECT_TRUE(child3->visible_layer_rect().IsEmpty()); // But the DrawableContentRects are unclipped. EXPECT_EQ(gfx::Rect(5, 5, 50, 50), child1->drawable_content_rect()); @@ -3219,23 +3151,22 @@ TEST_F(LayerTreeHostCommonTest, TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForSurfaceHierarchy) { // Check that clipping does not propagate down surfaces. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); - scoped_refptr<Layer> render_surface2 = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child3 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(render_surface1); render_surface1->AddChild(render_surface2); render_surface2->AddChild(child1); render_surface2->AddChild(child2); render_surface2->AddChild(child3); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; SetLayerPropertiesForTesting(root.get(), @@ -3294,9 +3225,9 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect()); // Layers that do not draw content should have empty visible content rects. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface2->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface2->visible_layer_rect()); // A clipped surface grows its DrawableContentRect to include all drawable // regions of the subtree, but also gets clamped by the ancestor's clip. @@ -3310,9 +3241,9 @@ TEST_F(LayerTreeHostCommonTest, render_surface2->render_surface()->DrawableContentRect()); // All layers that draw content into render_surface2 think they are unclipped. - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child2->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child3->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child2->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child3->visible_layer_rect()); // DrawableContentRects are also unclipped. EXPECT_EQ(gfx::Rect(5, 5, 50, 50), child1->drawable_content_rect()); @@ -3325,15 +3256,14 @@ TEST_F(LayerTreeHostCommonTest, // Layers that have non-axis aligned bounds (due to transforms) have an // expanded, axis-aligned DrawableContentRect and visible content rect. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(render_surface1); render_surface1->AddChild(child1); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; gfx::Transform child_rotation; @@ -3370,8 +3300,8 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect()); // Layers that do not draw content should have empty visible content rects. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_layer_rect()); // The unclipped surface grows its DrawableContentRect to include all drawable // regions of the subtree. @@ -3385,7 +3315,7 @@ TEST_F(LayerTreeHostCommonTest, render_surface1->render_surface()->DrawableContentRect()); // All layers that draw content into the unclipped surface are also unclipped. - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_layer_rect()); EXPECT_EQ(expected_surface_drawable_content, child1->drawable_content_rect()); } @@ -3394,15 +3324,14 @@ TEST_F(LayerTreeHostCommonTest, // Layers that have non-axis aligned bounds (due to transforms) have an // expanded, axis-aligned DrawableContentRect and visible content rect. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(render_surface1); render_surface1->AddChild(child1); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; gfx::Transform child_rotation; @@ -3453,7 +3382,7 @@ TEST_F(LayerTreeHostCommonTest, // up covering the full left half of child1. // // Given the floating point math, this number is a little bit fuzzy. - EXPECT_EQ(gfx::Rect(0, 0, 26, 50), child1->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 26, 50), child1->visible_layer_rect()); // The child's DrawableContentRect is unclipped. EXPECT_EQ(unclipped_surface_content, child1->drawable_content_rect()); @@ -3462,22 +3391,24 @@ TEST_F(LayerTreeHostCommonTest, TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsInHighDPI) { MockContentLayerClient client; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<FakePictureLayer> render_surface1 = - CreateDrawablePictureLayer(&client); + CreateDrawablePictureLayer(layer_settings(), &client); scoped_refptr<FakePictureLayer> render_surface2 = - CreateDrawablePictureLayer(&client); - scoped_refptr<FakePictureLayer> child1 = CreateDrawablePictureLayer(&client); - scoped_refptr<FakePictureLayer> child2 = CreateDrawablePictureLayer(&client); - scoped_refptr<FakePictureLayer> child3 = CreateDrawablePictureLayer(&client); + CreateDrawablePictureLayer(layer_settings(), &client); + scoped_refptr<FakePictureLayer> child1 = + CreateDrawablePictureLayer(layer_settings(), &client); + scoped_refptr<FakePictureLayer> child2 = + CreateDrawablePictureLayer(layer_settings(), &client); + scoped_refptr<FakePictureLayer> child3 = + CreateDrawablePictureLayer(layer_settings(), &client); root->AddChild(render_surface1); render_surface1->AddChild(render_surface2); render_surface2->AddChild(child1); render_surface2->AddChild(child2); render_surface2->AddChild(child3); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; SetLayerPropertiesForTesting(root.get(), @@ -3551,15 +3482,15 @@ TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsInHighDPI) { EXPECT_EQ(gfx::Rect(250, 250, 100, 100), child3->drawable_content_rect()); // The root layer does not actually draw content of its own. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect()); // All layer visible content rects are not expressed in content space of each // layer, so they are not scaled by the device_scale_factor. - EXPECT_EQ(gfx::Rect(0, 0, 3, 4), render_surface1->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 7, 13), render_surface2->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child2->visible_content_rect()); - EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child3->visible_content_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 3, 4), render_surface1->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 7, 13), render_surface2->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child2->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child3->visible_layer_rect()); } TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithoutPreserves3d) { @@ -3568,27 +3499,27 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithoutPreserves3d) { // "flattened" to each parent layer according to current W3C spec. const gfx::Transform identity_matrix; - scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> front_facing_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> back_facing_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> front_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> back_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> front_facing_child_of_front_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> back_facing_child_of_front_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> front_facing_child_of_back_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> back_facing_child_of_back_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); parent->AddChild(front_facing_child); parent->AddChild(back_facing_child); @@ -3599,8 +3530,7 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithoutPreserves3d) { back_facing_surface->AddChild(front_facing_child_of_back_facing_surface); back_facing_surface->AddChild(back_facing_child_of_back_facing_surface); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); // Nothing is double-sided front_facing_child->SetDoubleSided(false); @@ -3770,31 +3700,31 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithPreserves3d) { // is used. const gfx::Transform identity_matrix; - scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> front_facing_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> back_facing_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> front_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> back_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> - front_facing_child_of_front_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + front_facing_child_of_front_facing_surface = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> - back_facing_child_of_front_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + back_facing_child_of_front_facing_surface = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> - front_facing_child_of_back_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + front_facing_child_of_back_facing_surface = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> - back_facing_child_of_back_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + back_facing_child_of_back_facing_surface = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> dummy_replica_layer1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> dummy_replica_layer2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); parent->AddChild(front_facing_child); parent->AddChild(back_facing_child); @@ -3805,8 +3735,7 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithPreserves3d) { back_facing_surface->AddChild(front_facing_child_of_back_facing_surface); back_facing_surface->AddChild(back_facing_child_of_back_facing_surface); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); // Nothing is double-sided front_facing_child->SetDoubleSided(false); @@ -3955,17 +3884,17 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithAnimatingTransforms) { // transforms should be treated as "unknown" so we can not be sure that their // back face is really showing. const gfx::Transform identity_matrix; - scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> animating_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child_of_animating_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> animating_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); parent->AddChild(child); parent->AddChild(animating_surface); @@ -3973,8 +3902,7 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithAnimatingTransforms) { parent->AddChild(animating_child); parent->AddChild(child2); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); // Nothing is double-sided child->SetDoubleSided(false); @@ -4084,18 +4012,18 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithAnimatingTransforms) { render_surface_layer_list.at(1) ->render_surface()->layer_list().at(1)->id()); - EXPECT_FALSE(child2->visible_content_rect().IsEmpty()); + EXPECT_FALSE(child2->visible_layer_rect().IsEmpty()); // The animating layers should have a visible content rect that represents the // area of the front face that is within the viewport. - EXPECT_EQ(animating_child->visible_content_rect(), - gfx::Rect(animating_child->content_bounds())); - EXPECT_EQ(animating_surface->visible_content_rect(), - gfx::Rect(animating_surface->content_bounds())); + EXPECT_EQ(animating_child->visible_layer_rect(), + gfx::Rect(animating_child->bounds())); + EXPECT_EQ(animating_surface->visible_layer_rect(), + gfx::Rect(animating_surface->bounds())); // And layers in the subtree of the animating layer should have valid visible // content rects also. - EXPECT_EQ(child_of_animating_surface->visible_content_rect(), - gfx::Rect(child_of_animating_surface->content_bounds())); + EXPECT_EQ(child_of_animating_surface->visible_layer_rect(), + gfx::Rect(child_of_animating_surface->bounds())); } TEST_F(LayerTreeHostCommonTest, @@ -4104,23 +4032,22 @@ TEST_F(LayerTreeHostCommonTest, // created when it flattens its subtree, and its parent has preserves-3d. const gfx::Transform identity_matrix; - scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> front_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> back_facing_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child1 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child2 = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); parent->AddChild(front_facing_surface); parent->AddChild(back_facing_surface); front_facing_surface->AddChild(child1); back_facing_surface->AddChild(child2); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); // RenderSurfaces are not double-sided front_facing_surface->SetDoubleSided(false); @@ -4212,110 +4139,50 @@ TEST_F(LayerTreeHostCommonTest, ->render_surface()->layer_list().at(1)->id()); } -class NoScaleContentLayer : public ContentLayer { - public: - static scoped_refptr<NoScaleContentLayer> Create(ContentLayerClient* client) { - return make_scoped_refptr(new NoScaleContentLayer(client)); - } - - void CalculateContentsScale(float ideal_contents_scale, - float* contents_scale_x, - float* contents_scale_y, - gfx::Size* content_bounds) override { - // Skip over the ContentLayer to the base Layer class. - Layer::CalculateContentsScale(ideal_contents_scale, - contents_scale_x, - contents_scale_y, - content_bounds); - } - - protected: - explicit NoScaleContentLayer(ContentLayerClient* client) - : ContentLayer(client) {} - ~NoScaleContentLayer() override {} -}; - -scoped_refptr<NoScaleContentLayer> CreateNoScaleDrawableContentLayer( - ContentLayerClient* delegate) { - scoped_refptr<NoScaleContentLayer> to_return = - NoScaleContentLayer::Create(delegate); - to_return->SetIsDrawable(true); - return to_return; -} - -TEST_F(LayerTreeHostCommonTest, LayerTransformsInHighDPI) { +TEST_F(LayerTreeHostCommonScalingTest, LayerTransformsInHighDPI) { // Verify draw and screen space transforms of layers not in a surface. - MockContentLayerClient delegate; gfx::Transform identity_matrix; - scoped_refptr<FakePictureLayer> parent = - CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(parent.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - false, - true); - - scoped_refptr<FakePictureLayer> child = CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(child.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(10, 10), - false, + LayerImpl* parent = root_layer(); + SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), false, true, true); - scoped_refptr<FakePictureLayer> child_empty = - CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(child_empty.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(), - false, - true); - - parent->AddChild(child); - parent->AddChild(child_empty); + LayerImpl* child = AddChildToRoot<LayerImpl>(); + SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(), + gfx::PointF(2.f, 2.f), gfx::Size(10, 10), false, + true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + LayerImpl* child_empty = AddChildToRoot<LayerImpl>(); + SetLayerPropertiesForTesting(child_empty, identity_matrix, gfx::Point3F(), + gfx::PointF(2.f, 2.f), gfx::Size(), false, true, + false); float device_scale_factor = 2.5f; - float page_scale_factor = 1.f; + gfx::Size viewport_size(100, 100); + ExecuteCalculateDrawProperties(parent, device_scale_factor); - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - parent.get(), parent->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.can_adjust_raster_scales = true; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_IDEAL_SCALE_EQ(device_scale_factor * page_scale_factor, parent); - EXPECT_IDEAL_SCALE_EQ(device_scale_factor * page_scale_factor, child); - EXPECT_IDEAL_SCALE_EQ(device_scale_factor * page_scale_factor, child_empty); + EXPECT_IDEAL_SCALE_EQ(device_scale_factor, parent); + EXPECT_IDEAL_SCALE_EQ(device_scale_factor, child); + EXPECT_IDEAL_SCALE_EQ(device_scale_factor, child_empty); - EXPECT_EQ(1u, render_surface_layer_list.size()); + EXPECT_EQ(1u, render_surface_layer_list_impl()->size()); // Verify parent transforms gfx::Transform expected_parent_transform; - expected_parent_transform.Scale(device_scale_factor * page_scale_factor, - device_scale_factor * page_scale_factor); + expected_parent_transform.Scale(device_scale_factor, device_scale_factor); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_parent_transform, parent->screen_space_transform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_parent_transform, parent->draw_transform()); // Verify results of transformed parent rects - gfx::RectF parent_content_bounds(parent->content_bounds()); + gfx::RectF parent_bounds(parent->bounds()); gfx::RectF parent_draw_rect = - MathUtil::MapClippedRect(parent->draw_transform(), parent_content_bounds); - gfx::RectF parent_screen_space_rect = MathUtil::MapClippedRect( - parent->screen_space_transform(), parent_content_bounds); + MathUtil::MapClippedRect(parent->draw_transform(), parent_bounds); + gfx::RectF parent_screen_space_rect = + MathUtil::MapClippedRect(parent->screen_space_transform(), parent_bounds); gfx::RectF expected_parent_draw_rect(parent->bounds()); expected_parent_draw_rect.Scale(device_scale_factor); @@ -4338,17 +4205,17 @@ TEST_F(LayerTreeHostCommonTest, LayerTransformsInHighDPI) { // Verify results of transformed child and child_empty rects. They should // match. - gfx::RectF child_content_bounds(child->content_bounds()); + gfx::RectF child_bounds(child->bounds()); gfx::RectF child_draw_rect = - MathUtil::MapClippedRect(child->draw_transform(), child_content_bounds); - gfx::RectF child_screen_space_rect = MathUtil::MapClippedRect( - child->screen_space_transform(), child_content_bounds); + MathUtil::MapClippedRect(child->draw_transform(), child_bounds); + gfx::RectF child_screen_space_rect = + MathUtil::MapClippedRect(child->screen_space_transform(), child_bounds); - gfx::RectF child_empty_draw_rect = MathUtil::MapClippedRect( - child_empty->draw_transform(), child_content_bounds); + gfx::RectF child_empty_draw_rect = + MathUtil::MapClippedRect(child_empty->draw_transform(), child_bounds); gfx::RectF child_empty_screen_space_rect = MathUtil::MapClippedRect( - child_empty->screen_space_transform(), child_content_bounds); + child_empty->screen_space_transform(), child_bounds); gfx::RectF expected_child_draw_rect(child->position(), child->bounds()); expected_child_draw_rect.Scale(device_scale_factor); @@ -4358,70 +4225,41 @@ TEST_F(LayerTreeHostCommonTest, LayerTransformsInHighDPI) { EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child_empty_screen_space_rect); } -TEST_F(LayerTreeHostCommonTest, SurfaceLayerTransformsInHighDPI) { +TEST_F(LayerTreeHostCommonScalingTest, SurfaceLayerTransformsInHighDPI) { // Verify draw and screen space transforms of layers in a surface. - MockContentLayerClient delegate; gfx::Transform identity_matrix; - gfx::Transform perspective_matrix; perspective_matrix.ApplyPerspectiveDepth(2.0); gfx::Transform scale_small_matrix; scale_small_matrix.Scale(SK_MScalar1 / 10.f, SK_MScalar1 / 12.f); - scoped_refptr<Layer> root = Layer::Create(); - - scoped_refptr<FakePictureLayer> parent = - CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(parent.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - false, - true); + LayerImpl* root = root_layer(); + SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), false, true, + false); + LayerImpl* parent = AddChildToRoot<LayerImpl>(); + SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), false, true, + false); - scoped_refptr<FakePictureLayer> perspective_surface = - CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(perspective_surface.get(), + LayerImpl* perspective_surface = AddChild<LayerImpl>(parent); + SetLayerPropertiesForTesting(perspective_surface, perspective_matrix * scale_small_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(10, 10), - false, - true); + gfx::Point3F(), gfx::PointF(2.f, 2.f), + gfx::Size(10, 10), false, true, true); + perspective_surface->SetDrawsContent(true); - scoped_refptr<FakePictureLayer> scale_surface = - CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(scale_surface.get(), - scale_small_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(10, 10), - false, - true); - - perspective_surface->SetForceRenderSurface(true); - scale_surface->SetForceRenderSurface(true); - - parent->AddChild(perspective_surface); - parent->AddChild(scale_surface); - root->AddChild(parent); - - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + LayerImpl* scale_surface = AddChild<LayerImpl>(parent); + SetLayerPropertiesForTesting(scale_surface, scale_small_matrix, + gfx::Point3F(), gfx::PointF(2.f, 2.f), + gfx::Size(10, 10), false, true, true); + scale_surface->SetDrawsContent(true); float device_scale_factor = 2.5f; float page_scale_factor = 3.f; - - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), parent->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); - inputs.can_adjust_raster_scales = true; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); + ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor, + root); EXPECT_IDEAL_SCALE_EQ(device_scale_factor * page_scale_factor, parent); EXPECT_IDEAL_SCALE_EQ(device_scale_factor * page_scale_factor, @@ -4446,7 +4284,7 @@ TEST_F(LayerTreeHostCommonTest, SurfaceLayerTransformsInHighDPI) { std::max(target_space_transform_scales.x(), target_space_transform_scales.y())); - EXPECT_EQ(3u, render_surface_layer_list.size()); + EXPECT_EQ(3u, render_surface_layer_list_impl()->size()); gfx::Transform expected_parent_draw_transform; expected_parent_draw_transform.Scale(device_scale_factor * page_scale_factor, @@ -4478,422 +4316,7 @@ TEST_F(LayerTreeHostCommonTest, SurfaceLayerTransformsInHighDPI) { perspective_surface->draw_transform()); } -// TODO(sohanjg): Remove this test when ContentLayer is removed. -TEST_F(LayerTreeHostCommonTest, - LayerTransformsInHighDPIAccurateScaleZeroChildPosition) { - // Verify draw and screen space transforms of layers not in a surface. - MockContentLayerClient delegate; - gfx::Transform identity_matrix; - - scoped_refptr<ContentLayer> parent = CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(parent.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(133, 133), - false, - true); - - scoped_refptr<ContentLayer> child = CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(child.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(13, 13), - false, - true); - - scoped_refptr<NoScaleContentLayer> child_no_scale = - CreateNoScaleDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(child_no_scale.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(13, 13), - false, - true); - - parent->AddChild(child); - parent->AddChild(child_no_scale); - - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); - - float device_scale_factor = 1.7f; - float page_scale_factor = 1.f; - - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - parent.get(), parent->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = parent.get(); - inputs.can_adjust_raster_scales = true; - inputs.verify_property_trees = false; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, parent); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, child); - EXPECT_CONTENTS_SCALE_EQ(1, child_no_scale); - - EXPECT_EQ(1u, render_surface_layer_list.size()); - - // Verify parent transforms - gfx::Transform expected_parent_transform; - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_parent_transform, - parent->screen_space_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_parent_transform, - parent->draw_transform()); - - // Verify results of transformed parent rects - gfx::RectF parent_content_bounds(parent->content_bounds()); - - gfx::RectF parent_draw_rect = - MathUtil::MapClippedRect(parent->draw_transform(), parent_content_bounds); - gfx::RectF parent_screen_space_rect = MathUtil::MapClippedRect( - parent->screen_space_transform(), parent_content_bounds); - - gfx::RectF expected_parent_draw_rect(parent->bounds()); - expected_parent_draw_rect.Scale(device_scale_factor); - expected_parent_draw_rect.set_width(ceil(expected_parent_draw_rect.width())); - expected_parent_draw_rect.set_height( - ceil(expected_parent_draw_rect.height())); - EXPECT_FLOAT_RECT_EQ(expected_parent_draw_rect, parent_draw_rect); - EXPECT_FLOAT_RECT_EQ(expected_parent_draw_rect, parent_screen_space_rect); - - // Verify child transforms - gfx::Transform expected_child_transform; - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->screen_space_transform()); - - // Verify results of transformed child rects - gfx::RectF child_content_bounds(child->content_bounds()); - - gfx::RectF child_draw_rect = - MathUtil::MapClippedRect(child->draw_transform(), child_content_bounds); - gfx::RectF child_screen_space_rect = MathUtil::MapClippedRect( - child->screen_space_transform(), child_content_bounds); - - gfx::RectF expected_child_draw_rect(child->bounds()); - expected_child_draw_rect.Scale(device_scale_factor); - expected_child_draw_rect.set_width(ceil(expected_child_draw_rect.width())); - expected_child_draw_rect.set_height(ceil(expected_child_draw_rect.height())); - EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child_draw_rect); - EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child_screen_space_rect); - - // Verify child_no_scale transforms - gfx::Transform expected_child_no_scale_transform = child->draw_transform(); - // All transforms operate on content rects. The child's content rect - // incorporates device scale, but the child_no_scale does not; add it here. - expected_child_no_scale_transform.Scale(device_scale_factor, - device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_no_scale_transform, - child_no_scale->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_no_scale_transform, - child_no_scale->screen_space_transform()); -} - -// TODO(sohanjg): Remove this test when ContentLayer is removed. -TEST_F(LayerTreeHostCommonTest, ContentsScale) { - MockContentLayerClient delegate; - gfx::Transform identity_matrix; - - gfx::Transform parent_scale_matrix; - SkMScalar initial_parent_scale = 1.75; - parent_scale_matrix.Scale(initial_parent_scale, initial_parent_scale); - - gfx::Transform child_scale_matrix; - SkMScalar initial_child_scale = 1.25; - child_scale_matrix.Scale(initial_child_scale, initial_child_scale); - - scoped_refptr<Layer> root = Layer::Create(); - root->SetBounds(gfx::Size(100, 100)); - - scoped_refptr<ContentLayer> parent = CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(parent.get(), - parent_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - false, - true); - - scoped_refptr<ContentLayer> child_scale = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(child_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<ContentLayer> child_empty = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(child_empty.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(), - false, - true); - - scoped_refptr<NoScaleContentLayer> child_no_scale = - CreateNoScaleDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(child_no_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(12.f, 12.f), - gfx::Size(10, 10), - false, - true); - - root->AddChild(parent); - - parent->AddChild(child_scale); - parent->AddChild(child_empty); - parent->AddChild(child_no_scale); - - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); - - float device_scale_factor = 2.5f; - float page_scale_factor = 1.f; - - { - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), root->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); - inputs.can_adjust_raster_scales = true; - inputs.verify_property_trees = false; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale, parent); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - child_scale); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - child_empty); - EXPECT_CONTENTS_SCALE_EQ(1, child_no_scale); - - // The parent is scaled up and shouldn't need to scale during draw. The - // child that can scale its contents should also not need to scale during - // draw. This shouldn't change if the child has empty bounds. The other - // children should. - EXPECT_FLOAT_EQ(1.0, parent->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(1.0, parent->draw_transform().matrix().get(1, 1)); - EXPECT_FLOAT_EQ(1.0, child_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(1.0, child_scale->draw_transform().matrix().get(1, 1)); - EXPECT_FLOAT_EQ(1.0, child_empty->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(1.0, child_empty->draw_transform().matrix().get(1, 1)); - EXPECT_FLOAT_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - child_no_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - child_no_scale->draw_transform().matrix().get(1, 1)); - } - - // If the device_scale_factor or page_scale_factor changes, then it should be - // updated using the initial transform as the raster scale. - device_scale_factor = 2.25f; - page_scale_factor = 1.25f; - - { - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), root->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); - inputs.can_adjust_raster_scales = true; - inputs.verify_property_trees = false; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_CONTENTS_SCALE_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale, parent); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - child_scale); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - child_empty); - EXPECT_CONTENTS_SCALE_EQ(1, child_no_scale); - } - - // If the transform changes, we expect the raster scale to be reset to 1.0. - SkMScalar second_child_scale = 1.75; - child_scale_matrix.Scale(second_child_scale / initial_child_scale, - second_child_scale / initial_child_scale); - child_scale->SetTransform(child_scale_matrix); - child_empty->SetTransform(child_scale_matrix); - - { - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), root->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); - inputs.can_adjust_raster_scales = true; - inputs.verify_property_trees = false; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale, - parent); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - child_scale); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - child_empty); - EXPECT_CONTENTS_SCALE_EQ(1, child_no_scale); - } - - // If the device_scale_factor or page_scale_factor changes, then it should be - // updated, but still using 1.0 as the raster scale. - device_scale_factor = 2.75f; - page_scale_factor = 1.75f; - - { - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), root->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); - inputs.can_adjust_raster_scales = true; - inputs.verify_property_trees = false; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale, - parent); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - child_scale); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - child_empty); - EXPECT_CONTENTS_SCALE_EQ(1, child_no_scale); - } -} - -// TODO(sohanjg): Remove this test when ContentLayer is removed. -TEST_F(LayerTreeHostCommonTest, - ContentsScale_LayerTransformsDontAffectContentsScale) { - MockContentLayerClient delegate; - gfx::Transform identity_matrix; - - gfx::Transform parent_scale_matrix; - SkMScalar initial_parent_scale = 1.75; - parent_scale_matrix.Scale(initial_parent_scale, initial_parent_scale); - - gfx::Transform child_scale_matrix; - SkMScalar initial_child_scale = 1.25; - child_scale_matrix.Scale(initial_child_scale, initial_child_scale); - - scoped_refptr<Layer> root = Layer::Create(); - root->SetBounds(gfx::Size(100, 100)); - - scoped_refptr<ContentLayer> parent = CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(parent.get(), - parent_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - false, - true); - - scoped_refptr<ContentLayer> child_scale = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(child_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<ContentLayer> child_empty = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(child_empty.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(), - false, - true); - - scoped_refptr<NoScaleContentLayer> child_no_scale = - CreateNoScaleDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(child_no_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(12.f, 12.f), - gfx::Size(10, 10), - false, - true); - - root->AddChild(parent); - - parent->AddChild(child_scale); - parent->AddChild(child_empty); - parent->AddChild(child_no_scale); - - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); - - RenderSurfaceLayerList render_surface_layer_list; - - float device_scale_factor = 2.5f; - float page_scale_factor = 1.f; - - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), root->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); - inputs.verify_property_trees = false; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, parent); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - child_scale); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - child_empty); - EXPECT_CONTENTS_SCALE_EQ(1, child_no_scale); - - // Since the transform scale does not affect contents scale, it should affect - // the draw transform instead. - EXPECT_FLOAT_EQ(initial_parent_scale, - parent->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(initial_parent_scale, - parent->draw_transform().matrix().get(1, 1)); - EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale, - child_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale, - child_scale->draw_transform().matrix().get(1, 1)); - EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale, - child_empty->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale, - child_empty->draw_transform().matrix().get(1, 1)); - EXPECT_FLOAT_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - child_no_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - child_no_scale->draw_transform().matrix().get(1, 1)); -} - -TEST_F(LayerTreeHostCommonTest, SmallIdealScale) { - MockContentLayerClient delegate; - gfx::Transform identity_matrix; - +TEST_F(LayerTreeHostCommonScalingTest, SmallIdealScale) { gfx::Transform parent_scale_matrix; SkMScalar initial_parent_scale = 1.75; parent_scale_matrix.Scale(initial_parent_scale, initial_parent_scale); @@ -4902,48 +4325,25 @@ TEST_F(LayerTreeHostCommonTest, SmallIdealScale) { SkMScalar initial_child_scale = 0.25; child_scale_matrix.Scale(initial_child_scale, initial_child_scale); - scoped_refptr<Layer> root = Layer::Create(); + LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); - scoped_refptr<FakePictureLayer> parent = - CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(parent.get(), - parent_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - false, - true); - - scoped_refptr<FakePictureLayer> child_scale = - CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(child_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(10, 10), - false, - true); - - root->AddChild(parent); - - parent->AddChild(child_scale); + LayerImpl* parent = AddChildToRoot<LayerImpl>(); + SetLayerPropertiesForTesting(parent, parent_scale_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), false, true, + false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + LayerImpl* child_scale = AddChild<LayerImpl>(parent); + SetLayerPropertiesForTesting(child_scale, child_scale_matrix, gfx::Point3F(), + gfx::PointF(2.f, 2.f), gfx::Size(10, 10), false, + true, false); float device_scale_factor = 2.5f; float page_scale_factor = 0.01f; { - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), root->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); - inputs.can_adjust_raster_scales = true; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); + ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor, + root); // The ideal scale is able to go below 1. float expected_ideal_scale = @@ -4958,422 +4358,7 @@ TEST_F(LayerTreeHostCommonTest, SmallIdealScale) { } } -TEST_F(LayerTreeHostCommonTest, ContentsScaleForSurfaces) { - MockContentLayerClient delegate; - gfx::Transform identity_matrix; - - gfx::Transform parent_scale_matrix; - SkMScalar initial_parent_scale = 2.0; - parent_scale_matrix.Scale(initial_parent_scale, initial_parent_scale); - - gfx::Transform child_scale_matrix; - SkMScalar initial_child_scale = 3.0; - child_scale_matrix.Scale(initial_child_scale, initial_child_scale); - - scoped_refptr<Layer> root = Layer::Create(); - root->SetBounds(gfx::Size(100, 100)); - - scoped_refptr<ContentLayer> parent = CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(parent.get(), - parent_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - false, - true); - - scoped_refptr<ContentLayer> surface_scale = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<ContentLayer> surface_scale_child_scale = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_scale_child_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<NoScaleContentLayer> surface_scale_child_no_scale = - CreateNoScaleDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_scale_child_no_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<NoScaleContentLayer> surface_no_scale = - CreateNoScaleDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_no_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(12.f, 12.f), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<ContentLayer> surface_no_scale_child_scale = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_no_scale_child_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<NoScaleContentLayer> surface_no_scale_child_no_scale = - CreateNoScaleDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_no_scale_child_no_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - false, - true); - - root->AddChild(parent); - - parent->AddChild(surface_scale); - parent->AddChild(surface_no_scale); - - surface_scale->SetForceRenderSurface(true); - surface_scale->AddChild(surface_scale_child_scale); - surface_scale->AddChild(surface_scale_child_no_scale); - - surface_no_scale->SetForceRenderSurface(true); - surface_no_scale->AddChild(surface_no_scale_child_scale); - surface_no_scale->AddChild(surface_no_scale_child_no_scale); - - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); - - SkMScalar device_scale_factor = 5; - SkMScalar page_scale_factor = 7; - - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), root->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); - inputs.can_adjust_raster_scales = true; - inputs.verify_property_trees = false; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_CONTENTS_SCALE_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale, parent); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - surface_scale); - EXPECT_CONTENTS_SCALE_EQ(1, surface_no_scale); - EXPECT_CONTENTS_SCALE_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_scale_child_scale); - EXPECT_CONTENTS_SCALE_EQ(1, surface_scale_child_no_scale); - EXPECT_CONTENTS_SCALE_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_no_scale_child_scale); - EXPECT_CONTENTS_SCALE_EQ(1, surface_no_scale_child_no_scale); - - // The parent is scaled up and shouldn't need to scale during draw. - EXPECT_FLOAT_EQ(1.0, parent->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(1.0, parent->draw_transform().matrix().get(1, 1)); - - // RenderSurfaces should always be 1:1 with their target. - EXPECT_FLOAT_EQ( - 1.0, - surface_scale->render_surface()->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - 1.0, - surface_scale->render_surface()->draw_transform().matrix().get(1, 1)); - - // The surface_scale can apply contents scale so the layer shouldn't need to - // scale during draw. - EXPECT_FLOAT_EQ(1.0, surface_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(1.0, surface_scale->draw_transform().matrix().get(1, 1)); - - // The surface_scale_child_scale can apply contents scale so it shouldn't need - // to scale during draw. - EXPECT_FLOAT_EQ( - 1.0, surface_scale_child_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - 1.0, surface_scale_child_scale->draw_transform().matrix().get(1, 1)); - - // The surface_scale_child_no_scale can not apply contents scale, so it needs - // to be scaled during draw. - EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_scale_child_no_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_scale_child_no_scale->draw_transform().matrix().get(1, 1)); - - // RenderSurfaces should always be 1:1 with their target. - EXPECT_FLOAT_EQ( - 1.0, - surface_no_scale->render_surface()->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - 1.0, - surface_no_scale->render_surface()->draw_transform().matrix().get(1, 1)); - - // The surface_no_scale layer can not apply contents scale, so it needs to be - // scaled during draw. - EXPECT_FLOAT_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - surface_no_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(device_scale_factor * page_scale_factor * - initial_parent_scale * initial_child_scale, - surface_no_scale->draw_transform().matrix().get(1, 1)); - - // The surface_scale_child_scale can apply contents scale so it shouldn't need - // to scale during draw. - EXPECT_FLOAT_EQ( - 1.0, surface_no_scale_child_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - 1.0, surface_no_scale_child_scale->draw_transform().matrix().get(1, 1)); - - // The surface_scale_child_no_scale can not apply contents scale, so it needs - // to be scaled during draw. - EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_no_scale_child_no_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_no_scale_child_no_scale->draw_transform().matrix().get(1, 1)); -} - -// TODO(sohanjg): Remove this test when ContentLayer is removed. -TEST_F(LayerTreeHostCommonTest, - ContentsScaleForSurfaces_LayerTransformsDontAffectContentsScale) { - MockContentLayerClient delegate; - gfx::Transform identity_matrix; - - gfx::Transform parent_scale_matrix; - SkMScalar initial_parent_scale = 2.0; - parent_scale_matrix.Scale(initial_parent_scale, initial_parent_scale); - - gfx::Transform child_scale_matrix; - SkMScalar initial_child_scale = 3.0; - child_scale_matrix.Scale(initial_child_scale, initial_child_scale); - - scoped_refptr<Layer> root = Layer::Create(); - root->SetBounds(gfx::Size(100, 100)); - - scoped_refptr<ContentLayer> parent = CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(parent.get(), - parent_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - false, - true); - - scoped_refptr<ContentLayer> surface_scale = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<ContentLayer> surface_scale_child_scale = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_scale_child_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<NoScaleContentLayer> surface_scale_child_no_scale = - CreateNoScaleDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_scale_child_no_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<NoScaleContentLayer> surface_no_scale = - CreateNoScaleDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_no_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(12.f, 12.f), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<ContentLayer> surface_no_scale_child_scale = - CreateDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_no_scale_child_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - false, - true); - - scoped_refptr<NoScaleContentLayer> surface_no_scale_child_no_scale = - CreateNoScaleDrawableContentLayer(&delegate); - SetLayerPropertiesForTesting(surface_no_scale_child_no_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(10, 10), - false, - true); - - root->AddChild(parent); - - parent->AddChild(surface_scale); - parent->AddChild(surface_no_scale); - - surface_scale->SetForceRenderSurface(true); - surface_scale->AddChild(surface_scale_child_scale); - surface_scale->AddChild(surface_scale_child_no_scale); - - surface_no_scale->SetForceRenderSurface(true); - surface_no_scale->AddChild(surface_no_scale_child_scale); - surface_no_scale->AddChild(surface_no_scale_child_no_scale); - - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); - - RenderSurfaceLayerList render_surface_layer_list; - - SkMScalar device_scale_factor = 5.0; - SkMScalar page_scale_factor = 7.0; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), root->bounds(), &render_surface_layer_list); - inputs.device_scale_factor = device_scale_factor; - inputs.page_scale_factor = page_scale_factor; - inputs.page_scale_application_layer = root.get(); - inputs.verify_property_trees = false; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - parent); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - surface_scale); - EXPECT_CONTENTS_SCALE_EQ(1.f, surface_no_scale); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - surface_scale_child_scale); - EXPECT_CONTENTS_SCALE_EQ(1.f, surface_scale_child_no_scale); - EXPECT_CONTENTS_SCALE_EQ(device_scale_factor * page_scale_factor, - surface_no_scale_child_scale); - EXPECT_CONTENTS_SCALE_EQ(1.f, surface_no_scale_child_no_scale); - - // The parent is scaled up during draw, since its contents are not scaled by - // the transform hierarchy. - EXPECT_FLOAT_EQ(initial_parent_scale, - parent->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(initial_parent_scale, - parent->draw_transform().matrix().get(1, 1)); - - // The child surface is not scaled up during draw since its subtree is scaled - // by the transform hierarchy. - EXPECT_FLOAT_EQ( - 1.f, - surface_scale->render_surface()->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - 1.f, - surface_scale->render_surface()->draw_transform().matrix().get(1, 1)); - - // The surface_scale's RenderSurface is not scaled during draw, so the layer - // needs to be scaled when drawing into its surface. - EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale, - surface_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale, - surface_scale->draw_transform().matrix().get(1, 1)); - - // The surface_scale_child_scale is not scaled when drawing into its surface, - // since its content bounds are scaled by the transform hierarchy. - EXPECT_FLOAT_EQ( - initial_child_scale * initial_child_scale * initial_parent_scale, - surface_scale_child_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - initial_child_scale * initial_child_scale * initial_parent_scale, - surface_scale_child_scale->draw_transform().matrix().get(1, 1)); - - // The surface_scale_child_no_scale is scaled by the device scale, page scale - // and transform hierarchy. - EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_scale_child_no_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_scale_child_no_scale->draw_transform().matrix().get(1, 1)); - - // The child surface is not scaled up during draw since its subtree is scaled - // by the transform hierarchy. - EXPECT_FLOAT_EQ( - 1.f, - surface_no_scale->render_surface()->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - 1.f, - surface_no_scale->render_surface()->draw_transform().matrix().get(1, 1)); - - // The surface_no_scale layer has a fixed contents scale of 1, so it needs to - // be scaled by the device and page scale factors. Its surface is already - // scaled by the transform hierarchy so those don't need to scale the layer's - // drawing. - EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale * - device_scale_factor * page_scale_factor, - surface_no_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale * - device_scale_factor * page_scale_factor, - surface_no_scale->draw_transform().matrix().get(1, 1)); - - // The surface_no_scale_child_scale has its contents scaled by the page and - // device scale factors, but needs to be scaled by the transform hierarchy - // when drawing. - EXPECT_FLOAT_EQ( - initial_parent_scale * initial_child_scale * initial_child_scale, - surface_no_scale_child_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - initial_parent_scale * initial_child_scale * initial_child_scale, - surface_no_scale_child_scale->draw_transform().matrix().get(1, 1)); - - // The surface_no_scale_child_no_scale needs to be scaled by the device and - // page scale factors and by any transform heirarchy below its target surface. - EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_no_scale_child_no_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_parent_scale * - initial_child_scale * initial_child_scale, - surface_no_scale_child_no_scale->draw_transform().matrix().get(1, 1)); -} - -TEST_F(LayerTreeHostCommonTest, IdealScaleForAnimatingLayer) { - MockContentLayerClient delegate; - gfx::Transform identity_matrix; - +TEST_F(LayerTreeHostCommonScalingTest, IdealScaleForAnimatingLayer) { gfx::Transform parent_scale_matrix; SkMScalar initial_parent_scale = 1.75; parent_scale_matrix.Scale(initial_parent_scale, initial_parent_scale); @@ -5382,42 +4367,21 @@ TEST_F(LayerTreeHostCommonTest, IdealScaleForAnimatingLayer) { SkMScalar initial_child_scale = 1.25; child_scale_matrix.Scale(initial_child_scale, initial_child_scale); - scoped_refptr<Layer> root = Layer::Create(); + LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); - scoped_refptr<FakePictureLayer> parent = - CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(parent.get(), - parent_scale_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - false, - true); - - scoped_refptr<FakePictureLayer> child_scale = - CreateDrawablePictureLayer(&delegate); - SetLayerPropertiesForTesting(child_scale.get(), - child_scale_matrix, - gfx::Point3F(), - gfx::PointF(2.f, 2.f), - gfx::Size(10, 10), - false, - true); - - root->AddChild(parent); - - parent->AddChild(child_scale); + LayerImpl* parent = AddChildToRoot<LayerImpl>(); + SetLayerPropertiesForTesting(parent, parent_scale_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), false, true, + false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + LayerImpl* child_scale = AddChild<LayerImpl>(parent); + SetLayerPropertiesForTesting(child_scale, child_scale_matrix, gfx::Point3F(), + gfx::PointF(2.f, 2.f), gfx::Size(10, 10), false, + true, false); { - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), root->bounds(), &render_surface_layer_list); - inputs.can_adjust_raster_scales = true; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); + ExecuteCalculateDrawProperties(root); EXPECT_IDEAL_SCALE_EQ(initial_parent_scale, parent); // Animating layers compute ideal scale in the same way as when @@ -5427,74 +4391,12 @@ TEST_F(LayerTreeHostCommonTest, IdealScaleForAnimatingLayer) { } } -// TODO(sohanjg): Remove this test when ContentLayer is removed. -TEST_F(LayerTreeHostCommonTest, - ChangeInContentBoundsOrScaleTriggersPushProperties) { - MockContentLayerClient delegate; - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = CreateDrawableContentLayer(&delegate); - root->AddChild(child); - - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); - - gfx::Transform identity_matrix; - SetLayerPropertiesForTesting(root.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - true, - false); - SetLayerPropertiesForTesting(child.get(), - identity_matrix, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(100, 100), - true, - false); - - root->reset_needs_push_properties_for_testing(); - child->reset_needs_push_properties_for_testing(); - - gfx::Size device_viewport_size = gfx::Size(100, 100); - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), device_viewport_size, &render_surface_layer_list); - inputs.device_scale_factor = 1.f; - inputs.can_adjust_raster_scales = true; - inputs.verify_property_trees = false; - - // This will change both layers' content bounds. - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - EXPECT_TRUE(root->needs_push_properties()); - EXPECT_TRUE(child->needs_push_properties()); - - root->reset_needs_push_properties_for_testing(); - child->reset_needs_push_properties_for_testing(); - - // This will change only the child layer's contents scale and content bounds, - // since the root layer is not a ContentsScalingLayer. - inputs.device_scale_factor = 2.f; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - EXPECT_FALSE(root->needs_push_properties()); - EXPECT_TRUE(child->needs_push_properties()); - - root->reset_needs_push_properties_for_testing(); - child->reset_needs_push_properties_for_testing(); - - // This will not change either layer's contents scale or content bounds. - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - EXPECT_FALSE(root->needs_push_properties()); - EXPECT_FALSE(child->needs_push_properties()); -} - TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) { MockContentLayerClient delegate; gfx::Transform identity_matrix; scoped_refptr<FakePictureLayer> parent = - CreateDrawablePictureLayer(&delegate); + CreateDrawablePictureLayer(layer_settings(), &delegate); SetLayerPropertiesForTesting(parent.get(), identity_matrix, gfx::Point3F(), @@ -5503,7 +4405,8 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) { false, true); - scoped_refptr<FakePictureLayer> child = CreateDrawablePictureLayer(&delegate); + scoped_refptr<FakePictureLayer> child = + CreateDrawablePictureLayer(layer_settings(), &delegate); SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(), @@ -5515,7 +4418,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) { gfx::Transform replica_transform; replica_transform.Scale(1.0, -1.0); scoped_refptr<FakePictureLayer> replica = - CreateDrawablePictureLayer(&delegate); + CreateDrawablePictureLayer(layer_settings(), &delegate); SetLayerPropertiesForTesting(replica.get(), replica_transform, gfx::Point3F(), @@ -5527,7 +4430,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) { // This layer should end up in the same surface as child, with the same draw // and screen space transforms. scoped_refptr<FakePictureLayer> duplicate_child_non_owner = - CreateDrawablePictureLayer(&delegate); + CreateDrawablePictureLayer(layer_settings(), &delegate); SetLayerPropertiesForTesting(duplicate_child_non_owner.get(), identity_matrix, gfx::Point3F(), @@ -5540,8 +4443,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) { child->AddChild(duplicate_child_non_owner); child->SetReplicaLayer(replica.get()); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); RenderSurfaceLayerList render_surface_layer_list; @@ -5585,8 +4487,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) { duplicate_child_non_owner->screen_space_transform()); EXPECT_EQ(child->drawable_content_rect(), duplicate_child_non_owner->drawable_content_rect()); - EXPECT_EQ(child->content_bounds(), - duplicate_child_non_owner->content_bounds()); + EXPECT_EQ(child->bounds(), duplicate_child_non_owner->bounds()); gfx::Transform expected_render_surface_draw_transform; expected_render_surface_draw_transform.Translate( @@ -5634,7 +4535,7 @@ TEST_F(LayerTreeHostCommonTest, gfx::Transform identity_matrix; scoped_refptr<FakePictureLayer> parent = - CreateDrawablePictureLayer(&delegate); + CreateDrawablePictureLayer(layer_settings(), &delegate); SetLayerPropertiesForTesting(parent.get(), identity_matrix, gfx::Point3F(), @@ -5643,7 +4544,8 @@ TEST_F(LayerTreeHostCommonTest, false, true); - scoped_refptr<FakePictureLayer> child = CreateDrawablePictureLayer(&delegate); + scoped_refptr<FakePictureLayer> child = + CreateDrawablePictureLayer(layer_settings(), &delegate); SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(), @@ -5655,7 +4557,7 @@ TEST_F(LayerTreeHostCommonTest, gfx::Transform replica_transform; replica_transform.Scale(1.0, -1.0); scoped_refptr<FakePictureLayer> replica = - CreateDrawablePictureLayer(&delegate); + CreateDrawablePictureLayer(layer_settings(), &delegate); SetLayerPropertiesForTesting(replica.get(), replica_transform, gfx::Point3F(), @@ -5667,8 +4569,7 @@ TEST_F(LayerTreeHostCommonTest, parent->AddChild(child); child->SetReplicaLayer(replica.get()); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(parent); + host()->SetRootLayer(parent); float device_scale_factor = 1.7f; @@ -5705,19 +4606,18 @@ TEST_F(LayerTreeHostCommonTest, } TEST_F(LayerTreeHostCommonTest, SubtreeSearch) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grand_child = Layer::Create(); - scoped_refptr<Layer> mask_layer = Layer::Create(); - scoped_refptr<Layer> replica_layer = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings()); + scoped_refptr<Layer> mask_layer = Layer::Create(layer_settings()); + scoped_refptr<Layer> replica_layer = Layer::Create(layer_settings()); grand_child->SetReplicaLayer(replica_layer.get()); child->AddChild(grand_child.get()); child->SetMaskLayer(mask_layer.get()); root->AddChild(child.get()); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); int nonexistent_id = -1; EXPECT_EQ(root.get(), @@ -5738,10 +4638,10 @@ TEST_F(LayerTreeHostCommonTest, SubtreeSearch) { } TEST_F(LayerTreeHostCommonTest, TransparentChildRenderSurfaceCreation) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> grand_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); const gfx::Transform identity_matrix; SetLayerPropertiesForTesting(root.get(), @@ -5770,8 +4670,7 @@ TEST_F(LayerTreeHostCommonTest, TransparentChildRenderSurfaceCreation) { child->AddChild(grand_child); child->SetOpacity(0.5f); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -5781,7 +4680,9 @@ TEST_F(LayerTreeHostCommonTest, TransparentChildRenderSurfaceCreation) { TEST_F(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.pending_tree(), 1); @@ -5818,12 +4719,12 @@ TEST_F(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) { } using LCDTextTestParam = std::tr1::tuple<bool, bool, bool>; -class LCDTextTest - : public LayerTreeHostCommonTestBase, - public testing::TestWithParam<LCDTextTestParam> { +class LCDTextTest : public LayerTreeHostCommonTestBase, + public testing::TestWithParam<LCDTextTestParam> { public: LCDTextTest() - : host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_), + : LayerTreeHostCommonTestBase(LayerTreeSettings()), + host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_), root_(nullptr), child_(nullptr), grand_child_(nullptr) {} @@ -5853,6 +4754,10 @@ class LCDTextTest child_->SetContentsOpaque(true); grand_child_->SetContentsOpaque(true); + root_->SetDrawsContent(true); + child_->SetDrawsContent(true); + grand_child_->SetDrawsContent(true); + gfx::Transform identity_matrix; SetLayerPropertiesForTesting(root_, identity_matrix, gfx::Point3F(), gfx::PointF(), gfx::Size(1, 1), true, false, @@ -5894,6 +4799,7 @@ TEST_P(LCDTextTest, CanUseLCDText) { gfx::Transform integral_translation; integral_translation.Translate(1.0, 2.0); child_->SetTransform(integral_translation); + child_->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root_, 1.f, 1.f, NULL, can_use_lcd_text_, layers_always_allowed_lcd_text_); EXPECT_EQ(expect_lcd_text, root_->can_use_lcd_text()); @@ -5904,6 +4810,7 @@ TEST_P(LCDTextTest, CanUseLCDText) { gfx::Transform non_integral_translation; non_integral_translation.Translate(1.5, 2.5); child_->SetTransform(non_integral_translation); + child_->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root_, 1.f, 1.f, NULL, can_use_lcd_text_, layers_always_allowed_lcd_text_); EXPECT_EQ(expect_lcd_text, root_->can_use_lcd_text()); @@ -5914,6 +4821,7 @@ TEST_P(LCDTextTest, CanUseLCDText) { gfx::Transform rotation; rotation.Rotate(10.0); child_->SetTransform(rotation); + child_->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root_, 1.f, 1.f, NULL, can_use_lcd_text_, layers_always_allowed_lcd_text_); EXPECT_EQ(expect_lcd_text, root_->can_use_lcd_text()); @@ -5924,6 +4832,7 @@ TEST_P(LCDTextTest, CanUseLCDText) { gfx::Transform scale; scale.Scale(2.0, 2.0); child_->SetTransform(scale); + child_->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root_, 1.f, 1.f, NULL, can_use_lcd_text_, layers_always_allowed_lcd_text_); EXPECT_EQ(expect_lcd_text, root_->can_use_lcd_text()); @@ -5934,6 +4843,7 @@ TEST_P(LCDTextTest, CanUseLCDText) { gfx::Transform skew; skew.SkewX(10.0); child_->SetTransform(skew); + child_->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root_, 1.f, 1.f, NULL, can_use_lcd_text_, layers_always_allowed_lcd_text_); EXPECT_EQ(expect_lcd_text, root_->can_use_lcd_text()); @@ -5942,6 +4852,7 @@ TEST_P(LCDTextTest, CanUseLCDText) { // Case 7: Translucent. child_->SetTransform(identity_matrix); + child_->layer_tree_impl()->property_trees()->needs_rebuild = true; child_->SetOpacity(0.5f); ExecuteCalculateDrawProperties(root_, 1.f, 1.f, NULL, can_use_lcd_text_, layers_always_allowed_lcd_text_); @@ -5951,6 +4862,7 @@ TEST_P(LCDTextTest, CanUseLCDText) { // Case 8: Sanity check: restore transform and opacity. child_->SetTransform(identity_matrix); + child_->layer_tree_impl()->property_trees()->needs_rebuild = true; child_->SetOpacity(1.f); ExecuteCalculateDrawProperties(root_, 1.f, 1.f, NULL, can_use_lcd_text_, layers_always_allowed_lcd_text_); @@ -5988,6 +4900,7 @@ TEST_P(LCDTextTest, CanUseLCDTextWithAnimation) { // Add opacity animation. child_->SetOpacity(0.9f); + child_->layer_tree_impl()->property_trees()->needs_rebuild = true; AddOpacityTransitionToController( child_->layer_animation_controller(), 10.0, 0.9f, 0.1f, false); @@ -6032,11 +4945,13 @@ INSTANTIATE_TEST_CASE_P(LayerTreeHostCommonTest, TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayer) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); const gfx::Transform identity_matrix; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), @@ -6046,7 +4961,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayer) { false); root->SetIsDrawable(true); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(), @@ -6056,7 +4971,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayer) { false); child->SetIsDrawable(true); - scoped_refptr<Layer> grand_child = Layer::Create(); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(grand_child.get(), identity_matrix, gfx::Point3F(), @@ -6070,8 +4985,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayer) { child->AddChild(grand_child); root->AddChild(child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); RenderSurfaceLayerList render_surface_layer_list; LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( @@ -6090,7 +5004,9 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayer) { TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayerImpl) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); const gfx::Transform identity_matrix; @@ -6135,11 +5051,13 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayerImpl) { TEST_F(LayerTreeHostCommonTest, SubtreeHidden_TwoLayers) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); const gfx::Transform identity_matrix; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), @@ -6149,7 +5067,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_TwoLayers) { false); root->SetIsDrawable(true); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(), @@ -6160,7 +5078,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_TwoLayers) { child->SetIsDrawable(true); child->SetHideLayerAndSubtree(true); - scoped_refptr<Layer> grand_child = Layer::Create(); + scoped_refptr<Layer> grand_child = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(grand_child.get(), identity_matrix, gfx::Point3F(), @@ -6173,8 +5091,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_TwoLayers) { child->AddChild(grand_child); root->AddChild(child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); RenderSurfaceLayerList render_surface_layer_list; LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( @@ -6192,7 +5109,9 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_TwoLayers) { TEST_F(LayerTreeHostCommonTest, SubtreeHidden_TwoLayersImpl) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); const gfx::Transform identity_matrix; @@ -6237,11 +5156,13 @@ void EmptyCopyOutputCallback(scoped_ptr<CopyOutputResult> result) {} TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); const gfx::Transform identity_matrix; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), @@ -6251,7 +5172,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { false); root->SetIsDrawable(true); - scoped_refptr<Layer> copy_grand_parent = Layer::Create(); + scoped_refptr<Layer> copy_grand_parent = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(copy_grand_parent.get(), identity_matrix, gfx::Point3F(), @@ -6261,7 +5182,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { false); copy_grand_parent->SetIsDrawable(true); - scoped_refptr<Layer> copy_parent = Layer::Create(); + scoped_refptr<Layer> copy_parent = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(copy_parent.get(), identity_matrix, gfx::Point3F(), @@ -6272,7 +5193,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { copy_parent->SetIsDrawable(true); copy_parent->SetForceRenderSurface(true); - scoped_refptr<Layer> copy_layer = Layer::Create(); + scoped_refptr<Layer> copy_layer = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(copy_layer.get(), identity_matrix, gfx::Point3F(), @@ -6282,7 +5203,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { false); copy_layer->SetIsDrawable(true); - scoped_refptr<Layer> copy_child = Layer::Create(); + scoped_refptr<Layer> copy_child = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(copy_child.get(), identity_matrix, gfx::Point3F(), @@ -6292,7 +5213,8 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { false); copy_child->SetIsDrawable(true); - scoped_refptr<Layer> copy_grand_parent_sibling_before = Layer::Create(); + scoped_refptr<Layer> copy_grand_parent_sibling_before = + Layer::Create(layer_settings()); SetLayerPropertiesForTesting(copy_grand_parent_sibling_before.get(), identity_matrix, gfx::Point3F(), @@ -6302,7 +5224,8 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { false); copy_grand_parent_sibling_before->SetIsDrawable(true); - scoped_refptr<Layer> copy_grand_parent_sibling_after = Layer::Create(); + scoped_refptr<Layer> copy_grand_parent_sibling_after = + Layer::Create(layer_settings()); SetLayerPropertiesForTesting(copy_grand_parent_sibling_after.get(), identity_matrix, gfx::Point3F(), @@ -6319,8 +5242,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { root->AddChild(copy_grand_parent); root->AddChild(copy_grand_parent_sibling_after); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // Hide the copy_grand_parent and its subtree. But make a copy request in that // hidden subtree on copy_layer. @@ -6384,11 +5306,13 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { TEST_F(LayerTreeHostCommonTest, ClippedOutCopyRequest) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); const gfx::Transform identity_matrix; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), @@ -6398,7 +5322,7 @@ TEST_F(LayerTreeHostCommonTest, ClippedOutCopyRequest) { false); root->SetIsDrawable(true); - scoped_refptr<Layer> copy_parent = Layer::Create(); + scoped_refptr<Layer> copy_parent = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(copy_parent.get(), identity_matrix, gfx::Point3F(), @@ -6409,7 +5333,7 @@ TEST_F(LayerTreeHostCommonTest, ClippedOutCopyRequest) { copy_parent->SetIsDrawable(true); copy_parent->SetMasksToBounds(true); - scoped_refptr<Layer> copy_layer = Layer::Create(); + scoped_refptr<Layer> copy_layer = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(copy_layer.get(), identity_matrix, gfx::Point3F(), @@ -6419,7 +5343,7 @@ TEST_F(LayerTreeHostCommonTest, ClippedOutCopyRequest) { false); copy_layer->SetIsDrawable(true); - scoped_refptr<Layer> copy_child = Layer::Create(); + scoped_refptr<Layer> copy_child = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(copy_child.get(), identity_matrix, gfx::Point3F(), @@ -6433,8 +5357,7 @@ TEST_F(LayerTreeHostCommonTest, ClippedOutCopyRequest) { copy_parent->AddChild(copy_layer); root->AddChild(copy_parent); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); copy_layer->RequestCopyOfOutput(CopyOutputRequest::CreateRequest( base::Bind(&EmptyCopyOutputCallback))); @@ -6459,11 +5382,13 @@ TEST_F(LayerTreeHostCommonTest, ClippedOutCopyRequest) { TEST_F(LayerTreeHostCommonTest, VisibleContentRectInsideSurface) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); const gfx::Transform identity_matrix; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), @@ -6474,7 +5399,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInsideSurface) { root->SetIsDrawable(true); // The surface is moved slightly outside of the viewport. - scoped_refptr<Layer> surface = Layer::Create(); + scoped_refptr<Layer> surface = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(surface.get(), identity_matrix, gfx::Point3F(), @@ -6484,7 +5409,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInsideSurface) { false); surface->SetForceRenderSurface(true); - scoped_refptr<Layer> surface_child = Layer::Create(); + scoped_refptr<Layer> surface_child = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(surface_child.get(), identity_matrix, gfx::Point3F(), @@ -6497,8 +5422,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInsideSurface) { surface->AddChild(surface_child); root->AddChild(surface); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); RenderSurfaceLayerList render_surface_layer_list; LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( @@ -6506,10 +5430,10 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInsideSurface) { inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawProperties(&inputs); - // The visible_content_rect for the |surface_child| should not be clipped by + // The visible_layer_rect for the |surface_child| should not be clipped by // the viewport. EXPECT_EQ(gfx::Rect(50, 50).ToString(), - surface_child->visible_content_rect().ToString()); + surface_child->visible_layer_rect().ToString()); } TEST_F(LayerTreeHostCommonTest, TransformedClipParent) { @@ -6524,12 +5448,12 @@ TEST_F(LayerTreeHostCommonTest, TransformedClipParent) { // // The render surface should be resized correctly and the clip child should // inherit the right clip rect. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> render_surface = Layer::Create(); - scoped_refptr<Layer> clip_parent = Layer::Create(); - scoped_refptr<Layer> intervening = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface = Layer::Create(layer_settings()); + scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> intervening = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> clip_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(render_surface); render_surface->AddChild(clip_parent); @@ -6584,8 +5508,7 @@ TEST_F(LayerTreeHostCommonTest, TransformedClipParent) { true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -6626,13 +5549,13 @@ TEST_F(LayerTreeHostCommonTest, ClipParentWithInterveningRenderSurface) { // + render_surface2 (also sets opacity) // + clip_child // - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> clip_parent = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); - scoped_refptr<Layer> intervening = Layer::Create(); - scoped_refptr<Layer> render_surface2 = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> intervening = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> clip_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(clip_parent); clip_parent->AddChild(render_surface1); @@ -6695,8 +5618,7 @@ TEST_F(LayerTreeHostCommonTest, ClipParentWithInterveningRenderSurface) { true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -6737,7 +5659,7 @@ TEST_F(LayerTreeHostCommonTest, ClipParentWithInterveningRenderSurface) { EXPECT_EQ(gfx::Rect(-1, -1, 40, 40).ToString(), clip_child->clip_rect().ToString()); EXPECT_EQ(gfx::Rect(9, 9, 40, 40).ToString(), - clip_child->visible_content_rect().ToString()); + clip_child->visible_layer_rect().ToString()); EXPECT_TRUE(clip_child->is_clipped()); } @@ -6753,13 +5675,13 @@ TEST_F(LayerTreeHostCommonTest, ClipParentScrolledInterveningLayer) { // + render_surface2 (also sets opacity) // + clip_child // - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> clip_parent = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); - scoped_refptr<Layer> intervening = Layer::Create(); - scoped_refptr<Layer> render_surface2 = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> intervening = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> clip_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(clip_parent); clip_parent->AddChild(render_surface1); @@ -6824,8 +5746,7 @@ TEST_F(LayerTreeHostCommonTest, ClipParentScrolledInterveningLayer) { true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -6866,7 +5787,7 @@ TEST_F(LayerTreeHostCommonTest, ClipParentScrolledInterveningLayer) { EXPECT_EQ(gfx::Rect(2, 2, 40, 40).ToString(), clip_child->clip_rect().ToString()); EXPECT_EQ(gfx::Rect(12, 12, 40, 40).ToString(), - clip_child->visible_content_rect().ToString()); + clip_child->visible_layer_rect().ToString()); EXPECT_TRUE(clip_child->is_clipped()); } @@ -6879,12 +5800,12 @@ TEST_F(LayerTreeHostCommonTest, DescendantsOfClipChildren) { // + clip_child // + child // - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> clip_parent = Layer::Create(); - scoped_refptr<Layer> intervening = Layer::Create(); - scoped_refptr<Layer> clip_child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> intervening = Layer::Create(layer_settings()); + scoped_refptr<Layer> clip_child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(clip_parent); clip_parent->AddChild(intervening); @@ -6933,8 +5854,7 @@ TEST_F(LayerTreeHostCommonTest, DescendantsOfClipChildren) { true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -6946,7 +5866,7 @@ TEST_F(LayerTreeHostCommonTest, DescendantsOfClipChildren) { clip_child->clip_rect().ToString()); EXPECT_TRUE(clip_child->is_clipped()); EXPECT_EQ(gfx::Rect(0, 0, 40, 40).ToString(), - child->visible_content_rect().ToString()); + child->visible_layer_rect().ToString()); EXPECT_TRUE(child->is_clipped()); } @@ -6963,14 +5883,14 @@ TEST_F(LayerTreeHostCommonTest, // + non_clip_child // // In this example render_surface2 should be unaffected by clip_child. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> clip_parent = Layer::Create(); - scoped_refptr<Layer> render_surface1 = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> clip_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); - scoped_refptr<Layer> render_surface2 = Layer::Create(); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); + scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> non_clip_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(clip_parent); clip_parent->AddChild(render_surface1); @@ -7030,8 +5950,7 @@ TEST_F(LayerTreeHostCommonTest, render_surface1->SetForceRenderSurface(true); render_surface2->SetForceRenderSurface(true); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -7063,14 +5982,16 @@ TEST_F(LayerTreeHostCommonTest, render_surface2->render_surface()->content_rect().ToString()); // Sanity check our num_unclipped_descendants values. - EXPECT_EQ(1, render_surface1->num_unclipped_descendants()); - EXPECT_EQ(0, render_surface2->num_unclipped_descendants()); + EXPECT_EQ(1u, render_surface1->num_unclipped_descendants()); + EXPECT_EQ(0u, render_surface2->num_unclipped_descendants()); } TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 12345); scoped_ptr<LayerImpl> child1 = @@ -7120,8 +6041,8 @@ TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { int count_represents_target_render_surface = 0; int count_represents_contributing_render_surface = 0; int count_represents_itself = 0; - auto end = LayerIterator<LayerImpl>::End(&render_surface_layer_list); - for (auto it = LayerIterator<LayerImpl>::Begin(&render_surface_layer_list); + LayerIterator end = LayerIterator::End(&render_surface_layer_list); + for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list); it != end; ++it) { if (it.represents_target_render_surface()) count_represents_target_render_surface++; @@ -7151,8 +6072,8 @@ TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { int count_represents_target_render_surface = 0; int count_represents_contributing_render_surface = 0; int count_represents_itself = 0; - auto end = LayerIterator<LayerImpl>::End(&render_surface_layer_list); - for (auto it = LayerIterator<LayerImpl>::Begin(&render_surface_layer_list); + LayerIterator end = LayerIterator::End(&render_surface_layer_list); + for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list); it != end; ++it) { if (it.represents_target_render_surface()) count_represents_target_render_surface++; @@ -7172,66 +6093,53 @@ TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { } TEST_F(LayerTreeHostCommonTest, DoNotIncludeBackfaceInvisibleSurfaces) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> render_surface = Layer::Create(); - scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent); - - root->AddChild(render_surface); - render_surface->AddChild(child); + LayerImpl* root = root_layer(); + LayerImpl* render_surface = AddChild<LayerImpl>(root); + LayerImpl* child = AddChild<LayerImpl>(render_surface); + child->SetDrawsContent(true); gfx::Transform identity_transform; - SetLayerPropertiesForTesting(root.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(render_surface.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(30, 30), - false, + SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false, true); - SetLayerPropertiesForTesting(child.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(20, 20), - true, + SetLayerPropertiesForTesting(render_surface, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30), + false, true, true); + SetLayerPropertiesForTesting(child, identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(20, 20), true, false, false); root->SetShouldFlattenTransform(false); root->Set3dSortingContextId(1); render_surface->SetDoubleSided(false); - render_surface->SetForceRenderSurface(true); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + ExecuteCalculateDrawProperties(root); - ExecuteCalculateDrawProperties(root.get()); - - EXPECT_EQ(2u, render_surface_layer_list()->size()); - EXPECT_EQ(1u, - render_surface_layer_list()->at(0) - ->render_surface()->layer_list().size()); - EXPECT_EQ(1u, - render_surface_layer_list()->at(1) - ->render_surface()->layer_list().size()); + EXPECT_EQ(2u, render_surface_layer_list_impl()->size()); + EXPECT_EQ(1u, render_surface_layer_list_impl() + ->at(0) + ->render_surface() + ->layer_list() + .size()); + EXPECT_EQ(1u, render_surface_layer_list_impl() + ->at(1) + ->render_surface() + ->layer_list() + .size()); gfx::Transform rotation_transform = identity_transform; rotation_transform.RotateAboutXAxis(180.0); render_surface->SetTransform(rotation_transform); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawProperties(root); - EXPECT_EQ(1u, render_surface_layer_list()->size()); - EXPECT_EQ(0u, - render_surface_layer_list()->at(0) - ->render_surface()->layer_list().size()); + EXPECT_EQ(1u, render_surface_layer_list_impl()->size()); + EXPECT_EQ(0u, render_surface_layer_list_impl() + ->at(0) + ->render_surface() + ->layer_list() + .size()); } TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) { @@ -7244,13 +6152,13 @@ TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) { // | + scroll_parent // + scroll_child // - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> scroll_parent_border = Layer::Create(); - scoped_refptr<Layer> scroll_parent_clip = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> scroll_parent_border = Layer::Create(layer_settings()); + scoped_refptr<Layer> scroll_parent_clip = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> scroll_parent = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> scroll_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(scroll_child); @@ -7299,8 +6207,7 @@ TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) { true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -7313,11 +6220,11 @@ TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) { TEST_F(LayerTreeHostCommonTest, SingularTransformSubtreesDoNotDraw) { scoped_refptr<LayerWithForcedDrawsContent> root = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> parent = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(parent); parent->AddChild(child); @@ -7348,8 +6255,7 @@ TEST_F(LayerTreeHostCommonTest, SingularTransformSubtreesDoNotDraw) { true); child->SetForceRenderSurface(true); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -7380,70 +6286,45 @@ TEST_F(LayerTreeHostCommonTest, ClippedByOutOfOrderScrollParent) { // still results in correct clipping. // // + root - // + scroll_child // + scroll_parent_border // + scroll_parent_clip // + scroll_parent + // + scroll_child // - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> scroll_parent_border = Layer::Create(); - scoped_refptr<Layer> scroll_parent_clip = Layer::Create(); - scoped_refptr<LayerWithForcedDrawsContent> scroll_parent = - make_scoped_refptr(new LayerWithForcedDrawsContent); - scoped_refptr<LayerWithForcedDrawsContent> scroll_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); - - root->AddChild(scroll_parent_border); - scroll_parent_border->AddChild(scroll_parent_clip); - scroll_parent_clip->AddChild(scroll_parent); + LayerImpl* root = root_layer(); + LayerImpl* scroll_parent_border = AddChild<LayerImpl>(root); + LayerImpl* scroll_parent_clip = AddChild<LayerImpl>(scroll_parent_border); + LayerImpl* scroll_parent = AddChild<LayerImpl>(scroll_parent_clip); + LayerImpl* scroll_child = AddChild<LayerImpl>(root); - root->AddChild(scroll_child); + scroll_parent->SetDrawsContent(true); + scroll_child->SetDrawsContent(true); scroll_parent_clip->SetMasksToBounds(true); - scroll_child->SetScrollParent(scroll_parent.get()); + scroll_child->SetScrollParent(scroll_parent); + scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>); + scroll_children->insert(scroll_child); + scroll_parent->SetScrollChildren(scroll_children.release()); gfx::Transform identity_transform; - SetLayerPropertiesForTesting(root.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(scroll_parent_border.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(40, 40), - true, - false); - SetLayerPropertiesForTesting(scroll_parent_clip.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(30, 30), - true, - false); - SetLayerPropertiesForTesting(scroll_parent.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(scroll_child.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, + SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false, + true); + SetLayerPropertiesForTesting(scroll_parent_border, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(40, 40), + true, false, false); + SetLayerPropertiesForTesting(scroll_parent_clip, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30), + true, false, false); + SetLayerPropertiesForTesting(scroll_parent, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), + true, false, false); + SetLayerPropertiesForTesting(scroll_child, identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); - - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawProperties(root); EXPECT_TRUE(root->render_surface()); @@ -7465,98 +6346,60 @@ TEST_F(LayerTreeHostCommonTest, ClippedByOutOfOrderScrollGrandparent) { // + scroll_grandparent_clip // + scroll_grandparent // - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> scroll_parent_border = Layer::Create(); - scoped_refptr<Layer> scroll_parent_clip = Layer::Create(); - scoped_refptr<LayerWithForcedDrawsContent> scroll_parent = - make_scoped_refptr(new LayerWithForcedDrawsContent); - - scoped_refptr<Layer> scroll_grandparent_border = Layer::Create(); - scoped_refptr<Layer> scroll_grandparent_clip = Layer::Create(); - scoped_refptr<LayerWithForcedDrawsContent> scroll_grandparent = - make_scoped_refptr(new LayerWithForcedDrawsContent); - - scoped_refptr<LayerWithForcedDrawsContent> scroll_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); - - root->AddChild(scroll_child); - - root->AddChild(scroll_parent_border); - scroll_parent_border->AddChild(scroll_parent_clip); - scroll_parent_clip->AddChild(scroll_parent); - - root->AddChild(scroll_grandparent_border); - scroll_grandparent_border->AddChild(scroll_grandparent_clip); - scroll_grandparent_clip->AddChild(scroll_grandparent); + LayerImpl* root = root_layer(); + LayerImpl* scroll_child = AddChild<LayerImpl>(root); + LayerImpl* scroll_parent_border = AddChild<LayerImpl>(root); + LayerImpl* scroll_parent_clip = AddChild<LayerImpl>(scroll_parent_border); + LayerImpl* scroll_parent = AddChild<LayerImpl>(scroll_parent_clip); + LayerImpl* scroll_grandparent_border = AddChild<LayerImpl>(root); + LayerImpl* scroll_grandparent_clip = + AddChild<LayerImpl>(scroll_grandparent_border); + LayerImpl* scroll_grandparent = AddChild<LayerImpl>(scroll_grandparent_clip); + + scroll_parent->SetDrawsContent(true); + scroll_grandparent->SetDrawsContent(true); + scroll_child->SetDrawsContent(true); scroll_parent_clip->SetMasksToBounds(true); scroll_grandparent_clip->SetMasksToBounds(true); - scroll_child->SetScrollParent(scroll_parent.get()); - scroll_parent_border->SetScrollParent(scroll_grandparent.get()); + scroll_child->SetScrollParent(scroll_parent); + scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>); + scroll_children->insert(scroll_child); + scroll_parent->SetScrollChildren(scroll_children.release()); + + scroll_parent_border->SetScrollParent(scroll_grandparent); + scroll_children.reset(new std::set<LayerImpl*>); + scroll_children->insert(scroll_parent_border); + scroll_grandparent->SetScrollChildren(scroll_children.release()); gfx::Transform identity_transform; - SetLayerPropertiesForTesting(root.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(scroll_grandparent_border.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(40, 40), - true, - false); - SetLayerPropertiesForTesting(scroll_grandparent_clip.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(20, 20), - true, - false); - SetLayerPropertiesForTesting(scroll_grandparent.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(scroll_parent_border.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(40, 40), - true, - false); - SetLayerPropertiesForTesting(scroll_parent_clip.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(30, 30), - true, - false); - SetLayerPropertiesForTesting(scroll_parent.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(scroll_child.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, + SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false, + true); + SetLayerPropertiesForTesting(scroll_grandparent_border, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(40, 40), + true, false, false); + SetLayerPropertiesForTesting(scroll_grandparent_clip, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(20, 20), + true, false, false); + SetLayerPropertiesForTesting(scroll_grandparent, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), + true, false, false); + SetLayerPropertiesForTesting(scroll_parent_border, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(40, 40), + true, false, false); + SetLayerPropertiesForTesting(scroll_parent_clip, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30), + true, false, false); + SetLayerPropertiesForTesting(scroll_parent, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), + true, false, false); + SetLayerPropertiesForTesting(scroll_child, identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); - - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawProperties(root); EXPECT_TRUE(root->render_surface()); @@ -7567,12 +6410,9 @@ TEST_F(LayerTreeHostCommonTest, ClippedByOutOfOrderScrollGrandparent) { // Despite the fact that we visited the above layers out of order to get the // correct clip, the layer lists should be unaffected. EXPECT_EQ(3u, root->render_surface()->layer_list().size()); - EXPECT_EQ(scroll_child.get(), - root->render_surface()->layer_list().at(0).get()); - EXPECT_EQ(scroll_parent.get(), - root->render_surface()->layer_list().at(1).get()); - EXPECT_EQ(scroll_grandparent.get(), - root->render_surface()->layer_list().at(2).get()); + EXPECT_EQ(scroll_child, root->render_surface()->layer_list().at(0)); + EXPECT_EQ(scroll_parent, root->render_surface()->layer_list().at(1)); + EXPECT_EQ(scroll_grandparent, root->render_surface()->layer_list().at(2)); } TEST_F(LayerTreeHostCommonTest, OutOfOrderClippingRequiresRSLLSorting) { @@ -7583,136 +6423,79 @@ TEST_F(LayerTreeHostCommonTest, OutOfOrderClippingRequiresRSLLSorting) { // + scroll_parent_border // + scroll_parent_clip // + scroll_parent - // + render_surface1 + // + render_surface2 // + scroll_grandparent_border // + scroll_grandparent_clip // + scroll_grandparent - // + render_surface2 + // + render_surface1 // - scoped_refptr<LayerWithForcedDrawsContent> root = - make_scoped_refptr(new LayerWithForcedDrawsContent); - - scoped_refptr<Layer> scroll_parent_border = Layer::Create(); - scoped_refptr<Layer> scroll_parent_clip = Layer::Create(); - scoped_refptr<LayerWithForcedDrawsContent> scroll_parent = - make_scoped_refptr(new LayerWithForcedDrawsContent); - scoped_refptr<LayerWithForcedDrawsContent> render_surface1 = - make_scoped_refptr(new LayerWithForcedDrawsContent); - - scoped_refptr<Layer> scroll_grandparent_border = Layer::Create(); - scoped_refptr<Layer> scroll_grandparent_clip = Layer::Create(); - scoped_refptr<LayerWithForcedDrawsContent> scroll_grandparent = - make_scoped_refptr(new LayerWithForcedDrawsContent); - scoped_refptr<LayerWithForcedDrawsContent> render_surface2 = - make_scoped_refptr(new LayerWithForcedDrawsContent); - - scoped_refptr<LayerWithForcedDrawsContent> scroll_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); + LayerImpl* root = root_layer(); + root->SetDrawsContent(true); - root->AddChild(scroll_child); + LayerImpl* scroll_child = AddChild<LayerImpl>(root); + scroll_child->SetDrawsContent(true); - root->AddChild(scroll_parent_border); - scroll_parent_border->AddChild(scroll_parent_clip); - scroll_parent_clip->AddChild(scroll_parent); - scroll_parent->AddChild(render_surface2); + LayerImpl* scroll_parent_border = AddChild<LayerImpl>(root); + LayerImpl* scroll_parent_clip = AddChild<LayerImpl>(scroll_parent_border); + LayerImpl* scroll_parent = AddChild<LayerImpl>(scroll_parent_clip); + LayerImpl* render_surface2 = AddChild<LayerImpl>(scroll_parent); + LayerImpl* scroll_grandparent_border = AddChild<LayerImpl>(root); + LayerImpl* scroll_grandparent_clip = + AddChild<LayerImpl>(scroll_grandparent_border); + LayerImpl* scroll_grandparent = AddChild<LayerImpl>(scroll_grandparent_clip); + LayerImpl* render_surface1 = AddChild<LayerImpl>(scroll_grandparent); - root->AddChild(scroll_grandparent_border); - scroll_grandparent_border->AddChild(scroll_grandparent_clip); - scroll_grandparent_clip->AddChild(scroll_grandparent); - scroll_grandparent->AddChild(render_surface1); + scroll_parent->SetDrawsContent(true); + render_surface1->SetDrawsContent(true); + scroll_grandparent->SetDrawsContent(true); + render_surface2->SetDrawsContent(true); scroll_parent_clip->SetMasksToBounds(true); scroll_grandparent_clip->SetMasksToBounds(true); - scroll_child->SetScrollParent(scroll_parent.get()); - scroll_parent_border->SetScrollParent(scroll_grandparent.get()); + scroll_child->SetScrollParent(scroll_parent); + scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>); + scroll_children->insert(scroll_child); + scroll_parent->SetScrollChildren(scroll_children.release()); - render_surface1->SetForceRenderSurface(true); - render_surface2->SetForceRenderSurface(true); + scroll_parent_border->SetScrollParent(scroll_grandparent); + scroll_children.reset(new std::set<LayerImpl*>); + scroll_children->insert(scroll_parent_border); + scroll_grandparent->SetScrollChildren(scroll_children.release()); gfx::Transform identity_transform; - SetLayerPropertiesForTesting(root.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(scroll_grandparent_border.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(40, 40), - true, - false); - SetLayerPropertiesForTesting(scroll_grandparent_clip.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(20, 20), - true, - false); - SetLayerPropertiesForTesting(scroll_grandparent.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(render_surface1.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(scroll_parent_border.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(40, 40), - true, - false); - SetLayerPropertiesForTesting(scroll_parent_clip.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(30, 30), - true, - false); - SetLayerPropertiesForTesting(scroll_parent.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(render_surface2.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, - false); - SetLayerPropertiesForTesting(scroll_child.get(), - identity_transform, - gfx::Point3F(), - gfx::PointF(), - gfx::Size(50, 50), - true, + SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false, + true); + SetLayerPropertiesForTesting(scroll_grandparent_border, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(40, 40), + true, false, false); + SetLayerPropertiesForTesting(scroll_grandparent_clip, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(20, 20), + true, false, false); + SetLayerPropertiesForTesting(scroll_grandparent, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), + true, false, false); + SetLayerPropertiesForTesting(render_surface1, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), + true, false, true); + SetLayerPropertiesForTesting(scroll_parent_border, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(40, 40), + true, false, false); + SetLayerPropertiesForTesting(scroll_parent_clip, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30), + true, false, false); + SetLayerPropertiesForTesting(scroll_parent, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), + true, false, false); + SetLayerPropertiesForTesting(render_surface2, identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), + true, false, true); + SetLayerPropertiesForTesting(scroll_child, identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); - - RenderSurfaceLayerList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root.get(), - root->bounds(), - identity_transform, - &render_surface_layer_list); - - LayerTreeHostCommon::CalculateDrawProperties(&inputs); + ExecuteCalculateDrawProperties(root); EXPECT_TRUE(root->render_surface()); @@ -7722,13 +6505,13 @@ TEST_F(LayerTreeHostCommonTest, OutOfOrderClippingRequiresRSLLSorting) { // Despite the fact that we had to process the layers out of order to get the // right clip, our render_surface_layer_list's order should be unaffected. - EXPECT_EQ(3u, render_surface_layer_list.size()); - EXPECT_EQ(root.get(), render_surface_layer_list.at(0)); - EXPECT_EQ(render_surface2.get(), render_surface_layer_list.at(1)); - EXPECT_EQ(render_surface1.get(), render_surface_layer_list.at(2)); - EXPECT_TRUE(render_surface_layer_list.at(0)->render_surface()); - EXPECT_TRUE(render_surface_layer_list.at(1)->render_surface()); - EXPECT_TRUE(render_surface_layer_list.at(2)->render_surface()); + EXPECT_EQ(3u, render_surface_layer_list_impl()->size()); + EXPECT_EQ(root, render_surface_layer_list_impl()->at(0)); + EXPECT_EQ(render_surface2, render_surface_layer_list_impl()->at(1)); + EXPECT_EQ(render_surface1, render_surface_layer_list_impl()->at(2)); + EXPECT_TRUE(render_surface_layer_list_impl()->at(0)->render_surface()); + EXPECT_TRUE(render_surface_layer_list_impl()->at(1)->render_surface()); + EXPECT_TRUE(render_surface_layer_list_impl()->at(2)->render_surface()); } TEST_F(LayerTreeHostCommonTest, FixedPositionWithInterveningRenderSurface) { @@ -7742,13 +6525,13 @@ TEST_F(LayerTreeHostCommonTest, FixedPositionWithInterveningRenderSurface) { // + fixed // + child // - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> render_surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> fixed = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(render_surface); render_surface->AddChild(fixed); @@ -7773,8 +6556,7 @@ TEST_F(LayerTreeHostCommonTest, FixedPositionWithInterveningRenderSurface) { gfx::PointF(1.f, 2.f), gfx::Size(50, 50), true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); @@ -7808,7 +6590,9 @@ TEST_F(LayerTreeHostCommonTest, ScrollCompensationWithRounding) { // FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1); scoped_ptr<LayerImpl> container = @@ -7952,7 +6736,9 @@ TEST_F(LayerTreeHostCommonTest, // FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); host_impl.CreatePendingTree(); scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1); scoped_ptr<LayerImpl> container = @@ -8046,7 +6832,9 @@ class AnimationScaleFactorTrackingLayerImpl : public LayerImpl { TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); gfx::Transform identity_matrix; scoped_ptr<AnimationScaleFactorTrackingLayerImpl> grand_parent = AnimationScaleFactorTrackingLayerImpl::Create(host_impl.active_tree(), 1); @@ -8178,6 +6966,7 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { scale_matrix.Scale(1.f, 2.f); grand_parent->SetTransform(scale_matrix); parent_raw->SetTransform(scale_matrix); + grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true; AddAnimatedTransformToLayer(parent_raw, 1.0, TransformOperations(), scale); ExecuteCalculateDrawProperties(grand_parent.get()); @@ -8196,6 +6985,7 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { gfx::Transform perspective_matrix; perspective_matrix.ApplyPerspectiveDepth(2.f); child_raw->SetTransform(perspective_matrix); + grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(grand_parent.get()); // |child| has a transform that's neither a translation nor a scale. @@ -8208,6 +6998,7 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { 0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale); parent_raw->SetTransform(perspective_matrix); + grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(grand_parent.get()); // |parent| and |child| have transforms that are neither translations nor @@ -8223,6 +7014,7 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { parent_raw->SetTransform(identity_matrix); child_raw->SetTransform(identity_matrix); grand_parent->SetTransform(perspective_matrix); + grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(grand_parent.get()); @@ -8242,10 +7034,9 @@ static int membership_id(LayerImpl* layer) { static void GatherDrawnLayers(LayerImplList* rsll, std::set<LayerImpl*>* drawn_layers) { - for (LayerIterator<LayerImpl> it = LayerIterator<LayerImpl>::Begin(rsll), - end = LayerIterator<LayerImpl>::End(rsll); - it != end; - ++it) { + for (LayerIterator it = LayerIterator::Begin(rsll), + end = LayerIterator::End(rsll); + it != end; ++it) { LayerImpl* layer = *it; if (it.represents_itself()) drawn_layers->insert(layer); @@ -8263,7 +7054,9 @@ static void GatherDrawnLayers(LayerImplList* rsll, TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); gfx::Transform identity_matrix; scoped_ptr<LayerImpl> grand_parent = @@ -8506,7 +7299,11 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + LayerTreeSettings settings; + settings.layer_transforms_should_scale_layer_contents = true; + FakeLayerTreeHostImpl host_impl(settings, &proxy, &shared_bitmap_manager, + &task_graph_runner); scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1); LayerImpl* root_layer = root.get(); @@ -8553,16 +7350,10 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { ExecuteCalculateDrawProperties(root_layer); - EXPECT_FLOAT_EQ(1.f, root_layer->draw_properties().ideal_contents_scale); - EXPECT_FLOAT_EQ(3.f, child1_layer->draw_properties().ideal_contents_scale); - EXPECT_FLOAT_EQ( - 3.f, child1_layer->mask_layer()->draw_properties().ideal_contents_scale); - EXPECT_FLOAT_EQ(3.f, - child1_layer->replica_layer() - ->mask_layer() - ->draw_properties() - .ideal_contents_scale); - EXPECT_FLOAT_EQ(5.f, child2_layer->draw_properties().ideal_contents_scale); + EXPECT_FLOAT_EQ(1.f, root_layer->GetIdealContentsScale()); + EXPECT_FLOAT_EQ(3.f, child1_layer->GetIdealContentsScale()); + EXPECT_FLOAT_EQ(3.f, child1_layer->mask_layer()->GetIdealContentsScale()); + EXPECT_FLOAT_EQ(5.f, child2_layer->GetIdealContentsScale()); EXPECT_FLOAT_EQ( 0.f, root_layer->draw_properties().maximum_animation_contents_scale); @@ -8580,28 +7371,6 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { EXPECT_FLOAT_EQ( 8.f, child2_layer->draw_properties().maximum_animation_contents_scale); - EXPECT_FLOAT_EQ(1.f, root_layer->draw_properties().page_scale_factor); - EXPECT_FLOAT_EQ(1.f, child1_layer->draw_properties().page_scale_factor); - EXPECT_FLOAT_EQ( - 1.f, child1_layer->mask_layer()->draw_properties().page_scale_factor); - EXPECT_FLOAT_EQ(1.f, - child1_layer->replica_layer() - ->mask_layer() - ->draw_properties() - .page_scale_factor); - EXPECT_FLOAT_EQ(1.f, child2_layer->draw_properties().page_scale_factor); - - EXPECT_FLOAT_EQ(1.f, root_layer->draw_properties().device_scale_factor); - EXPECT_FLOAT_EQ(1.f, child1_layer->draw_properties().device_scale_factor); - EXPECT_FLOAT_EQ( - 1.f, child1_layer->mask_layer()->draw_properties().device_scale_factor); - EXPECT_FLOAT_EQ(1.f, - child1_layer->replica_layer() - ->mask_layer() - ->draw_properties() - .device_scale_factor); - EXPECT_FLOAT_EQ(1.f, child2_layer->draw_properties().device_scale_factor); - // Changing page-scale would affect ideal_contents_scale and // maximum_animation_contents_scale. @@ -8616,19 +7385,16 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { inputs.page_scale_factor = page_scale_factor; inputs.can_adjust_raster_scales = true; - inputs.page_scale_application_layer = root_layer; + inputs.page_scale_layer = root_layer; LayerTreeHostCommon::CalculateDrawProperties(&inputs); - EXPECT_FLOAT_EQ(1.f, root_layer->draw_properties().ideal_contents_scale); - EXPECT_FLOAT_EQ(9.f, child1_layer->draw_properties().ideal_contents_scale); + EXPECT_FLOAT_EQ(3.f, root_layer->GetIdealContentsScale()); + EXPECT_FLOAT_EQ(9.f, child1_layer->GetIdealContentsScale()); + EXPECT_FLOAT_EQ(9.f, child1_layer->mask_layer()->GetIdealContentsScale()); EXPECT_FLOAT_EQ( - 9.f, child1_layer->mask_layer()->draw_properties().ideal_contents_scale); - EXPECT_FLOAT_EQ(9.f, - child1_layer->replica_layer() - ->mask_layer() - ->draw_properties() - .ideal_contents_scale); - EXPECT_FLOAT_EQ(15.f, child2_layer->draw_properties().ideal_contents_scale); + 9.f, + child1_layer->replica_layer()->mask_layer()->GetIdealContentsScale()); + EXPECT_FLOAT_EQ(15.f, child2_layer->GetIdealContentsScale()); EXPECT_FLOAT_EQ( 0.f, root_layer->draw_properties().maximum_animation_contents_scale); @@ -8646,28 +7412,6 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { EXPECT_FLOAT_EQ( 24.f, child2_layer->draw_properties().maximum_animation_contents_scale); - EXPECT_FLOAT_EQ(1.f, root_layer->draw_properties().page_scale_factor); - EXPECT_FLOAT_EQ(3.f, child1_layer->draw_properties().page_scale_factor); - EXPECT_FLOAT_EQ( - 3.f, child1_layer->mask_layer()->draw_properties().page_scale_factor); - EXPECT_FLOAT_EQ(3.f, - child1_layer->replica_layer() - ->mask_layer() - ->draw_properties() - .page_scale_factor); - EXPECT_FLOAT_EQ(3.f, child2_layer->draw_properties().page_scale_factor); - - EXPECT_FLOAT_EQ(1.f, root_layer->draw_properties().device_scale_factor); - EXPECT_FLOAT_EQ(1.f, child1_layer->draw_properties().device_scale_factor); - EXPECT_FLOAT_EQ( - 1.f, child1_layer->mask_layer()->draw_properties().device_scale_factor); - EXPECT_FLOAT_EQ(1.f, - child1_layer->replica_layer() - ->mask_layer() - ->draw_properties() - .device_scale_factor); - EXPECT_FLOAT_EQ(1.f, child2_layer->draw_properties().device_scale_factor); - // Changing device-scale would affect ideal_contents_scale and // maximum_animation_contents_scale. @@ -8676,16 +7420,13 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawProperties(&inputs); - EXPECT_FLOAT_EQ(4.f, root_layer->draw_properties().ideal_contents_scale); - EXPECT_FLOAT_EQ(36.f, child1_layer->draw_properties().ideal_contents_scale); + EXPECT_FLOAT_EQ(12.f, root_layer->GetIdealContentsScale()); + EXPECT_FLOAT_EQ(36.f, child1_layer->GetIdealContentsScale()); + EXPECT_FLOAT_EQ(36.f, child1_layer->mask_layer()->GetIdealContentsScale()); EXPECT_FLOAT_EQ( - 36.f, child1_layer->mask_layer()->draw_properties().ideal_contents_scale); - EXPECT_FLOAT_EQ(36.f, - child1_layer->replica_layer() - ->mask_layer() - ->draw_properties() - .ideal_contents_scale); - EXPECT_FLOAT_EQ(60.f, child2_layer->draw_properties().ideal_contents_scale); + 36.f, + child1_layer->replica_layer()->mask_layer()->GetIdealContentsScale()); + EXPECT_FLOAT_EQ(60.f, child2_layer->GetIdealContentsScale()); EXPECT_FLOAT_EQ( 0.f, root_layer->draw_properties().maximum_animation_contents_scale); @@ -8702,32 +7443,10 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { .maximum_animation_contents_scale); EXPECT_FLOAT_EQ( 96.f, child2_layer->draw_properties().maximum_animation_contents_scale); - - EXPECT_FLOAT_EQ(1.f, root_layer->draw_properties().page_scale_factor); - EXPECT_FLOAT_EQ(3.f, child1_layer->draw_properties().page_scale_factor); - EXPECT_FLOAT_EQ( - 3.f, child1_layer->mask_layer()->draw_properties().page_scale_factor); - EXPECT_FLOAT_EQ(3.f, - child1_layer->replica_layer() - ->mask_layer() - ->draw_properties() - .page_scale_factor); - EXPECT_FLOAT_EQ(3.f, child2_layer->draw_properties().page_scale_factor); - - EXPECT_FLOAT_EQ(4.f, root_layer->draw_properties().device_scale_factor); - EXPECT_FLOAT_EQ(4.f, child1_layer->draw_properties().device_scale_factor); - EXPECT_FLOAT_EQ( - 4.f, child1_layer->mask_layer()->draw_properties().device_scale_factor); - EXPECT_FLOAT_EQ(4.f, - child1_layer->replica_layer() - ->mask_layer() - ->draw_properties() - .device_scale_factor); - EXPECT_FLOAT_EQ(4.f, child2_layer->draw_properties().device_scale_factor); } TEST_F(LayerTreeHostCommonTest, VisibleContentRectInChildRenderSurface) { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), gfx::Transform(), gfx::Point3F(), @@ -8737,7 +7456,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInChildRenderSurface) { false); root->SetIsDrawable(true); - scoped_refptr<Layer> clip = Layer::Create(); + scoped_refptr<Layer> clip = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(clip.get(), gfx::Transform(), gfx::Point3F(), @@ -8747,7 +7466,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInChildRenderSurface) { false); clip->SetMasksToBounds(true); - scoped_refptr<Layer> content = Layer::Create(); + scoped_refptr<Layer> content = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(content.get(), gfx::Transform(), gfx::Point3F(), @@ -8761,32 +7480,32 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInChildRenderSurface) { root->AddChild(clip); clip->AddChild(content); - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Size device_viewport_size(768, 582); RenderSurfaceLayerList render_surface_layer_list; LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - host->root_layer(), device_viewport_size, &render_surface_layer_list); + host()->root_layer(), device_viewport_size, &render_surface_layer_list); inputs.device_scale_factor = 2.f; inputs.page_scale_factor = 1.f; - inputs.page_scale_application_layer = NULL; + inputs.page_scale_layer = NULL; LayerTreeHostCommon::CalculateDrawProperties(&inputs); // Layers in the root render surface have their visible content rect clipped // by the viewport. - EXPECT_EQ(gfx::Rect(768 / 2, 582 / 2), root->visible_content_rect()); + EXPECT_EQ(gfx::Rect(768 / 2, 582 / 2), root->visible_layer_rect()); // Layers drawing to a child render surface should still have their visible // content rect clipped by the viewport. - EXPECT_EQ(gfx::Rect(768 / 2, 582 / 2), content->visible_content_rect()); + EXPECT_EQ(gfx::Rect(768 / 2, 582 / 2), content->visible_layer_rect()); } TEST_F(LayerTreeHostCommonTest, BoundsDeltaAffectVisibleContentRect) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); // Set two layers: the root layer clips it's child, // the child draws its content. @@ -8800,6 +7519,7 @@ TEST_F(LayerTreeHostCommonTest, BoundsDeltaAffectVisibleContentRect) { gfx::Size device_viewport_size = gfx::Size(300, 600); gfx::Transform identity_matrix; + host_impl.SetViewportSize(device_viewport_size); host_impl.active_tree()->SetRootLayer( LayerImpl::Create(host_impl.active_tree(), 1)); @@ -8812,8 +7532,6 @@ TEST_F(LayerTreeHostCommonTest, BoundsDeltaAffectVisibleContentRect) { false, false, true); - - root->SetContentBounds(root_size); root->SetMasksToBounds(true); root->AddChild(LayerImpl::Create(host_impl.active_tree(), 2)); @@ -8827,8 +7545,6 @@ TEST_F(LayerTreeHostCommonTest, BoundsDeltaAffectVisibleContentRect) { false, false, false); - - sublayer->SetContentBounds(sublayer_size); sublayer->SetDrawsContent(true); LayerImplList layer_impl_list; @@ -8837,7 +7553,7 @@ TEST_F(LayerTreeHostCommonTest, BoundsDeltaAffectVisibleContentRect) { LayerTreeHostCommon::CalculateDrawProperties(&inputs); - EXPECT_EQ(gfx::Rect(root_size), sublayer->visible_content_rect()); + EXPECT_EQ(gfx::Rect(root_size), sublayer->visible_layer_rect()); root->SetBoundsDelta(gfx::Vector2dF(0.0, 50.0)); @@ -8845,19 +7561,80 @@ TEST_F(LayerTreeHostCommonTest, BoundsDeltaAffectVisibleContentRect) { gfx::Rect affected_by_delta(0, 0, root_size.width(), root_size.height() + 50); - EXPECT_EQ(affected_by_delta, sublayer->visible_content_rect()); + EXPECT_EQ(affected_by_delta, sublayer->visible_layer_rect()); +} + +TEST_F(LayerTreeHostCommonTest, NodesAffectedByBoundsDeltaGetUpdated) { + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> inner_viewport_container_layer = + Layer::Create(layer_settings()); + scoped_refptr<Layer> inner_viewport_scroll_layer = + Layer::Create(layer_settings()); + scoped_refptr<Layer> outer_viewport_container_layer = + Layer::Create(layer_settings()); + scoped_refptr<Layer> outer_viewport_scroll_layer = + Layer::Create(layer_settings()); + + root->AddChild(inner_viewport_container_layer); + inner_viewport_container_layer->AddChild(inner_viewport_scroll_layer); + inner_viewport_scroll_layer->AddChild(outer_viewport_container_layer); + outer_viewport_container_layer->AddChild(outer_viewport_scroll_layer); + + inner_viewport_scroll_layer->SetScrollClipLayerId( + inner_viewport_container_layer->id()); + outer_viewport_scroll_layer->SetScrollClipLayerId( + outer_viewport_container_layer->id()); + + inner_viewport_scroll_layer->SetIsContainerForFixedPositionLayers(true); + outer_viewport_scroll_layer->SetIsContainerForFixedPositionLayers(true); + + host()->SetRootLayer(root); + host()->RegisterViewportLayers(nullptr, root, inner_viewport_scroll_layer, + outer_viewport_scroll_layer); + + scoped_refptr<Layer> fixed_to_inner = Layer::Create(layer_settings()); + scoped_refptr<Layer> fixed_to_outer = Layer::Create(layer_settings()); + + inner_viewport_scroll_layer->AddChild(fixed_to_inner); + outer_viewport_scroll_layer->AddChild(fixed_to_outer); + + LayerPositionConstraint fixed_to_right; + fixed_to_right.set_is_fixed_position(true); + fixed_to_right.set_is_fixed_to_right_edge(true); + + fixed_to_inner->SetPositionConstraint(fixed_to_right); + fixed_to_outer->SetPositionConstraint(fixed_to_right); + + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); + + TransformTree& transform_tree = host()->property_trees()->transform_tree; + EXPECT_TRUE(transform_tree.HasNodesAffectedByInnerViewportBoundsDelta()); + EXPECT_TRUE(transform_tree.HasNodesAffectedByOuterViewportBoundsDelta()); + + LayerPositionConstraint fixed_to_left; + fixed_to_left.set_is_fixed_position(true); + fixed_to_inner->SetPositionConstraint(fixed_to_left); + + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); + EXPECT_FALSE(transform_tree.HasNodesAffectedByInnerViewportBoundsDelta()); + EXPECT_TRUE(transform_tree.HasNodesAffectedByOuterViewportBoundsDelta()); + + fixed_to_outer->SetPositionConstraint(fixed_to_left); + + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); + EXPECT_FALSE(transform_tree.HasNodesAffectedByInnerViewportBoundsDelta()); + EXPECT_FALSE(transform_tree.HasNodesAffectedByOuterViewportBoundsDelta()); } TEST_F(LayerTreeHostCommonTest, VisibleContentRectForAnimatedLayer) { const gfx::Transform identity_matrix; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> animated = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(animated); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), gfx::PointF(), gfx::Size(100, 100), true, false); @@ -8871,7 +7648,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectForAnimatedLayer) { AddOpacityTransitionToController(animated->layer_animation_controller(), 10.0, 0.f, 1.f, false); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_FALSE(animated->visible_rect_from_property_trees().IsEmpty()); } @@ -8879,14 +7656,14 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectForAnimatedLayer) { TEST_F(LayerTreeHostCommonTest, VisibleContentRectForAnimatedLayerWithSingularTransform) { const gfx::Transform identity_matrix; - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> clip = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> clip = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> animated = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> surface = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> descendant_of_animation = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(clip); clip->AddChild(animated); @@ -8896,8 +7673,7 @@ TEST_F(LayerTreeHostCommonTest, clip->SetMasksToBounds(true); surface->SetForceRenderSurface(true); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform uninvertible_matrix; uninvertible_matrix.Scale3d(6.f, 6.f, 0.f); @@ -8922,7 +7698,7 @@ TEST_F(LayerTreeHostCommonTest, AddAnimatedTransformToLayer(animated.get(), 10.0, start_transform_operations, end_transform_operations); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); // The animated layer has a singular transform and maps to a non-empty rect in // clipped target space, so is treated as fully visible. @@ -8939,7 +7715,7 @@ TEST_F(LayerTreeHostCommonTest, SetLayerPropertiesForTesting(animated.get(), zero_matrix, gfx::Point3F(), gfx::PointF(), gfx::Size(120, 120), true, false); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); // The animated layer maps to the empty rect in clipped target space, so is // treated as having an empty visible rect. @@ -8956,9 +7732,9 @@ TEST_F(LayerTreeHostCommonTest, // Verify that having an animated filter (but no current filter, as these // are mutually exclusive) correctly creates a render surface. TEST_F(LayerTreeHostCommonTest, AnimatedFilterCreatesRenderSurface) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); - scoped_refptr<Layer> grandchild = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<Layer> grandchild = Layer::Create(layer_settings()); root->AddChild(child); child->AddChild(grandchild); @@ -8970,8 +7746,7 @@ TEST_F(LayerTreeHostCommonTest, AnimatedFilterCreatesRenderSurface) { SetLayerPropertiesForTesting(grandchild.get(), identity_transform, gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); AddAnimatedFilterToLayer(child.get(), 10.0, 0.1f, 0.2f); @@ -8993,10 +7768,10 @@ TEST_F(LayerTreeHostCommonTest, AnimatedFilterCreatesRenderSurface) { // Ensures that the property tree code accounts for offsets between fixed // position layers and their respective containers. TEST_F(LayerTreeHostCommonTest, PropertyTreesAccountForFixedParentOffset) { - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> grandchild = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(child); child->AddChild(grandchild); @@ -9019,10 +7794,49 @@ TEST_F(LayerTreeHostCommonTest, PropertyTreesAccountForFixedParentOffset) { root->SetIsContainerForFixedPositionLayers(true); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); + + EXPECT_EQ(gfx::Rect(0, 0, 50, 50), + grandchild->visible_rect_from_property_trees()); +} + +// Ensures that the property tree code accounts for offsets between fixed +// position containers and their transform tree parents, when a fixed position +// layer's container is its layer tree parent, but this parent doesn't have its +// own transform tree node. +TEST_F(LayerTreeHostCommonTest, + PropertyTreesAccountForFixedParentOffsetWhenContainerIsParent) { + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + scoped_refptr<LayerWithForcedDrawsContent> grandchild = + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); + + root->AddChild(child); + child->AddChild(grandchild); + + gfx::Transform identity_transform; + SetLayerPropertiesForTesting(root.get(), identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false); + SetLayerPropertiesForTesting(child.get(), identity_transform, gfx::Point3F(), + gfx::PointF(1000, 1000), gfx::Size(50, 50), true, + false); + SetLayerPropertiesForTesting(grandchild.get(), identity_transform, + gfx::Point3F(), gfx::PointF(-1000, -1000), + gfx::Size(50, 50), true, false); + + root->SetMasksToBounds(true); + child->SetIsContainerForFixedPositionLayers(true); + LayerPositionConstraint constraint; + constraint.set_is_fixed_position(true); + grandchild->SetPositionConstraint(constraint); + + root->SetIsContainerForFixedPositionLayers(true); + + host()->SetRootLayer(root); + + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0, 50, 50), grandchild->visible_rect_from_property_trees()); @@ -9038,35 +7852,35 @@ TEST_F(LayerTreeHostCommonTest, CombineClipsUsingContentTarget) { rotate.Rotate(5); gfx::Transform identity; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(2500, 1500), true, false); - scoped_refptr<Layer> frame_clip = Layer::Create(); + scoped_refptr<Layer> frame_clip = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(frame_clip.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(2500, 1500), true, false); frame_clip->SetMasksToBounds(true); - scoped_refptr<Layer> rotated = Layer::Create(); + scoped_refptr<Layer> rotated = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(rotated.get(), rotate, gfx::Point3F(1250, 250, 0), gfx::PointF(), gfx::Size(2500, 500), true, false); - scoped_refptr<Layer> surface = Layer::Create(); + scoped_refptr<Layer> surface = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(surface.get(), rotate, gfx::Point3F(), gfx::PointF(), gfx::Size(2500, 500), true, false); surface->SetOpacity(0.5); scoped_refptr<LayerWithForcedDrawsContent> container = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(container.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(300, 300), true, false); scoped_refptr<LayerWithForcedDrawsContent> box = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(box.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(100, 100), true, false); @@ -9076,8 +7890,7 @@ TEST_F(LayerTreeHostCommonTest, CombineClipsUsingContentTarget) { surface->AddChild(container); surface->AddChild(box); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); } @@ -9087,19 +7900,19 @@ TEST_F(LayerTreeHostCommonTest, OnlyApplyFixedPositioningOnce) { gfx::Transform translate_z; translate_z.Translate3d(0, 0, 10); - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(800, 800), true, false); root->SetIsContainerForFixedPositionLayers(true); - scoped_refptr<Layer> frame_clip = Layer::Create(); + scoped_refptr<Layer> frame_clip = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(frame_clip.get(), translate_z, gfx::Point3F(), gfx::PointF(500, 100), gfx::Size(100, 100), true, false); frame_clip->SetMasksToBounds(true); scoped_refptr<LayerWithForcedDrawsContent> fixed = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(fixed.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(1000, 1000), true, false); @@ -9111,10 +7924,9 @@ TEST_F(LayerTreeHostCommonTest, OnlyApplyFixedPositioningOnce) { root->AddChild(frame_clip); frame_clip->AddChild(fixed); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); gfx::Rect expected(0, 0, 100, 100); EXPECT_EQ(expected, fixed->visible_rect_from_property_trees()); @@ -9126,19 +7938,19 @@ TEST_F(LayerTreeHostCommonTest, gfx::Transform translate_z; translate_z.Translate3d(0, 0, 10); - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(800, 800), true, false); root->SetIsContainerForFixedPositionLayers(true); - scoped_refptr<Layer> frame_clip = Layer::Create(); + scoped_refptr<Layer> frame_clip = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(frame_clip.get(), translate_z, gfx::Point3F(), gfx::PointF(500, 100), gfx::Size(100, 100), true, false); frame_clip->SetMasksToBounds(true); scoped_refptr<LayerWithForcedDrawsContent> scroller = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(scroller.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(1000, 1000), true, false); @@ -9148,7 +7960,7 @@ TEST_F(LayerTreeHostCommonTest, scroller->SetScrollClipLayerId(frame_clip->id()); scoped_refptr<LayerWithForcedDrawsContent> fixed = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(fixed.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), true, false); @@ -9157,7 +7969,7 @@ TEST_F(LayerTreeHostCommonTest, fixed->SetPositionConstraint(constraint); scoped_refptr<LayerWithForcedDrawsContent> fixed_child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(fixed_child.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10), true, false); @@ -9168,10 +7980,9 @@ TEST_F(LayerTreeHostCommonTest, scroller->AddChild(fixed); fixed->AddChild(fixed_child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); gfx::Rect expected(0, 0, 50, 50); EXPECT_EQ(expected, fixed->visible_rect_from_property_trees()); @@ -9183,19 +7994,19 @@ TEST_F(LayerTreeHostCommonTest, TEST_F(LayerTreeHostCommonTest, FixedClipsShouldBeAssociatedWithTheRightNode) { gfx::Transform identity; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(800, 800), true, false); root->SetIsContainerForFixedPositionLayers(true); - scoped_refptr<Layer> frame_clip = Layer::Create(); + scoped_refptr<Layer> frame_clip = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(frame_clip.get(), identity, gfx::Point3F(), gfx::PointF(500, 100), gfx::Size(100, 100), true, false); frame_clip->SetMasksToBounds(true); scoped_refptr<LayerWithForcedDrawsContent> scroller = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(scroller.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(1000, 1000), true, false); @@ -9204,7 +8015,7 @@ TEST_F(LayerTreeHostCommonTest, FixedClipsShouldBeAssociatedWithTheRightNode) { scroller->SetScrollClipLayerId(frame_clip->id()); scoped_refptr<LayerWithForcedDrawsContent> fixed = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(fixed.get(), identity, gfx::Point3F(), gfx::PointF(100, 100), gfx::Size(50, 50), true, false); @@ -9219,10 +8030,9 @@ TEST_F(LayerTreeHostCommonTest, FixedClipsShouldBeAssociatedWithTheRightNode) { frame_clip->AddChild(scroller); scroller->AddChild(fixed); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); gfx::Rect expected(0, 0, 50, 50); EXPECT_EQ(expected, fixed->visible_rect_from_property_trees()); @@ -9236,31 +8046,30 @@ TEST_F(LayerTreeHostCommonTest, ChangingAxisAlignmentTriggersRebuild) { translate.Translate(10, 10); rotate.Rotate(45); - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(800, 800), true, false); root->SetIsContainerForFixedPositionLayers(true); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); + EXPECT_FALSE(host()->property_trees()->needs_rebuild); root->SetTransform(translate); - EXPECT_FALSE(host->property_trees()->needs_rebuild); + EXPECT_FALSE(host()->property_trees()->needs_rebuild); root->SetTransform(rotate); - EXPECT_TRUE(host->property_trees()->needs_rebuild); + EXPECT_TRUE(host()->property_trees()->needs_rebuild); } TEST_F(LayerTreeHostCommonTest, ChangeTransformOrigin) { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_matrix; gfx::Transform scale_matrix; @@ -9270,29 +8079,28 @@ TEST_F(LayerTreeHostCommonTest, ChangeTransformOrigin) { SetLayerPropertiesForTesting(child.get(), scale_matrix, gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10), true, false); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(10, 10), child->visible_rect_from_property_trees()); child->SetTransformOrigin(gfx::Point3F(10.f, 10.f, 10.f)); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(5, 5, 5, 5), child->visible_rect_from_property_trees()); } TEST_F(LayerTreeHostCommonTest, UpdateScrollChildPosition) { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> scroll_parent = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> scroll_child = - make_scoped_refptr(new LayerWithForcedDrawsContent); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); root->AddChild(scroll_child); root->AddChild(scroll_parent); scroll_child->SetScrollParent(scroll_parent.get()); scroll_parent->SetScrollClipLayerId(root->id()); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); gfx::Transform identity_transform; gfx::Transform scale; @@ -9305,13 +8113,13 @@ TEST_F(LayerTreeHostCommonTest, UpdateScrollChildPosition) { gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30), true, false); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(25, 25), scroll_child->visible_rect_from_property_trees()); scroll_child->SetPosition(gfx::PointF(0, -10.f)); scroll_parent->SetScrollOffset(gfx::ScrollOffset(0.f, 10.f)); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 5, 25, 25), scroll_child->visible_rect_from_property_trees()); } @@ -9322,13 +8130,13 @@ static void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { TEST_F(LayerTreeHostCommonTest, SkippingSubtreeMain) { gfx::Transform identity; FakeContentLayerClient client; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> grandchild = - make_scoped_refptr(new LayerWithForcedDrawsContent()); - scoped_refptr<FakeContentLayer> greatgrandchild( - FakeContentLayer::Create(&client)); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); + scoped_refptr<FakePictureLayer> greatgrandchild( + FakePictureLayer::Create(layer_settings(), &client)); SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(100, 100), true, false); SetLayerPropertiesForTesting(child.get(), identity, gfx::Point3F(), @@ -9342,11 +8150,10 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeMain) { child->AddChild(grandchild); grandchild->AddChild(greatgrandchild); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); // Check the non-skipped case. - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees()); // Now we will reset the visible rect from property trees for the grandchild, @@ -9358,41 +8165,43 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeMain) { singular.matrix().set(0, 0, 0); child->SetTransform(singular); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees()); child->SetTransform(identity); child->SetHideLayerAndSubtree(true); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees()); child->SetHideLayerAndSubtree(false); child->SetOpacity(0.f); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees()); // Now, even though child has zero opacity, we will configure |grandchild| and // |greatgrandchild| in several ways that should force the subtree to be // processed anyhow. grandchild->SetTouchEventHandlerRegion(Region(gfx::Rect(0, 0, 10, 10))); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees()); grandchild->set_visible_rect_from_property_trees(gfx::Rect()); grandchild->SetTouchEventHandlerRegion(Region()); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees()); grandchild->set_visible_rect_from_property_trees(gfx::Rect()); greatgrandchild->RequestCopyOfOutput( CopyOutputRequest::CreateBitmapRequest(base::Bind(&CopyOutputCallback))); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees()); } TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) { FakeImplProxy proxy; TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, + &task_graph_runner); gfx::Transform identity; scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1); @@ -9400,8 +8209,8 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) { scoped_ptr<LayerImpl> grandchild = LayerImpl::Create(host_impl.active_tree(), 3); - scoped_ptr<FakeContentLayerImpl> greatgrandchild( - FakeContentLayerImpl::Create(host_impl.active_tree(), 4)); + scoped_ptr<FakePictureLayerImpl> greatgrandchild( + FakePictureLayerImpl::Create(host_impl.active_tree(), 4)); child->SetDrawsContent(true); grandchild->SetDrawsContent(true); @@ -9429,7 +8238,7 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) { root->AddChild(child.Pass()); // Check the non-skipped case. - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_rect_from_property_trees()); @@ -9442,19 +8251,19 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) { singular.matrix().set(0, 0, 0); child_ptr->SetTransform(singular); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_rect_from_property_trees()); child_ptr->SetTransform(identity); child_ptr->SetHideLayerAndSubtree(true); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_rect_from_property_trees()); child_ptr->SetHideLayerAndSubtree(false); child_ptr->SetOpacity(0.f); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_rect_from_property_trees()); @@ -9462,12 +8271,12 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) { // |greatgrandchild| in several ways that should force the subtree to be // processed anyhow. grandchild_ptr->SetTouchEventHandlerRegion(Region(gfx::Rect(0, 0, 10, 10))); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_rect_from_property_trees()); grandchild_ptr->set_visible_rect_from_property_trees(gfx::Rect()); grandchild_ptr->SetTouchEventHandlerRegion(Region()); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_rect_from_property_trees()); grandchild_ptr->set_visible_rect_from_property_trees(gfx::Rect()); @@ -9476,7 +8285,7 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) { requests.push_back(CopyOutputRequest::CreateEmptyRequest()); greatgrandchild_ptr->PassCopyRequests(&requests); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_rect_from_property_trees()); } @@ -9484,29 +8293,28 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) { TEST_F(LayerTreeHostCommonTest, SkippingLayer) { gfx::Transform identity; FakeContentLayerClient client; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<LayerWithForcedDrawsContent> child = - make_scoped_refptr(new LayerWithForcedDrawsContent()); + make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(100, 100), true, false); SetLayerPropertiesForTesting(child.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10), true, false); root->AddChild(child); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(10, 10), child->visible_rect_from_property_trees()); child->set_visible_rect_from_property_trees(gfx::Rect()); child->SetHideLayerAndSubtree(true); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), child->visible_rect_from_property_trees()); child->SetHideLayerAndSubtree(false); child->SetBounds(gfx::Size()); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), child->visible_rect_from_property_trees()); child->SetBounds(gfx::Size(10, 10)); @@ -9514,22 +8322,22 @@ TEST_F(LayerTreeHostCommonTest, SkippingLayer) { child->SetDoubleSided(false); rotate.RotateAboutXAxis(180.f); child->SetTransform(rotate); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), child->visible_rect_from_property_trees()); child->SetDoubleSided(true); child->SetTransform(identity); child->SetOpacity(0.f); - ExecuteCalculateDrawProperties(root.get()); + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); EXPECT_EQ(gfx::Rect(0, 0), child->visible_rect_from_property_trees()); } TEST_F(LayerTreeHostCommonTest, LayerTreeRebuildTest) { // Ensure that the treewalk in LayerTreeHostCommom:: // PreCalculateMetaInformation happens when its required. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> parent = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> parent = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); root->AddChild(parent); parent->AddChild(child); @@ -9545,11 +8353,10 @@ TEST_F(LayerTreeHostCommonTest, LayerTreeRebuildTest) { SetLayerPropertiesForTesting(child.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(100, 100), true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); ExecuteCalculateDrawProperties(root.get()); - EXPECT_EQ(parent->draw_properties().num_unclipped_descendants, 1); + EXPECT_EQ(parent->draw_properties().num_unclipped_descendants, 1u); // Ensure the dynamic update to input handlers happens. child->SetHaveWheelEventHandlers(true); @@ -9572,8 +8379,8 @@ TEST_F(LayerTreeHostCommonTest, LayerTreeRebuildTest) { TEST_F(LayerTreeHostCommonTest, InputHandlersRecursiveUpdateTest) { // Ensure that the treewalk in LayertreeHostCommon:: // PreCalculateMetaInformation updates input handlers correctly. - scoped_refptr<Layer> root = Layer::Create(); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); root->AddChild(child); @@ -9586,8 +8393,7 @@ TEST_F(LayerTreeHostCommonTest, InputHandlersRecursiveUpdateTest) { SetLayerPropertiesForTesting(child.get(), identity, gfx::Point3F(), gfx::PointF(), gfx::Size(100, 100), true, false); - scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); - host->SetRootLayer(root); + host()->SetRootLayer(root); EXPECT_EQ(root->num_layer_or_descendants_with_input_handler(), 0); ExecuteCalculateDrawProperties(root.get()); @@ -9596,5 +8402,69 @@ TEST_F(LayerTreeHostCommonTest, InputHandlersRecursiveUpdateTest) { EXPECT_EQ(root->num_layer_or_descendants_with_input_handler(), 0); } +TEST_F(LayerTreeHostCommonTest, ResetPropertyTreeIndices) { + gfx::Transform identity; + gfx::Transform translate_z; + translate_z.Translate3d(0, 0, 10); + + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(800, 800), true, false); + + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + SetLayerPropertiesForTesting(child.get(), translate_z, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), true, false); + + root->AddChild(child); + + host()->SetRootLayer(root); + + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); + EXPECT_NE(-1, child->transform_tree_index()); + + child->RemoveFromParent(); + + ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get()); + EXPECT_EQ(-1, child->transform_tree_index()); +} + +TEST_F(LayerTreeHostCommonTest, ResetLayerDrawPropertiestest) { + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); + + root->AddChild(child); + gfx::Transform identity; + + SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), true, false); + SetLayerPropertiesForTesting(child.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), true, false); + + host()->SetRootLayer(root); + + EXPECT_FALSE(root->layer_or_descendant_is_drawn()); + EXPECT_FALSE(root->visited()); + EXPECT_FALSE(root->sorted_for_recursion()); + EXPECT_FALSE(child->layer_or_descendant_is_drawn()); + EXPECT_FALSE(child->visited()); + EXPECT_FALSE(child->sorted_for_recursion()); + + root->set_layer_or_descendant_is_drawn(true); + root->set_visited(true); + root->set_sorted_for_recursion(true); + child->set_layer_or_descendant_is_drawn(true); + child->set_visited(true); + child->set_sorted_for_recursion(true); + + LayerTreeHostCommon::PreCalculateMetaInformationForTesting(root.get()); + + EXPECT_FALSE(root->layer_or_descendant_is_drawn()); + EXPECT_FALSE(root->visited()); + EXPECT_FALSE(root->sorted_for_recursion()); + EXPECT_FALSE(child->layer_or_descendant_is_drawn()); + EXPECT_FALSE(child->visited()); + EXPECT_FALSE(child->sorted_for_recursion()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index 9e1474586cb..f616d517a3f 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -14,15 +14,16 @@ #include "base/containers/small_map.h" #include "base/json/json_writer.h" #include "base/metrics/histogram.h" +#include "base/numerics/safe_conversions.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/animation/animation_host.h" #include "cc/animation/animation_id_provider.h" #include "cc/animation/scroll_offset_animation_curve.h" #include "cc/animation/scrollbar_animation_controller.h" #include "cc/animation/timing_function.h" #include "cc/base/math_util.h" -#include "cc/base/util.h" #include "cc/debug/benchmark_instrumentation.h" #include "cc/debug/debug_rect_history.h" #include "cc/debug/devtools_instrumentation.h" @@ -60,7 +61,6 @@ #include "cc/raster/tile_task_worker_pool.h" #include "cc/raster/zero_copy_tile_task_worker_pool.h" #include "cc/resources/memory_history.h" -#include "cc/resources/prioritized_resource_manager.h" #include "cc/resources/resource_pool.h" #include "cc/resources/ui_resource_bitmap.h" #include "cc/scheduler/delay_based_time_source.h" @@ -76,7 +76,6 @@ #include "cc/trees/tree_synchronizer.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/gles2_interface.h" -#include "ui/gfx/frame_time.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/size_conversions.h" @@ -158,6 +157,16 @@ size_t GetMaxStagingResourceCount() { return 32; } +size_t GetDefaultMemoryAllocationLimit() { + // TODO(ccameron): (http://crbug.com/137094) This 64MB default is a straggler + // from the old texture manager and is just to give us a default memory + // allocation before we get a callback from the GPU memory manager. We + // should probaby either: + // - wait for the callback before rendering anything instead + // - push this into the GPU memory manager somehow. + return 64 * 1024 * 1024; +} + } // namespace LayerTreeHostImpl::FrameData::FrameData() : has_no_damage(false) { @@ -190,6 +199,7 @@ LayerTreeHostImpl::LayerTreeHostImpl( int id) : client_(client), proxy_(proxy), + current_begin_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), content_is_suitable_for_gpu_rasterization_(true), has_gpu_rasterization_trigger_(false), use_gpu_rasterization_(false), @@ -207,23 +217,27 @@ LayerTreeHostImpl::LayerTreeHostImpl( settings_(settings), visible_(true), cached_managed_memory_policy_( - PrioritizedResourceManager::DefaultMemoryAllocationLimit(), + GetDefaultMemoryAllocationLimit(), gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, ManagedMemoryPolicy::kDefaultNumResourcesLimit), + // Must be initialized after settings_ and proxy_. + tile_manager_( + TileManager::Create(this, + GetTaskRunner(), + IsSynchronousSingleThreaded() + ? std::numeric_limits<size_t>::max() + : settings.scheduled_raster_task_limit)), pinch_gesture_active_(false), pinch_gesture_end_should_clear_scrolling_layer_(false), fps_counter_(FrameRateCounter::Create(proxy_->HasImplThread())), paint_time_counter_(PaintTimeCounter::Create()), memory_history_(MemoryHistory::Create()), debug_rect_history_(DebugRectHistory::Create()), - texture_mailbox_deleter_(new TextureMailboxDeleter( - proxy_->HasImplThread() ? proxy_->ImplThreadTaskRunner() - : proxy_->MainThreadTaskRunner())), + texture_mailbox_deleter_(new TextureMailboxDeleter(GetTaskRunner())), max_memory_needed_bytes_(0), device_scale_factor_(1.f), resourceless_software_draw_(false), - begin_impl_frame_interval_(BeginFrameArgs::DefaultInterval()), - animation_registrar_(AnimationRegistrar::Create()), + animation_registrar_(), rendering_stats_instrumentation_(rendering_stats_instrumentation), micro_benchmark_controller_(this), shared_bitmap_manager_(shared_bitmap_manager), @@ -232,11 +246,24 @@ LayerTreeHostImpl::LayerTreeHostImpl( id_(id), requires_high_res_to_draw_(false), is_likely_to_require_a_draw_(false), - frame_timing_tracker_(FrameTimingTracker::Create()) { + frame_timing_tracker_(FrameTimingTracker::Create(this)) { + if (settings.use_compositor_animation_timelines) { + if (settings.accelerated_animation_enabled) { + animation_host_ = AnimationHost::Create(ThreadInstance::IMPL); + animation_host_->SetMutatorHostClient(this); + animation_host_->SetSupportsScrollAnimations( + proxy_->SupportsImplScrolling()); + } + } else { + animation_registrar_ = AnimationRegistrar::Create(); + animation_registrar_->set_supports_scroll_animations( + proxy_->SupportsImplScrolling()); + } + DCHECK(proxy_->IsImplThread()); + DCHECK_IMPLIES(settings.use_one_copy, !settings.use_zero_copy); + DCHECK_IMPLIES(settings.use_zero_copy, !settings.use_one_copy); DidVisibilityChange(this, visible_); - animation_registrar_->set_supports_scroll_animations( - proxy_->SupportsImplScrolling()); SetDebugState(settings.initial_debug_state); @@ -280,29 +307,36 @@ LayerTreeHostImpl::~LayerTreeHostImpl() { recycle_tree_ = nullptr; pending_tree_ = nullptr; active_tree_ = nullptr; - DestroyTileManager(); + + if (animation_host_) { + animation_host_->ClearTimelines(); + animation_host_->SetMutatorHostClient(nullptr); + } + + CleanUpTileManager(); } void LayerTreeHostImpl::BeginMainFrameAborted(CommitEarlyOutReason reason) { // If the begin frame data was handled, then scroll and scale set was applied // by the main thread, so the active tree needs to be updated as if these sent // values were applied and committed. - if (CommitEarlyOutHandledCommit(reason)) { + if (CommitEarlyOutHandledCommit(reason)) active_tree_->ApplySentScrollAndScaleDeltasFromAbortedCommit(); - active_tree_->ResetContentsTexturesPurged(); - } } void LayerTreeHostImpl::BeginCommit() { TRACE_EVENT0("cc", "LayerTreeHostImpl::BeginCommit"); // Ensure all textures are returned so partial texture updates can happen - // during the commit. Impl-side-painting doesn't upload during commits, so - // is unaffected. - if (!settings_.impl_side_painting && output_surface_) + // during the commit. + // TODO(ericrk): We should not need to ForceReclaimResources when using + // Impl-side-painting as it doesn't upload during commits. However, + // Display::Draw currently relies on resource being reclaimed to block drawing + // between BeginCommit / Swap. See crbug.com/489515. + if (output_surface_) output_surface_->ForceReclaimResources(); - if (settings_.impl_side_painting && !proxy_->CommitToActiveTree()) + if (!proxy_->CommitToActiveTree()) CreatePendingTree(); } @@ -314,31 +348,25 @@ void LayerTreeHostImpl::CommitComplete() { UpdateTreeResourcesForGpuRasterizationIfNeeded(); sync_tree()->set_needs_update_draw_properties(); - if (settings_.impl_side_painting) { - // Impl-side painting needs an update immediately post-commit to have the - // opportunity to create tilings. Other paths can call UpdateDrawProperties - // more lazily when needed prior to drawing. Because invalidations may - // be coming from the main thread, it's safe to do an update for lcd text - // at this point and see if lcd text needs to be disabled on any layers. - bool update_lcd_text = true; - sync_tree()->UpdateDrawProperties(update_lcd_text); - // Start working on newly created tiles immediately if needed. - if (tile_manager_ && tile_priorities_dirty_) { - PrepareTiles(); - } else { - NotifyReadyToActivate(); - - // Ensure we get ReadyToDraw signal even when PrepareTiles not run. This - // is important for SingleThreadProxy and impl-side painting case. For - // STP, we commit to active tree and RequiresHighResToDraw, and set - // Scheduler to wait for ReadyToDraw signal to avoid Checkerboard. - if (proxy_->CommitToActiveTree()) - NotifyReadyToDraw(); - } - } else { - // If we're not in impl-side painting, the tree is immediately considered - // active. - ActivateSyncTree(); + // We need an update immediately post-commit to have the opportunity to create + // tilings. Because invalidations may be coming from the main thread, it's + // safe to do an update for lcd text at this point and see if lcd text needs + // to be disabled on any layers. + bool update_lcd_text = true; + sync_tree()->UpdateDrawProperties(update_lcd_text); + // Start working on newly created tiles immediately if needed. + // TODO(vmpstr): Investigate always having PrepareTiles issue + // NotifyReadyToActivate, instead of handling it here. + bool did_prepare_tiles = PrepareTiles(); + if (!did_prepare_tiles) { + NotifyReadyToActivate(); + + // Ensure we get ReadyToDraw signal even when PrepareTiles not run. This + // is important for SingleThreadProxy and impl-side painting case. For + // STP, we commit to active tree and RequiresHighResToDraw, and set + // Scheduler to wait for ReadyToDraw signal to avoid Checkerboard. + if (proxy_->CommitToActiveTree()) + NotifyReadyToDraw(); } micro_benchmark_controller_.DidCompleteCommit(); @@ -381,12 +409,6 @@ bool LayerTreeHostImpl::CanDraw() const { TRACE_EVENT_SCOPE_THREAD); return false; } - if (active_tree_->ContentsTexturesPurged()) { - TRACE_EVENT_INSTANT0( - "cc", "LayerTreeHostImpl::CanDraw contents textures purged", - TRACE_EVENT_SCOPE_THREAD); - return false; - } if (EvictedUIResourcesExist()) { TRACE_EVENT_INSTANT0( "cc", "LayerTreeHostImpl::CanDraw UI resources evicted not recreated", @@ -397,24 +419,31 @@ bool LayerTreeHostImpl::CanDraw() const { } void LayerTreeHostImpl::Animate(base::TimeTicks monotonic_time) { - if (input_handler_client_) - input_handler_client_->Animate(monotonic_time); + // mithro(TODO): Enable these checks. + // DCHECK(!current_begin_frame_tracker_.HasFinished()); + // DCHECK(monotonic_time == current_begin_frame_tracker_.Current().frame_time) + // << "Called animate with unknown frame time!?"; + if (!root_layer_scroll_offset_delegate_ || + (CurrentlyScrollingLayer() != InnerViewportScrollLayer() && + CurrentlyScrollingLayer() != OuterViewportScrollLayer())) { + AnimateInput(monotonic_time); + } AnimatePageScale(monotonic_time); AnimateLayers(monotonic_time); AnimateScrollbars(monotonic_time); AnimateTopControls(monotonic_time); } -void LayerTreeHostImpl::PrepareTiles() { - if (!tile_manager_) - return; +bool LayerTreeHostImpl::PrepareTiles() { if (!tile_priorities_dirty_) - return; - - tile_priorities_dirty_ = false; - tile_manager_->PrepareTiles(global_tile_state_); + return false; + client_->WillPrepareTiles(); + bool did_prepare_tiles = tile_manager_->PrepareTiles(global_tile_state_); + if (did_prepare_tiles) + tile_priorities_dirty_ = false; client_->DidPrepareTiles(); + return did_prepare_tiles; } void LayerTreeHostImpl::StartPageScaleAnimation( @@ -457,6 +486,22 @@ void LayerTreeHostImpl::StartPageScaleAnimation( client_->RenewTreePriority(); } +void LayerTreeHostImpl::SetNeedsAnimateInput() { + if (root_layer_scroll_offset_delegate_ && + (CurrentlyScrollingLayer() == InnerViewportScrollLayer() || + CurrentlyScrollingLayer() == OuterViewportScrollLayer())) { + if (root_layer_animation_callback_.is_null()) { + root_layer_animation_callback_ = + base::Bind(&LayerTreeHostImpl::AnimateInput, AsWeakPtr()); + } + root_layer_scroll_offset_delegate_->SetNeedsAnimate( + root_layer_animation_callback_); + return; + } + + SetNeedsAnimate(); +} + bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt( const gfx::Point& viewport_point, InputHandler::ScrollInputType type) { @@ -566,10 +611,9 @@ void LayerTreeHostImpl::TrackDamageForAllSurfaces( // must compute all damage tracking before drawing anything, so that we know // the root damage rect. The root damage rect is then used to scissor each // surface. - - for (int surface_index = render_surface_layer_list.size() - 1; - surface_index >= 0; - --surface_index) { + size_t render_surface_layer_list_size = render_surface_layer_list.size(); + for (size_t i = 0; i < render_surface_layer_list_size; ++i) { + size_t surface_index = render_surface_layer_list_size - 1 - i; LayerImpl* render_surface_layer = render_surface_layer_list[surface_index]; RenderSurfaceImpl* render_surface = render_surface_layer->render_surface(); DCHECK(render_surface); @@ -745,9 +789,10 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses( "RequiresHighResToDraw", RequiresHighResToDraw()); // Create the render passes in dependency order. - for (int surface_index = frame->render_surface_layer_list->size() - 1; - surface_index >= 0; - --surface_index) { + size_t render_surface_layer_list_size = + frame->render_surface_layer_list->size(); + for (size_t i = 0; i < render_surface_layer_list_size; ++i) { + size_t surface_index = render_surface_layer_list_size - 1 - i; LayerImpl* render_surface_layer = (*frame->render_surface_layer_list)[surface_index]; RenderSurfaceImpl* render_surface = render_surface_layer->render_surface(); @@ -795,9 +840,9 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses( bool have_copy_request = false; bool have_missing_animated_tiles = false; - auto end = LayerIterator<LayerImpl>::End(frame->render_surface_layer_list); - for (auto it = - LayerIterator<LayerImpl>::Begin(frame->render_surface_layer_list); + LayerIterator end = LayerIterator::End(frame->render_surface_layer_list); + for (LayerIterator it = + LayerIterator::Begin(frame->render_surface_layer_list); it != end; ++it) { RenderPassId target_render_pass_id = it.target_render_surface_layer()->render_surface()->GetRenderPassId(); @@ -822,11 +867,10 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses( *it, contributing_render_pass, &append_quads_data); - } else if (it.represents_itself() && - !it->visible_content_rect().IsEmpty()) { + } else if (it.represents_itself() && !it->visible_layer_rect().IsEmpty()) { bool occluded = it->draw_properties().occlusion_in_content_space.IsOccluded( - it->visible_content_rect()); + it->visible_layer_rect()); if (!occluded && it->WillDraw(draw_mode, resource_provider_.get())) { DCHECK_EQ(active_tree_, it->layer_tree_impl()); @@ -852,9 +896,7 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses( // For layers that represent themselves, add composite frame timing // requests if the visible rect intersects the requested rect. for (const auto& request : it->frame_timing_requests()) { - const gfx::Rect& request_content_rect = - it->LayerRectToContentRect(request.rect()); - if (request_content_rect.Intersects(it->visible_content_rect())) { + if (request.rect().Intersects(it->visible_layer_rect())) { frame->composite_events.push_back( FrameTimingTracker::FrameAndRectIds( active_tree_->source_frame_number(), request.id())); @@ -866,7 +908,7 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses( } rendering_stats_instrumentation_->AddVisibleContentArea( - append_quads_data.visible_content_area); + append_quads_data.visible_layer_area); rendering_stats_instrumentation_->AddApproximatedVisibleContentArea( append_quads_data.approximated_visible_content_area); rendering_stats_instrumentation_->AddCheckerboardedVisibleContentArea( @@ -991,25 +1033,26 @@ DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) { input_handler_client_->ReconcileElasticOverscrollAndRootScroll(); UMA_HISTOGRAM_CUSTOM_COUNTS( - "Compositing.NumActiveLayers", active_tree_->NumLayers(), 1, 400, 20); + "Compositing.NumActiveLayers", + base::saturated_cast<int>(active_tree_->NumLayers()), 1, 400, 20); size_t total_picture_memory = 0; for (const PictureLayerImpl* layer : active_tree()->picture_layers()) total_picture_memory += layer->GetRasterSource()->GetPictureMemoryUsage(); if (total_picture_memory != 0) { - UMA_HISTOGRAM_COUNTS("Compositing.PictureMemoryUsageKb", - total_picture_memory / 1024); + UMA_HISTOGRAM_COUNTS( + "Compositing.PictureMemoryUsageKb", + base::saturated_cast<int>(total_picture_memory / 1024)); } bool update_lcd_text = false; bool ok = active_tree_->UpdateDrawProperties(update_lcd_text); DCHECK(ok) << "UpdateDrawProperties failed during draw"; - // This will cause NotifyTileStateChanged() to be called for any visible tiles - // that completed, which will add damage to the frame for them so they appear - // as part of the current frame being drawn. - if (tile_manager_) - tile_manager_->UpdateVisibleTiles(global_tile_state_); + // This will cause NotifyTileStateChanged() to be called for any tiles that + // completed, which will add damage for visible tiles to the frame for them so + // they appear as part of the current frame being drawn. + tile_manager_->Flush(); frame->render_surface_layer_list = &active_tree_->RenderSurfaceLayerList(); frame->render_passes.clear(); @@ -1122,7 +1165,7 @@ void LayerTreeHostImpl::RemoveRenderPasses(FrameData* frame) { } void LayerTreeHostImpl::EvictTexturesForTesting() { - EnforceManagedMemoryPolicy(ManagedMemoryPolicy(0)); + UpdateTileManagerMemoryPolicy(ManagedMemoryPolicy(0)); } void LayerTreeHostImpl::BlockNotifyReadyToActivateForTesting(bool block) { @@ -1144,29 +1187,13 @@ void LayerTreeHostImpl::ResetTreesForTesting() { recycle_tree_ = nullptr; } -void LayerTreeHostImpl::EnforceManagedMemoryPolicy( - const ManagedMemoryPolicy& policy) { - - bool evicted_resources = client_->ReduceContentsTextureMemoryOnImplThread( - visible_ ? policy.bytes_limit_when_visible : 0, - ManagedMemoryPolicy::PriorityCutoffToValue( - visible_ ? policy.priority_cutoff_when_visible - : gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING)); - if (evicted_resources) { - active_tree_->SetContentsTexturesPurged(); - if (pending_tree_) - pending_tree_->SetContentsTexturesPurged(); - client_->SetNeedsCommitOnImplThread(); - client_->OnCanDrawStateChanged(CanDraw()); - client_->RenewTreePriority(); - } - - UpdateTileManagerMemoryPolicy(policy); +size_t LayerTreeHostImpl::SourceAnimationFrameNumberForTesting() const { + return fps_counter_->current_frame_number(); } void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy( const ManagedMemoryPolicy& policy) { - if (!tile_manager_) + if (!resource_pool_) return; global_tile_state_.hard_memory_limit_in_bytes = 0; @@ -1186,6 +1213,16 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy( gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING); global_tile_state_.num_resources_limit = policy.num_resources_limit; + if (output_surface_ && global_tile_state_.hard_memory_limit_in_bytes > 0) { + // If |global_tile_state_.hard_memory_limit_in_bytes| is greater than 0, we + // allow the worker context to retain allocated resources. Notify the worker + // context. If the memory policy has become zero, we'll handle the + // notification in NotifyAllTileTasksCompleted, after in-progress work + // finishes. + output_surface_->SetWorkerContextShouldAggressivelyFreeResources( + false /* aggressively_free_resources */); + } + // TODO(reveman): We should avoid keeping around unused resources if // possible. crbug.com/224475 // Unused limit is calculated from soft-limit, as hard-limit may @@ -1217,7 +1254,6 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy( } void LayerTreeHostImpl::DidModifyTilePriorities() { - DCHECK(settings_.impl_side_painting); // Mark priorities as dirty and schedule a PrepareTiles(). tile_priorities_dirty_ = true; client_->SetNeedsPrepareTilesOnImplThread(); @@ -1269,6 +1305,15 @@ void LayerTreeHostImpl::NotifyReadyToDraw() { client_->NotifyReadyToDraw(); } +void LayerTreeHostImpl::NotifyAllTileTasksCompleted() { + // The tile tasks started by the most recent call to PrepareTiles have + // completed. Now is a good time to free resources if necessary. + if (output_surface_ && global_tile_state_.hard_memory_limit_in_bytes == 0) { + output_surface_->SetWorkerContextShouldAggressivelyFreeResources( + true /* aggressively_free_resources */); + } +} + void LayerTreeHostImpl::NotifyTileStateChanged(const Tile* tile) { TRACE_EVENT0("cc", "LayerTreeHostImpl::NotifyTileStateChanged"); @@ -1300,14 +1345,17 @@ void LayerTreeHostImpl::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { // This is short term solution to synchronously drop tile resources when // using synchronous compositing to avoid memory usage regression. // TODO(boliu): crbug.com/499004 to track removing this. - if (!policy.bytes_limit_when_visible && tile_manager_ && + if (!policy.bytes_limit_when_visible && resource_pool_ && settings_.using_synchronous_renderer_compositor) { ReleaseTreeResources(); - // TileManager destruction will synchronoulsy wait for all tile workers to - // be cancelled or completed. This allows all resources to be freed - // synchronously. - DestroyTileManager(); - CreateAndSetTileManager(); + CleanUpTileManager(); + + // Force a call to NotifyAllTileTasks completed - otherwise this logic may + // be skipped if no work was enqueued at the time the tile manager was + // destroyed. + NotifyAllTileTasksCompleted(); + + CreateTileManagerResources(); RecreateTreeResources(); } } @@ -1315,7 +1363,6 @@ void LayerTreeHostImpl::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { void LayerTreeHostImpl::SetTreeActivationCallback( const base::Closure& callback) { DCHECK(proxy_->IsImplThread()); - DCHECK(settings_.impl_side_painting || callback.is_null()); tree_activation_callback_ = callback; } @@ -1336,10 +1383,10 @@ void LayerTreeHostImpl::SetManagedMemoryPolicy( // In single-thread mode, this can be called on the main thread by // GLRenderer::OnMemoryAllocationChanged. DebugScopedSetImplThread impl_thread(proxy_); - EnforceManagedMemoryPolicy(actual_policy); + UpdateTileManagerMemoryPolicy(actual_policy); } else { DCHECK(proxy_->IsImplThread()); - EnforceManagedMemoryPolicy(actual_policy); + UpdateTileManagerMemoryPolicy(actual_policy); } // If there is already enough memory to draw everything imaginable and the @@ -1415,9 +1462,7 @@ void LayerTreeHostImpl::ReclaimResources(const CompositorFrameAck* ack) { // In OOM, we now might be able to release more resources that were held // because they were exported. - if (tile_manager_) { - DCHECK(resource_pool_); - + if (resource_pool_) { resource_pool_->CheckBusyResources(false); resource_pool_->ReduceResourceUsage(); } @@ -1496,10 +1541,7 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame) { !output_surface_->context_provider()); rendering_stats_instrumentation_->IncrementFrameCount(1); - if (tile_manager_) { - memory_history_->SaveEntry( - tile_manager_->memory_stats_from_last_assign()); - } + memory_history_->SaveEntry(tile_manager_->memory_stats_from_last_assign()); if (debug_state_.ShowHudRects()) { debug_rect_history_->SaveDebugRectsForCurrentFrame( @@ -1509,13 +1551,6 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame) { debug_state_); } - if (!settings_.impl_side_painting && debug_state_.continuous_painting) { - const RenderingStats& stats = - rendering_stats_instrumentation_->GetRenderingStats(); - paint_time_counter_->SavePaintTime( - stats.begin_main_frame_to_commit_duration.GetLastTimeDelta()); - } - bool is_new_trace; TRACE_EVENT_IS_NEW_TRACE(&is_new_trace); if (is_new_trace) { @@ -1549,7 +1584,9 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame) { if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) { bool disable_picture_quad_image_filtering = - IsActivelyScrolling() || animation_registrar_->needs_animate_layers(); + IsActivelyScrolling() || + (animation_host_ ? animation_host_->NeedsAnimateLayers() + : animation_registrar_->needs_animate_layers()); scoped_ptr<SoftwareRenderer> temp_software_renderer = SoftwareRenderer::Create(this, &settings_.renderer_settings, @@ -1593,10 +1630,6 @@ void LayerTreeHostImpl::DidDrawAllLayers(const FrameData& frame) { for (auto& it : video_frame_controllers_) it->DidDrawFrame(); - - // Once all layers have been drawn, pending texture uploads should no - // longer block future uploads. - resource_provider_->MarkPendingUploadsAsNonBlocking(); } void LayerTreeHostImpl::FinishAllRendering() { @@ -1674,11 +1707,13 @@ void LayerTreeHostImpl::UpdateTreeResourcesForGpuRasterizationIfNeeded() { return; // Clean up and replace existing tile manager with another one that uses - // appropriate rasterizer. + // appropriate rasterizer. Only do this however if we already have a + // resource pool, since otherwise we might not be able to create a new + // one. ReleaseTreeResources(); - if (tile_manager_) { - DestroyTileManager(); - CreateAndSetTileManager(); + if (resource_pool_) { + CleanUpTileManager(); + CreateTileManagerResources(); } RecreateTreeResources(); @@ -1723,16 +1758,7 @@ bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) { } void LayerTreeHostImpl::WillBeginImplFrame(const BeginFrameArgs& args) { - // Sample the frame time now. This time will be used for updating animations - // when we draw. - DCHECK(!current_begin_frame_args_.IsValid()); - current_begin_frame_args_ = args; - // TODO(mithro): Stop overriding the frame time once the usage of frame - // timing is unified. - current_begin_frame_args_.frame_time = gfx::FrameTime::Now(); - - // Cache the begin impl frame interval - begin_impl_frame_interval_ = args.interval; + current_begin_frame_tracker_.Start(args); if (is_likely_to_require_a_draw_) { // Optimistically schedule a draw. This will let us expect the tile manager @@ -1746,8 +1772,7 @@ void LayerTreeHostImpl::WillBeginImplFrame(const BeginFrameArgs& args) { } void LayerTreeHostImpl::DidFinishImplFrame() { - DCHECK(current_begin_frame_args_.IsValid()); - current_begin_frame_args_ = BeginFrameArgs(); + current_begin_frame_tracker_.Finish(); } void LayerTreeHostImpl::UpdateViewportContainerSizes() { @@ -1806,8 +1831,7 @@ void LayerTreeHostImpl::UpdateViewportContainerSizes() { void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() { // Only valid for the single-threaded non-scheduled/synchronous case // using the zero copy raster worker pool. - if (tile_manager_) - single_thread_synchronous_task_graph_runner_->RunUntilIdle(); + single_thread_synchronous_task_graph_runner_->RunUntilIdle(); } void LayerTreeHostImpl::DidLoseOutputSurface() { @@ -1837,11 +1861,15 @@ LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const { } bool LayerTreeHostImpl::IsActivelyScrolling() const { - return (did_lock_scrolling_layer_ && CurrentlyScrollingLayer()) || - (InnerViewportScrollLayer() && - InnerViewportScrollLayer()->IsExternalFlingActive()) || - (OuterViewportScrollLayer() && - OuterViewportScrollLayer()->IsExternalFlingActive()); + if (!CurrentlyScrollingLayer()) + return false; + if (root_layer_scroll_offset_delegate_ && + (CurrentlyScrollingLayer() == InnerViewportScrollLayer() || + CurrentlyScrollingLayer() == OuterViewportScrollLayer())) { + // ScrollDelegate cannot determine current scroll, so assume no. + return false; + } + return did_lock_scrolling_layer_; } // Content layers can be either directly scrollable or contained in an outer @@ -1911,15 +1939,16 @@ void LayerTreeHostImpl::ActivateSyncTree() { active_tree_->ProcessUIResourceRequestQueue(); } + // bounds_delta isn't a pushed property, so the newly-pushed property tree + // won't already account for current bounds_delta values. + active_tree_->UpdatePropertyTreesForBoundsDelta(); active_tree_->DidBecomeActive(); ActivateAnimations(); - if (settings_.impl_side_painting) { - client_->RenewTreePriority(); - // If we have any picture layers, then by activating we also modified tile - // priorities. - if (!active_tree_->picture_layers().empty()) - DidModifyTilePriorities(); - } + client_->RenewTreePriority(); + // If we have any picture layers, then by activating we also modified tile + // priorities. + if (!active_tree_->picture_layers().empty()) + DidModifyTilePriorities(); client_->OnCanDrawStateChanged(CanDraw()); client_->DidActivateSyncTree(); @@ -1954,7 +1983,7 @@ void LayerTreeHostImpl::SetVisible(bool visible) { return; visible_ = visible; DidVisibilityChange(this, visible_); - EnforceManagedMemoryPolicy(ActualManagedMemoryPolicy()); + UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy()); // If we just became visible, we have to ensure that we draw high res tiles, // to prevent checkerboard/low res flashes. @@ -1963,10 +1992,11 @@ void LayerTreeHostImpl::SetVisible(bool visible) { else EvictAllUIResources(); - // Evict tiles immediately if invisible since this tab may never get another - // draw or timer tick. - if (!visible_) - PrepareTiles(); + // Call PrepareTiles unconditionally on visibility change since this tab may + // never get another draw or timer tick. When becoming visible we care about + // unblocking the scheduler which might be waiting for activation / ready to + // draw. When becoming invisible we care about evicting tiles immediately. + PrepareTiles(); if (!renderer_) return; @@ -2000,11 +2030,6 @@ size_t LayerTreeHostImpl::memory_allocation_limit_bytes() const { return ActualManagedMemoryPolicy().bytes_limit_when_visible; } -int LayerTreeHostImpl::memory_allocation_priority_cutoff() const { - return ManagedMemoryPolicy::PriorityCutoffToValue( - ActualManagedMemoryPolicy().priority_cutoff_when_visible); -} - void LayerTreeHostImpl::ReleaseTreeResources() { active_tree_->ReleaseResources(); if (pending_tree_) @@ -2056,28 +2081,13 @@ void LayerTreeHostImpl::CreateAndSetRenderer() { client_->UpdateRendererCapabilitiesOnImplThread(); } -void LayerTreeHostImpl::CreateAndSetTileManager() { - DCHECK(!tile_manager_); - DCHECK(settings_.impl_side_painting); - DCHECK(output_surface_); - DCHECK(resource_provider_); - +void LayerTreeHostImpl::CreateTileManagerResources() { CreateResourceAndTileTaskWorkerPool(&tile_task_worker_pool_, &resource_pool_, &staging_resource_pool_); - DCHECK(tile_task_worker_pool_); - DCHECK(resource_pool_); - - base::SingleThreadTaskRunner* task_runner = - proxy_->HasImplThread() ? proxy_->ImplThreadTaskRunner() - : proxy_->MainThreadTaskRunner(); - DCHECK(task_runner); - size_t scheduled_raster_task_limit = + tile_manager_->SetResources( + resource_pool_.get(), tile_task_worker_pool_->AsTileTaskRunner(), IsSynchronousSingleThreaded() ? std::numeric_limits<size_t>::max() - : settings_.scheduled_raster_task_limit; - tile_manager_ = TileManager::Create( - this, task_runner, resource_pool_.get(), - tile_task_worker_pool_->AsTileTaskRunner(), scheduled_raster_task_limit); - + : settings_.scheduled_raster_task_limit); UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy()); } @@ -2085,10 +2095,7 @@ void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool( scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool, scoped_ptr<ResourcePool>* resource_pool, scoped_ptr<ResourcePool>* staging_resource_pool) { - base::SingleThreadTaskRunner* task_runner = - proxy_->HasImplThread() ? proxy_->ImplThreadTaskRunner() - : proxy_->MainThreadTaskRunner(); - DCHECK(task_runner); + DCHECK(GetTaskRunner()); // Pass the single-threaded synchronous task graph runner to the worker pool // if we're in synchronous single-threaded mode. @@ -2105,7 +2112,7 @@ void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool( ResourcePool::Create(resource_provider_.get(), GL_TEXTURE_2D); *tile_task_worker_pool = BitmapTileTaskWorkerPool::Create( - task_runner, task_graph_runner, resource_provider_.get()); + GetTaskRunner(), task_graph_runner, resource_provider_.get()); return; } @@ -2117,42 +2124,51 @@ void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool( use_msaa_ ? settings_.gpu_rasterization_msaa_sample_count : 0; *tile_task_worker_pool = GpuTileTaskWorkerPool::Create( - task_runner, task_graph_runner, context_provider, + GetTaskRunner(), task_graph_runner, context_provider, resource_provider_.get(), settings_.use_distance_field_text, msaa_sample_count); return; } - if (GetRendererCapabilities().using_image) { - unsigned image_target = settings_.use_image_texture_target; - DCHECK_IMPLIES( - image_target == GL_TEXTURE_RECTANGLE_ARB, - context_provider->ContextCapabilities().gpu.texture_rectangle); - DCHECK_IMPLIES( - image_target == GL_TEXTURE_EXTERNAL_OES, - context_provider->ContextCapabilities().gpu.egl_image_external); + DCHECK(GetRendererCapabilities().using_image); + unsigned image_target = settings_.use_image_texture_target; + DCHECK_IMPLIES(image_target == GL_TEXTURE_RECTANGLE_ARB, + context_provider->ContextCapabilities().gpu.texture_rectangle); + DCHECK_IMPLIES( + image_target == GL_TEXTURE_EXTERNAL_OES, + context_provider->ContextCapabilities().gpu.egl_image_external); - if (settings_.use_zero_copy || IsSynchronousSingleThreaded()) { - *resource_pool = - ResourcePool::Create(resource_provider_.get(), image_target); + if (settings_.use_zero_copy) { + *resource_pool = + ResourcePool::Create(resource_provider_.get(), image_target); - *tile_task_worker_pool = ZeroCopyTileTaskWorkerPool::Create( - task_runner, task_graph_runner, resource_provider_.get()); - return; - } + *tile_task_worker_pool = ZeroCopyTileTaskWorkerPool::Create( + GetTaskRunner(), task_graph_runner, resource_provider_.get()); + return; + } - if (settings_.use_one_copy) { - // We need to create a staging resource pool when using copy rasterizer. - *staging_resource_pool = - ResourcePool::Create(resource_provider_.get(), image_target); - *resource_pool = - ResourcePool::Create(resource_provider_.get(), GL_TEXTURE_2D); - - *tile_task_worker_pool = OneCopyTileTaskWorkerPool::Create( - task_runner, task_graph_runner, context_provider, - resource_provider_.get(), staging_resource_pool_.get()); - return; - } + if (settings_.use_one_copy) { + // Synchronous single-threaded mode depends on tiles being ready to + // draw when raster is complete. Therefore, it must use one of zero + // copy, software raster, or GPU raster. + DCHECK(!IsSynchronousSingleThreaded()); + + // We need to create a staging resource pool when using copy rasterizer. + *staging_resource_pool = + ResourcePool::Create(resource_provider_.get(), image_target); + *resource_pool = + ResourcePool::Create(resource_provider_.get(), GL_TEXTURE_2D); + + int max_copy_texture_chromium_size = + context_provider->ContextCapabilities() + .gpu.max_copy_texture_chromium_size; + + *tile_task_worker_pool = OneCopyTileTaskWorkerPool::Create( + GetTaskRunner(), task_graph_runner, context_provider, + resource_provider_.get(), staging_resource_pool_.get(), + max_copy_texture_chromium_size, + settings_.use_persistent_map_for_gpu_memory_buffers); + return; } // Synchronous single-threaded mode depends on tiles being ready to @@ -2164,7 +2180,7 @@ void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool( resource_provider_.get(), GL_TEXTURE_2D); *tile_task_worker_pool = PixelBufferTileTaskWorkerPool::Create( - task_runner, task_graph_runner_, context_provider, + GetTaskRunner(), task_graph_runner_, context_provider, resource_provider_.get(), GetMaxTransferBufferUsageBytes(context_provider->ContextCapabilities(), settings_.renderer_settings.refresh_rate)); @@ -2184,8 +2200,15 @@ void LayerTreeHostImpl::RecordMainFrameTiming( request_ids, start_time, end_time, active_tree_->source_frame_number()); } -void LayerTreeHostImpl::DestroyTileManager() { - tile_manager_ = nullptr; +void LayerTreeHostImpl::PostFrameTimingEvents( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) { + client_->PostFrameTimingEventsOnImplThread(composite_events.Pass(), + main_frame_events.Pass()); +} + +void LayerTreeHostImpl::CleanUpTileManager() { + tile_manager_->FinishTasksAndCleanUp(); resource_pool_ = nullptr; staging_resource_pool_ = nullptr; tile_task_worker_pool_ = nullptr; @@ -2207,7 +2230,7 @@ bool LayerTreeHostImpl::InitializeRenderer( // Note: order is important here. renderer_ = nullptr; - DestroyTileManager(); + CleanUpTileManager(); resource_provider_ = nullptr; output_surface_ = nullptr; @@ -2224,15 +2247,15 @@ bool LayerTreeHostImpl::InitializeRenderer( proxy_->blocking_main_thread_task_runner(), settings_.renderer_settings.highp_threshold_min, settings_.renderer_settings.use_rgba_4444_textures, - settings_.renderer_settings.texture_id_allocation_chunk_size); + settings_.renderer_settings.texture_id_allocation_chunk_size, + settings_.use_persistent_map_for_gpu_memory_buffers); CreateAndSetRenderer(); // Since the new renderer may be capable of MSAA, update status here. UpdateGpuRasterizationStatus(); - if (settings_.impl_side_painting && settings_.raster_enabled) - CreateAndSetTileManager(); + CreateTileManagerResources(); RecreateTreeResources(); // Initialize vsync parameters to sane values. @@ -2419,18 +2442,42 @@ static bool HasScrollAncestor(LayerImpl* child, LayerImpl* scroll_ancestor) { return false; } +InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( + LayerImpl* scrolling_layer_impl, + InputHandler::ScrollInputType type) { + if (!scrolling_layer_impl) + return SCROLL_IGNORED; + + top_controls_manager_->ScrollBegin(); + + active_tree_->SetCurrentlyScrollingLayer(scrolling_layer_impl); + should_bubble_scrolls_ = (type != NON_BUBBLING_GESTURE); + wheel_scrolling_ = (type == WHEEL); + client_->RenewTreePriority(); + UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false); + return SCROLL_STARTED; +} + +InputHandler::ScrollStatus LayerTreeHostImpl::RootScrollBegin( + InputHandler::ScrollInputType type) { + TRACE_EVENT0("cc", "LayerTreeHostImpl::RootScrollBegin"); + + DCHECK(!CurrentlyScrollingLayer()); + ClearCurrentlyScrollingLayer(); + + return ScrollBeginImpl(InnerViewportScrollLayer(), type); +} + InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin( const gfx::Point& viewport_point, InputHandler::ScrollInputType type) { TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBegin"); - top_controls_manager_->ScrollBegin(); - DCHECK(!CurrentlyScrollingLayer()); ClearCurrentlyScrollingLayer(); - gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point, - device_scale_factor_); + gfx::PointF device_viewport_point = + gfx::ScalePoint(viewport_point, device_scale_factor_); LayerImpl* layer_impl = active_tree_->FindLayerThatIsHitByPoint(device_viewport_point); @@ -2443,27 +2490,16 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin( } bool scroll_on_main_thread = false; - LayerImpl* scrolling_layer_impl = - FindScrollLayerForDeviceViewportPoint(device_viewport_point, - type, - layer_impl, - &scroll_on_main_thread, - &scroll_affects_scroll_handler_); + LayerImpl* scrolling_layer_impl = FindScrollLayerForDeviceViewportPoint( + device_viewport_point, type, layer_impl, &scroll_on_main_thread, + &scroll_affects_scroll_handler_); if (scroll_on_main_thread) { UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true); return SCROLL_ON_MAIN_THREAD; } - if (scrolling_layer_impl) { - active_tree_->SetCurrentlyScrollingLayer(scrolling_layer_impl); - should_bubble_scrolls_ = (type != NON_BUBBLING_GESTURE); - wheel_scrolling_ = (type == WHEEL); - client_->RenewTreePriority(); - UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false); - return SCROLL_STARTED; - } - return SCROLL_IGNORED; + return ScrollBeginImpl(scrolling_layer_impl, type); } InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( @@ -2555,13 +2591,6 @@ gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta( if (start_clipped || end_clipped) return gfx::Vector2dF(); - // local_start_point and local_end_point are in content space but we want to - // move them to layer space for scrolling. - float width_scale = 1.f / layer_impl->contents_scale_x(); - float height_scale = 1.f / layer_impl->contents_scale_y(); - local_start_point.Scale(width_scale, height_scale); - local_end_point.Scale(width_scale, height_scale); - // Apply the scroll delta. gfx::ScrollOffset previous_offset = layer_impl->CurrentScrollOffset(); layer_impl->ScrollBy(local_end_point - local_start_point); @@ -2572,16 +2601,11 @@ gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta( // ScreenSpaceTransform. gfx::PointF actual_local_end_point = local_start_point + gfx::Vector2dF(scrolled.x(), scrolled.y()); - gfx::PointF actual_local_content_end_point = - gfx::ScalePoint(actual_local_end_point, - 1.f / width_scale, - 1.f / height_scale); // Calculate the applied scroll delta in viewport space coordinates. gfx::PointF actual_screen_space_end_point = MathUtil::MapPoint(layer_impl->screen_space_transform(), - actual_local_content_end_point, - &end_clipped); + actual_local_end_point, &end_clipped); DCHECK(!end_clipped); if (end_clipped) return gfx::Vector2dF(); @@ -2601,7 +2625,10 @@ static gfx::Vector2dF ScrollLayerWithLocalDelta( layer_impl->ScrollBy(delta); gfx::ScrollOffset scrolled = layer_impl->CurrentScrollOffset() - previous_offset; - return gfx::Vector2dF(scrolled.x(), scrolled.y()); + gfx::Vector2dF consumed_scroll(scrolled.x(), scrolled.y()); + consumed_scroll.Scale(page_scale_factor); + + return consumed_scroll; } gfx::Vector2dF LayerTreeHostImpl::ScrollLayer(LayerImpl* layer_impl, @@ -2645,6 +2672,13 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( bool did_scroll_y = false; bool did_scroll_top_controls = false; + if (pinch_gesture_active_ && settings().invert_viewport_scroll_order) { + // Scrolls during a pinch gesture should pan the visual viewport, rather + // than a typical bubbling scroll. + viewport()->Pan(pending_delta); + return InputHandlerScrollResult(); + } + for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); layer_impl; layer_impl = nextLayerInScrollOrder(layer_impl)) { @@ -2656,9 +2690,11 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( gfx::Vector2dF applied_delta; if (layer_impl == InnerViewportScrollLayer()) { + bool affect_top_controls = true; Viewport::ScrollResult result = viewport()->ScrollBy(pending_delta, viewport_point, - wheel_scrolling_); + wheel_scrolling_, + affect_top_controls); applied_delta = result.applied_delta; unused_root_delta = result.unused_scroll_delta; did_scroll_top_controls = result.top_controls_applied_delta.y() != 0; @@ -2807,19 +2843,15 @@ void LayerTreeHostImpl::ScrollEnd() { } InputHandler::ScrollStatus LayerTreeHostImpl::FlingScrollBegin() { - if (!active_tree_->CurrentlyScrollingLayer()) - return SCROLL_IGNORED; - - if (settings_.ignore_root_layer_flings && - (active_tree_->CurrentlyScrollingLayer() == InnerViewportScrollLayer() || - active_tree_->CurrentlyScrollingLayer() == OuterViewportScrollLayer())) { - ClearCurrentlyScrollingLayer(); + if (!CurrentlyScrollingLayer()) return SCROLL_IGNORED; - } - if (!wheel_scrolling_) { + bool currently_scrolling_viewport = + CurrentlyScrollingLayer() == OuterViewportScrollLayer() || + CurrentlyScrollingLayer() == InnerViewportScrollLayer(); + if (!wheel_scrolling_ && !currently_scrolling_viewport) { // Allow the fling to lock to the first layer that moves after the initial - // fling |ScrollBy()| event. + // fling |ScrollBy()| event, unless we're already scrolling the viewport. did_lock_scrolling_layer_ = false; should_bubble_scrolls_ = false; } @@ -2833,8 +2865,7 @@ float LayerTreeHostImpl::DeviceSpaceDistanceToLayer( if (!layer_impl) return std::numeric_limits<float>::max(); - gfx::Rect layer_impl_bounds( - layer_impl->content_bounds()); + gfx::Rect layer_impl_bounds(layer_impl->bounds()); gfx::RectF device_viewport_layer_impl_bounds = MathUtil::MapClippedRect( layer_impl->screen_space_transform(), @@ -2913,7 +2944,6 @@ bool LayerTreeHostImpl::HandleMouseOverScrollbar(LayerImpl* layer_impl, void LayerTreeHostImpl::PinchGestureBegin() { pinch_gesture_active_ = true; - previous_pinch_anchor_ = gfx::Point(); client_->RenewTreePriority(); pinch_gesture_end_should_clear_scrolling_layer_ = !CurrentlyScrollingLayer(); if (active_tree_->OuterViewportScrollLayer()) { @@ -2938,35 +2968,7 @@ void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta, // the pinch update. active_tree_->SetRootLayerScrollOffsetDelegate(NULL); - // Keep the center-of-pinch anchor specified by (x, y) in a stable - // position over the course of the magnify. - float page_scale = active_tree_->current_page_scale_factor(); - gfx::PointF previous_scale_anchor = gfx::ScalePoint(anchor, 1.f / page_scale); - active_tree_->SetPageScaleOnActiveTree(page_scale * magnify_delta); - page_scale = active_tree_->current_page_scale_factor(); - gfx::PointF new_scale_anchor = gfx::ScalePoint(anchor, 1.f / page_scale); - gfx::Vector2dF move = previous_scale_anchor - new_scale_anchor; - - previous_pinch_anchor_ = anchor; - - // If clamping the inner viewport scroll offset causes a change, it should - // be accounted for from the intended move. - move -= InnerViewportScrollLayer()->ClampScrollToMaxScrollOffset(); - - // We manually manage the bubbling behaviour here as it is different to that - // implemented in LayerTreeHostImpl::ScrollBy(). Specifically: - // 1) we want to explicit limit the bubbling to the outer/inner viewports, - // 2) we don't want the directional limitations on the unused parts that - // ScrollBy() implements, and - // 3) pinching should not engage the top controls manager. - gfx::Vector2dF unused = OuterViewportScrollLayer() - ? OuterViewportScrollLayer()->ScrollBy(move) - : move; - - if (!unused.IsZero()) { - InnerViewportScrollLayer()->ScrollBy(unused); - InnerViewportScrollLayer()->ClampScrollToMaxScrollOffset(); - } + viewport()->PinchUpdate(magnify_delta, anchor); active_tree_->SetRootLayerScrollOffsetDelegate( root_layer_scroll_offset_delegate_); @@ -2982,6 +2984,7 @@ void LayerTreeHostImpl::PinchGestureEnd() { pinch_gesture_end_should_clear_scrolling_layer_ = false; ClearCurrentlyScrollingLayer(); } + viewport()->PinchEnd(); top_controls_manager_->PinchEnd(); client_->SetNeedsCommitOnImplThread(); // When a pinch ends, we may be displaying content cached at incorrect scales, @@ -3049,6 +3052,12 @@ void LayerTreeHostImpl::ScrollViewportBy(gfx::Vector2dF scroll_delta) { InnerViewportScrollLayer()->ScrollBy(unused_delta); } +void LayerTreeHostImpl::AnimateInput(base::TimeTicks monotonic_time) { + DCHECK(proxy_->IsImplThread()); + if (input_handler_client_) + input_handler_client_->Animate(monotonic_time); +} + void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks monotonic_time) { if (!page_scale_animation_) return; @@ -3115,18 +3124,31 @@ void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time) { if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer()) return; - if (animation_registrar_->AnimateLayers(monotonic_time)) - SetNeedsAnimate(); + if (animation_host_) { + if (animation_host_->AnimateLayers(monotonic_time)) + SetNeedsAnimate(); + } else { + if (animation_registrar_->AnimateLayers(monotonic_time)) + SetNeedsAnimate(); + } } void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) { if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer()) return; - scoped_ptr<AnimationEventsVector> events = - animation_registrar_->CreateEvents(); - const bool has_active_animations = animation_registrar_->UpdateAnimationState( - start_ready_animations, events.get()); + bool has_active_animations = false; + scoped_ptr<AnimationEventsVector> events; + + if (animation_host_) { + events = animation_host_->CreateEvents(); + has_active_animations = animation_host_->UpdateAnimationState( + start_ready_animations, events.get()); + } else { + events = animation_registrar_->CreateEvents(); + has_active_animations = animation_registrar_->UpdateAnimationState( + start_ready_animations, events.get()); + } if (!events->empty()) client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass()); @@ -3139,8 +3161,13 @@ void LayerTreeHostImpl::ActivateAnimations() { if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer()) return; - if (animation_registrar_->ActivateAnimations()) - SetNeedsAnimate(); + if (animation_host_) { + if (animation_host_->ActivateAnimations()) + SetNeedsAnimate(); + } else { + if (animation_registrar_->ActivateAnimations()) + SetNeedsAnimate(); + } } std::string LayerTreeHostImpl::LayerTreeAsJson() const { @@ -3148,15 +3175,11 @@ std::string LayerTreeHostImpl::LayerTreeAsJson() const { if (active_tree_->root_layer()) { scoped_ptr<base::Value> json(active_tree_->root_layer()->LayerTreeAsJson()); base::JSONWriter::WriteWithOptions( - json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); + *json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); } return str; } -int LayerTreeHostImpl::SourceAnimationFrameNumber() const { - return fps_counter_->current_frame_number(); -} - void LayerTreeHostImpl::StartAnimatingScrollbarAnimationController( ScrollbarAnimationController* controller) { scrollbar_animation_controllers_.insert(controller); @@ -3182,8 +3205,9 @@ void LayerTreeHostImpl::AddVideoFrameController( VideoFrameController* controller) { bool was_empty = video_frame_controllers_.empty(); video_frame_controllers_.insert(controller); - if (current_begin_frame_args_.IsValid()) - controller->OnBeginFrame(current_begin_frame_args_); + if (current_begin_frame_tracker_.DangerousMethodHasStarted() && + !current_begin_frame_tracker_.DangerousMethodHasFinished()) + controller->OnBeginFrame(current_begin_frame_tracker_.Current()); if (was_empty) client_->SetVideoNeedsBeginFrames(true); } @@ -3210,14 +3234,13 @@ TreePriority LayerTreeHostImpl::GetTreePriority() const { } BeginFrameArgs LayerTreeHostImpl::CurrentBeginFrameArgs() const { - // Try to use the current frame time to keep animations non-jittery. But if - // we're not in a frame (because this is during an input event or a delayed - // task), fall back to physical time. This should still be monotonic. - if (current_begin_frame_args_.IsValid()) - return current_begin_frame_args_; - return BeginFrameArgs::Create( - BEGINFRAME_FROM_HERE, gfx::FrameTime::Now(), base::TimeTicks(), - BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL); + // TODO(mithro): Replace call with current_begin_frame_tracker_.Current() + // once all calls which happens outside impl frames are fixed. + return current_begin_frame_tracker_.DangerousMethodCurrentOrLast(); +} + +base::TimeDelta LayerTreeHostImpl::CurrentBeginFrameInterval() const { + return current_begin_frame_tracker_.Interval(); } scoped_refptr<base::trace_event::ConvertableToTraceFormat> @@ -3310,7 +3333,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, // Allow for multiple creation requests with the same UIResourceId. The // previous resource is simply deleted. - ResourceProvider::ResourceId id = ResourceIdForUIResource(uid); + ResourceId id = ResourceIdForUIResource(uid); if (id) DeleteUIResource(uid); @@ -3343,7 +3366,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, } void LayerTreeHostImpl::DeleteUIResource(UIResourceId uid) { - ResourceProvider::ResourceId id = ResourceIdForUIResource(uid); + ResourceId id = ResourceIdForUIResource(uid); if (id) { resource_provider_->DeleteResource(id); ui_resource_map_.erase(uid); @@ -3368,8 +3391,7 @@ void LayerTreeHostImpl::EvictAllUIResources() { client_->RenewTreePriority(); } -ResourceProvider::ResourceId LayerTreeHostImpl::ResourceIdForUIResource( - UIResourceId uid) const { +ResourceId LayerTreeHostImpl::ResourceIdForUIResource(UIResourceId uid) const { UIResourceMap::const_iterator iter = ui_resource_map_.find(uid); if (iter != ui_resource_map_.end()) return iter->second.resource_id; @@ -3425,6 +3447,10 @@ void LayerTreeHostImpl::ScrollAnimationCreate( LayerImpl* layer_impl, const gfx::ScrollOffset& target_offset, const gfx::ScrollOffset& current_offset) { + if (animation_host_) + return animation_host_->ImplOnlyScrollAnimationCreate( + layer_impl->id(), target_offset, current_offset); + scoped_ptr<ScrollOffsetAnimationCurve> curve = ScrollOffsetAnimationCurve::Create(target_offset, EaseInOutTimingFunction::Create()); @@ -3441,6 +3467,11 @@ void LayerTreeHostImpl::ScrollAnimationCreate( bool LayerTreeHostImpl::ScrollAnimationUpdateTarget( LayerImpl* layer_impl, const gfx::Vector2dF& scroll_delta) { + if (animation_host_) + return animation_host_->ImplOnlyScrollAnimationUpdateTarget( + layer_impl->id(), scroll_delta, layer_impl->MaxScrollOffset(), + CurrentBeginFrameArgs().frame_time); + Animation* animation = layer_impl->layer_animation_controller() ? layer_impl->layer_animation_controller()->GetAnimation( @@ -3464,4 +3495,132 @@ bool LayerTreeHostImpl::ScrollAnimationUpdateTarget( return true; } + +bool LayerTreeHostImpl::IsLayerInTree(int layer_id, + LayerTreeType tree_type) const { + if (tree_type == LayerTreeType::ACTIVE) { + return active_tree() ? active_tree()->LayerById(layer_id) != nullptr + : false; + } else { + if (pending_tree() && pending_tree()->LayerById(layer_id)) + return true; + if (recycle_tree() && recycle_tree()->LayerById(layer_id)) + return true; + + return false; + } +} + +void LayerTreeHostImpl::SetMutatorsNeedCommit() { + SetNeedsCommit(); +} + +void LayerTreeHostImpl::SetTreeLayerFilterMutated( + int layer_id, + LayerTreeImpl* tree, + const FilterOperations& filters) { + if (!tree) + return; + + LayerAnimationValueObserver* layer = tree->LayerById(layer_id); + if (layer) + layer->OnFilterAnimated(filters); +} + +void LayerTreeHostImpl::SetTreeLayerOpacityMutated(int layer_id, + LayerTreeImpl* tree, + float opacity) { + if (!tree) + return; + + LayerAnimationValueObserver* layer = tree->LayerById(layer_id); + if (layer) + layer->OnOpacityAnimated(opacity); +} + +void LayerTreeHostImpl::SetTreeLayerTransformMutated( + int layer_id, + LayerTreeImpl* tree, + const gfx::Transform& transform) { + if (!tree) + return; + + LayerAnimationValueObserver* layer = tree->LayerById(layer_id); + if (layer) + layer->OnTransformAnimated(transform); +} + +void LayerTreeHostImpl::SetTreeLayerScrollOffsetMutated( + int layer_id, + LayerTreeImpl* tree, + const gfx::ScrollOffset& scroll_offset) { + if (!tree) + return; + + LayerAnimationValueObserver* layer = tree->LayerById(layer_id); + if (layer) + layer->OnScrollOffsetAnimated(scroll_offset); +} + +void LayerTreeHostImpl::SetLayerFilterMutated(int layer_id, + LayerTreeType tree_type, + const FilterOperations& filters) { + if (tree_type == LayerTreeType::ACTIVE) { + SetTreeLayerFilterMutated(layer_id, active_tree(), filters); + } else { + SetTreeLayerFilterMutated(layer_id, pending_tree(), filters); + SetTreeLayerFilterMutated(layer_id, recycle_tree(), filters); + } +} + +void LayerTreeHostImpl::SetLayerOpacityMutated(int layer_id, + LayerTreeType tree_type, + float opacity) { + if (tree_type == LayerTreeType::ACTIVE) { + SetTreeLayerOpacityMutated(layer_id, active_tree(), opacity); + } else { + SetTreeLayerOpacityMutated(layer_id, pending_tree(), opacity); + SetTreeLayerOpacityMutated(layer_id, recycle_tree(), opacity); + } +} + +void LayerTreeHostImpl::SetLayerTransformMutated( + int layer_id, + LayerTreeType tree_type, + const gfx::Transform& transform) { + if (tree_type == LayerTreeType::ACTIVE) { + SetTreeLayerTransformMutated(layer_id, active_tree(), transform); + } else { + SetTreeLayerTransformMutated(layer_id, pending_tree(), transform); + SetTreeLayerTransformMutated(layer_id, recycle_tree(), transform); + } +} + +void LayerTreeHostImpl::SetLayerScrollOffsetMutated( + int layer_id, + LayerTreeType tree_type, + const gfx::ScrollOffset& scroll_offset) { + if (tree_type == LayerTreeType::ACTIVE) { + SetTreeLayerScrollOffsetMutated(layer_id, active_tree(), scroll_offset); + } else { + SetTreeLayerScrollOffsetMutated(layer_id, pending_tree(), scroll_offset); + SetTreeLayerScrollOffsetMutated(layer_id, recycle_tree(), scroll_offset); + } +} + +void LayerTreeHostImpl::ScrollOffsetAnimationFinished() { + ScrollEnd(); +} + +gfx::ScrollOffset LayerTreeHostImpl::GetScrollOffsetForAnimation( + int layer_id) const { + if (active_tree()) { + LayerAnimationValueProvider* layer = active_tree()->LayerById(layer_id); + if (layer) + return layer->ScrollOffsetForAnimation(); + } + + return gfx::ScrollOffset(); +} + } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index 42454a61c00..f66f5b1de83 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -32,11 +32,13 @@ #include "cc/quads/render_pass.h" #include "cc/resources/resource_provider.h" #include "cc/resources/ui_resource_client.h" +#include "cc/scheduler/begin_frame_tracker.h" #include "cc/scheduler/commit_earlyout_reason.h" #include "cc/scheduler/draw_result.h" #include "cc/scheduler/video_frame_controller.h" #include "cc/tiles/tile_manager.h" #include "cc/trees/layer_tree_settings.h" +#include "cc/trees/mutator_host_client.h" #include "cc/trees/proxy.h" #include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkColor.h" @@ -48,6 +50,7 @@ class ScrollOffset; namespace cc { +class AnimationHost; class CompletionEvent; class CompositorFrameMetadata; class DebugRectHistory; @@ -109,15 +112,12 @@ class LayerTreeHostImplClient { virtual void SetVideoNeedsBeginFrames(bool needs_begin_frames) = 0; virtual void PostAnimationEventsToMainThreadOnImplThread( scoped_ptr<AnimationEventsVector> events) = 0; - // Returns true if resources were deleted by this call. - virtual bool ReduceContentsTextureMemoryOnImplThread( - size_t limit_bytes, - int priority_cutoff) = 0; virtual bool IsInsideDraw() = 0; virtual void RenewTreePriority() = 0; virtual void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, base::TimeDelta delay) = 0; virtual void DidActivateSyncTree() = 0; + virtual void WillPrepareTiles() = 0; virtual void DidPrepareTiles() = 0; // Called when page scale animation has completed on the impl thread. @@ -126,6 +126,10 @@ class LayerTreeHostImplClient { // Called when output surface asks for a draw. virtual void OnDrawForOutputSurface() = 0; + virtual void PostFrameTimingEventsOnImplThread( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) = 0; + protected: virtual ~LayerTreeHostImplClient() {} }; @@ -140,6 +144,7 @@ class CC_EXPORT LayerTreeHostImpl public TopControlsManagerClient, public ScrollbarAnimationControllerClient, public VideoFrameControllerClient, + public MutatorHostClient, public base::SupportsWeakPtr<LayerTreeHostImpl> { public: static scoped_ptr<LayerTreeHostImpl> Create( @@ -158,6 +163,8 @@ class CC_EXPORT LayerTreeHostImpl InputHandler::ScrollStatus ScrollBegin( const gfx::Point& viewport_point, InputHandler::ScrollInputType type) override; + InputHandler::ScrollStatus RootScrollBegin( + InputHandler::ScrollInputType type) override; InputHandler::ScrollStatus ScrollAnimated( const gfx::Point& viewport_point, const gfx::Vector2dF& scroll_delta) override; @@ -180,7 +187,7 @@ class CC_EXPORT LayerTreeHostImpl bool anchor_point, float page_scale, base::TimeDelta duration); - void SetNeedsAnimate() override; + void SetNeedsAnimateInput() override; bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point, InputHandler::ScrollInputType type) override; bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) override; @@ -226,7 +233,39 @@ class CC_EXPORT LayerTreeHostImpl void DidAnimateScrollOffset(); void SetViewportDamage(const gfx::Rect& damage_rect); - virtual void PrepareTiles(); + void SetTreeLayerFilterMutated(int layer_id, + LayerTreeImpl* tree, + const FilterOperations& filters); + void SetTreeLayerOpacityMutated(int layer_id, + LayerTreeImpl* tree, + float opacity); + void SetTreeLayerTransformMutated(int layer_id, + LayerTreeImpl* tree, + const gfx::Transform& transform); + void SetTreeLayerScrollOffsetMutated(int layer_id, + LayerTreeImpl* tree, + const gfx::ScrollOffset& scroll_offset); + + // LayerTreeMutatorsClient implementation. + bool IsLayerInTree(int layer_id, LayerTreeType tree_type) const override; + void SetMutatorsNeedCommit() override; + void SetLayerFilterMutated(int layer_id, + LayerTreeType tree_type, + const FilterOperations& filters) override; + void SetLayerOpacityMutated(int layer_id, + LayerTreeType tree_type, + float opacity) override; + void SetLayerTransformMutated(int layer_id, + LayerTreeType tree_type, + const gfx::Transform& transform) override; + void SetLayerScrollOffsetMutated( + int layer_id, + LayerTreeType tree_type, + const gfx::ScrollOffset& scroll_offset) override; + void ScrollOffsetAnimationFinished() override; + gfx::ScrollOffset GetScrollOffsetForAnimation(int layer_id) const override; + + virtual bool PrepareTiles(); // Returns DRAW_SUCCESS unless problems occured preparing the frame, and we // should try to avoid displaying the frame. If PrepareToDraw is called, @@ -250,6 +289,8 @@ class CC_EXPORT LayerTreeHostImpl // Resets all of the trees to an empty state. void ResetTreesForTesting(); + size_t SourceAnimationFrameNumberForTesting() const; + DrawMode GetDrawMode() const; // Viewport size in draw space: this size is in physical pixels and is used @@ -265,6 +306,7 @@ class CC_EXPORT LayerTreeHostImpl // TileManagerClient implementation. void NotifyReadyToActivate() override; void NotifyReadyToDraw() override; + void NotifyAllTileTasksCompleted() override; void NotifyTileStateChanged(const Tile* tile) override; scoped_ptr<RasterTilePriorityQueue> BuildRasterQueue( TreePriority tree_priority, @@ -316,7 +358,6 @@ class CC_EXPORT LayerTreeHostImpl std::string LayerTreeAsJson() const; void FinishAllRendering(); - int SourceAnimationFrameNumber() const; virtual bool InitializeRenderer(scoped_ptr<OutputSurface> output_surface); TileManager* tile_manager() { return tile_manager_.get(); } @@ -388,12 +429,12 @@ class CC_EXPORT LayerTreeHostImpl bool AnimationsAreVisible() { return visible() && CanDraw(); } void SetNeedsCommit() { client_->SetNeedsCommitOnImplThread(); } + void SetNeedsAnimate(); void SetNeedsRedraw(); ManagedMemoryPolicy ActualManagedMemoryPolicy() const; size_t memory_allocation_limit_bytes() const; - int memory_allocation_priority_cutoff() const; void SetViewportSize(const gfx::Size& device_viewport_size); gfx::Size device_viewport_size() const { return device_viewport_size_; } @@ -438,6 +479,7 @@ class CC_EXPORT LayerTreeHostImpl AnimationRegistrar* animation_registrar() const { return animation_registrar_.get(); } + AnimationHost* animation_host() const { return animation_host_.get(); } void SetDebugState(const LayerTreeDebugState& new_debug_state); const LayerTreeDebugState& debug_state() const { return debug_state_; } @@ -451,12 +493,12 @@ class CC_EXPORT LayerTreeHostImpl void SetTreePriority(TreePriority priority); TreePriority GetTreePriority() const; + // TODO(mithro): Remove this methods which exposes the internal + // BeginFrameArgs to external callers. virtual BeginFrameArgs CurrentBeginFrameArgs() const; // Expected time between two begin impl frame calls. - base::TimeDelta begin_impl_frame_interval() const { - return begin_impl_frame_interval_; - } + base::TimeDelta CurrentBeginFrameInterval() const; void AsValueWithFrameInto(FrameData* frame, base::trace_event::TracedValue* value) const; @@ -473,13 +515,12 @@ class CC_EXPORT LayerTreeHostImpl void EvictAllUIResources(); bool EvictedUIResourcesExist() const; - virtual ResourceProvider::ResourceId ResourceIdForUIResource( - UIResourceId uid) const; + virtual ResourceId ResourceIdForUIResource(UIResourceId uid) const; virtual bool IsUIResourceOpaque(UIResourceId uid) const; struct UIResourceData { - ResourceProvider::ResourceId resource_id; + ResourceId resource_id; gfx::Size size; bool opaque; }; @@ -538,6 +579,11 @@ class CC_EXPORT LayerTreeHostImpl const BeginFrameArgs& start_of_main_frame_args, const BeginFrameArgs& expected_next_main_frame_args); + // Post the given frame timing events to the requester. + void PostFrameTimingEvents( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events); + protected: LayerTreeHostImpl( const LayerTreeSettings& settings, @@ -562,6 +608,8 @@ class CC_EXPORT LayerTreeHostImpl LayerTreeHostImplClient* client_; Proxy* proxy_; + BeginFrameTracker current_begin_frame_tracker_; + private: gfx::Vector2dF ScrollLayerWithViewportSpaceDelta( LayerImpl* layer_impl, @@ -569,8 +617,8 @@ class CC_EXPORT LayerTreeHostImpl const gfx::Vector2dF& viewport_delta); void CreateAndSetRenderer(); - void CreateAndSetTileManager(); - void DestroyTileManager(); + void CleanUpTileManager(); + void CreateTileManagerResources(); void ReleaseTreeResources(); void RecreateTreeResources(); @@ -587,6 +635,11 @@ class CC_EXPORT LayerTreeHostImpl // outer if the inner is at its scroll extents. void ScrollViewportInnerFirst(gfx::Vector2dF scroll_delta); + InputHandler::ScrollStatus ScrollBeginImpl( + LayerImpl* scrolling_layer_impl, + InputHandler::ScrollInputType type); + + void AnimateInput(base::TimeTicks monotonic_time); void AnimatePageScale(base::TimeTicks monotonic_time); void AnimateScrollbars(base::TimeTicks monotonic_time); void AnimateTopControls(base::TimeTicks monotonic_time); @@ -617,7 +670,6 @@ class CC_EXPORT LayerTreeHostImpl LayerImpl* layer_impl); void StartScrollbarFadeRecursive(LayerImpl* layer); void SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy); - void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy); void MarkUIResourceNotEvicted(UIResourceId uid); @@ -630,6 +682,12 @@ class CC_EXPORT LayerTreeHostImpl bool ScrollAnimationUpdateTarget(LayerImpl* layer_impl, const gfx::Vector2dF& scroll_delta); + base::SingleThreadTaskRunner* GetTaskRunner() const { + DCHECK(proxy_); + return proxy_->HasImplThread() ? proxy_->ImplThreadTaskRunner() + : proxy_->MainThreadTaskRunner(); + } + typedef base::hash_map<UIResourceId, UIResourceData> UIResourceMap; UIResourceMap ui_resource_map_; @@ -641,11 +699,7 @@ class CC_EXPORT LayerTreeHostImpl scoped_ptr<OutputSurface> output_surface_; - // |resource_provider_| and |tile_manager_| can be NULL, e.g. when using tile- - // free rendering - see OutputSurface::ForcedDrawToSoftwareDevice(). - // |tile_manager_| can also be NULL when raster_enabled is false. scoped_ptr<ResourceProvider> resource_provider_; - scoped_ptr<TileManager> tile_manager_; bool content_is_suitable_for_gpu_rasterization_; bool has_gpu_rasterization_trigger_; bool use_gpu_rasterization_; @@ -686,16 +740,19 @@ class CC_EXPORT LayerTreeHostImpl // The optional delegate for the root layer scroll offset. LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate_; + LayerScrollOffsetDelegate::AnimationCallback root_layer_animation_callback_; + const LayerTreeSettings settings_; LayerTreeDebugState debug_state_; bool visible_; ManagedMemoryPolicy cached_managed_memory_policy_; + scoped_ptr<TileManager> tile_manager_; + gfx::Vector2dF accumulated_root_overscroll_; bool pinch_gesture_active_; bool pinch_gesture_end_should_clear_scrolling_layer_; - gfx::Point previous_pinch_anchor_; scoped_ptr<TopControlsManager> top_controls_manager_; @@ -737,12 +794,8 @@ class CC_EXPORT LayerTreeHostImpl gfx::Rect viewport_damage_rect_; - BeginFrameArgs current_begin_frame_args_; - - // Expected time between two begin impl frame calls. - base::TimeDelta begin_impl_frame_interval_; - scoped_ptr<AnimationRegistrar> animation_registrar_; + scoped_ptr<AnimationHost> animation_host_; std::set<ScrollbarAnimationController*> scrollbar_animation_controllers_; std::set<VideoFrameController*> video_frame_controllers_; diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc index 8ff2f62a1e3..daa179f62eb 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -27,8 +27,8 @@ #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/layers/video_layer_impl.h" +#include "cc/layers/viewport.h" #include "cc/output/begin_frame_args.h" #include "cc/output/compositor_frame_ack.h" #include "cc/output/compositor_frame_metadata.h" @@ -58,14 +58,12 @@ #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/tiles/layer_tiling_data.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" #include "media/base/media.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" @@ -88,9 +86,6 @@ class LayerTreeHostImplTest : public testing::Test, base::ThreadTaskRunnerHandle::Get()), 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), @@ -98,19 +93,15 @@ class LayerTreeHostImplTest : public testing::Test, 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) { + reduce_memory_result_(true) { media::InitializeMediaLibrary(); } 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; settings.gpu_rasterization_enabled = true; return settings; } @@ -149,12 +140,6 @@ class LayerTreeHostImplTest : public testing::Test, void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {} 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, @@ -163,11 +148,16 @@ class LayerTreeHostImplTest : public testing::Test, requested_animation_delay_ = delay; } void DidActivateSyncTree() override {} + void WillPrepareTiles() override {} void DidPrepareTiles() override {} void DidCompletePageScaleAnimationOnImplThread() override { did_complete_page_scale_animation_ = true; } void OnDrawForOutputSurface() override {} + void PostFrameTimingEventsOnImplThread( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) + override {} void set_reduce_memory_result(bool reduce_memory_result) { reduce_memory_result_ = reduce_memory_result; @@ -177,19 +167,21 @@ class LayerTreeHostImplTest : public testing::Test, 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); + &shared_bitmap_manager_, &gpu_memory_buffer_manager_, + &task_graph_runner_, 0); bool init = host_impl_->InitializeRenderer(output_surface.Pass()); host_impl_->SetViewportSize(gfx::Size(10, 10)); + // Set the BeginFrameArgs so that methods which use it are able to. + host_impl_->WillBeginImplFrame( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); 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->draw_properties().visible_layer_rect = gfx::Rect(0, 0, 10, 10); root->SetHasRenderSurface(true); host_impl_->active_tree()->SetRootLayer(root.Pass()); } @@ -200,19 +192,27 @@ class LayerTreeHostImplTest : public testing::Test, ExpectClearedScrollDeltasRecursive(layer->children()[i]); } - static void ExpectContains(const ScrollAndScaleSet& scroll_info, - int id, - const gfx::Vector2d& scroll_delta) { + static ::testing::AssertionResult ScrollInfoContains( + 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); + + if (scroll_delta != scroll_info.scrolls[i].scroll_delta) { + return ::testing::AssertionFailure() + << "Expected " << scroll_delta.ToString() << ", not " + << scroll_info.scrolls[i].scroll_delta.ToString(); + } times_encountered++; } - ASSERT_EQ(1, times_encountered); + if (times_encountered != 1) + return ::testing::AssertionFailure() << "No layer found with id " << id; + return ::testing::AssertionSuccess(); } static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) { @@ -242,7 +242,6 @@ class LayerTreeHostImplTest : public testing::Test, 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); @@ -261,7 +260,6 @@ class LayerTreeHostImplTest : public testing::Test, inner_scroll->SetScrollClipLayer(inner_clip->id()); inner_scroll->SetBounds(content_size); - inner_scroll->SetContentBounds(content_size); inner_scroll->SetPosition(gfx::PointF()); scoped_ptr<LayerImpl> outer_clip = @@ -274,14 +272,12 @@ class LayerTreeHostImplTest : public testing::Test, 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, kContentLayerId); contents->SetDrawsContent(true); contents->SetBounds(content_size); - contents->SetContentBounds(content_size); contents->SetPosition(gfx::PointF()); outer_scroll->AddChild(contents.Pass()); @@ -307,6 +303,34 @@ class LayerTreeHostImplTest : public testing::Test, return scroll_layer; } + // Sets up a typical virtual viewport setup with one child content layer. + // Returns a pointer to the content layer. + LayerImpl* CreateBasicVirtualViewportLayers(const gfx::Size& viewport_size, + const gfx::Size& content_size) { + // CreateScrollAndContentsLayers makes the outer viewport unscrollable and + // the inner a different size from the outer. We'll reuse its layer + // hierarchy but adjust the sizing to our needs. + CreateScrollAndContentsLayers(host_impl_->active_tree(), content_size); + + LayerImpl* content_layer = + host_impl_->OuterViewportScrollLayer()->children().back(); + content_layer->SetBounds(content_size); + host_impl_->OuterViewportScrollLayer()->SetBounds(content_size); + + LayerImpl* outer_clip = host_impl_->OuterViewportScrollLayer()->parent(); + outer_clip->SetBounds(viewport_size); + + LayerImpl* inner_clip_layer = + host_impl_->InnerViewportScrollLayer()->parent()->parent(); + inner_clip_layer->SetBounds(viewport_size); + host_impl_->InnerViewportScrollLayer()->SetBounds(viewport_size); + + host_impl_->SetViewportSize(viewport_size); + host_impl_->active_tree()->DidBecomeActive(); + + return content_layer; + } + // TODO(wjmaclean) Add clip-layer pointer to parameters. scoped_ptr<LayerImpl> CreateScrollableLayer(int id, const gfx::Size& size, @@ -318,7 +342,6 @@ class LayerTreeHostImplTest : public testing::Test, 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(); } @@ -374,32 +397,6 @@ class LayerTreeHostImplTest : public testing::Test, 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); @@ -419,9 +416,9 @@ class LayerTreeHostImplTest : public testing::Test, 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_; + TestSharedBitmapManager shared_bitmap_manager_; + TestGpuMemoryBufferManager gpu_memory_buffer_manager_; + TestTaskGraphRunner task_graph_runner_; scoped_ptr<LayerTreeHostImpl> host_impl_; FakeRenderingStatsInstrumentation stats_instrumentation_; bool on_can_draw_state_changed_called_; @@ -434,8 +431,16 @@ class LayerTreeHostImplTest : public testing::Test, bool reduce_memory_result_; base::Closure animation_task_; base::TimeDelta requested_animation_delay_; - size_t current_limit_bytes_; - int current_priority_cutoff_value_; +}; + +// A test fixture for new animation timelines tests. +class LayerTreeHostImplTimelinesTest : public LayerTreeHostImplTest { + public: + void SetUp() override { + LayerTreeSettings settings = DefaultSettings(); + settings.use_compositor_animation_timelines = true; + CreateHostImpl(settings, CreateOutputSurface()); + } }; TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) { @@ -510,17 +515,19 @@ TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) { scroll_info = host_impl_->ProcessScrollDeltas(); ASSERT_EQ(scroll_info->scrolls.size(), 1u); - ExpectContains(*scroll_info, root->id(), scroll_delta); + EXPECT_TRUE(ScrollInfoContains(*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); + EXPECT_TRUE(ScrollInfoContains(*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); + EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(), + scroll_delta + scroll_delta2)); } TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) { @@ -597,7 +604,8 @@ TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) { 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); + EXPECT_TRUE( + ScrollInfoContains(*scroll_info, scroll_layer->id(), scroll_delta)); } TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) { @@ -646,7 +654,6 @@ TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) { 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()); } @@ -846,7 +853,6 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) { 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(); @@ -887,7 +893,6 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) { 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)); @@ -1020,7 +1025,6 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { 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()); @@ -1126,11 +1130,184 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoom) { scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); - ExpectContains(*scroll_info.get(), scroll_layer->id(), - gfx::Vector2d(0, scroll_delta.y() / page_scale_delta)); + EXPECT_TRUE(ScrollInfoContains( + *scroll_info.get(), scroll_layer->id(), + gfx::Vector2d(0, scroll_delta.y() / page_scale_delta))); } } +TEST_F(LayerTreeHostImplTest, ScrollDuringPinchScrollsInnerViewport) { + LayerTreeSettings settings = DefaultSettings(); + settings.invert_viewport_scroll_order = true; + CreateHostImpl(settings, + CreateOutputSurface()); + + const gfx::Size content_size(1000, 1000); + const gfx::Size viewport_size(500, 500); + CreateBasicVirtualViewportLayers(viewport_size, content_size); + + LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer(); + LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer(); + + EXPECT_VECTOR_EQ( + gfx::Vector2dF(500, 500), + outer_scroll_layer->MaxScrollOffset()); + + host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE); + host_impl_->PinchGestureBegin(); + host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250)); + host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f, 10.f)); + host_impl_->PinchGestureEnd(); + host_impl_->ScrollEnd(); + + EXPECT_VECTOR_EQ( + gfx::Vector2dF(0, 0), + outer_scroll_layer->CurrentScrollOffset()); + EXPECT_VECTOR_EQ( + gfx::Vector2dF(130, 130), + inner_scroll_layer->CurrentScrollOffset()); +} + +// Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when +// a pinch zoom is anchored within a certain margin of the screen edge, we +// should assume the user means to scroll into the edge of the screen. +TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) { + LayerTreeSettings settings = DefaultSettings(); + settings.invert_viewport_scroll_order = true; + CreateHostImpl(settings, + CreateOutputSurface()); + + const gfx::Size content_size(1000, 1000); + const gfx::Size viewport_size(500, 500); + CreateBasicVirtualViewportLayers(viewport_size, content_size); + + int offsetFromEdge = Viewport::kPinchZoomSnapMarginDips - 5; + gfx::Point anchor(viewport_size.width() - offsetFromEdge, + viewport_size.height() - offsetFromEdge); + + // Pinch in within the margins. The scroll should stay exactly locked to the + // bottom and right. + host_impl_->ScrollBegin(anchor, InputHandler::GESTURE); + host_impl_->PinchGestureBegin(); + host_impl_->PinchGestureUpdate(2, anchor); + host_impl_->PinchGestureEnd(); + host_impl_->ScrollEnd(); + + EXPECT_VECTOR_EQ( + gfx::Vector2dF(250, 250), + host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset()); + + // Reset. + host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f); + host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d()); + host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d()); + + // Pinch in within the margins. The scroll should stay exactly locked to the + // top and left. + anchor = gfx::Point(offsetFromEdge, offsetFromEdge); + host_impl_->ScrollBegin(anchor, InputHandler::GESTURE); + host_impl_->PinchGestureBegin(); + host_impl_->PinchGestureUpdate(2, anchor); + host_impl_->PinchGestureEnd(); + host_impl_->ScrollEnd(); + + EXPECT_VECTOR_EQ( + gfx::Vector2dF(0, 0), + host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset()); + + // Reset. + host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f); + host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d()); + host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d()); + + // Pinch in just outside the margin. There should be no snapping. + offsetFromEdge = Viewport::kPinchZoomSnapMarginDips; + anchor = gfx::Point(offsetFromEdge, offsetFromEdge); + host_impl_->ScrollBegin(anchor, InputHandler::GESTURE); + host_impl_->PinchGestureBegin(); + host_impl_->PinchGestureUpdate(2, anchor); + host_impl_->PinchGestureEnd(); + host_impl_->ScrollEnd(); + + EXPECT_VECTOR_EQ( + gfx::Vector2dF(50, 50), + host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset()); + + // Reset. + host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f); + host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d()); + host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d()); + + // Pinch in just outside the margin. There should be no snapping. + offsetFromEdge = Viewport::kPinchZoomSnapMarginDips; + anchor = gfx::Point(viewport_size.width() - offsetFromEdge, + viewport_size.height() - offsetFromEdge); + host_impl_->ScrollBegin(anchor, InputHandler::GESTURE); + host_impl_->PinchGestureBegin(); + host_impl_->PinchGestureUpdate(2, anchor); + host_impl_->PinchGestureEnd(); + host_impl_->ScrollEnd(); + + EXPECT_VECTOR_EQ( + gfx::Vector2dF(200, 200), + host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset()); +} + +TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) { + const gfx::Size content_size(200, 200); + const gfx::Size viewport_size(100, 100); + CreateBasicVirtualViewportLayers(viewport_size, content_size); + + LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer(); + LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer(); + + // Zoom into the page by a 2X factor + float min_page_scale = 1.f, max_page_scale = 4.f; + float page_scale_factor = 2.f; + host_impl_->active_tree()->PushPageScaleFromMainThread( + page_scale_factor, min_page_scale, max_page_scale); + host_impl_->SetPageScaleOnActiveTree(page_scale_factor); + + // Scroll by a small amount, there should be no bubbling up to the inner + // viewport. + host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL); + host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f, 20.f)); + host_impl_->ScrollEnd(); + + EXPECT_VECTOR_EQ( + gfx::Vector2dF(5, 10), + outer_scroll_layer->CurrentScrollOffset()); + EXPECT_VECTOR_EQ( + gfx::Vector2dF(), + inner_scroll_layer->CurrentScrollOffset()); + + // Scroll by the outer viewport's max scroll extent, there the remainder + // should bubble up to the inner viewport. + host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL); + host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f, 200.f)); + host_impl_->ScrollEnd(); + + EXPECT_VECTOR_EQ( + gfx::Vector2dF(100, 100), + outer_scroll_layer->CurrentScrollOffset()); + EXPECT_VECTOR_EQ( + gfx::Vector2dF(5, 10), + inner_scroll_layer->CurrentScrollOffset()); + + // Scroll by the inner viewport's max scroll extent, it should all go to the + // inner viewport. + host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL); + host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f, 80.f)); + host_impl_->ScrollEnd(); + + EXPECT_VECTOR_EQ( + gfx::Vector2dF(100, 100), + outer_scroll_layer->CurrentScrollOffset()); + EXPECT_VECTOR_EQ( + gfx::Vector2dF(50, 50), + inner_scroll_layer->CurrentScrollOffset()); +} + TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) { ui::LatencyInfo latency_info; latency_info.trace_id = 1234; @@ -1342,7 +1519,8 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) { 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)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(), + gfx::Vector2d(-10, -10))); } // Two-finger panning should work when starting fully zoomed out. @@ -1364,7 +1542,8 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) { 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)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(), + gfx::Vector2d(20, 20))); } } @@ -1424,7 +1603,8 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimation) { 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)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(), + gfx::Vector2d(-50, -50))); } // Anchor zoom-out @@ -1463,7 +1643,8 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimation) { 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)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(), + gfx::Vector2d(-50, -50))); } } @@ -1604,7 +1785,8 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) { 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)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(), + gfx::Vector2d(-50, -50))); } TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) { @@ -1646,14 +1828,15 @@ class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl { LayerTreeHostImplClient* client, Proxy* proxy, SharedBitmapManager* manager, + TaskGraphRunner* task_graph_runner, RenderingStatsInstrumentation* rendering_stats_instrumentation) : LayerTreeHostImpl(settings, client, proxy, rendering_stats_instrumentation, manager, - NULL, - NULL, + nullptr, + task_graph_runner, 0) {} BeginFrameArgs CurrentBeginFrameArgs() const override { @@ -1676,9 +1859,9 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { gfx::Size content_size(100, 100); LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = - new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_, - shared_bitmap_manager_.get(), - &stats_instrumentation_); + new LayerTreeHostImplOverridePhysicalTime( + settings, this, &proxy_, &shared_bitmap_manager_, + &task_graph_runner_, &stats_instrumentation_); host_impl_ = make_scoped_ptr(host_impl_override_time); host_impl_->InitializeRenderer(CreateOutputSurface()); host_impl_->SetViewportSize(viewport_size); @@ -1693,14 +1876,12 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { 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, @@ -1728,7 +1909,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { SetupLayers(settings); - base::TimeTicks fake_now = gfx::FrameTime::Now(); + base::TimeTicks fake_now = base::TimeTicks::Now(); EXPECT_FALSE(did_request_animate_); EXPECT_FALSE(did_request_redraw_); @@ -1851,21 +2032,18 @@ void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( 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()); @@ -2058,9 +2236,8 @@ class DidDrawCheckLayer : public LayerImpl { 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); + draw_properties().visible_layer_rect = gfx::Rect(0, 0, 10, 10); } private: @@ -2124,10 +2301,9 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { 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. + // Ensure visible_layer_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; @@ -2141,9 +2317,9 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { EXPECT_FALSE(layer->will_draw_called()); EXPECT_FALSE(layer->did_draw_called()); - EXPECT_TRUE(layer->visible_content_rect().IsEmpty()); + EXPECT_TRUE(layer->visible_layer_rect().IsEmpty()); - // Ensure visible_content_rect for layer is not empty + // Ensure visible_layer_rect for layer is not empty layer->SetPosition(gfx::PointF()); EXPECT_FALSE(layer->will_draw_called()); @@ -2156,7 +2332,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { EXPECT_TRUE(layer->will_draw_called()); EXPECT_TRUE(layer->did_draw_called()); - EXPECT_FALSE(layer->visible_content_rect().IsEmpty()); + EXPECT_FALSE(layer->visible_layer_rect().IsEmpty()); } TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) { @@ -2179,7 +2355,6 @@ TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) { // 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; @@ -2539,8 +2714,6 @@ class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest { : 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_); } @@ -2564,7 +2737,6 @@ class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest { 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); @@ -2593,7 +2765,6 @@ class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest { 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); @@ -2635,7 +2806,6 @@ class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest { 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); @@ -2643,7 +2813,6 @@ class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest { 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); @@ -2848,7 +3017,6 @@ TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) { 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); @@ -3204,8 +3372,6 @@ TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) { 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); @@ -3215,7 +3381,6 @@ TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) { 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()); @@ -3238,7 +3403,6 @@ TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) { 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()); @@ -3362,7 +3526,8 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) { page_scale); scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); - ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta); + EXPECT_TRUE(ScrollInfoContains(*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()); @@ -3418,7 +3583,8 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) { // 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); + EXPECT_TRUE(ScrollInfoContains(*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()); @@ -3458,15 +3624,6 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) { 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; @@ -3494,7 +3651,6 @@ TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) { 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(); @@ -3526,8 +3682,8 @@ TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) { DrawOneFrame(); scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); - ExpectContains( - *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta); + EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_scroll_layer_id, + expected_scroll_delta)); // The scroll range should not have changed. EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll); @@ -3576,10 +3732,12 @@ TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) { // 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)); + EXPECT_TRUE(ScrollInfoContains(*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)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(), + gfx::Vector2d(-3, 0))); } } @@ -3631,7 +3789,8 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) { 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)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(), + gfx::Vector2d(0, -2))); // The child should not have scrolled. ExpectNone(*scroll_info.get(), child->id()); @@ -3649,10 +3808,12 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) { scroll_info = host_impl_->ProcessScrollDeltas(); // The child should have scrolled up to its limit. - ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3)); + EXPECT_TRUE(ScrollInfoContains(*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)); + EXPECT_TRUE(ScrollInfoContains(*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. @@ -3668,11 +3829,12 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) { scroll_info = host_impl_->ProcessScrollDeltas(); // The grand child should have scrolled. - ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5)); + EXPECT_TRUE(ScrollInfoContains(*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)); - + EXPECT_TRUE(ScrollInfoContains(*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); @@ -3689,7 +3851,8 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) { 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)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(), + gfx::Vector2d(0, 4))); } } TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) { @@ -3731,7 +3894,8 @@ TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) { // Only the root scroll should have scrolled. ASSERT_EQ(scroll_info->scrolls.size(), 1u); - ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta); + EXPECT_TRUE( + ScrollInfoContains(*scroll_info.get(), root_scroll_id, scroll_delta)); } } @@ -3792,8 +3956,8 @@ TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) { // 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())); + EXPECT_TRUE(ScrollInfoContains(*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()); @@ -3805,9 +3969,8 @@ TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) { // 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); + EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(), + wheel_scroll_delta)); } TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) { @@ -3820,7 +3983,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) { 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()); + child_layer_id, scroll_layer->bounds(), clip_layer.get()); gfx::Transform rotate_transform; rotate_transform.Translate(-50.0, -50.0); rotate_transform.Rotate(child_layer_angle); @@ -3857,7 +4020,8 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) { 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); + EXPECT_TRUE(ScrollInfoContains(*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. @@ -3879,7 +4043,8 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) { 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); + EXPECT_TRUE(ScrollInfoContains(*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. @@ -3887,9 +4052,83 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) { 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); + EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(), + expected_root_scroll_delta)); + } +} + +TEST_F(LayerTreeHostImplTest, ScrollPerspectiveTransformedLayer) { + // When scrolling an element with perspective, the distance scrolled + // depends on the point at which the scroll begins. + LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); + int child_clip_layer_id = 6; + int child_layer_id = 7; + + // Create a child layer that is rotated on its x axis, with perspective. + 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->bounds(), clip_layer.get()); + LayerImpl* child_ptr = child.get(); + gfx::Transform perspective_transform; + perspective_transform.Translate(-50.0, -50.0); + perspective_transform.ApplyPerspectiveDepth(20); + perspective_transform.RotateAboutXAxis(45); + perspective_transform.Translate(50.0, 50.0); + clip_layer->SetTransform(perspective_transform); + + clip_layer->SetBounds(gfx::Size(child_ptr->bounds().width() / 2, + child_ptr->bounds().height() / 2)); + // The transform 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(), clip_layer->bounds().height(), 0.f)); + clip_layer->AddChild(child.Pass()); + scroll_layer->AddChild(clip_layer.Pass()); + + gfx::Size surface_size(50, 50); + host_impl_->SetViewportSize(surface_size); + + scoped_ptr<ScrollAndScaleSet> scroll_info; + + gfx::Vector2d gesture_scroll_deltas[4]; + gesture_scroll_deltas[0] = gfx::Vector2d(4, 10); + gesture_scroll_deltas[1] = gfx::Vector2d(4, 10); + gesture_scroll_deltas[2] = gfx::Vector2d(10, 0); + gesture_scroll_deltas[3] = gfx::Vector2d(10, 0); + + gfx::Vector2d expected_scroll_deltas[4]; + // Perspective affects the vertical delta by a different + // amount depending on the vertical position of the |viewport_point|. + expected_scroll_deltas[0] = gfx::Vector2d(2, 8); + expected_scroll_deltas[1] = gfx::Vector2d(1, 4); + // Deltas which start with the same vertical position of the + // |viewport_point| are subject to identical perspective effects. + expected_scroll_deltas[2] = gfx::Vector2d(4, 0); + expected_scroll_deltas[3] = gfx::Vector2d(4, 0); + + gfx::Point viewport_point(1, 1); + + // Scroll in screen coordinates with a gesture. Each scroll starts + // where the previous scroll ended, but the scroll position is reset + // for each scroll. + for (int i = 0; i < 4; ++i) { + child_ptr->SetScrollDelta(gfx::Vector2dF()); + DrawFrame(); + EXPECT_EQ(InputHandler::SCROLL_STARTED, + host_impl_->ScrollBegin(viewport_point, InputHandler::GESTURE)); + host_impl_->ScrollBy(viewport_point, gesture_scroll_deltas[i]); + viewport_point += gesture_scroll_deltas[i]; + host_impl_->ScrollEnd(); + + scroll_info = host_impl_->ProcessScrollDeltas(); + EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id, + expected_scroll_deltas[i])); + + // 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); } } @@ -3917,9 +4156,8 @@ TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) { // 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)); + EXPECT_TRUE(ScrollInfoContains(*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()); @@ -3931,9 +4169,8 @@ TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) { // 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); + EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(), + wheel_scroll_delta)); } TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) { @@ -3957,7 +4194,8 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { TestScrollOffsetDelegate() : page_scale_factor_(0.f), min_page_scale_factor_(-1.f), - max_page_scale_factor_(-1.f) {} + max_page_scale_factor_(-1.f), + needs_animate_(false) {} ~TestScrollOffsetDelegate() override {} @@ -3965,7 +4203,11 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { return getter_return_value_; } - bool IsExternalFlingActive() const override { return false; } + bool IsExternalScrollActive() const override { return false; } + + void SetNeedsAnimate(const AnimationCallback&) override { + needs_animate_ = true; + } void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset, const gfx::ScrollOffset& max_scroll_offset, @@ -3985,6 +4227,12 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { set_getter_return_value(last_set_scroll_offset_); } + bool GetAndResetNeedsAnimate() { + bool needs_animate = needs_animate_; + needs_animate_ = false; + return needs_animate; + } + gfx::ScrollOffset last_set_scroll_offset() { return last_set_scroll_offset_; } @@ -4021,8 +4269,10 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { float page_scale_factor_; float min_page_scale_factor_; float max_page_scale_factor_; + bool needs_animate_; }; +// TODO(jdduke): Test root fling animation. TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { TestScrollOffsetDelegate scroll_delegate; host_impl_->SetViewportSize(gfx::Size(10, 20)); @@ -4270,6 +4520,7 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) { TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) { // Scroll child layers beyond their maximum scroll range and make sure root // overscroll does not accumulate. + InputHandlerScrollResult scroll_result; gfx::Size surface_size(10, 10); scoped_ptr<LayerImpl> root_clip = LayerImpl::Create(host_impl_->active_tree(), 4); @@ -4300,7 +4551,9 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) { EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->ScrollBegin(gfx::Point(), InputHandler::NON_BUBBLING_GESTURE)); - host_impl_->ScrollBy(gfx::Point(), scroll_delta); + scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); host_impl_->ScrollEnd(); @@ -4312,7 +4565,9 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) { 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); + scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer); EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); host_impl_->ScrollEnd(); @@ -4324,7 +4579,9 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) { 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); + scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer); EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); host_impl_->ScrollEnd(); @@ -4335,6 +4592,7 @@ 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. + InputHandlerScrollResult scroll_result; gfx::Size surface_size(10, 10); gfx::Size content_size(20, 20); scoped_ptr<LayerImpl> root_clip = @@ -4361,17 +4619,24 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) { 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); + scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); - host_impl_->ScrollBy(gfx::Point(), scroll_delta); + scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll()); - host_impl_->ScrollBy(gfx::Point(), scroll_delta); + scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta); + EXPECT_FALSE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll()); host_impl_->ScrollEnd(); } } TEST_F(LayerTreeHostImplTest, OverscrollAlways) { + InputHandlerScrollResult scroll_result; LayerTreeSettings settings; CreateHostImpl(settings, CreateOutputSurface()); @@ -4386,11 +4651,14 @@ TEST_F(LayerTreeHostImplTest, OverscrollAlways) { // 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)); + 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), host_impl_->accumulated_root_overscroll()); } TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) { + InputHandlerScrollResult scroll_result; gfx::Size surface_size(980, 1439); gfx::Size content_size(980, 1438); float device_scale_factor = 1.5f; @@ -4424,7 +4692,9 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) { // 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)); + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1)); + EXPECT_FALSE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); EXPECT_EQ(gfx::Vector2dF().ToString(), host_impl_->accumulated_root_overscroll().ToString()); @@ -4433,6 +4703,7 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) { } TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) { + InputHandlerScrollResult scroll_result; gfx::Size surface_size(100, 100); gfx::Size content_size(200, 200); scoped_ptr<LayerImpl> root_clip = @@ -4461,10 +4732,15 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) { // 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)); + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); EXPECT_EQ(gfx::Vector2dF().ToString(), host_impl_->accumulated_root_overscroll().ToString()); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f)); + scroll_result = + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); EXPECT_EQ(gfx::Vector2dF().ToString(), host_impl_->accumulated_root_overscroll().ToString()); host_impl_->ScrollEnd(); @@ -4474,11 +4750,16 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) { 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)); + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); 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)); + scroll_result = + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f)); + EXPECT_FALSE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(), host_impl_->accumulated_root_overscroll().ToString()); host_impl_->ScrollEnd(); @@ -4486,7 +4767,10 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) { // 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)); + scroll_result = + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f)); + EXPECT_FALSE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); EXPECT_EQ(gfx::Vector2dF().ToString(), host_impl_->accumulated_root_overscroll().ToString()); host_impl_->ScrollEnd(); @@ -4564,7 +4848,6 @@ class BlendStateCheckLayer : public LayerImpl { RGBA_8888)) { resource_provider->AllocateForTesting(resource_id_); SetBounds(gfx::Size(10, 10)); - SetContentBounds(gfx::Size(10, 10)); SetDrawsContent(true); } @@ -4574,7 +4857,7 @@ class BlendStateCheckLayer : public LayerImpl { gfx::Rect quad_rect_; gfx::Rect opaque_content_rect_; gfx::Rect quad_visible_rect_; - ResourceProvider::ResourceId resource_id_; + ResourceId resource_id_; }; TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { @@ -4582,7 +4865,6 @@ 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()); @@ -4602,7 +4884,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // Opaque layer, drawn without blending. layer1->SetContentsOpaque(true); layer1->SetExpectation(false, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4611,7 +4893,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // Layer with translucent content and painting, so drawn with blending. layer1->SetContentsOpaque(false); layer1->SetExpectation(true, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4621,7 +4903,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetContentsOpaque(true); layer1->SetOpacity(0.5f); layer1->SetExpectation(true, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4631,7 +4913,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetContentsOpaque(true); layer1->SetOpacity(0.5f); layer1->SetExpectation(true, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4649,11 +4931,11 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetContentsOpaque(true); layer1->SetOpacity(1.f); layer1->SetExpectation(false, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetContentsOpaque(true); layer2->SetOpacity(1.f); layer2->SetExpectation(false, false); - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4664,9 +4946,9 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // Child layer with opaque content, drawn without blending. layer1->SetContentsOpaque(false); layer1->SetExpectation(true, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetExpectation(false, false); - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4678,9 +4960,9 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // Child layer with opaque content, drawn without blending. layer1->SetContentsOpaque(true); layer1->SetExpectation(false, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetExpectation(false, false); - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4696,9 +4978,9 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetOpacity(0.5f); layer1->SetHasRenderSurface(true); layer1->SetExpectation(false, true); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetExpectation(false, false); - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); FakeLayerTreeHostImpl::RecursiveUpdateNumChildren( host_impl_->active_tree()->root_layer()); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); @@ -4713,11 +4995,11 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetContentsOpaque(true); layer1->SetOpacity(1.f); layer1->SetExpectation(false, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetContentsOpaque(true); layer2->SetOpacity(0.5f); layer2->SetExpectation(true, false); - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4728,11 +5010,11 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetContentsOpaque(true); layer1->SetOpacity(1.f); layer1->SetExpectation(false, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetContentsOpaque(false); layer2->SetOpacity(1.f); layer2->SetExpectation(true, false); - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4744,11 +5026,11 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetContentsOpaque(true); layer1->SetOpacity(1.f); layer1->SetExpectation(false, false); - layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetContentsOpaque(true); layer2->SetOpacity(1.f); layer2->SetExpectation(false, false); - layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); + layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4761,7 +5043,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { 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())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4773,7 +5055,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { 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())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4785,7 +5067,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { 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())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4798,7 +5080,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { 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())); + layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); EXPECT_TRUE(layer1->quads_appended()); @@ -4839,7 +5121,6 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { 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())); @@ -4860,7 +5141,6 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { 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())); @@ -4881,7 +5161,6 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { 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())); @@ -4903,7 +5182,6 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { 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())); @@ -5069,7 +5347,6 @@ TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) { 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()); @@ -5128,8 +5405,10 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl = LayerTreeHostImpl::Create( settings, this, &proxy_, &stats_instrumentation_, - shared_bitmap_manager_.get(), NULL, task_graph_runner_.get(), 0); + &shared_bitmap_manager_, NULL, &task_graph_runner_, 0); layer_tree_host_impl->InitializeRenderer(output_surface.Pass()); + layer_tree_host_impl->WillBeginImplFrame( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500)); scoped_ptr<LayerImpl> root = @@ -5139,10 +5418,8 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { 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()); @@ -5196,10 +5473,8 @@ TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) { 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()); @@ -5227,7 +5502,7 @@ class FakeLayerWithQuads : public LayerImpl { PopulateSharedQuadState(shared_quad_state); SkColor gray = SkColorSetRGB(100, 100, 100); - gfx::Rect quad_rect(content_bounds()); + gfx::Rect quad_rect(bounds()); gfx::Rect visible_quad_rect(quad_rect); SolidColorDrawQuad* my_quad = render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -5406,6 +5681,7 @@ static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity( LayerTreeHostImplClient* client, Proxy* proxy, SharedBitmapManager* manager, + TaskGraphRunner* task_graph_runner, RenderingStatsInstrumentation* stats_instrumentation) { scoped_refptr<TestContextProvider> provider(TestContextProvider::Create()); scoped_ptr<OutputSurface> output_surface( @@ -5415,9 +5691,12 @@ static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity( 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); + scoped_ptr<LayerTreeHostImpl> my_host_impl = + LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation, + manager, nullptr, task_graph_runner, 0); my_host_impl->InitializeRenderer(output_surface.Pass()); + my_host_impl->WillBeginImplFrame( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); my_host_impl->SetViewportSize(gfx::Size(100, 100)); /* @@ -5452,23 +5731,20 @@ static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity( 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->draw_properties().visible_layer_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->draw_properties().visible_layer_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->draw_properties().visible_layer_rect = grand_child_rect; grand_child->SetDrawsContent(true); child->AddChild(grand_child.Pass()); @@ -5479,14 +5755,11 @@ static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity( } TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) { - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; scoped_ptr<LayerTreeHostImpl> my_host_impl = - SetupLayersForOpacity(true, - this, - &proxy_, - shared_bitmap_manager.get(), - &stats_instrumentation_); + SetupLayersForOpacity(true, this, &proxy_, &shared_bitmap_manager, + &task_graph_runner, &stats_instrumentation_); { LayerTreeHostImpl::FrameData frame; EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); @@ -5506,14 +5779,11 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) { } TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) { - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; scoped_ptr<LayerTreeHostImpl> my_host_impl = - SetupLayersForOpacity(false, - this, - &proxy_, - shared_bitmap_manager.get(), - &stats_instrumentation_); + SetupLayersForOpacity(false, this, &proxy_, &shared_bitmap_manager, + &task_graph_runner, &stats_instrumentation_); { LayerTreeHostImpl::FrameData frame; EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); @@ -5553,14 +5823,12 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create( host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0); video_layer->SetBounds(gfx::Size(10, 10)); - video_layer->SetContentBounds(gfx::Size(10, 10)); video_layer->SetDrawsContent(true); root_layer->AddChild(video_layer.Pass()); 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()); @@ -5627,46 +5895,6 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) { 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: @@ -5695,12 +5923,12 @@ class LayerTreeHostImplTestWithDelegatingRenderer 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()); + gfx::RectF expected_child_visible_rect(child->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()); + gfx::RectF expected_root_visible_rect(root->bounds()); EXPECT_EQ(expected_root_visible_rect, root_render_pass->quad_list.ElementAt(1)->visible_rect); } @@ -5716,7 +5944,6 @@ TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) { 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); @@ -5725,7 +5952,6 @@ TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) { 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()); @@ -5761,7 +5987,7 @@ class FakeMaskLayerImpl : public LayerImpl { return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id)); } - void GetContentsResourceId(ResourceProvider::ResourceId* resource_id, + void GetContentsResourceId(ResourceId* resource_id, gfx::Size* resource_size) const override { *resource_id = 0; } @@ -5834,9 +6060,14 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) { ASSERT_LE(1u, frame.render_passes[0]->quad_list.size()); const DrawQuad* quad = frame.render_passes[0]->quad_list.front(); + bool clipped = false, force_aa = false; + gfx::QuadF device_layer_quad = MathUtil::MapQuad( + quad->shared_quad_state->quad_to_target_transform, + gfx::QuadF(quad->shared_quad_state->visible_quad_layer_rect), &clipped); + EXPECT_FALSE(clipped); bool antialiased = GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad( - quad->quadTransform(), quad, false); + device_layer_quad, clipped, force_aa); EXPECT_FALSE(antialiased); host_impl_->DrawLayers(&frame); @@ -5949,7 +6180,6 @@ TEST_F(LayerTreeHostImplTest, scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create( host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0); video_layer->SetBounds(gfx::Size(10, 10)); - video_layer->SetContentBounds(gfx::Size(10, 10)); video_layer->SetDrawsContent(true); root_layer->AddChild(video_layer.Pass()); SetupRootLayerImpl(root_layer.Pass()); @@ -5968,9 +6198,8 @@ TEST_F(LayerTreeHostImplTest, 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); + settings, this, &proxy_, &stats_instrumentation_, &shared_bitmap_manager_, + &gpu_memory_buffer_manager_, &task_graph_runner_, 0); scoped_ptr<OutputSurface> output_surface( FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create())); @@ -5978,51 +6207,6 @@ TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) { 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; - CreateHostImpl(settings, CreateOutputSurface()); - host_impl_->SetContentIsSuitableForGpuRasterization(true); - host_impl_->SetHasGpuRasterizationTrigger(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()); @@ -6076,12 +6260,9 @@ TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) { 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()); + fake_host_impl_ = + new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_, + &shared_bitmap_manager_, &task_graph_runner_); host_impl_.reset(fake_host_impl_); host_impl_->InitializeRenderer(CreateOutputSurface()); host_impl_->SetViewportSize(gfx::Size(10, 10)); @@ -6111,16 +6292,14 @@ TEST_F(LayerTreeHostImplTest, UIResourceManagement) { 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); + 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); + ResourceId id2 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id2); EXPECT_NE(id1, id2); @@ -6163,8 +6342,7 @@ TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { 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); + ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id1); } @@ -6288,7 +6466,8 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) { // 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_TRUE( + ScrollInfoContains(*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 @@ -6296,8 +6475,9 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) { 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_TRUE( + ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(), scroll_delta)); EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child); // The first |ScrollBy| after the fling should re-lock the scrolling @@ -6309,8 +6489,10 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) { // 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); + EXPECT_TRUE( + ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta)); + EXPECT_TRUE(ScrollInfoContains(*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); @@ -6357,7 +6539,8 @@ TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) { // The root should have scrolled. ASSERT_EQ(2u, scroll_info->scrolls.size()); - ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10)); + EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll_id, + gfx::Vector2d(0, 10))); } } @@ -6381,7 +6564,6 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) { 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. @@ -6410,7 +6592,6 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) { 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; @@ -6482,7 +6663,6 @@ TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) { 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)); @@ -6519,7 +6699,6 @@ TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) { 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)); @@ -6561,7 +6740,6 @@ TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) { 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); @@ -6602,7 +6780,6 @@ TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) { 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); @@ -6918,7 +7095,7 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) { // The top controls should properly animate until finished, despite the scroll // offset being at the origin. - base::TimeTicks animation_time = gfx::FrameTime::Now(); + base::TimeTicks animation_time = base::TimeTicks::Now(); while (did_request_animate_) { did_request_redraw_ = false; did_request_animate_ = false; @@ -6988,7 +7165,7 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) { EXPECT_FALSE(did_request_commit_); // Animate the top controls to the limit. - base::TimeTicks animation_time = gfx::FrameTime::Now(); + base::TimeTicks animation_time = base::TimeTicks::Now(); while (did_request_animate_) { did_request_redraw_ = false; did_request_animate_ = false; @@ -7052,7 +7229,7 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, EXPECT_FALSE(did_request_commit_); // Animate the top controls to the limit. - base::TimeTicks animation_time = gfx::FrameTime::Now(); + base::TimeTicks animation_time = base::TimeTicks::Now(); while (did_request_animate_) { did_request_redraw_ = false; did_request_animate_ = false; @@ -7163,7 +7340,6 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { 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 = @@ -7176,14 +7352,12 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { 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()); @@ -7256,13 +7430,17 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) { // Make sure the fling goes to the outer viewport first EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); + EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer()); EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); + EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer()); 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()); + EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), outer_scroll); host_impl_->ScrollEnd(); + EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer()); EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); @@ -7270,15 +7448,20 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) { // 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(outer_scroll, host_impl_->CurrentlyScrollingLayer()); EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); + EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer()); host_impl_->ScrollBy(gfx::Point(), scroll_delta); outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y()); + EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer()); host_impl_->ScrollBy(gfx::Point(), scroll_delta); inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y()); + EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer()); host_impl_->ScrollEnd(); + EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer()); EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); @@ -7366,7 +7549,8 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, // 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_TRUE( + ScrollInfoContains(*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 @@ -7380,8 +7564,10 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, // 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); + EXPECT_TRUE( + ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta)); + EXPECT_TRUE( + ScrollInfoContains(*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); @@ -7392,6 +7578,34 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, } } +TEST_F(LayerTreeHostImplVirtualViewportTest, + ScrollBeginEventThatTargetsViewportLayerSkipsHitTest) { + 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(); + + EXPECT_EQ(InputHandler::SCROLL_STARTED, + host_impl_->RootScrollBegin(InputHandler::GESTURE)); + EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll); + host_impl_->ScrollEnd(); + EXPECT_EQ(InputHandler::SCROLL_STARTED, + host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); + EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll); + host_impl_->ScrollEnd(); +} + class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest { public: void SetUp() override { @@ -7486,6 +7700,49 @@ TEST_F(LayerTreeHostImplTest, ScrollAnimated) { EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer()); } +// Evolved from LayerTreeHostImplTest.ScrollAnimated. +TEST_F(LayerTreeHostImplTimelinesTest, 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, InvalidLayerNotAddedToRasterQueue) { host_impl_->CreatePendingTree(); @@ -7778,6 +8035,8 @@ class FakeVideoFrameController : public VideoFrameController { }; TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) { + host_impl_->DidFinishImplFrame(); + BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE); FakeVideoFrameController controller; @@ -7801,6 +8060,8 @@ TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) { } TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) { + host_impl_->DidFinishImplFrame(); + BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE); FakeVideoFrameController controller; @@ -7884,5 +8145,40 @@ TEST_F(LayerTreeHostImplTest, GpuRasterizationStatusModes) { EXPECT_TRUE(host_impl_->use_gpu_rasterization()); } +// A mock output surface which lets us detect calls to ForceReclaimResources. +class MockReclaimResourcesOutputSurface : public FakeOutputSurface { + public: + static scoped_ptr<MockReclaimResourcesOutputSurface> Create3d() { + return make_scoped_ptr(new MockReclaimResourcesOutputSurface( + TestContextProvider::Create(), TestContextProvider::Create(), false)); + } + + MOCK_METHOD0(ForceReclaimResources, void()); + + protected: + MockReclaimResourcesOutputSurface( + scoped_refptr<ContextProvider> context_provider, + scoped_refptr<ContextProvider> worker_context_provider, + bool delegated_rendering) + : FakeOutputSurface(context_provider, + worker_context_provider, + delegated_rendering) {} +}; + +// Display::Draw (and the planned Display Scheduler) currently rely on resources +// being reclaimed to block drawing between BeginCommit / Swap. This test +// ensures that BeginCommit triggers ForceReclaimResources. See +// crbug.com/489515. +TEST_F(LayerTreeHostImplTest, BeginCommitReclaimsResources) { + scoped_ptr<MockReclaimResourcesOutputSurface> output_surface( + MockReclaimResourcesOutputSurface::Create3d()); + // Hold an unowned pointer to the output surface to use for mock expectations. + MockReclaimResourcesOutputSurface* mock_output_surface = output_surface.get(); + + CreateHostImpl(DefaultSettings(), output_surface.Pass()); + EXPECT_CALL(*mock_output_surface, ForceReclaimResources()).Times(1); + host_impl_->BeginCommit(); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc index c8e2a8c02c1..eb8183fadf2 100644 --- a/chromium/cc/trees/layer_tree_host_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_perftest.cc @@ -12,7 +12,6 @@ #include "base/strings/string_piece.h" #include "base/time/time.h" #include "cc/debug/lap_timer.h" -#include "cc/layers/content_layer.h" #include "cc/layers/nine_patch_layer.h" #include "cc/layers/solid_color_layer.h" #include "cc/layers/texture_layer.h" @@ -45,7 +44,7 @@ class LayerTreeHostPerfTest : public LayerTreeTest { } void InitializeSettings(LayerTreeSettings* settings) override { - settings->throttle_frame_production = false; + settings->renderer_settings.disable_gpu_vsync = true; } void BeginTest() override { @@ -148,13 +147,13 @@ class LayerTreeHostPerfTestJsonReader : public LayerTreeHostPerfTest { TEST_F(LayerTreeHostPerfTestJsonReader, TenTenSingleThread) { SetTestName("10_10_single_thread"); ReadTestFile("10_10_layer_tree"); - RunTest(false, false, false); + RunTest(false, false); } -TEST_F(LayerTreeHostPerfTestJsonReader, TenTenThreadedImplSide) { +TEST_F(LayerTreeHostPerfTestJsonReader, TenTenThreaded) { SetTestName("10_10_threaded_impl_side"); ReadTestFile("10_10_layer_tree"); - RunTestWithImplSidePainting(); + RunTest(true, false); } // Simulates a tab switcher scene with two stacks of 10 tabs each. @@ -163,15 +162,14 @@ TEST_F(LayerTreeHostPerfTestJsonReader, full_damage_each_frame_ = true; SetTestName("10_10_single_thread_full_damage_each_frame"); ReadTestFile("10_10_layer_tree"); - RunTest(false, false, false); + RunTest(false, false); } -TEST_F(LayerTreeHostPerfTestJsonReader, - TenTenThreadedImplSide_FullDamageEachFrame) { +TEST_F(LayerTreeHostPerfTestJsonReader, TenTenThreaded_FullDamageEachFrame) { full_damage_each_frame_ = true; SetTestName("10_10_threaded_impl_side_full_damage_each_frame"); ReadTestFile("10_10_layer_tree"); - RunTestWithImplSidePainting(); + RunTest(true, false); } // Invalidates a leaf layer in the tree on the main thread after every commit. @@ -205,13 +203,13 @@ class LayerTreeHostPerfTestLeafInvalidates TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenSingleThread) { SetTestName("10_10_single_thread_leaf_invalidates"); ReadTestFile("10_10_layer_tree"); - RunTest(false, false, false); + RunTest(false, false); } -TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenThreadedImplSide) { +TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenThreaded) { SetTestName("10_10_threaded_impl_side_leaf_invalidates"); ReadTestFile("10_10_layer_tree"); - RunTestWithImplSidePainting(); + RunTest(true, false); } // Simulates main-thread scrolling on each frame. @@ -246,18 +244,18 @@ TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageSingleThread) { // crbug.com/444219 is fixed. bool old_verify_property_trees = verify_property_trees(); set_verify_property_trees(false); - RunTest(false, false, false); + RunTest(false, false); set_verify_property_trees(old_verify_property_trees); } -TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageThreadedImplSide) { +TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageThreaded) { SetTestName("long_scrollable_page_threaded_impl_side"); ReadTestFile("long_scrollable_page"); // TODO(vollick): Remove verify_property_trees setting after // crbug.com/444219 is fixed. bool old_verify_property_trees = verify_property_trees(); set_verify_property_trees(false); - RunTestWithImplSidePainting(); + RunTest(true, false); set_verify_property_trees(old_verify_property_trees); } @@ -327,20 +325,20 @@ class BrowserCompositorInvalidateLayerTreePerfTest bool clean_up_started_; }; -TEST_F(BrowserCompositorInvalidateLayerTreePerfTest, DenseBrowserUI) { +TEST_F(BrowserCompositorInvalidateLayerTreePerfTest, DenseBrowserUIThreaded) { measure_commit_cost_ = true; SetTestName("dense_layer_tree"); ReadTestFile("dense_layer_tree"); - RunTestWithImplSidePainting(); + RunTest(true, false); } // Simulates a page with several large, transformed and animated layers. -TEST_F(LayerTreeHostPerfTestJsonReader, HeavyPageThreadedImplSide) { +TEST_F(LayerTreeHostPerfTestJsonReader, HeavyPageThreaded) { begin_frame_driven_drawing_ = true; measure_commit_cost_ = true; SetTestName("heavy_page"); ReadTestFile("heavy_layer_tree"); - RunTestWithImplSidePainting(); + RunTest(true, false); } } // namespace diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc index b31d3e85395..e2715e3907c 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc @@ -137,7 +137,8 @@ class LayerTreeHostBlendingPixelTest : public LayerTreeHostPixelResourceTest { canvas.drawRect( SkRect::MakeXYWH(0, i * kLaneHeight, kLaneWidth, kLaneHeight), paint); } - scoped_refptr<PictureImageLayer> layer = PictureImageLayer::Create(); + scoped_refptr<PictureImageLayer> layer = + PictureImageLayer::Create(layer_settings()); layer->SetIsDrawable(true); layer->SetBounds(gfx::Size(width, height)); layer->SetBitmap(backing_store); @@ -147,7 +148,8 @@ class LayerTreeHostBlendingPixelTest : public LayerTreeHostPixelResourceTest { void SetupMaskLayer(scoped_refptr<Layer> layer) { const int kMaskOffset = 2; gfx::Size bounds = layer->bounds(); - scoped_refptr<PictureImageLayer> mask = PictureImageLayer::Create(); + scoped_refptr<PictureImageLayer> mask = + PictureImageLayer::Create(layer_settings()); mask->SetIsDrawable(true); mask->SetIsMask(true); mask->SetBounds(bounds); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc index 0cb6aeaa846..6a4bebd4f35 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -46,11 +46,11 @@ class MaskContentLayerClient : public ContentLayerClient { } } - void PaintContentsToDisplayList( - DisplayItemList* display_list, + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { NOTIMPLEMENTED(); + return nullptr; } private: @@ -67,7 +67,8 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfLayer) { gfx::Size mask_bounds(50, 50); MaskContentLayerClient client(mask_bounds); - scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> mask = + PictureLayer::Create(layer_settings(), &client); mask->SetBounds(mask_bounds); mask->SetIsDrawable(true); mask->SetIsMask(true); @@ -83,7 +84,8 @@ TEST_P(LayerTreeHostMasksPixelTest, ImageMaskOfLayer) { gfx::Size mask_bounds(50, 50); - scoped_refptr<PictureImageLayer> mask = PictureImageLayer::Create(); + scoped_refptr<PictureImageLayer> mask = + PictureImageLayer::Create(layer_settings()); mask->SetIsDrawable(true); mask->SetIsMask(true); mask->SetBounds(mask_bounds); @@ -111,7 +113,7 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfClippedLayer) { gfx::Rect(100, 100), SK_ColorWHITE); // Clip to the top half of the green layer. - scoped_refptr<Layer> clip = Layer::Create(); + scoped_refptr<Layer> clip = Layer::Create(layer_settings()); clip->SetPosition(gfx::Point(0, 0)); clip->SetBounds(gfx::Size(100, 50)); clip->SetMasksToBounds(true); @@ -123,7 +125,8 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfClippedLayer) { gfx::Size mask_bounds(50, 50); MaskContentLayerClient client(mask_bounds); - scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> mask = + PictureLayer::Create(layer_settings(), &client); mask->SetBounds(mask_bounds); mask->SetIsDrawable(true); mask->SetIsMask(true); @@ -140,7 +143,8 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplica) { gfx::Size mask_bounds(50, 50); MaskContentLayerClient client(mask_bounds); - scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> mask = + PictureLayer::Create(layer_settings(), &client); mask->SetBounds(mask_bounds); mask->SetIsDrawable(true); mask->SetIsMask(true); @@ -153,7 +157,7 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplica) { gfx::Transform replica_transform; replica_transform.Rotate(-90.0); - scoped_refptr<Layer> replica = Layer::Create(); + scoped_refptr<Layer> replica = Layer::Create(layer_settings()); replica->SetTransformOrigin(gfx::Point3F(25.f, 25.f, 0.f)); replica->SetPosition(gfx::Point(50, 50)); replica->SetTransform(replica_transform); @@ -169,14 +173,15 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplicaOfClippedLayer) { gfx::Size mask_bounds(50, 50); MaskContentLayerClient client(mask_bounds); - scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> mask = + PictureLayer::Create(layer_settings(), &client); mask->SetBounds(mask_bounds); mask->SetIsDrawable(true); mask->SetIsMask(true); // Clip to the bottom half of the green layer, and the left half of the // replica. - scoped_refptr<Layer> clip = Layer::Create(); + scoped_refptr<Layer> clip = Layer::Create(layer_settings()); clip->SetPosition(gfx::Point(0, 25)); clip->SetBounds(gfx::Size(75, 75)); clip->SetMasksToBounds(true); @@ -190,7 +195,7 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplicaOfClippedLayer) { gfx::Transform replica_transform; replica_transform.Rotate(-90.0); - scoped_refptr<Layer> replica = Layer::Create(); + scoped_refptr<Layer> replica = Layer::Create(layer_settings()); replica->SetTransformOrigin(gfx::Point3F(25.f, 25.f, 0.f)); replica->SetPosition(gfx::Point(50, 50)); replica->SetTransform(replica_transform); @@ -207,7 +212,8 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfReplica) { gfx::Size mask_bounds(50, 50); MaskContentLayerClient client(mask_bounds); - scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> mask = + PictureLayer::Create(layer_settings(), &client); mask->SetBounds(mask_bounds); mask->SetIsDrawable(true); mask->SetIsMask(true); @@ -224,7 +230,7 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfReplica) { replica_transform.Rotate(180.0); replica_transform.Translate(50.0, 0.0); - scoped_refptr<Layer> replica = Layer::Create(); + scoped_refptr<Layer> replica = Layer::Create(layer_settings()); replica->SetTransformOrigin(gfx::Point3F(50.f, 50.f, 0.f)); replica->SetPosition(gfx::Point()); replica->SetTransform(replica_transform); @@ -241,13 +247,14 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfReplicaOfClippedLayer) { gfx::Size mask_bounds(50, 50); MaskContentLayerClient client(mask_bounds); - scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> mask = + PictureLayer::Create(layer_settings(), &client); mask->SetBounds(mask_bounds); mask->SetIsDrawable(true); mask->SetIsMask(true); // Clip to the bottom 3/4 of the green layer, and the top 3/4 of the replica. - scoped_refptr<Layer> clip = Layer::Create(); + scoped_refptr<Layer> clip = Layer::Create(layer_settings()); clip->SetPosition(gfx::Point(0, 12)); clip->SetBounds(gfx::Size(100, 75)); clip->SetMasksToBounds(true); @@ -265,7 +272,7 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfReplicaOfClippedLayer) { replica_transform.Rotate(180.0); replica_transform.Translate(50.0, 0.0); - scoped_refptr<Layer> replica = Layer::Create(); + scoped_refptr<Layer> replica = Layer::Create(layer_settings()); replica->SetTransformOrigin(gfx::Point3F(50.f, 50.f, 0.f)); replica->SetPosition(gfx::Point()); replica->SetTransform(replica_transform); @@ -303,11 +310,11 @@ class CheckerContentLayerClient : public ContentLayerClient { } } } - void PaintContentsToDisplayList( - DisplayItemList* display_list, + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { NOTIMPLEMENTED(); + return nullptr; } private: @@ -334,11 +341,11 @@ class CircleContentLayerClient : public ContentLayerClient { bounds_.width() / 4, paint); } - void PaintContentsToDisplayList( - DisplayItemList* display_list, + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { NOTIMPLEMENTED(); + return nullptr; } private: @@ -369,7 +376,8 @@ TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, gfx::Size picture_bounds(100, 100); CheckerContentLayerClient picture_client(picture_bounds, SK_ColorGREEN, true); - scoped_refptr<PictureLayer> picture = PictureLayer::Create(&picture_client); + scoped_refptr<PictureLayer> picture = + PictureLayer::Create(layer_settings(), &picture_client); picture->SetBounds(picture_bounds); picture->SetIsDrawable(true); @@ -384,7 +392,8 @@ TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, gfx::Size mask_bounds(100, 100); CircleContentLayerClient mask_client(mask_bounds); - scoped_refptr<PictureLayer> mask = PictureLayer::Create(&mask_client); + scoped_refptr<PictureLayer> mask = + PictureLayer::Create(layer_settings(), &mask_client); mask->SetBounds(mask_bounds); mask->SetIsDrawable(true); mask->SetIsMask(true); @@ -417,14 +426,14 @@ TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, CheckerContentLayerClient picture_client_vertical( picture_bounds, SK_ColorGREEN, true); scoped_refptr<PictureLayer> picture_vertical = - PictureLayer::Create(&picture_client_vertical); + PictureLayer::Create(layer_settings(), &picture_client_vertical); picture_vertical->SetBounds(picture_bounds); picture_vertical->SetIsDrawable(true); CheckerContentLayerClient picture_client_horizontal( picture_bounds, SK_ColorMAGENTA, false); scoped_refptr<PictureLayer> picture_horizontal = - PictureLayer::Create(&picture_client_horizontal); + PictureLayer::Create(layer_settings(), &picture_client_horizontal); picture_horizontal->SetBounds(picture_bounds); picture_horizontal->SetIsDrawable(true); picture_horizontal->SetContentsOpaque(false); @@ -435,7 +444,8 @@ TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, gfx::Size mask_bounds(128, 128); CircleContentLayerClient mask_client(mask_bounds); - scoped_refptr<PictureLayer> mask = PictureLayer::Create(&mask_client); + scoped_refptr<PictureLayer> mask = + PictureLayer::Create(layer_settings(), &mask_client); mask->SetBounds(mask_bounds); mask->SetIsDrawable(true); mask->SetIsMask(true); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc index b3729047aa5..6af0bb2f8d0 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc @@ -485,18 +485,18 @@ class LayerTreeHostReadbackDeviceScalePixelTest TEST_P(LayerTreeHostReadbackDeviceScalePixelTest, ReadbackSubrect) { scoped_refptr<FakePictureLayer> background = - FakePictureLayer::Create(&white_client_); + FakePictureLayer::Create(layer_settings(), &white_client_); background->SetBounds(gfx::Size(100, 100)); background->SetIsDrawable(true); scoped_refptr<FakePictureLayer> green = - FakePictureLayer::Create(&green_client_); + FakePictureLayer::Create(layer_settings(), &green_client_); green->SetBounds(gfx::Size(100, 100)); green->SetIsDrawable(true); background->AddChild(green); scoped_refptr<FakePictureLayer> blue = - FakePictureLayer::Create(&blue_client_); + FakePictureLayer::Create(layer_settings(), &blue_client_); blue->SetPosition(gfx::Point(50, 50)); blue->SetBounds(gfx::Size(25, 25)); blue->SetIsDrawable(true); @@ -512,19 +512,19 @@ TEST_P(LayerTreeHostReadbackDeviceScalePixelTest, ReadbackSubrect) { TEST_P(LayerTreeHostReadbackDeviceScalePixelTest, ReadbackNonRootLayerSubrect) { scoped_refptr<FakePictureLayer> background = - FakePictureLayer::Create(&white_client_); + FakePictureLayer::Create(layer_settings(), &white_client_); background->SetBounds(gfx::Size(100, 100)); background->SetIsDrawable(true); scoped_refptr<FakePictureLayer> green = - FakePictureLayer::Create(&green_client_); + FakePictureLayer::Create(layer_settings(), &green_client_); green->SetPosition(gfx::Point(10, 20)); green->SetBounds(gfx::Size(90, 80)); green->SetIsDrawable(true); background->AddChild(green); scoped_refptr<FakePictureLayer> blue = - FakePictureLayer::Create(&blue_client_); + FakePictureLayer::Create(layer_settings(), &blue_client_); blue->SetPosition(gfx::Point(50, 50)); blue->SetBounds(gfx::Size(25, 25)); blue->SetIsDrawable(true); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc b/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc index 7dd6d7d856d..a5286a2473e 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc @@ -21,6 +21,8 @@ class LayerTreeHostSynchronousPixelTest : public LayerTreePixelTest { void InitializeSettings(LayerTreeSettings* settings) override { LayerTreePixelTest::InitializeSettings(settings); settings->single_thread_proxy_scheduler = false; + settings->use_zero_copy = true; + settings->use_one_copy = false; } void BeginTest() override { @@ -36,7 +38,8 @@ TEST_F(LayerTreeHostSynchronousPixelTest, OneContentLayer) { SkPaint green_paint; green_paint.setColor(SkColorSetARGB(255, 0, 255, 0)); client.add_draw_rect(gfx::RectF(bounds), green_paint); - scoped_refptr<PictureLayer> root = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> root = + PictureLayer::Create(layer_settings(), &client); root->SetBounds(bounds); root->SetIsDrawable(true); @@ -66,7 +69,8 @@ TEST_F(LayerTreeHostSynchronousGPUPixelTest, OneContentLayer) { SkPaint green_paint; green_paint.setColor(SkColorSetARGB(255, 0, 255, 0)); client.add_draw_rect(gfx::RectF(bounds), green_paint); - scoped_refptr<PictureLayer> root = PictureLayer::Create(&client); + scoped_refptr<PictureLayer> root = + PictureLayer::Create(layer_settings(), &client); root->SetBounds(bounds); root->SetIsDrawable(true); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc new file mode 100644 index 00000000000..7a0af81f4e4 --- /dev/null +++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc @@ -0,0 +1,214 @@ +// Copyright 2015 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/layers/content_layer_client.h" +#include "cc/layers/picture_layer.h" +#include "cc/output/copy_output_request.h" +#include "cc/playback/display_item_list.h" +#include "cc/playback/drawing_display_item.h" +#include "cc/test/layer_tree_pixel_test.h" +#include "cc/test/test_gpu_memory_buffer_manager.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" + +#if !defined(OS_ANDROID) + +namespace cc { +namespace { + +enum RasterMode { + PARTIAL_ONE_COPY, + FULL_ONE_COPY, + GPU, + BITMAP, +}; + +class LayerTreeHostTilesPixelTest : public LayerTreePixelTest { + protected: + void InitializeSettings(LayerTreeSettings* settings) override { + LayerTreePixelTest::InitializeSettings(settings); + settings->use_display_lists = true; + switch (raster_mode_) { + case PARTIAL_ONE_COPY: + settings->use_one_copy = true; + settings->use_zero_copy = false; + settings->use_persistent_map_for_gpu_memory_buffers = true; + break; + case FULL_ONE_COPY: + settings->use_one_copy = true; + settings->use_zero_copy = false; + settings->use_persistent_map_for_gpu_memory_buffers = false; + break; + case BITMAP: + // This is done via context creation. No settings to change here! + break; + case GPU: + settings->gpu_rasterization_enabled = true; + settings->gpu_rasterization_forced = true; + break; + } + } + + void BeginTest() override { + // Don't set up a readback target at the start of the test. + PostSetNeedsCommitToMainThread(); + } + + void DoReadback() { + Layer* target = + readback_target_ ? readback_target_ : layer_tree_host()->root_layer(); + target->RequestCopyOfOutput(CreateCopyOutputRequest()); + } + + void RunRasterPixelTest(bool threaded, + RasterMode mode, + scoped_refptr<Layer> content_root, + base::FilePath file_name) { + raster_mode_ = mode; + + PixelTestType test_type = PIXEL_TEST_SOFTWARE; + switch (mode) { + case PARTIAL_ONE_COPY: + case FULL_ONE_COPY: + case GPU: + test_type = PIXEL_TEST_GL; + break; + case BITMAP: + test_type = PIXEL_TEST_SOFTWARE; + } + + if (threaded) + RunPixelTest(test_type, content_root, file_name); + else + RunSingleThreadedPixelTest(test_type, content_root, file_name); + } + + base::FilePath ref_file_; + scoped_ptr<SkBitmap> result_bitmap_; + RasterMode raster_mode_; +}; + +class BlueYellowClient : public ContentLayerClient { + public: + explicit BlueYellowClient(const gfx::Size& size) + : size_(size), blue_top_(true) {} + + void PaintContents(SkCanvas* canvas, + const gfx::Rect& clip, + PaintingControlSetting painting_status) override {} + + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + PaintingControlSetting painting_status) override { + bool use_cached_picture = false; + scoped_refptr<DisplayItemList> display_list = + DisplayItemList::Create(clip, use_cached_picture); + + SkPictureRecorder recorder; + skia::RefPtr<SkCanvas> canvas = skia::SharePtr( + recorder.beginRecording(gfx::RectToSkRect(gfx::Rect(size_)))); + gfx::Rect top(0, 0, size_.width(), size_.height() / 2); + gfx::Rect bottom(0, size_.height() / 2, size_.width(), size_.height() / 2); + + gfx::Rect blue_rect = blue_top_ ? top : bottom; + gfx::Rect yellow_rect = blue_top_ ? bottom : top; + + SkPaint paint; + paint.setStyle(SkPaint::kFill_Style); + + paint.setColor(SK_ColorBLUE); + canvas->drawRect(gfx::RectToSkRect(blue_rect), paint); + paint.setColor(SK_ColorYELLOW); + canvas->drawRect(gfx::RectToSkRect(yellow_rect), paint); + + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); + + auto* item = display_list->CreateAndAppendItem<DrawingDisplayItem>(); + item->SetNew(picture.Pass()); + + display_list->Finalize(); + return display_list; + } + + bool FillsBoundsCompletely() const override { return true; } + + void set_blue_top(bool b) { blue_top_ = b; } + + private: + gfx::Size size_; + bool blue_top_; +}; + +class LayerTreeHostTilesTestPartialInvalidation + : public LayerTreeHostTilesPixelTest { + public: + LayerTreeHostTilesTestPartialInvalidation() + : client_(gfx::Size(200, 200)), + picture_layer_(PictureLayer::Create(layer_settings(), &client_)) { + picture_layer_->SetBounds(gfx::Size(200, 200)); + picture_layer_->SetIsDrawable(true); + } + + void DidCommitAndDrawFrame() override { + switch (layer_tree_host()->source_frame_number()) { + case 1: + // We have done one frame, so the layer's content has been rastered. + // Now we change the picture behind it to record something completely + // different, but we give a smaller invalidation rect. The layer should + // only re-raster the stuff in the rect. If it doesn't do partial raster + // it would re-raster the whole thing instead. + client_.set_blue_top(false); + picture_layer_->SetNeedsDisplayRect(gfx::Rect(50, 50, 100, 100)); + + // Add a copy request to see what happened! + DoReadback(); + break; + } + } + + protected: + BlueYellowClient client_; + scoped_refptr<PictureLayer> picture_layer_; +}; + +TEST_F(LayerTreeHostTilesTestPartialInvalidation, + PartialRaster_SingleThread_OneCopy) { + RunRasterPixelTest( + false, PARTIAL_ONE_COPY, picture_layer_, + base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png"))); +} + +TEST_F(LayerTreeHostTilesTestPartialInvalidation, + FullRaster_SingleThread_OneCopy) { + RunRasterPixelTest( + false, FULL_ONE_COPY, picture_layer_, + base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png"))); +} + +TEST_F(LayerTreeHostTilesTestPartialInvalidation, + FullRaster_MultiThread_OneCopy) { + RunRasterPixelTest( + true, FULL_ONE_COPY, picture_layer_, + base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png"))); +} + +TEST_F(LayerTreeHostTilesTestPartialInvalidation, + PartialRaster_SingleThread_Software) { + RunRasterPixelTest( + false, BITMAP, picture_layer_, + base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png"))); +} + +TEST_F(LayerTreeHostTilesTestPartialInvalidation, + PartialRaster_SingleThread_GpuRaster) { + RunRasterPixelTest( + false, GPU, picture_layer_, + base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png"))); +} + +} // namespace +} // namespace cc + +#endif // !defined(OS_ANDROID) diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index 98ac5a11d6e..6d9c9c67199 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -13,7 +13,6 @@ #include "base/thread_task_runner_handle.h" #include "cc/animation/timing_function.h" #include "cc/debug/frame_rate_counter.h" -#include "cc/layers/content_layer.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/io_surface_layer.h" #include "cc/layers/layer_impl.h" @@ -31,12 +30,7 @@ #include "cc/quads/io_surface_draw_quad.h" #include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/tile_draw_quad.h" -#include "cc/resources/prioritized_resource.h" -#include "cc/resources/prioritized_resource_manager.h" -#include "cc/resources/resource_update_queue.h" -#include "cc/test/fake_content_layer.h" #include "cc/test/fake_content_layer_client.h" -#include "cc/test/fake_content_layer_impl.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_painted_scrollbar_layer.h" @@ -47,7 +41,6 @@ #include "cc/test/fake_scoped_ui_resource.h" #include "cc/test/fake_video_frame_provider.h" #include "cc/test/geometry_test_utils.h" -#include "cc/test/impl_side_painting_settings.h" #include "cc/test/layer_tree_test.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_web_graphics_context_3d.h" @@ -61,7 +54,6 @@ #include "third_party/khronos/GLES2/gl2.h" #include "third_party/khronos/GLES2/gl2ext.h" #include "third_party/skia/include/core/SkPicture.h" -#include "ui/gfx/frame_time.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/geometry/vector2d_conversions.h" @@ -74,28 +66,15 @@ using testing::Mock; namespace cc { namespace { -class LayerTreeHostTest : public LayerTreeTest { - public: - LayerTreeHostTest() : contents_texture_manager_(nullptr) {} - - void DidInitializeOutputSurface() override { - contents_texture_manager_ = layer_tree_host()->contents_texture_manager(); - } - - protected: - PrioritizedResourceManager* contents_texture_manager_; -}; +class LayerTreeHostTest : public LayerTreeTest {}; class LayerTreeHostTestHasImplThreadTest : public LayerTreeHostTest { public: LayerTreeHostTestHasImplThreadTest() : threaded_(false) {} - void RunTest(bool threaded, - bool delegating_renderer, - bool impl_side_painting) override { + void RunTest(bool threaded, bool delegating_renderer) override { threaded_ = threaded; - LayerTreeHostTest::RunTest(threaded, delegating_renderer, - impl_side_painting); + LayerTreeHostTest::RunTest(threaded, delegating_renderer); } void BeginTest() override { @@ -109,7 +88,7 @@ class LayerTreeHostTestHasImplThreadTest : public LayerTreeHostTest { bool threaded_; }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestHasImplThreadTest); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestHasImplThreadTest); class LayerTreeHostTestSetNeedsCommitInsideLayout : public LayerTreeHostTest { protected: @@ -128,8 +107,7 @@ class LayerTreeHostTestSetNeedsCommitInsideLayout : public LayerTreeHostTest { void AfterTest() override {} }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F( - LayerTreeHostTestSetNeedsCommitInsideLayout); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsCommitInsideLayout); class LayerTreeHostTestSetNeedsUpdateInsideLayout : public LayerTreeHostTest { protected: @@ -148,8 +126,7 @@ class LayerTreeHostTestSetNeedsUpdateInsideLayout : public LayerTreeHostTest { void AfterTest() override {} }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F( - LayerTreeHostTestSetNeedsUpdateInsideLayout); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsUpdateInsideLayout); // Test if the LTHI receives ReadyToActivate notifications from the TileManager // when no raster tasks get scheduled. @@ -193,7 +170,7 @@ class LayerTreeHostTestReadyToActivateEmpty : public LayerTreeHostTest { size_t required_for_activation_count_; }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestReadyToActivateEmpty); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestReadyToActivateEmpty); // Test if the LTHI receives ReadyToActivate notifications from the TileManager // when some raster tasks flagged as REQUIRED_FOR_ACTIVATION got scheduled. @@ -203,7 +180,7 @@ class LayerTreeHostTestReadyToActivateNonEmpty void SetupTree() override { client_.set_fill_with_nonsolid_color(true); scoped_refptr<FakePictureLayer> root_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); root_layer->SetBounds(gfx::Size(1024, 1024)); root_layer->SetIsDrawable(true); @@ -223,7 +200,7 @@ class LayerTreeHostTestReadyToActivateNonEmpty // Multi-thread only because in single thread the commit goes directly to the // active tree, so notify ready to activate is skipped. -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestReadyToActivateNonEmpty); +MULTI_THREAD_TEST_F(LayerTreeHostTestReadyToActivateNonEmpty); // Test if the LTHI receives ReadyToDraw notifications from the TileManager when // no raster tasks get scheduled. @@ -263,7 +240,7 @@ class LayerTreeHostTestReadyToDrawEmpty : public LayerTreeHostTest { size_t required_for_draw_count_; }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestReadyToDrawEmpty); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestReadyToDrawEmpty); // Test if the LTHI receives ReadyToDraw notifications from the TileManager when // some raster tasks flagged as REQUIRED_FOR_DRAW got scheduled. @@ -273,7 +250,7 @@ class LayerTreeHostTestReadyToDrawNonEmpty void SetupTree() override { client_.set_fill_with_nonsolid_color(true); scoped_refptr<FakePictureLayer> root_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); root_layer->SetBounds(gfx::Size(1024, 1024)); root_layer->SetIsDrawable(true); @@ -293,7 +270,104 @@ class LayerTreeHostTestReadyToDrawNonEmpty // Note: With this test setup, we only get tiles flagged as REQUIRED_FOR_DRAW in // single threaded mode. -SINGLE_THREAD_IMPL_TEST_F(LayerTreeHostTestReadyToDrawNonEmpty); +SINGLE_THREAD_TEST_F(LayerTreeHostTestReadyToDrawNonEmpty); + +class LayerTreeHostFreeWorkerContextResourcesTest : public LayerTreeHostTest { + public: + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { + auto output_surface = make_scoped_ptr(new testing::StrictMock< + MockSetWorkerContextShouldAggressivelyFreeResourcesOutputSurface>( + delegating_renderer())); + + // At init, we expect one call to set visibility to true. + testing::Expectation visibility_true = + EXPECT_CALL(*output_surface, + SetWorkerContextShouldAggressivelyFreeResources(false)) + .Times(1); + + // After running, we should get exactly one call to + // FreeWorkerContextGpuResources. + EXPECT_CALL(*output_surface, + SetWorkerContextShouldAggressivelyFreeResources(true)) + .After(visibility_true) + .WillOnce(testing::Invoke([this](bool is_visible) { EndTest(); })); + return output_surface.Pass(); + } + + void InitializeSettings(LayerTreeSettings* settings) override { + settings->gpu_rasterization_enabled = true; + settings->gpu_rasterization_forced = true; + } + + void BeginTest() override { + // Logic is handled in InitializedRendererOnThread to ensure that our + // LTHI is fully set up. + } + + void AfterTest() override { + // Expectations handled via mock. + } + + private: + class MockSetWorkerContextShouldAggressivelyFreeResourcesOutputSurface + : public FakeOutputSurface { + public: + ~MockSetWorkerContextShouldAggressivelyFreeResourcesOutputSurface() {} + explicit MockSetWorkerContextShouldAggressivelyFreeResourcesOutputSurface( + bool delegated_rendering) + : FakeOutputSurface(TestContextProvider::Create(), + TestContextProvider::Create(), + delegated_rendering) {} + MOCK_METHOD1(SetWorkerContextShouldAggressivelyFreeResources, + void(bool is_visible)); + }; +}; + +// Test if the LTH successfully frees resources on the worker context when +// visibility is set to false. +class LayerTreeHostFreeWorkerContextResourcesOnInvisible + : public LayerTreeHostFreeWorkerContextResourcesTest { + public: + void InitializedRendererOnThread(LayerTreeHostImpl* host_impl, + bool success) override { + PostSetVisibleToMainThread(false); + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostFreeWorkerContextResourcesOnInvisible); + +// Test if the LTH successfully frees resources on the worker context when +// hard memory limit is set to zero. +class LayerTreeHostFreeWorkerContextResourcesOnZeroMemoryLimit + : public LayerTreeHostFreeWorkerContextResourcesTest { + public: + void InitializedRendererOnThread(LayerTreeHostImpl* host_impl, + bool success) override { + ManagedMemoryPolicy zero_policy( + 0, gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING, 0); + host_impl->SetMemoryPolicy(zero_policy); + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostFreeWorkerContextResourcesOnZeroMemoryLimit); + +// Test if the LTH successfully frees resources on the worker context when +// hard memory limit is set to zero while using a synchronous compositor (like +// Android WebView). +class LayerTreeHostFreeWorkerContextResourcesOnZeroMemoryLimitSynchronous + : public LayerTreeHostFreeWorkerContextResourcesOnZeroMemoryLimit { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + LayerTreeHostFreeWorkerContextResourcesTest::InitializeSettings(settings); + settings->use_external_begin_frame_source = true; + settings->using_synchronous_renderer_compositor = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostFreeWorkerContextResourcesOnZeroMemoryLimitSynchronous); // Two setNeedsCommits in a row should lead to at least 1 commit and at least 1 // draw with frame 0. @@ -368,7 +442,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsCommit2); class LayerTreeHostTestPushPropertiesTo : public LayerTreeHostTest { protected: void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->CreateRenderSurface(); root->SetBounds(gfx::Size(10, 10)); layer_tree_host()->SetRootLayer(root); @@ -502,10 +576,7 @@ class LayerTreeHostTestSetNeedsRedrawRect : public LayerTreeHostTest { : num_draws_(0), bounds_(50, 50), invalid_rect_(10, 10, 20, 20) {} void BeginTest() override { - if (layer_tree_host()->settings().impl_side_painting) - root_layer_ = FakePictureLayer::Create(&client_); - else - root_layer_ = ContentLayer::Create(&client_); + root_layer_ = FakePictureLayer::Create(layer_settings(), &client_); root_layer_->SetIsDrawable(true); root_layer_->SetBounds(bounds_); layer_tree_host()->SetRootLayer(root_layer_); @@ -549,7 +620,7 @@ class LayerTreeHostTestSetNeedsRedrawRect : public LayerTreeHostTest { const gfx::Size bounds_; const gfx::Rect invalid_rect_; FakeContentLayerClient client_; - scoped_refptr<Layer> root_layer_; + scoped_refptr<FakePictureLayer> root_layer_; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsRedrawRect); @@ -563,7 +634,7 @@ class LayerTreeHostTestGpuRasterDeviceSizeChanged : public LayerTreeHostTest { void BeginTest() override { client_.set_fill_with_nonsolid_color(true); - root_layer_ = FakePictureLayer::Create(&client_); + root_layer_ = FakePictureLayer::Create(layer_settings(), &client_); root_layer_->SetIsDrawable(true); gfx::Transform transform; // Translate the layer out of the viewport to force it to not update its @@ -631,8 +702,7 @@ class LayerTreeHostTestGpuRasterDeviceSizeChanged : public LayerTreeHostTest { scoped_refptr<FakePictureLayer> root_layer_; }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F( - LayerTreeHostTestGpuRasterDeviceSizeChanged); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterDeviceSizeChanged); class LayerTreeHostTestNoExtraCommitFromInvalidate : public LayerTreeHostTest { public: @@ -641,14 +711,11 @@ class LayerTreeHostTestNoExtraCommitFromInvalidate : public LayerTreeHostTest { } void SetupTree() override { - root_layer_ = Layer::Create(); + root_layer_ = Layer::Create(layer_settings()); root_layer_->SetBounds(gfx::Size(10, 20)); root_layer_->CreateRenderSurface(); - if (layer_tree_host()->settings().impl_side_painting) - scaled_layer_ = FakePictureLayer::Create(&client_); - else - scaled_layer_ = FakeContentLayer::Create(&client_); + scaled_layer_ = FakePictureLayer::Create(layer_settings(), &client_); scaled_layer_->SetBounds(gfx::Size(1, 1)); root_layer_->AddChild(scaled_layer_); @@ -695,14 +762,14 @@ class LayerTreeHostTestNoExtraCommitFromScrollbarInvalidate } void SetupTree() override { - root_layer_ = Layer::Create(); + root_layer_ = Layer::Create(layer_settings()); root_layer_->SetBounds(gfx::Size(10, 20)); root_layer_->CreateRenderSurface(); bool paint_scrollbar = true; bool has_thumb = false; scrollbar_ = FakePaintedScrollbarLayer::Create( - paint_scrollbar, has_thumb, root_layer_->id()); + layer_settings(), paint_scrollbar, has_thumb, root_layer_->id()); scrollbar_->SetPosition(gfx::Point(0, 10)); scrollbar_->SetBounds(gfx::Size(10, 10)); @@ -752,10 +819,7 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { : num_draws_(0), bounds_(50, 50), invalid_rect_(10, 10, 20, 20) {} void BeginTest() override { - if (layer_tree_host()->settings().impl_side_painting) - root_layer_ = FakePictureLayer::Create(&client_); - else - root_layer_ = ContentLayer::Create(&client_); + root_layer_ = FakePictureLayer::Create(layer_settings(), &client_); root_layer_->SetIsDrawable(true); root_layer_->SetBounds(bounds_); layer_tree_host()->SetRootLayer(root_layer_); @@ -764,7 +828,7 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { } void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { - if (num_draws_ == 3 && host_impl->settings().impl_side_painting) + if (num_draws_ == 3) host_impl->SetNeedsRedrawRect(invalid_rect_); } @@ -810,10 +874,7 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { // Should force full frame damage on the next commit PostSetNextCommitForcesRedrawToMainThread(); PostSetNeedsCommitToMainThread(); - if (host_impl->settings().impl_side_painting) - host_impl->BlockNotifyReadyToActivateForTesting(true); - else - num_draws_++; + host_impl->BlockNotifyReadyToActivateForTesting(true); break; case 3: host_impl->BlockNotifyReadyToActivateForTesting(false); @@ -832,18 +893,16 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { const gfx::Size bounds_; const gfx::Rect invalid_rect_; FakeContentLayerClient client_; - scoped_refptr<Layer> root_layer_; + scoped_refptr<FakePictureLayer> root_layer_; }; -SINGLE_AND_MULTI_THREAD_BLOCKNOTIFY_TEST_F( - LayerTreeHostTestSetNextCommitForcesRedraw); +// This test blocks activation which is not supported for single thread mode. +MULTI_THREAD_BLOCKNOTIFY_TEST_F(LayerTreeHostTestSetNextCommitForcesRedraw); // Tests that if a layer is not drawn because of some reason in the parent then // its damage is preserved until the next time it is drawn. class LayerTreeHostTestUndrawnLayersDamageLater : public LayerTreeHostTest { public: - LayerTreeHostTestUndrawnLayersDamageLater() {} - void InitializeSettings(LayerTreeSettings* settings) override { // If we don't set the minimum contents scale, it's harder to verify whether // the damage we get is correct. For other scale amounts, please see @@ -852,28 +911,19 @@ class LayerTreeHostTestUndrawnLayersDamageLater : public LayerTreeHostTest { } void SetupTree() override { - if (layer_tree_host()->settings().impl_side_painting) - root_layer_ = FakePictureLayer::Create(&client_); - else - root_layer_ = ContentLayer::Create(&client_); + root_layer_ = FakePictureLayer::Create(layer_settings(), &client_); root_layer_->SetIsDrawable(true); root_layer_->SetBounds(gfx::Size(50, 50)); layer_tree_host()->SetRootLayer(root_layer_); // The initially transparent layer has a larger child layer, which is // not initially drawn because of the this (parent) layer. - if (layer_tree_host()->settings().impl_side_painting) - parent_layer_ = FakePictureLayer::Create(&client_); - else - parent_layer_ = FakeContentLayer::Create(&client_); + parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_); parent_layer_->SetBounds(gfx::Size(15, 15)); parent_layer_->SetOpacity(0.0f); root_layer_->AddChild(parent_layer_); - if (layer_tree_host()->settings().impl_side_painting) - child_layer_ = FakePictureLayer::Create(&client_); - else - child_layer_ = FakeContentLayer::Create(&client_); + child_layer_ = FakePictureLayer::Create(layer_settings(), &client_); child_layer_->SetBounds(gfx::Size(25, 25)); parent_layer_->AddChild(child_layer_); @@ -938,9 +988,9 @@ class LayerTreeHostTestUndrawnLayersDamageLater : public LayerTreeHostTest { private: FakeContentLayerClient client_; - scoped_refptr<Layer> root_layer_; - scoped_refptr<Layer> parent_layer_; - scoped_refptr<Layer> child_layer_; + scoped_refptr<FakePictureLayer> root_layer_; + scoped_refptr<FakePictureLayer> parent_layer_; + scoped_refptr<FakePictureLayer> child_layer_; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestUndrawnLayersDamageLater); @@ -955,17 +1005,16 @@ class LayerTreeHostTestDamageWithScale : public LayerTreeHostTest { client_.set_fill_with_nonsolid_color(true); scoped_ptr<FakePicturePile> pile( - new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, - ImplSidePaintingSettings().default_tile_grid_size)); - root_layer_ = - FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass()); + new FakePicturePile(LayerTreeSettings().minimum_contents_scale, + LayerTreeSettings().default_tile_grid_size)); + root_layer_ = FakePictureLayer::CreateWithRecordingSource( + layer_settings(), &client_, pile.Pass()); root_layer_->SetBounds(gfx::Size(50, 50)); - pile.reset( - new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, - ImplSidePaintingSettings().default_tile_grid_size)); - child_layer_ = - FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass()); + pile.reset(new FakePicturePile(LayerTreeSettings().minimum_contents_scale, + LayerTreeSettings().default_tile_grid_size)); + child_layer_ = FakePictureLayer::CreateWithRecordingSource( + layer_settings(), &client_, pile.Pass()); child_layer_->SetBounds(gfx::Size(25, 25)); child_layer_->SetIsDrawable(true); child_layer_->SetContentsOpaque(true); @@ -1051,79 +1100,7 @@ class LayerTreeHostTestDamageWithScale : public LayerTreeHostTest { scoped_refptr<Layer> child_layer_; }; -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestDamageWithScale); - -// Tests that if a layer is not drawn because of some reason in the parent, -// causing its content bounds to not be computed, then when it is later drawn, -// its content bounds get pushed. -class LayerTreeHostTestUndrawnLayersPushContentBoundsLater - : public LayerTreeHostTest { - public: - LayerTreeHostTestUndrawnLayersPushContentBoundsLater() - : root_layer_(Layer::Create()) {} - - void SetupTree() override { - root_layer_->CreateRenderSurface(); - root_layer_->SetIsDrawable(true); - root_layer_->SetBounds(gfx::Size(20, 20)); - layer_tree_host()->SetRootLayer(root_layer_); - - parent_layer_ = Layer::Create(); - parent_layer_->SetBounds(gfx::Size(20, 20)); - parent_layer_->SetOpacity(0.0f); - root_layer_->AddChild(parent_layer_); - - child_layer_ = Layer::Create(); - child_layer_->SetBounds(gfx::Size(15, 15)); - parent_layer_->AddChild(child_layer_); - - LayerTreeHostTest::SetupTree(); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { - LayerImpl* root = host_impl->active_tree()->root_layer(); - LayerImpl* parent = root->children()[0]; - LayerImpl* child = parent->children()[0]; - - switch (host_impl->active_tree()->source_frame_number()) { - case 0: - EXPECT_EQ(0.f, parent->opacity()); - EXPECT_EQ(gfx::SizeF(), child->content_bounds()); - break; - case 1: - EXPECT_EQ(1.f, parent->opacity()); - EXPECT_EQ(gfx::SizeF(15.f, 15.f), child->content_bounds()); - EndTest(); - break; - default: - NOTREACHED(); - } - } - - void DidCommit() override { - switch (layer_tree_host()->source_frame_number()) { - case 1: - parent_layer_->SetOpacity(1.0f); - break; - case 2: - break; - default: - NOTREACHED(); - } - } - - void AfterTest() override {} - - private: - scoped_refptr<Layer> root_layer_; - scoped_refptr<Layer> parent_layer_; - scoped_refptr<Layer> child_layer_; -}; - -SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F( - LayerTreeHostTestUndrawnLayersPushContentBoundsLater); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDamageWithScale); // This test verifies that properties on the layer tree host are commited // to the impl side. @@ -1168,8 +1145,7 @@ class LayerTreeHostTestFrameTimeUpdatesAfterActivationFails void BeginCommitOnThread(LayerTreeHostImpl* impl) override { EXPECT_EQ(frame_count_with_pending_tree_, 0); - if (impl->settings().impl_side_painting) - impl->BlockNotifyReadyToActivateForTesting(true); + impl->BlockNotifyReadyToActivateForTesting(true); } void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl, @@ -1180,27 +1156,21 @@ class LayerTreeHostTestFrameTimeUpdatesAfterActivationFails if (frame_count_with_pending_tree_ == 1) { EXPECT_EQ(first_frame_time_.ToInternalValue(), 0); first_frame_time_ = impl->CurrentBeginFrameArgs().frame_time; - } else if (frame_count_with_pending_tree_ == 2 && - impl->settings().impl_side_painting) { + } else if (frame_count_with_pending_tree_ == 2) { impl->BlockNotifyReadyToActivateForTesting(false); } } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - if (frame_count_with_pending_tree_ > 1) { - EXPECT_NE(first_frame_time_.ToInternalValue(), 0); - EXPECT_NE(first_frame_time_.ToInternalValue(), - impl->CurrentBeginFrameArgs().frame_time.ToInternalValue()); - EndTest(); - return; - } - - EXPECT_FALSE(impl->settings().impl_side_painting); + EXPECT_GT(frame_count_with_pending_tree_, 1); + EXPECT_NE(first_frame_time_.ToInternalValue(), 0); + EXPECT_NE(first_frame_time_.ToInternalValue(), + impl->CurrentBeginFrameArgs().frame_time.ToInternalValue()); EndTest(); } + void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { - if (impl->settings().impl_side_painting) - EXPECT_NE(frame_count_with_pending_tree_, 1); + EXPECT_GT(frame_count_with_pending_tree_, 1); } void AfterTest() override {} @@ -1210,7 +1180,8 @@ class LayerTreeHostTestFrameTimeUpdatesAfterActivationFails base::TimeTicks first_frame_time_; }; -SINGLE_AND_MULTI_THREAD_BLOCKNOTIFY_TEST_F( +// This test blocks activation which is not supported for single thread mode. +MULTI_THREAD_BLOCKNOTIFY_TEST_F( LayerTreeHostTestFrameTimeUpdatesAfterActivationFails); // This test verifies that LayerTreeHostImpl's current frame time gets @@ -1234,7 +1205,7 @@ class LayerTreeHostTestFrameTimeUpdatesAfterDraw : public LayerTreeHostTest { // Since we might use a low-resolution clock on Windows, we need to // make sure that the clock has incremented past first_frame_time_. - while (first_frame_time_ == gfx::FrameTime::Now()) { + while (first_frame_time_ == base::TimeTicks::Now()) { } return; @@ -1271,7 +1242,8 @@ class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest { void SetupTree() override { LayerTreeHostTest::SetupTree(); - scoped_refptr<FakePictureLayer> layer = FakePictureLayer::Create(&client_); + scoped_refptr<FakePictureLayer> layer = + FakePictureLayer::Create(layer_settings(), &client_); layer->set_always_update_resources(true); scroll_layer_ = layer; @@ -1291,7 +1263,9 @@ class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } - void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, + void ApplyViewportDeltas(const gfx::Vector2dF& scroll_delta, + const gfx::Vector2dF&, + const gfx::Vector2dF& elastic_overscroll_delta, float scale, float) override { gfx::ScrollOffset offset = scroll_layer_->scroll_offset(); @@ -1335,7 +1309,8 @@ class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest { scoped_refptr<Layer> scroll_layer_; }; -MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostTestStartPageScaleAnimation); +// Single thread proxy does not support impl-side page scale changes. +MULTI_THREAD_TEST_F(LayerTreeHostTestStartPageScaleAnimation); class LayerTreeHostTestSetVisible : public LayerTreeHostTest { public: @@ -1377,11 +1352,11 @@ class TestOpacityChangeLayerDelegate : public ContentLayerClient { if (test_layer_) test_layer_->SetOpacity(0.f); } - void PaintContentsToDisplayList( - DisplayItemList* display_list, + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { NOTIMPLEMENTED(); + return nullptr; } bool FillsBoundsCompletely() const override { return false; } @@ -1389,78 +1364,34 @@ class TestOpacityChangeLayerDelegate : public ContentLayerClient { Layer* test_layer_; }; -class ContentLayerWithUpdateTracking : public ContentLayer { - public: - static scoped_refptr<ContentLayerWithUpdateTracking> Create( - ContentLayerClient* client) { - return make_scoped_refptr(new ContentLayerWithUpdateTracking(client)); - } - - int PaintContentsCount() { return paint_contents_count_; } - void ResetPaintContentsCount() { paint_contents_count_ = 0; } - - bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) override { - bool updated = ContentLayer::Update(queue, occlusion); - paint_contents_count_++; - return updated; - } - - private: - explicit ContentLayerWithUpdateTracking(ContentLayerClient* client) - : ContentLayer(client), paint_contents_count_(0) { - SetBounds(gfx::Size(10, 10)); - SetIsDrawable(true); - } - ~ContentLayerWithUpdateTracking() override {} - - int paint_contents_count_; -}; - // Layer opacity change during paint should not prevent compositor resources // from being updated during commit. class LayerTreeHostTestOpacityChange : public LayerTreeHostTest { public: LayerTreeHostTestOpacityChange() : test_opacity_change_delegate_() {} - void BeginTest() override { - if (layer_tree_host()->settings().impl_side_painting) { - update_check_picture_layer_ = - FakePictureLayer::Create(&test_opacity_change_delegate_); - test_opacity_change_delegate_.SetTestLayer( - update_check_picture_layer_.get()); - is_impl_paint_ = true; - } else { - update_check_content_layer_ = ContentLayerWithUpdateTracking::Create( - &test_opacity_change_delegate_); - test_opacity_change_delegate_.SetTestLayer( - update_check_content_layer_.get()); - is_impl_paint_ = false; - } - layer_tree_host()->SetViewportSize(gfx::Size(10, 10)); - if (layer_tree_host()->settings().impl_side_painting) - layer_tree_host()->root_layer()->AddChild(update_check_picture_layer_); - else - layer_tree_host()->root_layer()->AddChild(update_check_content_layer_); + void SetupTree() override { + LayerTreeHostTest::SetupTree(); - PostSetNeedsCommitToMainThread(); + update_check_picture_layer_ = FakePictureLayer::Create( + layer_settings(), &test_opacity_change_delegate_); + test_opacity_change_delegate_.SetTestLayer( + update_check_picture_layer_.get()); + layer_tree_host()->root_layer()->AddChild(update_check_picture_layer_); } + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { EndTest(); } void AfterTest() override { // Update() should have been called once. - if (is_impl_paint_) - EXPECT_EQ(1u, update_check_picture_layer_->update_count()); - else - EXPECT_EQ(1, update_check_content_layer_->PaintContentsCount()); + EXPECT_EQ(1, update_check_picture_layer_->update_count()); } private: TestOpacityChangeLayerDelegate test_opacity_change_delegate_; - scoped_refptr<ContentLayerWithUpdateTracking> update_check_content_layer_; scoped_refptr<FakePictureLayer> update_check_picture_layer_; - bool is_impl_paint_; }; MULTI_THREAD_TEST_F(LayerTreeHostTestOpacityChange); @@ -1470,15 +1401,10 @@ class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers public: LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers() {} - void InitializeSettings(LayerTreeSettings* settings) override { - // PictureLayer can only be used with impl side painting enabled. - settings->impl_side_painting = true; - } - void BeginTest() override { client_.set_fill_with_nonsolid_color(true); - root_layer_ = FakePictureLayer::Create(&client_); - child_layer_ = FakePictureLayer::Create(&client_); + root_layer_ = FakePictureLayer::Create(layer_settings(), &client_); + child_layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_tree_host()->SetViewportSize(gfx::Size(60, 60)); layer_tree_host()->SetDeviceScaleFactor(1.5); @@ -1573,666 +1499,6 @@ class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers); -// TODO(sohanjg) : Remove it once impl-side painting ships everywhere. -// Verify atomicity of commits and reuse of textures. -class LayerTreeHostTestDirectRendererAtomicCommit : public LayerTreeHostTest { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->renderer_settings.texture_id_allocation_chunk_size = 1; - // Make sure partial texture updates are turned off. - settings->max_partial_texture_updates = 0; - // Linear fade animator prevents scrollbars from drawing immediately. - settings->scrollbar_animator = LayerTreeSettings::NO_ANIMATOR; - } - - void SetupTree() override { - layer_ = FakeContentLayer::Create(&client_); - layer_->SetBounds(gfx::Size(10, 20)); - - bool paint_scrollbar = true; - bool has_thumb = false; - scrollbar_ = FakePaintedScrollbarLayer::Create( - paint_scrollbar, has_thumb, layer_->id()); - scrollbar_->SetPosition(gfx::Point(0, 10)); - scrollbar_->SetBounds(gfx::Size(10, 10)); - - layer_->AddChild(scrollbar_); - - layer_tree_host()->SetRootLayer(layer_); - LayerTreeHostTest::SetupTree(); - } - - void BeginTest() override { - drew_frame_ = -1; - PostSetNeedsCommitToMainThread(); - } - - void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { - ASSERT_EQ(0u, impl->settings().max_partial_texture_updates); - - TestWebGraphicsContext3D* context = TestContext(); - - switch (impl->active_tree()->source_frame_number()) { - case 0: - // Number of textures should be one for each layer - ASSERT_EQ(2u, context->NumTextures()); - // Number of textures used for commit should be one for each layer. - EXPECT_EQ(2u, context->NumUsedTextures()); - // Verify that used texture is correct. - EXPECT_TRUE(context->UsedTexture(context->TextureAt(0))); - EXPECT_TRUE(context->UsedTexture(context->TextureAt(1))); - - context->ResetUsedTextures(); - break; - case 1: - // Number of textures should be one for scrollbar layer since it was - // requested and deleted on the impl-thread, and double for the content - // layer since its first texture is used by impl thread and cannot by - // used for update. - ASSERT_EQ(3u, context->NumTextures()); - // Number of textures used for commit should be one for each layer. - EXPECT_EQ(2u, context->NumUsedTextures()); - // First textures should not have been used. - EXPECT_FALSE(context->UsedTexture(context->TextureAt(0))); - EXPECT_TRUE(context->UsedTexture(context->TextureAt(1))); - // New textures should have been used. - EXPECT_TRUE(context->UsedTexture(context->TextureAt(2))); - context->ResetUsedTextures(); - break; - case 2: - EndTest(); - break; - default: - NOTREACHED(); - break; - } - } - - void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - TestWebGraphicsContext3D* context = TestContext(); - - if (drew_frame_ == impl->active_tree()->source_frame_number()) { - EXPECT_EQ(0u, context->NumUsedTextures()) << "For frame " << drew_frame_; - return; - } - drew_frame_ = impl->active_tree()->source_frame_number(); - - // We draw/ship one texture each frame for each layer. - EXPECT_EQ(2u, context->NumUsedTextures()); - context->ResetUsedTextures(); - - if (!TestEnded()) - PostSetNeedsCommitToMainThread(); - } - - void Layout() override { - layer_->SetNeedsDisplay(); - scrollbar_->SetNeedsDisplay(); - } - - void AfterTest() override {} - - protected: - FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> layer_; - scoped_refptr<FakePaintedScrollbarLayer> scrollbar_; - int drew_frame_; -}; - -MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( - LayerTreeHostTestDirectRendererAtomicCommit); - -// TODO(sohanjg) : Remove it once impl-side painting ships everywhere. -class LayerTreeHostTestDelegatingRendererAtomicCommit - : public LayerTreeHostTestDirectRendererAtomicCommit { - public: - void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { - ASSERT_EQ(0u, impl->settings().max_partial_texture_updates); - - TestWebGraphicsContext3D* context = TestContext(); - - switch (impl->active_tree()->source_frame_number()) { - case 0: - // Number of textures should be one for each layer - ASSERT_EQ(2u, context->NumTextures()); - // Number of textures used for commit should be one for each layer. - EXPECT_EQ(2u, context->NumUsedTextures()); - // Verify that used texture is correct. - EXPECT_TRUE(context->UsedTexture(context->TextureAt(0))); - EXPECT_TRUE(context->UsedTexture(context->TextureAt(1))); - break; - case 1: - // Number of textures should be doubled as the first context layer - // texture is being used by the impl-thread and cannot be used for - // update. The scrollbar behavior is different direct renderer because - // UI resource deletion with delegating renderer occurs after tree - // activation. - ASSERT_EQ(4u, context->NumTextures()); - // Number of textures used for commit should still be - // one for each layer. - EXPECT_EQ(2u, context->NumUsedTextures()); - // First textures should not have been used. - EXPECT_FALSE(context->UsedTexture(context->TextureAt(0))); - EXPECT_FALSE(context->UsedTexture(context->TextureAt(1))); - // New textures should have been used. - EXPECT_TRUE(context->UsedTexture(context->TextureAt(2))); - EXPECT_TRUE(context->UsedTexture(context->TextureAt(3))); - break; - case 2: - EndTest(); - break; - default: - NOTREACHED(); - break; - } - } -}; - -MULTI_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F( - LayerTreeHostTestDelegatingRendererAtomicCommit); - -static void SetLayerPropertiesForTesting(Layer* layer, - Layer* parent, - const gfx::Transform& transform, - const gfx::Point3F& transform_origin, - const gfx::PointF& position, - const gfx::Size& bounds, - bool opaque) { - layer->RemoveAllChildren(); - if (parent) - parent->AddChild(layer); - layer->SetTransform(transform); - layer->SetTransformOrigin(transform_origin); - layer->SetPosition(position); - layer->SetBounds(bounds); - layer->SetContentsOpaque(opaque); -} - -// TODO(sohanjg) : Remove it once impl-side painting ships everywhere. -class LayerTreeHostTestAtomicCommitWithPartialUpdate - : public LayerTreeHostTest { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->renderer_settings.texture_id_allocation_chunk_size = 1; - // Allow one partial texture update. - settings->max_partial_texture_updates = 1; - // No partial updates when impl side painting is enabled. - settings->impl_side_painting = false; - } - - void SetupTree() override { - parent_ = FakeContentLayer::Create(&client_); - parent_->SetBounds(gfx::Size(10, 20)); - - child_ = FakeContentLayer::Create(&client_); - child_->SetPosition(gfx::Point(0, 10)); - child_->SetBounds(gfx::Size(3, 10)); - - parent_->AddChild(child_); - - layer_tree_host()->SetRootLayer(parent_); - LayerTreeHostTest::SetupTree(); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - void DidCommitAndDrawFrame() override { - switch (layer_tree_host()->source_frame_number()) { - case 1: - parent_->SetNeedsDisplay(); - child_->SetNeedsDisplay(); - break; - case 2: - // Damage part of layers. - parent_->SetNeedsDisplayRect(gfx::Rect(5, 5)); - child_->SetNeedsDisplayRect(gfx::Rect(5, 5)); - break; - case 3: - child_->SetNeedsDisplay(); - layer_tree_host()->SetViewportSize(gfx::Size(10, 10)); - break; - case 4: - layer_tree_host()->SetViewportSize(gfx::Size(10, 20)); - break; - case 5: - EndTest(); - break; - default: - NOTREACHED() << layer_tree_host()->source_frame_number(); - break; - } - } - - void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { - ASSERT_EQ(1u, impl->settings().max_partial_texture_updates); - - TestWebGraphicsContext3D* context = TestContext(); - - switch (impl->active_tree()->source_frame_number()) { - case 0: - // Number of textures should be one for each layer. - ASSERT_EQ(2u, context->NumTextures()); - // Number of textures used for commit should be one for each layer. - EXPECT_EQ(2u, context->NumUsedTextures()); - // Verify that used textures are correct. - EXPECT_TRUE(context->UsedTexture(context->TextureAt(0))); - EXPECT_TRUE(context->UsedTexture(context->TextureAt(1))); - context->ResetUsedTextures(); - break; - case 1: - if (HasImplThread()) { - // Number of textures should be two for each content layer. - ASSERT_EQ(4u, context->NumTextures()); - } else { - // In single thread we can always do partial updates, so the limit has - // no effect. - ASSERT_EQ(2u, context->NumTextures()); - } - // Number of textures used for commit should be one for each content - // layer. - EXPECT_EQ(2u, context->NumUsedTextures()); - - if (HasImplThread()) { - // First content textures should not have been used. - EXPECT_FALSE(context->UsedTexture(context->TextureAt(0))); - EXPECT_FALSE(context->UsedTexture(context->TextureAt(1))); - // New textures should have been used. - EXPECT_TRUE(context->UsedTexture(context->TextureAt(2))); - EXPECT_TRUE(context->UsedTexture(context->TextureAt(3))); - } else { - // In single thread we can always do partial updates, so the limit has - // no effect. - EXPECT_TRUE(context->UsedTexture(context->TextureAt(0))); - EXPECT_TRUE(context->UsedTexture(context->TextureAt(1))); - } - - context->ResetUsedTextures(); - break; - case 2: - if (HasImplThread()) { - // Number of textures should be two for each content layer. - ASSERT_EQ(4u, context->NumTextures()); - } else { - // In single thread we can always do partial updates, so the limit has - // no effect. - ASSERT_EQ(2u, context->NumTextures()); - } - // Number of textures used for commit should be one for each content - // layer. - EXPECT_EQ(2u, context->NumUsedTextures()); - - if (HasImplThread()) { - // One content layer does a partial update also. - EXPECT_TRUE(context->UsedTexture(context->TextureAt(2))); - EXPECT_FALSE(context->UsedTexture(context->TextureAt(3))); - } else { - // In single thread we can always do partial updates, so the limit has - // no effect. - EXPECT_TRUE(context->UsedTexture(context->TextureAt(0))); - EXPECT_TRUE(context->UsedTexture(context->TextureAt(1))); - } - - context->ResetUsedTextures(); - break; - case 3: - // No textures should be used for commit. - EXPECT_EQ(0u, context->NumUsedTextures()); - - context->ResetUsedTextures(); - break; - case 4: - // Number of textures used for commit should be one, for the - // content layer. - EXPECT_EQ(1u, context->NumUsedTextures()); - - context->ResetUsedTextures(); - break; - default: - NOTREACHED(); - break; - } - } - - void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - EXPECT_LT(impl->active_tree()->source_frame_number(), 5); - - TestWebGraphicsContext3D* context = TestContext(); - - // Number of textures used for drawing should one per layer except for - // frame 3 where the viewport only contains one layer. - if (impl->active_tree()->source_frame_number() == 3) { - EXPECT_EQ(1u, context->NumUsedTextures()); - } else { - EXPECT_EQ(2u, context->NumUsedTextures()) - << "For frame " << impl->active_tree()->source_frame_number(); - } - - context->ResetUsedTextures(); - } - - void AfterTest() override {} - - private: - FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> parent_; - scoped_refptr<FakeContentLayer> child_; -}; - -// Partial updates are not possible with a delegating renderer. -SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( - LayerTreeHostTestAtomicCommitWithPartialUpdate); - -// TODO(sohanjg) : Make it work with impl-side painting. -class LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit - : public LayerTreeHostTest { - protected: - void SetupTree() override { - root_layer_ = FakeContentLayer::Create(&client_); - root_layer_->SetBounds(gfx::Size(100, 100)); - - surface_layer1_ = FakeContentLayer::Create(&client_); - surface_layer1_->SetBounds(gfx::Size(100, 100)); - surface_layer1_->SetForceRenderSurface(true); - surface_layer1_->SetOpacity(0.5f); - root_layer_->AddChild(surface_layer1_); - - surface_layer2_ = FakeContentLayer::Create(&client_); - surface_layer2_->SetBounds(gfx::Size(100, 100)); - surface_layer2_->SetForceRenderSurface(true); - surface_layer2_->SetOpacity(0.5f); - surface_layer1_->AddChild(surface_layer2_); - - replica_layer1_ = FakeContentLayer::Create(&client_); - surface_layer1_->SetReplicaLayer(replica_layer1_.get()); - - replica_layer2_ = FakeContentLayer::Create(&client_); - surface_layer2_->SetReplicaLayer(replica_layer2_.get()); - - layer_tree_host()->SetRootLayer(root_layer_); - LayerTreeHostTest::SetupTree(); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { - Renderer* renderer = host_impl->renderer(); - RenderPassId surface1_render_pass_id = host_impl->active_tree() - ->root_layer() - ->children()[0] - ->render_surface() - ->GetRenderPassId(); - RenderPassId surface2_render_pass_id = host_impl->active_tree() - ->root_layer() - ->children()[0] - ->children()[0] - ->render_surface() - ->GetRenderPassId(); - - switch (host_impl->active_tree()->source_frame_number()) { - case 0: - EXPECT_TRUE( - renderer->HasAllocatedResourcesForTesting(surface1_render_pass_id)); - EXPECT_TRUE( - renderer->HasAllocatedResourcesForTesting(surface2_render_pass_id)); - - // Reduce the memory limit to only fit the root layer and one render - // surface. This prevents any contents drawing into surfaces - // from being allocated. - host_impl->SetMemoryPolicy(ManagedMemoryPolicy(100 * 100 * 4 * 2)); - break; - case 1: - EXPECT_FALSE( - renderer->HasAllocatedResourcesForTesting(surface1_render_pass_id)); - EXPECT_FALSE( - renderer->HasAllocatedResourcesForTesting(surface2_render_pass_id)); - - EndTest(); - break; - } - } - - void DidCommitAndDrawFrame() override { - if (layer_tree_host()->source_frame_number() < 2) - root_layer_->SetNeedsDisplay(); - } - - void AfterTest() override { - EXPECT_LE(2u, root_layer_->update_count()); - EXPECT_LE(2u, surface_layer1_->update_count()); - EXPECT_LE(2u, surface_layer2_->update_count()); - } - - FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_layer_; - scoped_refptr<FakeContentLayer> surface_layer1_; - scoped_refptr<FakeContentLayer> replica_layer1_; - scoped_refptr<FakeContentLayer> surface_layer2_; - scoped_refptr<FakeContentLayer> replica_layer2_; -}; - -// Surfaces don't exist with a delegated renderer. -SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( - LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit); - -class EvictionTestLayer : public Layer { - public: - static scoped_refptr<EvictionTestLayer> Create() { - return make_scoped_refptr(new EvictionTestLayer()); - } - - bool Update(ResourceUpdateQueue*, const OcclusionTracker<Layer>*) override; - bool DrawsContent() const override { return true; } - - scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; - void PushPropertiesTo(LayerImpl* impl) override; - void SetTexturePriorities(const PriorityCalculator&) override; - - bool HaveBackingTexture() const { - return texture_.get() ? texture_->have_backing_texture() : false; - } - - private: - EvictionTestLayer() : Layer() {} - ~EvictionTestLayer() override {} - - void CreateTextureIfNeeded() { - if (texture_) - return; - texture_ = PrioritizedResource::Create( - layer_tree_host()->contents_texture_manager()); - texture_->SetDimensions(gfx::Size(10, 10), RGBA_8888); - bitmap_.allocN32Pixels(10, 10); - } - - scoped_ptr<PrioritizedResource> texture_; - SkBitmap bitmap_; -}; - -class EvictionTestLayerImpl : public LayerImpl { - public: - static scoped_ptr<EvictionTestLayerImpl> Create(LayerTreeImpl* tree_impl, - int id) { - return make_scoped_ptr(new EvictionTestLayerImpl(tree_impl, id)); - } - ~EvictionTestLayerImpl() override {} - - void AppendQuads(RenderPass* render_pass, - AppendQuadsData* append_quads_data) override { - ASSERT_TRUE(has_texture_); - ASSERT_NE(0u, layer_tree_impl()->resource_provider()->num_resources()); - } - - void SetHasTexture(bool has_texture) { has_texture_ = has_texture; } - - private: - EvictionTestLayerImpl(LayerTreeImpl* tree_impl, int id) - : LayerImpl(tree_impl, id), has_texture_(false) {} - - bool has_texture_; -}; - -void EvictionTestLayer::SetTexturePriorities(const PriorityCalculator&) { - CreateTextureIfNeeded(); - if (!texture_) - return; - texture_->set_request_priority(PriorityCalculator::UIPriority(true)); -} - -bool EvictionTestLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker<Layer>* occlusion) { - CreateTextureIfNeeded(); - if (!texture_) - return false; - - gfx::Rect full_rect(0, 0, 10, 10); - ResourceUpdate upload = ResourceUpdate::Create( - texture_.get(), &bitmap_, full_rect, full_rect, gfx::Vector2d()); - queue->AppendFullUpload(upload); - return true; -} - -scoped_ptr<LayerImpl> EvictionTestLayer::CreateLayerImpl( - LayerTreeImpl* tree_impl) { - return EvictionTestLayerImpl::Create(tree_impl, layer_id_); -} - -void EvictionTestLayer::PushPropertiesTo(LayerImpl* layer_impl) { - Layer::PushPropertiesTo(layer_impl); - - EvictionTestLayerImpl* test_layer_impl = - static_cast<EvictionTestLayerImpl*>(layer_impl); - test_layer_impl->SetHasTexture(texture_->have_backing_texture()); -} - -class LayerTreeHostTestEvictTextures : public LayerTreeHostTest { - public: - LayerTreeHostTestEvictTextures() - : layer_(EvictionTestLayer::Create()), - impl_for_evict_textures_(0), - num_commits_(0) {} - - void BeginTest() override { - layer_tree_host()->SetRootLayer(layer_); - layer_tree_host()->SetViewportSize(gfx::Size(10, 20)); - - gfx::Transform identity_matrix; - SetLayerPropertiesForTesting(layer_.get(), - 0, - identity_matrix, - gfx::Point3F(0.f, 0.f, 0.f), - gfx::PointF(0.f, 0.f), - gfx::Size(10, 20), - true); - - PostSetNeedsCommitToMainThread(); - } - - void PostEvictTextures() { - ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&LayerTreeHostTestEvictTextures::EvictTexturesOnImplThread, - base::Unretained(this))); - } - - void EvictTexturesOnImplThread() { - DCHECK(impl_for_evict_textures_); - impl_for_evict_textures_->EvictTexturesForTesting(); - } - - // Commit 1: Just commit and draw normally, then post an eviction at the end - // that will trigger a commit. - // Commit 2: Triggered by the eviction, let it go through and then set - // needsCommit. - // Commit 3: Triggered by the setNeedsCommit. In Layout(), post an eviction - // task, which will be handled before the commit. Don't set needsCommit, it - // should have been posted. A frame should not be drawn (note, - // didCommitAndDrawFrame may be called anyway). - // Commit 4: Triggered by the eviction, let it go through and then set - // needsCommit. - // Commit 5: Triggered by the setNeedsCommit, post an eviction task in - // Layout(), a frame should not be drawn but a commit will be posted. - // Commit 6: Triggered by the eviction, post an eviction task in - // Layout(), which will be a noop, letting the commit (which recreates the - // textures) go through and draw a frame, then end the test. - // - // Commits 1+2 test the eviction recovery path where eviction happens outside - // of the beginFrame/commit pair. - // Commits 3+4 test the eviction recovery path where eviction happens inside - // the beginFrame/commit pair. - // Commits 5+6 test the path where an eviction happens during the eviction - // recovery path. - void DidCommit() override { - switch (num_commits_) { - case 1: - EXPECT_TRUE(layer_->HaveBackingTexture()); - PostEvictTextures(); - break; - case 2: - EXPECT_TRUE(layer_->HaveBackingTexture()); - layer_tree_host()->SetNeedsCommit(); - break; - case 3: - break; - case 4: - EXPECT_TRUE(layer_->HaveBackingTexture()); - layer_tree_host()->SetNeedsCommit(); - break; - case 5: - break; - case 6: - EXPECT_TRUE(layer_->HaveBackingTexture()); - EndTest(); - break; - default: - NOTREACHED(); - break; - } - } - - void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { - impl_for_evict_textures_ = impl; - } - - void Layout() override { - ++num_commits_; - switch (num_commits_) { - case 1: - case 2: - break; - case 3: - PostEvictTextures(); - break; - case 4: - // We couldn't check in didCommitAndDrawFrame on commit 3, - // so check here. - EXPECT_FALSE(layer_->HaveBackingTexture()); - break; - case 5: - PostEvictTextures(); - break; - case 6: - // We couldn't check in didCommitAndDrawFrame on commit 5, - // so check here. - EXPECT_FALSE(layer_->HaveBackingTexture()); - PostEvictTextures(); - break; - default: - NOTREACHED(); - break; - } - } - - void AfterTest() override {} - - private: - FakeContentLayerClient client_; - scoped_refptr<EvictionTestLayer> layer_; - LayerTreeHostImpl* impl_for_evict_textures_; - int num_commits_; -}; - -MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostTestEvictTextures); - class LayerTreeHostTestContinuousInvalidate : public LayerTreeHostTest { public: LayerTreeHostTestContinuousInvalidate() @@ -2242,11 +1508,7 @@ class LayerTreeHostTestContinuousInvalidate : public LayerTreeHostTest { layer_tree_host()->SetViewportSize(gfx::Size(10, 10)); layer_tree_host()->root_layer()->SetBounds(gfx::Size(10, 10)); - if (layer_tree_host()->settings().impl_side_painting) - layer_ = FakePictureLayer::Create(&client_); - else - layer_ = FakeContentLayer::Create(&client_); - + layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_->SetBounds(gfx::Size(10, 10)); layer_->SetPosition(gfx::PointF(0.f, 0.f)); layer_->SetIsDrawable(true); @@ -2364,6 +1626,8 @@ class LayerTreeHostTestCompositeImmediatelyStateTransitions void InitializeSettings(LayerTreeSettings* settings) override { settings->single_thread_proxy_scheduler = false; + settings->use_zero_copy = true; + settings->use_one_copy = false; } void BeginTest() override { @@ -2414,263 +1678,13 @@ class LayerTreeHostTestCompositeImmediatelyStateTransitions SINGLE_THREAD_TEST_F(LayerTreeHostTestCompositeImmediatelyStateTransitions); -class LayerTreeHostWithProxy : public LayerTreeHost { - public: - LayerTreeHostWithProxy(FakeLayerTreeHostClient* client, - scoped_ptr<FakeProxy> proxy, - LayerTreeHost::InitParams* params) - : LayerTreeHost(params) { - proxy->SetLayerTreeHost(this); - client->SetLayerTreeHost(this); - InitializeForTesting(proxy.Pass()); - } -}; - -TEST(LayerTreeHostTest, LimitPartialUpdates) { - // When partial updates are not allowed, max updates should be 0. - { - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - - scoped_ptr<FakeProxy> proxy(new FakeProxy); - proxy->GetRendererCapabilities().allow_partial_texture_updates = false; - proxy->SetMaxPartialTextureUpdates(5); - - LayerTreeSettings settings; - settings.impl_side_painting = false; - settings.max_partial_texture_updates = 10; - - LayerTreeHost::InitParams params; - params.client = &client; - params.settings = &settings; - LayerTreeHostWithProxy host(&client, proxy.Pass(), ¶ms); - - EXPECT_EQ(0u, host.MaxPartialTextureUpdates()); - } - - // When partial updates are allowed, - // max updates should be limited by the proxy. - { - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - - scoped_ptr<FakeProxy> proxy(new FakeProxy); - proxy->GetRendererCapabilities().allow_partial_texture_updates = true; - proxy->SetMaxPartialTextureUpdates(5); - - LayerTreeSettings settings; - settings.impl_side_painting = false; - settings.max_partial_texture_updates = 10; - - LayerTreeHost::InitParams params; - params.client = &client; - params.settings = &settings; - LayerTreeHostWithProxy host(&client, proxy.Pass(), ¶ms); - - EXPECT_EQ(5u, host.MaxPartialTextureUpdates()); - } - - // When partial updates are allowed, - // max updates should also be limited by the settings. - { - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - - scoped_ptr<FakeProxy> proxy(new FakeProxy); - proxy->GetRendererCapabilities().allow_partial_texture_updates = true; - proxy->SetMaxPartialTextureUpdates(20); - - LayerTreeSettings settings; - settings.impl_side_painting = false; - settings.max_partial_texture_updates = 10; - - LayerTreeHost::InitParams params; - params.client = &client; - params.settings = &settings; - LayerTreeHostWithProxy host(&client, proxy.Pass(), ¶ms); - - EXPECT_EQ(10u, host.MaxPartialTextureUpdates()); - } -} - -TEST(LayerTreeHostTest, PartialUpdatesWithGLRenderer) { - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - - LayerTreeSettings settings; - settings.max_partial_texture_updates = 4; - settings.single_thread_proxy_scheduler = false; - settings.impl_side_painting = false; - - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); - LayerTreeHost::InitParams params; - params.client = &client; - params.shared_bitmap_manager = shared_bitmap_manager.get(); - params.settings = &settings; - params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); - scoped_ptr<LayerTreeHost> host = - LayerTreeHost::CreateSingleThreaded(&client, ¶ms); - client.SetLayerTreeHost(host.get()); - host->Composite(base::TimeTicks::Now()); - - EXPECT_EQ(4u, host->settings().max_partial_texture_updates); -} - -TEST(LayerTreeHostTest, PartialUpdatesWithSoftwareRenderer) { - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_SOFTWARE); - - LayerTreeSettings settings; - settings.max_partial_texture_updates = 4; - settings.single_thread_proxy_scheduler = false; - settings.impl_side_painting = false; - - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); - LayerTreeHost::InitParams params; - params.client = &client; - params.shared_bitmap_manager = shared_bitmap_manager.get(); - params.settings = &settings; - params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); - scoped_ptr<LayerTreeHost> host = - LayerTreeHost::CreateSingleThreaded(&client, ¶ms); - client.SetLayerTreeHost(host.get()); - host->Composite(base::TimeTicks::Now()); - - EXPECT_EQ(4u, host->settings().max_partial_texture_updates); -} - -TEST(LayerTreeHostTest, PartialUpdatesWithDelegatingRendererAndGLContent) { - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DELEGATED_3D); - - LayerTreeSettings settings; - settings.max_partial_texture_updates = 4; - settings.single_thread_proxy_scheduler = false; - settings.impl_side_painting = false; - - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); - LayerTreeHost::InitParams params; - params.client = &client; - params.shared_bitmap_manager = shared_bitmap_manager.get(); - params.settings = &settings; - params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); - scoped_ptr<LayerTreeHost> host = - LayerTreeHost::CreateSingleThreaded(&client, ¶ms); - client.SetLayerTreeHost(host.get()); - host->Composite(base::TimeTicks::Now()); - - EXPECT_EQ(0u, host->MaxPartialTextureUpdates()); -} - -TEST(LayerTreeHostTest, - PartialUpdatesWithDelegatingRendererAndSoftwareContent) { - FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DELEGATED_SOFTWARE); - - LayerTreeSettings settings; - settings.max_partial_texture_updates = 4; - settings.single_thread_proxy_scheduler = false; - settings.impl_side_painting = false; - - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); - LayerTreeHost::InitParams params; - params.client = &client; - params.shared_bitmap_manager = shared_bitmap_manager.get(); - params.settings = &settings; - params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); - scoped_ptr<LayerTreeHost> host = - LayerTreeHost::CreateSingleThreaded(&client, ¶ms); - client.SetLayerTreeHost(host.get()); - host->Composite(base::TimeTicks::Now()); - - EXPECT_EQ(0u, host->MaxPartialTextureUpdates()); -} - -// TODO(sohanjg) : Remove it once impl-side painting ships everywhere. -class LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted - : public LayerTreeHostTest { - public: - LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted() - : root_layer_(FakeContentLayer::Create(&client_)), - child_layer1_(FakeContentLayer::Create(&client_)), - child_layer2_(FakeContentLayer::Create(&client_)), - num_commits_(0) {} - - void BeginTest() override { - layer_tree_host()->SetViewportSize(gfx::Size(100, 100)); - root_layer_->SetBounds(gfx::Size(100, 100)); - child_layer1_->SetBounds(gfx::Size(100, 100)); - child_layer2_->SetBounds(gfx::Size(100, 100)); - root_layer_->AddChild(child_layer1_); - root_layer_->AddChild(child_layer2_); - layer_tree_host()->SetRootLayer(root_layer_); - PostSetNeedsCommitToMainThread(); - } - - void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl, - bool visible) override { - if (visible) { - // One backing should remain unevicted. - EXPECT_EQ(100u * 100u * 4u * 1u, - contents_texture_manager_->MemoryUseBytes()); - } else { - EXPECT_EQ(0u, contents_texture_manager_->MemoryUseBytes()); - } - - // Make sure that contents textures are marked as having been - // purged. - EXPECT_TRUE(host_impl->active_tree()->ContentsTexturesPurged()); - // End the test in this state. - EndTest(); - } - - void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { - ++num_commits_; - switch (num_commits_) { - case 1: - // All three backings should have memory. - EXPECT_EQ(100u * 100u * 4u * 3u, - contents_texture_manager_->MemoryUseBytes()); - - // Set a new policy that will kick out 1 of the 3 resources. - // Because a resource was evicted, a commit will be kicked off. - host_impl->SetMemoryPolicy( - ManagedMemoryPolicy(100 * 100 * 4 * 2, - gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, - 1000)); - break; - case 2: - // Only two backings should have memory. - EXPECT_EQ(100u * 100u * 4u * 2u, - contents_texture_manager_->MemoryUseBytes()); - // Become backgrounded, which will cause 1 more resource to be - // evicted. - PostSetVisibleToMainThread(false); - break; - default: - // No further commits should happen because this is not visible - // anymore. - NOTREACHED(); - break; - } - } - - void AfterTest() override {} - - private: - FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_layer_; - scoped_refptr<FakeContentLayer> child_layer1_; - scoped_refptr<FakeContentLayer> child_layer2_; - int num_commits_; -}; - -SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F( - LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted); - class LayerTreeHostTestLCDChange : public LayerTreeHostTest { public: void SetupTree() override { num_tiles_rastered_ = 0; - scoped_refptr<Layer> root_layer = PictureLayer::Create(&client_); + scoped_refptr<Layer> root_layer = + PictureLayer::Create(layer_settings(), &client_); client_.set_fill_with_nonsolid_color(true); root_layer->SetIsDrawable(true); root_layer->SetBounds(gfx::Size(10, 10)); @@ -2751,7 +1765,7 @@ class LayerTreeHostTestLCDChange : public LayerTreeHostTest { int num_tiles_rastered_; }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestLCDChange); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestLCDChange); // Verify that the BeginFrame notification is used to initiate rendering. class LayerTreeHostTestBeginFrameNotification : public LayerTreeHostTest { @@ -2886,7 +1900,7 @@ class LayerTreeHostTestAbortedCommitDoesntStallDisabledVsync : public LayerTreeHostTestAbortedCommitDoesntStall { void InitializeSettings(LayerTreeSettings* settings) override { LayerTreeHostTestAbortedCommitDoesntStall::InitializeSettings(settings); - settings->throttle_frame_production = false; + settings->renderer_settings.disable_gpu_vsync = true; } }; @@ -2895,14 +1909,11 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestAbortedCommitDoesntStallDisabledVsync); class LayerTreeHostTestUninvertibleTransformDoesNotBlockActivation : public LayerTreeHostTest { protected: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; - } - void SetupTree() override { LayerTreeHostTest::SetupTree(); - scoped_refptr<Layer> layer = PictureLayer::Create(&client_); + scoped_refptr<Layer> layer = + PictureLayer::Create(layer_settings(), &client_); layer->SetTransform(gfx::Transform(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); layer->SetBounds(gfx::Size(10, 10)); layer_tree_host()->root_layer()->AddChild(layer); @@ -2919,7 +1930,7 @@ class LayerTreeHostTestUninvertibleTransformDoesNotBlockActivation FakeContentLayerClient client_; }; -MULTI_THREAD_TEST_F( +SINGLE_AND_MULTI_THREAD_TEST_F( LayerTreeHostTestUninvertibleTransformDoesNotBlockActivation); class LayerTreeHostTestChangeLayerPropertiesInPaintContents @@ -2937,11 +1948,11 @@ class LayerTreeHostTestChangeLayerPropertiesInPaintContents layer_->SetBounds(gfx::Size(2, 2)); } - void PaintContentsToDisplayList( - DisplayItemList* display_list, + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { NOTIMPLEMENTED(); + return nullptr; } bool FillsBoundsCompletely() const override { return false; } @@ -2953,19 +1964,13 @@ class LayerTreeHostTestChangeLayerPropertiesInPaintContents LayerTreeHostTestChangeLayerPropertiesInPaintContents() : num_commits_(0) {} void SetupTree() override { - if (layer_tree_host()->settings().impl_side_painting) { - scoped_refptr<PictureLayer> root_layer = PictureLayer::Create(&client_); - layer_tree_host()->SetRootLayer(root_layer); - } else { - scoped_refptr<ContentLayer> root_layer = ContentLayer::Create(&client_); - layer_tree_host()->SetRootLayer(root_layer); - } - Layer* root_layer = layer_tree_host()->root_layer(); + scoped_refptr<PictureLayer> root_layer = + PictureLayer::Create(layer_settings(), &client_); root_layer->SetIsDrawable(true); root_layer->SetBounds(gfx::Size(1, 1)); + client_.set_layer(root_layer.get()); - client_.set_layer(root_layer); - + layer_tree_host()->SetRootLayer(root_layer); LayerTreeHostTest::SetupTree(); } @@ -3041,7 +2046,8 @@ class LayerTreeHostTestIOSurfaceDrawing : public LayerTreeHostTest { io_surface_id_ = 9; io_surface_size_ = gfx::Size(6, 7); - scoped_refptr<IOSurfaceLayer> io_surface_layer = IOSurfaceLayer::Create(); + scoped_refptr<IOSurfaceLayer> io_surface_layer = + IOSurfaceLayer::Create(layer_settings()); io_surface_layer->SetBounds(gfx::Size(10, 10)); io_surface_layer->SetIsDrawable(true); io_surface_layer->SetContentsOpaque(true); @@ -3102,10 +2108,10 @@ class LayerTreeHostTestIOSurfaceDrawing : public LayerTreeHostTest { const IOSurfaceDrawQuad* io_surface_draw_quad = IOSurfaceDrawQuad::MaterialCast(quad); EXPECT_EQ(io_surface_size_, io_surface_draw_quad->io_surface_size); - EXPECT_NE(0u, io_surface_draw_quad->io_surface_resource_id); + EXPECT_NE(0u, io_surface_draw_quad->io_surface_resource_id()); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_RECTANGLE_ARB), resource_provider->TargetForTesting( - io_surface_draw_quad->io_surface_resource_id)); + io_surface_draw_quad->io_surface_resource_id())); if (delegating_renderer()) { // The io surface layer's resource should be sent to the parent. @@ -3182,28 +2188,21 @@ class LayerTreeHostTestNumFramesPending : public LayerTreeHostTest { int frame_; }; -// Flaky on all platforms: http://crbug.com/327498 -TEST_F(LayerTreeHostTestNumFramesPending, DISABLED_DelegatingRenderer) { - RunTest(true, true, true); -} - -TEST_F(LayerTreeHostTestNumFramesPending, DISABLED_GLRenderer) { - RunTest(true, false, true); -} +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestNumFramesPending); class LayerTreeHostTestResourcelessSoftwareDraw : public LayerTreeHostTest { public: void SetupTree() override { - root_layer_ = FakePictureLayer::Create(&client_); + root_layer_ = FakePictureLayer::Create(layer_settings(), &client_); root_layer_->SetIsDrawable(true); root_layer_->SetBounds(gfx::Size(50, 50)); - parent_layer_ = FakePictureLayer::Create(&client_); + parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_); parent_layer_->SetIsDrawable(true); parent_layer_->SetBounds(gfx::Size(50, 50)); parent_layer_->SetForceRenderSurface(true); - child_layer_ = FakePictureLayer::Create(&client_); + child_layer_ = FakePictureLayer::Create(layer_settings(), &client_); child_layer_->SetIsDrawable(true); child_layer_->SetBounds(gfx::Size(50, 50)); @@ -3280,7 +2279,7 @@ class LayerTreeHostTestResourcelessSoftwareDraw : public LayerTreeHostTest { int swap_count_; }; -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestResourcelessSoftwareDraw); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestResourcelessSoftwareDraw); // Test for UI Resource management. class LayerTreeHostTestUIResource : public LayerTreeHostTest { @@ -3325,7 +2324,7 @@ class LayerTreeHostTestUIResource : public LayerTreeHostTest { } } - void PerformTest(LayerTreeHostImpl* impl) { + void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { TestWebGraphicsContext3D* context = TestContext(); int frame = impl->active_tree()->source_frame_number(); @@ -3354,16 +2353,6 @@ class LayerTreeHostTestUIResource : public LayerTreeHostTest { } } - void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { - if (!impl->settings().impl_side_painting) - PerformTest(impl); - } - - void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { - if (impl->settings().impl_side_painting) - PerformTest(impl); - } - void AfterTest() override {} private: @@ -3420,8 +2409,9 @@ class PushPropertiesCountingLayerImpl : public LayerImpl { class PushPropertiesCountingLayer : public Layer { public: - static scoped_refptr<PushPropertiesCountingLayer> Create() { - return new PushPropertiesCountingLayer(); + static scoped_refptr<PushPropertiesCountingLayer> Create( + const LayerSettings& settings) { + return new PushPropertiesCountingLayer(settings); } void PushPropertiesTo(LayerImpl* layer) override { @@ -3448,8 +2438,10 @@ class PushPropertiesCountingLayer : public Layer { } private: - PushPropertiesCountingLayer() - : push_properties_count_(0), persist_needs_push_properties_(false) { + explicit PushPropertiesCountingLayer(const LayerSettings& settings) + : Layer(settings), + push_properties_count_(0), + persist_needs_push_properties_(false) { SetBounds(gfx::Size(1, 1)); } ~PushPropertiesCountingLayer() override {} @@ -3472,12 +2464,13 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest { } void SetupTree() override { - root_ = PushPropertiesCountingLayer::Create(); + root_ = PushPropertiesCountingLayer::Create(layer_settings()); root_->CreateRenderSurface(); - child_ = PushPropertiesCountingLayer::Create(); - child2_ = PushPropertiesCountingLayer::Create(); - grandchild_ = PushPropertiesCountingLayer::Create(); - leaf_always_pushing_layer_ = PushPropertiesCountingLayer::Create(); + child_ = PushPropertiesCountingLayer::Create(layer_settings()); + child2_ = PushPropertiesCountingLayer::Create(layer_settings()); + grandchild_ = PushPropertiesCountingLayer::Create(layer_settings()); + leaf_always_pushing_layer_ = + PushPropertiesCountingLayer::Create(layer_settings()); leaf_always_pushing_layer_->set_persist_needs_push_properties(true); root_->AddChild(child_); @@ -3485,7 +2478,7 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest { child_->AddChild(grandchild_); child2_->AddChild(leaf_always_pushing_layer_); - other_root_ = PushPropertiesCountingLayer::Create(); + other_root_ = PushPropertiesCountingLayer::Create(layer_settings()); other_root_->CreateRenderSurface(); // Don't set the root layer here. @@ -3854,9 +2847,8 @@ class LayerTreeHostTestImplLayersPushProperties size_t expected_push_properties_grandchild2_impl_; }; -TEST_F(LayerTreeHostTestImplLayersPushProperties, DelegatingRenderer) { - RunTestWithImplSidePainting(); -} +// In single thread there's no pending tree to push properties from. +MULTI_THREAD_TEST_F(LayerTreeHostTestImplLayersPushProperties); class LayerTreeHostTestPropertyChangesDuringUpdateArePushed : public LayerTreeHostTest { @@ -3864,14 +2856,14 @@ class LayerTreeHostTestPropertyChangesDuringUpdateArePushed void BeginTest() override { PostSetNeedsCommitToMainThread(); } void SetupTree() override { - root_ = Layer::Create(); + root_ = Layer::Create(layer_settings()); root_->CreateRenderSurface(); root_->SetBounds(gfx::Size(1, 1)); bool paint_scrollbar = true; bool has_thumb = false; scrollbar_layer_ = FakePaintedScrollbarLayer::Create( - paint_scrollbar, has_thumb, root_->id()); + layer_settings(), paint_scrollbar, has_thumb, root_->id()); root_->AddChild(scrollbar_layer_); @@ -3921,9 +2913,9 @@ class LayerTreeHostTestSetDrawableCausesCommit : public LayerTreeHostTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } void SetupTree() override { - root_ = PushPropertiesCountingLayer::Create(); + root_ = PushPropertiesCountingLayer::Create(layer_settings()); root_->CreateRenderSurface(); - child_ = PushPropertiesCountingLayer::Create(); + child_ = PushPropertiesCountingLayer::Create(layer_settings()); root_->AddChild(child_); layer_tree_host()->SetRootLayer(root_); @@ -3983,12 +2975,12 @@ class LayerTreeHostTestCasePushPropertiesThreeGrandChildren } void SetupTree() override { - root_ = PushPropertiesCountingLayer::Create(); + root_ = PushPropertiesCountingLayer::Create(layer_settings()); root_->CreateRenderSurface(); - child_ = PushPropertiesCountingLayer::Create(); - grandchild1_ = PushPropertiesCountingLayer::Create(); - grandchild2_ = PushPropertiesCountingLayer::Create(); - grandchild3_ = PushPropertiesCountingLayer::Create(); + child_ = PushPropertiesCountingLayer::Create(layer_settings()); + grandchild1_ = PushPropertiesCountingLayer::Create(layer_settings()); + grandchild2_ = PushPropertiesCountingLayer::Create(layer_settings()); + grandchild3_ = PushPropertiesCountingLayer::Create(layer_settings()); root_->AddChild(child_); child_->AddChild(grandchild1_); @@ -4388,7 +3380,6 @@ class LayerTreeHostTestTreeActivationCallback : public LayerTreeHostTest { : num_commits_(0), callback_count_(0) {} void BeginTest() override { - EXPECT_TRUE(HasImplThread()); PostSetNeedsCommitToMainThread(); } @@ -4440,13 +3431,7 @@ class LayerTreeHostTestTreeActivationCallback : public LayerTreeHostTest { int callback_count_; }; -TEST_F(LayerTreeHostTestTreeActivationCallback, DirectRenderer) { - RunTest(true, false, true); -} - -TEST_F(LayerTreeHostTestTreeActivationCallback, DelegatingRenderer) { - RunTest(true, true, true); -} +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestTreeActivationCallback); class LayerInvalidateCausesDraw : public LayerTreeHostTest { public: @@ -4496,8 +3481,8 @@ class LayerTreeHostTestVideoLayerInvalidate : public LayerInvalidateCausesDraw { public: void SetupTree() override { LayerTreeHostTest::SetupTree(); - scoped_refptr<VideoLayer> video_layer = - VideoLayer::Create(&provider_, media::VIDEO_ROTATION_0); + scoped_refptr<VideoLayer> video_layer = VideoLayer::Create( + layer_settings(), &provider_, media::VIDEO_ROTATION_0); video_layer->SetBounds(gfx::Size(10, 10)); video_layer->SetIsDrawable(true); layer_tree_host()->root_layer()->AddChild(video_layer); @@ -4519,7 +3504,8 @@ class LayerTreeHostTestIOSurfaceLayerInvalidate public: void SetupTree() override { LayerTreeHostTest::SetupTree(); - scoped_refptr<IOSurfaceLayer> layer = IOSurfaceLayer::Create(); + scoped_refptr<IOSurfaceLayer> layer = + IOSurfaceLayer::Create(layer_settings()); layer->SetBounds(gfx::Size(10, 10)); uint32_t fake_io_surface_id = 7; layer->SetIOSurfaceProperties(fake_io_surface_id, layer->bounds()); @@ -4530,25 +3516,23 @@ class LayerTreeHostTestIOSurfaceLayerInvalidate } }; -// TODO(danakj): IOSurface layer can not be transported. crbug.com/239335 -SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( - LayerTreeHostTestIOSurfaceLayerInvalidate); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestIOSurfaceLayerInvalidate); class LayerTreeHostTestPushHiddenLayer : public LayerTreeHostTest { protected: void SetupTree() override { - root_layer_ = Layer::Create(); + root_layer_ = Layer::Create(layer_settings()); root_layer_->CreateRenderSurface(); root_layer_->SetPosition(gfx::Point()); root_layer_->SetBounds(gfx::Size(10, 10)); - parent_layer_ = SolidColorLayer::Create(); + parent_layer_ = SolidColorLayer::Create(layer_settings()); parent_layer_->SetPosition(gfx::Point()); parent_layer_->SetBounds(gfx::Size(10, 10)); parent_layer_->SetIsDrawable(true); root_layer_->AddChild(parent_layer_); - child_layer_ = SolidColorLayer::Create(); + child_layer_ = SolidColorLayer::Create(layer_settings()); child_layer_->SetPosition(gfx::Point()); child_layer_->SetBounds(gfx::Size(10, 10)); child_layer_->SetIsDrawable(true); @@ -4603,12 +3587,8 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPushHiddenLayer); class LayerTreeHostTestUpdateLayerInEmptyViewport : public LayerTreeHostTest { protected: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; - } - void SetupTree() override { - root_layer_ = FakePictureLayer::Create(&client_); + root_layer_ = FakePictureLayer::Create(layer_settings(), &client_); root_layer_->SetBounds(gfx::Size(10, 10)); layer_tree_host()->SetRootLayer(root_layer_); @@ -4625,7 +3605,7 @@ class LayerTreeHostTestUpdateLayerInEmptyViewport : public LayerTreeHostTest { void DidCommit() override { // The layer should be updated even though the viewport is empty, so we // are capable of drawing it on the impl tree. - EXPECT_GT(root_layer_->update_count(), 0u); + EXPECT_GT(root_layer_->update_count(), 0); EndTest(); } @@ -4637,72 +3617,10 @@ class LayerTreeHostTestUpdateLayerInEmptyViewport : public LayerTreeHostTest { MULTI_THREAD_TEST_F(LayerTreeHostTestUpdateLayerInEmptyViewport); -class LayerTreeHostTestAbortEvictedTextures : public LayerTreeHostTest { - public: - LayerTreeHostTestAbortEvictedTextures() - : num_will_begin_main_frames_(0), num_impl_commits_(0) {} - - protected: - void SetupTree() override { - scoped_refptr<SolidColorLayer> root_layer = SolidColorLayer::Create(); - root_layer->SetBounds(gfx::Size(200, 200)); - root_layer->SetIsDrawable(true); - root_layer->CreateRenderSurface(); - - layer_tree_host()->SetRootLayer(root_layer); - LayerTreeHostTest::SetupTree(); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - void WillBeginMainFrame() override { - num_will_begin_main_frames_++; - switch (num_will_begin_main_frames_) { - case 2: - // Send a redraw to the compositor thread. This will (wrongly) be - // ignored unless aborting resets the texture state. - layer_tree_host()->SetNeedsRedraw(); - break; - } - } - - void BeginCommitOnThread(LayerTreeHostImpl* impl) override { - num_impl_commits_++; - } - - void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - switch (impl->SourceAnimationFrameNumber()) { - case 1: - // Prevent draws until commit. - impl->active_tree()->SetContentsTexturesPurged(); - EXPECT_FALSE(impl->CanDraw()); - // Trigger an abortable commit. - impl->SetNeedsCommit(); - break; - case 2: - EndTest(); - break; - } - } - - void AfterTest() override { - // Ensure that the commit was truly aborted. - EXPECT_EQ(2, num_will_begin_main_frames_); - EXPECT_EQ(1, num_impl_commits_); - } - - private: - int num_will_begin_main_frames_; - int num_impl_commits_; -}; - -// Commits can only be aborted when using the thread proxy. -MULTI_THREAD_TEST_F(LayerTreeHostTestAbortEvictedTextures); - class LayerTreeHostTestMaxTransferBufferUsageBytes : public LayerTreeHostTest { protected: void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; + // Testing async uploads. settings->use_zero_copy = false; settings->use_one_copy = false; } @@ -4720,7 +3638,7 @@ class LayerTreeHostTestMaxTransferBufferUsageBytes : public LayerTreeHostTest { void SetupTree() override { client_.set_fill_with_nonsolid_color(true); scoped_refptr<FakePictureLayer> root_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); root_layer->SetBounds(gfx::Size(1024, 1024)); root_layer->SetIsDrawable(true); @@ -4748,99 +3666,6 @@ class LayerTreeHostTestMaxTransferBufferUsageBytes : public LayerTreeHostTest { // Impl-side painting is a multi-threaded compositor feature. MULTI_THREAD_TEST_F(LayerTreeHostTestMaxTransferBufferUsageBytes); -// Test ensuring that memory limits are sent to the prioritized resource -// manager. -class LayerTreeHostTestMemoryLimits : public LayerTreeHostTest { - public: - LayerTreeHostTestMemoryLimits() : num_commits_(0) {} - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - void WillCommit() override { - // Some commits are aborted, so increment number of attempted commits here. - num_commits_++; - } - - void DidCommit() override { - switch (num_commits_) { - case 1: - // Verify default values. - EXPECT_EQ(PrioritizedResourceManager::DefaultMemoryAllocationLimit(), - layer_tree_host() - ->contents_texture_manager() - ->MaxMemoryLimitBytes()); - EXPECT_EQ(PriorityCalculator::AllowEverythingCutoff(), - layer_tree_host() - ->contents_texture_manager() - ->ExternalPriorityCutoff()); - PostSetNeedsCommitToMainThread(); - break; - case 2: - // The values should remain the same until the commit after the policy - // is changed. - EXPECT_EQ(PrioritizedResourceManager::DefaultMemoryAllocationLimit(), - layer_tree_host() - ->contents_texture_manager() - ->MaxMemoryLimitBytes()); - EXPECT_EQ(PriorityCalculator::AllowEverythingCutoff(), - layer_tree_host() - ->contents_texture_manager() - ->ExternalPriorityCutoff()); - break; - case 3: - // Verify values were correctly passed. - EXPECT_EQ(16u * 1024u * 1024u, - layer_tree_host() - ->contents_texture_manager() - ->MaxMemoryLimitBytes()); - EXPECT_EQ(PriorityCalculator::AllowVisibleAndNearbyCutoff(), - layer_tree_host() - ->contents_texture_manager() - ->ExternalPriorityCutoff()); - EndTest(); - break; - case 4: - // Make sure no extra commits happen. - NOTREACHED(); - break; - } - } - - void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { - switch (num_commits_) { - case 1: - break; - case 2: - // This will trigger a commit because the priority cutoff has changed. - impl->SetMemoryPolicy(ManagedMemoryPolicy( - 16u * 1024u * 1024u, - gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, - 1000)); - break; - case 3: - // This will not trigger a commit because the priority cutoff has not - // changed, and there is already enough memory for all allocations. - impl->SetMemoryPolicy(ManagedMemoryPolicy( - 32u * 1024u * 1024u, - gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, - 1000)); - break; - case 4: - NOTREACHED(); - break; - } - } - - void AfterTest() override {} - - private: - int num_commits_; -}; - -SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostTestMemoryLimits); - -} // namespace - class LayerTreeHostTestSetMemoryPolicyOnLostOutputSurface : public LayerTreeHostTest { protected: @@ -4874,10 +3699,7 @@ class LayerTreeHostTestSetMemoryPolicyOnLostOutputSurface } void SetupTree() override { - if (layer_tree_host()->settings().impl_side_painting) - root_ = FakePictureLayer::Create(&client_); - else - root_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); layer_tree_host()->SetRootLayer(root_); LayerTreeHostTest::SetupTree(); @@ -5026,7 +3848,12 @@ class LayerTreeHostTestBreakSwapPromise : public LayerTreeHostTest { if (commit_complete_count_ == 1) { // This commit will be aborted because no actual update. PostSetNeedsUpdateLayersToMainThread(); - } else { + } + } + + void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { + int frame = host_impl->active_tree()->source_frame_number(); + if (frame == 2) { EndTest(); } } @@ -5079,7 +3906,7 @@ class LayerTreeHostTestKeepSwapPromise : public LayerTreeTest { LayerTreeHostTestKeepSwapPromise() {} void BeginTest() override { - layer_ = SolidColorLayer::Create(); + layer_ = SolidColorLayer::Create(layer_settings()); layer_->SetIsDrawable(true); layer_->SetBounds(gfx::Size(10, 10)); layer_tree_host()->SetRootLayer(layer_); @@ -5344,10 +4171,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSimpleSwapPromiseMonitor); class LayerTreeHostTestHighResRequiredAfterEvictingUIResources : public LayerTreeHostTest { protected: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; - } - void SetupTree() override { LayerTreeHostTest::SetupTree(); ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); @@ -5389,8 +4212,6 @@ class LayerTreeHostTestHighResRequiredAfterEvictingUIResources class LayerTreeHostTestGpuRasterizationDefault : public LayerTreeHostTest { protected: void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; - EXPECT_FALSE(settings->gpu_rasterization_enabled); EXPECT_FALSE(settings->gpu_rasterization_forced); } @@ -5398,7 +4219,8 @@ class LayerTreeHostTestGpuRasterizationDefault : public LayerTreeHostTest { void SetupTree() override { LayerTreeHostTest::SetupTree(); - scoped_refptr<PictureLayer> layer = PictureLayer::Create(&layer_client_); + scoped_refptr<PictureLayer> layer = + PictureLayer::Create(layer_settings(), &layer_client_); layer->SetBounds(gfx::Size(10, 10)); layer->SetIsDrawable(true); layer_tree_host()->root_layer()->AddChild(layer); @@ -5443,8 +4265,6 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationDefault); class LayerTreeHostTestGpuRasterizationEnabled : public LayerTreeHostTest { protected: void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; - EXPECT_FALSE(settings->gpu_rasterization_enabled); settings->gpu_rasterization_enabled = true; } @@ -5452,7 +4272,8 @@ class LayerTreeHostTestGpuRasterizationEnabled : public LayerTreeHostTest { void SetupTree() override { LayerTreeHostTest::SetupTree(); - scoped_refptr<PictureLayer> layer = PictureLayer::Create(&layer_client_); + scoped_refptr<PictureLayer> layer = + PictureLayer::Create(layer_settings(), &layer_client_); layer->SetBounds(gfx::Size(10, 10)); layer->SetIsDrawable(true); layer_tree_host()->root_layer()->AddChild(layer); @@ -5506,8 +4327,6 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationEnabled); class LayerTreeHostTestGpuRasterizationForced : public LayerTreeHostTest { protected: void InitializeSettings(LayerTreeSettings* settings) override { - ASSERT_TRUE(settings->impl_side_painting); - EXPECT_FALSE(settings->gpu_rasterization_forced); settings->gpu_rasterization_forced = true; } @@ -5516,7 +4335,7 @@ class LayerTreeHostTestGpuRasterizationForced : public LayerTreeHostTest { LayerTreeHostTest::SetupTree(); scoped_refptr<FakePictureLayer> layer = - FakePictureLayer::Create(&layer_client_); + FakePictureLayer::Create(layer_settings(), &layer_client_); layer->SetBounds(gfx::Size(10, 10)); layer->SetIsDrawable(true); layer_tree_host()->root_layer()->AddChild(layer); @@ -5565,7 +4384,7 @@ class LayerTreeHostTestGpuRasterizationForced : public LayerTreeHostTest { FakeContentLayerClient layer_client_; }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestGpuRasterizationForced); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationForced); class LayerTreeHostTestContinuousPainting : public LayerTreeHostTest { public: @@ -5576,17 +4395,11 @@ class LayerTreeHostTestContinuousPainting : public LayerTreeHostTest { enum { kExpectedNumCommits = 10 }; void SetupTree() override { - scoped_refptr<Layer> root_layer = Layer::Create(); + scoped_refptr<Layer> root_layer = Layer::Create(layer_settings()); root_layer->SetBounds(bounds_); root_layer->CreateRenderSurface(); - if (layer_tree_host()->settings().impl_side_painting) { - picture_layer_ = FakePictureLayer::Create(&client_); - child_layer_ = picture_layer_.get(); - } else { - content_layer_ = ContentLayerWithUpdateTracking::Create(&client_); - child_layer_ = content_layer_.get(); - } + child_layer_ = FakePictureLayer::Create(layer_settings(), &client_); child_layer_->SetBounds(bounds_); child_layer_->SetIsDrawable(true); root_layer->AddChild(child_layer_); @@ -5621,10 +4434,7 @@ class LayerTreeHostTestContinuousPainting : public LayerTreeHostTest { void AfterTest() override { EXPECT_LE(kExpectedNumCommits, num_commits_); EXPECT_LE(kExpectedNumCommits, num_draws_); - int update_count = content_layer_.get() - ? content_layer_->PaintContentsCount() - : picture_layer_->update_count(); - EXPECT_LE(kExpectedNumCommits, update_count); + EXPECT_LE(kExpectedNumCommits, child_layer_->update_count()); } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { @@ -5654,9 +4464,7 @@ class LayerTreeHostTestContinuousPainting : public LayerTreeHostTest { int num_draws_; const gfx::Size bounds_; FakeContentLayerClient client_; - scoped_refptr<ContentLayerWithUpdateTracking> content_layer_; - scoped_refptr<FakePictureLayer> picture_layer_; - Layer* child_layer_; + scoped_refptr<FakePictureLayer> child_layer_; }; MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousPainting); @@ -5792,10 +4600,6 @@ class LayerTreeHostTestActivateOnInvisible : public LayerTreeHostTest { LayerTreeHostTestActivateOnInvisible() : activation_count_(0), visible_(true) {} - void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; - } - void BeginTest() override { // Kick off the test with a commit. PostSetNeedsCommitToMainThread(); @@ -5841,7 +4645,8 @@ class LayerTreeHostTestActivateOnInvisible : public LayerTreeHostTest { }; // TODO(vmpstr): Enable with single thread impl-side painting. -MULTI_THREAD_TEST_F(LayerTreeHostTestActivateOnInvisible); +// This test blocks activation which is not supported for single thread mode. +MULTI_THREAD_BLOCKNOTIFY_TEST_F(LayerTreeHostTestActivateOnInvisible); // Do a synchronous composite and assert that the swap promise succeeds. class LayerTreeHostTestSynchronousCompositeSwapPromise @@ -5851,6 +4656,8 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise void InitializeSettings(LayerTreeSettings* settings) override { settings->single_thread_proxy_scheduler = false; + settings->use_zero_copy = true; + settings->use_one_copy = false; } void BeginTest() override { @@ -5858,14 +4665,14 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise scoped_ptr<SwapPromise> swap_promise0( new TestSwapPromise(&swap_promise_result_[0])); layer_tree_host()->QueueSwapPromise(swap_promise0.Pass()); - layer_tree_host()->Composite(gfx::FrameTime::Now()); + layer_tree_host()->Composite(base::TimeTicks::Now()); // Fail to swap (no damage). scoped_ptr<SwapPromise> swap_promise1( new TestSwapPromise(&swap_promise_result_[1])); layer_tree_host()->QueueSwapPromise(swap_promise1.Pass()); layer_tree_host()->SetNeedsCommit(); - layer_tree_host()->Composite(gfx::FrameTime::Now()); + layer_tree_host()->Composite(base::TimeTicks::Now()); // Fail to draw (not visible). scoped_ptr<SwapPromise> swap_promise2( @@ -5873,7 +4680,7 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise layer_tree_host()->QueueSwapPromise(swap_promise2.Pass()); layer_tree_host()->SetNeedsDisplayOnAllLayers(); layer_tree_host()->SetVisible(false); - layer_tree_host()->Composite(gfx::FrameTime::Now()); + layer_tree_host()->Composite(base::TimeTicks::Now()); EndTest(); } @@ -5919,8 +4726,7 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise TestSwapPromiseResult swap_promise_result_[3]; }; -// Impl-side painting is not supported for synchronous compositing. -SINGLE_THREAD_NOIMPL_TEST_F(LayerTreeHostTestSynchronousCompositeSwapPromise); +SINGLE_THREAD_TEST_F(LayerTreeHostTestSynchronousCompositeSwapPromise); // Make sure page scale and top control deltas are applied to the client even // when the LayerTreeHost doesn't have a root layer. @@ -5955,15 +4761,6 @@ class LayerTreeHostAcceptsDeltasFromImplWithoutRootLayer deltas_sent_to_client_ = true; } - void ApplyViewportDeltas( - const gfx::Vector2d& scroll, - float scale_delta, - float top_controls_delta) override { - EXPECT_EQ(info_.page_scale_delta, scale_delta); - EXPECT_EQ(info_.top_controls_delta, top_controls_delta); - deltas_sent_to_client_ = true; - } - void AfterTest() override { EXPECT_TRUE(deltas_sent_to_client_); } @@ -5984,21 +4781,22 @@ class LayerTreeHostTestCrispUpAfterPinchEnds : public LayerTreeHostTest { posted_ = false; client_.set_fill_with_nonsolid_color(true); - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(500, 500)); - scoped_refptr<Layer> pinch = Layer::Create(); + scoped_refptr<Layer> pinch = Layer::Create(layer_settings()); pinch->SetBounds(gfx::Size(500, 500)); pinch->SetScrollClipLayerId(root->id()); pinch->SetIsContainerForFixedPositionLayers(true); root->AddChild(pinch); scoped_ptr<FakePicturePile> pile( - new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, - ImplSidePaintingSettings().default_tile_grid_size)); + new FakePicturePile(LayerTreeSettings().minimum_contents_scale, + LayerTreeSettings().default_tile_grid_size)); pile->SetPlaybackAllowedEvent(&playback_allowed_event_); scoped_refptr<FakePictureLayer> layer = - FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass()); + FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_, + pile.Pass()); layer->SetBounds(gfx::Size(500, 500)); layer->SetContentsOpaque(true); // Avoid LCD text on the layer so we don't cause extra commits when we @@ -6026,8 +4824,8 @@ class LayerTreeHostTestCrispUpAfterPinchEnds : public LayerTreeHostTest { const TileDrawQuad* quad = TileDrawQuad::MaterialCast(draw_quad); float quad_scale = quad->tex_coord_rect.width() / static_cast<float>(quad->rect.width()); - float transform_scale = - SkMScalarToFloat(quad->quadTransform().matrix().get(0, 0)); + float transform_scale = SkMScalarToFloat( + quad->shared_quad_state->quad_to_target_transform.matrix().get(0, 0)); float scale = quad_scale / transform_scale; if (frame_scale != 0.f && frame_scale != scale) return 0.f; @@ -6156,7 +4954,9 @@ class LayerTreeHostTestCrispUpAfterPinchEnds : public LayerTreeHostTest { base::WaitableEvent playback_allowed_event_; }; -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestCrispUpAfterPinchEnds); +// This test does pinching on the impl side which is not supported in single +// thread. +MULTI_THREAD_TEST_F(LayerTreeHostTestCrispUpAfterPinchEnds); class LayerTreeHostTestCrispUpAfterPinchEndsWithOneCopy : public LayerTreeHostTestCrispUpAfterPinchEnds { @@ -6181,28 +4981,30 @@ class LayerTreeHostTestCrispUpAfterPinchEndsWithOneCopy } }; -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestCrispUpAfterPinchEndsWithOneCopy); +// This test does pinching on the impl side which is not supported in single +// thread. +MULTI_THREAD_TEST_F(LayerTreeHostTestCrispUpAfterPinchEndsWithOneCopy); class RasterizeWithGpuRasterizationCreatesResources : public LayerTreeHostTest { protected: RasterizeWithGpuRasterizationCreatesResources() {} void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; settings->gpu_rasterization_forced = true; } void SetupTree() override { client_.set_fill_with_nonsolid_color(true); - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(500, 500)); scoped_ptr<FakePicturePile> pile( - new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, - ImplSidePaintingSettings().default_tile_grid_size)); + new FakePicturePile(LayerTreeSettings().minimum_contents_scale, + LayerTreeSettings().default_tile_grid_size)); scoped_refptr<FakePictureLayer> layer = - FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass()); + FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_, + pile.Pass()); layer->SetBounds(gfx::Size(500, 500)); layer->SetContentsOpaque(true); root->AddChild(layer); @@ -6225,14 +5027,13 @@ class RasterizeWithGpuRasterizationCreatesResources : public LayerTreeHostTest { FakeContentLayerClient client_; }; -MULTI_THREAD_IMPL_TEST_F(RasterizeWithGpuRasterizationCreatesResources); +SINGLE_AND_MULTI_THREAD_TEST_F(RasterizeWithGpuRasterizationCreatesResources); class GpuRasterizationRasterizesBorderTiles : public LayerTreeHostTest { protected: GpuRasterizationRasterizesBorderTiles() : viewport_size_(1024, 2048) {} void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; settings->gpu_rasterization_enabled = true; settings->gpu_rasterization_forced = true; } @@ -6241,10 +5042,11 @@ class GpuRasterizationRasterizesBorderTiles : public LayerTreeHostTest { client_.set_fill_with_nonsolid_color(true); scoped_ptr<FakePicturePile> pile( - new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, - ImplSidePaintingSettings().default_tile_grid_size)); + new FakePicturePile(LayerTreeSettings().minimum_contents_scale, + LayerTreeSettings().default_tile_grid_size)); scoped_refptr<FakePictureLayer> root = - FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass()); + FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_, + pile.Pass()); root->SetBounds(gfx::Size(10000, 10000)); root->SetContentsOpaque(true); @@ -6270,7 +5072,7 @@ class GpuRasterizationRasterizesBorderTiles : public LayerTreeHostTest { gfx::Size viewport_size_; }; -MULTI_THREAD_IMPL_TEST_F(GpuRasterizationRasterizesBorderTiles); +SINGLE_AND_MULTI_THREAD_TEST_F(GpuRasterizationRasterizesBorderTiles); class LayerTreeHostTestContinuousDrawWhenCreatingVisibleTiles : public LayerTreeHostTest { @@ -6278,30 +5080,27 @@ class LayerTreeHostTestContinuousDrawWhenCreatingVisibleTiles LayerTreeHostTestContinuousDrawWhenCreatingVisibleTiles() : playback_allowed_event_(true, true) {} - void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; - } - void SetupTree() override { step_ = 1; continuous_draws_ = 0; client_.set_fill_with_nonsolid_color(true); - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(500, 500)); - scoped_refptr<Layer> pinch = Layer::Create(); + scoped_refptr<Layer> pinch = Layer::Create(layer_settings()); pinch->SetBounds(gfx::Size(500, 500)); pinch->SetScrollClipLayerId(root->id()); pinch->SetIsContainerForFixedPositionLayers(true); root->AddChild(pinch); scoped_ptr<FakePicturePile> pile( - new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, - ImplSidePaintingSettings().default_tile_grid_size)); + new FakePicturePile(LayerTreeSettings().minimum_contents_scale, + LayerTreeSettings().default_tile_grid_size)); pile->SetPlaybackAllowedEvent(&playback_allowed_event_); scoped_refptr<FakePictureLayer> layer = - FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass()); + FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_, + pile.Pass()); layer->SetBounds(gfx::Size(500, 500)); layer->SetContentsOpaque(true); // Avoid LCD text on the layer so we don't cause extra commits when we @@ -6326,8 +5125,8 @@ class LayerTreeHostTestContinuousDrawWhenCreatingVisibleTiles const TileDrawQuad* quad = TileDrawQuad::MaterialCast(draw_quad); float quad_scale = quad->tex_coord_rect.width() / static_cast<float>(quad->rect.width()); - float transform_scale = - SkMScalarToFloat(quad->quadTransform().matrix().get(0, 0)); + float transform_scale = SkMScalarToFloat( + quad->shared_quad_state->quad_to_target_transform.matrix().get(0, 0)); float scale = quad_scale / transform_scale; if (frame_scale != 0.f && frame_scale != scale) return 0.f; @@ -6460,7 +5259,7 @@ class LayerTreeHostTestOneActivatePerPrepareTiles : public LayerTreeHostTest { void SetupTree() override { client_.set_fill_with_nonsolid_color(true); scoped_refptr<FakePictureLayer> root_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); root_layer->SetBounds(gfx::Size(1500, 1500)); root_layer->SetIsDrawable(true); @@ -6505,7 +5304,7 @@ class LayerTreeHostTestOneActivatePerPrepareTiles : public LayerTreeHostTest { size_t scheduled_prepare_tiles_count_; }; -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestOneActivatePerPrepareTiles); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestOneActivatePerPrepareTiles); class LayerTreeHostTestFrameTimingRequestsSaveTimestamps : public LayerTreeHostTest { @@ -6515,12 +5314,12 @@ class LayerTreeHostTestFrameTimingRequestsSaveTimestamps void SetupTree() override { scoped_refptr<FakePictureLayer> root_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); root_layer->SetBounds(gfx::Size(200, 200)); root_layer->SetIsDrawable(true); scoped_refptr<FakePictureLayer> child_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); child_layer->SetBounds(gfx::Size(1500, 1500)); child_layer->SetIsDrawable(true); @@ -6591,7 +5390,8 @@ class LayerTreeHostTestFrameTimingRequestsSaveTimestamps bool check_results_on_commit_; }; -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestFrameTimingRequestsSaveTimestamps); +// Frame timing is not implemented in single thread proxy. +MULTI_THREAD_TEST_F(LayerTreeHostTestFrameTimingRequestsSaveTimestamps); class LayerTreeHostTestActivationCausesPrepareTiles : public LayerTreeHostTest { public: @@ -6601,7 +5401,7 @@ class LayerTreeHostTestActivationCausesPrepareTiles : public LayerTreeHostTest { void SetupTree() override { client_.set_fill_with_nonsolid_color(true); scoped_refptr<FakePictureLayer> root_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); root_layer->SetBounds(gfx::Size(150, 150)); root_layer->SetIsDrawable(true); @@ -6635,7 +5435,9 @@ class LayerTreeHostTestActivationCausesPrepareTiles : public LayerTreeHostTest { int scheduled_prepare_tiles_count_; }; -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestActivationCausesPrepareTiles); +// This test is testing activation from a pending tree and doesn't make sense +// with single thread commit-to-active. +MULTI_THREAD_TEST_F(LayerTreeHostTestActivationCausesPrepareTiles); // This tests an assertion that DidCommit and WillCommit happen in the same // stack frame with no tasks that run between them. Various embedders of @@ -6674,90 +5476,11 @@ class LayerTreeHostTestNoTasksBetweenWillAndDidCommit SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestNoTasksBetweenWillAndDidCommit); -// Verify that if a LayerImpl holds onto a copy request for multiple -// frames that it will continue to have a render surface through -// multiple commits, even though the Layer itself has no reason -// to have a render surface. -class LayerPreserveRenderSurfaceFromOutputRequests : public LayerTreeHostTest { - protected: - void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); - root->CreateRenderSurface(); - root->SetBounds(gfx::Size(10, 10)); - child_ = Layer::Create(); - child_->SetBounds(gfx::Size(20, 20)); - root->AddChild(child_); - - layer_tree_host()->SetRootLayer(root); - LayerTreeHostTest::SetupTree(); - } - - static void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {} - - void BeginTest() override { - child_->RequestCopyOfOutput( - CopyOutputRequest::CreateBitmapRequest(base::Bind(CopyOutputCallback))); - EXPECT_TRUE(child_->HasCopyRequest()); - PostSetNeedsCommitToMainThread(); - } - - void DidCommit() override { EXPECT_FALSE(child_->HasCopyRequest()); } - - void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { - LayerImpl* child_impl = host_impl->sync_tree()->LayerById(child_->id()); - - switch (host_impl->sync_tree()->source_frame_number()) { - case 0: - EXPECT_TRUE(child_impl->HasCopyRequest()); - EXPECT_TRUE(child_impl->render_surface()); - break; - case 1: - if (host_impl->proxy()->CommitToActiveTree()) { - EXPECT_TRUE(child_impl->HasCopyRequest()); - EXPECT_TRUE(child_impl->render_surface()); - } else { - EXPECT_FALSE(child_impl->HasCopyRequest()); - EXPECT_FALSE(child_impl->render_surface()); - } - break; - default: - NOTREACHED(); - break; - } - } - - void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { - LayerImpl* child_impl = host_impl->active_tree()->LayerById(child_->id()); - EXPECT_TRUE(child_impl->HasCopyRequest()); - EXPECT_TRUE(child_impl->render_surface()); - - switch (host_impl->active_tree()->source_frame_number()) { - case 0: - // Lose output surface to prevent drawing and cause another commit. - host_impl->DidLoseOutputSurface(); - break; - case 1: - EndTest(); - break; - default: - NOTREACHED(); - break; - } - } - - void AfterTest() override {} - - private: - scoped_refptr<Layer> child_; -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerPreserveRenderSurfaceFromOutputRequests); - class LayerTreeHostTestUpdateCopyRequests : public LayerTreeHostTest { protected: void SetupTree() override { - root = Layer::Create(); - child = Layer::Create(); + root = Layer::Create(layer_settings()); + child = Layer::Create(layer_settings()); root->AddChild(child); layer_tree_host()->SetRootLayer(root); LayerTreeHostTest::SetupTree(); @@ -6799,21 +5522,21 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { // the surface bounds to be larger. It also has a parent that clips the // masked layer and its surface. - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); - scoped_refptr<Layer> clipping_layer = Layer::Create(); + scoped_refptr<Layer> clipping_layer = Layer::Create(layer_settings()); root->AddChild(clipping_layer); scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); clipping_layer->AddChild(content_layer); scoped_refptr<FakePictureLayer> content_child_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); content_layer->AddChild(content_child_layer); scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); content_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -6893,17 +5616,17 @@ class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { // +-- Content Layer // +--Mask - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); - scoped_refptr<Layer> scaling_layer = Layer::Create(); + scoped_refptr<Layer> scaling_layer = Layer::Create(layer_settings()); root->AddChild(scaling_layer); scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); scaling_layer->AddChild(content_layer); scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); content_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -6988,14 +5711,14 @@ class LayerTreeTestMaskLayerWithDifferentBounds : public LayerTreeTest { // The mask layer has bounds 100x100 but is attached to a layer with bounds // 50x50. - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); root->AddChild(content_layer); scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); content_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -7076,17 +5799,17 @@ class LayerTreeTestReflectionMaskLayerWithDifferentBounds // The replica's mask layer has bounds 100x100 but the replica is of a // layer with bounds 50x50. - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); root->AddChild(content_layer); - scoped_refptr<Layer> replica_layer = Layer::Create(); + scoped_refptr<Layer> replica_layer = Layer::Create(layer_settings()); content_layer->SetReplicaLayer(replica_layer.get()); scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); replica_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -7169,20 +5892,20 @@ class LayerTreeTestReflectionMaskLayerForSurfaceWithUnclippedChild // The replica is of a layer with bounds 50x50, but it has a child that // causes the surface bounds to be larger. - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); root->AddChild(content_layer); - content_child_layer_ = FakePictureLayer::Create(&client_); + content_child_layer_ = FakePictureLayer::Create(layer_settings(), &client_); content_layer->AddChild(content_child_layer_); - scoped_refptr<Layer> replica_layer = Layer::Create(); + scoped_refptr<Layer> replica_layer = Layer::Create(layer_settings()); content_layer->SetReplicaLayer(replica_layer.get()); scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); replica_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -7262,4 +5985,77 @@ class LayerTreeTestReflectionMaskLayerForSurfaceWithUnclippedChild SINGLE_AND_MULTI_THREAD_TEST_F( LayerTreeTestReflectionMaskLayerForSurfaceWithUnclippedChild); +class LayerTreeTestPageScaleFlags : public LayerTreeTest { + protected: + void SetupTree() override { + // -root + // -pre page scale + // -page scale + // -page scale child1 + // -page scale grandchild + // -page scale child2 + // -post page scale + + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + scoped_refptr<Layer> pre_page_scale = Layer::Create(layer_settings()); + scoped_refptr<Layer> page_scale = Layer::Create(layer_settings()); + scoped_refptr<Layer> page_scale_child1 = Layer::Create(layer_settings()); + scoped_refptr<Layer> page_scale_grandchild = + Layer::Create(layer_settings()); + scoped_refptr<Layer> page_scale_child2 = Layer::Create(layer_settings()); + scoped_refptr<Layer> post_page_scale = Layer::Create(layer_settings()); + + root->AddChild(pre_page_scale); + root->AddChild(page_scale); + root->AddChild(post_page_scale); + + page_scale->AddChild(page_scale_child1); + page_scale->AddChild(page_scale_child2); + page_scale_child1->AddChild(page_scale_grandchild); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + + scoped_refptr<Layer> overscroll_elasticity_layer = nullptr; + scoped_refptr<Layer> inner_viewport_scroll_layer = nullptr; + scoped_refptr<Layer> outer_viewport_scroll_layer = nullptr; + layer_tree_host()->RegisterViewportLayers( + overscroll_elasticity_layer, page_scale, inner_viewport_scroll_layer, + outer_viewport_scroll_layer); + + affected_by_page_scale_.push_back(page_scale->id()); + affected_by_page_scale_.push_back(page_scale_child1->id()); + affected_by_page_scale_.push_back(page_scale_child2->id()); + affected_by_page_scale_.push_back(page_scale_grandchild->id()); + + not_affected_by_page_scale_.push_back(root->id()); + not_affected_by_page_scale_.push_back(pre_page_scale->id()); + not_affected_by_page_scale_.push_back(post_page_scale->id()); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { + LayerTreeHostCommon::CallFunctionForSubtree( + host_impl->sync_tree()->root_layer(), [this](LayerImpl* layer) { + const std::vector<int>& list = + layer->IsAffectedByPageScale() + ? this->affected_by_page_scale_ + : this->not_affected_by_page_scale_; + EXPECT_TRUE(std::find(list.begin(), list.end(), layer->id()) != + list.end()); + }); + + EndTest(); + } + + void AfterTest() override {} + + std::vector<int> affected_by_page_scale_; + std::vector<int> not_affected_by_page_scale_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestPageScaleFlags); + +} // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation.cc b/chromium/cc/trees/layer_tree_host_unittest_animation.cc index ed27a03a2f8..9b16e39cb83 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc @@ -12,8 +12,8 @@ #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" #include "cc/test/animation_test_common.h" -#include "cc/test/fake_content_layer.h" #include "cc/test/fake_content_layer_client.h" +#include "cc/test/fake_picture_layer.h" #include "cc/test/layer_tree_test.h" #include "cc/trees/layer_tree_impl.h" @@ -231,12 +231,12 @@ class LayerTreeHostAnimationTestAddAnimationWithTimingFunction void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); - content_ = FakeContentLayer::Create(&client_); - content_->SetBounds(gfx::Size(4, 4)); - layer_tree_host()->root_layer()->AddChild(content_); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_->SetBounds(gfx::Size(4, 4)); + layer_tree_host()->root_layer()->AddChild(picture_); } - void BeginTest() override { PostAddAnimationToMainThread(content_.get()); } + void BeginTest() override { PostAddAnimationToMainThread(picture_.get()); } void AnimateLayers(LayerTreeHostImpl* host_impl, base::TimeTicks monotonic_time) override { @@ -265,7 +265,7 @@ class LayerTreeHostAnimationTestAddAnimationWithTimingFunction void AfterTest() override {} FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> content_; + scoped_refptr<FakePictureLayer> picture_; }; SINGLE_AND_MULTI_THREAD_TEST_F( @@ -280,13 +280,13 @@ class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); - content_ = FakeContentLayer::Create(&client_); - content_->SetBounds(gfx::Size(4, 4)); - content_->set_layer_animation_delegate(this); - layer_tree_host()->root_layer()->AddChild(content_); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_->SetBounds(gfx::Size(4, 4)); + picture_->set_layer_animation_delegate(this); + layer_tree_host()->root_layer()->AddChild(picture_); } - void BeginTest() override { PostAddAnimationToMainThread(content_.get()); } + void BeginTest() override { PostAddAnimationToMainThread(picture_.get()); } void NotifyAnimationStarted(base::TimeTicks monotonic_time, Animation::TargetProperty target_property, @@ -321,7 +321,7 @@ class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes base::TimeTicks main_start_time_; base::TimeTicks impl_start_time_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> content_; + scoped_refptr<FakePictureLayer> picture_; }; SINGLE_AND_MULTI_THREAD_TEST_F( @@ -360,8 +360,8 @@ class LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity : public LayerTreeHostAnimationTest { public: LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity() - : update_check_layer_(FakeContentLayer::Create(&client_)) { - } + : update_check_layer_( + FakePictureLayer::Create(layer_settings(), &client_)) {} void SetupTree() override { update_check_layer_->SetOpacity(0.f); @@ -385,7 +385,7 @@ class LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity void AfterTest() override { // Update() should have been called once, proving that the layer was not // skipped. - EXPECT_EQ(1u, update_check_layer_->update_count()); + EXPECT_EQ(1, update_check_layer_->update_count()); // clear update_check_layer_ so LayerTreeHost dies. update_check_layer_ = NULL; @@ -393,7 +393,7 @@ class LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity private: FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> update_check_layer_; + scoped_refptr<FakePictureLayer> update_check_layer_; }; SINGLE_AND_MULTI_THREAD_TEST_F( @@ -410,7 +410,7 @@ class LayerTreeHostAnimationTestLayerAddedWithAnimation void DidCommit() override { if (layer_tree_host()->source_frame_number() == 1) { - scoped_refptr<Layer> layer = Layer::Create(); + scoped_refptr<Layer> layer = Layer::Create(layer_settings()); layer->set_layer_animation_delegate(this); // Any valid AnimationCurve will do here. @@ -475,8 +475,6 @@ class LayerTreeHostAnimationTestCancelAnimateCommit int num_begin_frames_; int num_commit_calls_; int num_draw_calls_; - FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> content_; }; MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCancelAnimateCommit); @@ -558,15 +556,15 @@ class LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); - content_ = FakeContentLayer::Create(&client_); - content_->SetBounds(gfx::Size(4, 4)); - content_->set_layer_animation_delegate(this); - layer_tree_host()->root_layer()->AddChild(content_); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_->SetBounds(gfx::Size(4, 4)); + picture_->set_layer_animation_delegate(this); + layer_tree_host()->root_layer()->AddChild(picture_); } void BeginTest() override { layer_tree_host()->SetViewportSize(gfx::Size()); - PostAddAnimationToMainThread(content_.get()); + PostAddAnimationToMainThread(picture_.get()); } void NotifyAnimationStarted(base::TimeTicks monotonic_time, @@ -586,7 +584,7 @@ class LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw private: int started_times_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> content_; + scoped_refptr<FakePictureLayer> picture_; }; SINGLE_AND_MULTI_THREAD_TEST_F( @@ -598,10 +596,10 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations : public LayerTreeHostAnimationTest { void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); - content_ = FakeContentLayer::Create(&client_); - content_->SetBounds(gfx::Size(4, 4)); - content_->set_layer_animation_delegate(this); - layer_tree_host()->root_layer()->AddChild(content_); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_->SetBounds(gfx::Size(4, 4)); + picture_->set_layer_animation_delegate(this); + layer_tree_host()->root_layer()->AddChild(picture_); } void InitializeSettings(LayerTreeSettings* settings) override { @@ -636,12 +634,12 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations switch (layer_tree_host()->source_frame_number()) { case 1: // The animation is longer than 1 BeginFrame interval. - AddOpacityTransitionToLayer(content_.get(), 0.1, 0.2f, 0.8f, false); + AddOpacityTransitionToLayer(picture_.get(), 0.1, 0.2f, 0.8f, false); added_animations_++; break; case 2: // This second animation will not be drawn so it should not start. - AddAnimatedTransformToLayer(content_.get(), 0.1, 5, 5); + AddAnimatedTransformToLayer(picture_.get(), 0.1, 5, 5); added_animations_++; break; } @@ -667,7 +665,7 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations int added_animations_; int started_times_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> content_; + scoped_refptr<FakePictureLayer> picture_; }; MULTI_THREAD_TEST_F( @@ -684,7 +682,7 @@ class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); - scroll_layer_ = FakeContentLayer::Create(&client_); + scroll_layer_ = FakePictureLayer::Create(layer_settings(), &client_); scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id()); scroll_layer_->SetBounds(gfx::Size(1000, 1000)); scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20)); @@ -722,7 +720,7 @@ class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated private: FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> scroll_layer_; + scoped_refptr<FakePictureLayer> scroll_layer_; }; SINGLE_AND_MULTI_THREAD_TEST_F( @@ -741,7 +739,7 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); - scroll_layer_ = FakeContentLayer::Create(&client_); + scroll_layer_ = FakePictureLayer::Create(layer_settings(), &client_); scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id()); scroll_layer_->SetBounds(gfx::Size(10000, 10000)); scroll_layer_->SetScrollOffset(gfx::ScrollOffset(100.0, 200.0)); @@ -777,8 +775,7 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval } void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override { - if (host_impl->settings().impl_side_painting) - host_impl->BlockNotifyReadyToActivateForTesting(true); + host_impl->BlockNotifyReadyToActivateForTesting(true); } void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl, @@ -812,8 +809,6 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval } void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { - if (!host_impl->settings().impl_side_painting) - return; if (host_impl->pending_tree()->source_frame_number() != 1) return; LayerImpl* scroll_layer_impl = @@ -836,7 +831,7 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval private: FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> scroll_layer_; + scoped_refptr<FakePictureLayer> scroll_layer_; const gfx::ScrollOffset final_postion_; }; @@ -860,7 +855,7 @@ class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers AddOpacityTransitionToLayer( layer_tree_host()->root_layer(), 1, 0.f, 0.5f, true); - scoped_refptr<Layer> layer = Layer::Create(); + scoped_refptr<Layer> layer = Layer::Create(layer_settings()); layer_tree_host()->root_layer()->AddChild(layer); layer->set_layer_animation_delegate(this); layer->SetBounds(gfx::Size(4, 4)); @@ -869,8 +864,7 @@ class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers } void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override { - if (host_impl->settings().impl_side_painting) - host_impl->BlockNotifyReadyToActivateForTesting(true); + host_impl->BlockNotifyReadyToActivateForTesting(true); } void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { @@ -878,8 +872,7 @@ class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers // blocking activation. We want to verify that even with activation blocked, // the animation on the layer that's already in the active tree won't get a // head start. - if (host_impl->settings().impl_side_painting && - host_impl->pending_tree()->source_frame_number() != 2) { + if (host_impl->pending_tree()->source_frame_number() != 2) { host_impl->BlockNotifyReadyToActivateForTesting(false); } } @@ -891,8 +884,7 @@ class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers return; frame_count_with_pending_tree_++; - if (frame_count_with_pending_tree_ == 2 && - host_impl->settings().impl_side_painting) { + if (frame_count_with_pending_tree_ == 2) { host_impl->BlockNotifyReadyToActivateForTesting(false); } } @@ -925,20 +917,70 @@ class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers int frame_count_with_pending_tree_; }; -SINGLE_AND_MULTI_THREAD_BLOCKNOTIFY_TEST_F( +// This test blocks activation which is not supported for single thread mode. +MULTI_THREAD_BLOCKNOTIFY_TEST_F( LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers); -class LayerTreeHostAnimationTestAddAnimationAfterAnimating +// When a layer with an animation is removed from the tree and later re-added, +// the animation should resume. +class LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded : public LayerTreeHostAnimationTest { public: - LayerTreeHostAnimationTestAddAnimationAfterAnimating() - : num_swap_buffers_(0) {} + LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded() {} + + void SetupTree() override { + LayerTreeHostAnimationTest::SetupTree(); + layer_ = Layer::Create(layer_settings()); + layer_->SetBounds(gfx::Size(4, 4)); + layer_tree_host()->root_layer()->AddChild(layer_); + AddOpacityTransitionToLayer(layer_.get(), 10000.0, 0.1f, 0.9f, true); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void DidCommit() override { + switch (layer_tree_host()->source_frame_number()) { + case 1: + layer_->RemoveFromParent(); + break; + case 2: + layer_tree_host()->root_layer()->AddChild(layer_); + break; + } + } + void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { + switch (host_impl->active_tree()->source_frame_number()) { + case 0: + EXPECT_TRUE(host_impl->animation_registrar()->needs_animate_layers()); + break; + case 1: + EXPECT_FALSE(host_impl->animation_registrar()->needs_animate_layers()); + break; + case 2: + EXPECT_TRUE(host_impl->animation_registrar()->needs_animate_layers()); + EndTest(); + break; + } + } + + void AfterTest() override {} + + private: + scoped_refptr<Layer> layer_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded); + +class LayerTreeHostAnimationTestAddAnimationAfterAnimating + : public LayerTreeHostAnimationTest { + public: void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); - content_ = Layer::Create(); - content_->SetBounds(gfx::Size(4, 4)); - layer_tree_host()->root_layer()->AddChild(content_); + layer_ = Layer::Create(layer_settings()); + layer_->SetBounds(gfx::Size(4, 4)); + layer_tree_host()->root_layer()->AddChild(layer_); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -952,7 +994,7 @@ class LayerTreeHostAnimationTestAddAnimationAfterAnimating case 2: // Second frame: add an animation to the content layer. The root layer // animation has caused us to animate already during this frame. - AddOpacityTransitionToLayer(content_.get(), 0.1, 5, 5, false); + AddOpacityTransitionToLayer(layer_.get(), 0.1, 5, 5, false); break; } } @@ -960,35 +1002,83 @@ class LayerTreeHostAnimationTestAddAnimationAfterAnimating void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { // After both animations have started, verify that they have valid // start times. - num_swap_buffers_++; + if (host_impl->active_tree()->source_frame_number() < 2) + return; AnimationRegistrar::AnimationControllerMap controllers_copy = host_impl->animation_registrar() ->active_animation_controllers_for_testing(); - if (controllers_copy.size() == 2u) { - EndTest(); - EXPECT_GE(num_swap_buffers_, 3); - for (auto& it : controllers_copy) { - int id = it.first; - if (id == host_impl->RootLayer()->id()) { - Animation* anim = it.second->GetAnimation(Animation::TRANSFORM); - EXPECT_GT((anim->start_time() - base::TimeTicks()).InSecondsF(), 0); - } else if (id == host_impl->RootLayer()->children()[0]->id()) { - Animation* anim = it.second->GetAnimation(Animation::OPACITY); - EXPECT_GT((anim->start_time() - base::TimeTicks()).InSecondsF(), 0); - } + EXPECT_EQ(2u, controllers_copy.size()); + for (auto& it : controllers_copy) { + int id = it.first; + if (id == host_impl->RootLayer()->id()) { + Animation* anim = it.second->GetAnimation(Animation::TRANSFORM); + EXPECT_GT((anim->start_time() - base::TimeTicks()).InSecondsF(), 0); + } else if (id == host_impl->RootLayer()->children()[0]->id()) { + Animation* anim = it.second->GetAnimation(Animation::OPACITY); + EXPECT_GT((anim->start_time() - base::TimeTicks()).InSecondsF(), 0); } + EndTest(); } } void AfterTest() override {} private: - scoped_refptr<Layer> content_; - int num_swap_buffers_; + scoped_refptr<Layer> layer_; }; SINGLE_AND_MULTI_THREAD_TEST_F( LayerTreeHostAnimationTestAddAnimationAfterAnimating); +class LayerTreeHostAnimationTestNotifyAnimationFinished + : public LayerTreeHostAnimationTest { + public: + LayerTreeHostAnimationTestNotifyAnimationFinished() + : called_animation_started_(false), called_animation_finished_(false) {} + + void SetupTree() override { + LayerTreeHostAnimationTest::SetupTree(); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_->SetBounds(gfx::Size(4, 4)); + picture_->set_layer_animation_delegate(this); + layer_tree_host()->root_layer()->AddChild(picture_); + } + + void BeginTest() override { + layer_tree_host()->SetViewportSize(gfx::Size()); + PostAddLongAnimationToMainThread(picture_.get()); + } + + void NotifyAnimationStarted(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + called_animation_started_ = true; + layer_tree_host()->AnimateLayers( + base::TimeTicks::FromInternalValue(std::numeric_limits<int64>::max())); + PostSetNeedsCommitToMainThread(); + } + + void NotifyAnimationFinished(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + called_animation_finished_ = true; + EndTest(); + } + + void AfterTest() override { + EXPECT_TRUE(called_animation_started_); + EXPECT_TRUE(called_animation_finished_); + } + + private: + bool called_animation_started_; + bool called_animation_finished_; + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> picture_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostAnimationTestNotifyAnimationFinished); + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation_timelines.cc b/chromium/cc/trees/layer_tree_host_unittest_animation_timelines.cc new file mode 100644 index 00000000000..4bf8e83d221 --- /dev/null +++ b/chromium/cc/trees/layer_tree_host_unittest_animation_timelines.cc @@ -0,0 +1,923 @@ +// Copyright 2015 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.h" + +#include "cc/animation/animation_curve.h" +#include "cc/animation/animation_host.h" +#include "cc/animation/animation_id_provider.h" +#include "cc/animation/animation_player.h" +#include "cc/animation/animation_timeline.h" +#include "cc/animation/element_animations.h" +#include "cc/animation/layer_animation_controller.h" +#include "cc/animation/scroll_offset_animation_curve.h" +#include "cc/animation/timing_function.h" +#include "cc/base/time_util.h" +#include "cc/layers/layer.h" +#include "cc/layers/layer_impl.h" +#include "cc/test/animation_test_common.h" +#include "cc/test/fake_content_layer_client.h" +#include "cc/test/fake_picture_layer.h" +#include "cc/test/layer_tree_test.h" +#include "cc/trees/layer_tree_impl.h" + +namespace cc { +namespace { + +class LayerTreeHostTimelinesTest : public LayerTreeTest { + public: + LayerTreeHostTimelinesTest() + : timeline_id_(AnimationIdProvider::NextTimelineId()), + player_id_(AnimationIdProvider::NextPlayerId()), + player_child_id_(AnimationIdProvider::NextPlayerId()) { + timeline_ = AnimationTimeline::Create(timeline_id_); + player_ = AnimationPlayer::Create(player_id_); + player_child_ = AnimationPlayer::Create(player_child_id_); + + player_->set_layer_animation_delegate(this); + } + + void InitializeSettings(LayerTreeSettings* settings) override { + settings->use_compositor_animation_timelines = true; + } + + void InitializeLayerSettings(LayerSettings* layer_settings) override { + layer_settings->use_compositor_animation_timelines = true; + } + + void SetupTree() override { LayerTreeTest::SetupTree(); } + + void AttachPlayersToTimeline() { + layer_tree_host()->animation_host()->AddAnimationTimeline(timeline_.get()); + timeline_->AttachPlayer(player_.get()); + timeline_->AttachPlayer(player_child_.get()); + } + + protected: + scoped_refptr<AnimationTimeline> timeline_; + scoped_refptr<AnimationPlayer> player_; + scoped_refptr<AnimationPlayer> player_child_; + + const int timeline_id_; + const int player_id_; + const int player_child_id_; +}; + +// Add a layer animation and confirm that +// LayerTreeHostImpl::UpdateAnimationState does get called. +// Evolved frome LayerTreeHostAnimationTestAddAnimation +class LayerTreeHostTimelinesTestAddAnimation + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestAddAnimation() + : update_animation_state_was_called_(false) {} + + void BeginTest() override { + AttachPlayersToTimeline(); + player_->AttachLayer(layer_tree_host()->root_layer()->id()); + PostAddInstantAnimationToMainThreadPlayer(player_.get()); + } + + void UpdateAnimationState(LayerTreeHostImpl* host_impl, + bool has_unfinished_animation) override { + EXPECT_FALSE(has_unfinished_animation); + update_animation_state_was_called_ = true; + } + + void NotifyAnimationStarted(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + EXPECT_LT(base::TimeTicks(), monotonic_time); + + LayerAnimationController* controller = + player_->element_animations()->layer_animation_controller(); + Animation* animation = controller->GetAnimation(Animation::OPACITY); + if (animation) + player_->RemoveAnimation(animation->id()); + + EndTest(); + } + + void AfterTest() override { EXPECT_TRUE(update_animation_state_was_called_); } + + private: + bool update_animation_state_was_called_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTimelinesTestAddAnimation); + +// Add a layer animation to a layer, but continually fail to draw. Confirm that +// after a while, we do eventually force a draw. +// Evolved from LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws. +class LayerTreeHostTimelinesTestCheckerboardDoesNotStarveDraws + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestCheckerboardDoesNotStarveDraws() + : started_animating_(false) {} + + void BeginTest() override { + AttachPlayersToTimeline(); + player_->AttachLayer(layer_tree_host()->root_layer()->id()); + PostAddAnimationToMainThreadPlayer(player_.get()); + } + + void AnimateLayers(LayerTreeHostImpl* host_impl, + base::TimeTicks monotonic_time) override { + started_animating_ = true; + } + + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { + if (started_animating_) + EndTest(); + } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame, + DrawResult draw_result) override { + return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS; + } + + void AfterTest() override {} + + private: + bool started_animating_; +}; + +// Starvation can only be an issue with the MT compositor. +MULTI_THREAD_TEST_F(LayerTreeHostTimelinesTestCheckerboardDoesNotStarveDraws); + +// Ensures that animations eventually get deleted. +// Evolved from LayerTreeHostAnimationTestAnimationsGetDeleted. +class LayerTreeHostTimelinesTestAnimationsGetDeleted + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestAnimationsGetDeleted() + : started_animating_(false) {} + + void BeginTest() override { + AttachPlayersToTimeline(); + player_->AttachLayer(layer_tree_host()->root_layer()->id()); + PostAddAnimationToMainThreadPlayer(player_.get()); + } + + void AnimateLayers(LayerTreeHostImpl* host_impl, + base::TimeTicks monotonic_time) override { + bool have_animations = !host_impl->animation_host() + ->animation_registrar() + ->active_animation_controllers_for_testing() + .empty(); + if (!started_animating_ && have_animations) { + started_animating_ = true; + return; + } + + if (started_animating_ && !have_animations) + EndTest(); + } + + void NotifyAnimationFinished(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + // Animations on the impl-side controller only get deleted during a commit, + // so we need to schedule a commit. + layer_tree_host()->SetNeedsCommit(); + } + + void AfterTest() override {} + + private: + bool started_animating_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTimelinesTestAnimationsGetDeleted); + +// Ensure that an animation's timing function is respected. +// Evolved from LayerTreeHostAnimationTestAddAnimationWithTimingFunction. +class LayerTreeHostTimelinesTestAddAnimationWithTimingFunction + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestAddAnimationWithTimingFunction() {} + + void SetupTree() override { + LayerTreeHostTimelinesTest::SetupTree(); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_->SetBounds(gfx::Size(4, 4)); + layer_tree_host()->root_layer()->AddChild(picture_); + + AttachPlayersToTimeline(); + player_child_->AttachLayer(picture_->id()); + } + + void BeginTest() override { + PostAddAnimationToMainThreadPlayer(player_child_.get()); + } + + void AnimateLayers(LayerTreeHostImpl* host_impl, + base::TimeTicks monotonic_time) override { + scoped_refptr<AnimationTimeline> timeline_impl = + host_impl->animation_host()->GetTimelineById(timeline_id_); + scoped_refptr<AnimationPlayer> player_child_impl = + timeline_impl->GetPlayerById(player_child_id_); + + LayerAnimationController* controller_impl = + player_child_impl->element_animations()->layer_animation_controller(); + if (!controller_impl) + return; + + Animation* animation = controller_impl->GetAnimation(Animation::OPACITY); + if (!animation) + return; + + const FloatAnimationCurve* curve = + animation->curve()->ToFloatAnimationCurve(); + float start_opacity = curve->GetValue(base::TimeDelta()); + float end_opacity = curve->GetValue(curve->Duration()); + float linearly_interpolated_opacity = + 0.25f * end_opacity + 0.75f * start_opacity; + base::TimeDelta time = TimeUtil::Scale(curve->Duration(), 0.25f); + // If the linear timing function associated with this animation was not + // picked up, then the linearly interpolated opacity would be different + // because of the default ease timing function. + EXPECT_FLOAT_EQ(linearly_interpolated_opacity, curve->GetValue(time)); + + EndTest(); + } + + void AfterTest() override {} + + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> picture_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTimelinesTestAddAnimationWithTimingFunction); + +// Ensures that main thread animations have their start times synchronized with +// impl thread animations. +// Evolved from LayerTreeHostAnimationTestSynchronizeAnimationStartTimes. +class LayerTreeHostTimelinesTestSynchronizeAnimationStartTimes + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestSynchronizeAnimationStartTimes() {} + + void SetupTree() override { + LayerTreeHostTimelinesTest::SetupTree(); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_->SetBounds(gfx::Size(4, 4)); + + layer_tree_host()->root_layer()->AddChild(picture_); + + AttachPlayersToTimeline(); + player_child_->set_layer_animation_delegate(this); + player_child_->AttachLayer(picture_->id()); + } + + void BeginTest() override { + PostAddAnimationToMainThreadPlayer(player_child_.get()); + } + + void NotifyAnimationStarted(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + LayerAnimationController* controller = + player_child_->element_animations()->layer_animation_controller(); + Animation* animation = controller->GetAnimation(Animation::OPACITY); + main_start_time_ = animation->start_time(); + controller->RemoveAnimation(animation->id()); + EndTest(); + } + + void UpdateAnimationState(LayerTreeHostImpl* impl_host, + bool has_unfinished_animation) override { + scoped_refptr<AnimationTimeline> timeline_impl = + impl_host->animation_host()->GetTimelineById(timeline_id_); + scoped_refptr<AnimationPlayer> player_child_impl = + timeline_impl->GetPlayerById(player_child_id_); + + LayerAnimationController* controller = + player_child_impl->element_animations()->layer_animation_controller(); + Animation* animation = controller->GetAnimation(Animation::OPACITY); + if (!animation) + return; + + impl_start_time_ = animation->start_time(); + } + + void AfterTest() override { + EXPECT_EQ(impl_start_time_, main_start_time_); + EXPECT_LT(base::TimeTicks(), impl_start_time_); + } + + private: + base::TimeTicks main_start_time_; + base::TimeTicks impl_start_time_; + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> picture_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTimelinesTestSynchronizeAnimationStartTimes); + +// Ensures that notify animation finished is called. +// Evolved from LayerTreeHostAnimationTestAnimationFinishedEvents. +class LayerTreeHostTimelinesTestAnimationFinishedEvents + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestAnimationFinishedEvents() {} + + void BeginTest() override { + AttachPlayersToTimeline(); + player_->AttachLayer(layer_tree_host()->root_layer()->id()); + PostAddInstantAnimationToMainThreadPlayer(player_.get()); + } + + void NotifyAnimationFinished(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + LayerAnimationController* controller = + player_->element_animations()->layer_animation_controller(); + Animation* animation = controller->GetAnimation(Animation::OPACITY); + if (animation) + controller->RemoveAnimation(animation->id()); + EndTest(); + } + + void AfterTest() override {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTimelinesTestAnimationFinishedEvents); + +// Ensures that when opacity is being animated, this value does not cause the +// subtree to be skipped. +// Evolved from LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity. +class LayerTreeHostTimelinesTestDoNotSkipLayersWithAnimatedOpacity + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestDoNotSkipLayersWithAnimatedOpacity() + : update_check_layer_( + FakePictureLayer::Create(layer_settings(), &client_)) {} + + void SetupTree() override { + update_check_layer_->SetOpacity(0.f); + layer_tree_host()->SetRootLayer(update_check_layer_); + LayerTreeHostTimelinesTest::SetupTree(); + + AttachPlayersToTimeline(); + player_->AttachLayer(update_check_layer_->id()); + } + + void BeginTest() override { + PostAddAnimationToMainThreadPlayer(player_.get()); + } + + void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { + scoped_refptr<AnimationTimeline> timeline_impl = + host_impl->animation_host()->GetTimelineById(timeline_id_); + scoped_refptr<AnimationPlayer> player_impl = + timeline_impl->GetPlayerById(player_id_); + + LayerAnimationController* controller_impl = + player_impl->element_animations()->layer_animation_controller(); + Animation* animation_impl = + controller_impl->GetAnimation(Animation::OPACITY); + controller_impl->RemoveAnimation(animation_impl->id()); + EndTest(); + } + + void AfterTest() override { + // Update() should have been called once, proving that the layer was not + // skipped. + EXPECT_EQ(1, update_check_layer_->update_count()); + + // clear update_check_layer_ so LayerTreeHost dies. + update_check_layer_ = NULL; + } + + private: + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> update_check_layer_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTimelinesTestDoNotSkipLayersWithAnimatedOpacity); + +// Layers added to tree with existing active animations should have the +// animation correctly recognized. +// Evolved from LayerTreeHostAnimationTestLayerAddedWithAnimation. +class LayerTreeHostTimelinesTestLayerAddedWithAnimation + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestLayerAddedWithAnimation() {} + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void DidCommit() override { + if (layer_tree_host()->source_frame_number() == 1) { + AttachPlayersToTimeline(); + + scoped_refptr<Layer> layer = Layer::Create(layer_settings()); + player_->AttachLayer(layer->id()); + player_->set_layer_animation_delegate(this); + + // Any valid AnimationCurve will do here. + scoped_ptr<AnimationCurve> curve(new FakeFloatAnimationCurve()); + scoped_ptr<Animation> animation( + Animation::Create(curve.Pass(), 1, 1, Animation::OPACITY)); + player_->AddAnimation(animation.Pass()); + + // We add the animation *before* attaching the layer to the tree. + layer_tree_host()->root_layer()->AddChild(layer); + } + } + + void AnimateLayers(LayerTreeHostImpl* impl_host, + base::TimeTicks monotonic_time) override { + EndTest(); + } + + void AfterTest() override {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTimelinesTestLayerAddedWithAnimation); + +// Make sure the main thread can still execute animations when CanDraw() is not +// true. +// Evolved from LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw +class LayerTreeHostTimelinesTestRunAnimationWhenNotCanDraw + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestRunAnimationWhenNotCanDraw() : started_times_(0) {} + + void SetupTree() override { + LayerTreeHostTimelinesTest::SetupTree(); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_->SetBounds(gfx::Size(4, 4)); + layer_tree_host()->root_layer()->AddChild(picture_); + + AttachPlayersToTimeline(); + player_child_->AttachLayer(picture_->id()); + player_child_->set_layer_animation_delegate(this); + } + + void BeginTest() override { + layer_tree_host()->SetViewportSize(gfx::Size()); + PostAddAnimationToMainThreadPlayer(player_child_.get()); + } + + void NotifyAnimationStarted(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + started_times_++; + } + + void NotifyAnimationFinished(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + EndTest(); + } + + void AfterTest() override { EXPECT_EQ(1, started_times_); } + + private: + int started_times_; + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> picture_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTimelinesTestRunAnimationWhenNotCanDraw); + +// Animations should not be started when frames are being skipped due to +// checkerboard. +// Evolved from LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations. +class LayerTreeHostTimelinesTestCheckerboardDoesntStartAnimations + : public LayerTreeHostTimelinesTest { + void SetupTree() override { + LayerTreeHostTimelinesTest::SetupTree(); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_->SetBounds(gfx::Size(4, 4)); + layer_tree_host()->root_layer()->AddChild(picture_); + + AttachPlayersToTimeline(); + player_child_->AttachLayer(picture_->id()); + player_child_->set_layer_animation_delegate(this); + } + + void InitializeSettings(LayerTreeSettings* settings) override { + // Make sure that drawing many times doesn't cause a checkerboarded + // animation to start so we avoid flake in this test. + settings->timeout_and_draw_when_animation_checkerboards = false; + LayerTreeHostTimelinesTest::InitializeSettings(settings); + } + + void BeginTest() override { + prevented_draw_ = 0; + added_animations_ = 0; + started_times_ = 0; + + PostSetNeedsCommitToMainThread(); + } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + if (added_animations_ < 2) + return draw_result; + if (TestEnded()) + return draw_result; + // Act like there is checkerboard when the second animation wants to draw. + ++prevented_draw_; + if (prevented_draw_ > 2) + EndTest(); + return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS; + } + + void DidCommitAndDrawFrame() override { + switch (layer_tree_host()->source_frame_number()) { + case 1: + // The animation is longer than 1 BeginFrame interval. + AddOpacityTransitionToPlayer(player_child_.get(), 0.1, 0.2f, 0.8f, + false); + added_animations_++; + break; + case 2: + // This second animation will not be drawn so it should not start. + AddAnimatedTransformToPlayer(player_child_.get(), 0.1, 5, 5); + added_animations_++; + break; + } + } + + void NotifyAnimationStarted(base::TimeTicks monotonic_time, + Animation::TargetProperty target_property, + int group) override { + if (TestEnded()) + return; + started_times_++; + } + + void AfterTest() override { + // Make sure we tried to draw the second animation but failed. + EXPECT_LT(0, prevented_draw_); + // The first animation should be started, but the second should not because + // of checkerboard. + EXPECT_EQ(1, started_times_); + } + + int prevented_draw_; + int added_animations_; + int started_times_; + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> picture_; +}; + +MULTI_THREAD_TEST_F( + LayerTreeHostTimelinesTestCheckerboardDoesntStartAnimations); + +// Verifies that scroll offset animations are only accepted when impl-scrolling +// is supported, and that when scroll offset animations are accepted, +// scroll offset updates are sent back to the main thread. +// Evolved from LayerTreeHostAnimationTestScrollOffsetChangesArePropagated +class LayerTreeHostTimelinesTestScrollOffsetChangesArePropagated + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestScrollOffsetChangesArePropagated() {} + + void SetupTree() override { + LayerTreeHostTimelinesTest::SetupTree(); + + scroll_layer_ = FakePictureLayer::Create(layer_settings(), &client_); + scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id()); + scroll_layer_->SetBounds(gfx::Size(1000, 1000)); + scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20)); + layer_tree_host()->root_layer()->AddChild(scroll_layer_); + + AttachPlayersToTimeline(); + player_child_->AttachLayer(scroll_layer_->id()); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void DidCommit() override { + switch (layer_tree_host()->source_frame_number()) { + case 1: { + scoped_ptr<ScrollOffsetAnimationCurve> curve( + ScrollOffsetAnimationCurve::Create( + gfx::ScrollOffset(500.f, 550.f), + EaseInOutTimingFunction::Create())); + scoped_ptr<Animation> animation( + Animation::Create(curve.Pass(), 1, 0, Animation::SCROLL_OFFSET)); + animation->set_needs_synchronized_start_time(true); + bool impl_scrolling_supported = + layer_tree_host()->proxy()->SupportsImplScrolling(); + if (impl_scrolling_supported) + player_child_->AddAnimation(animation.Pass()); + else + EndTest(); + break; + } + default: + if (scroll_layer_->scroll_offset().x() > 10 && + scroll_layer_->scroll_offset().y() > 20) + EndTest(); + } + } + + void AfterTest() override {} + + private: + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> scroll_layer_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTimelinesTestScrollOffsetChangesArePropagated); + +// Verifies that when the main thread removes a scroll animation and sets a new +// scroll position, the active tree takes on exactly this new scroll position +// after activation, and the main thread doesn't receive a spurious scroll +// delta. +// Evolved from LayerTreeHostAnimationTestScrollOffsetAnimationRemoval +class LayerTreeHostTimelinesTestScrollOffsetAnimationRemoval + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestScrollOffsetAnimationRemoval() + : final_postion_(50.0, 100.0) {} + + void SetupTree() override { + LayerTreeHostTimelinesTest::SetupTree(); + + scroll_layer_ = FakePictureLayer::Create(layer_settings(), &client_); + scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id()); + scroll_layer_->SetBounds(gfx::Size(10000, 10000)); + scroll_layer_->SetScrollOffset(gfx::ScrollOffset(100.0, 200.0)); + layer_tree_host()->root_layer()->AddChild(scroll_layer_); + + scoped_ptr<ScrollOffsetAnimationCurve> curve( + ScrollOffsetAnimationCurve::Create(gfx::ScrollOffset(6500.f, 7500.f), + EaseInOutTimingFunction::Create())); + scoped_ptr<Animation> animation( + Animation::Create(curve.Pass(), 1, 0, Animation::SCROLL_OFFSET)); + animation->set_needs_synchronized_start_time(true); + + AttachPlayersToTimeline(); + player_child_->AttachLayer(scroll_layer_->id()); + player_child_->AddAnimation(animation.Pass()); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void BeginMainFrame(const BeginFrameArgs& args) override { + switch (layer_tree_host()->source_frame_number()) { + case 0: + break; + case 1: { + Animation* animation = player_child_->element_animations() + ->layer_animation_controller() + ->GetAnimation(Animation::SCROLL_OFFSET); + player_child_->RemoveAnimation(animation->id()); + scroll_layer_->SetScrollOffset(final_postion_); + break; + } + default: + EXPECT_EQ(final_postion_, scroll_layer_->scroll_offset()); + } + } + + void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override { + host_impl->BlockNotifyReadyToActivateForTesting(true); + } + + void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl, + const BeginFrameArgs& args) override { + if (!host_impl->pending_tree()) + return; + + if (!host_impl->active_tree()->root_layer()) { + host_impl->BlockNotifyReadyToActivateForTesting(false); + return; + } + + scoped_refptr<AnimationTimeline> timeline_impl = + host_impl->animation_host()->GetTimelineById(timeline_id_); + scoped_refptr<AnimationPlayer> player_impl = + timeline_impl->GetPlayerById(player_child_id_); + + LayerImpl* scroll_layer_impl = + host_impl->active_tree()->root_layer()->children()[0]; + Animation* animation = player_impl->element_animations() + ->layer_animation_controller() + ->GetAnimation(Animation::SCROLL_OFFSET); + + if (!animation || animation->run_state() != Animation::RUNNING) { + host_impl->BlockNotifyReadyToActivateForTesting(false); + return; + } + + // Block activation until the running animation has a chance to produce a + // scroll delta. + gfx::Vector2dF scroll_delta = scroll_layer_impl->ScrollDelta(); + if (scroll_delta.x() < 1.f || scroll_delta.y() < 1.f) + return; + + host_impl->BlockNotifyReadyToActivateForTesting(false); + } + + void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { + if (host_impl->pending_tree()->source_frame_number() != 1) + return; + LayerImpl* scroll_layer_impl = + host_impl->pending_tree()->root_layer()->children()[0]; + EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset()); + } + + void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { + if (host_impl->active_tree()->source_frame_number() != 1) + return; + LayerImpl* scroll_layer_impl = + host_impl->active_tree()->root_layer()->children()[0]; + EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset()); + EndTest(); + } + + void AfterTest() override { + EXPECT_EQ(final_postion_, scroll_layer_->scroll_offset()); + } + + private: + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> scroll_layer_; + const gfx::ScrollOffset final_postion_; +}; + +MULTI_THREAD_TEST_F(LayerTreeHostTimelinesTestScrollOffsetAnimationRemoval); + +// When animations are simultaneously added to an existing layer and to a new +// layer, they should start at the same time, even when there's already a +// running animation on the existing layer. +// Evolved from LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers. +class LayerTreeHostTimelinesTestAnimationsAddedToNewAndExistingLayers + : public LayerTreeHostTimelinesTest { + public: + LayerTreeHostTimelinesTestAnimationsAddedToNewAndExistingLayers() + : frame_count_with_pending_tree_(0) {} + + void BeginTest() override { + AttachPlayersToTimeline(); + PostSetNeedsCommitToMainThread(); + } + + void DidCommit() override { + if (layer_tree_host()->source_frame_number() == 1) { + player_->AttachLayer(layer_tree_host()->root_layer()->id()); + AddAnimatedTransformToPlayer(player_.get(), 4, 1, 1); + } else if (layer_tree_host()->source_frame_number() == 2) { + AddOpacityTransitionToPlayer(player_.get(), 1, 0.f, 0.5f, true); + + scoped_refptr<Layer> layer = Layer::Create(layer_settings()); + layer_tree_host()->root_layer()->AddChild(layer); + layer->SetBounds(gfx::Size(4, 4)); + + player_child_->AttachLayer(layer->id()); + player_child_->set_layer_animation_delegate(this); + AddOpacityTransitionToPlayer(player_child_.get(), 1, 0.f, 0.5f, true); + } + } + + void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override { + host_impl->BlockNotifyReadyToActivateForTesting(true); + } + + void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { + // For the commit that added animations to new and existing layers, keep + // blocking activation. We want to verify that even with activation blocked, + // the animation on the layer that's already in the active tree won't get a + // head start. + if (host_impl->pending_tree()->source_frame_number() != 2) { + host_impl->BlockNotifyReadyToActivateForTesting(false); + } + } + + void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl, + const BeginFrameArgs& args) override { + if (!host_impl->pending_tree() || + host_impl->pending_tree()->source_frame_number() != 2) + return; + + frame_count_with_pending_tree_++; + if (frame_count_with_pending_tree_ == 2) { + host_impl->BlockNotifyReadyToActivateForTesting(false); + } + } + + void UpdateAnimationState(LayerTreeHostImpl* host_impl, + bool has_unfinished_animation) override { + scoped_refptr<AnimationTimeline> timeline_impl = + host_impl->animation_host()->GetTimelineById(timeline_id_); + scoped_refptr<AnimationPlayer> player_impl = + timeline_impl->GetPlayerById(player_id_); + scoped_refptr<AnimationPlayer> player_child_impl = + timeline_impl->GetPlayerById(player_child_id_); + + // wait for tree activation. + if (!player_impl->element_animations()) + return; + + LayerAnimationController* root_controller_impl = + player_impl->element_animations()->layer_animation_controller(); + Animation* root_animation = + root_controller_impl->GetAnimation(Animation::OPACITY); + if (!root_animation || root_animation->run_state() != Animation::RUNNING) + return; + + LayerAnimationController* child_controller_impl = + player_child_impl->element_animations()->layer_animation_controller(); + Animation* child_animation = + child_controller_impl->GetAnimation(Animation::OPACITY); + EXPECT_EQ(Animation::RUNNING, child_animation->run_state()); + EXPECT_EQ(root_animation->start_time(), child_animation->start_time()); + root_controller_impl->AbortAnimations(Animation::OPACITY); + root_controller_impl->AbortAnimations(Animation::TRANSFORM); + child_controller_impl->AbortAnimations(Animation::OPACITY); + EndTest(); + } + + void AfterTest() override {} + + private: + int frame_count_with_pending_tree_; +}; + +// This test blocks activation which is not supported for single thread mode. +MULTI_THREAD_BLOCKNOTIFY_TEST_F( + LayerTreeHostTimelinesTestAnimationsAddedToNewAndExistingLayers); + +// Evolved from LayerTreeHostAnimationTestAddAnimationAfterAnimating. +class LayerTreeHostTimelinesTestAddAnimationAfterAnimating + : public LayerTreeHostTimelinesTest { + public: + void SetupTree() override { + LayerTreeHostTimelinesTest::SetupTree(); + content_ = Layer::Create(layer_settings()); + content_->SetBounds(gfx::Size(4, 4)); + layer_tree_host()->root_layer()->AddChild(content_); + + AttachPlayersToTimeline(); + + player_->AttachLayer(layer_tree_host()->root_layer()->id()); + player_child_->AttachLayer(content_->id()); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void DidCommit() override { + switch (layer_tree_host()->source_frame_number()) { + case 1: + // First frame: add an animation to the root layer. + AddAnimatedTransformToPlayer(player_.get(), 0.1, 5, 5); + break; + case 2: + // Second frame: add an animation to the content layer. The root layer + // animation has caused us to animate already during this frame. + AddOpacityTransitionToPlayer(player_child_.get(), 0.1, 5, 5, false); + break; + } + } + + void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { + // After both animations have started, verify that they have valid + // start times. + if (host_impl->active_tree()->source_frame_number() < 2) + return; + AnimationRegistrar::AnimationControllerMap controllers_copy = + host_impl->animation_host() + ->animation_registrar() + ->active_animation_controllers_for_testing(); + EXPECT_EQ(2u, controllers_copy.size()); + for (auto& it : controllers_copy) { + int id = it.first; + if (id == host_impl->RootLayer()->id()) { + Animation* anim = it.second->GetAnimation(Animation::TRANSFORM); + EXPECT_GT((anim->start_time() - base::TimeTicks()).InSecondsF(), 0); + } else if (id == host_impl->RootLayer()->children()[0]->id()) { + Animation* anim = it.second->GetAnimation(Animation::OPACITY); + EXPECT_GT((anim->start_time() - base::TimeTicks()).InSecondsF(), 0); + } + EndTest(); + } + } + + void AfterTest() override {} + + private: + scoped_refptr<Layer> content_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTimelinesTestAddAnimationAfterAnimating); + +} // namespace +} // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc index 82e47b89b0e..d25d047d0a7 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_context.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc @@ -5,7 +5,6 @@ #include "cc/trees/layer_tree_host.h" #include "base/basictypes.h" -#include "cc/layers/content_layer.h" #include "cc/layers/delegated_frame_provider.h" #include "cc/layers/delegated_frame_resource_collection.h" #include "cc/layers/heads_up_display_layer.h" @@ -20,9 +19,7 @@ #include "cc/output/filter_operations.h" #include "cc/resources/single_release_callback.h" #include "cc/test/failure_output_surface.h" -#include "cc/test/fake_content_layer.h" #include "cc/test/fake_content_layer_client.h" -#include "cc/test/fake_content_layer_impl.h" #include "cc/test/fake_delegated_renderer_layer.h" #include "cc/test/fake_delegated_renderer_layer_impl.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -31,6 +28,7 @@ #include "cc/test/fake_painted_scrollbar_layer.h" #include "cc/test/fake_picture_layer.h" #include "cc/test/fake_picture_layer_impl.h" +#include "cc/test/fake_resource_provider.h" #include "cc/test/fake_scoped_ui_resource.h" #include "cc/test/fake_scrollbar.h" #include "cc/test/fake_video_frame_provider.h" @@ -70,6 +68,9 @@ class LayerTreeHostContextTest : public LayerTreeTest { } void LoseContext() { + // CreateFakeOutputSurface happens on a different thread, so lock context3d_ + // to make sure we don't set it to null after recreating it there. + base::AutoLock lock(context3d_lock_); // For sanity-checking tests, they should only call this when the // context is not lost. CHECK(context3d_); @@ -90,6 +91,7 @@ class LayerTreeHostContextTest : public LayerTreeTest { } scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d(); + base::AutoLock lock(context3d_lock_); context3d_ = context3d.get(); if (context_should_support_io_surface_) { @@ -107,10 +109,9 @@ class LayerTreeHostContextTest : public LayerTreeTest { LayerTreeHostImpl::FrameData* frame, DrawResult draw_result) override { if (draw_result == DRAW_ABORTED_MISSING_HIGH_RES_CONTENT) { - // Only valid for single-threaded impl-side painting, which activates + // Only valid for single-threaded compositing, which activates // immediately and will try to draw again when content has finished. DCHECK(!host_impl->proxy()->HasImplThread()); - DCHECK(host_impl->settings().impl_side_painting); return draw_result; } EXPECT_EQ(DRAW_SUCCESS, draw_result); @@ -148,7 +149,11 @@ class LayerTreeHostContextTest : public LayerTreeTest { void ExpectCreateToFail() { ++times_to_expect_create_failed_; } protected: + // Protects use of context3d_ so LoseContext and CreateFakeOutputSurface + // can both use it on different threads. + base::Lock context3d_lock_; TestWebGraphicsContext3D* context3d_; + int times_to_fail_create_; int times_to_lose_during_commit_; int times_to_lose_during_draw_; @@ -385,6 +390,8 @@ class MultipleCompositeDoesNotCreateOutputSurface void InitializeSettings(LayerTreeSettings* settings) override { settings->single_thread_proxy_scheduler = false; + settings->use_zero_copy = true; + settings->use_one_copy = false; } void RequestNewOutputSurface() override { @@ -393,8 +400,8 @@ class MultipleCompositeDoesNotCreateOutputSurface } void BeginTest() override { - layer_tree_host()->Composite(base::TimeTicks()); - layer_tree_host()->Composite(base::TimeTicks()); + layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(1)); + layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(2)); } scoped_ptr<OutputSurface> CreateOutputSurface() override { @@ -409,7 +416,8 @@ class MultipleCompositeDoesNotCreateOutputSurface int request_count_; }; -SINGLE_THREAD_NOIMPL_TEST_F(MultipleCompositeDoesNotCreateOutputSurface); +// This test uses Composite() which only exists for single thread. +SINGLE_THREAD_TEST_F(MultipleCompositeDoesNotCreateOutputSurface); // This test makes sure that once a SingleThreadProxy issues a // DidFailToInitializeOutputSurface, that future Composite calls will not @@ -422,6 +430,8 @@ class FailedCreateDoesNotCreateExtraOutputSurface void InitializeSettings(LayerTreeSettings* settings) override { settings->single_thread_proxy_scheduler = false; + settings->use_zero_copy = true; + settings->use_one_copy = false; } void RequestNewOutputSurface() override { @@ -439,12 +449,12 @@ class FailedCreateDoesNotCreateExtraOutputSurface void BeginTest() override { // First composite tries to create a surface. - layer_tree_host()->Composite(base::TimeTicks()); + layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(1)); EXPECT_EQ(num_requests_, 2); EXPECT_TRUE(has_failed_); // Second composite should not request or fail. - layer_tree_host()->Composite(base::TimeTicks()); + layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(2)); EXPECT_EQ(num_requests_, 2); EndTest(); } @@ -463,7 +473,8 @@ class FailedCreateDoesNotCreateExtraOutputSurface bool has_failed_; }; -SINGLE_THREAD_NOIMPL_TEST_F(FailedCreateDoesNotCreateExtraOutputSurface); +// This test uses Composite() which only exists for single thread. +SINGLE_THREAD_TEST_F(FailedCreateDoesNotCreateExtraOutputSurface); class LayerTreeHostContextTestCommitAfterDelayedOutputSurface : public LayerTreeHostContextTest { @@ -473,6 +484,8 @@ class LayerTreeHostContextTestCommitAfterDelayedOutputSurface void InitializeSettings(LayerTreeSettings* settings) override { settings->single_thread_proxy_scheduler = false; + settings->use_zero_copy = true; + settings->use_one_copy = false; } void RequestNewOutputSurface() override { @@ -489,7 +502,9 @@ class LayerTreeHostContextTestCommitAfterDelayedOutputSurface LayerTreeHostContextTest::CreateOutputSurface()); } - void BeginTest() override { layer_tree_host()->Composite(base::TimeTicks()); } + void BeginTest() override { + layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(1)); + } void ScheduleComposite() override { if (creating_output_) @@ -501,8 +516,8 @@ class LayerTreeHostContextTestCommitAfterDelayedOutputSurface bool creating_output_; }; -SINGLE_THREAD_NOIMPL_TEST_F( - LayerTreeHostContextTestCommitAfterDelayedOutputSurface); +// This test uses Composite() which only exists for single thread. +SINGLE_THREAD_TEST_F(LayerTreeHostContextTestCommitAfterDelayedOutputSurface); class LayerTreeHostContextTestAvoidUnnecessaryComposite : public LayerTreeHostContextTest { @@ -512,6 +527,8 @@ class LayerTreeHostContextTestAvoidUnnecessaryComposite void InitializeSettings(LayerTreeSettings* settings) override { settings->single_thread_proxy_scheduler = false; + settings->use_zero_copy = true; + settings->use_one_copy = false; } void RequestNewOutputSurface() override { @@ -522,7 +539,7 @@ class LayerTreeHostContextTestAvoidUnnecessaryComposite void BeginTest() override { in_composite_ = true; - layer_tree_host()->Composite(base::TimeTicks()); + layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(1)); in_composite_ = false; } @@ -533,13 +550,15 @@ class LayerTreeHostContextTestAvoidUnnecessaryComposite bool in_composite_; }; -SINGLE_THREAD_NOIMPL_TEST_F(LayerTreeHostContextTestAvoidUnnecessaryComposite); +// This test uses Composite() which only exists for single thread. +SINGLE_THREAD_TEST_F(LayerTreeHostContextTestAvoidUnnecessaryComposite); +// This test uses PictureLayer to check for a working context. class LayerTreeHostContextTestLostContextSucceedsWithContent : public LayerTreeHostContextTestLostContextSucceeds { public: void SetupTree() override { - root_ = Layer::Create(); + root_ = Layer::Create(layer_settings()); root_->SetBounds(gfx::Size(10, 10)); root_->SetIsDrawable(true); @@ -548,10 +567,7 @@ class LayerTreeHostContextTestLostContextSucceedsWithContent paint.setColor(SkColorSetARGB(100, 80, 200, 200)); client_.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint); - if (layer_tree_host()->settings().impl_side_painting) - layer_ = FakePictureLayer::Create(&client_); - else - layer_ = FakeContentLayer::Create(&client_); + layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_->SetBounds(gfx::Size(10, 10)); layer_->SetIsDrawable(true); @@ -570,21 +586,12 @@ class LayerTreeHostContextTestLostContextSucceedsWithContent } void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { - if (!host_impl->settings().impl_side_painting) { - FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>( - host_impl->active_tree()->root_layer()->children()[0]); - // Even though the context was lost, we should have a resource. The - // TestWebGraphicsContext3D ensures that this resource is created with - // the active context. - EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0)); - } else { - FakePictureLayerImpl* picture_impl = static_cast<FakePictureLayerImpl*>( - host_impl->active_tree()->root_layer()->children()[0]); - EXPECT_TRUE(picture_impl->HighResTiling() - ->TileAt(0, 0) - ->draw_info() - .IsReadyToDraw()); - } + FakePictureLayerImpl* picture_impl = static_cast<FakePictureLayerImpl*>( + host_impl->active_tree()->root_layer()->children()[0]); + EXPECT_TRUE(picture_impl->HighResTiling() + ->TileAt(0, 0) + ->draw_info() + .IsReadyToDraw()); } protected: @@ -593,7 +600,6 @@ class LayerTreeHostContextTestLostContextSucceedsWithContent scoped_refptr<Layer> layer_; }; -// This test uses TiledLayer and PictureLayer to check for a working context. SINGLE_AND_MULTI_THREAD_TEST_F( LayerTreeHostContextTestLostContextSucceedsWithContent); @@ -639,15 +645,10 @@ class LayerTreeHostContextTestLostContextAndEvictTextures paint.setColor(SkColorSetARGB(100, 80, 200, 200)); client_.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint); - if (layer_tree_host()->settings().impl_side_painting) { - picture_layer_ = FakePictureLayer::Create(&client_); - picture_layer_->SetBounds(gfx::Size(10, 20)); - layer_tree_host()->SetRootLayer(picture_layer_); - } else { - content_layer_ = FakeContentLayer::Create(&client_); - content_layer_->SetBounds(gfx::Size(10, 20)); - layer_tree_host()->SetRootLayer(content_layer_); - } + scoped_refptr<FakePictureLayer> picture_layer = + FakePictureLayer::Create(layer_settings(), &client_); + picture_layer->SetBounds(gfx::Size(10, 20)); + layer_tree_host()->SetRootLayer(picture_layer); LayerTreeHostContextTest::SetupTree(); } @@ -679,9 +680,6 @@ class LayerTreeHostContextTestLostContextAndEvictTextures void DidCommitAndDrawFrame() override { if (num_commits_ > 1) return; - if (!layer_tree_host()->settings().impl_side_painting) { - EXPECT_TRUE(content_layer_->HaveBackingAt(0, 0)); - } PostEvictTextures(); } @@ -697,18 +695,12 @@ class LayerTreeHostContextTestLostContextAndEvictTextures } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - if (impl->settings().impl_side_painting) { - FakePictureLayerImpl* picture_impl = - static_cast<FakePictureLayerImpl*>(impl->active_tree()->root_layer()); - EXPECT_TRUE(picture_impl->HighResTiling() - ->TileAt(0, 0) - ->draw_info() - .IsReadyToDraw()); - } else { - FakeContentLayerImpl* content_impl = - static_cast<FakeContentLayerImpl*>(impl->active_tree()->root_layer()); - EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0)); - } + FakePictureLayerImpl* picture_impl = + static_cast<FakePictureLayerImpl*>(impl->active_tree()->root_layer()); + EXPECT_TRUE(picture_impl->HighResTiling() + ->TileAt(0, 0) + ->draw_info() + .IsReadyToDraw()); impl_host_ = impl; if (lost_context_) @@ -722,8 +714,6 @@ class LayerTreeHostContextTestLostContextAndEvictTextures protected: bool lose_after_evict_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> content_layer_; - scoped_refptr<FakePictureLayer> picture_layer_; LayerTreeHostImpl* impl_host_; int num_commits_; bool lost_context_; @@ -732,143 +722,60 @@ class LayerTreeHostContextTestLostContextAndEvictTextures TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, LoseAfterEvict_SingleThread_DirectRenderer) { lose_after_evict_ = true; - RunTest(false, false, false); + RunTest(false, false); } TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, LoseAfterEvict_SingleThread_DelegatingRenderer) { lose_after_evict_ = true; - RunTest(false, true, false); + RunTest(false, true); } TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, - LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint) { + LoseAfterEvict_MultiThread_DirectRenderer) { lose_after_evict_ = true; - RunTest(true, false, false); + RunTest(true, false); } TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, - LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) { + LoseAfterEvict_MultiThread_DelegatingRenderer) { lose_after_evict_ = true; - RunTest(true, true, false); -} - -// Flaky on all platforms, http://crbug.com/310979 -TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, - DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) { - lose_after_evict_ = true; - RunTest(true, true, true); + RunTest(true, true); } TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, LoseBeforeEvict_SingleThread_DirectRenderer) { lose_after_evict_ = false; - RunTest(false, false, false); + RunTest(false, false); } TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, LoseBeforeEvict_SingleThread_DelegatingRenderer) { lose_after_evict_ = false; - RunTest(false, true, false); -} - -TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, - LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint) { - lose_after_evict_ = false; - RunTest(true, false, false); -} - -TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, - LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint) { - lose_after_evict_ = false; - RunTest(true, false, true); + RunTest(false, true); } TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, - LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint) { + LoseBeforeEvict_MultiThread_DirectRenderer) { lose_after_evict_ = false; - RunTest(true, true, false); + RunTest(true, false); } TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, - LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint) { + LoseBeforeEvict_MultiThread_DelegatingRenderer) { lose_after_evict_ = false; - RunTest(true, true, true); + RunTest(true, true); } -class LayerTreeHostContextTestLostContextWhileUpdatingResources - : public LayerTreeHostContextTest { - public: - LayerTreeHostContextTestLostContextWhileUpdatingResources() - : num_children_(50), times_to_lose_on_end_query_(3) {} - - scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() override { - scoped_ptr<TestWebGraphicsContext3D> context = - LayerTreeHostContextTest::CreateContext3d(); - if (times_to_lose_on_end_query_) { - --times_to_lose_on_end_query_; - context->set_times_end_query_succeeds(5); - } - return context.Pass(); - } - - void SetupTree() override { - if (layer_tree_host()->settings().impl_side_painting) - parent_ = FakePictureLayer::Create(&client_); - else - parent_ = FakeContentLayer::Create(&client_); - - parent_->SetBounds(gfx::Size(num_children_, 1)); - - for (int i = 0; i < num_children_; i++) { - scoped_refptr<Layer> child; - if (layer_tree_host()->settings().impl_side_painting) - child = FakePictureLayer::Create(&client_); - else - child = FakeContentLayer::Create(&client_); - child->SetPosition(gfx::PointF(i, 0.f)); - child->SetBounds(gfx::Size(1, 1)); - parent_->AddChild(child); - } - - layer_tree_host()->SetRootLayer(parent_); - LayerTreeHostContextTest::SetupTree(); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { - EXPECT_EQ(0, times_to_lose_on_end_query_); - EndTest(); - } - - void AfterTest() override { EXPECT_EQ(0, times_to_lose_on_end_query_); } - - private: - FakeContentLayerClient client_; - scoped_refptr<Layer> parent_; - int num_children_; - int times_to_lose_on_end_query_; -}; - -SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F( - LayerTreeHostContextTestLostContextWhileUpdatingResources); - class LayerTreeHostContextTestLayersNotified : public LayerTreeHostContextTest { public: LayerTreeHostContextTestLayersNotified() : LayerTreeHostContextTest(), num_commits_(0) {} void SetupTree() override { - if (layer_tree_host()->settings().impl_side_painting) { - root_ = FakePictureLayer::Create(&client_); - child_ = FakePictureLayer::Create(&client_); - grandchild_ = FakePictureLayer::Create(&client_); - } else { - root_ = FakeContentLayer::Create(&client_); - child_ = FakeContentLayer::Create(&client_); - grandchild_ = FakeContentLayer::Create(&client_); - } + root_ = FakePictureLayer::Create(layer_settings(), &client_); + child_ = FakePictureLayer::Create(layer_settings(), &client_); + grandchild_ = FakePictureLayer::Create(layer_settings(), &client_); root_->AddChild(child_); child_->AddChild(grandchild_); @@ -885,54 +792,29 @@ class LayerTreeHostContextTestLayersNotified : public LayerTreeHostContextTest { FakePictureLayerImpl* root_picture = NULL; FakePictureLayerImpl* child_picture = NULL; FakePictureLayerImpl* grandchild_picture = NULL; - FakeContentLayerImpl* root_content = NULL; - FakeContentLayerImpl* child_content = NULL; - FakeContentLayerImpl* grandchild_content = NULL; - - if (host_impl->settings().impl_side_painting) { - root_picture = static_cast<FakePictureLayerImpl*>( - host_impl->active_tree()->root_layer()); - child_picture = - static_cast<FakePictureLayerImpl*>(root_picture->children()[0]); - grandchild_picture = - static_cast<FakePictureLayerImpl*>(child_picture->children()[0]); - } else { - root_content = static_cast<FakeContentLayerImpl*>( - host_impl->active_tree()->root_layer()); - child_content = - static_cast<FakeContentLayerImpl*>(root_content->children()[0]); - grandchild_content = - static_cast<FakeContentLayerImpl*>(child_content->children()[0]); - } + root_picture = static_cast<FakePictureLayerImpl*>( + host_impl->active_tree()->root_layer()); + child_picture = + static_cast<FakePictureLayerImpl*>(root_picture->children()[0]); + grandchild_picture = + static_cast<FakePictureLayerImpl*>(child_picture->children()[0]); ++num_commits_; switch (num_commits_) { case 1: - if (host_impl->settings().impl_side_painting) { - EXPECT_EQ(0u, root_picture->release_resources_count()); - EXPECT_EQ(0u, child_picture->release_resources_count()); - EXPECT_EQ(0u, grandchild_picture->release_resources_count()); - } else { - EXPECT_EQ(0u, root_content->lost_output_surface_count()); - EXPECT_EQ(0u, child_content->lost_output_surface_count()); - EXPECT_EQ(0u, grandchild_content->lost_output_surface_count()); - } + EXPECT_EQ(0u, root_picture->release_resources_count()); + EXPECT_EQ(0u, child_picture->release_resources_count()); + EXPECT_EQ(0u, grandchild_picture->release_resources_count()); // Lose the context and struggle to recreate it. LoseContext(); times_to_fail_create_ = 1; break; case 2: - if (host_impl->settings().impl_side_painting) { - EXPECT_TRUE(root_picture->release_resources_count()); - EXPECT_TRUE(child_picture->release_resources_count()); - EXPECT_TRUE(grandchild_picture->release_resources_count()); - } else { - EXPECT_TRUE(root_content->lost_output_surface_count()); - EXPECT_TRUE(child_content->lost_output_surface_count()); - EXPECT_TRUE(grandchild_content->lost_output_surface_count()); - } + EXPECT_TRUE(root_picture->release_resources_count()); + EXPECT_TRUE(child_picture->release_resources_count()); + EXPECT_TRUE(grandchild_picture->release_resources_count()); EndTest(); break; @@ -963,14 +845,8 @@ class LayerTreeHostContextTestDontUseLostResources child_output_surface_ = FakeOutputSurface::Create3d(); child_output_surface_->BindToClient(&output_surface_client_); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - child_resource_provider_ = - ResourceProvider::Create(child_output_surface_.get(), - shared_bitmap_manager_.get(), - NULL, - NULL, - 0, - false, - 1); + child_resource_provider_ = FakeResourceProvider::Create( + child_output_surface_.get(), shared_bitmap_manager_.get()); } static void EmptyReleaseCallback(unsigned sync_point, bool lost) {} @@ -1004,10 +880,9 @@ class LayerTreeHostContextTestDontUseLostResources delegated_frame_provider_ = new DelegatedFrameProvider( delegated_resource_collection_.get(), frame_data.Pass()); - ResourceProvider::ResourceId resource = - child_resource_provider_->CreateResource( - gfx::Size(4, 4), GL_CLAMP_TO_EDGE, - ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); + ResourceId resource = child_resource_provider_->CreateResource( + gfx::Size(4, 4), GL_CLAMP_TO_EDGE, + ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888); ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(), resource); @@ -1015,26 +890,25 @@ class LayerTreeHostContextTestDontUseLostResources gl->GenMailboxCHROMIUM(mailbox.name); GLuint sync_point = gl->InsertSyncPointCHROMIUM(); - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(10, 10)); root->SetIsDrawable(true); scoped_refptr<FakeDelegatedRendererLayer> delegated = - FakeDelegatedRendererLayer::Create(delegated_frame_provider_.get()); + FakeDelegatedRendererLayer::Create(layer_settings(), + delegated_frame_provider_.get()); delegated->SetBounds(gfx::Size(10, 10)); delegated->SetIsDrawable(true); root->AddChild(delegated); - scoped_refptr<Layer> layer; - if (layer_tree_host()->settings().impl_side_painting) - layer = PictureLayer::Create(&client_); - else - layer = ContentLayer::Create(&client_); + scoped_refptr<PictureLayer> layer = + PictureLayer::Create(layer_settings(), &client_); layer->SetBounds(gfx::Size(10, 10)); layer->SetIsDrawable(true); root->AddChild(layer); - scoped_refptr<TextureLayer> texture = TextureLayer::CreateForMailbox(NULL); + scoped_refptr<TextureLayer> texture = + TextureLayer::CreateForMailbox(layer_settings_, NULL); texture->SetBounds(gfx::Size(10, 10)); texture->SetIsDrawable(true); texture->SetTextureMailbox( @@ -1044,37 +918,31 @@ class LayerTreeHostContextTestDontUseLostResources EmptyReleaseCallback))); root->AddChild(texture); - scoped_refptr<Layer> mask; - if (layer_tree_host()->settings().impl_side_painting) - mask = PictureLayer::Create(&client_); - else - mask = ContentLayer::Create(&client_); + scoped_refptr<PictureLayer> mask = + PictureLayer::Create(layer_settings_, &client_); mask->SetBounds(gfx::Size(10, 10)); - scoped_refptr<Layer> layer_with_mask; - if (layer_tree_host()->settings().impl_side_painting) - layer_with_mask = PictureLayer::Create(&client_); - else - layer_with_mask = ContentLayer::Create(&client_); + scoped_refptr<PictureLayer> layer_with_mask = + PictureLayer::Create(layer_settings_, &client_); layer_with_mask->SetBounds(gfx::Size(10, 10)); layer_with_mask->SetIsDrawable(true); layer_with_mask->SetMaskLayer(mask.get()); root->AddChild(layer_with_mask); - scoped_refptr<VideoLayer> video_color = - VideoLayer::Create(&color_frame_provider_, media::VIDEO_ROTATION_0); + scoped_refptr<VideoLayer> video_color = VideoLayer::Create( + layer_settings_, &color_frame_provider_, media::VIDEO_ROTATION_0); video_color->SetBounds(gfx::Size(10, 10)); video_color->SetIsDrawable(true); root->AddChild(video_color); - scoped_refptr<VideoLayer> video_hw = - VideoLayer::Create(&hw_frame_provider_, media::VIDEO_ROTATION_0); + scoped_refptr<VideoLayer> video_hw = VideoLayer::Create( + layer_settings_, &hw_frame_provider_, media::VIDEO_ROTATION_0); video_hw->SetBounds(gfx::Size(10, 10)); video_hw->SetIsDrawable(true); root->AddChild(video_hw); - scoped_refptr<VideoLayer> video_scaled_hw = - VideoLayer::Create(&scaled_hw_frame_provider_, media::VIDEO_ROTATION_0); + scoped_refptr<VideoLayer> video_scaled_hw = VideoLayer::Create( + layer_settings_, &scaled_hw_frame_provider_, media::VIDEO_ROTATION_0); video_scaled_hw->SetBounds(gfx::Size(10, 10)); video_scaled_hw->SetIsDrawable(true); root->AddChild(video_scaled_hw); @@ -1082,28 +950,26 @@ class LayerTreeHostContextTestDontUseLostResources color_video_frame_ = VideoFrame::CreateColorFrame( gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta()); hw_video_frame_ = VideoFrame::WrapNativeTexture( + media::VideoFrame::ARGB, gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point), media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4), - gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta(), - false /* allow_overlay */, true /* has_alpha */); + gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta()); scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture( + media::VideoFrame::ARGB, gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point), media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4), - gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta(), - false /* allow_overlay */, true /* has_alpha */); + gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta()); color_frame_provider_.set_frame(color_video_frame_); hw_frame_provider_.set_frame(hw_video_frame_); scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_); - if (!delegating_renderer()) { - // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335 - scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create(); - io_surface->SetBounds(gfx::Size(10, 10)); - io_surface->SetIsDrawable(true); - io_surface->SetIOSurfaceProperties(1, gfx::Size(10, 10)); - root->AddChild(io_surface); - } + scoped_refptr<IOSurfaceLayer> io_surface = + IOSurfaceLayer::Create(layer_settings_); + io_surface->SetBounds(gfx::Size(10, 10)); + io_surface->SetIsDrawable(true); + io_surface->SetIOSurfaceProperties(1, gfx::Size(10, 10)); + root->AddChild(io_surface); // Enable the hud. LayerTreeDebugState debug_state; @@ -1112,7 +978,8 @@ class LayerTreeHostContextTestDontUseLostResources scoped_refptr<PaintedScrollbarLayer> scrollbar = PaintedScrollbarLayer::Create( - scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), layer->id()); + layer_settings_, scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), + layer->id()); scrollbar->SetBounds(gfx::Size(10, 10)); scrollbar->SetIsDrawable(true); root->AddChild(scrollbar); @@ -1189,27 +1056,22 @@ class LayerTreeHostContextTestDontUseLostResources FakeVideoFrameProvider color_frame_provider_; FakeVideoFrameProvider hw_frame_provider_; FakeVideoFrameProvider scaled_hw_frame_provider_; + + LayerSettings layer_settings_; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources); -class ImplSidePaintingLayerTreeHostContextTest - : public LayerTreeHostContextTest { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; - } -}; - class LayerTreeHostContextTestImplSidePainting - : public ImplSidePaintingLayerTreeHostContextTest { + : public LayerTreeHostContextTest { public: void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(10, 10)); root->SetIsDrawable(true); - scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_); + scoped_refptr<PictureLayer> picture = + PictureLayer::Create(layer_settings(), &client_); picture->SetBounds(gfx::Size(10, 10)); picture->SetIsDrawable(true); root->AddChild(picture); @@ -1231,16 +1093,16 @@ class LayerTreeHostContextTestImplSidePainting FakeContentLayerClient client_; }; -MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting); class ScrollbarLayerLostContext : public LayerTreeHostContextTest { public: ScrollbarLayerLostContext() : commits_(0) {} void BeginTest() override { - scoped_refptr<Layer> scroll_layer = Layer::Create(); - scrollbar_layer_ = - FakePaintedScrollbarLayer::Create(false, true, scroll_layer->id()); + scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings()); + scrollbar_layer_ = FakePaintedScrollbarLayer::Create( + layer_settings(), false, true, scroll_layer->id()); scrollbar_layer_->SetBounds(gfx::Size(10, 100)); layer_tree_host()->root_layer()->AddChild(scrollbar_layer_); layer_tree_host()->root_layer()->AddChild(scroll_layer); @@ -1328,24 +1190,13 @@ class UIResourceLostTest : public LayerTreeHostContextTest { class UIResourceLostTestSimple : public UIResourceLostTest { public: - // This is called when the commit is complete and the new layer tree has been - // activated. + // This is called when the new layer tree has been activated. virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) = 0; - void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { - if (!impl->settings().impl_side_painting) { - StepCompleteOnImplThread(impl); - PostStepCompleteToMainThread(); - ++time_step_; - } - } - void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { - if (impl->settings().impl_side_painting) { - StepCompleteOnImplThread(impl); - PostStepCompleteToMainThread(); - ++time_step_; - } + StepCompleteOnImplThread(impl); + PostStepCompleteToMainThread(); + ++time_step_; } }; @@ -1585,15 +1436,7 @@ class UIResourceLostBeforeActivateTree : public UIResourceLostTest { UIResourceId test_id_; }; -TEST_F(UIResourceLostBeforeActivateTree, - RunMultiThread_DirectRenderer_ImplSidePaint) { - RunTest(true, false, true); -} - -TEST_F(UIResourceLostBeforeActivateTree, - RunMultiThread_DelegatingRenderer_ImplSidePaint) { - RunTest(true, true, true); -} +SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeActivateTree); // Resources evicted explicitly and by visibility changes. class UIResourceLostEviction : public UIResourceLostTestSimple { @@ -1685,15 +1528,9 @@ class LayerTreeHostContextTestSurfaceCreateCallback : LayerTreeHostContextTest() {} void SetupTree() override { - if (layer_tree_host()->settings().impl_side_painting) { - picture_layer_ = FakePictureLayer::Create(&client_); - picture_layer_->SetBounds(gfx::Size(10, 20)); - layer_tree_host()->SetRootLayer(picture_layer_); - } else { - content_layer_ = FakeContentLayer::Create(&client_); - content_layer_->SetBounds(gfx::Size(10, 20)); - layer_tree_host()->SetRootLayer(content_layer_); - } + picture_layer_ = FakePictureLayer::Create(layer_settings(), &client_); + picture_layer_->SetBounds(gfx::Size(10, 20)); + layer_tree_host()->SetRootLayer(picture_layer_); LayerTreeHostContextTest::SetupTree(); } @@ -1703,30 +1540,18 @@ class LayerTreeHostContextTestSurfaceCreateCallback void DidCommit() override { switch (layer_tree_host()->source_frame_number()) { case 1: - if (layer_tree_host()->settings().impl_side_painting) - EXPECT_EQ(1u, picture_layer_->output_surface_created_count()); - else - EXPECT_EQ(1u, content_layer_->output_surface_created_count()); + EXPECT_EQ(1u, picture_layer_->output_surface_created_count()); layer_tree_host()->SetNeedsCommit(); break; case 2: - if (layer_tree_host()->settings().impl_side_painting) - EXPECT_EQ(1u, picture_layer_->output_surface_created_count()); - else - EXPECT_EQ(1u, content_layer_->output_surface_created_count()); + EXPECT_EQ(1u, picture_layer_->output_surface_created_count()); layer_tree_host()->SetNeedsCommit(); break; case 3: - if (layer_tree_host()->settings().impl_side_painting) - EXPECT_EQ(1u, picture_layer_->output_surface_created_count()); - else - EXPECT_EQ(1u, content_layer_->output_surface_created_count()); + EXPECT_EQ(1u, picture_layer_->output_surface_created_count()); break; case 4: - if (layer_tree_host()->settings().impl_side_painting) - EXPECT_EQ(2u, picture_layer_->output_surface_created_count()); - else - EXPECT_EQ(2u, content_layer_->output_surface_created_count()); + EXPECT_EQ(2u, picture_layer_->output_surface_created_count()); layer_tree_host()->SetNeedsCommit(); break; } @@ -1753,7 +1578,6 @@ class LayerTreeHostContextTestSurfaceCreateCallback protected: FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> picture_layer_; - scoped_refptr<FakeContentLayer> content_layer_; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback); diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc index 5766a192106..e29cb21333e 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc @@ -5,9 +5,9 @@ #include "cc/layers/layer_iterator.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" -#include "cc/test/fake_content_layer.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_output_surface.h" +#include "cc/test/fake_picture_layer.h" #include "cc/test/layer_tree_test.h" #include "cc/trees/layer_tree_impl.h" #include "gpu/GLES2/gl2extchromium.h" @@ -23,10 +23,10 @@ class LayerTreeHostCopyRequestTestMultipleRequests : public LayerTreeHostCopyRequestTest { protected: void SetupTree() override { - root = FakeContentLayer::Create(&client_); + root = FakePictureLayer::Create(layer_settings(), &client_); root->SetBounds(gfx::Size(20, 20)); - child = FakeContentLayer::Create(&client_); + child = FakePictureLayer::Create(layer_settings(), &client_); child->SetBounds(gfx::Size(10, 10)); root->AddChild(child); @@ -114,48 +114,47 @@ class LayerTreeHostCopyRequestTestMultipleRequests bool use_gl_renderer_; std::vector<gfx::Size> callbacks_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root; - scoped_refptr<FakeContentLayer> child; + scoped_refptr<FakePictureLayer> root; + scoped_refptr<FakePictureLayer> child; }; // Readback can't be done with a delegating renderer. -// Disabled due to flake: http://crbug.com/448521 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests, - DISABLED_GLRenderer_RunSingleThread) { + GLRenderer_RunSingleThread) { use_gl_renderer_ = true; - RunTest(false, false, false); + RunTest(false, false); } TEST_F(LayerTreeHostCopyRequestTestMultipleRequests, - GLRenderer_RunMultiThread_MainThreadPainting) { + GLRenderer_RunMultiThread) { use_gl_renderer_ = true; - RunTest(true, false, false); + RunTest(true, false); } TEST_F(LayerTreeHostCopyRequestTestMultipleRequests, SoftwareRenderer_RunSingleThread) { use_gl_renderer_ = false; - RunTest(false, false, false); + RunTest(false, false); } TEST_F(LayerTreeHostCopyRequestTestMultipleRequests, - SoftwareRenderer_RunMultiThread_MainThreadPainting) { + SoftwareRenderer_RunMultiThread) { use_gl_renderer_ = false; - RunTest(true, false, false); + RunTest(true, false); } class LayerTreeHostCopyRequestTestLayerDestroyed : public LayerTreeHostCopyRequestTest { protected: void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); - main_destroyed_ = FakeContentLayer::Create(&client_); + main_destroyed_ = FakePictureLayer::Create(layer_settings(), &client_); main_destroyed_->SetBounds(gfx::Size(15, 15)); root_->AddChild(main_destroyed_); - impl_destroyed_ = FakeContentLayer::Create(&client_); + impl_destroyed_ = FakePictureLayer::Create(layer_settings(), &client_); impl_destroyed_->SetBounds(gfx::Size(10, 10)); root_->AddChild(impl_destroyed_); @@ -229,9 +228,9 @@ class LayerTreeHostCopyRequestTestLayerDestroyed int callback_count_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> main_destroyed_; - scoped_refptr<FakeContentLayer> impl_destroyed_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> main_destroyed_; + scoped_refptr<FakePictureLayer> impl_destroyed_; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestLayerDestroyed); @@ -240,20 +239,20 @@ class LayerTreeHostCopyRequestTestInHiddenSubtree : public LayerTreeHostCopyRequestTest { protected: void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); - grand_parent_layer_ = FakeContentLayer::Create(&client_); + grand_parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_); grand_parent_layer_->SetBounds(gfx::Size(15, 15)); root_->AddChild(grand_parent_layer_); // parent_layer_ owns a render surface. - parent_layer_ = FakeContentLayer::Create(&client_); + parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_); parent_layer_->SetBounds(gfx::Size(15, 15)); parent_layer_->SetForceRenderSurface(true); grand_parent_layer_->AddChild(parent_layer_); - copy_layer_ = FakeContentLayer::Create(&client_); + copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_); copy_layer_->SetBounds(gfx::Size(10, 10)); parent_layer_->AddChild(copy_layer_); @@ -326,34 +325,34 @@ class LayerTreeHostCopyRequestTestInHiddenSubtree int callback_count_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> grand_parent_layer_; - scoped_refptr<FakeContentLayer> parent_layer_; - scoped_refptr<FakeContentLayer> copy_layer_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> grand_parent_layer_; + scoped_refptr<FakePictureLayer> parent_layer_; + scoped_refptr<FakePictureLayer> copy_layer_; }; -SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( +SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( LayerTreeHostCopyRequestTestInHiddenSubtree); class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest : public LayerTreeHostCopyRequestTest { protected: void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); - grand_parent_layer_ = FakeContentLayer::Create(&client_); + grand_parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_); grand_parent_layer_->SetBounds(gfx::Size(15, 15)); grand_parent_layer_->SetHideLayerAndSubtree(true); root_->AddChild(grand_parent_layer_); // parent_layer_ owns a render surface. - parent_layer_ = FakeContentLayer::Create(&client_); + parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_); parent_layer_->SetBounds(gfx::Size(15, 15)); parent_layer_->SetForceRenderSurface(true); grand_parent_layer_->AddChild(parent_layer_); - copy_layer_ = FakeContentLayer::Create(&client_); + copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_); copy_layer_->SetBounds(gfx::Size(10, 10)); parent_layer_->AddChild(copy_layer_); @@ -403,10 +402,10 @@ class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest FakeContentLayerClient client_; bool did_draw_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> grand_parent_layer_; - scoped_refptr<FakeContentLayer> parent_layer_; - scoped_refptr<FakeContentLayer> copy_layer_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> grand_parent_layer_; + scoped_refptr<FakePictureLayer> parent_layer_; + scoped_refptr<FakePictureLayer> copy_layer_; }; // No output to copy for delegated renderers. @@ -417,15 +416,15 @@ class LayerTreeHostCopyRequestTestClippedOut : public LayerTreeHostCopyRequestTest { protected: void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); - parent_layer_ = FakeContentLayer::Create(&client_); + parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_); parent_layer_->SetBounds(gfx::Size(15, 15)); parent_layer_->SetMasksToBounds(true); root_->AddChild(parent_layer_); - copy_layer_ = FakeContentLayer::Create(&client_); + copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_); copy_layer_->SetPosition(gfx::Point(15, 15)); copy_layer_->SetBounds(gfx::Size(10, 10)); parent_layer_->AddChild(copy_layer_); @@ -453,9 +452,9 @@ class LayerTreeHostCopyRequestTestClippedOut void AfterTest() override {} FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> parent_layer_; - scoped_refptr<FakeContentLayer> copy_layer_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> parent_layer_; + scoped_refptr<FakePictureLayer> copy_layer_; }; SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( @@ -465,10 +464,10 @@ class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw : public LayerTreeHostCopyRequestTest { protected: void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); - copy_layer_ = FakeContentLayer::Create(&client_); + copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_); copy_layer_->SetBounds(gfx::Size(10, 10)); root_->AddChild(copy_layer_); @@ -513,11 +512,24 @@ class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread()); - EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString()); - ++callback_count_; - if (callback_count_ == 2) - EndTest(); + // The first frame can't be drawn. + switch (callback_count_) { + case 0: + EXPECT_TRUE(result->IsEmpty()); + EXPECT_EQ(gfx::Size(), result->size()); + break; + case 1: + EXPECT_FALSE(result->IsEmpty()); + EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString()); + EndTest(); + break; + default: + NOTREACHED(); + break; + } + + ++callback_count_; } void AfterTest() override { EXPECT_TRUE(saw_copy_request_); } @@ -525,11 +537,11 @@ class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw bool saw_copy_request_; int callback_count_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> copy_layer_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> copy_layer_; }; -SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( +SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( LayerTreeHostTestAsyncTwoReadbacksWithoutDraw); class LayerTreeHostCopyRequestTestLostOutputSurface @@ -547,10 +559,10 @@ class LayerTreeHostCopyRequestTestLostOutputSurface } void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); - copy_layer_ = FakeContentLayer::Create(&client_); + copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_); copy_layer_->SetBounds(gfx::Size(10, 10)); root_->AddChild(copy_layer_); @@ -652,12 +664,12 @@ class LayerTreeHostCopyRequestTestLostOutputSurface size_t num_textures_without_readback_; size_t num_textures_after_loss_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> copy_layer_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> copy_layer_; scoped_ptr<CopyOutputResult> result_; }; -SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( +SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( LayerTreeHostCopyRequestTestLostOutputSurface); class LayerTreeHostCopyRequestTestCountTextures @@ -669,10 +681,12 @@ class LayerTreeHostCopyRequestTestCountTextures } void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); + client_.set_fill_with_nonsolid_color(true); + + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); - copy_layer_ = FakeContentLayer::Create(&client_); + copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_); copy_layer_->SetBounds(gfx::Size(10, 10)); root_->AddChild(copy_layer_); @@ -728,8 +742,8 @@ class LayerTreeHostCopyRequestTestCountTextures size_t num_textures_with_readback_; unsigned waited_sync_point_after_readback_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> copy_layer_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> copy_layer_; }; class LayerTreeHostCopyRequestTestCreatesTexture @@ -763,7 +777,7 @@ class LayerTreeHostCopyRequestTestCreatesTexture } }; -SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( +SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( LayerTreeHostCopyRequestTestCreatesTexture); class LayerTreeHostCopyRequestTestProvideTexture @@ -816,17 +830,17 @@ class LayerTreeHostCopyRequestTestProvideTexture unsigned sync_point_; }; -SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( +SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( LayerTreeHostCopyRequestTestProvideTexture); class LayerTreeHostCopyRequestTestDestroyBeforeCopy : public LayerTreeHostCopyRequestTest { protected: void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); - copy_layer_ = FakeContentLayer::Create(&client_); + copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_); copy_layer_->SetBounds(gfx::Size(10, 10)); root_->AddChild(copy_layer_); @@ -889,8 +903,8 @@ class LayerTreeHostCopyRequestTestDestroyBeforeCopy int callback_count_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> copy_layer_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> copy_layer_; }; SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( @@ -900,10 +914,10 @@ class LayerTreeHostCopyRequestTestShutdownBeforeCopy : public LayerTreeHostCopyRequestTest { protected: void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(20, 20)); - copy_layer_ = FakeContentLayer::Create(&client_); + copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_); copy_layer_->SetBounds(gfx::Size(10, 10)); root_->AddChild(copy_layer_); @@ -960,8 +974,8 @@ class LayerTreeHostCopyRequestTestShutdownBeforeCopy int callback_count_; FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> copy_layer_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> copy_layer_; }; SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( @@ -971,10 +985,11 @@ class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest : public LayerTreeHostCopyRequestTest { protected: void SetupTree() override { - scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_); + scoped_refptr<FakePictureLayer> root = + FakePictureLayer::Create(layer_settings(), &client_); root->SetBounds(gfx::Size(20, 20)); - child_ = FakeContentLayer::Create(&client_); + child_ = FakePictureLayer::Create(layer_settings(), &client_); child_->SetBounds(gfx::Size(10, 10)); root->AddChild(child_); child_->SetHideLayerAndSubtree(true); @@ -1009,10 +1024,9 @@ class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest bool saw_root = false; bool saw_child = false; - for (LayerIterator<LayerImpl> it = LayerIterator<LayerImpl>::Begin( - frame_data->render_surface_layer_list); - it != LayerIterator<LayerImpl>::End( - frame_data->render_surface_layer_list); + for (LayerIterator it = + LayerIterator::Begin(frame_data->render_surface_layer_list); + it != LayerIterator::End(frame_data->render_surface_layer_list); ++it) { if (it.represents_itself()) { if (*it == root) @@ -1073,7 +1087,7 @@ class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest void AfterTest() override {} - scoped_refptr<FakeContentLayer> child_; + scoped_refptr<FakePictureLayer> child_; FakeContentLayerClient client_; int num_draws_; bool copy_happened_; diff --git a/chromium/cc/trees/layer_tree_host_unittest_damage.cc b/chromium/cc/trees/layer_tree_host_unittest_damage.cc index daff40beb2d..fc5cacf087e 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_damage.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_damage.cc @@ -7,9 +7,8 @@ #include "base/bind.h" #include "base/callback.h" #include "base/location.h" -#include "base/message_loop/message_loop_proxy.h" #include "base/time/time.h" -#include "cc/test/fake_content_layer.h" +#include "cc/layers/solid_color_layer.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_painted_scrollbar_layer.h" #include "cc/test/fake_picture_layer.h" @@ -28,7 +27,8 @@ class LayerTreeHostDamageTestSetNeedsRedraw : public LayerTreeHostDamageTest { void SetupTree() override { // Viewport is 10x10. - scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_); + scoped_refptr<FakePictureLayer> root = + FakePictureLayer::Create(layer_settings(), &client_); root->SetBounds(gfx::Size(10, 10)); layer_tree_host()->SetRootLayer(root); @@ -89,7 +89,8 @@ class LayerTreeHostDamageTestSetViewportSize : public LayerTreeHostDamageTest { void SetupTree() override { // Viewport is 10x10. - scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_); + scoped_refptr<FakePictureLayer> root = + FakePictureLayer::Create(layer_settings(), &client_); root->SetBounds(gfx::Size(10, 10)); layer_tree_host()->SetRootLayer(root); @@ -155,11 +156,12 @@ class LayerTreeHostDamageTestNoDamageDoesNotSwap } void SetupTree() override { - scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_); + scoped_refptr<FakePictureLayer> root = + FakePictureLayer::Create(layer_settings(), &client_); root->SetBounds(gfx::Size(10, 10)); // Most of the layer isn't visible. - content_ = FakeContentLayer::Create(&client_); + content_ = FakePictureLayer::Create(layer_settings(), &client_); content_->SetBounds(gfx::Size(2000, 100)); root->AddChild(content_); @@ -227,21 +229,20 @@ class LayerTreeHostDamageTestNoDamageDoesNotSwap } FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> content_; + scoped_refptr<FakePictureLayer> content_; int expect_swap_and_succeed_; int did_swaps_; int did_swap_and_succeed_; }; -SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F( - LayerTreeHostDamageTestNoDamageDoesNotSwap); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageDoesNotSwap); class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } void SetupTree() override { - root_ = FakeContentLayer::Create(&client_); - child_ = FakeContentLayer::Create(&client_); + root_ = FakePictureLayer::Create(layer_settings(), &client_); + child_ = FakePictureLayer::Create(layer_settings(), &client_); root_->SetBounds(gfx::Size(500, 500)); child_->SetPosition(gfx::Point(100, 100)); @@ -293,21 +294,6 @@ class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest { // should match the invalidation. EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(), root_damage.ToString()); - - // TODO(danakj): Remove this when impl side painting is always on. - if (delegating_renderer() || - host_impl->settings().impl_side_painting) { - // When using a delegating renderer, or using impl side painting, the - // entire child is considered damaged as we need to replace its - // resources with newly created ones. The damaged area is kept as it - // is, but entire child is painted. - - // The paint rect should match the layer bounds. - gfx::RectF paint_rect = child_->LastPaintRect(); - paint_rect.set_origin(child_->position()); - EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(), - paint_rect.ToString()); - } EXPECT_FALSE(frame_data->has_no_damage); // If we damage part of the frame, but also damage the full @@ -340,33 +326,35 @@ class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest { void AfterTest() override {} FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> root_; - scoped_refptr<FakeContentLayer> child_; + scoped_refptr<FakePictureLayer> root_; + scoped_refptr<FakePictureLayer> child_; gfx::Rect child_damage_rect_; }; -SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestForcedFullDamage); class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest { void SetupTree() override { - scoped_refptr<Layer> root_layer = Layer::Create(); + scoped_refptr<Layer> root_layer = Layer::Create(layer_settings()); root_layer->SetBounds(gfx::Size(400, 400)); root_layer->SetMasksToBounds(true); layer_tree_host()->SetRootLayer(root_layer); - scoped_refptr<Layer> scroll_clip_layer = Layer::Create(); - scoped_refptr<Layer> content_layer = FakeContentLayer::Create(&client_); + scoped_refptr<Layer> scroll_clip_layer = Layer::Create(layer_settings()); + scoped_refptr<Layer> content_layer = + FakePictureLayer::Create(layer_settings(), &client_); content_layer->SetScrollClipLayerId(scroll_clip_layer->id()); content_layer->SetScrollOffset(gfx::ScrollOffset(10, 20)); content_layer->SetBounds(gfx::Size(100, 200)); + content_layer->SetIsDrawable(true); scroll_clip_layer->SetBounds( gfx::Size(content_layer->bounds().width() - 30, content_layer->bounds().height() - 50)); scroll_clip_layer->AddChild(content_layer); root_layer->AddChild(scroll_clip_layer); - scoped_refptr<Layer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, content_layer->id()); + scoped_refptr<Layer> scrollbar_layer = FakePaintedScrollbarLayer::Create( + layer_settings(), false, true, content_layer->id()); scrollbar_layer->SetPosition(gfx::Point(300, 300)); scrollbar_layer->SetBounds(gfx::Size(10, 100)); scrollbar_layer->ToScrollbarLayer()->SetClipLayer(scroll_clip_layer->id()); @@ -443,13 +431,25 @@ class LayerTreeHostDamageTestScrollbarDoesDamage host_impl->SetNeedsRedraw(); break; case 3: - scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 60, - root->bounds().height() + 100)); - host_impl->SetNeedsRedraw(); + // We will resize the content layer, on the main thread. + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind( + &LayerTreeHostDamageTestScrollbarDoesDamage::ResizeScrollLayer, + base::Unretained(this))); break; } } + void ResizeScrollLayer() { + EXPECT_EQ(3, did_swaps_); + Layer* root = layer_tree_host()->root_layer(); + Layer* scroll_clip_layer = root->child_at(0); + Layer* scroll_layer = scroll_clip_layer->child_at(0); + scroll_layer->SetBounds( + gfx::Size(root->bounds().width() + 60, root->bounds().height() + 100)); + } + void AfterTest() override { EXPECT_EQ(4, did_swaps_); } int did_swaps_; diff --git a/chromium/cc/trees/layer_tree_host_unittest_delegated.cc b/chromium/cc/trees/layer_tree_host_unittest_delegated.cc index 2864eb82ad6..2ebb337e807 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_delegated.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_delegated.cc @@ -135,7 +135,7 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest { } void AddTransferableResource(DelegatedFrameData* frame, - ResourceProvider::ResourceId resource_id) { + ResourceId resource_id) { TransferableResource resource; resource.id = resource_id; resource.mailbox_holder.texture_target = GL_TEXTURE_2D; @@ -147,8 +147,7 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest { frame->resource_list.push_back(resource); } - void AddTextureQuad(DelegatedFrameData* frame, - ResourceProvider::ResourceId resource_id) { + void AddTextureQuad(DelegatedFrameData* frame, ResourceId resource_id) { RenderPass* render_pass = frame->render_pass_list[0]; SharedQuadState* sqs = render_pass->CreateAndAppendSharedQuadState(); TextureDrawQuad* quad = @@ -201,9 +200,9 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest { background_filters); } - static ResourceProvider::ResourceId AppendResourceId( - std::vector<ResourceProvider::ResourceId>* resources_in_last_sent_frame, - ResourceProvider::ResourceId resource_id) { + static ResourceId AppendResourceId( + std::vector<ResourceId>* resources_in_last_sent_frame, + ResourceId resource_id) { resources_in_last_sent_frame->push_back(resource_id); return resource_id; } @@ -214,19 +213,18 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest { if (!delegated_frame_data) return; - std::vector<ResourceProvider::ResourceId> resources_in_last_sent_frame; + std::vector<ResourceId> resources_in_last_sent_frame; for (size_t i = 0; i < delegated_frame_data->resource_list.size(); ++i) { resources_in_last_sent_frame.push_back( delegated_frame_data->resource_list[i].id); } - std::vector<ResourceProvider::ResourceId> resources_to_return; + std::vector<ResourceId> resources_to_return; const TransferableResourceArray& resources_held_by_parent = output_surface()->resources_held_by_parent(); for (size_t i = 0; i < resources_held_by_parent.size(); ++i) { - ResourceProvider::ResourceId resource_in_parent = - resources_held_by_parent[i].id; + ResourceId resource_in_parent = resources_held_by_parent[i].id; bool resource_in_parent_is_not_part_of_frame = std::find(resources_in_last_sent_frame.begin(), resources_in_last_sent_frame.end(), @@ -274,7 +272,7 @@ class LayerTreeHostDelegatedTestCaseSingleDelegatedLayer } void SetupTree() override { - root_ = Layer::Create(); + root_ = Layer::Create(layer_settings()); root_->SetBounds(gfx::Size(15, 15)); layer_tree_host()->SetRootLayer(root_); @@ -310,7 +308,7 @@ class LayerTreeHostDelegatedTestCaseSingleDelegatedLayer scoped_refptr<DelegatedRendererLayer> CreateDelegatedLayer( DelegatedFrameProvider* frame_provider) { scoped_refptr<DelegatedRendererLayer> delegated = - FakeDelegatedRendererLayer::Create(frame_provider); + FakeDelegatedRendererLayer::Create(layer_settings(), frame_provider); delegated->SetBounds(gfx::Size(10, 10)); delegated->SetIsDrawable(true); @@ -432,7 +430,7 @@ class LayerTreeHostDelegatedTestDontUseLostChildIdAfterCommit } }; -MULTI_THREAD_IMPL_TEST_F( +SINGLE_AND_MULTI_THREAD_TEST_F( LayerTreeHostDelegatedTestDontUseLostChildIdAfterCommit); // Test that we can gracefully handle invalid frames after the context was lost. @@ -804,18 +802,18 @@ class LayerTreeHostDelegatedTestRemapResourcesInQuads EXPECT_EQ(1u, map.count(999)); EXPECT_EQ(1u, map.count(555)); - ResourceProvider::ResourceId parent_resource_id1 = map.find(999)->second; + ResourceId parent_resource_id1 = map.find(999)->second; EXPECT_NE(parent_resource_id1, 999u); - ResourceProvider::ResourceId parent_resource_id2 = map.find(555)->second; + ResourceId parent_resource_id2 = map.find(555)->second; EXPECT_NE(parent_resource_id2, 555u); // The resources in the quads should be remapped to the parent's namespace. const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast( delegated_impl->RenderPassesInDrawOrder()[0]->quad_list.ElementAt(0)); - EXPECT_EQ(parent_resource_id1, quad1->resource_id); + EXPECT_EQ(parent_resource_id1, quad1->resource_id()); const TextureDrawQuad* quad2 = TextureDrawQuad::MaterialCast( delegated_impl->RenderPassesInDrawOrder()[0]->quad_list.ElementAt(1)); - EXPECT_EQ(parent_resource_id2, quad2->resource_id); + EXPECT_EQ(parent_resource_id2, quad2->resource_id()); EndTest(); } @@ -1057,7 +1055,7 @@ class LayerTreeHostDelegatedTestFrameBeforeAck EXPECT_EQ(1u, pass->quad_list.size()); const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(pass->quad_list.front()); - EXPECT_EQ(map.find(999)->second, quad->resource_id); + EXPECT_EQ(map.find(999)->second, quad->resource_id()); EndTest(); } @@ -1169,13 +1167,13 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources EXPECT_EQ(3u, pass->quad_list.size()); const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast(pass->quad_list.ElementAt(0)); - EXPECT_EQ(map.find(999)->second, quad1->resource_id); + EXPECT_EQ(map.find(999)->second, quad1->resource_id()); const TextureDrawQuad* quad2 = TextureDrawQuad::MaterialCast(pass->quad_list.ElementAt(1)); - EXPECT_EQ(map.find(555)->second, quad2->resource_id); + EXPECT_EQ(map.find(555)->second, quad2->resource_id()); const TextureDrawQuad* quad3 = TextureDrawQuad::MaterialCast(pass->quad_list.ElementAt(2)); - EXPECT_EQ(map.find(444)->second, quad3->resource_id); + EXPECT_EQ(map.find(444)->second, quad3->resource_id()); } void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { @@ -1288,10 +1286,10 @@ class LayerTreeHostDelegatedTestBadFrame EXPECT_EQ(2u, pass->quad_list.size()); const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast(pass->quad_list.ElementAt(0)); - EXPECT_EQ(map.find(999)->second, quad1->resource_id); + EXPECT_EQ(map.find(999)->second, quad1->resource_id()); const TextureDrawQuad* quad2 = TextureDrawQuad::MaterialCast(pass->quad_list.ElementAt(1)); - EXPECT_EQ(map.find(555)->second, quad2->resource_id); + EXPECT_EQ(map.find(555)->second, quad2->resource_id()); break; } case 2: { @@ -1310,10 +1308,10 @@ class LayerTreeHostDelegatedTestBadFrame EXPECT_EQ(2u, pass->quad_list.size()); const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast(pass->quad_list.ElementAt(0)); - EXPECT_EQ(map.find(999)->second, quad1->resource_id); + EXPECT_EQ(map.find(999)->second, quad1->resource_id()); const TextureDrawQuad* quad2 = TextureDrawQuad::MaterialCast(pass->quad_list.ElementAt(1)); - EXPECT_EQ(map.find(555)->second, quad2->resource_id); + EXPECT_EQ(map.find(555)->second, quad2->resource_id()); break; } case 3: { @@ -1328,7 +1326,7 @@ class LayerTreeHostDelegatedTestBadFrame EXPECT_EQ(1u, pass->quad_list.size()); const TextureDrawQuad* quad1 = TextureDrawQuad::MaterialCast(pass->quad_list.front()); - EXPECT_EQ(map.find(999)->second, quad1->resource_id); + EXPECT_EQ(map.find(999)->second, quad1->resource_id()); break; } } @@ -2288,7 +2286,8 @@ class LayerTreeHostDelegatedTestActiveFrameIsValid bool drew_with_pending_tree_; }; -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostDelegatedTestActiveFrameIsValid); +// This test blocks activation which is not supported for single thread mode. +MULTI_THREAD_BLOCKNOTIFY_TEST_F(LayerTreeHostDelegatedTestActiveFrameIsValid); } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_no_message_loop.cc b/chromium/cc/trees/layer_tree_host_unittest_no_message_loop.cc deleted file mode 100644 index ef948f70240..00000000000 --- a/chromium/cc/trees/layer_tree_host_unittest_no_message_loop.cc +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/thread_task_runner_handle.h" -#include "base/threading/simple_thread.h" -#include "cc/layers/delegated_frame_provider.h" -#include "cc/layers/delegated_frame_resource_collection.h" -#include "cc/layers/delegated_renderer_layer.h" -#include "cc/layers/layer.h" -#include "cc/layers/solid_color_layer.h" -#include "cc/output/delegated_frame_data.h" -#include "cc/output/output_surface.h" -#include "cc/output/output_surface_client.h" -#include "cc/resources/resource_provider.h" -#include "cc/scheduler/begin_frame_source.h" -#include "cc/test/fake_delegated_renderer_layer.h" -#include "cc/test/test_context_provider.h" -#include "cc/trees/layer_tree_host.h" -#include "cc/trees/layer_tree_host_client.h" -#include "cc/trees/layer_tree_host_single_thread_client.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/frame_time.h" - -namespace cc { -namespace { - -class NoMessageLoopOutputSurface : public OutputSurface { - public: - NoMessageLoopOutputSurface() : OutputSurface(TestContextProvider::Create()) {} - ~NoMessageLoopOutputSurface() override {} - - // OutputSurface overrides. - void SwapBuffers(CompositorFrame* frame) override { - DCHECK(client_); - client_->DidSwapBuffers(); - client_->DidSwapBuffersComplete(); - } -}; - -class LayerTreeHostNoMessageLoopTest - : public testing::Test, - public base::DelegateSimpleThread::Delegate, - public LayerTreeHostClient, - public LayerTreeHostSingleThreadClient { - public: - LayerTreeHostNoMessageLoopTest() - : did_initialize_output_surface_(false), - did_commit_(false), - did_commit_and_draw_frame_(false), - size_(100, 100), - no_loop_thread_(this, "LayerTreeHostNoMessageLoopTest") {} - ~LayerTreeHostNoMessageLoopTest() override {} - - // LayerTreeHostClient overrides. - void WillBeginMainFrame() override {} - void BeginMainFrame(const BeginFrameArgs& args) override {} - void BeginMainFrameNotExpectedSoon() override {} - void DidBeginMainFrame() override {} - void Layout() override {} - void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta, - const gfx::Vector2dF& outer_delta, - const gfx::Vector2dF& elastic_overscroll_delta, - float page_scale, - float top_controls_delta) override {} - void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, - float page_scale, - float top_controls_delta) override {} - void RequestNewOutputSurface() override { - layer_tree_host_->SetOutputSurface( - make_scoped_ptr<OutputSurface>(new NoMessageLoopOutputSurface)); - } - void DidInitializeOutputSurface() override { - did_initialize_output_surface_ = true; - } - void DidFailToInitializeOutputSurface() override {} - void WillCommit() override {} - void DidCommit() override { did_commit_ = true; } - void DidCommitAndDrawFrame() override { did_commit_and_draw_frame_ = true; } - void DidCompleteSwapBuffers() override {} - void DidCompletePageScaleAnimation() override {} - - // LayerTreeHostSingleThreadClient overrides. - void DidPostSwapBuffers() override {} - void DidAbortSwapBuffers() override {} - - void RunTest() { - no_loop_thread_.Start(); - no_loop_thread_.Join(); - } - - // base::DelegateSimpleThread::Delegate override. - void Run() override { - ASSERT_FALSE(base::ThreadTaskRunnerHandle::IsSet()); - RunTestWithoutMessageLoop(); - EXPECT_FALSE(base::ThreadTaskRunnerHandle::IsSet()); - } - - protected: - virtual void RunTestWithoutMessageLoop() = 0; - - void SetupLayerTreeHost() { - LayerTreeSettings settings; - settings.single_thread_proxy_scheduler = false; - settings.verify_property_trees = true; - settings.raster_enabled = false; - - LayerTreeHost::InitParams params; - params.client = this; - params.settings = &settings; - layer_tree_host_ = LayerTreeHost::CreateSingleThreaded(this, ¶ms); - layer_tree_host_->SetViewportSize(size_); - layer_tree_host_->SetRootLayer(root_layer_); - } - - void Composite() { - did_commit_ = false; - did_commit_and_draw_frame_ = false; - layer_tree_host_->Composite(gfx::FrameTime::Now()); - EXPECT_TRUE(did_initialize_output_surface_); - EXPECT_TRUE(did_commit_); - EXPECT_TRUE(did_commit_and_draw_frame_); - } - - void TearDownLayerTreeHost() { - // Explicit teardown to make failures easier to debug. - layer_tree_host_ = nullptr; - root_layer_ = nullptr; - } - - // All protected member variables are accessed only on |no_loop_thread_|. - scoped_ptr<LayerTreeHost> layer_tree_host_; - scoped_refptr<Layer> root_layer_; - - bool did_initialize_output_surface_; - bool did_commit_; - bool did_commit_and_draw_frame_; - gfx::Size size_; - - private: - base::DelegateSimpleThread no_loop_thread_; -}; - -class LayerTreeHostNoMessageLoopSmokeTest - : public LayerTreeHostNoMessageLoopTest { - protected: - void RunTestWithoutMessageLoop() override { - gfx::Size size(100, 100); - - // Set up root layer. - { - scoped_refptr<SolidColorLayer> solid_color_layer = - SolidColorLayer::Create(); - solid_color_layer->SetBackgroundColor(SK_ColorRED); - solid_color_layer->SetBounds(size_); - solid_color_layer->SetIsDrawable(true); - root_layer_ = solid_color_layer; - } - - SetupLayerTreeHost(); - Composite(); - TearDownLayerTreeHost(); - } -}; - -TEST_F(LayerTreeHostNoMessageLoopSmokeTest, SmokeTest) { - RunTest(); -} - -class LayerTreeHostNoMessageLoopDelegatedLayer - : public LayerTreeHostNoMessageLoopTest, - public DelegatedFrameResourceCollectionClient { - protected: - void RunTestWithoutMessageLoop() override { - resource_collection_ = new DelegatedFrameResourceCollection; - frame_provider_ = new DelegatedFrameProvider( - resource_collection_.get(), CreateFrameDataWithResource(998)); - - root_layer_ = Layer::Create(); - delegated_layer_ = - FakeDelegatedRendererLayer::Create(frame_provider_.get()); - delegated_layer_->SetBounds(size_); - delegated_layer_->SetIsDrawable(true); - root_layer_->AddChild(delegated_layer_); - - SetupLayerTreeHost(); - - // Draw first frame. - Composite(); - - // Prepare and draw second frame. - frame_provider_->SetFrameData(CreateFrameDataWithResource(999)); - Composite(); - - // Resource from first frame should be returned. - CheckReturnedResource(1u); - - TearDownLayerTreeHost(); - delegated_layer_ = NULL; - frame_provider_ = NULL; - - // Resource from second frame should be returned. - CheckReturnedResource(1u); - resource_collection_ = NULL; - } - - // DelegatedFrameResourceCollectionClient overrides. - void UnusedResourcesAreAvailable() override {} - - private: - scoped_ptr<DelegatedFrameData> CreateFrameDataWithResource( - ResourceProvider::ResourceId resource_id) { - scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData); - gfx::Rect frame_rect(size_); - - scoped_ptr<RenderPass> root_pass(RenderPass::Create()); - root_pass->SetNew( - RenderPassId(1, 1), frame_rect, frame_rect, gfx::Transform()); - frame->render_pass_list.push_back(root_pass.Pass()); - - TransferableResource resource; - resource.id = resource_id; - resource.mailbox_holder.texture_target = GL_TEXTURE_2D; - resource.mailbox_holder.mailbox = gpu::Mailbox::Generate(); - frame->resource_list.push_back(resource); - - return frame.Pass(); - } - - void CheckReturnedResource(size_t expected_num) { - ReturnedResourceArray returned_resources; - resource_collection_->TakeUnusedResourcesForChildCompositor( - &returned_resources); - EXPECT_EQ(expected_num, returned_resources.size()); - } - - scoped_refptr<DelegatedFrameResourceCollection> resource_collection_; - scoped_refptr<DelegatedFrameProvider> frame_provider_; - scoped_refptr<DelegatedRendererLayer> delegated_layer_; -}; - -TEST_F(LayerTreeHostNoMessageLoopDelegatedLayer, SingleDelegatedLayer) { - RunTest(); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_occlusion.cc b/chromium/cc/trees/layer_tree_host_unittest_occlusion.cc index 9974ae4066b..37c56d1e74a 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_occlusion.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_occlusion.cc @@ -30,11 +30,11 @@ class LayerTreeHostOcclusionTestDrawPropertiesOnLayer : public LayerTreeHostOcclusionTest { public: void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(100, 100)); root->SetIsDrawable(true); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); child->SetBounds(gfx::Size(50, 60)); child->SetPosition(gfx::PointF(10.f, 5.5f)); child->SetContentsOpaque(true); @@ -76,18 +76,18 @@ class LayerTreeHostOcclusionTestDrawPropertiesOnSurface : public LayerTreeHostOcclusionTest { public: void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(100, 100)); root->SetIsDrawable(true); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); child->SetBounds(gfx::Size(1, 1)); child->SetPosition(gfx::PointF(10.f, 5.5f)); child->SetIsDrawable(true); child->SetForceRenderSurface(true); root->AddChild(child); - scoped_refptr<Layer> child2 = Layer::Create(); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings()); child2->SetBounds(gfx::Size(10, 12)); child2->SetPosition(gfx::PointF(13.f, 8.5f)); child2->SetContentsOpaque(true); @@ -128,28 +128,29 @@ class LayerTreeHostOcclusionTestDrawPropertiesOnMask : public LayerTreeHostOcclusionTest { public: void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(100, 100)); root->SetIsDrawable(true); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); child->SetBounds(gfx::Size(30, 40)); child->SetPosition(gfx::PointF(10.f, 5.5f)); child->SetIsDrawable(true); root->AddChild(child); - scoped_refptr<Layer> make_surface_bigger = Layer::Create(); + scoped_refptr<Layer> make_surface_bigger = Layer::Create(layer_settings()); make_surface_bigger->SetBounds(gfx::Size(100, 100)); make_surface_bigger->SetPosition(gfx::PointF(-10.f, -15.f)); make_surface_bigger->SetIsDrawable(true); child->AddChild(make_surface_bigger); - scoped_refptr<Layer> mask = PictureLayer::Create(&client_); + scoped_refptr<Layer> mask = + PictureLayer::Create(layer_settings(), &client_); mask->SetBounds(gfx::Size(30, 40)); mask->SetIsDrawable(true); child->SetMaskLayer(mask.get()); - scoped_refptr<Layer> child2 = Layer::Create(); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings()); child2->SetBounds(gfx::Size(10, 12)); child2->SetPosition(gfx::PointF(13.f, 8.5f)); child2->SetContentsOpaque(true); @@ -198,29 +199,30 @@ class LayerTreeHostOcclusionTestDrawPropertiesInsideReplica : public LayerTreeHostOcclusionTest { public: void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(100, 100)); root->SetIsDrawable(true); - scoped_refptr<Layer> child = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(layer_settings()); child->SetBounds(gfx::Size(1, 1)); child->SetPosition(gfx::PointF(10.f, 5.5f)); child->SetIsDrawable(true); child->SetForceRenderSurface(true); root->AddChild(child); - scoped_refptr<Layer> replica = Layer::Create(); + scoped_refptr<Layer> replica = Layer::Create(layer_settings()); gfx::Transform translate; translate.Translate(20.f, 4.f); replica->SetTransform(translate); child->SetReplicaLayer(replica.get()); - scoped_refptr<Layer> mask = PictureLayer::Create(&client_); + scoped_refptr<Layer> mask = + PictureLayer::Create(layer_settings(), &client_); mask->SetBounds(gfx::Size(30, 40)); mask->SetIsDrawable(true); child->SetMaskLayer(mask.get()); - scoped_refptr<Layer> child2 = Layer::Create(); + scoped_refptr<Layer> child2 = Layer::Create(layer_settings()); child2->SetBounds(gfx::Size(10, 12)); child2->SetPosition(gfx::PointF(13.f, 8.5f)); child2->SetContentsOpaque(true); diff --git a/chromium/cc/trees/layer_tree_host_unittest_picture.cc b/chromium/cc/trees/layer_tree_host_unittest_picture.cc index 6f222f71e71..7a0d7bfa520 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_picture.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_picture.cc @@ -17,10 +17,10 @@ namespace { class LayerTreeHostPictureTest : public LayerTreeTest { protected: void SetupTreeWithSinglePictureLayer(const gfx::Size& size) { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(size); - root_picture_layer_ = FakePictureLayer::Create(&client_); + root_picture_layer_ = FakePictureLayer::Create(layer_settings(), &client_); root_picture_layer_->SetBounds(size); root->AddChild(root_picture_layer_); @@ -57,7 +57,7 @@ class LayerTreeHostPictureTestTwinLayer // Add a new picture layer so the activate will have a pending layer // without an active twin. scoped_refptr<FakePictureLayer> picture = - FakePictureLayer::Create(&client_); + FakePictureLayer::Create(layer_settings(), &client_); layer_tree_host()->root_layer()->AddChild(picture); break; } @@ -107,24 +107,16 @@ class LayerTreeHostPictureTestTwinLayer active_picture_impl->GetPendingOrActiveTwinLayer()); EXPECT_EQ(active_picture_impl, pending_picture_impl->GetPendingOrActiveTwinLayer()); - EXPECT_EQ(nullptr, active_picture_impl->GetRecycledTwinLayer()); } void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { LayerImpl* active_root_impl = impl->active_tree()->root_layer(); - LayerImpl* recycle_root_impl = impl->recycle_tree()->root_layer(); - if (active_root_impl->children().empty()) { EXPECT_EQ(2, activates_); } else { FakePictureLayerImpl* active_picture_impl = static_cast<FakePictureLayerImpl*>(active_root_impl->children()[0]); - FakePictureLayerImpl* recycle_picture_impl = - static_cast<FakePictureLayerImpl*>(recycle_root_impl->children()[0]); - EXPECT_EQ(nullptr, active_picture_impl->GetPendingOrActiveTwinLayer()); - EXPECT_EQ(recycle_picture_impl, - active_picture_impl->GetRecycledTwinLayer()); } ++activates_; @@ -136,7 +128,7 @@ class LayerTreeHostPictureTestTwinLayer }; // There is no pending layers in single thread mode. -MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestTwinLayer); +MULTI_THREAD_TEST_F(LayerTreeHostPictureTestTwinLayer); class LayerTreeHostPictureTestResizeViewportWithGpuRaster : public LayerTreeHostPictureTest { @@ -145,11 +137,11 @@ class LayerTreeHostPictureTestResizeViewportWithGpuRaster } void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(768, 960)); client_.set_fill_with_nonsolid_color(true); - picture_ = FakePictureLayer::Create(&client_); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(768, 960)); root->AddChild(picture_); @@ -199,7 +191,7 @@ class LayerTreeHostPictureTestResizeViewportWithGpuRaster scoped_refptr<FakePictureLayer> picture_; }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F( +SINGLE_AND_MULTI_THREAD_TEST_F( LayerTreeHostPictureTestResizeViewportWithGpuRaster); class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree @@ -208,13 +200,13 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree frame_ = 0; did_post_commit_ = false; - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(100, 100)); // The layer is big enough that the live tiles rect won't cover the full // layer. client_.set_fill_with_nonsolid_color(true); - picture_ = FakePictureLayer::Create(&client_); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(100, 100000)); root->AddChild(picture_); @@ -228,13 +220,9 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree LayerImpl* child = impl->active_tree()->root_layer()->children()[0]; FakePictureLayerImpl* picture_impl = static_cast<FakePictureLayerImpl*>(child); - FakePictureLayerImpl* recycled_impl = static_cast<FakePictureLayerImpl*>( - picture_impl->GetRecycledTwinLayer()); - switch (++frame_) { case 1: { PictureLayerTiling* tiling = picture_impl->HighResTiling(); - PictureLayerTiling* recycled_tiling = recycled_impl->HighResTiling(); int num_tiles_y = tiling->TilingDataForTesting().num_tiles_y(); // There should be tiles at the top of the picture layer but not at the @@ -242,52 +230,34 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree EXPECT_TRUE(tiling->TileAt(0, 0)); EXPECT_FALSE(tiling->TileAt(0, num_tiles_y)); - // The recycled tiling has no tiles. - EXPECT_FALSE(recycled_tiling->TileAt(0, 0)); - EXPECT_FALSE(recycled_tiling->TileAt(0, num_tiles_y)); - - // The live tiles rect matches on the recycled tree. - EXPECT_EQ(tiling->live_tiles_rect(), - recycled_tiling->live_tiles_rect()); - // Make the bottom of the layer visible. - picture_impl->SetPosition(gfx::PointF(0.f, -100000.f + 100.f)); + gfx::Transform transform; + transform.Translate(0.f, -100000.f + 100.f); + picture_impl->SetTransform(transform); + picture_impl->UpdatePropertyTreeTransform(); impl->SetNeedsRedraw(); break; } case 2: { PictureLayerTiling* tiling = picture_impl->HighResTiling(); - PictureLayerTiling* recycled_tiling = recycled_impl->HighResTiling(); // There not be tiles at the top of the layer now. EXPECT_FALSE(tiling->TileAt(0, 0)); - // The recycled twin tiling should not have unshared tiles at the top - // either. - EXPECT_FALSE(recycled_tiling->TileAt(0, 0)); - // Make the top of the layer visible again. - picture_impl->SetPosition(gfx::PointF()); + picture_impl->SetTransform(gfx::Transform()); + picture_impl->UpdatePropertyTreeTransform(); impl->SetNeedsRedraw(); break; } case 3: { PictureLayerTiling* tiling = picture_impl->HighResTiling(); - PictureLayerTiling* recycled_tiling = recycled_impl->HighResTiling(); int num_tiles_y = tiling->TilingDataForTesting().num_tiles_y(); // There should be tiles at the top of the picture layer again. EXPECT_TRUE(tiling->TileAt(0, 0)); EXPECT_FALSE(tiling->TileAt(0, num_tiles_y)); - // The recycled tiling should have no tiles. - EXPECT_FALSE(recycled_tiling->TileAt(0, 0)); - EXPECT_FALSE(recycled_tiling->TileAt(0, num_tiles_y)); - - // The live tiles rect matches on the recycled tree. - EXPECT_EQ(tiling->live_tiles_rect(), - recycled_tiling->live_tiles_rect()); - // Make a new main frame without changing the picture layer at all, so // it won't need to update or push properties. did_post_commit_ = true; @@ -328,20 +298,19 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree }; // Multi-thread only since there is no recycle tree in single thread. -MULTI_THREAD_IMPL_TEST_F( - LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree); +MULTI_THREAD_TEST_F(LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree); class LayerTreeHostPictureTestRSLLMembership : public LayerTreeHostPictureTest { void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(100, 100)); - child_ = Layer::Create(); + child_ = Layer::Create(layer_settings()); root->AddChild(child_); // Don't be solid color so the layer has tilings/tiles. client_.set_fill_with_nonsolid_color(true); - picture_ = FakePictureLayer::Create(&client_); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(100, 100)); child_->AddChild(picture_); @@ -417,15 +386,15 @@ class LayerTreeHostPictureTestRSLLMembership : public LayerTreeHostPictureTest { scoped_refptr<FakePictureLayer> picture_; }; -SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestRSLLMembership); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostPictureTestRSLLMembership); class LayerTreeHostPictureTestRSLLMembershipWithScale : public LayerTreeHostPictureTest { void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(100, 100)); - pinch_ = Layer::Create(); + pinch_ = Layer::Create(layer_settings()); pinch_->SetBounds(gfx::Size(500, 500)); pinch_->SetScrollClipLayerId(root->id()); pinch_->SetIsContainerForFixedPositionLayers(true); @@ -433,7 +402,7 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale // Don't be solid color so the layer has tilings/tiles. client_.set_fill_with_nonsolid_color(true); - picture_ = FakePictureLayer::Create(&client_); + picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(100, 100)); pinch_->AddChild(picture_); @@ -568,7 +537,7 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale // Multi-thread only because in single thread you can't pinch zoom on the // compositor thread. // Disabled due to flakiness. See http://crbug.com/460581 -// MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestRSLLMembershipWithScale); +// MULTI_THREAD_TEST_F(LayerTreeHostPictureTestRSLLMembershipWithScale); } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc index 313510371e7..66340e7bbff 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc @@ -7,16 +7,8 @@ #include "cc/test/layer_tree_test.h" #include "cc/trees/thread_proxy.h" -#define THREAD_PROXY_NO_IMPL_TEST_F(TEST_FIXTURE_NAME) \ - TEST_F(TEST_FIXTURE_NAME, Run_MainThreadPaint) { \ - Run(true, false); \ - } - -#define THREAD_PROXY_TEST_F(TEST_FIXTURE_NAME) \ - THREAD_PROXY_NO_IMPL_TEST_F(TEST_FIXTURE_NAME); \ - TEST_F(TEST_FIXTURE_NAME, Run_ImplSidePaint) { \ - Run(true, true); \ - } +#define THREAD_PROXY_TEST_F(TEST_FIXTURE_NAME) \ + TEST_F(TEST_FIXTURE_NAME, MultiThread) { Run(true); } // Do common tests for single thread proxy and thread proxy. // TODO(simonhong): Add SINGLE_THREAD_PROXY_TEST_F @@ -30,11 +22,11 @@ class ProxyTest : public LayerTreeTest { ProxyTest() {} ~ProxyTest() override {} - void Run(bool threaded, bool impl_side_painting) { + void Run(bool threaded) { // We don't need to care about delegating mode. bool delegating_renderer = true; - RunTest(threaded, delegating_renderer, impl_side_painting); + RunTest(threaded, delegating_renderer); } void BeginTest() override {} diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc index 4e77a2d245f..dc075b563cf 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc @@ -19,6 +19,7 @@ #include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_test.h" #include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_impl.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" @@ -39,7 +40,7 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest { void BeginTest() override { Layer* root_layer = layer_tree_host()->root_layer(); - scoped_refptr<Layer> scroll_layer = Layer::Create(); + scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings()); root_layer->AddChild(scroll_layer); // Create an effective max_scroll_offset of (100, 100). scroll_layer->SetBounds(gfx::Size(root_layer->bounds().width() + 100, @@ -92,7 +93,9 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest { } } - void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, + void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta, + const gfx::Vector2dF& outer_delta, + const gfx::Vector2dF& elastic_overscroll_delta, float scale, float top_controls_delta) override { num_scrolls_++; @@ -117,7 +120,7 @@ class LayerTreeHostScrollTestScrollMultipleRedraw void BeginTest() override { Layer* root_layer = layer_tree_host()->root_layer(); - scroll_layer_ = Layer::Create(); + scroll_layer_ = Layer::Create(layer_settings()); root_layer->AddChild(scroll_layer_); // Create an effective max_scroll_offset of (100, 100). scroll_layer_->SetBounds(gfx::Size(root_layer->bounds().width() + 100, @@ -154,7 +157,7 @@ class LayerTreeHostScrollTestScrollMultipleRedraw LayerImpl* scroll_layer = impl->active_tree()->LayerById(scroll_layer_->id()); if (impl->active_tree()->source_frame_number() == 0 && - impl->SourceAnimationFrameNumber() == 1) { + impl->SourceAnimationFrameNumberForTesting() == 1) { // First draw after first commit. EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), gfx::Vector2d()); scroll_layer->ScrollBy(scroll_amount_); @@ -163,7 +166,7 @@ class LayerTreeHostScrollTestScrollMultipleRedraw EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), initial_scroll_); PostSetNeedsRedrawToMainThread(); } else if (impl->active_tree()->source_frame_number() == 0 && - impl->SourceAnimationFrameNumber() == 2) { + impl->SourceAnimationFrameNumberForTesting() == 2) { // Second draw after first commit. EXPECT_EQ(scroll_layer->ScrollDelta(), scroll_amount_); scroll_layer->ScrollBy(scroll_amount_); @@ -174,7 +177,7 @@ class LayerTreeHostScrollTestScrollMultipleRedraw PostSetNeedsCommitToMainThread(); } else if (impl->active_tree()->source_frame_number() == 1) { // Third or later draw after second commit. - EXPECT_GE(impl->SourceAnimationFrameNumber(), 3); + EXPECT_GE(impl->SourceAnimationFrameNumberForTesting(), 3u); EXPECT_VECTOR_EQ(scroll_layer_->ScrollDelta(), gfx::Vector2d()); EXPECT_VECTOR_EQ( scroll_layer_->scroll_offset(), @@ -184,7 +187,9 @@ class LayerTreeHostScrollTestScrollMultipleRedraw } } - void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, + void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta, + const gfx::Vector2dF& outer_delta, + const gfx::Vector2dF& elastic_overscroll_delta, float scale, float top_controls_delta) override { num_scrolls_++; @@ -221,7 +226,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit void SetupTree() override { LayerTreeHostScrollTest::SetupTree(); Layer* root_layer = layer_tree_host()->root_layer(); - scoped_refptr<Layer> root_scroll_layer = Layer::Create(); + scoped_refptr<Layer> root_scroll_layer = Layer::Create(layer_settings()); root_scroll_layer->SetScrollClipLayerId(root_layer->id()); root_scroll_layer->SetScrollOffset(initial_scroll_); root_scroll_layer->SetBounds(gfx::Size(200, 200)); @@ -301,7 +306,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit impl->active_tree()->root_layer()->children()[0]; if (impl->active_tree()->source_frame_number() == 0 && - impl->SourceAnimationFrameNumber() == 1) { + impl->SourceAnimationFrameNumberForTesting() == 1) { // First draw EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d()); root_scroll_layer->ScrollBy(impl_scroll_); @@ -317,7 +322,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit // To simplify the testing flow, don't redraw here, just commit. impl->SetNeedsCommit(); } else if (impl->active_tree()->source_frame_number() == 0 && - impl->SourceAnimationFrameNumber() == 2) { + impl->SourceAnimationFrameNumberForTesting() == 2) { // Test a second draw after an aborted commit. // The scroll/scale values should be baked into the offset/scale factor // since the main thread consumed but aborted the begin frame. @@ -340,7 +345,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit // Commit for source frame 1 is aborted. NOTREACHED(); } else if (impl->active_tree()->source_frame_number() == 2 && - impl->SourceAnimationFrameNumber() == 3) { + impl->SourceAnimationFrameNumberForTesting() == 3) { // Third draw after the second full commit. EXPECT_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d()); root_scroll_layer->ScrollBy(impl_scroll_); @@ -350,7 +355,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit EXPECT_VECTOR_EQ(root_scroll_layer->BaseScrollOffset(), gfx::ScrollOffsetWithDelta(initial_scroll_, delta)); } else if (impl->active_tree()->source_frame_number() == 2 && - impl->SourceAnimationFrameNumber() == 4) { + impl->SourceAnimationFrameNumberForTesting() == 4) { // Final draw after the second aborted commit. EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d()); gfx::Vector2dF delta = @@ -364,7 +369,9 @@ class LayerTreeHostScrollTestScrollAbortedCommit } } - void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, + void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta, + const gfx::Vector2dF& outer_delta, + const gfx::Vector2dF& elastic_overscroll_delta, float scale, float top_controls_delta) override { num_impl_scrolls_++; @@ -403,7 +410,7 @@ class LayerTreeHostScrollTestFractionalScroll : public LayerTreeHostScrollTest { void SetupTree() override { LayerTreeHostScrollTest::SetupTree(); Layer* root_layer = layer_tree_host()->root_layer(); - scoped_refptr<Layer> root_scroll_layer = Layer::Create(); + scoped_refptr<Layer> root_scroll_layer = Layer::Create(layer_settings()); root_scroll_layer->SetScrollClipLayerId(root_layer->id()); root_scroll_layer->SetBounds( gfx::Size(root_layer->bounds().width() + 100, @@ -470,10 +477,11 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { void SetupTree() override { layer_tree_host()->SetDeviceScaleFactor(device_scale_factor_); - scoped_refptr<Layer> root_layer = Layer::Create(); + scoped_refptr<Layer> root_layer = Layer::Create(layer_settings()); root_layer->SetBounds(gfx::Size(10, 10)); - root_scroll_layer_ = FakePictureLayer::Create(&fake_content_layer_client_); + root_scroll_layer_ = + FakePictureLayer::Create(layer_settings(), &fake_content_layer_client_); root_scroll_layer_->SetBounds(gfx::Size(110, 110)); root_scroll_layer_->SetPosition(gfx::Point()); @@ -483,7 +491,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { root_scroll_layer_->SetIsContainerForFixedPositionLayers(true); root_layer->AddChild(root_scroll_layer_); - child_layer_ = FakePictureLayer::Create(&fake_content_layer_client_); + child_layer_ = + FakePictureLayer::Create(layer_settings(), &fake_content_layer_client_); child_layer_->set_did_scroll_callback( base::Bind(&LayerTreeHostScrollTestCaseWithChild::DidScroll, base::Unretained(this))); @@ -534,7 +543,9 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { final_scroll_offset_ = expected_scroll_layer_->scroll_offset(); } - void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, + void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta, + const gfx::Vector2dF& outer_delta, + const gfx::Vector2dF& elastic_overscroll_delta, float scale, float top_controls_delta) override { num_scrolls_++; @@ -670,101 +681,89 @@ TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor1_ScrollChild_DirectRenderer) { device_scale_factor_ = 1.f; scroll_child_layer_ = true; - RunTest(true, false, true); + RunTest(true, false); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor1_ScrollChild_DelegatingRenderer) { device_scale_factor_ = 1.f; scroll_child_layer_ = true; - RunTest(true, true, true); + RunTest(true, true); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor15_ScrollChild_DirectRenderer) { device_scale_factor_ = 1.5f; scroll_child_layer_ = true; - RunTest(true, false, true); + RunTest(true, false); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor15_ScrollChild_DelegatingRenderer) { device_scale_factor_ = 1.5f; scroll_child_layer_ = true; - RunTest(true, true, true); + RunTest(true, true); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor2_ScrollChild_DirectRenderer) { device_scale_factor_ = 2.f; scroll_child_layer_ = true; - RunTest(true, false, true); + RunTest(true, false); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor2_ScrollChild_DelegatingRenderer) { device_scale_factor_ = 2.f; scroll_child_layer_ = true; - RunTest(true, true, true); + RunTest(true, true); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor1_ScrollRootScrollLayer_DirectRenderer) { device_scale_factor_ = 1.f; scroll_child_layer_ = false; - RunTest(true, false, true); + RunTest(true, false); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor1_ScrollRootScrollLayer_DelegatingRenderer) { device_scale_factor_ = 1.f; scroll_child_layer_ = false; - RunTest(true, true, true); + RunTest(true, true); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor15_ScrollRootScrollLayer_DirectRenderer) { device_scale_factor_ = 1.5f; scroll_child_layer_ = false; - RunTest(true, false, true); + RunTest(true, false); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor15_ScrollRootScrollLayer_DelegatingRenderer) { device_scale_factor_ = 1.5f; scroll_child_layer_ = false; - RunTest(true, true, true); + RunTest(true, true); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor2_ScrollRootScrollLayer_DirectRenderer) { device_scale_factor_ = 2.f; scroll_child_layer_ = false; - RunTest(true, false, true); + RunTest(true, false); } TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor2_ScrollRootScrollLayer_DelegatingRenderer) { device_scale_factor_ = 2.f; scroll_child_layer_ = false; - RunTest(true, true, true); + RunTest(true, true); } -class ImplSidePaintingScrollTest : public LayerTreeHostScrollTest { +class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest { public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; - } - - void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - if (impl->pending_tree()) - impl->SetNeedsRedraw(); - } -}; - -class ImplSidePaintingScrollTestSimple : public ImplSidePaintingScrollTest { - public: - ImplSidePaintingScrollTestSimple() + LayerTreeHostScrollTestSimple() : initial_scroll_(10, 20), main_thread_scroll_(40, 5), impl_thread_scroll1_(2, -1), @@ -774,7 +773,7 @@ class ImplSidePaintingScrollTestSimple : public ImplSidePaintingScrollTest { void SetupTree() override { LayerTreeHostScrollTest::SetupTree(); Layer* root_layer = layer_tree_host()->root_layer(); - scoped_refptr<Layer> root_scroll_layer = Layer::Create(); + scoped_refptr<Layer> root_scroll_layer = Layer::Create(layer_settings()); root_scroll_layer->SetScrollClipLayerId(root_layer->id()); root_scroll_layer->SetScrollOffset(initial_scroll_); root_scroll_layer->SetBounds( @@ -817,7 +816,8 @@ class ImplSidePaintingScrollTestSimple : public ImplSidePaintingScrollTest { } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - ImplSidePaintingScrollTest::DrawLayersOnThread(impl); + if (impl->pending_tree()) + impl->SetNeedsRedraw(); LayerImpl* root = impl->active_tree()->root_layer(); LayerImpl* scroll_layer = root->children()[0]; @@ -868,7 +868,9 @@ class ImplSidePaintingScrollTestSimple : public ImplSidePaintingScrollTest { } } - void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, + void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta, + const gfx::Vector2dF& outer_delta, + const gfx::Vector2dF& elastic_overscroll_delta, float scale, float top_controls_delta) override { num_scrolls_++; @@ -884,22 +886,22 @@ class ImplSidePaintingScrollTestSimple : public ImplSidePaintingScrollTest { int num_scrolls_; }; -MULTI_THREAD_TEST_F(ImplSidePaintingScrollTestSimple); +// This tests scrolling on the impl side which is only possible with a thread. +MULTI_THREAD_TEST_F(LayerTreeHostScrollTestSimple); // This test makes sure that layers pick up scrolls that occur between // beginning a commit and finishing a commit (aka scroll deltas not // included in sent scroll delta) still apply to layers that don't // push properties. -class ImplSidePaintingScrollTestImplOnlyScroll - : public ImplSidePaintingScrollTest { +class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest { public: - ImplSidePaintingScrollTestImplOnlyScroll() + LayerTreeHostScrollTestImplOnlyScroll() : initial_scroll_(20, 10), impl_thread_scroll_(-2, 3), impl_scale_(2.f) {} void SetupTree() override { LayerTreeHostScrollTest::SetupTree(); Layer* root_layer = layer_tree_host()->root_layer(); - scoped_refptr<Layer> root_scroll_layer = Layer::Create(); + scoped_refptr<Layer> root_scroll_layer = Layer::Create(layer_settings()); root_scroll_layer->SetScrollClipLayerId(root_layer->id()); root_scroll_layer->SetScrollOffset(initial_scroll_); root_scroll_layer->SetBounds( @@ -986,7 +988,8 @@ class ImplSidePaintingScrollTestImplOnlyScroll } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - ImplSidePaintingScrollTest::DrawLayersOnThread(impl); + if (impl->pending_tree()) + impl->SetNeedsRedraw(); LayerImpl* root = impl->active_tree()->root_layer(); LayerImpl* scroll_layer = root->children()[0]; @@ -1024,7 +1027,8 @@ class ImplSidePaintingScrollTestImplOnlyScroll float impl_scale_; }; -MULTI_THREAD_TEST_F(ImplSidePaintingScrollTestImplOnlyScroll); +// This tests scrolling on the impl side which is only possible with a thread. +MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplOnlyScroll); class LayerTreeHostScrollTestScrollZeroMaxScrollOffset : public LayerTreeHostScrollTest { @@ -1033,7 +1037,7 @@ class LayerTreeHostScrollTestScrollZeroMaxScrollOffset void SetupTree() override { LayerTreeTest::SetupTree(); - scoped_refptr<Layer> scroll_layer = Layer::Create(); + scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings()); layer_tree_host()->root_layer()->AddChild(scroll_layer); } @@ -1126,13 +1130,14 @@ TEST(LayerTreeHostFlingTest, DidStopFlingingThread) { impl_thread.task_runner().get(), &received_stop_flinging); FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D); - ASSERT_TRUE(impl_thread.task_runner().get()); - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); + ASSERT_TRUE(impl_thread.task_runner()); + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; LayerTreeHost::InitParams params; params.client = &client; - params.shared_bitmap_manager = shared_bitmap_manager.get(); + params.shared_bitmap_manager = &shared_bitmap_manager; + params.task_graph_runner = &task_graph_runner; params.settings = &settings; params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); scoped_ptr<LayerTreeHost> layer_tree_host = @@ -1156,7 +1161,7 @@ class LayerTreeHostScrollTestLayerStructureChange : scroll_destroy_whole_tree_(false) {} void SetupTree() override { - scoped_refptr<Layer> root_layer = Layer::Create(); + scoped_refptr<Layer> root_layer = Layer::Create(layer_settings()); root_layer->SetBounds(gfx::Size(10, 10)); Layer* root_scroll_layer = @@ -1208,7 +1213,7 @@ class LayerTreeHostScrollTestLayerStructureChange Layer* CreateScrollLayer(Layer* parent, FakeLayerScrollClient* client) { scoped_refptr<PictureLayer> scroll_layer = - PictureLayer::Create(&fake_content_layer_client_); + PictureLayer::Create(layer_settings(), &fake_content_layer_client_); scroll_layer->SetBounds(gfx::Size(110, 110)); scroll_layer->SetPosition(gfx::Point(0, 0)); scroll_layer->SetIsDrawable(true); @@ -1233,12 +1238,12 @@ class LayerTreeHostScrollTestLayerStructureChange }; TEST_F(LayerTreeHostScrollTestLayerStructureChange, ScrollDestroyLayer) { - RunTest(true, false, true); + RunTest(true, false); } TEST_F(LayerTreeHostScrollTestLayerStructureChange, ScrollDestroyWholeTree) { scroll_destroy_whole_tree_ = true; - RunTest(true, false, true); + RunTest(true, false); } } // namespace diff --git a/chromium/cc/trees/layer_tree_host_unittest_video.cc b/chromium/cc/trees/layer_tree_host_unittest_video.cc index ffeda727fe3..31854ac68a9 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_video.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_video.cc @@ -23,12 +23,12 @@ class LayerTreeHostVideoTestSetNeedsDisplay : public LayerTreeHostVideoTest { public: void SetupTree() override { - scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(10, 10)); root->SetIsDrawable(true); - scoped_refptr<VideoLayer> video = - VideoLayer::Create(&video_frame_provider_, media::VIDEO_ROTATION_90); + scoped_refptr<VideoLayer> video = VideoLayer::Create( + layer_settings(), &video_frame_provider_, media::VIDEO_ROTATION_90); video->SetPosition(gfx::PointF(3.f, 3.f)); video->SetBounds(gfx::Size(4, 5)); video->SetIsDrawable(true); diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index 01a4cfd19ec..d4d2dee7f23 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -10,13 +10,13 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/animation/animation_host.h" #include "cc/animation/keyframed_animation_curve.h" #include "cc/animation/scrollbar_animation_controller.h" #include "cc/animation/scrollbar_animation_controller_linear_fade.h" #include "cc/animation/scrollbar_animation_controller_thinning.h" #include "cc/base/math_util.h" #include "cc/base/synced_property.h" -#include "cc/base/util.h" #include "cc/debug/devtools_instrumentation.h" #include "cc/debug/traced_value.h" #include "cc/input/layer_scroll_offset_delegate.h" @@ -30,6 +30,9 @@ #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/occlusion_tracker.h" +#include "cc/trees/property_tree.h" +#include "cc/trees/property_tree_builder.h" +#include "ui/gfx/geometry/box_f.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/geometry/vector2d_conversions.h" @@ -57,7 +60,6 @@ LayerTreeImpl::LayerTreeImpl( max_page_scale_factor_(0), elastic_overscroll_(elastic_overscroll), scrolling_layer_id_from_previous_tree_(0), - contents_textures_purged_(false), viewport_size_invalid_(false), needs_update_draw_properties_(true), needs_full_tree_sync_(true), @@ -112,9 +114,9 @@ void LayerTreeImpl::GatherFrameTimingRequestIds( }); } -bool LayerTreeImpl::IsExternalFlingActive() const { +bool LayerTreeImpl::IsExternalScrollActive() const { return root_layer_scroll_offset_delegate_ && - root_layer_scroll_offset_delegate_->IsExternalFlingActive(); + root_layer_scroll_offset_delegate_->IsExternalScrollActive(); } void LayerTreeImpl::DidUpdateScrollOffset(int layer_id) { @@ -189,6 +191,40 @@ scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() { return root_layer_.Pass(); } +static void UpdateClipTreeForBoundsDeltaOnLayer(LayerImpl* layer, + ClipTree* clip_tree) { + if (layer && layer->masks_to_bounds()) { + ClipNode* clip_node = clip_tree->Node(layer->clip_tree_index()); + if (clip_node) { + DCHECK_EQ(layer->id(), clip_node->owner_id); + gfx::Size bounds = layer->bounds(); + if (clip_node->data.clip.size() != bounds) { + clip_node->data.clip.set_size(bounds); + clip_tree->set_needs_update(true); + } + } + } +} + +void LayerTreeImpl::UpdatePropertyTreesForBoundsDelta() { + DCHECK(IsActiveTree()); + LayerImpl* inner_container = InnerViewportContainerLayer(); + LayerImpl* outer_container = OuterViewportContainerLayer(); + + UpdateClipTreeForBoundsDeltaOnLayer(inner_container, + &property_trees_.clip_tree); + UpdateClipTreeForBoundsDeltaOnLayer(InnerViewportScrollLayer(), + &property_trees_.clip_tree); + UpdateClipTreeForBoundsDeltaOnLayer(outer_container, + &property_trees_.clip_tree); + + TransformTree& transform_tree = property_trees_.transform_tree; + if (inner_container) + transform_tree.SetInnerViewportBoundsDelta(inner_container->bounds_delta()); + if (outer_container) + transform_tree.SetOuterViewportBoundsDelta(outer_container->bounds_delta()); +} + void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { // The request queue should have been processed and does not require a push. DCHECK_EQ(ui_resource_request_queue_.size(), 0u); @@ -235,11 +271,6 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { target_tree->set_background_color(background_color()); target_tree->set_has_transparent_background(has_transparent_background()); - if (ContentsTexturesPurged()) - target_tree->SetContentsTexturesPurged(); - else - target_tree->ResetContentsTexturesPurged(); - if (ViewportSizeInvalid()) target_tree->SetViewportSizeInvalid(); else @@ -313,6 +344,21 @@ float LayerTreeImpl::ClampPageScaleFactorToLimits( return page_scale_factor; } +void LayerTreeImpl::UpdatePropertyTreeScrollingAndAnimationFromMainThread() { + // TODO(enne): This should get replaced by pulling out scrolling and + // animations into their own trees. Then scrolls and animations would have + // their own ways of synchronizing across commits. This occurs to push + // updates from scrolling deltas on the compositor thread that have occurred + // after begin frame and updates from animations that have ticked since begin + // frame to a newly-committed property tree. + if (!root_layer()) + return; + LayerTreeHostCommon::CallFunctionForSubtree( + root_layer(), [](LayerImpl* layer) { + layer->UpdatePropertyTreeForScrollingAndAnimationIfNeeded(); + }); +} + void LayerTreeImpl::SetPageScaleOnActiveTree(float active_page_scale) { DCHECK(IsActiveTree()); if (page_scale_factor()->SetCurrent( @@ -334,11 +380,21 @@ void LayerTreeImpl::PushPageScaleFactorAndLimits(const float* page_scale_factor, bool changed_page_scale = false; if (page_scale_factor) { DCHECK(!IsActiveTree() || !layer_tree_host_impl_->pending_tree()); + changed_page_scale |= page_scale_factor_->Delta() != 1.f; + // TODO(enne): Once CDP goes away, ignore this call below. The only time + // the property trees will differ is if there's been a page scale on the + // compositor thread after the begin frame, which is the delta check above. changed_page_scale |= page_scale_factor_->PushFromMainThread(*page_scale_factor); } - if (IsActiveTree()) + if (IsActiveTree()) { + // TODO(enne): Pushing from pending to active should never require + // DidUpdatePageScale. The values should already be set by the fully + // computed property trees being synced from one tree to another. Remove + // this once CDP goes away. changed_page_scale |= page_scale_factor_->PushPendingToActive(); + } + changed_page_scale |= SetPageScaleFactorLimits(min_page_scale_factor, max_page_scale_factor); @@ -414,6 +470,21 @@ void LayerTreeImpl::DidUpdatePageScale() { max_page_scale_factor_); } + if (page_scale_layer() && page_scale_layer()->transform_tree_index() != -1) { + TransformNode* node = property_trees_.transform_tree.Node( + page_scale_layer()->transform_tree_index()); + node->data.post_local_scale_factor = current_page_scale_factor(); + node->data.needs_local_transform_update = true; + // TODO(enne): property trees can't ask the layer these things, but + // the page scale layer should *just* be the page scale. + DCHECK_EQ(page_scale_layer()->position().ToString(), + gfx::PointF().ToString()); + DCHECK_EQ(page_scale_layer()->transform_origin().ToString(), + gfx::Point3F().ToString()); + node->data.update_post_local_transform(gfx::PointF(), gfx::Point3F()); + property_trees_.transform_tree.set_needs_update(true); + } + ForceScrollbarParameterUpdateAfterScaleChange(page_scale_layer()); HideInnerViewportScrollbarsIfNearMinimumScale(); @@ -464,7 +535,7 @@ gfx::Rect LayerTreeImpl::RootScrollLayerDeviceViewportBounds() const { return gfx::Rect(); LayerImpl* layer = root_scroll_layer->children()[0]; return MathUtil::MapEnclosingClippedRect(layer->screen_space_transform(), - gfx::Rect(layer->content_bounds())); + gfx::Rect(layer->bounds())); } void LayerTreeImpl::ApplySentScrollAndScaleDeltasFromAbortedCommit() { @@ -547,6 +618,7 @@ bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) { root_layer(), DrawViewportSize(), layer_tree_host_impl_->DrawTransform(), device_scale_factor(), current_page_scale_factor(), page_scale_layer, + inner_viewport_scroll_layer_, outer_viewport_scroll_layer_, elastic_overscroll()->Current(IsActiveTree()), overscroll_elasticity_layer_, resource_provider()->max_texture_size(), settings().can_use_lcd_text, settings().layers_always_allowed_lcd_text, @@ -561,7 +633,7 @@ bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) { TRACE_EVENT2("cc", "LayerTreeImpl::UpdateDrawProperties::Occlusion", "IsActive", IsActiveTree(), "SourceFrameNumber", source_frame_number_); - OcclusionTracker<LayerImpl> occlusion_tracker( + OcclusionTracker occlusion_tracker( root_layer()->render_surface()->content_rect()); occlusion_tracker.set_minimum_tracking_size( settings().minimum_occlusion_tracking_size); @@ -569,8 +641,8 @@ bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) { // LayerIterator is used here instead of CallFunctionForSubtree to only // UpdateTilePriorities on layers that will be visible (and thus have valid // draw properties) and not because any ordering is required. - auto end = LayerIterator<LayerImpl>::End(&render_surface_layer_list_); - for (auto it = LayerIterator<LayerImpl>::Begin(&render_surface_layer_list_); + LayerIterator end = LayerIterator::End(&render_surface_layer_list_); + for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list_); it != end; ++it) { occlusion_tracker.EnterLayer(it); @@ -678,6 +750,14 @@ bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) { return true; } +void LayerTreeImpl::BuildPropertyTreesForTesting() { + PropertyTreeBuilder::BuildPropertyTrees( + root_layer_.get(), page_scale_layer_, inner_viewport_scroll_layer_, + outer_viewport_scroll_layer_, current_page_scale_factor(), + device_scale_factor(), gfx::Rect(DrawViewportSize()), + layer_tree_host_impl_->DrawTransform(), &property_trees_); +} + const LayerImplList& LayerTreeImpl::RenderSurfaceLayerList() const { // If this assert triggers, then the list is dirty. DCHECK(!needs_update_draw_properties_); @@ -700,18 +780,26 @@ gfx::Size LayerTreeImpl::ScrollableSize() const { return root_scroll_layer->children()[0]->bounds(); } -LayerImpl* LayerTreeImpl::LayerById(int id) { - LayerIdMap::iterator iter = layer_id_map_.find(id); +LayerImpl* LayerTreeImpl::LayerById(int id) const { + LayerIdMap::const_iterator iter = layer_id_map_.find(id); return iter != layer_id_map_.end() ? iter->second : NULL; } void LayerTreeImpl::RegisterLayer(LayerImpl* layer) { DCHECK(!LayerById(layer->id())); layer_id_map_[layer->id()] = layer; + if (layer_tree_host_impl_->animation_host()) + layer_tree_host_impl_->animation_host()->RegisterLayer( + layer->id(), + IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING); } void LayerTreeImpl::UnregisterLayer(LayerImpl* layer) { DCHECK(LayerById(layer->id())); + if (layer_tree_host_impl_->animation_host()) + layer_tree_host_impl_->animation_host()->UnregisterLayer( + layer->id(), + IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING); layer_id_map_.erase(layer->id()); } @@ -751,24 +839,6 @@ void LayerTreeImpl::DidBecomeActive() { source_frame_number_); } -bool LayerTreeImpl::ContentsTexturesPurged() const { - return contents_textures_purged_; -} - -void LayerTreeImpl::SetContentsTexturesPurged() { - if (contents_textures_purged_) - return; - contents_textures_purged_ = true; - layer_tree_host_impl_->OnCanDrawStateChangedForTree(); -} - -void LayerTreeImpl::ResetContentsTexturesPurged() { - if (!contents_textures_purged_) - return; - contents_textures_purged_ = false; - layer_tree_host_impl_->OnCanDrawStateChangedForTree(); -} - bool LayerTreeImpl::RequiresHighResToDraw() const { return layer_tree_host_impl_->RequiresHighResToDraw(); } @@ -881,8 +951,8 @@ BeginFrameArgs LayerTreeImpl::CurrentBeginFrameArgs() const { return layer_tree_host_impl_->CurrentBeginFrameArgs(); } -base::TimeDelta LayerTreeImpl::begin_impl_frame_interval() const { - return layer_tree_host_impl_->begin_impl_frame_interval(); +base::TimeDelta LayerTreeImpl::CurrentBeginFrameInterval() const { + return layer_tree_host_impl_->CurrentBeginFrameInterval(); } void LayerTreeImpl::SetNeedsCommit() { @@ -960,12 +1030,9 @@ AnimationRegistrar* LayerTreeImpl::GetAnimationRegistrar() const { void LayerTreeImpl::GetAllPrioritizedTilesForTracing( std::vector<PrioritizedTile>* prioritized_tiles) const { - typedef LayerIterator<LayerImpl> LayerIteratorType; - LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_); - for (LayerIteratorType it = - LayerIteratorType::Begin(&render_surface_layer_list_); - it != end; - ++it) { + LayerIterator end = LayerIterator::End(&render_surface_layer_list_); + for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list_); + it != end; ++it) { if (!it.represents_itself()) continue; LayerImpl* layer_impl = *it; @@ -982,10 +1049,9 @@ void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->EndDictionary(); state->BeginArray("render_surface_layer_list"); - typedef LayerIterator<LayerImpl> LayerIteratorType; - LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_); - for (LayerIteratorType it = LayerIteratorType::Begin( - &render_surface_layer_list_); it != end; ++it) { + LayerIterator end = LayerIterator::End(&render_surface_layer_list_); + for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list_); + it != end; ++it) { if (!it.represents_itself()) continue; TracedValue::AppendIDRef(*it, state); @@ -1075,9 +1141,9 @@ void LayerTreeImpl::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) { void LayerTreeImpl::PassSwapPromises( ScopedPtrVector<SwapPromise>* new_swap_promise) { - // Any left over promises have failed to swap before the next frame. - BreakSwapPromises(SwapPromise::SWAP_FAILS); - swap_promise_list_.swap(*new_swap_promise); + swap_promise_list_.insert_and_take(swap_promise_list_.end(), + new_swap_promise); + new_swap_promise->clear(); } void LayerTreeImpl::FinishSwapPromises(CompositorFrameMetadata* metadata) { @@ -1101,8 +1167,7 @@ void LayerTreeImpl::set_ui_resource_request_queue( ui_resource_request_queue_ = queue; } -ResourceProvider::ResourceId LayerTreeImpl::ResourceIdForUIResource( - UIResourceId uid) const { +ResourceId LayerTreeImpl::ResourceIdForUIResource(UIResourceId uid) const { return layer_tree_host_impl_->ResourceIdForUIResource(uid); } @@ -1238,9 +1303,7 @@ static bool PointHitsRect( static bool PointHitsRegion(const gfx::PointF& screen_space_point, const gfx::Transform& screen_space_transform, - const Region& layer_space_region, - float layer_content_scale_x, - float layer_content_scale_y) { + const Region& layer_space_region) { // If the transform is not invertible, then assume that this point doesn't hit // this region. gfx::Transform inverse_screen_space_transform( @@ -1251,12 +1314,8 @@ static bool PointHitsRegion(const gfx::PointF& screen_space_point, // Transform the hit test point from screen space to the local space of the // given region. bool clipped = false; - gfx::PointF hit_test_point_in_content_space = MathUtil::ProjectPoint( + gfx::PointF hit_test_point_in_layer_space = MathUtil::ProjectPoint( inverse_screen_space_transform, screen_space_point, &clipped); - gfx::PointF hit_test_point_in_layer_space = - gfx::ScalePoint(hit_test_point_in_content_space, - 1.f / layer_content_scale_x, - 1.f / layer_content_scale_y); // If ProjectPoint could not project to a valid value, then we assume that // this point doesn't hit this region. @@ -1289,10 +1348,8 @@ static bool PointIsClippedBySurfaceOrClipRect( return true; if (LayerClipsSubtree(layer) && - !PointHitsRect(screen_space_point, - layer->screen_space_transform(), - gfx::Rect(layer->content_bounds()), - NULL)) + !PointHitsRect(screen_space_point, layer->screen_space_transform(), + gfx::Rect(layer->bounds()), NULL)) return true; } @@ -1304,7 +1361,7 @@ static bool PointIsClippedBySurfaceOrClipRect( static bool PointHitsLayer(const LayerImpl* layer, const gfx::PointF& screen_space_point, float* distance_to_intersection) { - gfx::RectF content_rect(layer->content_bounds()); + gfx::RectF content_rect(layer->bounds()); if (!PointHitsRect(screen_space_point, layer->screen_space_transform(), content_rect, @@ -1340,9 +1397,11 @@ static void FindClosestMatchingLayer( LayerImpl* layer, const Functor& func, FindClosestMatchingLayerDataForRecursion* data_for_recursion) { - for (int i = layer->children().size() - 1; i >= 0; --i) { - FindClosestMatchingLayer( - screen_space_point, layer->children()[i], func, data_for_recursion); + size_t children_size = layer->children().size(); + for (size_t i = 0; i < children_size; ++i) { + size_t index = children_size - 1 - i; + FindClosestMatchingLayer(screen_space_point, layer->children()[index], func, + data_for_recursion); } float distance_to_intersection = 0.f; @@ -1358,7 +1417,7 @@ static void FindClosestMatchingLayer( static bool ScrollsAnyDrawnRenderSurfaceLayerListMember(LayerImpl* layer) { if (!layer->scrollable()) return false; - if (layer->draw_properties().layer_or_descendant_is_drawn) + if (layer->layer_or_descendant_is_drawn()) return true; if (!layer->scroll_children()) @@ -1367,7 +1426,7 @@ static bool ScrollsAnyDrawnRenderSurfaceLayerListMember(LayerImpl* layer) { layer->scroll_children()->begin(); it != layer->scroll_children()->end(); ++it) { - if ((*it)->draw_properties().layer_or_descendant_is_drawn) + if ((*it)->layer_or_descendant_is_drawn()) return true; } return false; @@ -1418,11 +1477,8 @@ static bool LayerHasTouchEventHandlersAt(const gfx::PointF& screen_space_point, if (layer_impl->touch_event_handler_region().IsEmpty()) return false; - if (!PointHitsRegion(screen_space_point, - layer_impl->screen_space_transform(), - layer_impl->touch_event_handler_region(), - layer_impl->contents_scale_x(), - layer_impl->contents_scale_y())) + if (!PointHitsRegion(screen_space_point, layer_impl->screen_space_transform(), + layer_impl->touch_event_handler_region())) return false; // At this point, we think the point does hit the touch event handler region @@ -1490,18 +1546,14 @@ static ViewportSelectionBound ComputeViewportSelectionBound( if (!layer || layer_bound.type == SELECTION_BOUND_EMPTY) return viewport_bound; - gfx::PointF layer_scaled_top = gfx::ScalePoint(layer_bound.edge_top, - layer->contents_scale_x(), - layer->contents_scale_y()); - gfx::PointF layer_scaled_bottom = gfx::ScalePoint(layer_bound.edge_bottom, - layer->contents_scale_x(), - layer->contents_scale_y()); + gfx::PointF layer_top = layer_bound.edge_top; + gfx::PointF layer_bottom = layer_bound.edge_bottom; bool clipped = false; - gfx::PointF screen_top = MathUtil::MapPoint( - layer->screen_space_transform(), layer_scaled_top, &clipped); + gfx::PointF screen_top = + MathUtil::MapPoint(layer->screen_space_transform(), layer_top, &clipped); gfx::PointF screen_bottom = MathUtil::MapPoint( - layer->screen_space_transform(), layer_scaled_bottom, &clipped); + layer->screen_space_transform(), layer_bottom, &clipped); const float inv_scale = 1.f / device_scale_factor; viewport_bound.edge_top = gfx::ScalePoint(screen_top, inv_scale); @@ -1512,9 +1564,9 @@ static ViewportSelectionBound ComputeViewportSelectionBound( // Shifting the visibility point fractionally inward ensures that neighboring // or logically coincident layers aligned to integral DPI coordinates will not // spuriously occlude the bound. - gfx::Vector2dF visibility_offset = layer_scaled_top - layer_scaled_bottom; + gfx::Vector2dF visibility_offset = layer_top - layer_bottom; visibility_offset.Scale(device_scale_factor / visibility_offset.Length()); - gfx::PointF visibility_point = layer_scaled_bottom + visibility_offset; + gfx::PointF visibility_point = layer_bottom + visibility_offset; if (visibility_point.x() <= 0) visibility_point.set_x(visibility_point.x() + device_scale_factor); visibility_point = MathUtil::MapPoint( @@ -1574,4 +1626,131 @@ scoped_ptr<PendingPageScaleAnimation> return pending_page_scale_animation_.Pass(); } +bool LayerTreeImpl::IsAnimatingFilterProperty(const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->IsAnimatingFilterProperty(layer->id()) + : false; +} + +bool LayerTreeImpl::IsAnimatingOpacityProperty(const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->IsAnimatingOpacityProperty(layer->id()) + : false; +} + +bool LayerTreeImpl::IsAnimatingTransformProperty(const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->IsAnimatingTransformProperty(layer->id()) + : false; +} + +bool LayerTreeImpl::HasPotentiallyRunningOpacityAnimation( + const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->HasPotentiallyRunningOpacityAnimation(layer->id()) + : false; +} + +bool LayerTreeImpl::HasPotentiallyRunningTransformAnimation( + const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->HasPotentiallyRunningTransformAnimation(layer->id()) + : false; +} + +bool LayerTreeImpl::FilterIsAnimatingOnImplOnly(const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->FilterIsAnimatingOnImplOnly(layer->id()) + : false; +} + +bool LayerTreeImpl::OpacityIsAnimatingOnImplOnly(const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->OpacityIsAnimatingOnImplOnly(layer->id()) + : false; +} + +bool LayerTreeImpl::TransformIsAnimatingOnImplOnly( + const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->TransformIsAnimatingOnImplOnly(layer->id()) + : false; +} + +bool LayerTreeImpl::HasOnlyTranslationTransforms(const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->HasOnlyTranslationTransforms(layer->id()) + : true; +} + +bool LayerTreeImpl::MaximumTargetScale(const LayerImpl* layer, + float* max_scale) const { + *max_scale = 0.f; + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host()->MaximumTargetScale( + layer->id(), max_scale) + : true; +} + +bool LayerTreeImpl::AnimationStartScale(const LayerImpl* layer, + float* start_scale) const { + *start_scale = 0.f; + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host()->AnimationStartScale( + layer->id(), start_scale) + : true; +} + +bool LayerTreeImpl::HasFilterAnimationThatInflatesBounds( + const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->HasFilterAnimationThatInflatesBounds(layer->id()) + : false; +} + +bool LayerTreeImpl::HasTransformAnimationThatInflatesBounds( + const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->HasTransformAnimationThatInflatesBounds(layer->id()) + : false; +} + +bool LayerTreeImpl::HasAnimationThatInflatesBounds( + const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->HasAnimationThatInflatesBounds(layer->id()) + : false; +} + +bool LayerTreeImpl::FilterAnimationBoundsForBox(const LayerImpl* layer, + const gfx::BoxF& box, + gfx::BoxF* bounds) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->FilterAnimationBoundsForBox(layer->id(), box, bounds) + : false; +} + +bool LayerTreeImpl::TransformAnimationBoundsForBox(const LayerImpl* layer, + const gfx::BoxF& box, + gfx::BoxF* bounds) const { + *bounds = gfx::BoxF(); + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->TransformAnimationBoundsForBox(layer->id(), box, bounds) + : true; +} + } // namespace cc diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index 9c1b5b942db..973df977733 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -96,7 +96,7 @@ class CC_EXPORT LayerTreeImpl { LayerImpl* FindPendingTreeLayerById(int id); bool PinchGestureActive() const; BeginFrameArgs CurrentBeginFrameArgs() const; - base::TimeDelta begin_impl_frame_interval() const; + base::TimeDelta CurrentBeginFrameInterval() const; void SetNeedsCommit(); gfx::Rect DeviceViewport() const; gfx::Size DrawViewportSize() const; @@ -131,7 +131,11 @@ class CC_EXPORT LayerTreeImpl { void SetPropertyTrees(const PropertyTrees& property_trees) { property_trees_ = property_trees; + property_trees_.transform_tree.set_source_to_parent_updates_allowed(false); } + PropertyTrees* property_trees() { return &property_trees_; } + + void UpdatePropertyTreesForBoundsDelta(); void PushPropertiesTo(LayerTreeImpl* tree_impl); @@ -178,6 +182,7 @@ class CC_EXPORT LayerTreeImpl { has_transparent_background_ = transparent; } + void UpdatePropertyTreeScrollingAndAnimationFromMainThread(); void SetPageScaleOnActiveTree(float active_page_scale); void PushPageScaleFromMainThread(float page_scale_factor, float min_page_scale_factor, @@ -211,6 +216,7 @@ class CC_EXPORT LayerTreeImpl { // priorities. Returns false if it was unable to update. Updating lcd // text may cause invalidations, so should only be done after a commit. bool UpdateDrawProperties(bool update_lcd_text); + void BuildPropertyTreesForTesting(); void set_needs_update_draw_properties() { needs_update_draw_properties_ = true; @@ -241,7 +247,7 @@ class CC_EXPORT LayerTreeImpl { gfx::Rect RootScrollLayerDeviceViewportBounds() const; - LayerImpl* LayerById(int id); + LayerImpl* LayerById(int id) const; // These should be called by LayerImpl's ctor/dtor. void RegisterLayer(LayerImpl* layer); @@ -255,10 +261,6 @@ class CC_EXPORT LayerTreeImpl { void DidBecomeActive(); - bool ContentsTexturesPurged() const; - void SetContentsTexturesPurged(); - void ResetContentsTexturesPurged(); - // Set on the active tree when the viewport size recently changed // and the active tree's size is now out of date. bool ViewportSizeInvalid() const; @@ -286,7 +288,7 @@ class CC_EXPORT LayerTreeImpl { void DidModifyTilePriorities(); - ResourceProvider::ResourceId ResourceIdForUIResource(UIResourceId uid) const; + ResourceId ResourceIdForUIResource(UIResourceId uid) const; void ProcessUIResourceRequestQueue(); bool IsUIResourceOpaque(UIResourceId uid) const; @@ -340,9 +342,36 @@ class CC_EXPORT LayerTreeImpl { void GatherFrameTimingRequestIds(std::vector<int64_t>* request_ids); - bool IsExternalFlingActive() const; + bool IsExternalScrollActive() const; void DidUpdateScrollOffset(int layer_id); + bool IsAnimatingFilterProperty(const LayerImpl* layer) const; + bool IsAnimatingOpacityProperty(const LayerImpl* layer) const; + bool IsAnimatingTransformProperty(const LayerImpl* layer) const; + + bool HasPotentiallyRunningOpacityAnimation(const LayerImpl* layer) const; + bool HasPotentiallyRunningTransformAnimation(const LayerImpl* layer) const; + + bool FilterIsAnimatingOnImplOnly(const LayerImpl* layer) const; + bool OpacityIsAnimatingOnImplOnly(const LayerImpl* layer) const; + bool TransformIsAnimatingOnImplOnly(const LayerImpl* layer) const; + + bool HasOnlyTranslationTransforms(const LayerImpl* layer) const; + + bool MaximumTargetScale(const LayerImpl* layer, float* max_scale) const; + bool AnimationStartScale(const LayerImpl* layer, float* start_scale) const; + + bool HasFilterAnimationThatInflatesBounds(const LayerImpl* layer) const; + bool HasTransformAnimationThatInflatesBounds(const LayerImpl* layer) const; + bool HasAnimationThatInflatesBounds(const LayerImpl* layer) const; + + bool FilterAnimationBoundsForBox(const LayerImpl* layer, + const gfx::BoxF& box, + gfx::BoxF* bounds) const; + bool TransformAnimationBoundsForBox(const LayerImpl* layer, + const gfx::BoxF& box, + gfx::BoxF* bounds) const; + protected: explicit LayerTreeImpl( LayerTreeHostImpl* layer_tree_host_impl, @@ -396,7 +425,6 @@ class CC_EXPORT LayerTreeImpl { // would not be fully covered by opaque content. Region unoccluded_screen_space_region_; - bool contents_textures_purged_; bool viewport_size_invalid_; bool needs_update_draw_properties_; diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc index 04c108f1bdf..81a566fe7f3 100644 --- a/chromium/cc/trees/layer_tree_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_impl_unittest.cc @@ -380,87 +380,6 @@ TEST_F(LayerTreeImplTest, HitTestingForSinglePerspectiveLayer) { EXPECT_EQ(12345, result_layer->id()); } -TEST_F(LayerTreeImplTest, HitTestingForSingleLayerWithScaledContents) { - // A layer's visible content rect is actually in the layer's content space. - // The screen space transform converts from the layer's origin space to screen - // space. This test makes sure that hit testing works correctly accounts for - // the contents scale. A contents scale that is not 1 effectively forces a - // non-identity transform between layer's content space and layer's origin - // space. The hit testing code must take this into account. - // - // To test this, the layer is positioned at (25, 25), and is size (50, 50). If - // contents scale is ignored, then hit testing will mis-interpret the visible - // content rect as being larger than the actual bounds of the layer. - // - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1); - - gfx::Transform identity_matrix; - gfx::Point3F transform_origin; - - SetLayerPropertiesForTesting(root.get(), identity_matrix, transform_origin, - gfx::PointF(), gfx::Size(100, 100), true, false, - true); - { - gfx::PointF position(25.f, 25.f); - gfx::Size bounds(50, 50); - scoped_ptr<LayerImpl> test_layer = - LayerImpl::Create(host_impl().active_tree(), 12345); - SetLayerPropertiesForTesting(test_layer.get(), identity_matrix, - transform_origin, position, bounds, true, - false, false); - - // override content bounds and contents scale - test_layer->SetContentBounds(gfx::Size(100, 100)); - test_layer->SetContentsScale(2, 2); - - test_layer->SetDrawsContent(true); - root->AddChild(test_layer.Pass()); - } - - host_impl().SetViewportSize(root->bounds()); - host_impl().active_tree()->SetRootLayer(root.Pass()); - host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); - - // Sanity check the scenario we just created. - // The visible content rect for test_layer is actually 100x100, even though - // its layout size is 50x50, positioned at 25x25. - LayerImpl* test_layer = - host_impl().active_tree()->root_layer()->children()[0]; - EXPECT_EQ(gfx::Rect(0, 0, 100, 100), test_layer->visible_content_rect()); - ASSERT_EQ(1u, RenderSurfaceLayerList().size()); - ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size()); - - // Hit testing for a point outside the layer should return a null pointer (the - // root layer does not draw content, so it will not be hit tested either). - gfx::Point test_point(101, 101); - LayerImpl* result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point); - EXPECT_FALSE(result_layer); - - test_point = gfx::Point(24, 24); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point); - EXPECT_FALSE(result_layer); - - test_point = gfx::Point(76, 76); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point); - EXPECT_FALSE(result_layer); - - // Hit testing for a point inside should return the test layer. - test_point = gfx::Point(26, 26); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point); - ASSERT_TRUE(result_layer); - EXPECT_EQ(12345, result_layer->id()); - - test_point = gfx::Point(74, 74); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point); - ASSERT_TRUE(result_layer); - EXPECT_EQ(12345, result_layer->id()); -} - TEST_F(LayerTreeImplTest, HitTestingForSimpleClippedLayer) { // Test that hit-testing will only work for the visible portion of a layer, // and not the entire layer bounds. Here we just test the simple axis-aligned @@ -1500,110 +1419,6 @@ TEST_F(LayerTreeImplTest, } TEST_F(LayerTreeImplTest, - HitCheckingTouchHandlerRegionsForSingleLayerWithScaledContents) { - // A layer's visible content rect is actually in the layer's content space. - // The screen space transform converts from the layer's origin space to screen - // space. This test makes sure that hit testing works correctly accounts for - // the contents scale. A contents scale that is not 1 effectively forces a - // non-identity transform between layer's content space and layer's origin - // space. The hit testing code must take this into account. - // - // To test this, the layer is positioned at (25, 25), and is size (50, 50). If - // contents scale is ignored, then hit checking will mis-interpret the visible - // content rect as being larger than the actual bounds of the layer. - // - scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1); - - gfx::Transform identity_matrix; - gfx::Point3F transform_origin; - - SetLayerPropertiesForTesting(root.get(), identity_matrix, transform_origin, - gfx::PointF(), gfx::Size(100, 100), true, false, - true); - { - Region touch_handler_region(gfx::Rect(10, 10, 30, 30)); - gfx::PointF position(25.f, 25.f); - gfx::Size bounds(50, 50); - scoped_ptr<LayerImpl> test_layer = - LayerImpl::Create(host_impl().active_tree(), 12345); - SetLayerPropertiesForTesting(test_layer.get(), identity_matrix, - transform_origin, position, bounds, true, - false, false); - - // override content bounds and contents scale - test_layer->SetContentBounds(gfx::Size(100, 100)); - test_layer->SetContentsScale(2, 2); - - test_layer->SetDrawsContent(true); - test_layer->SetTouchEventHandlerRegion(touch_handler_region); - root->AddChild(test_layer.Pass()); - } - - host_impl().SetViewportSize(root->bounds()); - host_impl().active_tree()->SetRootLayer(root.Pass()); - host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); - - // Sanity check the scenario we just created. - // The visible content rect for test_layer is actually 100x100, even though - // its layout size is 50x50, positioned at 25x25. - LayerImpl* test_layer = - host_impl().active_tree()->root_layer()->children()[0]; - EXPECT_EQ(gfx::Rect(0, 0, 100, 100), test_layer->visible_content_rect()); - ASSERT_EQ(1u, RenderSurfaceLayerList().size()); - ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size()); - - // Hit checking for a point outside the layer should return a null pointer - // (the root layer does not draw content, so it will not be tested either). - gfx::Point test_point(76, 76); - LayerImpl* result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion( - test_point); - EXPECT_FALSE(result_layer); - - // Hit checking for a point inside the layer, but outside the touch handler - // region should return a null pointer. - test_point = gfx::Point(26, 26); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion( - test_point); - EXPECT_FALSE(result_layer); - - test_point = gfx::Point(34, 34); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion( - test_point); - EXPECT_FALSE(result_layer); - - test_point = gfx::Point(65, 65); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion( - test_point); - EXPECT_FALSE(result_layer); - - test_point = gfx::Point(74, 74); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion( - test_point); - EXPECT_FALSE(result_layer); - - // Hit checking for a point inside the touch event handler region should - // return the root layer. - test_point = gfx::Point(35, 35); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion( - test_point); - ASSERT_TRUE(result_layer); - EXPECT_EQ(12345, result_layer->id()); - - test_point = gfx::Point(64, 64); - result_layer = - host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion( - test_point); - ASSERT_TRUE(result_layer); - EXPECT_EQ(12345, result_layer->id()); -} - -TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSingleLayerWithDeviceScale) { // The layer's device_scale_factor and page_scale_factor should scale the // content rect and we should be able to hit the touch handler region by @@ -1655,8 +1470,7 @@ TEST_F(LayerTreeImplTest, ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size()); // Check whether the child layer fits into the root after scaled. - EXPECT_EQ(gfx::Rect(test_layer->content_bounds()), - test_layer->visible_content_rect()); + EXPECT_EQ(gfx::Rect(test_layer->bounds()), test_layer->visible_layer_rect()); // Hit checking for a point outside the layer should return a null pointer // (the root layer does not draw content, so it will not be tested either). @@ -2127,11 +1941,11 @@ TEST_F(LayerTreeImplTest, SelectionBoundsForScaledLayers) { host_impl().active_tree()->GetViewportSelection(&output); EXPECT_EQ(input.start.type, output.start.type); gfx::PointF expected_output_start_top = input.start.edge_top; - gfx::PointF expected_output_edge_botom = input.start.edge_bottom; + gfx::PointF expected_output_edge_bottom = input.start.edge_bottom; expected_output_start_top.Scale(page_scale_factor); - expected_output_edge_botom.Scale(page_scale_factor); - EXPECT_EQ(input.start.edge_top, output.start.edge_top); - EXPECT_EQ(input.start.edge_bottom, output.start.edge_bottom); + expected_output_edge_bottom.Scale(page_scale_factor); + EXPECT_EQ(expected_output_start_top, output.start.edge_top); + EXPECT_EQ(expected_output_edge_bottom, output.start.edge_bottom); EXPECT_TRUE(output.start.visible); EXPECT_EQ(input.end.type, output.end.type); diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc index f7f6f3047da..92d7dda7040 100644 --- a/chromium/cc/trees/layer_tree_settings.cc +++ b/chromium/cc/trees/layer_tree_settings.cc @@ -13,16 +13,18 @@ namespace cc { +LayerSettings::LayerSettings() : use_compositor_animation_timelines(false) { +} + +LayerSettings::~LayerSettings() { +} + LayerTreeSettings::LayerTreeSettings() - : impl_side_painting(false), - raster_enabled(true), - throttle_frame_production(true), - single_thread_proxy_scheduler(true), + : single_thread_proxy_scheduler(true), use_external_begin_frame_source(false), main_frame_before_activation_enabled(false), using_synchronous_renderer_compositor(false), report_overscroll_only_for_scrollable_axes(false), - per_tile_painting_enabled(false), accelerated_animation_enabled(true), can_use_lcd_text(true), use_distance_field_text(false), @@ -38,7 +40,6 @@ LayerTreeSettings::LayerTreeSettings() scrollbar_show_scale_threshold(1.0f), solid_color_scrollbar_color(SK_ColorWHITE), timeout_and_draw_when_animation_checkerboards(true), - maximum_number_of_failed_draws_before_draw_is_forced_(3), layer_transforms_should_scale_layer_contents(false), layers_always_allowed_lcd_text(false), minimum_contents_scale(0.0625f), @@ -51,7 +52,6 @@ LayerTreeSettings::LayerTreeSettings() max_untiled_layer_size(gfx::Size(512, 512)), default_tile_grid_size(gfx::Size(256, 256)), minimum_occlusion_tracking_size(gfx::Size(160, 160)), - use_pinch_virtual_viewport(false), // At 256x256 tiles, 128 tiles cover an area of 2048x4096 pixels. max_tiles_for_interest_area(128), skewport_target_time_in_seconds(1.0f), @@ -59,8 +59,9 @@ LayerTreeSettings::LayerTreeSettings() max_unused_resource_memory_percentage(100), max_memory_for_prepaint_percentage(100), strict_layer_property_change_checking(false), - use_one_copy(false), + use_one_copy(true), use_zero_copy(false), + use_persistent_map_for_gpu_memory_buffers(false), enable_elastic_overscroll(false), use_image_texture_target(GL_TEXTURE_2D), ignore_root_layer_flings(false), @@ -68,10 +69,10 @@ LayerTreeSettings::LayerTreeSettings() use_occlusion_for_tile_prioritization(false), record_full_layer(false), use_display_lists(false), - use_cached_picture_in_display_list(true), verify_property_trees(false), gather_pixel_refs(false), - use_compositor_animation_timelines(false) { + use_compositor_animation_timelines(false), + invert_viewport_scroll_order(false) { } LayerTreeSettings::~LayerTreeSettings() {} @@ -82,15 +83,12 @@ SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const { use_external_begin_frame_source; scheduler_settings.main_frame_before_activation_enabled = main_frame_before_activation_enabled; - scheduler_settings.impl_side_painting = impl_side_painting; scheduler_settings.timeout_and_draw_when_animation_checkerboards = timeout_and_draw_when_animation_checkerboards; - scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = - maximum_number_of_failed_draws_before_draw_is_forced_; scheduler_settings.using_synchronous_renderer_compositor = using_synchronous_renderer_compositor; - scheduler_settings.throttle_frame_production = throttle_frame_production; - scheduler_settings.main_thread_should_always_be_low_latency = false; + scheduler_settings.throttle_frame_production = + !renderer_settings.disable_gpu_vsync; scheduler_settings.background_frame_interval = base::TimeDelta::FromSecondsD(1.0 / background_animation_rate); return scheduler_settings; diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h index 56cfa3a9809..6334f94bb13 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -15,21 +15,25 @@ namespace cc { +class CC_EXPORT LayerSettings { + public: + LayerSettings(); + ~LayerSettings(); + + bool use_compositor_animation_timelines; +}; + class CC_EXPORT LayerTreeSettings { public: LayerTreeSettings(); ~LayerTreeSettings(); RendererSettings renderer_settings; - bool impl_side_painting; - bool raster_enabled; - bool throttle_frame_production; bool single_thread_proxy_scheduler; bool use_external_begin_frame_source; bool main_frame_before_activation_enabled; bool using_synchronous_renderer_compositor; bool report_overscroll_only_for_scrollable_axes; - bool per_tile_painting_enabled; bool accelerated_animation_enabled; bool can_use_lcd_text; bool use_distance_field_text; @@ -51,7 +55,6 @@ class CC_EXPORT LayerTreeSettings { float scrollbar_show_scale_threshold; SkColor solid_color_scrollbar_color; bool timeout_and_draw_when_animation_checkerboards; - int maximum_number_of_failed_draws_before_draw_is_forced_; bool layer_transforms_should_scale_layer_contents; bool layers_always_allowed_lcd_text; float minimum_contents_scale; @@ -64,7 +67,6 @@ class CC_EXPORT LayerTreeSettings { gfx::Size max_untiled_layer_size; gfx::Size default_tile_grid_size; gfx::Size minimum_occlusion_tracking_size; - bool use_pinch_virtual_viewport; size_t max_tiles_for_interest_area; float skewport_target_time_in_seconds; int skewport_extrapolation_limit_in_content_pixels; @@ -73,6 +75,7 @@ class CC_EXPORT LayerTreeSettings { bool strict_layer_property_change_checking; bool use_one_copy; bool use_zero_copy; + bool use_persistent_map_for_gpu_memory_buffers; bool enable_elastic_overscroll; unsigned use_image_texture_target; bool ignore_root_layer_flings; @@ -80,10 +83,10 @@ class CC_EXPORT LayerTreeSettings { bool use_occlusion_for_tile_prioritization; bool record_full_layer; bool use_display_lists; - bool use_cached_picture_in_display_list; bool verify_property_trees; bool gather_pixel_refs; bool use_compositor_animation_timelines; + bool invert_viewport_scroll_order; LayerTreeDebugState initial_debug_state; diff --git a/chromium/cc/trees/mutator_host_client.h b/chromium/cc/trees/mutator_host_client.h new file mode 100644 index 00000000000..56123b4a62a --- /dev/null +++ b/chromium/cc/trees/mutator_host_client.h @@ -0,0 +1,45 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TREES_MUTATOR_HOST_CLIENT_H_ +#define CC_TREES_MUTATOR_HOST_CLIENT_H_ + +namespace gfx { +class Transform; +class ScrollOffset; +} + +namespace cc { + +class FilterOperations; +class Layer; + +enum class LayerTreeType { ACTIVE, PENDING }; + +class MutatorHostClient { + public: + virtual bool IsLayerInTree(int layer_id, LayerTreeType tree_type) const = 0; + virtual void SetMutatorsNeedCommit() = 0; + + virtual void SetLayerFilterMutated(int layer_id, + LayerTreeType tree_type, + const FilterOperations& filters) = 0; + virtual void SetLayerOpacityMutated(int layer_id, + LayerTreeType tree_type, + float opacity) = 0; + virtual void SetLayerTransformMutated(int layer_id, + LayerTreeType tree_type, + const gfx::Transform& transform) = 0; + virtual void SetLayerScrollOffsetMutated( + int layer_id, + LayerTreeType tree_type, + const gfx::ScrollOffset& scroll_offset) = 0; + + virtual void ScrollOffsetAnimationFinished() = 0; + virtual gfx::ScrollOffset GetScrollOffsetForAnimation(int layer_id) const = 0; +}; + +} // namespace cc + +#endif // CC_TREES_MUTATOR_HOST_CLIENT_H_ diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc index 0f0ce158400..996adc895af 100644 --- a/chromium/cc/trees/occlusion_tracker.cc +++ b/chromium/cc/trees/occlusion_tracker.cc @@ -17,18 +17,14 @@ namespace cc { -template <typename LayerType> -OcclusionTracker<LayerType>::OcclusionTracker( - const gfx::Rect& screen_space_clip_rect) +OcclusionTracker::OcclusionTracker(const gfx::Rect& screen_space_clip_rect) : screen_space_clip_rect_(screen_space_clip_rect) { } -template <typename LayerType> -OcclusionTracker<LayerType>::~OcclusionTracker() { +OcclusionTracker::~OcclusionTracker() { } -template <typename LayerType> -Occlusion OcclusionTracker<LayerType>::GetCurrentOcclusionForLayer( +Occlusion OcclusionTracker::GetCurrentOcclusionForLayer( const gfx::Transform& draw_transform) const { DCHECK(!stack_.empty()); const StackObject& back = stack_.back(); @@ -37,9 +33,7 @@ Occlusion OcclusionTracker<LayerType>::GetCurrentOcclusionForLayer( back.occlusion_from_inside_target); } -template <typename LayerType> -Occlusion -OcclusionTracker<LayerType>::GetCurrentOcclusionForContributingSurface( +Occlusion OcclusionTracker::GetCurrentOcclusionForContributingSurface( const gfx::Transform& draw_transform) const { DCHECK(!stack_.empty()); if (stack_.size() < 2) @@ -52,10 +46,8 @@ OcclusionTracker<LayerType>::GetCurrentOcclusionForContributingSurface( second_last.occlusion_from_inside_target); } -template <typename LayerType> -void OcclusionTracker<LayerType>::EnterLayer( - const LayerIteratorPosition<LayerType>& layer_iterator) { - LayerType* render_target = layer_iterator.target_render_surface_layer; +void OcclusionTracker::EnterLayer(const LayerIteratorPosition& layer_iterator) { + LayerImpl* render_target = layer_iterator.target_render_surface_layer; if (layer_iterator.represents_itself) EnterRenderTarget(render_target); @@ -63,10 +55,8 @@ void OcclusionTracker<LayerType>::EnterLayer( FinishedRenderTarget(render_target); } -template <typename LayerType> -void OcclusionTracker<LayerType>::LeaveLayer( - const LayerIteratorPosition<LayerType>& layer_iterator) { - LayerType* render_target = layer_iterator.target_render_surface_layer; +void OcclusionTracker::LeaveLayer(const LayerIteratorPosition& layer_iterator) { + LayerImpl* render_target = layer_iterator.target_render_surface_layer; if (layer_iterator.represents_itself) MarkOccludedBehindLayer(layer_iterator.current_layer); @@ -76,9 +66,8 @@ void OcclusionTracker<LayerType>::LeaveLayer( LeaveToRenderTarget(render_target); } -template <typename RenderSurfaceType> static gfx::Rect ScreenSpaceClipRectInTargetSurface( - const RenderSurfaceType* target_surface, + const RenderSurfaceImpl* target_surface, const gfx::Rect& screen_space_clip_rect) { gfx::Transform inverse_screen_space_transform( gfx::Transform::kSkipInitialization); @@ -90,7 +79,6 @@ static gfx::Rect ScreenSpaceClipRectInTargetSurface( screen_space_clip_rect); } -template <typename RenderSurfaceType> static SimpleEnclosedRegion TransformSurfaceOpaqueRegion( const SimpleEnclosedRegion& region, bool have_clip_rect, @@ -119,73 +107,25 @@ static SimpleEnclosedRegion TransformSurfaceOpaqueRegion( return transformed_region; } -static inline bool LayerOpacityKnown(const Layer* layer) { - return !layer->draw_opacity_is_animating(); -} -static inline bool LayerOpacityKnown(const LayerImpl* layer) { - return true; -} -static inline bool LayerTransformsToTargetKnown(const Layer* layer) { - return !layer->draw_transform_is_animating(); -} -static inline bool LayerTransformsToTargetKnown(const LayerImpl* layer) { - return true; -} - -static inline bool SurfaceOpacityKnown(const RenderSurface* rs) { - return !rs->draw_opacity_is_animating(); -} -static inline bool SurfaceOpacityKnown(const RenderSurfaceImpl* rs) { - return true; -} -static inline bool SurfaceTransformsToTargetKnown(const RenderSurface* rs) { - return !rs->target_surface_transforms_are_animating(); -} -static inline bool SurfaceTransformsToTargetKnown(const RenderSurfaceImpl* rs) { - return true; -} -static inline bool SurfaceTransformsToScreenKnown(const RenderSurface* rs) { - return !rs->screen_space_transforms_are_animating(); -} -static inline bool SurfaceTransformsToScreenKnown(const RenderSurfaceImpl* rs) { - return true; -} - -static inline bool LayerIsInUnsorted3dRenderingContext(const Layer* layer) { - return layer->Is3dSorted(); -} -static inline bool LayerIsInUnsorted3dRenderingContext(const LayerImpl* layer) { - return layer->Is3dSorted(); -} - -template <typename LayerType> -static inline bool LayerIsHidden(const LayerType* layer) { - return layer->hide_layer_and_subtree() || - (layer->parent() && LayerIsHidden(layer->parent())); -} - -template <typename LayerType> -void OcclusionTracker<LayerType>::EnterRenderTarget( - const LayerType* new_target) { +void OcclusionTracker::EnterRenderTarget(const LayerImpl* new_target) { if (!stack_.empty() && stack_.back().target == new_target) return; - const LayerType* old_target = NULL; - const typename LayerType::RenderSurfaceType* old_occlusion_immune_ancestor = - NULL; + const LayerImpl* old_target = NULL; + const RenderSurfaceImpl* old_occlusion_immune_ancestor = NULL; if (!stack_.empty()) { old_target = stack_.back().target; old_occlusion_immune_ancestor = old_target->render_surface()->nearest_occlusion_immune_ancestor(); } - const typename LayerType::RenderSurfaceType* new_occlusion_immune_ancestor = + const RenderSurfaceImpl* new_occlusion_immune_ancestor = new_target->render_surface()->nearest_occlusion_immune_ancestor(); stack_.push_back(StackObject(new_target)); - // We copy the screen occlusion into the new RenderSurface subtree, but we + // We copy the screen occlusion into the new RenderSurfaceImpl subtree, but we // never copy in the occlusion from inside the target, since we are looking - // at a new RenderSurface target. + // at a new RenderSurfaceImpl target. // If entering an unoccluded subtree, do not carry forward the outside // occlusion calculated so far. @@ -193,15 +133,12 @@ void OcclusionTracker<LayerType>::EnterRenderTarget( new_occlusion_immune_ancestor && new_occlusion_immune_ancestor != old_occlusion_immune_ancestor; - bool have_transform_from_screen_to_new_target = false; gfx::Transform inverse_new_target_screen_space_transform( // Note carefully, not used if screen space transform is uninvertible. gfx::Transform::kSkipInitialization); - if (SurfaceTransformsToScreenKnown(new_target->render_surface())) { - have_transform_from_screen_to_new_target = - new_target->render_surface()->screen_space_transform().GetInverse( - &inverse_new_target_screen_space_transform); - } + bool have_transform_from_screen_to_new_target = + new_target->render_surface()->screen_space_transform().GetInverse( + &inverse_new_target_screen_space_transform); bool entering_root_target = new_target->parent() == NULL; @@ -213,32 +150,30 @@ void OcclusionTracker<LayerType>::EnterRenderTarget( if (!copy_outside_occlusion_forward) return; - int last_index = stack_.size() - 1; + size_t last_index = stack_.size() - 1; gfx::Transform old_target_to_new_target_transform( inverse_new_target_screen_space_transform, old_target->render_surface()->screen_space_transform()); stack_[last_index].occlusion_from_outside_target = - TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( - stack_[last_index - 1].occlusion_from_outside_target, - false, - gfx::Rect(), - old_target_to_new_target_transform); + TransformSurfaceOpaqueRegion( + stack_[last_index - 1].occlusion_from_outside_target, false, + gfx::Rect(), old_target_to_new_target_transform); stack_[last_index].occlusion_from_outside_target.Union( - TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( - stack_[last_index - 1].occlusion_from_inside_target, - false, - gfx::Rect(), - old_target_to_new_target_transform)); + TransformSurfaceOpaqueRegion( + stack_[last_index - 1].occlusion_from_inside_target, false, + gfx::Rect(), old_target_to_new_target_transform)); } -template <typename LayerType> -void OcclusionTracker<LayerType>::FinishedRenderTarget( - const LayerType* finished_target) { +static bool LayerIsHidden(const LayerImpl* layer) { + return layer->hide_layer_and_subtree() || + (layer->parent() && LayerIsHidden(layer->parent())); +} + +void OcclusionTracker::FinishedRenderTarget(const LayerImpl* finished_target) { // Make sure we know about the target surface. EnterRenderTarget(finished_target); - typename LayerType::RenderSurfaceType* surface = - finished_target->render_surface(); + RenderSurfaceImpl* surface = finished_target->render_surface(); // Readbacks always happen on render targets so we only need to check // for readbacks here. @@ -247,25 +182,20 @@ void OcclusionTracker<LayerType>::FinishedRenderTarget( // If the occlusion within the surface can not be applied to things outside of // the surface's subtree, then clear the occlusion here so it won't be used. - if (finished_target->mask_layer() || !SurfaceOpacityKnown(surface) || - surface->draw_opacity() < 1 || + if (finished_target->mask_layer() || surface->draw_opacity() < 1 || !finished_target->uses_default_blend_mode() || target_is_only_for_copy_request || finished_target->filters().HasFilterThatAffectsOpacity()) { stack_.back().occlusion_from_outside_target.Clear(); stack_.back().occlusion_from_inside_target.Clear(); - } else if (!SurfaceTransformsToTargetKnown(surface)) { - stack_.back().occlusion_from_inside_target.Clear(); - stack_.back().occlusion_from_outside_target.Clear(); } } -template <typename LayerType> static void ReduceOcclusionBelowSurface( - LayerType* contributing_layer, + const LayerImpl* contributing_layer, const gfx::Rect& surface_rect, const gfx::Transform& surface_transform, - LayerType* render_target, + const LayerImpl* render_target, SimpleEnclosedRegion* occlusion_from_inside_target) { if (surface_rect.IsEmpty()) return; @@ -315,10 +245,9 @@ static void ReduceOcclusionBelowSurface( } } -template <typename LayerType> -void OcclusionTracker<LayerType>::LeaveToRenderTarget( - const LayerType* new_target) { - int last_index = stack_.size() - 1; +void OcclusionTracker::LeaveToRenderTarget(const LayerImpl* new_target) { + DCHECK(!stack_.empty()); + size_t last_index = stack_.size() - 1; bool surface_will_be_at_top_after_pop = stack_.size() > 1 && stack_[last_index - 1].target == new_target; @@ -326,30 +255,25 @@ void OcclusionTracker<LayerType>::LeaveToRenderTarget( // out to its parent target RenderSurfaceImpl. The target occlusion can be // merged out as well but needs to be transformed to the new target. - const LayerType* old_target = stack_[last_index].target; - const typename LayerType::RenderSurfaceType* old_surface = - old_target->render_surface(); + const LayerImpl* old_target = stack_[last_index].target; + const RenderSurfaceImpl* old_surface = old_target->render_surface(); SimpleEnclosedRegion old_occlusion_from_inside_target_in_new_target = - TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( + TransformSurfaceOpaqueRegion( stack_[last_index].occlusion_from_inside_target, - old_surface->is_clipped(), - old_surface->clip_rect(), + old_surface->is_clipped(), old_surface->clip_rect(), old_surface->draw_transform()); if (old_target->has_replica() && !old_target->replica_has_mask()) { old_occlusion_from_inside_target_in_new_target.Union( - TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( + TransformSurfaceOpaqueRegion( stack_[last_index].occlusion_from_inside_target, - old_surface->is_clipped(), - old_surface->clip_rect(), + old_surface->is_clipped(), old_surface->clip_rect(), old_surface->replica_draw_transform())); } SimpleEnclosedRegion old_occlusion_from_outside_target_in_new_target = - TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( - stack_[last_index].occlusion_from_outside_target, - false, - gfx::Rect(), + TransformSurfaceOpaqueRegion( + stack_[last_index].occlusion_from_outside_target, false, gfx::Rect(), old_surface->draw_transform()); gfx::Rect unoccluded_surface_rect; @@ -419,29 +343,24 @@ void OcclusionTracker<LayerType>::LeaveToRenderTarget( &stack_.back().occlusion_from_outside_target); } -template <typename LayerType> -void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( - const LayerType* layer) { +void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) { DCHECK(!stack_.empty()); DCHECK_EQ(layer->render_target(), stack_.back().target); - if (!LayerOpacityKnown(layer) || layer->draw_opacity() < 1) + if (layer->draw_opacity() < 1) return; if (!layer->uses_default_blend_mode()) return; - if (LayerIsInUnsorted3dRenderingContext(layer)) + if (layer->Is3dSorted()) return; - if (!LayerTransformsToTargetKnown(layer)) + SimpleEnclosedRegion opaque_layer_region = layer->VisibleOpaqueRegion(); + if (opaque_layer_region.IsEmpty()) return; - SimpleEnclosedRegion opaque_contents = layer->VisibleContentOpaqueRegion(); - if (opaque_contents.IsEmpty()) - return; - - DCHECK(layer->visible_content_rect().Contains(opaque_contents.bounds())); + DCHECK(layer->visible_layer_rect().Contains(opaque_layer_region.bounds())); // TODO(danakj): Find a rect interior to each transformed quad. if (!layer->draw_transform().Preserves2dAxisAlignment()) @@ -456,10 +375,10 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( layer->render_target()->render_surface()->content_rect()); } - for (size_t i = 0; i < opaque_contents.GetRegionComplexity(); ++i) { + for (size_t i = 0; i < opaque_layer_region.GetRegionComplexity(); ++i) { gfx::Rect transformed_rect = MathUtil::MapEnclosedRectWith2dAxisAlignedTransform( - layer->draw_transform(), opaque_contents.GetRect(i)); + layer->draw_transform(), opaque_layer_region.GetRect(i)); transformed_rect.Intersect(clip_rect_in_target); if (transformed_rect.width() < minimum_tracking_size_.width() && transformed_rect.height() < minimum_tracking_size_.height()) @@ -468,8 +387,7 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( } } -template <typename LayerType> -Region OcclusionTracker<LayerType>::ComputeVisibleRegionInScreen() const { +Region OcclusionTracker::ComputeVisibleRegionInScreen() const { DCHECK(!stack_.back().target->parent()); const SimpleEnclosedRegion& occluded = stack_.back().occlusion_from_inside_target; @@ -479,8 +397,4 @@ Region OcclusionTracker<LayerType>::ComputeVisibleRegionInScreen() const { return visible_region; } -// Instantiate (and export) templates here for the linker. -template class OcclusionTracker<Layer>; -template class OcclusionTracker<LayerImpl>; - } // namespace cc diff --git a/chromium/cc/trees/occlusion_tracker.h b/chromium/cc/trees/occlusion_tracker.h index ff6f18dda9c..9a9294c779d 100644 --- a/chromium/cc/trees/occlusion_tracker.h +++ b/chromium/cc/trees/occlusion_tracker.h @@ -18,8 +18,6 @@ namespace cc { class LayerImpl; class Region; class RenderSurfaceImpl; -class Layer; -class RenderSurface; // This class is used to track occlusion of layers while traversing them in a // front-to-back order. As each layer is visited, one of the methods in this @@ -30,7 +28,6 @@ class RenderSurface; // queried via surfaceOccluded() and surfaceUnoccludedContentRect(). Finally, // once finished with the layer, occlusion behind the layer should be marked by // calling MarkOccludedBehindLayer(). -template <typename LayerType> class CC_EXPORT OcclusionTracker { public: explicit OcclusionTracker(const gfx::Rect& screen_space_clip_rect); @@ -45,10 +42,10 @@ class CC_EXPORT OcclusionTracker { // Called at the beginning of each step in the LayerIterator's front-to-back // traversal. - void EnterLayer(const LayerIteratorPosition<LayerType>& layer_iterator); + void EnterLayer(const LayerIteratorPosition& layer_iterator); // Called at the end of each step in the LayerIterator's front-to-back // traversal. - void LeaveLayer(const LayerIteratorPosition<LayerType>& layer_iterator); + void LeaveLayer(const LayerIteratorPosition& layer_iterator); // Gives the region of the screen that is not occluded by something opaque. Region ComputeVisibleRegionInScreen() const; @@ -60,8 +57,8 @@ class CC_EXPORT OcclusionTracker { protected: struct StackObject { StackObject() : target(0) {} - explicit StackObject(const LayerType* target) : target(target) {} - const LayerType* target; + explicit StackObject(const LayerImpl* target) : target(target) {} + const LayerImpl* target; SimpleEnclosedRegion occlusion_from_outside_target; SimpleEnclosedRegion occlusion_from_inside_target; }; @@ -86,21 +83,21 @@ class CC_EXPORT OcclusionTracker { private: // Called when visiting a layer representing itself. If the target was not // already current, then this indicates we have entered a new surface subtree. - void EnterRenderTarget(const LayerType* new_target); + void EnterRenderTarget(const LayerImpl* new_target); // Called when visiting a layer representing a target surface. This indicates // we have visited all the layers within the surface, and we may perform any // surface-wide operations. - void FinishedRenderTarget(const LayerType* finished_target); + void FinishedRenderTarget(const LayerImpl* finished_target); // Called when visiting a layer representing a contributing surface. This // indicates that we are leaving our current surface, and entering the new // one. We then perform any operations required for merging results from the // child subtree into its parent. - void LeaveToRenderTarget(const LayerType* new_target); + void LeaveToRenderTarget(const LayerImpl* new_target); // Add the layer's occlusion to the tracked state. - void MarkOccludedBehindLayer(const LayerType* layer); + void MarkOccludedBehindLayer(const LayerImpl* layer); gfx::Rect screen_space_clip_rect_; gfx::Size minimum_tracking_size_; @@ -108,11 +105,6 @@ class CC_EXPORT OcclusionTracker { DISALLOW_COPY_AND_ASSIGN(OcclusionTracker); }; -#if !defined(COMPILER_MSVC) -extern template class OcclusionTracker<Layer>; -extern template class OcclusionTracker<LayerImpl>; -#endif - } // namespace cc #endif // CC_TREES_OCCLUSION_TRACKER_H_ diff --git a/chromium/cc/trees/occlusion_tracker_perftest.cc b/chromium/cc/trees/occlusion_tracker_perftest.cc index 854dacdb5f0..209399dce11 100644 --- a/chromium/cc/trees/occlusion_tracker_perftest.cc +++ b/chromium/cc/trees/occlusion_tracker_perftest.cc @@ -4,6 +4,7 @@ #include "cc/trees/occlusion_tracker.h" +#include "base/thread_task_runner_handle.h" #include "base/time/time.h" #include "cc/debug/lap_timer.h" #include "cc/layers/layer_iterator.h" @@ -13,6 +14,7 @@ #include "cc/test/fake_proxy.h" #include "cc/test/fake_rendering_stats_instrumentation.h" #include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" @@ -32,13 +34,13 @@ class OcclusionTrackerPerfTest : public testing::Test { : timer_(kWarmupRuns, base::TimeDelta::FromMilliseconds(kTimeLimitMillis), kTimeCheckInterval), + proxy_(base::ThreadTaskRunnerHandle::Get(), nullptr), impl_(&proxy_) {} void CreateHost() { LayerTreeSettings settings; - shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - host_impl_ = - LayerTreeHostImpl::Create(settings, &client_, &proxy_, &stats_, - shared_bitmap_manager_.get(), NULL, NULL, 1); + host_impl_ = LayerTreeHostImpl::Create(settings, &client_, &proxy_, &stats_, + &shared_bitmap_manager_, nullptr, + &task_graph_runner_, 1); host_impl_->InitializeRenderer(FakeOutputSurface::Create3d()); scoped_ptr<LayerImpl> root_layer = LayerImpl::Create(active_tree(), 1); @@ -67,7 +69,8 @@ class OcclusionTrackerPerfTest : public testing::Test { FakeProxy proxy_; DebugScopedSetImplThread impl_; FakeRenderingStatsInstrumentation stats_; - scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; + TestSharedBitmapManager shared_bitmap_manager_; + TestTaskGraphRunner task_graph_runner_; scoped_ptr<LayerTreeHostImpl> host_impl_; }; @@ -75,7 +78,7 @@ TEST_F(OcclusionTrackerPerfTest, UnoccludedContentRect_FullyOccluded) { SetTestName("unoccluded_content_rect_fully_occluded"); gfx::Rect viewport_rect(768, 1038); - OcclusionTracker<LayerImpl> tracker(viewport_rect); + OcclusionTracker tracker(viewport_rect); CreateHost(); host_impl_->SetViewportSize(viewport_rect.size()); @@ -86,7 +89,6 @@ TEST_F(OcclusionTrackerPerfTest, UnoccludedContentRect_FullyOccluded) { opaque_layer->SetContentsOpaque(true); opaque_layer->SetDrawsContent(true); opaque_layer->SetBounds(viewport_rect.size()); - opaque_layer->SetContentBounds(viewport_rect.size()); active_tree()->root_layer()->AddChild(opaque_layer.Pass()); bool update_lcd_text = false; @@ -95,10 +97,10 @@ TEST_F(OcclusionTrackerPerfTest, UnoccludedContentRect_FullyOccluded) { ASSERT_EQ(1u, rsll.size()); EXPECT_EQ(1u, rsll[0]->render_surface()->layer_list().size()); - LayerIterator<LayerImpl> begin = LayerIterator<LayerImpl>::Begin(&rsll); - LayerIterator<LayerImpl> end = LayerIterator<LayerImpl>::End(&rsll); + LayerIterator begin = LayerIterator::Begin(&rsll); + LayerIterator end = LayerIterator::End(&rsll); - LayerIteratorPosition<LayerImpl> pos = begin; + LayerIteratorPosition pos = begin; // The opaque_layer adds occlusion over the whole viewport. tracker.EnterLayer(pos); @@ -128,7 +130,7 @@ TEST_F(OcclusionTrackerPerfTest, UnoccludedContentRect_FullyOccluded) { } while (!timer_.HasTimeLimitExpired()); ++begin; - LayerIteratorPosition<LayerImpl> next = begin; + LayerIteratorPosition next = begin; EXPECT_EQ(active_tree()->root_layer(), next.current_layer); ++begin; @@ -142,7 +144,7 @@ TEST_F(OcclusionTrackerPerfTest, UnoccludedContentRect_10OpaqueLayers) { SetTestName("unoccluded_content_rect_10_opaque_layers"); gfx::Rect viewport_rect(768, 1038); - OcclusionTracker<LayerImpl> tracker(viewport_rect); + OcclusionTracker tracker(viewport_rect); CreateHost(); host_impl_->SetViewportSize(viewport_rect.size()); @@ -155,8 +157,6 @@ TEST_F(OcclusionTrackerPerfTest, UnoccludedContentRect_10OpaqueLayers) { opaque_layer->SetDrawsContent(true); opaque_layer->SetBounds( gfx::Size(viewport_rect.width() / 2, viewport_rect.height() / 2)); - opaque_layer->SetContentBounds( - gfx::Size(viewport_rect.width() / 2, viewport_rect.height() / 2)); opaque_layer->SetPosition(gfx::Point(i, i)); active_tree()->root_layer()->AddChild(opaque_layer.Pass()); } @@ -168,17 +168,17 @@ TEST_F(OcclusionTrackerPerfTest, UnoccludedContentRect_10OpaqueLayers) { EXPECT_EQ(static_cast<size_t>(kNumOpaqueLayers), rsll[0]->render_surface()->layer_list().size()); - LayerIterator<LayerImpl> begin = LayerIterator<LayerImpl>::Begin(&rsll); - LayerIterator<LayerImpl> end = LayerIterator<LayerImpl>::End(&rsll); + LayerIterator begin = LayerIterator::Begin(&rsll); + LayerIterator end = LayerIterator::End(&rsll); // The opaque_layers add occlusion. for (int i = 0; i < kNumOpaqueLayers - 1; ++i) { - LayerIteratorPosition<LayerImpl> pos = begin; + LayerIteratorPosition pos = begin; tracker.EnterLayer(pos); tracker.LeaveLayer(pos); ++begin; } - LayerIteratorPosition<LayerImpl> pos = begin; + LayerIteratorPosition pos = begin; tracker.EnterLayer(pos); tracker.LeaveLayer(pos); @@ -200,7 +200,7 @@ TEST_F(OcclusionTrackerPerfTest, UnoccludedContentRect_10OpaqueLayers) { } while (!timer_.HasTimeLimitExpired()); ++begin; - LayerIteratorPosition<LayerImpl> next = begin; + LayerIteratorPosition next = begin; EXPECT_EQ(active_tree()->root_layer(), next.current_layer); ++begin; diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc index f3f218570eb..08cfcf7290e 100644 --- a/chromium/cc/trees/occlusion_tracker_unittest.cc +++ b/chromium/cc/trees/occlusion_tracker_unittest.cc @@ -18,6 +18,7 @@ #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/test_occlusion_tracker.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gmock/include/gmock/gmock.h" @@ -27,31 +28,6 @@ namespace cc { namespace { -class TestContentLayer : public Layer { - public: - TestContentLayer() : Layer(), override_opaque_contents_rect_(false) { - SetIsDrawable(true); - } - - SimpleEnclosedRegion VisibleContentOpaqueRegion() const override { - if (override_opaque_contents_rect_) { - return SimpleEnclosedRegion( - gfx::IntersectRects(opaque_contents_rect_, visible_content_rect())); - } - return Layer::VisibleContentOpaqueRegion(); - } - void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) { - override_opaque_contents_rect_ = true; - opaque_contents_rect_ = opaque_contents_rect; - } - - private: - ~TestContentLayer() override {} - - bool override_opaque_contents_rect_; - gfx::Rect opaque_contents_rect_; -}; - class TestContentLayerImpl : public LayerImpl { public: TestContentLayerImpl(LayerTreeImpl* tree_impl, int id) @@ -59,12 +35,12 @@ class TestContentLayerImpl : public LayerImpl { SetDrawsContent(true); } - SimpleEnclosedRegion VisibleContentOpaqueRegion() const override { + SimpleEnclosedRegion VisibleOpaqueRegion() const override { if (override_opaque_contents_rect_) { return SimpleEnclosedRegion( - gfx::IntersectRects(opaque_contents_rect_, visible_content_rect())); + gfx::IntersectRects(opaque_contents_rect_, visible_layer_rect())); } - return LayerImpl::VisibleContentOpaqueRegion(); + return LayerImpl::VisibleOpaqueRegion(); } void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) { override_opaque_contents_rect_ = true; @@ -76,162 +52,97 @@ class TestContentLayerImpl : public LayerImpl { gfx::Rect opaque_contents_rect_; }; -template <typename LayerType> -class TestOcclusionTrackerWithClip : public TestOcclusionTracker<LayerType> { +class TestOcclusionTrackerWithClip : public TestOcclusionTracker { public: explicit TestOcclusionTrackerWithClip(const gfx::Rect& viewport_rect) - : TestOcclusionTracker<LayerType>(viewport_rect) {} + : TestOcclusionTracker(viewport_rect) {} - bool OccludedLayer(const LayerType* layer, + bool OccludedLayer(const LayerImpl* layer, const gfx::Rect& content_rect) const { - DCHECK(layer->visible_content_rect().Contains(content_rect)); + DCHECK(layer->visible_layer_rect().Contains(content_rect)); return this->GetCurrentOcclusionForLayer(layer->draw_transform()) .IsOccluded(content_rect); } // Gives an unoccluded sub-rect of |content_rect| in the content space of the // layer. Simple wrapper around GetUnoccludedContentRect. - gfx::Rect UnoccludedLayerContentRect(const LayerType* layer, + gfx::Rect UnoccludedLayerContentRect(const LayerImpl* layer, const gfx::Rect& content_rect) const { - DCHECK(layer->visible_content_rect().Contains(content_rect)); + DCHECK(layer->visible_layer_rect().Contains(content_rect)); return this->GetCurrentOcclusionForLayer(layer->draw_transform()) .GetUnoccludedContentRect(content_rect); } - gfx::Rect UnoccludedSurfaceContentRect(const LayerType* layer, + gfx::Rect UnoccludedSurfaceContentRect(const LayerImpl* layer, const gfx::Rect& content_rect) const { - typename LayerType::RenderSurfaceType* surface = layer->render_surface(); + RenderSurfaceImpl* surface = layer->render_surface(); return this->GetCurrentOcclusionForContributingSurface( surface->draw_transform()) .GetUnoccludedContentRect(content_rect); } }; -struct OcclusionTrackerTestMainThreadTypes { - typedef Layer LayerType; - typedef FakeLayerTreeHost HostType; - typedef RenderSurface RenderSurfaceType; - typedef TestContentLayer ContentLayerType; - typedef scoped_refptr<Layer> LayerPtrType; - typedef scoped_refptr<ContentLayerType> ContentLayerPtrType; - typedef LayerIterator<Layer> TestLayerIterator; - typedef OcclusionTracker<Layer> OcclusionTrackerType; - - static LayerPtrType CreateLayer(HostType* host) { return Layer::Create(); } - static ContentLayerPtrType CreateContentLayer(HostType* host) { - return make_scoped_refptr(new ContentLayerType()); - } - - template <typename T> - static LayerPtrType PassLayerPtr(T* layer) { - LayerPtrType ref(*layer); - *layer = NULL; - return ref; - } - static void SetForceRenderSurface(LayerType* layer, bool force) { - layer->SetForceRenderSurface(force); - } - - static void DestroyLayer(LayerPtrType* layer) { *layer = NULL; } - - static void RecursiveUpdateNumChildren(LayerType* layerType) {} -}; - -struct OcclusionTrackerTestImplThreadTypes { - typedef LayerImpl LayerType; - typedef LayerTreeImpl HostType; - typedef RenderSurfaceImpl RenderSurfaceType; - typedef TestContentLayerImpl ContentLayerType; - typedef scoped_ptr<LayerImpl> LayerPtrType; - typedef scoped_ptr<ContentLayerType> ContentLayerPtrType; - typedef LayerIterator<LayerImpl> TestLayerIterator; - typedef OcclusionTracker<LayerImpl> OcclusionTrackerType; - - static LayerPtrType CreateLayer(HostType* host) { - return LayerImpl::Create(host, next_layer_impl_id++); - } - static ContentLayerPtrType CreateContentLayer(HostType* host) { - return make_scoped_ptr(new ContentLayerType(host, next_layer_impl_id++)); - } - static int next_layer_impl_id; - - template <typename T> - static LayerPtrType PassLayerPtr(T* layer) { - return layer->Pass(); - } - - static void SetForceRenderSurface(LayerType* layer, bool force) { - layer->SetHasRenderSurface(force); - } - static void DestroyLayer(LayerPtrType* layer) { layer->reset(); } - - static void RecursiveUpdateNumChildren(LayerType* layer) { - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(layer); - } -}; - -int OcclusionTrackerTestImplThreadTypes::next_layer_impl_id = 1; - -template <typename Types> class OcclusionTrackerTest : public testing::Test { +class OcclusionTrackerTest : public testing::Test { protected: explicit OcclusionTrackerTest(bool opaque_layers) : opaque_layers_(opaque_layers), client_(FakeLayerTreeHostClient::DIRECT_3D), - host_(FakeLayerTreeHost::Create(&client_)) {} + host_(FakeLayerTreeHost::Create(&client_, &task_graph_runner_)), + next_layer_impl_id_(1) {} virtual void RunMyTest() = 0; void TearDown() override { DestroyLayers(); } - typename Types::HostType* GetHost(); - - typename Types::ContentLayerType* CreateRoot(const gfx::Transform& transform, - const gfx::PointF& position, - const gfx::Size& bounds) { - typename Types::ContentLayerPtrType layer( - Types::CreateContentLayer(GetHost())); - typename Types::ContentLayerType* layer_ptr = layer.get(); + TestContentLayerImpl* CreateRoot(const gfx::Transform& transform, + const gfx::PointF& position, + const gfx::Size& bounds) { + LayerTreeImpl* tree = host_->host_impl()->active_tree(); + int id = next_layer_impl_id_++; + scoped_ptr<TestContentLayerImpl> layer(new TestContentLayerImpl(tree, id)); + TestContentLayerImpl* layer_ptr = layer.get(); SetProperties(layer_ptr, transform, position, bounds); DCHECK(!root_.get()); - root_ = Types::PassLayerPtr(&layer); + root_ = layer.Pass(); - Types::SetForceRenderSurface(layer_ptr, true); + layer_ptr->SetHasRenderSurface(true); SetRootLayerOnMainThread(layer_ptr); return layer_ptr; } - typename Types::LayerType* CreateLayer(typename Types::LayerType* parent, - const gfx::Transform& transform, - const gfx::PointF& position, - const gfx::Size& bounds) { - typename Types::LayerPtrType layer(Types::CreateLayer(GetHost())); - typename Types::LayerType* layer_ptr = layer.get(); + LayerImpl* CreateLayer(LayerImpl* parent, + const gfx::Transform& transform, + const gfx::PointF& position, + const gfx::Size& bounds) { + LayerTreeImpl* tree = host_->host_impl()->active_tree(); + int id = next_layer_impl_id_++; + scoped_ptr<LayerImpl> layer = LayerImpl::Create(tree, id); + LayerImpl* layer_ptr = layer.get(); SetProperties(layer_ptr, transform, position, bounds); - parent->AddChild(Types::PassLayerPtr(&layer)); + parent->AddChild(layer.Pass()); return layer_ptr; } - typename Types::LayerType* CreateSurface(typename Types::LayerType* parent, - const gfx::Transform& transform, - const gfx::PointF& position, - const gfx::Size& bounds) { - typename Types::LayerType* layer = - CreateLayer(parent, transform, position, bounds); - Types::SetForceRenderSurface(layer, true); + LayerImpl* CreateSurface(LayerImpl* parent, + const gfx::Transform& transform, + const gfx::PointF& position, + const gfx::Size& bounds) { + LayerImpl* layer = CreateLayer(parent, transform, position, bounds); + layer->SetHasRenderSurface(true); return layer; } - typename Types::ContentLayerType* CreateDrawingLayer( - typename Types::LayerType* parent, - const gfx::Transform& transform, - const gfx::PointF& position, - const gfx::Size& bounds, - bool opaque) { - typename Types::ContentLayerPtrType layer( - Types::CreateContentLayer(GetHost())); - typename Types::ContentLayerType* layer_ptr = layer.get(); + TestContentLayerImpl* CreateDrawingLayer(LayerImpl* parent, + const gfx::Transform& transform, + const gfx::PointF& position, + const gfx::Size& bounds, + bool opaque) { + LayerTreeImpl* tree = host_->host_impl()->active_tree(); + int id = next_layer_impl_id_++; + scoped_ptr<TestContentLayerImpl> layer(new TestContentLayerImpl(tree, id)); + TestContentLayerImpl* layer_ptr = layer.get(); SetProperties(layer_ptr, transform, position, bounds); if (opaque_layers_) { @@ -244,48 +155,46 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { layer_ptr->SetOpaqueContentsRect(gfx::Rect()); } - parent->AddChild(Types::PassLayerPtr(&layer)); + parent->AddChild(layer.Pass()); return layer_ptr; } - typename Types::LayerType* CreateReplicaLayer( - typename Types::LayerType* owning_layer, - const gfx::Transform& transform, - const gfx::PointF& position, - const gfx::Size& bounds) { - typename Types::ContentLayerPtrType layer( - Types::CreateContentLayer(GetHost())); - typename Types::ContentLayerType* layer_ptr = layer.get(); + LayerImpl* CreateReplicaLayer(LayerImpl* owning_layer, + const gfx::Transform& transform, + const gfx::PointF& position, + const gfx::Size& bounds) { + LayerTreeImpl* tree = host_->host_impl()->active_tree(); + int id = next_layer_impl_id_++; + scoped_ptr<TestContentLayerImpl> layer(new TestContentLayerImpl(tree, id)); + TestContentLayerImpl* layer_ptr = layer.get(); SetProperties(layer_ptr, transform, position, bounds); - SetReplica(owning_layer, Types::PassLayerPtr(&layer)); + SetReplica(owning_layer, layer.Pass()); return layer_ptr; } - typename Types::LayerType* CreateMaskLayer( - typename Types::LayerType* owning_layer, - const gfx::Size& bounds) { - typename Types::ContentLayerPtrType layer( - Types::CreateContentLayer(GetHost())); - typename Types::ContentLayerType* layer_ptr = layer.get(); + LayerImpl* CreateMaskLayer(LayerImpl* owning_layer, const gfx::Size& bounds) { + LayerTreeImpl* tree = host_->host_impl()->active_tree(); + int id = next_layer_impl_id_++; + scoped_ptr<TestContentLayerImpl> layer(new TestContentLayerImpl(tree, id)); + TestContentLayerImpl* layer_ptr = layer.get(); SetProperties(layer_ptr, identity_matrix, gfx::PointF(), bounds); - SetMask(owning_layer, Types::PassLayerPtr(&layer)); + SetMask(owning_layer, layer.Pass()); return layer_ptr; } - typename Types::ContentLayerType* CreateDrawingSurface( - typename Types::LayerType* parent, - const gfx::Transform& transform, - const gfx::PointF& position, - const gfx::Size& bounds, - bool opaque) { - typename Types::ContentLayerType* layer = + TestContentLayerImpl* CreateDrawingSurface(LayerImpl* parent, + const gfx::Transform& transform, + const gfx::PointF& position, + const gfx::Size& bounds, + bool opaque) { + TestContentLayerImpl* layer = CreateDrawingLayer(parent, transform, position, bounds, opaque); - Types::SetForceRenderSurface(layer, true); + layer->SetHasRenderSurface(true); return layer; } void DestroyLayers() { - Types::DestroyLayer(&root_); + root_ = nullptr; render_surface_layer_list_ = nullptr; render_surface_layer_list_impl_.clear(); replica_layers_.clear(); @@ -296,18 +205,15 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {} void AddCopyRequest(Layer* layer) { - layer->RequestCopyOfOutput( - CopyOutputRequest::CreateBitmapRequest(base::Bind( - &OcclusionTrackerTest<Types>::CopyOutputCallback, - base::Unretained(this)))); + layer->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest( + base::Bind(&OcclusionTrackerTest::CopyOutputCallback, + base::Unretained(this)))); } void AddCopyRequest(LayerImpl* layer) { ScopedPtrVector<CopyOutputRequest> requests; - requests.push_back( - CopyOutputRequest::CreateBitmapRequest(base::Bind( - &OcclusionTrackerTest<Types>::CopyOutputCallback, - base::Unretained(this)))); + requests.push_back(CopyOutputRequest::CreateBitmapRequest(base::Bind( + &OcclusionTrackerTest::CopyOutputCallback, base::Unretained(this)))); layer->SetHasRenderSurface(true); layer->PassCopyRequests(&requests); } @@ -315,54 +221,40 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { void CalcDrawEtc(TestContentLayerImpl* root) { DCHECK(root == root_.get()); - Types::RecursiveUpdateNumChildren(root); - LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( - root, root->bounds(), &render_surface_layer_list_impl_); - inputs.can_adjust_raster_scales = true; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); + // These occlusion tests attach and detach layers in multiple + // iterations, so rebuild property trees every time. + root->layer_tree_impl()->property_trees()->needs_rebuild = true; - layer_iterator_ = layer_iterator_begin_ = - Types::TestLayerIterator::Begin(&render_surface_layer_list_impl_); - } + FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root); - void CalcDrawEtc(TestContentLayer* root) { - DCHECK(root == root_.get()); - DCHECK(!root->render_surface()); - - render_surface_layer_list_.reset(new RenderSurfaceLayerList); - LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root, root->bounds(), render_surface_layer_list_.get()); + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root, root->bounds(), &render_surface_layer_list_impl_); inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawProperties(&inputs); layer_iterator_ = layer_iterator_begin_ = - Types::TestLayerIterator::Begin(render_surface_layer_list_.get()); + LayerIterator::Begin(&render_surface_layer_list_impl_); } - void EnterLayer(typename Types::LayerType* layer, - typename Types::OcclusionTrackerType* occlusion) { + void EnterLayer(LayerImpl* layer, OcclusionTracker* occlusion) { ASSERT_EQ(*layer_iterator_, layer); ASSERT_TRUE(layer_iterator_.represents_itself()); occlusion->EnterLayer(layer_iterator_); } - void LeaveLayer(typename Types::LayerType* layer, - typename Types::OcclusionTrackerType* occlusion) { + void LeaveLayer(LayerImpl* layer, OcclusionTracker* occlusion) { ASSERT_EQ(*layer_iterator_, layer); ASSERT_TRUE(layer_iterator_.represents_itself()); occlusion->LeaveLayer(layer_iterator_); ++layer_iterator_; } - void VisitLayer(typename Types::LayerType* layer, - typename Types::OcclusionTrackerType* occlusion) { + void VisitLayer(LayerImpl* layer, OcclusionTracker* occlusion) { EnterLayer(layer, occlusion); LeaveLayer(layer, occlusion); } - void EnterContributingSurface( - typename Types::LayerType* layer, - typename Types::OcclusionTrackerType* occlusion) { + void EnterContributingSurface(LayerImpl* layer, OcclusionTracker* occlusion) { ASSERT_EQ(*layer_iterator_, layer); ASSERT_TRUE(layer_iterator_.represents_target_render_surface()); occlusion->EnterLayer(layer_iterator_); @@ -372,18 +264,14 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { occlusion->EnterLayer(layer_iterator_); } - void LeaveContributingSurface( - typename Types::LayerType* layer, - typename Types::OcclusionTrackerType* occlusion) { + void LeaveContributingSurface(LayerImpl* layer, OcclusionTracker* occlusion) { ASSERT_EQ(*layer_iterator_, layer); ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface()); occlusion->LeaveLayer(layer_iterator_); ++layer_iterator_; } - void VisitContributingSurface( - typename Types::LayerType* layer, - typename Types::OcclusionTrackerType* occlusion) { + void VisitContributingSurface(LayerImpl* layer, OcclusionTracker* occlusion) { EnterContributingSurface(layer, occlusion); LeaveContributingSurface(layer, occlusion); } @@ -399,148 +287,72 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { void SetRootLayerOnMainThread(LayerImpl* root) {} - void SetBaseProperties(typename Types::LayerType* layer, - const gfx::Transform& transform, - const gfx::PointF& position, - const gfx::Size& bounds) { - layer->SetTransform(transform); - layer->SetPosition(position); - layer->SetBounds(bounds); - } - - void SetProperties(Layer* layer, - const gfx::Transform& transform, - const gfx::PointF& position, - const gfx::Size& bounds) { - SetBaseProperties(layer, transform, position, bounds); - } - void SetProperties(LayerImpl* layer, const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds) { - SetBaseProperties(layer, transform, position, bounds); - - layer->SetContentBounds(layer->bounds()); - } - - void SetReplica(Layer* owning_layer, scoped_refptr<Layer> layer) { - owning_layer->SetReplicaLayer(layer.get()); - replica_layers_.push_back(layer); + layer->SetTransform(transform); + layer->SetPosition(position); + layer->SetBounds(bounds); } void SetReplica(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) { owning_layer->SetReplicaLayer(layer.Pass()); } - void SetMask(Layer* owning_layer, scoped_refptr<Layer> layer) { - owning_layer->SetMaskLayer(layer.get()); - mask_layers_.push_back(layer); - } - void SetMask(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) { owning_layer->SetMaskLayer(layer.Pass()); } bool opaque_layers_; FakeLayerTreeHostClient client_; + TestTaskGraphRunner task_graph_runner_; scoped_ptr<FakeLayerTreeHost> host_; // These hold ownership of the layers for the duration of the test. - typename Types::LayerPtrType root_; + scoped_ptr<LayerImpl> root_; scoped_ptr<RenderSurfaceLayerList> render_surface_layer_list_; LayerImplList render_surface_layer_list_impl_; - typename Types::TestLayerIterator layer_iterator_begin_; - typename Types::TestLayerIterator layer_iterator_; - typename Types::LayerType* last_layer_visited_; + LayerIterator layer_iterator_begin_; + LayerIterator layer_iterator_; LayerList replica_layers_; LayerList mask_layers_; + int next_layer_impl_id_; }; -template <> -FakeLayerTreeHost* -OcclusionTrackerTest<OcclusionTrackerTestMainThreadTypes>::GetHost() { - return host_.get(); -} - -template <> -LayerTreeImpl* -OcclusionTrackerTest<OcclusionTrackerTestImplThreadTypes>::GetHost() { - return host_->host_impl()->active_tree(); -} - -#define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \ - class ClassName##MainThreadOpaqueLayers \ - : public ClassName<OcclusionTrackerTestMainThreadTypes> { \ - public: /* NOLINT(whitespace/indent) */ \ - ClassName##MainThreadOpaqueLayers() \ - : ClassName<OcclusionTrackerTestMainThreadTypes>(true) {} \ - }; \ - TEST_F(ClassName##MainThreadOpaqueLayers, RunTest) { RunMyTest(); } -#define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \ - class ClassName##MainThreadOpaquePaints \ - : public ClassName<OcclusionTrackerTestMainThreadTypes> { \ - public: /* NOLINT(whitespace/indent) */ \ - ClassName##MainThreadOpaquePaints() \ - : ClassName<OcclusionTrackerTestMainThreadTypes>(false) {} \ - }; \ - TEST_F(ClassName##MainThreadOpaquePaints, RunTest) { RunMyTest(); } - -#define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \ - class ClassName##ImplThreadOpaqueLayers \ - : public ClassName<OcclusionTrackerTestImplThreadTypes> { \ - public: /* NOLINT(whitespace/indent) */ \ - ClassName##ImplThreadOpaqueLayers() \ - : ClassName<OcclusionTrackerTestImplThreadTypes>(true) {} \ - }; \ +#define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \ + class ClassName##ImplThreadOpaqueLayers : public ClassName { \ + public: /* NOLINT(whitespace/indent) */ \ + ClassName##ImplThreadOpaqueLayers() : ClassName(true) {} \ + }; \ TEST_F(ClassName##ImplThreadOpaqueLayers, RunTest) { RunMyTest(); } -#define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \ - class ClassName##ImplThreadOpaquePaints \ - : public ClassName<OcclusionTrackerTestImplThreadTypes> { \ - public: /* NOLINT(whitespace/indent) */ \ - ClassName##ImplThreadOpaquePaints() \ - : ClassName<OcclusionTrackerTestImplThreadTypes>(false) {} \ - }; \ +#define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \ + class ClassName##ImplThreadOpaquePaints : public ClassName { \ + public: /* NOLINT(whitespace/indent) */ \ + ClassName##ImplThreadOpaquePaints() : ClassName(false) {} \ + }; \ TEST_F(ClassName##ImplThreadOpaquePaints, RunTest) { RunMyTest(); } #define ALL_OCCLUSIONTRACKER_TEST(ClassName) \ - RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \ - RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \ RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \ RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) -#define MAIN_THREAD_TEST(ClassName) \ - RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) - -#define IMPL_THREAD_TEST(ClassName) \ - RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) - -#define MAIN_AND_IMPL_THREAD_TEST(ClassName) \ - RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \ - RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) - -template <class Types> -class OcclusionTrackerTestIdentityTransforms - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestIdentityTransforms : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestIdentityTransforms(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); - typename Types::ContentLayerType* parent = this->CreateDrawingLayer( + TestContentLayerImpl* parent = this->CreateDrawingLayer( root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); - typename Types::ContentLayerType* layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(30.f, 30.f), - gfx::Size(500, 500), - true); + TestContentLayerImpl* layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(30.f, 30.f), + gfx::Size(500, 500), true); parent->SetMasksToBounds(true); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(layer, &occlusion); this->EnterLayer(parent, &occlusion); @@ -554,32 +366,27 @@ class OcclusionTrackerTestIdentityTransforms ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestIdentityTransforms); -template <class Types> -class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestRotatedChild(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform layer_transform; layer_transform.Translate(250.0, 250.0); layer_transform.Rotate(90.0); layer_transform.Translate(-250.0, -250.0); - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::Point(0, 0), gfx::Size(200, 200)); - typename Types::ContentLayerType* parent = this->CreateDrawingLayer( + TestContentLayerImpl* parent = this->CreateDrawingLayer( root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); - typename Types::ContentLayerType* layer = - this->CreateDrawingLayer(parent, - layer_transform, - gfx::PointF(30.f, 30.f), - gfx::Size(500, 500), - true); + TestContentLayerImpl* layer = this->CreateDrawingLayer( + parent, layer_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500), + true); parent->SetMasksToBounds(true); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(layer, &occlusion); this->EnterLayer(parent, &occlusion); @@ -593,30 +400,25 @@ class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> { ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestRotatedChild); -template <class Types> -class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestTranslatedChild(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform layer_transform; layer_transform.Translate(20.0, 20.0); - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); - typename Types::ContentLayerType* parent = this->CreateDrawingLayer( + TestContentLayerImpl* parent = this->CreateDrawingLayer( root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); - typename Types::ContentLayerType* layer = - this->CreateDrawingLayer(parent, - layer_transform, - gfx::PointF(30.f, 30.f), - gfx::Size(500, 500), - true); + TestContentLayerImpl* layer = this->CreateDrawingLayer( + parent, layer_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500), + true); parent->SetMasksToBounds(true); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(layer, &occlusion); this->EnterLayer(parent, &occlusion); @@ -630,34 +432,28 @@ class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> { ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestTranslatedChild); -template <class Types> -class OcclusionTrackerTestChildInRotatedChild - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestChildInRotatedChild : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestChildInRotatedChild(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform child_transform; child_transform.Translate(250.0, 250.0); child_transform.Rotate(90.0); child_transform.Translate(-250.0, -250.0); - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); parent->SetMasksToBounds(true); - typename Types::LayerType* child = this->CreateSurface( + LayerImpl* child = this->CreateSurface( parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500)); child->SetMasksToBounds(true); - typename Types::ContentLayerType* layer = - this->CreateDrawingLayer(child, - this->identity_matrix, - gfx::PointF(10.f, 10.f), - gfx::Size(500, 500), - true); + TestContentLayerImpl* layer = this->CreateDrawingLayer( + child, this->identity_matrix, gfx::PointF(10.f, 10.f), + gfx::Size(500, 500), true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(layer, &occlusion); this->EnterContributingSurface(child, &occlusion); @@ -727,37 +523,31 @@ class OcclusionTrackerTestChildInRotatedChild ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestChildInRotatedChild); -template <class Types> -class OcclusionTrackerTestScaledRenderSurface - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestScaledRenderSurface : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestScaledRenderSurface(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); gfx::Transform layer1_matrix; layer1_matrix.Scale(2.0, 2.0); - typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer( + TestContentLayerImpl* layer1 = this->CreateDrawingLayer( parent, layer1_matrix, gfx::PointF(), gfx::Size(100, 100), true); - Types::SetForceRenderSurface(layer1, true); + layer1->SetHasRenderSurface(true); gfx::Transform layer2_matrix; layer2_matrix.Translate(25.0, 25.0); - typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer( + TestContentLayerImpl* layer2 = this->CreateDrawingLayer( layer1, layer2_matrix, gfx::PointF(), gfx::Size(50, 50), true); - typename Types::ContentLayerType* occluder = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(100.f, 100.f), - gfx::Size(500, 500), - true); + TestContentLayerImpl* occluder = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(100.f, 100.f), + gfx::Size(500, 500), true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(occluder, &occlusion); this->EnterLayer(layer2, &occlusion); @@ -771,37 +561,28 @@ class OcclusionTrackerTestScaledRenderSurface ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledRenderSurface); -template <class Types> -class OcclusionTrackerTestVisitTargetTwoTimes - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestVisitTargetTwoTimes : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestVisitTargetTwoTimes(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); - typename Types::LayerType* surface = this->CreateSurface( + LayerImpl* surface = this->CreateSurface( root, this->identity_matrix, gfx::PointF(30.f, 30.f), gfx::Size()); - typename Types::ContentLayerType* surface_child = - this->CreateDrawingLayer(surface, - this->identity_matrix, - gfx::PointF(10.f, 10.f), - gfx::Size(50, 50), - true); + TestContentLayerImpl* surface_child = this->CreateDrawingLayer( + surface, this->identity_matrix, gfx::PointF(10.f, 10.f), + gfx::Size(50, 50), true); // |top_layer| makes |root|'s surface get considered by OcclusionTracker // first, instead of |surface|'s. This exercises different code in // LeaveToRenderTarget, as the target surface has already been seen when // leaving |surface| later. - typename Types::ContentLayerType* top_layer = - this->CreateDrawingLayer(root, - this->identity_matrix, - gfx::PointF(40.f, 90.f), - gfx::Size(50, 20), - true); + TestContentLayerImpl* top_layer = this->CreateDrawingLayer( + root, this->identity_matrix, gfx::PointF(40.f, 90.f), gfx::Size(50, 20), + true); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(top_layer, &occlusion); @@ -837,12 +618,10 @@ class OcclusionTrackerTestVisitTargetTwoTimes ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestVisitTargetTwoTimes); -template <class Types> -class OcclusionTrackerTestSurfaceRotatedOffAxis - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestSurfaceRotatedOffAxis : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestSurfaceRotatedOffAxis(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform child_transform; child_transform.Translate(250.0, 250.0); @@ -852,21 +631,20 @@ class OcclusionTrackerTestSurfaceRotatedOffAxis gfx::Transform layer_transform; layer_transform.Translate(10.0, 10.0); - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000)); - typename Types::ContentLayerType* parent = this->CreateDrawingLayer( + TestContentLayerImpl* parent = this->CreateDrawingLayer( root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); - typename Types::LayerType* child = this->CreateSurface( + LayerImpl* child = this->CreateSurface( parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500)); - typename Types::ContentLayerType* layer = this->CreateDrawingLayer( + TestContentLayerImpl* layer = this->CreateDrawingLayer( child, layer_transform, gfx::PointF(), gfx::Size(500, 500), true); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); gfx::Rect clipped_layer_in_child = MathUtil::MapEnclosingClippedRect( - layer_transform, layer->visible_content_rect()); + layer_transform, layer->visible_layer_rect()); this->VisitLayer(layer, &occlusion); this->EnterContributingSurface(child, &occlusion); @@ -888,46 +666,35 @@ class OcclusionTrackerTestSurfaceRotatedOffAxis ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceRotatedOffAxis); -template <class Types> class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestSurfaceWithTwoOpaqueChildren(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform child_transform; child_transform.Translate(250.0, 250.0); child_transform.Rotate(90.0); child_transform.Translate(-250.0, -250.0); - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000)); - typename Types::ContentLayerType* parent = this->CreateDrawingLayer( + TestContentLayerImpl* parent = this->CreateDrawingLayer( root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); parent->SetMasksToBounds(true); - typename Types::ContentLayerType* child = - this->CreateDrawingSurface(parent, - child_transform, - gfx::PointF(30.f, 30.f), - gfx::Size(500, 500), - false); + TestContentLayerImpl* child = this->CreateDrawingSurface( + parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500), + false); child->SetMasksToBounds(true); - typename Types::ContentLayerType* layer1 = - this->CreateDrawingLayer(child, - this->identity_matrix, - gfx::PointF(10.f, 10.f), - gfx::Size(500, 500), - true); - typename Types::ContentLayerType* layer2 = - this->CreateDrawingLayer(child, - this->identity_matrix, - gfx::PointF(10.f, 450.f), - gfx::Size(500, 60), - true); + TestContentLayerImpl* layer1 = this->CreateDrawingLayer( + child, this->identity_matrix, gfx::PointF(10.f, 10.f), + gfx::Size(500, 500), true); + TestContentLayerImpl* layer2 = this->CreateDrawingLayer( + child, this->identity_matrix, gfx::PointF(10.f, 450.f), + gfx::Size(500, 60), true); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(layer2, &occlusion); this->VisitLayer(layer1, &occlusion); @@ -976,32 +743,27 @@ class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithTwoOpaqueChildren); -template <class Types> class OcclusionTrackerTestOverlappingSurfaceSiblings - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestOverlappingSurfaceSiblings(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); parent->SetMasksToBounds(true); - typename Types::LayerType* child1 = this->CreateSurface( + LayerImpl* child1 = this->CreateSurface( parent, this->identity_matrix, gfx::PointF(10.f, 0.f), gfx::Size()); - typename Types::LayerType* child2 = this->CreateSurface( + LayerImpl* child2 = this->CreateSurface( parent, this->identity_matrix, gfx::PointF(30.f, 0.f), gfx::Size()); - typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer( + TestContentLayerImpl* layer1 = this->CreateDrawingLayer( child1, this->identity_matrix, gfx::PointF(), gfx::Size(40, 50), true); - typename Types::ContentLayerType* layer2 = - this->CreateDrawingLayer(child2, - this->identity_matrix, - gfx::PointF(10.f, 0.f), - gfx::Size(40, 50), - true); + TestContentLayerImpl* layer2 = this->CreateDrawingLayer( + child2, this->identity_matrix, gfx::PointF(10.f, 0.f), + gfx::Size(40, 50), true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(layer2, &occlusion); this->EnterContributingSurface(child2, &occlusion); @@ -1035,13 +797,12 @@ class OcclusionTrackerTestOverlappingSurfaceSiblings ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOverlappingSurfaceSiblings); -template <class Types> class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform child1_transform; child1_transform.Translate(250.0, 250.0); @@ -1053,33 +814,23 @@ class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms child2_transform.Rotate(90.0); child2_transform.Translate(-250.0, -250.0); - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); parent->SetMasksToBounds(true); - typename Types::LayerType* child1 = this->CreateSurface( + LayerImpl* child1 = this->CreateSurface( parent, child1_transform, gfx::PointF(30.f, 20.f), gfx::Size(10, 10)); - typename Types::LayerType* child2 = - this->CreateDrawingSurface(parent, - child2_transform, - gfx::PointF(20.f, 40.f), - gfx::Size(10, 10), - false); - typename Types::ContentLayerType* layer1 = - this->CreateDrawingLayer(child1, - this->identity_matrix, - gfx::PointF(-10.f, -20.f), - gfx::Size(510, 510), - true); - typename Types::ContentLayerType* layer2 = - this->CreateDrawingLayer(child2, - this->identity_matrix, - gfx::PointF(-10.f, -10.f), - gfx::Size(510, 510), - true); + LayerImpl* child2 = this->CreateDrawingSurface(parent, child2_transform, + gfx::PointF(20.f, 40.f), + gfx::Size(10, 10), false); + TestContentLayerImpl* layer1 = this->CreateDrawingLayer( + child1, this->identity_matrix, gfx::PointF(-10.f, -20.f), + gfx::Size(510, 510), true); + TestContentLayerImpl* layer2 = this->CreateDrawingLayer( + child2, this->identity_matrix, gfx::PointF(-10.f, -10.f), + gfx::Size(510, 510), true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(layer2, &occlusion); this->EnterLayer(child2, &occlusion); @@ -1143,58 +894,47 @@ class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms ALL_OCCLUSIONTRACKER_TEST( OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms); -template <class Types> -class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestFilters : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestFilters(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform layer_transform; layer_transform.Translate(250.0, 250.0); layer_transform.Rotate(90.0); layer_transform.Translate(-250.0, -250.0); - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); parent->SetMasksToBounds(true); - typename Types::ContentLayerType* blur_layer = - this->CreateDrawingLayer(parent, - layer_transform, - gfx::PointF(30.f, 30.f), - gfx::Size(500, 500), - true); - typename Types::ContentLayerType* opaque_layer = - this->CreateDrawingLayer(parent, - layer_transform, - gfx::PointF(30.f, 30.f), - gfx::Size(500, 500), - true); - typename Types::ContentLayerType* opacity_layer = - this->CreateDrawingLayer(parent, - layer_transform, - gfx::PointF(30.f, 30.f), - gfx::Size(500, 500), - true); - - Types::SetForceRenderSurface(blur_layer, true); + TestContentLayerImpl* blur_layer = this->CreateDrawingLayer( + parent, layer_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500), + true); + TestContentLayerImpl* opaque_layer = this->CreateDrawingLayer( + parent, layer_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500), + true); + TestContentLayerImpl* opacity_layer = this->CreateDrawingLayer( + parent, layer_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500), + true); + + blur_layer->SetHasRenderSurface(true); FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter(10.f)); blur_layer->SetFilters(filters); - Types::SetForceRenderSurface(opaque_layer, true); + opaque_layer->SetHasRenderSurface(true); filters.Clear(); filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f)); opaque_layer->SetFilters(filters); - Types::SetForceRenderSurface(opacity_layer, true); + opacity_layer->SetHasRenderSurface(true); filters.Clear(); filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); opacity_layer->SetFilters(filters); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); // Opacity layer won't contribute to occlusion. this->VisitLayer(opacity_layer, &occlusion); @@ -1245,23 +985,20 @@ class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> { ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestFilters); -template <class Types> -class OcclusionTrackerTestReplicaDoesOcclude - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestReplicaDoesOcclude : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestReplicaDoesOcclude(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); - typename Types::LayerType* surface = this->CreateDrawingSurface( + LayerImpl* surface = this->CreateDrawingSurface( parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), true); this->CreateReplicaLayer( surface, this->identity_matrix, gfx::PointF(0.f, 50.f), gfx::Size()); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(surface, &occlusion); @@ -1279,28 +1016,22 @@ class OcclusionTrackerTestReplicaDoesOcclude ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaDoesOcclude); -template <class Types> -class OcclusionTrackerTestReplicaWithClipping - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestReplicaWithClipping : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestReplicaWithClipping(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 170)); parent->SetMasksToBounds(true); - typename Types::LayerType* surface = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(0.f, 100.f), - gfx::Size(50, 50), - true); + LayerImpl* surface = this->CreateDrawingSurface( + parent, this->identity_matrix, gfx::PointF(0.f, 100.f), + gfx::Size(50, 50), true); this->CreateReplicaLayer( surface, this->identity_matrix, gfx::PointF(0.f, 50.f), gfx::Size()); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(surface, &occlusion); @@ -1322,27 +1053,22 @@ class OcclusionTrackerTestReplicaWithClipping ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithClipping); -template <class Types> -class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestReplicaWithMask(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); - typename Types::LayerType* surface = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(0.f, 100.f), - gfx::Size(50, 50), - true); - typename Types::LayerType* replica = this->CreateReplicaLayer( + LayerImpl* surface = this->CreateDrawingSurface( + parent, this->identity_matrix, gfx::PointF(0.f, 100.f), + gfx::Size(50, 50), true); + LayerImpl* replica = this->CreateReplicaLayer( surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size()); this->CreateMaskLayer(replica, gfx::Size(10, 10)); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(surface, &occlusion); @@ -1361,25 +1087,20 @@ class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> { ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithMask); -template <class Types> class OcclusionTrackerTestOpaqueContentsRegionEmpty - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestOpaqueContentsRegionEmpty(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); - typename Types::ContentLayerType* layer = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(200, 200), - false); + TestContentLayerImpl* layer = + this->CreateDrawingSurface(parent, this->identity_matrix, gfx::PointF(), + gfx::Size(200, 200), false); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->EnterLayer(layer, &occlusion); EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); @@ -1394,27 +1115,22 @@ class OcclusionTrackerTestOpaqueContentsRegionEmpty } }; -MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionEmpty); +ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOpaqueContentsRegionEmpty); -template <class Types> class OcclusionTrackerTestOpaqueContentsRegionNonEmpty - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestOpaqueContentsRegionNonEmpty(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); - typename Types::ContentLayerType* layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(100.f, 100.f), - gfx::Size(200, 200), - false); + TestContentLayerImpl* layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(100.f, 100.f), + gfx::Size(200, 200), false); this->CalcDrawEtc(parent); { - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); layer->SetOpaqueContentsRect(gfx::Rect(0, 0, 100, 100)); this->ResetLayerIterator(); @@ -1425,8 +1141,7 @@ class OcclusionTrackerTestOpaqueContentsRegionNonEmpty occlusion.occlusion_from_inside_target().ToString()); } { - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); layer->SetOpaqueContentsRect(gfx::Rect(20, 20, 180, 180)); this->ResetLayerIterator(); @@ -1437,8 +1152,7 @@ class OcclusionTrackerTestOpaqueContentsRegionNonEmpty occlusion.occlusion_from_inside_target().ToString()); } { - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); layer->SetOpaqueContentsRect(gfx::Rect(150, 150, 100, 100)); this->ResetLayerIterator(); @@ -1451,67 +1165,14 @@ class OcclusionTrackerTestOpaqueContentsRegionNonEmpty } }; -MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionNonEmpty); - -template <class Types> -class OcclusionTrackerTestUnsorted3dLayers - : public OcclusionTrackerTest<Types> { - protected: - explicit OcclusionTrackerTestUnsorted3dLayers(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} - void RunMyTest() override { - // Currently, The main thread layer iterator does not iterate over 3d items - // in sorted order, because layer sorting is not performed on the main - // thread. Because of this, the occlusion tracker cannot assume that a 3d - // layer occludes other layers that have not yet been iterated over. For - // now, the expected behavior is that a 3d layer simply does not add any - // occlusion to the occlusion tracker. - - gfx::Transform translation_to_front; - translation_to_front.Translate3d(0.0, 0.0, -10.0); - gfx::Transform translation_to_back; - translation_to_front.Translate3d(0.0, 0.0, -100.0); - - typename Types::ContentLayerType* parent = this->CreateRoot( - this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); - typename Types::ContentLayerType* child1 = this->CreateDrawingLayer( - parent, translation_to_back, gfx::PointF(), gfx::Size(100, 100), true); - typename Types::ContentLayerType* child2 = - this->CreateDrawingLayer(parent, - translation_to_front, - gfx::PointF(50.f, 50.f), - gfx::Size(100, 100), - true); - parent->SetShouldFlattenTransform(false); - parent->Set3dSortingContextId(1); - child1->Set3dSortingContextId(1); - child2->Set3dSortingContextId(1); - - this->CalcDrawEtc(parent); - - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); - this->VisitLayer(child2, &occlusion); - EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); - EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); - - this->VisitLayer(child1, &occlusion); - EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); - EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); - } -}; - -// This test will have different layer ordering on the impl thread; the test -// will only work on the main thread. -MAIN_THREAD_TEST(OcclusionTrackerTestUnsorted3dLayers); +ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOpaqueContentsRegionNonEmpty); -template <class Types> class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestLayerBehindCameraDoesNotOcclude( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform transform; transform.Translate(50.0, 50.0); @@ -1519,9 +1180,9 @@ class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude transform.Translate3d(0.0, 0.0, 110.0); transform.Translate(-50.0, -50.0); - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); - typename Types::ContentLayerType* layer = this->CreateDrawingLayer( + TestContentLayerImpl* layer = this->CreateDrawingLayer( parent, transform, gfx::PointF(), gfx::Size(100, 100), true); parent->SetShouldFlattenTransform(false); parent->Set3dSortingContextId(1); @@ -1529,8 +1190,7 @@ class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude layer->Set3dSortingContextId(1); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); // The |layer| is entirely behind the camera and should not occlude. this->VisitLayer(layer, &occlusion); @@ -1540,394 +1200,30 @@ class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude } }; -template <class Types> -class OcclusionTrackerTestAnimationOpacity1OnMainThread - : public OcclusionTrackerTest<Types> { - protected: - explicit OcclusionTrackerTestAnimationOpacity1OnMainThread(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} - void RunMyTest() override { - // parent - // +--layer - // +--surface - // | +--surface_child - // | +--surface_child2 - // +--parent2 - // +--topmost - - typename Types::ContentLayerType* parent = this->CreateRoot( - this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); - typename Types::ContentLayerType* layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(300, 300), - true); - typename Types::ContentLayerType* surface = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(300, 300), - true); - typename Types::ContentLayerType* surface_child = - this->CreateDrawingLayer(surface, - this->identity_matrix, - gfx::PointF(), - gfx::Size(200, 300), - true); - typename Types::ContentLayerType* surface_child2 = - this->CreateDrawingLayer(surface, - this->identity_matrix, - gfx::PointF(), - gfx::Size(100, 300), - true); - typename Types::ContentLayerType* parent2 = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(300, 300), - false); - typename Types::ContentLayerType* topmost = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(250.f, 0.f), - gfx::Size(50, 300), - true); - - AddOpacityTransitionToController( - layer->layer_animation_controller(), 10.0, 0.f, 1.f, false); - AddOpacityTransitionToController( - surface->layer_animation_controller(), 10.0, 0.f, 1.f, false); - this->CalcDrawEtc(parent); - - EXPECT_TRUE(layer->draw_opacity_is_animating()); - EXPECT_FALSE(surface->draw_opacity_is_animating()); - EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating()); - - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); - - this->VisitLayer(topmost, &occlusion); - this->EnterLayer(parent2, &occlusion); - - // This occlusion will affect all surfaces. - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->LeaveLayer(parent2, &occlusion); - this->VisitLayer(surface_child2, &occlusion); - this->EnterLayer(surface_child, &occlusion); - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->LeaveLayer(surface_child, &occlusion); - this->EnterLayer(surface, &occlusion); - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->LeaveLayer(surface, &occlusion); - this->EnterContributingSurface(surface, &occlusion); - // Occlusion within the surface is lost when leaving the animating surface. - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->LeaveContributingSurface(surface, &occlusion); - // Occlusion from outside the animating surface still exists. - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - - this->VisitLayer(layer, &occlusion); - this->EnterLayer(parent, &occlusion); - - // Occlusion is not added for the animating |layer|. - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - } -}; - -MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity1OnMainThread); - -template <class Types> -class OcclusionTrackerTestAnimationOpacity0OnMainThread - : public OcclusionTrackerTest<Types> { - protected: - explicit OcclusionTrackerTestAnimationOpacity0OnMainThread(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} - void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( - this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); - typename Types::ContentLayerType* layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(300, 300), - true); - typename Types::ContentLayerType* surface = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(300, 300), - true); - typename Types::ContentLayerType* surface_child = - this->CreateDrawingLayer(surface, - this->identity_matrix, - gfx::PointF(), - gfx::Size(200, 300), - true); - typename Types::ContentLayerType* surface_child2 = - this->CreateDrawingLayer(surface, - this->identity_matrix, - gfx::PointF(), - gfx::Size(100, 300), - true); - typename Types::ContentLayerType* parent2 = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(300, 300), - false); - typename Types::ContentLayerType* topmost = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(250.f, 0.f), - gfx::Size(50, 300), - true); - - AddOpacityTransitionToController( - layer->layer_animation_controller(), 10.0, 1.f, 0.f, false); - AddOpacityTransitionToController( - surface->layer_animation_controller(), 10.0, 1.f, 0.f, false); - this->CalcDrawEtc(parent); - - EXPECT_TRUE(layer->draw_opacity_is_animating()); - EXPECT_FALSE(surface->draw_opacity_is_animating()); - EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating()); - - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); - - this->VisitLayer(topmost, &occlusion); - this->EnterLayer(parent2, &occlusion); - // This occlusion will affect all surfaces. - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - - this->LeaveLayer(parent2, &occlusion); - this->VisitLayer(surface_child2, &occlusion); - this->EnterLayer(surface_child, &occlusion); - EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_outside_target().ToString()); - - this->LeaveLayer(surface_child, &occlusion); - this->EnterLayer(surface, &occlusion); - EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_outside_target().ToString()); - - this->LeaveLayer(surface, &occlusion); - this->EnterContributingSurface(surface, &occlusion); - // Occlusion within the surface is lost when leaving the animating surface. - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - - this->LeaveContributingSurface(surface, &occlusion); - // Occlusion from outside the animating surface still exists. - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - - this->VisitLayer(layer, &occlusion); - this->EnterLayer(parent, &occlusion); - - // Occlusion is not added for the animating |layer|. - EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - } -}; - -MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity0OnMainThread); - -template <class Types> -class OcclusionTrackerTestAnimationTranslateOnMainThread - : public OcclusionTrackerTest<Types> { - protected: - explicit OcclusionTrackerTestAnimationTranslateOnMainThread( - bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} - void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( - this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); - typename Types::ContentLayerType* layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(300, 300), - true); - typename Types::ContentLayerType* surface = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(300, 300), - true); - typename Types::ContentLayerType* surface_child = - this->CreateDrawingLayer(surface, - this->identity_matrix, - gfx::PointF(), - gfx::Size(200, 300), - true); - typename Types::ContentLayerType* surface_child2 = - this->CreateDrawingLayer(surface, - this->identity_matrix, - gfx::PointF(), - gfx::Size(100, 300), - true); - typename Types::ContentLayerType* surface2 = this->CreateDrawingSurface( - parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 300), true); - - AddAnimatedTransformToController( - layer->layer_animation_controller(), 10.0, 30, 0); - AddAnimatedTransformToController( - surface->layer_animation_controller(), 10.0, 30, 0); - AddAnimatedTransformToController( - surface_child->layer_animation_controller(), 10.0, 30, 0); - this->CalcDrawEtc(parent); - - EXPECT_TRUE(layer->draw_transform_is_animating()); - EXPECT_TRUE(layer->screen_space_transform_is_animating()); - EXPECT_TRUE( - surface->render_surface()->target_surface_transforms_are_animating()); - EXPECT_TRUE( - surface->render_surface()->screen_space_transforms_are_animating()); - // The surface owning layer doesn't animate against its own surface. - EXPECT_FALSE(surface->draw_transform_is_animating()); - EXPECT_TRUE(surface->screen_space_transform_is_animating()); - EXPECT_TRUE(surface_child->draw_transform_is_animating()); - EXPECT_TRUE(surface_child->screen_space_transform_is_animating()); - - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); - - this->VisitLayer(surface2, &occlusion); - this->EnterContributingSurface(surface2, &occlusion); - - EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->LeaveContributingSurface(surface2, &occlusion); - this->EnterLayer(surface_child2, &occlusion); - // surface_child2 is moving in screen space but not relative to its target, - // so occlusion should happen in its target space only. It also means that - // things occluding from outside the target (e.g. surface2) cannot occlude - // this layer. - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->LeaveLayer(surface_child2, &occlusion); - this->EnterLayer(surface_child, &occlusion); - // surface_child2 added to the occlusion since it is not moving relative - // to its target. - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->LeaveLayer(surface_child, &occlusion); - // surface_child is moving relative to its target, so it does not add - // occlusion. - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->EnterLayer(surface, &occlusion); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->LeaveLayer(surface, &occlusion); - // The surface's owning layer is moving in screen space but not relative to - // its target, so it adds to the occlusion. - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(0, 0, 300, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->EnterContributingSurface(surface, &occlusion); - this->LeaveContributingSurface(surface, &occlusion); - // The |surface| is moving in the screen and in its target, so all occlusion - // within the surface is lost when leaving it. Only the |surface2| occlusion - // is left. - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - - this->VisitLayer(layer, &occlusion); - // The |layer| is animating in the screen and in its target, so no occlusion - // is added. - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - } -}; - -MAIN_THREAD_TEST(OcclusionTrackerTestAnimationTranslateOnMainThread); - -template <class Types> class OcclusionTrackerTestSurfaceOcclusionTranslatesToParent - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestSurfaceOcclusionTranslatesToParent( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform surface_transform; surface_transform.Translate(300.0, 300.0); surface_transform.Scale(2.0, 2.0); surface_transform.Translate(-150.0, -150.0); - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(500, 500)); - typename Types::ContentLayerType* surface = this->CreateDrawingSurface( + TestContentLayerImpl* surface = this->CreateDrawingSurface( parent, surface_transform, gfx::PointF(), gfx::Size(300, 300), false); - typename Types::ContentLayerType* surface2 = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(50.f, 50.f), - gfx::Size(300, 300), - false); + TestContentLayerImpl* surface2 = this->CreateDrawingSurface( + parent, this->identity_matrix, gfx::PointF(50.f, 50.f), + gfx::Size(300, 300), false); surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200)); surface2->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200)); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(surface2, &occlusion); this->VisitContributingSurface(surface2, &occlusion); @@ -1951,31 +1247,26 @@ class OcclusionTrackerTestSurfaceOcclusionTranslatesToParent } }; -MAIN_AND_IMPL_THREAD_TEST( +ALL_OCCLUSIONTRACKER_TEST( OcclusionTrackerTestSurfaceOcclusionTranslatesToParent); -template <class Types> class OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); parent->SetMasksToBounds(true); - typename Types::ContentLayerType* surface = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(500, 300), - false); + TestContentLayerImpl* surface = + this->CreateDrawingSurface(parent, this->identity_matrix, gfx::PointF(), + gfx::Size(500, 300), false); surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 400, 200)); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(surface, &occlusion); this->VisitContributingSurface(surface, &occlusion); @@ -1987,38 +1278,30 @@ class OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping } }; -MAIN_AND_IMPL_THREAD_TEST( +ALL_OCCLUSIONTRACKER_TEST( OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping); -template <class Types> class OcclusionTrackerTestSurfaceWithReplicaUnoccluded - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestSurfaceWithReplicaUnoccluded(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); - typename Types::LayerType* surface = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(100, 100), - true); + LayerImpl* surface = + this->CreateDrawingSurface(parent, this->identity_matrix, gfx::PointF(), + gfx::Size(100, 100), true); this->CreateReplicaLayer(surface, this->identity_matrix, gfx::PointF(0.f, 100.f), gfx::Size(100, 100)); - typename Types::LayerType* topmost = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(100, 110), - true); + LayerImpl* topmost = + this->CreateDrawingLayer(parent, this->identity_matrix, gfx::PointF(), + gfx::Size(100, 110), true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); // |topmost| occludes the surface, but not the entire surface's replica. this->VisitLayer(topmost, &occlusion); @@ -2050,36 +1333,27 @@ class OcclusionTrackerTestSurfaceWithReplicaUnoccluded ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithReplicaUnoccluded); -template <class Types> -class OcclusionTrackerTestSurfaceChildOfSurface - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestSurfaceChildOfSurface : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestSurfaceChildOfSurface(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { // This test verifies that the surface cliprect does not end up empty and // clip away the entire unoccluded rect. - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); - typename Types::LayerType* surface = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(), - gfx::Size(100, 100), - false); - typename Types::LayerType* surface_child = - this->CreateDrawingSurface(surface, - this->identity_matrix, - gfx::PointF(0.f, 10.f), - gfx::Size(100, 50), - true); - typename Types::LayerType* topmost = this->CreateDrawingLayer( + LayerImpl* surface = + this->CreateDrawingSurface(parent, this->identity_matrix, gfx::PointF(), + gfx::Size(100, 100), false); + LayerImpl* surface_child = this->CreateDrawingSurface( + surface, this->identity_matrix, gfx::PointF(0.f, 10.f), + gfx::Size(100, 50), true); + LayerImpl* topmost = this->CreateDrawingLayer( parent, this->identity_matrix, gfx::PointF(), gfx::Size(100, 50), true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(-100, -100, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(-100, -100, 1000, 1000)); // |topmost| occludes everything partially so we know occlusion is happening // at all. @@ -2147,13 +1421,12 @@ class OcclusionTrackerTestSurfaceChildOfSurface ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfSurface); -template <class Types> class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform scale_by_half; scale_by_half.Scale(0.5, 0.5); @@ -2181,15 +1454,12 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter // which are above it in the z-order in various configurations. The // surface is scaled to test that the pixel moving is done in the target // space, where the background filter is applied. - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); - typename Types::LayerType* filtered_surface = - this->CreateDrawingLayer(parent, - scale_by_half, - gfx::PointF(50.f, 50.f), - gfx::Size(100, 100), - false); - Types::SetForceRenderSurface(filtered_surface, true); + LayerImpl* filtered_surface = this->CreateDrawingLayer( + parent, scale_by_half, gfx::PointF(50.f, 50.f), gfx::Size(100, 100), + false); + filtered_surface->SetHasRenderSurface(true); filtered_surface->SetBackgroundFilters(filters); gfx::Rect occlusion_rect; switch (i) { @@ -2207,16 +1477,12 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter break; } - typename Types::LayerType* occluding_layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - occlusion_rect.origin(), - occlusion_rect.size(), - true); + LayerImpl* occluding_layer = this->CreateDrawingLayer( + parent, this->identity_matrix, occlusion_rect.origin(), + occlusion_rect.size(), true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 200, 200)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 200, 200)); // This layer occludes pixels directly beside the filtered_surface. // Because filtered surface blends pixels in a radius, it will need to see @@ -2271,38 +1537,34 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter ALL_OCCLUSIONTRACKER_TEST( OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter); -template <class Types> class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform scale_by_half; scale_by_half.Scale(0.5, 0.5); // Makes two surfaces that completely cover |parent|. The occlusion both // above and below the filters will be reduced by each of them. - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(75, 75)); - typename Types::LayerType* parent = this->CreateSurface( - root, scale_by_half, gfx::PointF(), gfx::Size(150, 150)); + LayerImpl* parent = this->CreateSurface(root, scale_by_half, gfx::PointF(), + gfx::Size(150, 150)); parent->SetMasksToBounds(true); - typename Types::LayerType* filtered_surface1 = this->CreateDrawingLayer( + LayerImpl* filtered_surface1 = this->CreateDrawingLayer( parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false); - typename Types::LayerType* filtered_surface2 = this->CreateDrawingLayer( + LayerImpl* filtered_surface2 = this->CreateDrawingLayer( parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false); - typename Types::LayerType* occluding_layer_above = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(100.f, 100.f), - gfx::Size(50, 50), - true); + LayerImpl* occluding_layer_above = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(100.f, 100.f), + gfx::Size(50, 50), true); // Filters make the layers own surfaces. - Types::SetForceRenderSurface(filtered_surface1, true); - Types::SetForceRenderSurface(filtered_surface2, true); + filtered_surface1->SetHasRenderSurface(true); + filtered_surface2->SetHasRenderSurface(true); FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter(1.f)); filtered_surface1->SetBackgroundFilters(filters); @@ -2315,8 +1577,7 @@ class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(occluding_layer_above, &occlusion); EXPECT_EQ(gfx::Rect().ToString(), @@ -2348,13 +1609,12 @@ class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice ALL_OCCLUSIONTRACKER_TEST( OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice); -template <class Types> class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform scale_by_half; scale_by_half.Scale(0.5, 0.5); @@ -2363,41 +1623,31 @@ class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter // centered below each. The surface is scaled to test that the pixel moving // is done in the target space, where the background filter is applied, but // the surface appears at 50, 50 and the replica at 200, 50. - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(300, 150)); - typename Types::LayerType* behind_surface_layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(60.f, 60.f), - gfx::Size(30, 30), - true); - typename Types::LayerType* behind_replica_layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(210.f, 60.f), - gfx::Size(30, 30), - true); - typename Types::LayerType* filtered_surface = - this->CreateDrawingLayer(parent, - scale_by_half, - gfx::PointF(50.f, 50.f), - gfx::Size(100, 100), - false); + LayerImpl* behind_surface_layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(60.f, 60.f), + gfx::Size(30, 30), true); + LayerImpl* behind_replica_layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(210.f, 60.f), + gfx::Size(30, 30), true); + LayerImpl* filtered_surface = + this->CreateDrawingLayer(parent, scale_by_half, gfx::PointF(50.f, 50.f), + gfx::Size(100, 100), false); this->CreateReplicaLayer(filtered_surface, this->identity_matrix, gfx::PointF(300.f, 0.f), gfx::Size()); // Filters make the layer own a surface. - Types::SetForceRenderSurface(filtered_surface, true); + filtered_surface->SetHasRenderSurface(true); FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter(3.f)); filtered_surface->SetBackgroundFilters(filters); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); // The surface has a background blur, so it blurs non-opaque pixels below // it. @@ -2433,13 +1683,12 @@ class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter ALL_OCCLUSIONTRACKER_TEST( OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter); -template <class Types> class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform scale_by_half; scale_by_half.Scale(0.5, 0.5); @@ -2448,31 +1697,24 @@ class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded // layer which is above it in the z-order. The surface is // scaled to test that the pixel moving is done in the target space, where // the background filter is applied, but the surface appears at 50, 50. - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(200, 150)); - typename Types::LayerType* filtered_surface = - this->CreateDrawingLayer(parent, - scale_by_half, - gfx::PointF(50.f, 50.f), - gfx::Size(100, 100), - false); - typename Types::LayerType* occluding_layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(50.f, 50.f), - gfx::Size(50, 50), - true); + LayerImpl* filtered_surface = + this->CreateDrawingLayer(parent, scale_by_half, gfx::PointF(50.f, 50.f), + gfx::Size(100, 100), false); + LayerImpl* occluding_layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(50.f, 50.f), + gfx::Size(50, 50), true); // Filters make the layer own a surface. - Types::SetForceRenderSurface(filtered_surface, true); + filtered_surface->SetHasRenderSurface(true); FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter(3.f)); filtered_surface->SetBackgroundFilters(filters); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(occluding_layer, &occlusion); @@ -2506,14 +1748,12 @@ class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded ALL_OCCLUSIONTRACKER_TEST( OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded); -template <class Types> -class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded + : public OcclusionTrackerTest { protected: - explicit - OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded( + explicit OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform scale_by_half; scale_by_half.Scale(0.5, 0.5); @@ -2523,45 +1763,30 @@ class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded // scaled to test that the pixel moving is done in the target space, where // the background filter is applied, but the surface appears at 50, 50 and // the replica at 200, 50. - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(300, 150)); - typename Types::LayerType* filtered_surface = - this->CreateDrawingLayer(parent, - scale_by_half, - gfx::PointF(50.f, 50.f), - gfx::Size(100, 100), - false); + LayerImpl* filtered_surface = + this->CreateDrawingLayer(parent, scale_by_half, gfx::PointF(50.f, 50.f), + gfx::Size(100, 100), false); this->CreateReplicaLayer(filtered_surface, this->identity_matrix, gfx::PointF(300.f, 0.f), gfx::Size()); - typename Types::LayerType* above_surface_layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(70.f, 50.f), - gfx::Size(30, 50), - true); - typename Types::LayerType* above_replica_layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(200.f, 50.f), - gfx::Size(30, 50), - true); - typename Types::LayerType* beside_surface_layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(90.f, 40.f), - gfx::Size(10, 10), - true); - typename Types::LayerType* beside_replica_layer = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(200.f, 40.f), - gfx::Size(10, 10), - true); + LayerImpl* above_surface_layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(70.f, 50.f), + gfx::Size(30, 50), true); + LayerImpl* above_replica_layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(200.f, 50.f), + gfx::Size(30, 50), true); + LayerImpl* beside_surface_layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(90.f, 40.f), + gfx::Size(10, 10), true); + LayerImpl* beside_replica_layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(200.f, 40.f), + gfx::Size(10, 10), true); // Filters make the layer own a surface. - Types::SetForceRenderSurface(filtered_surface, true); + filtered_surface->SetHasRenderSurface(true); FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter(3.f)); filtered_surface->SetBackgroundFilters(filters); @@ -2573,8 +1798,7 @@ class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(beside_replica_layer, &occlusion); this->VisitLayer(beside_surface_layer, &occlusion); @@ -2619,32 +1843,30 @@ class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded }; ALL_OCCLUSIONTRACKER_TEST( - OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded); + OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded); -template <class Types> class OcclusionTrackerTestBlendModeDoesNotOcclude - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestBlendModeDoesNotOcclude(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); - typename Types::LayerType* blend_mode_layer = this->CreateDrawingLayer( + LayerImpl* blend_mode_layer = this->CreateDrawingLayer( parent, this->identity_matrix, gfx::PointF(0.f, 0.f), gfx::Size(100, 100), true); - typename Types::LayerType* top_layer = this->CreateDrawingLayer( + LayerImpl* top_layer = this->CreateDrawingLayer( parent, this->identity_matrix, gfx::PointF(10.f, 12.f), gfx::Size(20, 22), true); // Blend mode makes the layer own a surface. - Types::SetForceRenderSurface(blend_mode_layer, true); + blend_mode_layer->SetHasRenderSurface(true); blend_mode_layer->SetBlendMode(SkXfermode::kMultiply_Mode); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(top_layer, &occlusion); // |top_layer| occludes. @@ -2668,30 +1890,24 @@ class OcclusionTrackerTestBlendModeDoesNotOcclude ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestBlendModeDoesNotOcclude); -template <class Types> -class OcclusionTrackerTestMinimumTrackingSize - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestMinimumTrackingSize : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestMinimumTrackingSize(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Size tracking_size(100, 100); gfx::Size below_tracking_size(99, 99); - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(400, 400)); - typename Types::LayerType* large = this->CreateDrawingLayer( + LayerImpl* large = this->CreateDrawingLayer( parent, this->identity_matrix, gfx::PointF(), tracking_size, true); - typename Types::LayerType* small = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(), - below_tracking_size, - true); + LayerImpl* small = + this->CreateDrawingLayer(parent, this->identity_matrix, gfx::PointF(), + below_tracking_size, true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); occlusion.set_minimum_tracking_size(tracking_size); // The small layer is not tracked because it is too small. @@ -2714,31 +1930,27 @@ class OcclusionTrackerTestMinimumTrackingSize ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestMinimumTrackingSize); -template <class Types> -class OcclusionTrackerTestScaledLayerIsClipped - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestScaledLayerIsClipped : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestScaledLayerIsClipped(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform scale_transform; scale_transform.Scale(512.0, 512.0); - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(400, 400)); - typename Types::LayerType* clip = this->CreateLayer(parent, - this->identity_matrix, - gfx::PointF(10.f, 10.f), - gfx::Size(50, 50)); + LayerImpl* clip = + this->CreateLayer(parent, this->identity_matrix, + gfx::PointF(10.f, 10.f), gfx::Size(50, 50)); clip->SetMasksToBounds(true); - typename Types::LayerType* scale = this->CreateLayer( - clip, scale_transform, gfx::PointF(), gfx::Size(1, 1)); - typename Types::LayerType* scaled = this->CreateDrawingLayer( + LayerImpl* scale = this->CreateLayer(clip, scale_transform, gfx::PointF(), + gfx::Size(1, 1)); + LayerImpl* scaled = this->CreateDrawingLayer( scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(scaled, &occlusion); @@ -2751,33 +1963,30 @@ class OcclusionTrackerTestScaledLayerIsClipped ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerIsClipped) -template <class Types> class OcclusionTrackerTestScaledLayerInSurfaceIsClipped - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestScaledLayerInSurfaceIsClipped(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform scale_transform; scale_transform.Scale(512.0, 512.0); - typename Types::ContentLayerType* parent = this->CreateRoot( + TestContentLayerImpl* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(400, 400)); - typename Types::LayerType* clip = this->CreateLayer(parent, - this->identity_matrix, - gfx::PointF(10.f, 10.f), - gfx::Size(50, 50)); + LayerImpl* clip = + this->CreateLayer(parent, this->identity_matrix, + gfx::PointF(10.f, 10.f), gfx::Size(50, 50)); clip->SetMasksToBounds(true); - typename Types::LayerType* surface = this->CreateDrawingSurface( + LayerImpl* surface = this->CreateDrawingSurface( clip, this->identity_matrix, gfx::PointF(), gfx::Size(400, 30), false); - typename Types::LayerType* scale = this->CreateLayer( - surface, scale_transform, gfx::PointF(), gfx::Size(1, 1)); - typename Types::LayerType* scaled = this->CreateDrawingLayer( + LayerImpl* scale = this->CreateLayer(surface, scale_transform, + gfx::PointF(), gfx::Size(1, 1)); + LayerImpl* scaled = this->CreateDrawingLayer( scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true); this->CalcDrawEtc(parent); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(scaled, &occlusion); this->VisitLayer(surface, &occlusion); @@ -2792,35 +2001,26 @@ class OcclusionTrackerTestScaledLayerInSurfaceIsClipped ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerInSurfaceIsClipped) -template <class Types> -class OcclusionTrackerTestCopyRequestDoesOcclude - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestCopyRequestDoesOcclude : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestCopyRequestDoesOcclude(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::Point(), gfx::Size(400, 400)); - typename Types::ContentLayerType* parent = this->CreateDrawingLayer( + TestContentLayerImpl* parent = this->CreateDrawingLayer( root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true); - typename Types::LayerType* copy = this->CreateLayer(parent, - this->identity_matrix, - gfx::Point(100, 0), - gfx::Size(200, 400)); + LayerImpl* copy = this->CreateLayer( + parent, this->identity_matrix, gfx::Point(100, 0), gfx::Size(200, 400)); this->AddCopyRequest(copy); - typename Types::LayerType* copy_child = this->CreateDrawingLayer( - copy, - this->identity_matrix, - gfx::PointF(), - gfx::Size(200, 400), - true); - typename Types::LayerType* top_layer = + LayerImpl* copy_child = this->CreateDrawingLayer( + copy, this->identity_matrix, gfx::PointF(), gfx::Size(200, 400), true); + LayerImpl* top_layer = this->CreateDrawingLayer(root, this->identity_matrix, gfx::PointF(50, 0), gfx::Size(50, 400), true); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(top_layer, &occlusion); EXPECT_EQ(gfx::Rect().ToString(), @@ -2848,24 +2048,23 @@ class OcclusionTrackerTestCopyRequestDoesOcclude ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestCopyRequestDoesOcclude) -template <class Types> class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude - : public OcclusionTrackerTest<Types> { + : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude( bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::Point(), gfx::Size(400, 400)); - typename Types::ContentLayerType* parent = this->CreateDrawingLayer( + TestContentLayerImpl* parent = this->CreateDrawingLayer( root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true); - typename Types::LayerType* hide = this->CreateLayer( - parent, this->identity_matrix, gfx::Point(), gfx::Size()); - typename Types::LayerType* copy = this->CreateLayer( + LayerImpl* hide = this->CreateLayer(parent, this->identity_matrix, + gfx::Point(), gfx::Size()); + LayerImpl* copy = this->CreateLayer( hide, this->identity_matrix, gfx::Point(100, 0), gfx::Size(200, 400)); this->AddCopyRequest(copy); - typename Types::LayerType* copy_child = this->CreateDrawingLayer( + LayerImpl* copy_child = this->CreateDrawingLayer( copy, this->identity_matrix, gfx::PointF(), gfx::Size(200, 400), true); // The |copy| layer is hidden but since it is being copied, it will be @@ -2874,8 +2073,7 @@ class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000)); this->VisitLayer(copy_child, &occlusion); EXPECT_EQ(gfx::Rect().ToString(), @@ -2896,26 +2094,24 @@ class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude) -template <class Types> -class OcclusionTrackerTestOccludedLayer : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestOccludedLayer : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestOccludedLayer(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform translate; translate.Translate(10.0, 20.0); - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::Point(), gfx::Size(200, 200)); - typename Types::LayerType* surface = this->CreateSurface( - root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200)); - typename Types::LayerType* layer = this->CreateDrawingLayer( + LayerImpl* surface = this->CreateSurface(root, this->identity_matrix, + gfx::Point(), gfx::Size(200, 200)); + LayerImpl* layer = this->CreateDrawingLayer( surface, translate, gfx::Point(), gfx::Size(200, 200), false); - typename Types::ContentLayerType* outside_layer = this->CreateDrawingLayer( + TestContentLayerImpl* outside_layer = this->CreateDrawingLayer( root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200), false); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 200, 200)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 200, 200)); this->VisitLayer(outside_layer, &occlusion); this->EnterLayer(layer, &occlusion); @@ -2986,27 +2182,24 @@ class OcclusionTrackerTestOccludedLayer : public OcclusionTrackerTest<Types> { ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOccludedLayer) -template <class Types> -class OcclusionTrackerTestUnoccludedLayerQuery - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestUnoccludedLayerQuery : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestUnoccludedLayerQuery(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform translate; translate.Translate(10.0, 20.0); - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::Point(), gfx::Size(200, 200)); - typename Types::LayerType* surface = this->CreateSurface( - root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200)); - typename Types::LayerType* layer = this->CreateDrawingLayer( + LayerImpl* surface = this->CreateSurface(root, this->identity_matrix, + gfx::Point(), gfx::Size(200, 200)); + LayerImpl* layer = this->CreateDrawingLayer( surface, translate, gfx::Point(), gfx::Size(200, 200), false); - typename Types::ContentLayerType* outside_layer = this->CreateDrawingLayer( + TestContentLayerImpl* outside_layer = this->CreateDrawingLayer( root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200), false); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 200, 200)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 200, 200)); this->VisitLayer(outside_layer, &occlusion); this->EnterLayer(layer, &occlusion); @@ -3152,31 +2345,25 @@ class OcclusionTrackerTestUnoccludedLayerQuery ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestUnoccludedLayerQuery) -template <class Types> -class OcclusionTrackerTestUnoccludedSurfaceQuery - : public OcclusionTrackerTest<Types> { +class OcclusionTrackerTestUnoccludedSurfaceQuery : public OcclusionTrackerTest { protected: explicit OcclusionTrackerTestUnoccludedSurfaceQuery(bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} + : OcclusionTrackerTest(opaque_layers) {} void RunMyTest() override { gfx::Transform translate; translate.Translate(10.0, 20.0); - typename Types::ContentLayerType* root = this->CreateRoot( + TestContentLayerImpl* root = this->CreateRoot( this->identity_matrix, gfx::Point(), gfx::Size(200, 200)); - typename Types::LayerType* surface = + LayerImpl* surface = this->CreateSurface(root, translate, gfx::Point(), gfx::Size(200, 200)); - typename Types::LayerType* layer = - this->CreateDrawingLayer(surface, - this->identity_matrix, - gfx::Point(), - gfx::Size(200, 200), - false); - typename Types::ContentLayerType* outside_layer = this->CreateDrawingLayer( + LayerImpl* layer = + this->CreateDrawingLayer(surface, this->identity_matrix, gfx::Point(), + gfx::Size(200, 200), false); + TestContentLayerImpl* outside_layer = this->CreateDrawingLayer( root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200), false); this->CalcDrawEtc(root); - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 200, 200)); + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 200, 200)); this->VisitLayer(outside_layer, &occlusion); this->VisitLayer(layer, &occlusion); this->EnterContributingSurface(surface, &occlusion); diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc index d369ad91060..05fa3947f0c 100644 --- a/chromium/cc/trees/property_tree.cc +++ b/chromium/cc/trees/property_tree.cc @@ -23,6 +23,12 @@ template <typename T> PropertyTree<T>::~PropertyTree() { } +TransformTree::TransformTree() : source_to_parent_updates_allowed_(true) { +} + +TransformTree::~TransformTree() { +} + template <typename T> int PropertyTree<T>::Insert(const T& tree_node, int parent_id) { DCHECK_GT(nodes_.size(), 0u); @@ -56,9 +62,15 @@ TransformNodeData::TransformNodeData() to_screen_is_animated(false), flattens_inherited_transform(false), node_and_ancestors_are_flat(true), + node_and_ancestors_have_only_integer_translation(true), scrolls(false), needs_sublayer_scale(false), - layer_scale_factor(1.0f) { + affected_by_inner_viewport_bounds_delta_x(false), + affected_by_inner_viewport_bounds_delta_y(false), + affected_by_outer_viewport_bounds_delta_x(false), + affected_by_outer_viewport_bounds_delta_y(false), + layer_scale_factor(1.0f), + post_local_scale_factor(1.0f) { } TransformNodeData::~TransformNodeData() { @@ -85,6 +97,16 @@ void TransformNodeData::update_post_local_transform( ClipNodeData::ClipNodeData() : transform_id(-1), target_id(-1) { } +OpacityNodeData::OpacityNodeData() : opacity(1.f), screen_space_opacity(1.f) { +} + +void TransformTree::clear() { + PropertyTree<TransformNode>::clear(); + + nodes_affected_by_inner_viewport_bounds_delta_.clear(); + nodes_affected_by_outer_viewport_bounds_delta_.clear(); +} + bool TransformTree::ComputeTransform(int source_id, int dest_id, gfx::Transform* transform) const { @@ -136,18 +158,24 @@ bool TransformTree::Are2DAxisAligned(int source_id, int dest_id) const { transform.Preserves2dAxisAlignment(); } +bool TransformTree::NeedsSourceToParentUpdate(TransformNode* node) { + return (source_to_parent_updates_allowed() && + node->parent_id != node->data.source_node_id); +} + void TransformTree::UpdateTransforms(int id) { TransformNode* node = Node(id); TransformNode* parent_node = parent(node); TransformNode* target_node = Node(node->data.target_id); if (node->data.needs_local_transform_update || - node->parent_id != node->data.source_node_id) + NeedsSourceToParentUpdate(node)) UpdateLocalTransform(node); UpdateScreenSpaceTransform(node, parent_node, target_node); UpdateSublayerScale(node); UpdateTargetSpaceTransform(node, target_node); UpdateIsAnimated(node, parent_node); UpdateSnapping(node); + UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node); } bool TransformTree::IsDescendant(int desc_id, int source_id) const { @@ -188,12 +216,21 @@ bool TransformTree::CombineTransformsBetween(int source_id, // path from the source to the destination (this is traversing upward), and // then we visit these nodes in reverse order, flattening as needed. We // early-out if we get to a node whose target node is the destination, since - // we can then re-use the target space transform stored at that node. + // we can then re-use the target space transform stored at that node. However, + // we cannot re-use a stored target space transform if the destination has a + // zero sublayer scale, since stored target space transforms have sublayer + // scale baked in, but we need to compute an unscaled transform. std::vector<int> source_to_destination; source_to_destination.push_back(current->id); current = parent(current); + bool destination_has_non_zero_sublayer_scale = + dest->data.sublayer_scale.x() != 0.f && + dest->data.sublayer_scale.y() != 0.f; + DCHECK(destination_has_non_zero_sublayer_scale || + !dest->data.ancestors_are_invertible); for (; current && current->id > dest_id; current = parent(current)) { - if (current->data.target_id == dest_id && + if (destination_has_non_zero_sublayer_scale && + current->data.target_id == dest_id && current->data.content_target_id == dest_id) break; source_to_destination.push_back(current->id); @@ -230,8 +267,10 @@ bool TransformTree::CombineTransformsBetween(int source_id, SkDoubleToMScalar(1e-4))); } - for (int i = source_to_destination.size() - 1; i >= 0; i--) { - const TransformNode* node = Node(source_to_destination[i]); + size_t source_to_destination_size = source_to_destination.size(); + for (size_t i = 0; i < source_to_destination_size; ++i) { + size_t index = source_to_destination_size - 1 - i; + const TransformNode* node = Node(source_to_destination[index]); if (node->data.flattens_inherited_transform) combined_transform.FlattenTo2d(); combined_transform.PreconcatTransform(node->data.to_parent); @@ -273,14 +312,28 @@ bool TransformTree::CombineInversesBetween(int source_id, void TransformTree::UpdateLocalTransform(TransformNode* node) { gfx::Transform transform = node->data.post_local; - gfx::Vector2dF source_to_parent; - if (node->parent_id != node->data.source_node_id) { + if (NeedsSourceToParentUpdate(node)) { gfx::Transform to_parent; ComputeTransform(node->data.source_node_id, node->parent_id, &to_parent); - source_to_parent = to_parent.To2dTranslation(); + node->data.source_to_parent = to_parent.To2dTranslation(); } - transform.Translate(source_to_parent.x() - node->data.scroll_offset.x(), - source_to_parent.y() - node->data.scroll_offset.y()); + + gfx::Vector2dF fixed_position_adjustment; + if (node->data.affected_by_inner_viewport_bounds_delta_x) + fixed_position_adjustment.set_x(inner_viewport_bounds_delta_.x()); + else if (node->data.affected_by_outer_viewport_bounds_delta_x) + fixed_position_adjustment.set_x(outer_viewport_bounds_delta_.x()); + + if (node->data.affected_by_inner_viewport_bounds_delta_y) + fixed_position_adjustment.set_y(inner_viewport_bounds_delta_.y()); + else if (node->data.affected_by_outer_viewport_bounds_delta_y) + fixed_position_adjustment.set_y(outer_viewport_bounds_delta_.y()); + + transform.Translate( + node->data.source_to_parent.x() - node->data.scroll_offset.x() + + fixed_position_adjustment.x(), + node->data.source_to_parent.y() - node->data.scroll_offset.y() + + fixed_position_adjustment.y()); transform.PreconcatTransform(node->data.local); transform.PreconcatTransform(node->data.pre_local); node->data.set_to_parent(transform); @@ -382,6 +435,70 @@ void TransformTree::UpdateSnapping(TransformNode* node) { node->data.scroll_snap = translation; } +void TransformTree::SetInnerViewportBoundsDelta(gfx::Vector2dF bounds_delta) { + if (inner_viewport_bounds_delta_ == bounds_delta) + return; + + inner_viewport_bounds_delta_ = bounds_delta; + + if (nodes_affected_by_inner_viewport_bounds_delta_.empty()) + return; + + set_needs_update(true); + for (int i : nodes_affected_by_inner_viewport_bounds_delta_) + Node(i)->data.needs_local_transform_update = true; +} + +void TransformTree::SetOuterViewportBoundsDelta(gfx::Vector2dF bounds_delta) { + if (outer_viewport_bounds_delta_ == bounds_delta) + return; + + outer_viewport_bounds_delta_ = bounds_delta; + + if (nodes_affected_by_outer_viewport_bounds_delta_.empty()) + return; + + set_needs_update(true); + for (int i : nodes_affected_by_outer_viewport_bounds_delta_) + Node(i)->data.needs_local_transform_update = true; +} + +void TransformTree::AddNodeAffectedByInnerViewportBoundsDelta(int node_id) { + nodes_affected_by_inner_viewport_bounds_delta_.push_back(node_id); +} + +void TransformTree::AddNodeAffectedByOuterViewportBoundsDelta(int node_id) { + nodes_affected_by_outer_viewport_bounds_delta_.push_back(node_id); +} + +bool TransformTree::HasNodesAffectedByInnerViewportBoundsDelta() const { + return !nodes_affected_by_inner_viewport_bounds_delta_.empty(); +} + +bool TransformTree::HasNodesAffectedByOuterViewportBoundsDelta() const { + return !nodes_affected_by_outer_viewport_bounds_delta_.empty(); +} + +void OpacityTree::UpdateOpacities(int id) { + OpacityNode* node = Node(id); + node->data.screen_space_opacity = node->data.opacity; + + OpacityNode* parent_node = parent(node); + if (parent_node) + node->data.screen_space_opacity *= parent_node->data.screen_space_opacity; +} + +void TransformTree::UpdateNodeAndAncestorsHaveIntegerTranslations( + TransformNode* node, + TransformNode* parent_node) { + node->data.node_and_ancestors_have_only_integer_translation = + node->data.to_parent.IsIdentityOrIntegerTranslation(); + if (parent_node) + node->data.node_and_ancestors_have_only_integer_translation = + node->data.node_and_ancestors_have_only_integer_translation && + parent_node->data.node_and_ancestors_have_only_integer_translation; +} + PropertyTrees::PropertyTrees() : needs_rebuild(true), sequence_number(0) { } diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h index caa819c6c6d..0ec77bc5bbe 100644 --- a/chromium/cc/trees/property_tree.h +++ b/chromium/cc/trees/property_tree.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "cc/base/cc_export.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/transform.h" namespace cc { @@ -67,25 +68,36 @@ struct CC_EXPORT TransformNodeData { int source_node_id; // TODO(vollick): will be moved when accelerated effects are implemented. - bool needs_local_transform_update; + bool needs_local_transform_update : 1; - bool is_invertible; - bool ancestors_are_invertible; + bool is_invertible : 1; + bool ancestors_are_invertible : 1; - bool is_animated; - bool to_screen_is_animated; + bool is_animated : 1; + bool to_screen_is_animated : 1; // Flattening, when needed, is only applied to a node's inherited transform, // never to its local transform. - bool flattens_inherited_transform; + bool flattens_inherited_transform : 1; // This is true if the to_parent transform at every node on the path to the // root is flat. - bool node_and_ancestors_are_flat; + bool node_and_ancestors_are_flat : 1; - bool scrolls; + // This is needed to know if a layer can use lcd text. + bool node_and_ancestors_have_only_integer_translation : 1; + + bool scrolls : 1; + + bool needs_sublayer_scale : 1; + + // These are used to position nodes wrt the right or bottom of the inner or + // outer viewport. + bool affected_by_inner_viewport_bounds_delta_x : 1; + bool affected_by_inner_viewport_bounds_delta_y : 1; + bool affected_by_outer_viewport_bounds_delta_x : 1; + bool affected_by_outer_viewport_bounds_delta_y : 1; - bool needs_sublayer_scale; // This is used as a fallback when we either cannot adjust raster scale or if // the raster scale cannot be extracted from the screen space transform. float layer_scale_factor; @@ -96,7 +108,7 @@ struct CC_EXPORT TransformNodeData { gfx::Vector2dF sublayer_scale; // TODO(vollick): will be moved when accelerated effects are implemented. - gfx::Vector2dF scroll_offset; + gfx::ScrollOffset scroll_offset; // We scroll snap where possible, but this has an effect on scroll // compensation: the snap is yet more scrolling that must be compensated for. @@ -105,6 +117,7 @@ struct CC_EXPORT TransformNodeData { // TODO(vollick): will be moved when accelerated effects are implemented. gfx::Vector2dF source_offset; + gfx::Vector2dF source_to_parent; void set_to_parent(const gfx::Transform& transform) { to_parent = transform; @@ -130,7 +143,14 @@ struct CC_EXPORT ClipNodeData { typedef TreeNode<ClipNodeData> ClipNode; -typedef TreeNode<float> OpacityNode; +struct CC_EXPORT OpacityNodeData { + OpacityNodeData(); + + float opacity; + float screen_space_opacity; +}; + +typedef TreeNode<OpacityNodeData> OpacityNode; template <typename T> class CC_EXPORT PropertyTree { @@ -159,7 +179,7 @@ class CC_EXPORT PropertyTree { return size() ? &nodes_[nodes_.size() - 1] : nullptr; } - void clear(); + virtual void clear(); size_t size() const { return nodes_.size(); } void set_needs_update(bool needs_update) { needs_update_ = needs_update; } @@ -174,6 +194,11 @@ class CC_EXPORT PropertyTree { class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { public: + TransformTree(); + ~TransformTree() override; + + void clear() override; + // Computes the change of basis transform from node |source_id| to |dest_id|. // The function returns false iff the inverse of a singular transform was // used (and the result should, therefore, not be trusted). Transforms may @@ -211,6 +236,37 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { // Updates the parent, target, and screen space transforms and snapping. void UpdateTransforms(int id); + // A TransformNode's source_to_parent value is used to account for the fact + // that fixed-position layers are positioned by Blink wrt to their layer tree + // parent (their "source"), but are parented in the transform tree by their + // fixed-position container. This value needs to be updated on main-thread + // property trees (for position changes initiated by Blink), but not on the + // compositor thread (since the offset from a node corresponding to a + // fixed-position layer to its fixed-position container is unaffected by + // compositor-driven effects). + void set_source_to_parent_updates_allowed(bool allowed) { + source_to_parent_updates_allowed_ = allowed; + } + bool source_to_parent_updates_allowed() const { + return source_to_parent_updates_allowed_; + } + + void SetInnerViewportBoundsDelta(gfx::Vector2dF bounds_delta); + gfx::Vector2dF inner_viewport_bounds_delta() const { + return inner_viewport_bounds_delta_; + } + + void SetOuterViewportBoundsDelta(gfx::Vector2dF bounds_delta); + gfx::Vector2dF outer_viewport_bounds_delta() const { + return outer_viewport_bounds_delta_; + } + + void AddNodeAffectedByInnerViewportBoundsDelta(int node_id); + void AddNodeAffectedByOuterViewportBoundsDelta(int node_id); + + bool HasNodesAffectedByInnerViewportBoundsDelta() const; + bool HasNodesAffectedByOuterViewportBoundsDelta() const; + private: // Returns true iff the node at |desc_id| is a descendant of the node at // |anc_id|. @@ -239,11 +295,24 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { TransformNode* target_node); void UpdateIsAnimated(TransformNode* node, TransformNode* parent_node); void UpdateSnapping(TransformNode* node); + void UpdateNodeAndAncestorsHaveIntegerTranslations( + TransformNode* node, + TransformNode* parent_node); + bool NeedsSourceToParentUpdate(TransformNode* node); + + bool source_to_parent_updates_allowed_; + gfx::Vector2dF inner_viewport_bounds_delta_; + gfx::Vector2dF outer_viewport_bounds_delta_; + std::vector<int> nodes_affected_by_inner_viewport_bounds_delta_; + std::vector<int> nodes_affected_by_outer_viewport_bounds_delta_; }; class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> {}; -class CC_EXPORT OpacityTree final : public PropertyTree<OpacityNode> {}; +class CC_EXPORT OpacityTree final : public PropertyTree<OpacityNode> { + public: + void UpdateOpacities(int id); +}; class CC_EXPORT PropertyTrees final { public: diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc index 815692db211..28ad43f3091 100644 --- a/chromium/cc/trees/property_tree_builder.cc +++ b/chromium/cc/trees/property_tree_builder.cc @@ -31,9 +31,13 @@ struct DataForRecursion { int clip_tree_parent; int opacity_tree_parent; const LayerType* page_scale_layer; + const LayerType* inner_viewport_scroll_layer; + const LayerType* outer_viewport_scroll_layer; float page_scale_factor; float device_scale_factor; - bool in_subtree_of_page_scale_application_layer; + bool in_subtree_of_page_scale_layer; + bool affected_by_inner_viewport_bounds_delta; + bool affected_by_outer_viewport_bounds_delta; bool should_flatten; bool ancestor_clips_subtree; const gfx::Transform* device_transform; @@ -59,16 +63,6 @@ static ClipNode* GetClipParent(const DataForRecursion<LayerType>& data, } template <typename LayerType> -static bool HasPotentiallyRunningAnimation(LayerType* layer, - Animation::TargetProperty property) { - if (Animation* animation = - layer->layer_animation_controller()->GetAnimation(property)) { - return !animation->is_finished(); - } - return false; -} - -template <typename LayerType> static bool RequiresClipNode(LayerType* layer, const DataForRecursion<LayerType>& data, int parent_transform_id, @@ -78,7 +72,7 @@ static bool RequiresClipNode(LayerType* layer, const bool render_surface_may_grow_due_to_clip_children = layer->render_surface() && layer->num_unclipped_descendants() > 0; - if (!layer->parent() || layer->masks_to_bounds() || layer->mask_layer() || + if (layer->masks_to_bounds() || layer->mask_layer() || render_surface_may_grow_due_to_clip_children) return true; @@ -130,8 +124,7 @@ void AddClipNodeIfNeeded(const DataForRecursion<LayerType>& data_from_ancestor, data_for_children->ancestor_clips_subtree)) { // Unclipped surfaces reset the clip rect. data_for_children->clip_tree_parent = parent_id; - } else if (layer->parent()) { - // Note the root clip gets handled elsewhere. + } else { LayerType* transform_parent = data_for_children->transform_tree_parent; if (layer->position_constraint().is_fixed_position() && !created_transform_node) { @@ -163,8 +156,7 @@ bool AddTransformNodeIfNeeded( LayerType* layer, DataForRecursion<LayerType>* data_for_children) { const bool is_root = !layer->parent(); - const bool is_page_scale_application_layer = - layer->parent() && layer->parent() == data_from_ancestor.page_scale_layer; + const bool is_page_scale_layer = layer == data_from_ancestor.page_scale_layer; const bool is_scrollable = layer->scrollable(); const bool is_fixed = layer->position_constraint().is_fixed_position(); @@ -172,19 +164,17 @@ bool AddTransformNodeIfNeeded( !layer->transform().IsIdentityOr2DTranslation(); const bool has_potentially_animated_transform = - HasPotentiallyRunningAnimation(layer, Animation::TRANSFORM); - - const bool has_animated_transform = - layer->layer_animation_controller()->IsAnimatingProperty( - Animation::TRANSFORM); + layer->HasPotentiallyRunningTransformAnimation(); + const bool has_animated_transform = layer->TransformIsAnimating(); const bool has_surface = !!layer->render_surface(); bool requires_node = is_root || is_scrollable || has_significant_transform || has_potentially_animated_transform || has_surface || - is_fixed || is_page_scale_application_layer; + is_fixed || is_page_scale_layer; LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer); + DCHECK_IMPLIES(!is_root, transform_parent); int parent_index = 0; if (transform_parent) @@ -201,19 +191,27 @@ bool AddTransformNodeIfNeeded( } else if (!is_fixed) { source_offset = transform_parent->offset_to_transform_parent(); } else { - if (data_from_ancestor.transform_tree_parent != - data_from_ancestor.transform_fixed_parent) { - source_offset = data_from_ancestor.transform_tree_parent - ->offset_to_transform_parent(); - source_index = - data_from_ancestor.transform_tree_parent->transform_tree_index(); - } + source_offset = data_from_ancestor.transform_tree_parent + ->offset_to_transform_parent(); + source_index = + data_from_ancestor.transform_tree_parent->transform_tree_index(); source_offset += data_from_ancestor.scroll_compensation_adjustment; } } - if (layer->IsContainerForFixedPositionLayers() || is_root) - data_for_children->transform_fixed_parent = layer; + if (layer->IsContainerForFixedPositionLayers() || is_root) { + data_for_children->affected_by_inner_viewport_bounds_delta = + layer == data_from_ancestor.inner_viewport_scroll_layer; + data_for_children->affected_by_outer_viewport_bounds_delta = + layer == data_from_ancestor.outer_viewport_scroll_layer; + if (is_scrollable) { + DCHECK(!is_root); + DCHECK(layer->transform().IsIdentity()); + data_for_children->transform_fixed_parent = layer->parent(); + } else { + data_for_children->transform_fixed_parent = layer; + } + } data_for_children->transform_tree_parent = layer; if (layer->IsContainerForFixedPositionLayers() || is_fixed) @@ -262,30 +260,54 @@ bool AddTransformNodeIfNeeded( post_local_scale_factor = data_from_ancestor.device_scale_factor; } - if (is_page_scale_application_layer) + if (is_page_scale_layer) post_local_scale_factor *= data_from_ancestor.page_scale_factor; if (has_surface && !is_root) { node->data.needs_sublayer_scale = true; node->data.layer_scale_factor = data_from_ancestor.device_scale_factor; - if (data_from_ancestor.in_subtree_of_page_scale_application_layer) + if (data_from_ancestor.in_subtree_of_page_scale_layer) node->data.layer_scale_factor *= data_from_ancestor.page_scale_factor; } + node->data.source_node_id = source_index; if (is_root) { node->data.post_local.Scale(post_local_scale_factor, post_local_scale_factor); + node->data.post_local.Translate(layer->position().x(), + layer->position().y()); } else { node->data.post_local_scale_factor = post_local_scale_factor; node->data.source_offset = source_offset; - node->data.source_node_id = source_index; node->data.update_post_local_transform(layer->position(), layer->transform_origin()); } - if (!layer->scroll_parent()) { - node->data.scroll_offset = - gfx::ScrollOffsetToVector2dF(layer->CurrentScrollOffset()); + if (!layer->scroll_parent()) + node->data.scroll_offset = layer->CurrentScrollOffset(); + + if (is_fixed) { + if (data_from_ancestor.affected_by_inner_viewport_bounds_delta) { + node->data.affected_by_inner_viewport_bounds_delta_x = + layer->position_constraint().is_fixed_to_right_edge(); + node->data.affected_by_inner_viewport_bounds_delta_y = + layer->position_constraint().is_fixed_to_bottom_edge(); + if (node->data.affected_by_inner_viewport_bounds_delta_x || + node->data.affected_by_inner_viewport_bounds_delta_y) { + data_for_children->transform_tree + ->AddNodeAffectedByInnerViewportBoundsDelta(node->id); + } + } else if (data_from_ancestor.affected_by_outer_viewport_bounds_delta) { + node->data.affected_by_outer_viewport_bounds_delta_x = + layer->position_constraint().is_fixed_to_right_edge(); + node->data.affected_by_outer_viewport_bounds_delta_y = + layer->position_constraint().is_fixed_to_bottom_edge(); + if (node->data.affected_by_outer_viewport_bounds_delta_x || + node->data.affected_by_outer_viewport_bounds_delta_y) { + data_for_children->transform_tree + ->AddNodeAffectedByOuterViewportBoundsDelta(node->id); + } + } } node->data.local = layer->transform(); @@ -308,12 +330,12 @@ bool AddTransformNodeIfNeeded( } bool IsAnimatingOpacity(Layer* layer) { - return HasPotentiallyRunningAnimation(layer, Animation::OPACITY) || + return layer->HasPotentiallyRunningOpacityAnimation() || layer->OpacityCanAnimateOnImplThread(); } bool IsAnimatingOpacity(LayerImpl* layer) { - return HasPotentiallyRunningAnimation(layer, Animation::OPACITY); + return layer->HasPotentiallyRunningOpacityAnimation(); } template <typename LayerType> @@ -336,7 +358,12 @@ void AddOpacityNodeIfNeeded( OpacityNode node; node.owner_id = layer->id(); - node.data = layer->opacity(); + node.data.opacity = layer->opacity(); + node.data.screen_space_opacity = layer->opacity(); + if (!is_root) + node.data.screen_space_opacity *= + data_from_ancestor.opacity_tree->Node(parent_id) + ->data.screen_space_opacity; data_for_children->opacity_tree_parent = data_for_children->opacity_tree->Insert(node, parent_id); layer->SetOpacityTreeIndex(data_for_children->opacity_tree_parent); @@ -360,15 +387,22 @@ void BuildPropertyTreesInternal( AddOpacityNodeIfNeeded(data_from_parent, layer, &data_for_children); if (layer == data_from_parent.page_scale_layer) - data_for_children.in_subtree_of_page_scale_application_layer = true; + data_for_children.in_subtree_of_page_scale_layer = true; for (size_t i = 0; i < layer->children().size(); ++i) { - if (!layer->child_at(i)->scroll_parent()) + if (!layer->child_at(i)->scroll_parent()) { BuildPropertyTreesInternal(layer->child_at(i), data_for_children); + } else { + // The child should be included in its scroll parent's list of scroll + // children. + DCHECK(layer->child_at(i)->scroll_parent()->scroll_children()->count( + layer->child_at(i))); + } } if (layer->scroll_children()) { for (LayerType* scroll_child : *layer->scroll_children()) { + DCHECK_EQ(scroll_child->scroll_parent(), layer); BuildPropertyTreesInternal(scroll_child, data_for_children); } } @@ -380,13 +414,19 @@ void BuildPropertyTreesInternal( } // namespace template <typename LayerType> -void BuildPropertyTreesTopLevelInternal(LayerType* root_layer, - const LayerType* page_scale_layer, - float page_scale_factor, - float device_scale_factor, - const gfx::Rect& viewport, - const gfx::Transform& device_transform, - PropertyTrees* property_trees) { +void BuildPropertyTreesTopLevelInternal( + LayerType* root_layer, + const LayerType* page_scale_layer, + const LayerType* inner_viewport_scroll_layer, + const LayerType* outer_viewport_scroll_layer, + float page_scale_factor, + float device_scale_factor, + const gfx::Rect& viewport, + const gfx::Transform& device_transform, + PropertyTrees* property_trees) { + if (!property_trees->needs_rebuild) + return; + property_trees->sequence_number++; DataForRecursion<LayerType> data_for_recursion; @@ -399,9 +439,13 @@ void BuildPropertyTreesTopLevelInternal(LayerType* root_layer, data_for_recursion.clip_tree_parent = 0; data_for_recursion.opacity_tree_parent = -1; data_for_recursion.page_scale_layer = page_scale_layer; + data_for_recursion.inner_viewport_scroll_layer = inner_viewport_scroll_layer; + data_for_recursion.outer_viewport_scroll_layer = outer_viewport_scroll_layer; data_for_recursion.page_scale_factor = page_scale_factor; data_for_recursion.device_scale_factor = device_scale_factor; - data_for_recursion.in_subtree_of_page_scale_application_layer = false; + data_for_recursion.in_subtree_of_page_scale_layer = false; + data_for_recursion.affected_by_inner_viewport_bounds_delta = false; + data_for_recursion.affected_by_outer_viewport_bounds_delta = false; data_for_recursion.should_flatten = false; data_for_recursion.ancestor_clips_subtree = true; data_for_recursion.device_transform = &device_transform; @@ -424,35 +468,38 @@ void BuildPropertyTreesTopLevelInternal(LayerType* root_layer, // building. property_trees->transform_tree.set_needs_update(false); property_trees->clip_tree.set_needs_update(true); + property_trees->opacity_tree.set_needs_update(false); } void PropertyTreeBuilder::BuildPropertyTrees( Layer* root_layer, const Layer* page_scale_layer, + const Layer* inner_viewport_scroll_layer, + const Layer* outer_viewport_scroll_layer, float page_scale_factor, float device_scale_factor, const gfx::Rect& viewport, const gfx::Transform& device_transform, PropertyTrees* property_trees) { - // TODO(enne): hoist this out of here - if (!property_trees->needs_rebuild) - return; - BuildPropertyTreesTopLevelInternal( - root_layer, page_scale_layer, page_scale_factor, device_scale_factor, + root_layer, page_scale_layer, inner_viewport_scroll_layer, + outer_viewport_scroll_layer, page_scale_factor, device_scale_factor, viewport, device_transform, property_trees); } void PropertyTreeBuilder::BuildPropertyTrees( LayerImpl* root_layer, const LayerImpl* page_scale_layer, + const LayerImpl* inner_viewport_scroll_layer, + const LayerImpl* outer_viewport_scroll_layer, float page_scale_factor, float device_scale_factor, const gfx::Rect& viewport, const gfx::Transform& device_transform, PropertyTrees* property_trees) { BuildPropertyTreesTopLevelInternal( - root_layer, page_scale_layer, page_scale_factor, device_scale_factor, + root_layer, page_scale_layer, inner_viewport_scroll_layer, + outer_viewport_scroll_layer, page_scale_factor, device_scale_factor, viewport, device_transform, property_trees); } diff --git a/chromium/cc/trees/property_tree_builder.h b/chromium/cc/trees/property_tree_builder.h index 15f326ef15c..f877aebe3dd 100644 --- a/chromium/cc/trees/property_tree_builder.h +++ b/chromium/cc/trees/property_tree_builder.h @@ -20,6 +20,8 @@ class PropertyTreeBuilder { // in a null |opacity_tree|. static void BuildPropertyTrees(Layer* root_layer, const Layer* page_scale_layer, + const Layer* inner_viewport_scroll_layer, + const Layer* outer_viewport_scroll_layer, float page_scale_factor, float device_scale_factor, const gfx::Rect& viewport, @@ -27,6 +29,8 @@ class PropertyTreeBuilder { PropertyTrees* property_trees); static void BuildPropertyTrees(LayerImpl* root_layer, const LayerImpl* page_scale_layer, + const LayerImpl* inner_viewport_scroll_layer, + const LayerImpl* outer_viewport_scroll_layer, float page_scale_factor, float device_scale_factor, const gfx::Rect& viewport, diff --git a/chromium/cc/trees/property_tree_unittest.cc b/chromium/cc/trees/property_tree_unittest.cc index 7e179388b5f..8497dca6af1 100644 --- a/chromium/cc/trees/property_tree_unittest.cc +++ b/chromium/cc/trees/property_tree_unittest.cc @@ -422,6 +422,68 @@ TEST(PropertyTreeTest, ComputeTransformWithSublayerScale) { transform); } +TEST(PropertyTreeTest, ComputeTransformToTargetWithZeroSublayerScale) { + TransformTree tree; + TransformNode& root = *tree.Node(0); + root.data.target_id = 0; + tree.UpdateTransforms(0); + + TransformNode grand_parent; + grand_parent.data.local.Scale(2.f, 0.f); + grand_parent.data.target_id = 0; + grand_parent.data.source_node_id = 0; + grand_parent.data.needs_sublayer_scale = true; + int grand_parent_id = tree.Insert(grand_parent, 0); + tree.Node(grand_parent_id)->data.content_target_id = grand_parent_id; + tree.UpdateTransforms(grand_parent_id); + + TransformNode parent; + parent.data.local.Translate(1.f, 1.f); + parent.data.target_id = grand_parent_id; + parent.data.content_target_id = grand_parent_id; + parent.data.source_node_id = grand_parent_id; + int parent_id = tree.Insert(parent, grand_parent_id); + tree.UpdateTransforms(parent_id); + + TransformNode child; + child.data.local.Translate(3.f, 4.f); + child.data.target_id = grand_parent_id; + child.data.content_target_id = grand_parent_id; + child.data.source_node_id = parent_id; + int child_id = tree.Insert(child, parent_id); + tree.UpdateTransforms(child_id); + + gfx::Transform expected_transform; + expected_transform.Translate(4.f, 5.f); + + gfx::Transform transform; + bool success = tree.ComputeTransform(child_id, grand_parent_id, &transform); + EXPECT_TRUE(success); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform); + + tree.Node(grand_parent_id)->data.local.MakeIdentity(); + tree.Node(grand_parent_id)->data.local.Scale(0.f, 2.f); + tree.Node(grand_parent_id)->data.needs_local_transform_update = true; + tree.set_needs_update(true); + + ComputeTransforms(&tree); + + success = tree.ComputeTransform(child_id, grand_parent_id, &transform); + EXPECT_TRUE(success); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform); + + tree.Node(grand_parent_id)->data.local.MakeIdentity(); + tree.Node(grand_parent_id)->data.local.Scale(0.f, 0.f); + tree.Node(grand_parent_id)->data.needs_local_transform_update = true; + tree.set_needs_update(true); + + ComputeTransforms(&tree); + + success = tree.ComputeTransform(child_id, grand_parent_id, &transform); + EXPECT_TRUE(success); + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform); +} + TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { // This tests that flattening is performed correctly when // destination and its ancestors are flat, but there are 3d transforms @@ -464,4 +526,62 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { grand_child_to_parent); } +TEST(PropertyTreeTest, ScreenSpaceOpacityUpdateTest) { + // This tests that screen space opacity is updated for the subtree when + // opacity of a node changes. + OpacityTree tree; + + int parent = tree.Insert(OpacityNode(), 0); + int child = tree.Insert(OpacityNode(), parent); + + EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 1.f); + tree.Node(parent)->data.opacity = 0.5f; + tree.set_needs_update(true); + ComputeOpacities(&tree); + EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 0.5f); + + tree.Node(child)->data.opacity = 0.5f; + tree.set_needs_update(true); + ComputeOpacities(&tree); + EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 0.25f); +} + +TEST(PropertyTreeTest, NonIntegerTranslationTest) { + // This tests that when a node has non-integer translation, the information + // is propagated to the subtree. + TransformTree tree; + + int parent = tree.Insert(TransformNode(), 0); + tree.Node(parent)->data.target_id = parent; + tree.Node(parent)->data.local.Translate(1.5f, 1.5f); + + int child = tree.Insert(TransformNode(), parent); + tree.Node(child)->data.target_id = parent; + tree.Node(child)->data.local.Translate(1, 1); + tree.set_needs_update(true); + ComputeTransforms(&tree); + EXPECT_FALSE( + tree.Node(parent)->data.node_and_ancestors_have_only_integer_translation); + EXPECT_FALSE( + tree.Node(child)->data.node_and_ancestors_have_only_integer_translation); + + tree.Node(parent)->data.local.Translate(0.5f, 0.5f); + tree.Node(child)->data.local.Translate(0.5f, 0.5f); + tree.set_needs_update(true); + ComputeTransforms(&tree); + EXPECT_TRUE( + tree.Node(parent)->data.node_and_ancestors_have_only_integer_translation); + EXPECT_FALSE( + tree.Node(child)->data.node_and_ancestors_have_only_integer_translation); + + tree.Node(child)->data.local.Translate(0.5f, 0.5f); + tree.Node(child)->data.target_id = child; + tree.set_needs_update(true); + ComputeTransforms(&tree); + EXPECT_TRUE( + tree.Node(parent)->data.node_and_ancestors_have_only_integer_translation); + EXPECT_TRUE( + tree.Node(child)->data.node_and_ancestors_have_only_integer_translation); +} + } // namespace cc diff --git a/chromium/cc/trees/proxy.cc b/chromium/cc/trees/proxy.cc index eb81e2e6735..58d10b910cb 100644 --- a/chromium/cc/trees/proxy.cc +++ b/chromium/cc/trees/proxy.cc @@ -4,7 +4,6 @@ #include "cc/trees/proxy.h" -#include "base/message_loop/message_loop_proxy.h" #include "base/single_thread_task_runner.h" #include "cc/trees/blocking_task_runner.h" diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h index 55e54beb6ae..d403ae0eb6d 100644 --- a/chromium/cc/trees/proxy.h +++ b/chromium/cc/trees/proxy.h @@ -97,9 +97,6 @@ class CC_EXPORT Proxy { // to finish before executing in the GPU process. virtual void ForceSerializeOnSwapBuffers() = 0; - // Maximum number of sub-region texture updates supported for each commit. - virtual size_t MaxPartialTextureUpdates() const = 0; - virtual bool SupportsImplScrolling() const = 0; virtual void SetDebugState(const LayerTreeDebugState& debug_state) = 0; diff --git a/chromium/cc/trees/proxy_timing_history.cc b/chromium/cc/trees/proxy_timing_history.cc deleted file mode 100644 index 90abad1632f..00000000000 --- a/chromium/cc/trees/proxy_timing_history.cc +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/trees/proxy_timing_history.h" - -#include "base/metrics/histogram.h" - -const size_t kDurationHistorySize = 60; -const double kCommitAndActivationDurationEstimationPercentile = 50.0; -const double kDrawDurationEstimationPercentile = 100.0; -const int kDrawDurationEstimatePaddingInMicroseconds = 0; - -namespace cc { - -ProxyTimingHistory::ProxyTimingHistory( - RenderingStatsInstrumentation* rendering_stats_instrumentation) - : draw_duration_history_(kDurationHistorySize), - begin_main_frame_to_commit_duration_history_(kDurationHistorySize), - commit_to_activate_duration_history_(kDurationHistorySize), - rendering_stats_instrumentation_(rendering_stats_instrumentation) { -} - -ProxyTimingHistory::~ProxyTimingHistory() {} - -base::TimeDelta ProxyTimingHistory::DrawDurationEstimate() const { - base::TimeDelta historical_estimate = - draw_duration_history_.Percentile(kDrawDurationEstimationPercentile); - base::TimeDelta padding = base::TimeDelta::FromMicroseconds( - kDrawDurationEstimatePaddingInMicroseconds); - return historical_estimate + padding; -} - -base::TimeDelta ProxyTimingHistory::BeginMainFrameToCommitDurationEstimate() - const { - return begin_main_frame_to_commit_duration_history_.Percentile( - kCommitAndActivationDurationEstimationPercentile); -} - -base::TimeDelta ProxyTimingHistory::CommitToActivateDurationEstimate() const { - return commit_to_activate_duration_history_.Percentile( - kCommitAndActivationDurationEstimationPercentile); -} - -void ProxyTimingHistory::DidBeginMainFrame() { - begin_main_frame_sent_time_ = base::TimeTicks::Now(); -} - -void ProxyTimingHistory::DidCommit() { - commit_complete_time_ = base::TimeTicks::Now(); - base::TimeDelta begin_main_frame_to_commit_duration = - commit_complete_time_ - begin_main_frame_sent_time_; - - // Before adding the new data point to the timing history, see what we would - // have predicted for this frame. This allows us to keep track of the accuracy - // of our predictions. - rendering_stats_instrumentation_->AddBeginMainFrameToCommitDuration( - begin_main_frame_to_commit_duration, - BeginMainFrameToCommitDurationEstimate()); - - begin_main_frame_to_commit_duration_history_.InsertSample( - begin_main_frame_to_commit_duration); -} - -void ProxyTimingHistory::DidActivateSyncTree() { - base::TimeDelta commit_to_activate_duration = - base::TimeTicks::Now() - commit_complete_time_; - - // Before adding the new data point to the timing history, see what we would - // have predicted for this frame. This allows us to keep track of the accuracy - // of our predictions. - rendering_stats_instrumentation_->AddCommitToActivateDuration( - commit_to_activate_duration, CommitToActivateDurationEstimate()); - - commit_to_activate_duration_history_.InsertSample( - commit_to_activate_duration); -} - -void ProxyTimingHistory::DidStartDrawing() { - start_draw_time_ = base::TimeTicks::Now(); -} - -void ProxyTimingHistory::DidFinishDrawing() { - base::TimeDelta draw_duration = base::TimeTicks::Now() - start_draw_time_; - - // Before adding the new data point to the timing history, see what we would - // have predicted for this frame. This allows us to keep track of the accuracy - // of our predictions. - base::TimeDelta draw_duration_estimate = DrawDurationEstimate(); - rendering_stats_instrumentation_->AddDrawDuration(draw_duration, - draw_duration_estimate); - - AddDrawDurationUMA(draw_duration, draw_duration_estimate); - - draw_duration_history_.InsertSample(draw_duration); -} - -void ProxyTimingHistory::AddDrawDurationUMA( - base::TimeDelta draw_duration, - base::TimeDelta draw_duration_estimate) { - base::TimeDelta draw_duration_overestimate; - base::TimeDelta draw_duration_underestimate; - if (draw_duration > draw_duration_estimate) - draw_duration_underestimate = draw_duration - draw_duration_estimate; - else - draw_duration_overestimate = draw_duration_estimate - draw_duration; - UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration", - draw_duration, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMilliseconds(100), - 50); - UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate", - draw_duration_underestimate, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMilliseconds(100), - 50); - UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate", - draw_duration_overestimate, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMilliseconds(100), - 50); -} - -} // namespace cc diff --git a/chromium/cc/trees/proxy_timing_history.h b/chromium/cc/trees/proxy_timing_history.h deleted file mode 100644 index aa213b6bdb7..00000000000 --- a/chromium/cc/trees/proxy_timing_history.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_TREES_PROXY_TIMING_HISTORY_H_ -#define CC_TREES_PROXY_TIMING_HISTORY_H_ - -#include "cc/base/rolling_time_delta_history.h" -#include "cc/debug/rendering_stats_instrumentation.h" - -namespace cc { - -class ProxyTimingHistory { - public: - explicit ProxyTimingHistory( - RenderingStatsInstrumentation* rendering_stats_instrumentation); - ~ProxyTimingHistory(); - - base::TimeDelta DrawDurationEstimate() const; - base::TimeDelta BeginMainFrameToCommitDurationEstimate() const; - base::TimeDelta CommitToActivateDurationEstimate() const; - - void DidBeginMainFrame(); - void DidCommit(); - void DidActivateSyncTree(); - void DidStartDrawing(); - void DidFinishDrawing(); - - protected: - void AddDrawDurationUMA(base::TimeDelta draw_duration, - base::TimeDelta draw_duration_estimate); - - RollingTimeDeltaHistory draw_duration_history_; - RollingTimeDeltaHistory begin_main_frame_to_commit_duration_history_; - RollingTimeDeltaHistory commit_to_activate_duration_history_; - - base::TimeTicks begin_main_frame_sent_time_; - base::TimeTicks commit_complete_time_; - base::TimeTicks start_draw_time_; - - RenderingStatsInstrumentation* rendering_stats_instrumentation_; -}; - -} // namespace cc - -#endif // CC_TREES_PROXY_TIMING_HISTORY_H_ diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index f05a9a6a529..b6d120b4805 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -12,14 +12,13 @@ #include "cc/output/context_provider.h" #include "cc/output/output_surface.h" #include "cc/quads/draw_quad.h" -#include "cc/resources/prioritized_resource_manager.h" -#include "cc/resources/resource_update_controller.h" #include "cc/scheduler/commit_earlyout_reason.h" +#include "cc/scheduler/compositor_timing_history.h" +#include "cc/scheduler/scheduler.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_host_single_thread_client.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/scoped_abort_remaining_swap_promises.h" -#include "ui/gfx/frame_time.h" namespace cc { @@ -43,7 +42,7 @@ SingleThreadProxy::SingleThreadProxy( : Proxy(main_task_runner, NULL), layer_tree_host_(layer_tree_host), client_(client), - timing_history_(layer_tree_host->rendering_stats_instrumentation()), + external_begin_frame_source_(external_begin_frame_source.Pass()), next_frame_is_newly_committed_frame_(false), #if DCHECK_IS_ON() inside_impl_frame_(false), @@ -63,11 +62,16 @@ SingleThreadProxy::SingleThreadProxy( !scheduler_on_impl_thread_) { SchedulerSettings scheduler_settings( layer_tree_host->settings().ToSchedulerSettings()); - // SingleThreadProxy should run in main thread low latency mode. - scheduler_settings.main_thread_should_always_be_low_latency = true; + scheduler_settings.commit_to_active_tree = CommitToActiveTree(); + + scoped_ptr<CompositorTimingHistory> compositor_timing_history( + new CompositorTimingHistory( + layer_tree_host->rendering_stats_instrumentation())); + scheduler_on_impl_thread_ = Scheduler::Create( this, scheduler_settings, layer_tree_host_->id(), - MainThreadTaskRunner(), external_begin_frame_source.Pass()); + MainThreadTaskRunner(), external_begin_frame_source_.get(), + compositor_timing_history.Pass()); } } @@ -153,8 +157,6 @@ void SingleThreadProxy::SetOutputSurface( { DebugScopedSetMainThreadBlocked main_thread_blocked(this); DebugScopedSetImplThread impl(this); - layer_tree_host_->DeleteContentsTexturesOnImplThread( - layer_tree_host_impl_->resource_provider()); success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass()); } @@ -243,39 +245,10 @@ void SingleThreadProxy::DoCommit() { blocking_main_thread_task_runner())); layer_tree_host_impl_->BeginCommit(); - - if (PrioritizedResourceManager* contents_texture_manager = - layer_tree_host_->contents_texture_manager()) { - // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 - // is fixed. - tracked_objects::ScopedTracker tracking_profile3( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "461509 SingleThreadProxy::DoCommit3")); - contents_texture_manager->PushTexturePrioritiesToBackings(); - } layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get()); // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 // is fixed. - tracked_objects::ScopedTracker tracking_profile4( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "461509 SingleThreadProxy::DoCommit4")); - scoped_ptr<ResourceUpdateController> update_controller = - ResourceUpdateController::Create( - NULL, - MainThreadTaskRunner(), - queue_for_commit_.Pass(), - layer_tree_host_impl_->resource_provider()); - - // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 - // is fixed. - tracked_objects::ScopedTracker tracking_profile5( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "461509 SingleThreadProxy::DoCommit5")); - update_controller->Finalize(); - - // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 - // is fixed. tracked_objects::ScopedTracker tracking_profile6( FROM_HERE_WITH_EXPLICIT_FUNCTION( "461509 SingleThreadProxy::DoCommit6")); @@ -298,26 +271,17 @@ void SingleThreadProxy::DoCommit() { DCHECK_EQ(1.f, scroll_info->page_scale_delta); #endif - if (layer_tree_host_->settings().impl_side_painting) { - // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 - // is fixed. - tracked_objects::ScopedTracker tracking_profile8( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "461509 SingleThreadProxy::DoCommit8")); - // Commit goes directly to the active tree, but we need to synchronously - // "activate" the tree still during commit to satisfy any potential - // SetNextCommitWaitsForActivation calls. Unfortunately, the tree - // might not be ready to draw, so DidActivateSyncTree must set - // the flag to force the tree to not draw until textures are ready. - NotifyReadyToActivate(); - } else { - // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 - // is fixed. - tracked_objects::ScopedTracker tracking_profile9( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "461509 SingleThreadProxy::DoCommit9")); - CommitComplete(); - } + // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 + // is fixed. + tracked_objects::ScopedTracker tracking_profile8( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "461509 SingleThreadProxy::DoCommit8")); + // Commit goes directly to the active tree, but we need to synchronously + // "activate" the tree still during commit to satisfy any potential + // SetNextCommitWaitsForActivation calls. Unfortunately, the tree + // might not be ready to draw, so DidActivateSyncTree must set + // the flag to force the tree to not draw until textures are ready. + NotifyReadyToActivate(); } } @@ -326,6 +290,9 @@ void SingleThreadProxy::CommitComplete() { << "Activation is expected to have synchronously occurred by now."; DCHECK(commit_blocking_task_runner_); + if (scheduler_on_impl_thread_) + scheduler_on_impl_thread_->DidCommit(); + // Notify commit complete on the impl side after activate to satisfy any // SetNextCommitWaitsForActivation calls. layer_tree_host_impl_->CommitComplete(); @@ -334,7 +301,6 @@ void SingleThreadProxy::CommitComplete() { commit_blocking_task_runner_.reset(); layer_tree_host_->CommitComplete(); layer_tree_host_->DidBeginMainFrame(); - timing_history_.DidCommit(); next_frame_is_newly_committed_frame_ = true; } @@ -394,10 +360,6 @@ bool SingleThreadProxy::BeginMainFrameRequested() const { return commit_requested_; } -size_t SingleThreadProxy::MaxPartialTextureUpdates() const { - return std::numeric_limits<size_t>::max(); -} - void SingleThreadProxy::Stop() { TRACE_EVENT0("cc", "SingleThreadProxy::stop"); DCHECK(Proxy::IsMainThread()); @@ -407,8 +369,6 @@ void SingleThreadProxy::Stop() { BlockingTaskRunner::CapturePostTasks blocked( blocking_main_thread_task_runner()); - layer_tree_host_->DeleteContentsTexturesOnImplThread( - layer_tree_host_impl_->resource_provider()); scheduler_on_impl_thread_ = nullptr; layer_tree_host_impl_ = nullptr; } @@ -484,45 +444,27 @@ void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread( layer_tree_host_->SetAnimationEvents(events.Pass()); } -bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread( - size_t limit_bytes, - int priority_cutoff) { - DCHECK(IsImplThread()); - PrioritizedResourceManager* contents_texture_manager = - layer_tree_host_->contents_texture_manager(); - - ResourceProvider* resource_provider = - layer_tree_host_impl_->resource_provider(); - - if (!contents_texture_manager || !resource_provider) - return false; - - return contents_texture_manager->ReduceMemoryOnImplThread( - limit_bytes, priority_cutoff, resource_provider); -} - bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; } void SingleThreadProxy::DidActivateSyncTree() { - // Non-impl-side painting finishes commit in DoCommit. Impl-side painting - // defers until here to simulate SetNextCommitWaitsForActivation. - if (layer_tree_host_impl_->settings().impl_side_painting) { - // This is required because NotifyReadyToActivate gets called immediately - // after commit since single thread commits directly to the active tree. - if (scheduler_on_impl_thread_) - scheduler_on_impl_thread_->SetWaitForReadyToDraw(); + // This is required because NotifyReadyToActivate gets called immediately + // after commit since single thread commits directly to the active tree. + if (scheduler_on_impl_thread_) + scheduler_on_impl_thread_->SetWaitForReadyToDraw(); - // Synchronously call to CommitComplete. Resetting - // |commit_blocking_task_runner| would make sure all tasks posted during - // commit/activation before CommitComplete. - CommitComplete(); - } + // Synchronously call to CommitComplete. Resetting + // |commit_blocking_task_runner| would make sure all tasks posted during + // commit/activation before CommitComplete. + CommitComplete(); +} - timing_history_.DidActivateSyncTree(); +void SingleThreadProxy::WillPrepareTiles() { + DCHECK(Proxy::IsImplThread()); + if (scheduler_on_impl_thread_) + scheduler_on_impl_thread_->WillPrepareTiles(); } void SingleThreadProxy::DidPrepareTiles() { - DCHECK(layer_tree_host_impl_->settings().impl_side_painting); DCHECK(Proxy::IsImplThread()); if (scheduler_on_impl_thread_) scheduler_on_impl_thread_->DidPrepareTiles(); @@ -586,6 +528,26 @@ void SingleThreadProxy::OnDrawForOutputSurface() { NOTREACHED() << "Implemented by ThreadProxy for synchronous compositor."; } +void SingleThreadProxy::PostFrameTimingEventsOnImplThread( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) { + layer_tree_host_->RecordFrameTimingEvents(composite_events.Pass(), + main_frame_events.Pass()); +} + +void SingleThreadProxy::LayoutAndUpdateLayers() { + if (layer_tree_host_->output_surface_lost()) { + RequestNewOutputSurface(); + // RequestNewOutputSurface could have synchronously created an output + // surface, so check again before returning. + if (layer_tree_host_->output_surface_lost()) + return; + } + + layer_tree_host_->Layout(); + layer_tree_host_->UpdateLayers(); +} + void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately"); DCHECK(Proxy::IsMainThread()); @@ -627,13 +589,11 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { // Finish the impl frame. { DebugScopedSetImplThread impl(this); - if (layer_tree_host_impl_->settings().impl_side_painting) { - layer_tree_host_impl_->ActivateSyncTree(); - DCHECK(!layer_tree_host_impl_->active_tree() - ->needs_update_draw_properties()); - layer_tree_host_impl_->PrepareTiles(); - layer_tree_host_impl_->SynchronouslyInitializeAllTiles(); - } + layer_tree_host_impl_->ActivateSyncTree(); + DCHECK( + !layer_tree_host_impl_->active_tree()->needs_update_draw_properties()); + layer_tree_host_impl_->PrepareTiles(); + layer_tree_host_impl_->SynchronouslyInitializeAllTiles(); DoAnimate(); @@ -704,8 +664,6 @@ DrawResult SingleThreadProxy::DoComposite(LayerTreeHostImpl::FrameData* frame) { return DRAW_ABORTED_CANT_DRAW; } - timing_history_.DidStartDrawing(); - // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 // is fixed. tracked_objects::ScopedTracker tracking_profile2( @@ -741,7 +699,6 @@ DrawResult SingleThreadProxy::DoComposite(LayerTreeHostImpl::FrameData* frame) { tracked_objects::ScopedTracker tracking_profile7( FROM_HERE_WITH_EXPLICIT_FUNCTION( "461509 SingleThreadProxy::DoComposite7")); - timing_history_.DidFinishDrawing(); } if (draw_frame) { @@ -883,24 +840,10 @@ void SingleThreadProxy::DoBeginMainFrame( layer_tree_host_->AnimateLayers(begin_frame_args.frame_time); layer_tree_host_->Layout(); - if (PrioritizedResourceManager* contents_texture_manager = - layer_tree_host_->contents_texture_manager()) { - contents_texture_manager->UnlinkAndClearEvictedBackings(); - contents_texture_manager->SetMaxMemoryLimitBytes( - layer_tree_host_impl_->memory_allocation_limit_bytes()); - contents_texture_manager->SetExternalPriorityCutoff( - layer_tree_host_impl_->memory_allocation_priority_cutoff()); - } - - DCHECK(!queue_for_commit_); - queue_for_commit_ = make_scoped_ptr(new ResourceUpdateQueue); - // New commits requested inside UpdateLayers should be respected. commit_requested_ = false; - layer_tree_host_->UpdateLayers(queue_for_commit_.get()); - - timing_history_.DidBeginMainFrame(); + layer_tree_host_->UpdateLayers(); // TODO(enne): SingleThreadProxy does not support cancelling commits yet, // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside @@ -964,7 +907,6 @@ void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() { void SingleThreadProxy::ScheduledActionPrepareTiles() { TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionPrepareTiles"); - DCHECK(layer_tree_host_impl_->settings().impl_side_painting); DebugScopedSetImplThread impl(this); layer_tree_host_impl_->PrepareTiles(); } @@ -973,21 +915,6 @@ void SingleThreadProxy::ScheduledActionInvalidateOutputSurface() { NOTREACHED(); } -void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) { -} - -base::TimeDelta SingleThreadProxy::DrawDurationEstimate() { - return timing_history_.DrawDurationEstimate(); -} - -base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() { - return timing_history_.BeginMainFrameToCommitDurationEstimate(); -} - -base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() { - return timing_history_.CommitToActivateDurationEstimate(); -} - void SingleThreadProxy::DidFinishImplFrame() { layer_tree_host_impl_->DidFinishImplFrame(); #if DCHECK_IS_ON() diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index 98ac5e5c7d4..8bec2b133f9 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -15,7 +15,6 @@ #include "cc/trees/blocking_task_runner.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/proxy.h" -#include "cc/trees/proxy_timing_history.h" namespace cc { @@ -23,7 +22,6 @@ class BeginFrameSource; class ContextProvider; class LayerTreeHost; class LayerTreeHostSingleThreadClient; -class ResourceUpdateQueue; class CC_EXPORT SingleThreadProxy : public Proxy, NON_EXPORTED_BASE(LayerTreeHostImplClient), @@ -57,7 +55,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void MainThreadHasStoppedFlinging() override {} void Start() override; void Stop() override; - size_t MaxPartialTextureUpdates() const override; void ForceSerializeOnSwapBuffers() override; bool SupportsImplScrolling() const override; bool MainFrameWillHappenForTesting() override; @@ -76,10 +73,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void ScheduledActionBeginOutputSurfaceCreation() override; void ScheduledActionPrepareTiles() override; void ScheduledActionInvalidateOutputSurface() override; - void DidAnticipatedDrawTimeChange(base::TimeTicks time) override; - base::TimeDelta DrawDurationEstimate() override; - base::TimeDelta BeginMainFrameToCommitDurationEstimate() override; - base::TimeDelta CommitToActivateDurationEstimate() override; void SendBeginFramesToChildren(const BeginFrameArgs& args) override; void SendBeginMainFrameNotExpectedSoon() override; @@ -103,22 +96,26 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void SetVideoNeedsBeginFrames(bool needs_begin_frames) override; void PostAnimationEventsToMainThreadOnImplThread( scoped_ptr<AnimationEventsVector> events) override; - bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes, - int priority_cutoff) override; bool IsInsideDraw() override; void RenewTreePriority() override {} void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, base::TimeDelta delay) override {} void DidActivateSyncTree() override; + void WillPrepareTiles() override; void DidPrepareTiles() override; void DidCompletePageScaleAnimationOnImplThread() override; void OnDrawForOutputSurface() override; + void PostFrameTimingEventsOnImplThread( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) + override; void SetDebugState(const LayerTreeDebugState& debug_state) override {} void RequestNewOutputSurface(); // Called by the legacy path where RenderWidget does the scheduling. + void LayoutAndUpdateLayers(); void CompositeImmediately(base::TimeTicks frame_begin_time); protected: @@ -152,11 +149,10 @@ class CC_EXPORT SingleThreadProxy : public Proxy, RendererCapabilities renderer_capabilities_for_main_thread_; // Accessed from both threads. + scoped_ptr<BeginFrameSource> external_begin_frame_source_; scoped_ptr<Scheduler> scheduler_on_impl_thread_; - ProxyTimingHistory timing_history_; scoped_ptr<BlockingTaskRunner::CapturePostTasks> commit_blocking_task_runner_; - scoped_ptr<ResourceUpdateQueue> queue_for_commit_; bool next_frame_is_newly_committed_frame_; #if DCHECK_IS_ON() diff --git a/chromium/cc/trees/thread_proxy.cc b/chromium/cc/trees/thread_proxy.cc index 3010fba95c3..533c4906a01 100644 --- a/chromium/cc/trees/thread_proxy.cc +++ b/chromium/cc/trees/thread_proxy.cc @@ -19,16 +19,14 @@ #include "cc/output/output_surface.h" #include "cc/output/swap_promise.h" #include "cc/quads/draw_quad.h" -#include "cc/resources/prioritized_resource_manager.h" #include "cc/scheduler/commit_earlyout_reason.h" -#include "cc/scheduler/delay_based_time_source.h" +#include "cc/scheduler/compositor_timing_history.h" #include "cc/scheduler/scheduler.h" #include "cc/trees/blocking_task_runner.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/scoped_abort_remaining_swap_promises.h" #include "gpu/command_buffer/client/gles2_interface.h" -#include "ui/gfx/frame_time.h" namespace cc { @@ -98,18 +96,12 @@ ThreadProxy::MainThreadOrBlockedMainThread::MainThreadOrBlockedMainThread( ThreadProxy::MainThreadOrBlockedMainThread::~MainThreadOrBlockedMainThread() {} -PrioritizedResourceManager* -ThreadProxy::MainThreadOrBlockedMainThread::contents_texture_manager() { - return layer_tree_host->contents_texture_manager(); -} - ThreadProxy::CompositorThreadOnly::CompositorThreadOnly( ThreadProxy* proxy, int layer_tree_host_id, RenderingStatsInstrumentation* rendering_stats_instrumentation, scoped_ptr<BeginFrameSource> external_begin_frame_source) : layer_tree_host_id(layer_tree_host_id), - contents_texture_manager(NULL), commit_completion_event(NULL), completion_event_for_commit_held_on_tree_activation(NULL), next_frame_is_newly_committed_frame(false), @@ -120,8 +112,8 @@ ThreadProxy::CompositorThreadOnly::CompositorThreadOnly( base::Bind(&ThreadProxy::RenewTreePriority, base::Unretained(proxy)), base::TimeDelta::FromMilliseconds( kSmoothnessTakesPriorityExpirationDelay * 1000)), - timing_history(rendering_stats_instrumentation), external_begin_frame_source(external_begin_frame_source.Pass()), + rendering_stats_instrumentation(rendering_stats_instrumentation), weak_factory(proxy) { } @@ -154,9 +146,9 @@ bool ThreadProxy::IsStarted() const { } bool ThreadProxy::CommitToActiveTree() const { - // With ThreadProxy and impl-side painting, we use a pending tree and activate - // it once it's ready to draw. - return !impl().layer_tree_host_impl->settings().impl_side_painting; + // With ThreadProxy, we use a pending tree and activate it once it's ready to + // draw to allow input to modify the active tree and draw during raster. + return false; } void ThreadProxy::SetLayerTreeHostClientReady() { @@ -213,22 +205,6 @@ void ThreadProxy::DidLoseOutputSurface() { TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurface"); DCHECK(IsMainThread()); layer_tree_host()->DidLoseOutputSurface(); - - { - DebugScopedSetMainThreadBlocked main_thread_blocked(this); - - // Return lost resources to their owners immediately. - BlockingTaskRunner::CapturePostTasks blocked( - blocking_main_thread_task_runner()); - - CompletionEvent completion; - Proxy::ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::DeleteContentsTexturesOnImplThread, - impl_thread_weak_ptr_, - &completion)); - completion.Wait(); - } } void ThreadProxy::RequestNewOutputSurface() { @@ -422,32 +398,6 @@ void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread( base::Passed(&events))); } -bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes, - int priority_cutoff) { - DCHECK(IsImplThread()); - - if (!impl().contents_texture_manager) - return false; - if (!impl().layer_tree_host_impl->resource_provider()) - return false; - - bool reduce_result = - impl().contents_texture_manager->ReduceMemoryOnImplThread( - limit_bytes, - priority_cutoff, - impl().layer_tree_host_impl->resource_provider()); - if (!reduce_result) - return false; - - // The texture upload queue may reference textures that were just purged, - // clear them from the queue. - if (impl().current_resource_update_controller) { - impl() - .current_resource_update_controller->DiscardUploadsToEvictedResources(); - } - return true; -} - bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; } void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) { @@ -700,14 +650,8 @@ void ThreadProxy::ScheduledActionSendBeginMainFrame() { impl().layer_tree_host_impl->CurrentBeginFrameArgs(); begin_main_frame_state->scroll_info = impl().layer_tree_host_impl->ProcessScrollDeltas(); - - if (!impl().layer_tree_host_impl->settings().impl_side_painting) { - DCHECK_GT(impl().layer_tree_host_impl->memory_allocation_limit_bytes(), 0u); - } begin_main_frame_state->memory_allocation_limit_bytes = impl().layer_tree_host_impl->memory_allocation_limit_bytes(); - begin_main_frame_state->memory_allocation_priority_cutoff = - impl().layer_tree_host_impl->memory_allocation_priority_cutoff(); begin_main_frame_state->evicted_ui_resources = impl().layer_tree_host_impl->EvictedUIResourcesExist(); // TODO(vmpstr): This needs to be fixed if @@ -721,7 +665,6 @@ void ThreadProxy::ScheduledActionSendBeginMainFrame() { base::Passed(&begin_main_frame_state))); devtools_instrumentation::DidRequestMainThreadFrame( impl().layer_tree_host_id); - impl().timing_history.DidBeginMainFrame(); } void ThreadProxy::SendBeginMainFrameNotExpectedSoon() { @@ -797,17 +740,6 @@ void ThreadProxy::BeginMainFrame( layer_tree_host()->AnimateLayers( begin_main_frame_state->begin_frame_args.frame_time); - // Unlink any backings that the impl thread has evicted, so that we know to - // re-paint them in UpdateLayers. - if (blocked_main().contents_texture_manager()) { - blocked_main().contents_texture_manager()->UnlinkAndClearEvictedBackings(); - - blocked_main().contents_texture_manager()->SetMaxMemoryLimitBytes( - begin_main_frame_state->memory_allocation_limit_bytes); - blocked_main().contents_texture_manager()->SetExternalPriorityCutoff( - begin_main_frame_state->memory_allocation_priority_cutoff); - } - // Recreate all UI resources if there were evicted UI resources when the impl // thread initiated the commit. if (begin_main_frame_state->evicted_ui_resources) @@ -825,10 +757,7 @@ void ThreadProxy::BeginMainFrame( main().can_cancel_commit && !begin_main_frame_state->evicted_ui_resources; main().can_cancel_commit = true; - scoped_ptr<ResourceUpdateQueue> queue = - make_scoped_ptr(new ResourceUpdateQueue); - - bool updated = layer_tree_host()->UpdateLayers(queue.get()); + bool updated = layer_tree_host()->UpdateLayers(); layer_tree_host()->WillCommit(); devtools_instrumentation::ScopedCommitTrace commit_task( @@ -878,11 +807,8 @@ void ThreadProxy::BeginMainFrame( CompletionEvent completion; Proxy::ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::StartCommitOnImplThread, - impl_thread_weak_ptr_, - &completion, - queue.release())); + FROM_HERE, base::Bind(&ThreadProxy::StartCommitOnImplThread, + impl_thread_weak_ptr_, &completion)); completion.Wait(); } @@ -896,8 +822,7 @@ void ThreadProxy::BeginMainFrameNotExpectedSoon() { layer_tree_host()->BeginMainFrameNotExpectedSoon(); } -void ThreadProxy::StartCommitOnImplThread(CompletionEvent* completion, - ResourceUpdateQueue* raw_queue) { +void ThreadProxy::StartCommitOnImplThread(CompletionEvent* completion) { TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread"); DCHECK(!impl().commit_completion_event); DCHECK(IsImplThread() && IsMainThreadBlocked()); @@ -914,39 +839,8 @@ void ThreadProxy::StartCommitOnImplThread(CompletionEvent* completion, // Ideally, we should inform to impl thread when BeginMainFrame is started. // But, we can avoid a PostTask in here. impl().scheduler->NotifyBeginMainFrameStarted(); - - scoped_ptr<ResourceUpdateQueue> queue(raw_queue); - - if (impl().contents_texture_manager) { - DCHECK_EQ(impl().contents_texture_manager, - blocked_main().contents_texture_manager()); - } else { - // Cache this pointer that was created on the main thread side to avoid a - // data race between creating it and using it on the compositor thread. - impl().contents_texture_manager = blocked_main().contents_texture_manager(); - } - - if (impl().contents_texture_manager) { - if (impl().contents_texture_manager->LinkedEvictedBackingsExist()) { - // Clear any uploads we were making to textures linked to evicted - // resources - queue->ClearUploadsToEvictedResources(); - // Some textures in the layer tree are invalid. Kick off another commit - // to fill them again. - SetNeedsCommitOnImplThread(); - } - - impl().contents_texture_manager->PushTexturePrioritiesToBackings(); - } - impl().commit_completion_event = completion; - impl().current_resource_update_controller = ResourceUpdateController::Create( - this, - Proxy::ImplThreadTaskRunner(), - queue.Pass(), - impl().layer_tree_host_impl->resource_provider()); - impl().current_resource_update_controller->PerformMoreUpdates( - impl().scheduler->AnticipatedDrawTime()); + impl().scheduler->NotifyReadyToCommit(); } void ThreadProxy::BeginMainFrameAbortedOnImplThread( @@ -994,11 +888,6 @@ void ThreadProxy::ScheduledActionCommit() { DCHECK(IsImplThread()); DCHECK(IsMainThreadBlocked()); DCHECK(impl().commit_completion_event); - DCHECK(impl().current_resource_update_controller); - - // Complete all remaining texture updates. - impl().current_resource_update_controller->Finalize(); - impl().current_resource_update_controller = nullptr; blocked_main().main_thread_inside_commit = true; impl().layer_tree_host_impl->BeginCommit(); @@ -1007,8 +896,7 @@ void ThreadProxy::ScheduledActionCommit() { impl().layer_tree_host_impl.get()); blocked_main().main_thread_inside_commit = false; - bool hold_commit = layer_tree_host()->settings().impl_side_painting && - blocked_main().commit_waits_for_activation; + bool hold_commit = blocked_main().commit_waits_for_activation; blocked_main().commit_waits_for_activation = false; if (hold_commit) { @@ -1024,6 +912,8 @@ void ThreadProxy::ScheduledActionCommit() { impl().commit_completion_event = NULL; } + impl().scheduler->DidCommit(); + // Delay this step until afer the main thread has been released as it's // often a good bit of work to update the tree and prepare the new frame. impl().layer_tree_host_impl->CommitComplete(); @@ -1031,8 +921,6 @@ void ThreadProxy::ScheduledActionCommit() { SetInputThrottledUntilCommitOnImplThread(false); impl().next_frame_is_newly_committed_frame = true; - - impl().timing_history.DidCommit(); } void ThreadProxy::ScheduledActionActivateSyncTree() { @@ -1056,7 +944,6 @@ DrawResult ThreadProxy::DrawSwapInternal(bool forced_draw) { DCHECK(IsImplThread()); DCHECK(impl().layer_tree_host_impl.get()); - impl().timing_history.DidStartDrawing(); base::AutoReset<bool> mark_inside(&impl().inside_draw, true); if (impl().layer_tree_host_impl->pending_tree()) { @@ -1108,16 +995,12 @@ DrawResult ThreadProxy::DrawSwapInternal(bool forced_draw) { base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_)); } - if (result == DRAW_SUCCESS) - impl().timing_history.DidFinishDrawing(); - DCHECK_NE(INVALID_RESULT, result); return result; } void ThreadProxy::ScheduledActionPrepareTiles() { TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionPrepareTiles"); - DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting); impl().layer_tree_host_impl->PrepareTiles(); } @@ -1145,23 +1028,6 @@ void ThreadProxy::ScheduledActionInvalidateOutputSurface() { impl().layer_tree_host_impl->output_surface()->Invalidate(); } -void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) { - if (impl().current_resource_update_controller) - impl().current_resource_update_controller->PerformMoreUpdates(time); -} - -base::TimeDelta ThreadProxy::DrawDurationEstimate() { - return impl().timing_history.DrawDurationEstimate(); -} - -base::TimeDelta ThreadProxy::BeginMainFrameToCommitDurationEstimate() { - return impl().timing_history.BeginMainFrameToCommitDurationEstimate(); -} - -base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() { - return impl().timing_history.CommitToActivateDurationEstimate(); -} - void ThreadProxy::DidFinishImplFrame() { impl().layer_tree_host_impl->DidFinishImplFrame(); } @@ -1175,11 +1041,6 @@ void ThreadProxy::SetAuthoritativeVSyncInterval( NOTREACHED() << "Only used by SingleThreadProxy"; } -void ThreadProxy::ReadyToFinalizeTextureUpdates() { - DCHECK(IsImplThread()); - impl().scheduler->NotifyReadyToCommit(); -} - void ThreadProxy::DidCommitAndDrawFrame() { DCHECK(IsMainThread()); layer_tree_host()->DidCommitAndDrawFrame(); @@ -1201,29 +1062,23 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) { DCHECK(IsImplThread()); impl().layer_tree_host_impl = layer_tree_host()->CreateLayerTreeHostImpl(this); + SchedulerSettings scheduler_settings( layer_tree_host()->settings().ToSchedulerSettings()); + + scoped_ptr<CompositorTimingHistory> compositor_timing_history( + new CompositorTimingHistory(impl().rendering_stats_instrumentation)); + impl().scheduler = Scheduler::Create( - this, - scheduler_settings, - impl().layer_tree_host_id, - ImplThreadTaskRunner(), - impl().external_begin_frame_source.Pass()); + this, scheduler_settings, impl().layer_tree_host_id, + ImplThreadTaskRunner(), impl().external_begin_frame_source.get(), + compositor_timing_history.Pass()); + impl().scheduler->SetVisible(impl().layer_tree_host_impl->visible()); impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr(); completion->Signal(); } -void ThreadProxy::DeleteContentsTexturesOnImplThread( - CompletionEvent* completion) { - TRACE_EVENT0("cc", "ThreadProxy::DeleteContentsTexturesOnImplThread"); - DCHECK(IsImplThread()); - DCHECK(IsMainThreadBlocked()); - layer_tree_host()->DeleteContentsTexturesOnImplThread( - impl().layer_tree_host_impl->resource_provider()); - completion->Signal(); -} - void ThreadProxy::InitializeOutputSurfaceOnImplThread( scoped_ptr<OutputSurface> output_surface) { TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread"); @@ -1264,27 +1119,19 @@ void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) { TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread"); DCHECK(IsImplThread()); DCHECK(IsMainThreadBlocked()); - layer_tree_host()->DeleteContentsTexturesOnImplThread( - impl().layer_tree_host_impl->resource_provider()); - impl().current_resource_update_controller = nullptr; impl().scheduler = nullptr; + impl().external_begin_frame_source = nullptr; impl().layer_tree_host_impl = nullptr; impl().weak_factory.InvalidateWeakPtrs(); // We need to explicitly shutdown the notifier to destroy any weakptrs it is // holding while still on the compositor thread. This also ensures any // callbacks holding a ThreadProxy pointer are cancelled. impl().smoothness_priority_expiration_notifier.Shutdown(); - impl().contents_texture_manager = NULL; completion->Signal(); } -size_t ThreadProxy::MaxPartialTextureUpdates() const { - return ResourceUpdateController::MaxPartialTextureUpdates(); -} - ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState() : memory_allocation_limit_bytes(0), - memory_allocation_priority_cutoff(0), evicted_ui_resources(false) {} ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {} @@ -1340,10 +1187,9 @@ void ThreadProxy::RenewTreePriority() { if (impl().smoothness_priority_expiration_notifier.HasPendingNotification()) priority = SMOOTHNESS_TAKES_PRIORITY; - // New content always takes priority when the active tree has - // evicted resources or there is an invalid viewport size. - if (impl().layer_tree_host_impl->active_tree()->ContentsTexturesPurged() || - impl().layer_tree_host_impl->active_tree()->ViewportSizeInvalid() || + // New content always takes priority when there is an invalid viewport size or + // ui resources have been evicted. + if (impl().layer_tree_host_impl->active_tree()->ViewportSizeInvalid() || impl().layer_tree_host_impl->EvictedUIResourcesExist() || impl().input_throttled_until_commit) { // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active @@ -1386,16 +1232,19 @@ void ThreadProxy::DidActivateSyncTree() { if (impl().completion_event_for_commit_held_on_tree_activation) { TRACE_EVENT_INSTANT0( "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD); - DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting); impl().completion_event_for_commit_held_on_tree_activation->Signal(); impl().completion_event_for_commit_held_on_tree_activation = NULL; } - impl().timing_history.DidActivateSyncTree(); impl().last_processed_begin_main_frame_args = impl().last_begin_main_frame_args; } +void ThreadProxy::WillPrepareTiles() { + DCHECK(IsImplThread()); + impl().scheduler->WillPrepareTiles(); +} + void ThreadProxy::DidPrepareTiles() { DCHECK(IsImplThread()); impl().scheduler->DidPrepareTiles(); @@ -1413,4 +1262,23 @@ void ThreadProxy::OnDrawForOutputSurface() { impl().scheduler->OnDrawForOutputSurface(); } +void ThreadProxy::PostFrameTimingEventsOnImplThread( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) { + DCHECK(IsImplThread()); + Proxy::MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&ThreadProxy::PostFrameTimingEvents, main_thread_weak_ptr_, + base::Passed(composite_events.Pass()), + base::Passed(main_frame_events.Pass()))); +} + +void ThreadProxy::PostFrameTimingEvents( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) { + DCHECK(IsMainThread()); + layer_tree_host()->RecordFrameTimingEvents(composite_events.Pass(), + main_frame_events.Pass()); +} + } // namespace cc diff --git a/chromium/cc/trees/thread_proxy.h b/chromium/cc/trees/thread_proxy.h index f4f1f283c77..ca76e42669b 100644 --- a/chromium/cc/trees/thread_proxy.h +++ b/chromium/cc/trees/thread_proxy.h @@ -13,12 +13,10 @@ #include "cc/animation/animation_events.h" #include "cc/base/completion_event.h" #include "cc/base/delayed_unique_notifier.h" -#include "cc/resources/resource_update_controller.h" #include "cc/scheduler/commit_earlyout_reason.h" #include "cc/scheduler/scheduler.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/proxy.h" -#include "cc/trees/proxy_timing_history.h" namespace base { class SingleThreadTaskRunner; @@ -30,15 +28,12 @@ class BeginFrameSource; class ContextProvider; class InputHandlerClient; class LayerTreeHost; -class PrioritizedResourceManager; -class ResourceUpdateQueue; class Scheduler; class ScopedThreadProxy; class CC_EXPORT ThreadProxy : public Proxy, - NON_EXPORTED_BASE(LayerTreeHostImplClient), - NON_EXPORTED_BASE(SchedulerClient), - NON_EXPORTED_BASE(ResourceUpdateControllerClient) { + NON_EXPORTED_BASE(LayerTreeHostImplClient), + NON_EXPORTED_BASE(SchedulerClient) { public: static scoped_ptr<Proxy> Create( LayerTreeHost* layer_tree_host, @@ -56,7 +51,6 @@ class CC_EXPORT ThreadProxy : public Proxy, BeginFrameArgs begin_frame_args; scoped_ptr<ScrollAndScaleSet> scroll_info; size_t memory_allocation_limit_bytes; - int memory_allocation_priority_cutoff; bool evicted_ui_resources; }; @@ -88,8 +82,6 @@ class CC_EXPORT ThreadProxy : public Proxy, explicit MainThreadOrBlockedMainThread(LayerTreeHost* host); ~MainThreadOrBlockedMainThread(); - PrioritizedResourceManager* contents_texture_manager(); - LayerTreeHost* layer_tree_host; bool commit_waits_for_activation; bool main_thread_inside_commit; @@ -105,10 +97,6 @@ class CC_EXPORT ThreadProxy : public Proxy, const int layer_tree_host_id; - // Copy of the main thread side contents texture manager for work - // that needs to be done on the compositor thread. - PrioritizedResourceManager* contents_texture_manager; - scoped_ptr<Scheduler> scheduler; // Set when the main thread is waiting on a @@ -121,8 +109,6 @@ class CC_EXPORT ThreadProxy : public Proxy, // Set when the main thread is waiting on a pending tree activation. CompletionEvent* completion_event_for_commit_held_on_tree_activation; - scoped_ptr<ResourceUpdateController> current_resource_update_controller; - // Set when the next draw should post DidCommitAndDrawFrame to the main // thread. bool next_frame_is_newly_committed_frame; @@ -139,10 +125,10 @@ class CC_EXPORT ThreadProxy : public Proxy, DelayedUniqueNotifier smoothness_priority_expiration_notifier; - ProxyTimingHistory timing_history; - scoped_ptr<BeginFrameSource> external_begin_frame_source; + RenderingStatsInstrumentation* rendering_stats_instrumentation; + // Values used to keep track of frame durations. Used only in frame timing. BeginFrameArgs last_begin_main_frame_args; BeginFrameArgs last_processed_begin_main_frame_args; @@ -176,7 +162,6 @@ class CC_EXPORT ThreadProxy : public Proxy, void MainThreadHasStoppedFlinging() override; void Start() override; void Stop() override; - size_t MaxPartialTextureUpdates() const override; void ForceSerializeOnSwapBuffers() override; bool SupportsImplScrolling() const override; void SetDebugState(const LayerTreeDebugState& debug_state) override; @@ -207,16 +192,20 @@ class CC_EXPORT ThreadProxy : public Proxy, void SetVideoNeedsBeginFrames(bool needs_begin_frames) override; void PostAnimationEventsToMainThreadOnImplThread( scoped_ptr<AnimationEventsVector> queue) override; - bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes, - int priority_cutoff) override; bool IsInsideDraw() override; void RenewTreePriority() override; void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, base::TimeDelta delay) override; void DidActivateSyncTree() override; + void WillPrepareTiles() override; void DidPrepareTiles() override; void DidCompletePageScaleAnimationOnImplThread() override; void OnDrawForOutputSurface() override; + // This should only be called by LayerTreeHostImpl::PostFrameTimingEvents. + void PostFrameTimingEventsOnImplThread( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) + override; // SchedulerClient implementation void WillBeginImplFrame(const BeginFrameArgs& args) override; @@ -230,16 +219,9 @@ class CC_EXPORT ThreadProxy : public Proxy, void ScheduledActionBeginOutputSurfaceCreation() override; void ScheduledActionPrepareTiles() override; void ScheduledActionInvalidateOutputSurface() override; - void DidAnticipatedDrawTimeChange(base::TimeTicks time) override; - base::TimeDelta DrawDurationEstimate() override; - base::TimeDelta BeginMainFrameToCommitDurationEstimate() override; - base::TimeDelta CommitToActivateDurationEstimate() override; void SendBeginFramesToChildren(const BeginFrameArgs& args) override; void SendBeginMainFrameNotExpectedSoon() override; - // ResourceUpdateControllerClient implementation - void ReadyToFinalizeTextureUpdates() override; - protected: ThreadProxy( LayerTreeHost* layer_tree_host, @@ -267,8 +249,7 @@ class CC_EXPORT ThreadProxy : public Proxy, // Called on impl thread. struct SchedulerStateRequest; - void StartCommitOnImplThread(CompletionEvent* completion, - ResourceUpdateQueue* queue); + void StartCommitOnImplThread(CompletionEvent* completion); void BeginMainFrameAbortedOnImplThread(CommitEarlyOutReason reason); void FinishAllRenderingOnImplThread(CompletionEvent* completion); void InitializeImplOnImplThread(CompletionEvent* completion); @@ -292,6 +273,9 @@ class CC_EXPORT ThreadProxy : public Proxy, void SetInputThrottledUntilCommitOnImplThread(bool is_throttled); void SetDebugStateOnImplThread(const LayerTreeDebugState& debug_state); void SetDeferCommitsOnImplThread(bool defer_commits) const; + void PostFrameTimingEvents( + scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, + scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events); LayerTreeHost* layer_tree_host(); const LayerTreeHost* layer_tree_host() const; diff --git a/chromium/cc/trees/tree_synchronizer.cc b/chromium/cc/trees/tree_synchronizer.cc index 8fe23077a41..3646dcaa4f7 100644 --- a/chromium/cc/trees/tree_synchronizer.cc +++ b/chromium/cc/trees/tree_synchronizer.cc @@ -188,7 +188,7 @@ template <typename LayerType> void TreeSynchronizer::PushPropertiesInternal( LayerType* layer, LayerImpl* layer_impl, - size_t* num_dependents_need_push_properties_for_parent) { + int* num_dependents_need_push_properties_for_parent) { if (!layer) { DCHECK(!layer_impl); return; @@ -205,7 +205,7 @@ void TreeSynchronizer::PushPropertiesInternal( else if (layer->ToScrollbarLayer()) layer->ToScrollbarLayer()->PushScrollClipPropertiesTo(layer_impl); - size_t num_dependents_need_push_properties = 0; + int num_dependents_need_push_properties = 0; if (recurse_on_children_and_dependents) { PushPropertiesInternal(layer->mask_layer(), layer_impl->mask_layer(), @@ -295,7 +295,7 @@ static void CheckScrollAndClipPointersRecursive(Layer* layer, void TreeSynchronizer::PushProperties(Layer* layer, LayerImpl* layer_impl) { - size_t num_dependents_need_push_properties = 0; + int num_dependents_need_push_properties = 0; PushPropertiesInternal( layer, layer_impl, &num_dependents_need_push_properties); #if DCHECK_IS_ON() @@ -304,7 +304,7 @@ void TreeSynchronizer::PushProperties(Layer* layer, } void TreeSynchronizer::PushProperties(LayerImpl* layer, LayerImpl* layer_impl) { - size_t num_dependents_need_push_properties = 0; + int num_dependents_need_push_properties = 0; PushPropertiesInternal( layer, layer_impl, &num_dependents_need_push_properties); } diff --git a/chromium/cc/trees/tree_synchronizer.h b/chromium/cc/trees/tree_synchronizer.h index e7b2e2bdeda..ef13b1dba81 100644 --- a/chromium/cc/trees/tree_synchronizer.h +++ b/chromium/cc/trees/tree_synchronizer.h @@ -42,7 +42,7 @@ class CC_EXPORT TreeSynchronizer { static void PushPropertiesInternal( LayerType* layer, LayerImpl* layer_impl, - size_t* num_dependents_need_push_properties_for_parent); + int* num_dependents_need_push_properties_for_parent); DISALLOW_COPY_AND_ASSIGN(TreeSynchronizer); }; diff --git a/chromium/cc/trees/tree_synchronizer_unittest.cc b/chromium/cc/trees/tree_synchronizer_unittest.cc index a17bec8e53b..466a7017a72 100644 --- a/chromium/cc/trees/tree_synchronizer_unittest.cc +++ b/chromium/cc/trees/tree_synchronizer_unittest.cc @@ -18,6 +18,7 @@ #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_rendering_stats_instrumentation.h" #include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/proxy.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gtest/include/gtest/gtest.h" @@ -51,8 +52,10 @@ class MockLayerImpl : public LayerImpl { class MockLayer : public Layer { public: static scoped_refptr<MockLayer> Create( + const LayerSettings& settings, std::vector<int>* layer_impl_destruction_list) { - return make_scoped_refptr(new MockLayer(layer_impl_destruction_list)); + return make_scoped_refptr( + new MockLayer(settings, layer_impl_destruction_list)); } scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override { @@ -67,8 +70,10 @@ class MockLayer : public Layer { } private: - explicit MockLayer(std::vector<int>* layer_impl_destruction_list) - : Layer(), layer_impl_destruction_list_(layer_impl_destruction_list) {} + explicit MockLayer(const LayerSettings& settings, + std::vector<int>* layer_impl_destruction_list) + : Layer(settings), + layer_impl_destruction_list_(layer_impl_destruction_list) {} ~MockLayer() override {} std::vector<int>* layer_impl_destruction_list_; @@ -191,11 +196,13 @@ class TreeSynchronizerTest : public testing::Test { public: TreeSynchronizerTest() : client_(FakeLayerTreeHostClient::DIRECT_3D), - host_(FakeLayerTreeHost::Create(&client_)) {} + host_(FakeLayerTreeHost::Create(&client_, &task_graph_runner_)) {} protected: FakeLayerTreeHostClient client_; + TestTaskGraphRunner task_graph_runner_; scoped_ptr<FakeLayerTreeHost> host_; + LayerSettings layer_settings_; }; // Attempts to synchronizes a null tree. This should not crash, and should @@ -211,9 +218,9 @@ TEST_F(TreeSynchronizerTest, SyncNullTree) { // Constructs a very simple tree and synchronizes it without trying to reuse any // preexisting layers. TEST_F(TreeSynchronizerTest, SyncSimpleTreeFromEmpty) { - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - layer_tree_root->AddChild(Layer::Create()); - layer_tree_root->AddChild(Layer::Create()); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings_); + layer_tree_root->AddChild(Layer::Create(layer_settings_)); + layer_tree_root->AddChild(Layer::Create(layer_settings_)); host_->SetRootLayer(layer_tree_root); @@ -232,9 +239,11 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeReusingLayers) { std::vector<int> layer_impl_destruction_list; scoped_refptr<Layer> layer_tree_root = - MockLayer::Create(&layer_impl_destruction_list); - layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); - layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); + MockLayer::Create(layer_settings_, &layer_impl_destruction_list); + layer_tree_root->AddChild( + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); + layer_tree_root->AddChild( + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); host_->SetRootLayer(layer_tree_root); @@ -250,8 +259,8 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeReusingLayers) { layer_impl_tree_root.get()); // Add a new layer to the Layer side - layer_tree_root->children()[0]-> - AddChild(MockLayer::Create(&layer_impl_destruction_list)); + layer_tree_root->children()[0]->AddChild( + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); // Remove one. layer_tree_root->children()[1]->RemoveFromParent(); int second_layer_impl_id = layer_impl_tree_root->children()[1]->id(); @@ -278,9 +287,11 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndTrackStackingOrderChange) { // Set up the tree and sync once. child2 needs to be synced here, too, even // though we remove it to set up the intended scenario. scoped_refptr<Layer> layer_tree_root = - MockLayer::Create(&layer_impl_destruction_list); - scoped_refptr<Layer> child2 = MockLayer::Create(&layer_impl_destruction_list); - layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); + MockLayer::Create(layer_settings_, &layer_impl_destruction_list); + scoped_refptr<Layer> child2 = + MockLayer::Create(layer_settings_, &layer_impl_destruction_list); + layer_tree_root->AddChild( + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); layer_tree_root->AddChild(child2); host_->SetRootLayer(layer_tree_root); @@ -319,9 +330,9 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndTrackStackingOrderChange) { } TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndProperties) { - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - layer_tree_root->AddChild(Layer::Create()); - layer_tree_root->AddChild(Layer::Create()); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings_); + layer_tree_root->AddChild(Layer::Create(layer_settings_)); + layer_tree_root->AddChild(Layer::Create(layer_settings_)); host_->SetRootLayer(layer_tree_root); @@ -372,17 +383,21 @@ TEST_F(TreeSynchronizerTest, ReuseLayerImplsAfterStructuralChange) { // | // +--- D scoped_refptr<Layer> layer_tree_root = - MockLayer::Create(&layer_impl_destruction_list); - layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); + MockLayer::Create(layer_settings_, &layer_impl_destruction_list); + layer_tree_root->AddChild( + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); scoped_refptr<Layer> layer_a = layer_tree_root->children()[0].get(); - layer_a->AddChild(MockLayer::Create(&layer_impl_destruction_list)); + layer_a->AddChild( + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); scoped_refptr<Layer> layer_b = layer_a->children()[0].get(); - layer_b->AddChild(MockLayer::Create(&layer_impl_destruction_list)); + layer_b->AddChild( + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); scoped_refptr<Layer> layer_c = layer_b->children()[0].get(); - layer_b->AddChild(MockLayer::Create(&layer_impl_destruction_list)); + layer_b->AddChild( + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); scoped_refptr<Layer> layer_d = layer_b->children()[1].get(); host_->SetRootLayer(layer_tree_root); @@ -431,11 +446,11 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeThenDestroy) { std::vector<int> layer_impl_destruction_list; scoped_refptr<Layer> old_layer_tree_root = - MockLayer::Create(&layer_impl_destruction_list); + MockLayer::Create(layer_settings_, &layer_impl_destruction_list); old_layer_tree_root->AddChild( - MockLayer::Create(&layer_impl_destruction_list)); + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); old_layer_tree_root->AddChild( - MockLayer::Create(&layer_impl_destruction_list)); + MockLayer::Create(layer_settings_, &layer_impl_destruction_list)); host_->SetRootLayer(old_layer_tree_root); @@ -459,7 +474,7 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeThenDestroy) { // Synchronize again. After the sync all LayerImpls from the old tree should // be deleted. - scoped_refptr<Layer> new_layer_tree_root = Layer::Create(); + scoped_refptr<Layer> new_layer_tree_root = Layer::Create(layer_settings_); host_->SetRootLayer(new_layer_tree_root); layer_impl_tree_root = TreeSynchronizer::SynchronizeTrees(new_layer_tree_root.get(), @@ -487,22 +502,22 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeThenDestroy) { // Constructs+syncs a tree with mask, replica, and replica mask layers. TEST_F(TreeSynchronizerTest, SyncMaskReplicaAndReplicaMaskLayers) { - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - layer_tree_root->AddChild(Layer::Create()); - layer_tree_root->AddChild(Layer::Create()); - layer_tree_root->AddChild(Layer::Create()); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings_); + layer_tree_root->AddChild(Layer::Create(layer_settings_)); + layer_tree_root->AddChild(Layer::Create(layer_settings_)); + layer_tree_root->AddChild(Layer::Create(layer_settings_)); // First child gets a mask layer. - scoped_refptr<Layer> mask_layer = Layer::Create(); + scoped_refptr<Layer> mask_layer = Layer::Create(layer_settings_); layer_tree_root->children()[0]->SetMaskLayer(mask_layer.get()); // Second child gets a replica layer. - scoped_refptr<Layer> replica_layer = Layer::Create(); + scoped_refptr<Layer> replica_layer = Layer::Create(layer_settings_); layer_tree_root->children()[1]->SetReplicaLayer(replica_layer.get()); // Third child gets a replica layer with a mask layer. - scoped_refptr<Layer> replica_layer_with_mask = Layer::Create(); - scoped_refptr<Layer> replica_mask_layer = Layer::Create(); + scoped_refptr<Layer> replica_layer_with_mask = Layer::Create(layer_settings_); + scoped_refptr<Layer> replica_mask_layer = Layer::Create(layer_settings_); replica_layer_with_mask->SetMaskLayer(replica_mask_layer.get()); layer_tree_root->children()[2]-> SetReplicaLayer(replica_layer_with_mask.get()); @@ -553,13 +568,13 @@ TEST_F(TreeSynchronizerTest, SynchronizeAnimations) { FakeProxy proxy; DebugScopedSetImplThread impl(&proxy); FakeRenderingStatsInstrumentation stats_instrumentation; - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); - scoped_ptr<LayerTreeHostImpl> host_impl = - LayerTreeHostImpl::Create(settings, NULL, &proxy, &stats_instrumentation, - shared_bitmap_manager.get(), NULL, NULL, 0); + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( + settings, nullptr, &proxy, &stats_instrumentation, &shared_bitmap_manager, + nullptr, &task_graph_runner, 0); - scoped_refptr<Layer> layer_tree_root = Layer::Create(); + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings_); host_->SetRootLayer(layer_tree_root); layer_tree_root->SetLayerAnimationControllerForTest( @@ -587,17 +602,17 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollParent) { FakeProxy proxy; DebugScopedSetImplThread impl(&proxy); FakeRenderingStatsInstrumentation stats_instrumentation; - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); - scoped_ptr<LayerTreeHostImpl> host_impl = - LayerTreeHostImpl::Create(settings, NULL, &proxy, &stats_instrumentation, - shared_bitmap_manager.get(), NULL, NULL, 0); - - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - scoped_refptr<Layer> scroll_parent = Layer::Create(); + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( + settings, nullptr, &proxy, &stats_instrumentation, &shared_bitmap_manager, + nullptr, &task_graph_runner, 0); + + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings_); + scoped_refptr<Layer> scroll_parent = Layer::Create(layer_settings_); layer_tree_root->AddChild(scroll_parent); - layer_tree_root->AddChild(Layer::Create()); - layer_tree_root->AddChild(Layer::Create()); + layer_tree_root->AddChild(Layer::Create(layer_settings_)); + layer_tree_root->AddChild(Layer::Create(layer_settings_)); host_->SetRootLayer(layer_tree_root); @@ -633,7 +648,7 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollParent) { } // Add an additional scroll layer. - scoped_refptr<Layer> additional_scroll_child = Layer::Create(); + scoped_refptr<Layer> additional_scroll_child = Layer::Create(layer_settings_); layer_tree_root->AddChild(additional_scroll_child); additional_scroll_child->SetScrollParent(scroll_parent.get()); layer_impl_tree_root = @@ -655,17 +670,17 @@ TEST_F(TreeSynchronizerTest, SynchronizeClipParent) { FakeProxy proxy; DebugScopedSetImplThread impl(&proxy); FakeRenderingStatsInstrumentation stats_instrumentation; - scoped_ptr<SharedBitmapManager> shared_bitmap_manager( - new TestSharedBitmapManager()); - scoped_ptr<LayerTreeHostImpl> host_impl = - LayerTreeHostImpl::Create(settings, NULL, &proxy, &stats_instrumentation, - shared_bitmap_manager.get(), NULL, NULL, 0); - - scoped_refptr<Layer> layer_tree_root = Layer::Create(); - scoped_refptr<Layer> clip_parent = Layer::Create(); - scoped_refptr<Layer> intervening = Layer::Create(); - scoped_refptr<Layer> clip_child1 = Layer::Create(); - scoped_refptr<Layer> clip_child2 = Layer::Create(); + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( + settings, nullptr, &proxy, &stats_instrumentation, &shared_bitmap_manager, + nullptr, &task_graph_runner, 0); + + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings_); + scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings_); + scoped_refptr<Layer> intervening = Layer::Create(layer_settings_); + scoped_refptr<Layer> clip_child1 = Layer::Create(layer_settings_); + scoped_refptr<Layer> clip_child2 = Layer::Create(layer_settings_); layer_tree_root->AddChild(clip_parent); clip_parent->AddChild(intervening); intervening->AddChild(clip_child1); @@ -701,7 +716,7 @@ TEST_F(TreeSynchronizerTest, SynchronizeClipParent) { host_impl->active_tree()); // Add an additional clip child. - scoped_refptr<Layer> additional_clip_child = Layer::Create(); + scoped_refptr<Layer> additional_clip_child = Layer::Create(layer_settings_); intervening->AddChild(additional_clip_child); additional_clip_child->SetClipParent(clip_parent.get()); layer_impl_tree_root = |