diff options
Diffstat (limited to 'chromium/cc')
573 files changed, 15834 insertions, 11176 deletions
diff --git a/chromium/cc/BUILD.gn b/chromium/cc/BUILD.gn index e0d65133647..f791854447d 100644 --- a/chromium/cc/BUILD.gn +++ b/chromium/cc/BUILD.gn @@ -2,56 +2,31 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/ui.gni") import("//cc/cc.gni") +import("//gpu/vulkan/features.gni") cc_component("cc") { sources = [ - "debug/benchmark_instrumentation.cc", - "debug/benchmark_instrumentation.h", - "debug/debug_colors.cc", - "debug/debug_colors.h", - "debug/debug_rect_history.cc", - "debug/debug_rect_history.h", - "debug/devtools_instrumentation.cc", - "debug/devtools_instrumentation.h", - "debug/frame_rate_counter.cc", - "debug/frame_rate_counter.h", - "debug/frame_viewer_instrumentation.cc", - "debug/frame_viewer_instrumentation.h", - "debug/invalidation_benchmark.cc", - "debug/invalidation_benchmark.h", - "debug/lap_timer.cc", - "debug/lap_timer.h", - "debug/layer_tree_debug_state.cc", - "debug/layer_tree_debug_state.h", - "debug/micro_benchmark.cc", - "debug/micro_benchmark.h", - "debug/micro_benchmark_controller.cc", - "debug/micro_benchmark_controller.h", - "debug/micro_benchmark_controller_impl.cc", - "debug/micro_benchmark_controller_impl.h", - "debug/micro_benchmark_impl.cc", - "debug/micro_benchmark_impl.h", - "debug/picture_debug_util.cc", - "debug/picture_debug_util.h", - "debug/rasterize_and_record_benchmark.cc", - "debug/rasterize_and_record_benchmark.h", - "debug/rasterize_and_record_benchmark_impl.cc", - "debug/rasterize_and_record_benchmark_impl.h", - "debug/rendering_stats.cc", - "debug/rendering_stats.h", - "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_value.cc", - "debug/traced_value.h", - "debug/unittest_only_benchmark.cc", - "debug/unittest_only_benchmark.h", - "debug/unittest_only_benchmark_impl.cc", - "debug/unittest_only_benchmark_impl.h", + "benchmarks/benchmark_instrumentation.cc", + "benchmarks/benchmark_instrumentation.h", + "benchmarks/invalidation_benchmark.cc", + "benchmarks/invalidation_benchmark.h", + "benchmarks/micro_benchmark.cc", + "benchmarks/micro_benchmark.h", + "benchmarks/micro_benchmark_controller.cc", + "benchmarks/micro_benchmark_controller.h", + "benchmarks/micro_benchmark_controller_impl.cc", + "benchmarks/micro_benchmark_controller_impl.h", + "benchmarks/micro_benchmark_impl.cc", + "benchmarks/micro_benchmark_impl.h", + "benchmarks/rasterize_and_record_benchmark.cc", + "benchmarks/rasterize_and_record_benchmark.h", + "benchmarks/rasterize_and_record_benchmark_impl.cc", + "benchmarks/rasterize_and_record_benchmark_impl.h", + "benchmarks/unittest_only_benchmark.cc", + "benchmarks/unittest_only_benchmark.h", + "benchmarks/unittest_only_benchmark_impl.cc", + "benchmarks/unittest_only_benchmark_impl.h", "input/browser_controls_offset_manager.cc", "input/browser_controls_offset_manager.h", "input/browser_controls_offset_manager_client.h", @@ -73,12 +48,13 @@ cc_component("cc") { "input/selection.h", "input/single_scrollbar_animation_controller_thinning.cc", "input/single_scrollbar_animation_controller_thinning.h", + "layers/append_quads_data.cc", "layers/append_quads_data.h", "layers/content_layer_client.h", "layers/draw_properties.cc", "layers/draw_properties.h", - "layers/empty_content_layer_client.cc", - "layers/empty_content_layer_client.h", + "layers/effect_tree_layer_list_iterator.cc", + "layers/effect_tree_layer_list_iterator.h", "layers/heads_up_display_layer.cc", "layers/heads_up_display_layer.h", "layers/heads_up_display_layer_impl.cc", @@ -91,7 +67,6 @@ cc_component("cc") { "layers/layer_impl.h", "layers/layer_impl_test_properties.cc", "layers/layer_impl_test_properties.h", - "layers/layer_iterator.h", "layers/layer_list_iterator.cc", "layers/layer_list_iterator.h", "layers/layer_position_constraint.cc", @@ -119,7 +94,8 @@ cc_component("cc") { "layers/picture_layer.h", "layers/picture_layer_impl.cc", "layers/picture_layer_impl.h", - "layers/render_pass_sink.h", + "layers/recording_source.cc", + "layers/recording_source.h", "layers/render_surface_impl.cc", "layers/render_surface_impl.h", "layers/scrollbar_layer_impl_base.cc", @@ -182,14 +158,12 @@ cc_component("cc") { "output/copy_output_request.h", "output/copy_output_result.cc", "output/copy_output_result.h", + "output/dc_layer_overlay.cc", + "output/dc_layer_overlay.h", "output/direct_renderer.cc", "output/direct_renderer.h", "output/dynamic_geometry_binding.cc", "output/dynamic_geometry_binding.h", - "output/filter_operation.cc", - "output/filter_operation.h", - "output/filter_operations.cc", - "output/filter_operations.h", "output/geometry_binding.cc", "output/geometry_binding.h", "output/gl_renderer.cc", @@ -224,8 +198,6 @@ cc_component("cc") { "output/overlay_strategy_underlay_cast.h", "output/program_binding.cc", "output/program_binding.h", - "output/render_surface_filters.cc", - "output/render_surface_filters.h", "output/renderer_settings.cc", "output/renderer_settings.h", "output/shader.cc", @@ -242,40 +214,6 @@ cc_component("cc") { "output/vulkan_context_provider.h", "output/vulkan_in_process_context_provider.cc", "output/vulkan_in_process_context_provider.h", - "playback/clip_display_item.cc", - "playback/clip_display_item.h", - "playback/clip_path_display_item.cc", - "playback/clip_path_display_item.h", - "playback/compositing_display_item.cc", - "playback/compositing_display_item.h", - "playback/decoded_draw_image.cc", - "playback/decoded_draw_image.h", - "playback/discardable_image_map.cc", - "playback/discardable_image_map.h", - "playback/display_item.h", - "playback/display_item_list.cc", - "playback/display_item_list.h", - "playback/draw_image.cc", - "playback/draw_image.h", - "playback/drawing_display_item.cc", - "playback/drawing_display_item.h", - "playback/filter_display_item.cc", - "playback/filter_display_item.h", - "playback/float_clip_display_item.cc", - "playback/float_clip_display_item.h", - "playback/image_hijack_canvas.cc", - "playback/image_hijack_canvas.h", - "playback/image_id.h", - "playback/largest_display_item.cc", - "playback/largest_display_item.h", - "playback/raster_source.cc", - "playback/raster_source.h", - "playback/recording_source.cc", - "playback/recording_source.h", - "playback/skip_image_canvas.cc", - "playback/skip_image_canvas.h", - "playback/transform_display_item.cc", - "playback/transform_display_item.h", "quads/content_draw_quad_base.cc", "quads/content_draw_quad_base.h", "quads/debug_border_draw_quad.cc", @@ -312,16 +250,22 @@ cc_component("cc") { "raster/bitmap_raster_buffer_provider.h", "raster/gpu_raster_buffer_provider.cc", "raster/gpu_raster_buffer_provider.h", + "raster/image_hijack_canvas.cc", + "raster/image_hijack_canvas.h", "raster/one_copy_raster_buffer_provider.cc", "raster/one_copy_raster_buffer_provider.h", "raster/raster_buffer.cc", "raster/raster_buffer.h", "raster/raster_buffer_provider.cc", "raster/raster_buffer_provider.h", + "raster/raster_source.cc", + "raster/raster_source.h", "raster/scoped_gpu_raster.cc", "raster/scoped_gpu_raster.h", "raster/single_thread_task_graph_runner.cc", "raster/single_thread_task_graph_runner.h", + "raster/skip_image_canvas.cc", + "raster/skip_image_canvas.h", "raster/staging_buffer_pool.cc", "raster/staging_buffer_pool.h", "raster/synchronous_task_graph_runner.cc", @@ -398,10 +342,14 @@ cc_component("cc") { "scheduler/video_frame_controller.h", "tiles/checker_image_tracker.cc", "tiles/checker_image_tracker.h", + "tiles/decoded_draw_image.cc", + "tiles/decoded_draw_image.h", "tiles/decoded_image_tracker.cc", "tiles/decoded_image_tracker.h", "tiles/eviction_tile_priority_queue.cc", "tiles/eviction_tile_priority_queue.h", + "tiles/frame_viewer_instrumentation.cc", + "tiles/frame_viewer_instrumentation.h", "tiles/gpu_image_decode_cache.cc", "tiles/gpu_image_decode_cache.h", "tiles/image_controller.cc", @@ -449,12 +397,16 @@ cc_component("cc") { "trees/compositor_mode.h", "trees/damage_tracker.cc", "trees/damage_tracker.h", + "trees/debug_rect_history.cc", + "trees/debug_rect_history.h", "trees/draw_property_utils.cc", "trees/draw_property_utils.h", "trees/effect_node.cc", "trees/effect_node.h", "trees/element_id.cc", "trees/element_id.h", + "trees/frame_rate_counter.cc", + "trees/frame_rate_counter.h", "trees/latency_info_swap_promise_monitor.cc", "trees/latency_info_swap_promise_monitor.h", "trees/layer_tree_host.cc", @@ -533,6 +485,7 @@ cc_component("cc") { "//gpu/command_buffer/client:gles2_interface", "//gpu/ipc:gl_in_process_context", "//gpu/skia_bindings:skia_bindings", + "//gpu/vulkan:features", "//media", "//mojo/public/cpp/bindings:struct_traits", "//third_party/libyuv", @@ -540,6 +493,7 @@ cc_component("cc") { "//ui/gfx", "//ui/gfx/geometry", "//ui/gl", + "//ui/latency", ] defines = [ "CC_IMPLEMENTATION=1" ] @@ -569,6 +523,8 @@ cc_static_library("test_support") { "test/fake_compositor_frame_sink.h", "test/fake_compositor_frame_sink_client.cc", "test/fake_compositor_frame_sink_client.h", + "test/fake_compositor_frame_sink_support_client.cc", + "test/fake_compositor_frame_sink_support_client.h", "test/fake_content_layer_client.cc", "test/fake_content_layer_client.h", "test/fake_external_begin_frame_source.cc", @@ -630,8 +586,6 @@ cc_static_library("test_support") { "test/layer_tree_pixel_resource_test.h", "test/layer_tree_pixel_test.cc", "test/layer_tree_pixel_test.h", - "test/layer_tree_settings_for_testing.cc", - "test/layer_tree_settings_for_testing.h", "test/layer_tree_test.cc", "test/layer_tree_test.h", "test/mock_helper.h", @@ -731,6 +685,7 @@ cc_static_library("test_support") { "//ui/gfx/geometry", "//ui/gl", "//ui/gl:test_support", + "//ui/latency", ] if (!is_android) { data_deps = [ @@ -743,6 +698,7 @@ cc_test("cc_unittests") { sources = [ "base/contiguous_container_unittest.cc", "base/delayed_unique_notifier_unittest.cc", + "base/filter_operations_unittest.cc", "base/float_quad_unittest.cc", "base/histograms_unittest.cc", "base/index_rect_unittest.cc", @@ -756,7 +712,7 @@ cc_test("cc_unittests") { "base/spiral_iterator_unittest.cc", "base/tiling_data_unittest.cc", "base/unique_notifier_unittest.cc", - "debug/micro_benchmark_controller_unittest.cc", + "benchmarks/micro_benchmark_controller_unittest.cc", "debug/rendering_stats_unittest.cc", "input/browser_controls_offset_manager_unittest.cc", "input/scroll_state_unittest.cc", @@ -764,10 +720,10 @@ cc_test("cc_unittests") { "input/single_scrollbar_animation_controller_thinning_unittest.cc", "ipc/cc_param_traits_unittest.cc", "ipc/struct_traits_unittest.cc", + "layers/effect_tree_layer_list_iterator_unittest.cc", "layers/heads_up_display_layer_impl_unittest.cc", "layers/heads_up_display_unittest.cc", "layers/layer_impl_unittest.cc", - "layers/layer_iterator_unittest.cc", "layers/layer_list_iterator_unittest.cc", "layers/layer_position_constraint_unittest.cc", "layers/layer_unittest.cc", @@ -779,6 +735,7 @@ cc_test("cc_unittests") { "layers/picture_image_layer_unittest.cc", "layers/picture_layer_impl_unittest.cc", "layers/picture_layer_unittest.cc", + "layers/recording_source_unittest.cc", "layers/render_surface_impl_unittest.cc", "layers/render_surface_unittest.cc", "layers/scrollbar_layer_unittest.cc", @@ -798,7 +755,6 @@ cc_test("cc_unittests") { "output/buffer_to_texture_target_map_unittest.cc", "output/compositor_frame_sink_unittest.cc", "output/context_cache_controller_unittest.cc", - "output/filter_operations_unittest.cc", "output/gl_renderer_unittest.cc", "output/layer_quad_unittest.cc", "output/overlay_unittest.cc", @@ -806,16 +762,15 @@ cc_test("cc_unittests") { "output/shader_unittest.cc", "output/software_renderer_unittest.cc", "output/texture_mailbox_deleter_unittest.cc", - "playback/discardable_image_map_unittest.cc", - "playback/display_item_list_unittest.cc", - "playback/image_hijack_canvas_unittest.cc", - "playback/raster_source_unittest.cc", - "playback/recording_source_unittest.cc", + "paint/discardable_image_map_unittest.cc", + "paint/display_item_list_unittest.cc", "quads/draw_polygon_unittest.cc", "quads/draw_quad_unittest.cc", "quads/nine_patch_generator_unittest.cc", "quads/render_pass_unittest.cc", + "raster/image_hijack_canvas_unittest.cc", "raster/raster_buffer_provider_unittest.cc", + "raster/raster_source_unittest.cc", "raster/scoped_gpu_raster_unittest.cc", "raster/single_thread_task_graph_runner_unittest.cc", "raster/synchronous_task_graph_runner_unittest.cc", @@ -904,6 +859,7 @@ cc_test("cc_unittests") { # Setup. "test/cc_test_suite.cc", + "test/cc_test_suite.h", "test/run_all_unittests.cc", ] @@ -962,6 +918,7 @@ cc_test("cc_perftests") { "raster/texture_compressor_perftest.cc", "surfaces/surface_aggregator_perftest.cc", "test/cc_test_suite.cc", + "test/cc_test_suite.h", "test/run_all_perftests.cc", "tiles/software_image_decode_cache_perftest.cc", "tiles/tile_manager_perftest.cc", @@ -976,6 +933,7 @@ cc_test("cc_perftests") { "//base/test:test_support", "//cc/ipc", "//cc/ipc:interfaces", + "//cc/paint", "//cc/surfaces", "//cc/surfaces:surface_id", "//gpu", diff --git a/chromium/cc/DEPS b/chromium/cc/DEPS index bbab8316a10..0701904ad63 100644 --- a/chromium/cc/DEPS +++ b/chromium/cc/DEPS @@ -17,7 +17,7 @@ include_rules = [ "+third_party/khronos/GLES2/gl2ext.h", "+third_party/libyuv", "+third_party/skia/include", - "+ui/events/latency_info.h", + "+ui/latency/latency_info.h", "+ui/gfx", "+ui/gl", "-cc/blink", diff --git a/chromium/cc/OWNERS b/chromium/cc/OWNERS index cbba2c2b779..5a30b1399e8 100644 --- a/chromium/cc/OWNERS +++ b/chromium/cc/OWNERS @@ -57,9 +57,5 @@ ajuma@chromium.org # nduca@chromium.org # mithro@mithis.com / tansell@chromium.org -per-file *.isolate=maruel@chromium.org -per-file *.isolate=tandrii@chromium.org -per-file *.isolate=vadimsh@chromium.org - # TEAM: graphics-dev@chromium.org # COMPONENT: Internals>Compositing diff --git a/chromium/cc/PRESUBMIT.py b/chromium/cc/PRESUBMIT.py index c89768a81b6..1c1ff82e3ae 100644 --- a/chromium/cc/PRESUBMIT.py +++ b/chromium/cc/PRESUBMIT.py @@ -25,25 +25,17 @@ def CheckAsserts(input_api, output_api, white_list=CC_SOURCE_FILES, black_list=N source_file_filter = lambda x: input_api.FilterSourceFile(x, white_list, black_list) assert_files = [] - notreached_files = [] for f in input_api.AffectedSourceFiles(source_file_filter): contents = input_api.ReadFile(f, 'rb') # WebKit ASSERT() is not allowed. if re.search(r"\bASSERT\(", contents): assert_files.append(f.LocalPath()) - # WebKit ASSERT_NOT_REACHED() is not allowed. - if re.search(r"ASSERT_NOT_REACHED\(", contents): - notreached_files.append(f.LocalPath()) if assert_files: return [output_api.PresubmitError( 'These files use ASSERT instead of using DCHECK:', items=assert_files)] - if notreached_files: - return [output_api.PresubmitError( - 'These files use ASSERT_NOT_REACHED instead of using NOTREACHED:', - items=notreached_files)] return [] def CheckStdAbs(input_api, output_api, @@ -103,7 +95,7 @@ def CheckPassByValue(input_api, local_errors = [] - # Well-defined simple classes containing only <= 4 ints, or <= 2 floats. + # Well-defined simple classes the same size as a primitive type. pass_by_value_types = ['base::Time', 'base::TimeTicks', ] @@ -131,7 +123,7 @@ def CheckTodos(input_api, output_api): if errors: return [output_api.PresubmitError( - 'All TODO comments should be of the form TODO(name). ' + + 'All TODO comments should be of the form TODO(name/bug). ' + 'Use TODO instead of FIX' + 'ME', items=errors)] return [] diff --git a/chromium/cc/animation/DEPS b/chromium/cc/animation/DEPS index 3b405773b4a..e4afe36c79c 100644 --- a/chromium/cc/animation/DEPS +++ b/chromium/cc/animation/DEPS @@ -3,6 +3,7 @@ include_rules = [ "+cc/animation", "+cc/base", "+cc/debug", + "+cc/paint", "+cc/output/filter_operations.h", "+cc/test", "+cc/trees/element_id.h", diff --git a/chromium/cc/animation/animation_curve.h b/chromium/cc/animation/animation_curve.h index 4564446af6a..72b8e630914 100644 --- a/chromium/cc/animation/animation_curve.h +++ b/chromium/cc/animation/animation_curve.h @@ -9,7 +9,7 @@ #include "base/time/time.h" #include "cc/animation/animation_export.h" -#include "cc/output/filter_operations.h" +#include "cc/base/filter_operations.h" #include "ui/gfx/transform.h" namespace gfx { diff --git a/chromium/cc/animation/animation_events.h b/chromium/cc/animation/animation_events.h index d0f4709cf23..65a7ae67134 100644 --- a/chromium/cc/animation/animation_events.h +++ b/chromium/cc/animation/animation_events.h @@ -11,7 +11,7 @@ #include "cc/animation/animation.h" #include "cc/animation/animation_curve.h" #include "cc/animation/animation_export.h" -#include "cc/output/filter_operations.h" +#include "cc/base/filter_operations.h" #include "cc/trees/element_id.h" #include "cc/trees/mutator_host.h" #include "ui/gfx/transform.h" diff --git a/chromium/cc/animation/animation_host_perftest.cc b/chromium/cc/animation/animation_host_perftest.cc index 776a6872fac..4da56d00649 100644 --- a/chromium/cc/animation/animation_host_perftest.cc +++ b/chromium/cc/animation/animation_host_perftest.cc @@ -8,7 +8,7 @@ #include "cc/animation/animation_id_provider.h" #include "cc/animation/animation_player.h" #include "cc/animation/animation_timeline.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" diff --git a/chromium/cc/animation/animation_player.cc b/chromium/cc/animation/animation_player.cc index b45bc6b018d..634d64948ae 100644 --- a/chromium/cc/animation/animation_player.cc +++ b/chromium/cc/animation/animation_player.cc @@ -6,6 +6,7 @@ #include <algorithm> +#include "base/stl_util.h" #include "cc/animation/animation_delegate.h" #include "cc/animation/animation_events.h" #include "cc/animation/animation_host.h" @@ -817,9 +818,7 @@ void AnimationPlayer::ActivateAnimations() { return !animation->affects_active_elements() && !animation->affects_pending_elements(); }; - animations_.erase(std::remove_if(animations_.begin(), animations_.end(), - affects_no_elements), - animations_.end()); + base::EraseIf(animations_, affects_no_elements); if (animation_activated) element_animations_->UpdateClientAnimationState(); @@ -1101,14 +1100,11 @@ void AnimationPlayer::MarkAbortedAnimationsForDeletion( } void AnimationPlayer::PurgeAnimationsMarkedForDeletion(bool impl_only) { - animations_.erase( - std::remove_if(animations_.begin(), animations_.end(), - [impl_only](const std::unique_ptr<Animation>& animation) { - return animation->run_state() == - Animation::WAITING_FOR_DELETION && - (!impl_only || animation->is_impl_only()); - }), - animations_.end()); + base::EraseIf( + animations_, [impl_only](const std::unique_ptr<Animation>& animation) { + return animation->run_state() == Animation::WAITING_FOR_DELETION && + (!impl_only || animation->is_impl_only()); + }); } void AnimationPlayer::PushNewAnimationsToImplThread( @@ -1179,10 +1175,7 @@ void AnimationPlayer::RemoveAnimationsCompletedOnMainThread( return animation->run_state() == Animation::WAITING_FOR_DELETION && !animation->affects_pending_elements(); }; - animations.erase( - std::remove_if(animations.begin(), animations.end(), - affects_active_only_and_is_waiting_for_deletion), - animations.end()); + base::EraseIf(animations, affects_active_only_and_is_waiting_for_deletion); if (element_animations_ && animation_completed) element_animations_->SetNeedsUpdateImplClientState(); diff --git a/chromium/cc/animation/element_animations.cc b/chromium/cc/animation/element_animations.cc index 5e30ac1db8e..ebb9c3fc83e 100644 --- a/chromium/cc/animation/element_animations.cc +++ b/chromium/cc/animation/element_animations.cc @@ -15,7 +15,7 @@ #include "cc/animation/animation_host.h" #include "cc/animation/animation_player.h" #include "cc/animation/keyframed_animation_curve.h" -#include "cc/output/filter_operations.h" +#include "cc/base/filter_operations.h" #include "cc/trees/mutator_host_client.h" #include "ui/gfx/geometry/box_f.h" diff --git a/chromium/cc/animation/element_animations_unittest.cc b/chromium/cc/animation/element_animations_unittest.cc index c6cb2d27db4..75e69c9b25a 100644 --- a/chromium/cc/animation/element_animations_unittest.cc +++ b/chromium/cc/animation/element_animations_unittest.cc @@ -3588,5 +3588,27 @@ TEST_F(ElementAnimationsTest, DestroyTestMainLayerBeforePushProperties) { EXPECT_EQ(0u, host_impl_->ticking_players_for_testing().size()); } +TEST_F(ElementAnimationsTest, RemoveAndReAddPlayerToTicking) { + CreateTestLayer(false, false); + AttachTimelinePlayerLayer(); + EXPECT_EQ(0u, host_->ticking_players_for_testing().size()); + + // Add an animation and ensure the player is in the host's ticking players. + // Remove the player using RemoveFromTicking(). + player_->AddAnimation(CreateAnimation( + std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)), + 2, TargetProperty::OPACITY)); + ASSERT_EQ(1u, host_->ticking_players_for_testing().size()); + player_->RemoveFromTicking(); + ASSERT_EQ(0u, host_->ticking_players_for_testing().size()); + + // Ensure that adding a new animation will correctly update the ticking + // players list. + player_->AddAnimation(CreateAnimation( + std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)), + 2, TargetProperty::OPACITY)); + EXPECT_EQ(1u, host_->ticking_players_for_testing().size()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/base/BUILD.gn b/chromium/cc/base/BUILD.gn index ee72bb2c691..db70d19adb3 100644 --- a/chromium/cc/base/BUILD.gn +++ b/chromium/cc/base/BUILD.gn @@ -4,22 +4,30 @@ import("//cc/cc.gni") -cc_source_set("base") { - visibility = [ "//cc" ] - +component("base") { + output_name = "cc_base" sources = [ + "base_export.h", "completion_event.h", "container_util.h", "contiguous_container.cc", "contiguous_container.h", "delayed_unique_notifier.cc", "delayed_unique_notifier.h", + "devtools_instrumentation.cc", + "devtools_instrumentation.h", + "filter_operation.cc", + "filter_operation.h", + "filter_operations.cc", + "filter_operations.h", "histograms.cc", "histograms.h", "index_rect.cc", "index_rect.h", "invalidation_region.cc", "invalidation_region.h", + "lap_timer.cc", + "lap_timer.h", "list_container.h", "list_container_helper.cc", "list_container_helper.h", @@ -28,6 +36,8 @@ cc_source_set("base") { "random_access_list_container.h", "region.cc", "region.h", + "render_surface_filters.cc", + "render_surface_filters.h", "resource_id.h", "reverse_spiral_iterator.cc", "reverse_spiral_iterator.h", @@ -53,9 +63,10 @@ cc_source_set("base") { "//base", "//base/third_party/dynamic_annotations", "//skia", - "//ui/gfx", + "//ui/gfx:geometry_skia", + "//ui/gfx/animation", "//ui/gfx/geometry", ] - defines = [ "CC_IMPLEMENTATION=1" ] + defines = [ "CC_BASE_IMPLEMENTATION=1" ] } diff --git a/chromium/cc/base/base_export.h b/chromium/cc/base/base_export.h new file mode 100644 index 00000000000..3d7e02439e9 --- /dev/null +++ b/chromium/cc/base/base_export.h @@ -0,0 +1,29 @@ +// Copyright 2017 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_BASE_EXPORT_H_ +#define CC_BASE_BASE_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(CC_BASE_IMPLEMENTATION) +#define CC_BASE_EXPORT __declspec(dllexport) +#else +#define CC_BASE_EXPORT __declspec(dllimport) +#endif // defined(CC_BASE_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(CC_BASE_IMPLEMENTATION) +#define CC_BASE_EXPORT __attribute__((visibility("default"))) +#else +#define CC_BASE_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define CC_BASE_EXPORT +#endif + +#endif // CC_BASE_BASE_EXPORT_H_ diff --git a/chromium/cc/base/completion_event.h b/chromium/cc/base/completion_event.h index edee0b78bf0..0c620db4e72 100644 --- a/chromium/cc/base/completion_event.h +++ b/chromium/cc/base/completion_event.h @@ -43,12 +43,18 @@ class CompletionEvent { event_.Wait(); } - void TimedWait(const base::TimeDelta& max_time) { + bool TimedWait(const base::TimeDelta& max_time) { #if DCHECK_IS_ON() DCHECK(!waited_); waited_ = true; #endif - event_.TimedWait(max_time); + base::ThreadRestrictions::ScopedAllowWait allow_wait; + if (event_.TimedWait(max_time)) + return true; +#if DCHECK_IS_ON() + waited_ = false; +#endif + return false; } bool IsSignaled() { return event_.IsSignaled(); } diff --git a/chromium/cc/base/contiguous_container.cc b/chromium/cc/base/contiguous_container.cc index 59953b34db4..aa4f39dc008 100644 --- a/chromium/cc/base/contiguous_container.cc +++ b/chromium/cc/base/contiguous_container.cc @@ -5,7 +5,6 @@ #include "cc/base/contiguous_container.h" #include <stddef.h> - #include <algorithm> #include <utility> @@ -17,51 +16,43 @@ static const unsigned kDefaultInitialBufferSize = 32; class ContiguousContainerBase::Buffer { public: - explicit Buffer(size_t buffer_size) : end_(nullptr), capacity_(buffer_size) {} + explicit Buffer(size_t buffer_size) : capacity_(buffer_size) {} + ~Buffer() = default; - ~Buffer() {} + Buffer(Buffer&&) = default; + Buffer& operator=(Buffer&&) = default; size_t Capacity() const { return capacity_; } - size_t UsedCapacity() const { return end_ - begin(); } + size_t UsedCapacity() const { return end_ - data_.get(); } size_t UnusedCapacity() const { return Capacity() - UsedCapacity(); } - size_t MemoryUsage() const { return begin() ? capacity_ : 0; } + size_t MemoryUsage() const { return data_ ? capacity_ : 0; } bool empty() const { return UsedCapacity() == 0; } void* Allocate(size_t object_size) { DCHECK_GE(UnusedCapacity(), object_size); if (!data_) { data_.reset(new char[capacity_]); - end_ = begin(); + end_ = data_.get(); } void* result = end_; end_ += object_size; return result; } - void DeallocateLastObject(void* object) { - DCHECK_LE(begin(), object); - DCHECK_LT(object, end_); - end_ = static_cast<char*>(object); - } - private: - char* begin() { return data_.get(); } - const char* begin() const { return data_.get(); } - - // begin() <= end_ <= begin() + capacity_ - std::unique_ptr<char[]> data_; - char* end_; size_t capacity_; + std::unique_ptr<char[]> data_; + // begin() <= end_ <= begin() + capacity_ + char* end_ = nullptr; }; ContiguousContainerBase::ContiguousContainerBase(size_t max_object_size) - : end_index_(0), max_object_size_(max_object_size) {} + : max_object_size_(max_object_size) {} ContiguousContainerBase::ContiguousContainerBase(size_t max_object_size, size_t initial_size_bytes) - : ContiguousContainerBase(max_object_size) { - AllocateNewBufferForNextAllocation( - std::max(max_object_size, initial_size_bytes)); + : max_object_size_(max_object_size) { + buffers_.emplace_back(std::max(max_object_size_, initial_size_bytes)); } ContiguousContainerBase::~ContiguousContainerBase() {} @@ -69,21 +60,21 @@ ContiguousContainerBase::~ContiguousContainerBase() {} size_t ContiguousContainerBase::GetCapacityInBytes() const { size_t capacity = 0; for (const auto& buffer : buffers_) - capacity += buffer->Capacity(); + capacity += buffer.Capacity(); return capacity; } size_t ContiguousContainerBase::UsedCapacityInBytes() const { size_t used_capacity = 0; for (const auto& buffer : buffers_) - used_capacity += buffer->UsedCapacity(); + used_capacity += buffer.UsedCapacity(); return used_capacity; } size_t ContiguousContainerBase::MemoryUsageInBytes() const { size_t memory_usage = 0; for (const auto& buffer : buffers_) - memory_usage += buffer->MemoryUsage(); + memory_usage += buffer.MemoryUsage(); return sizeof(*this) + memory_usage + elements_.capacity() * sizeof(elements_[0]); } @@ -91,64 +82,14 @@ size_t ContiguousContainerBase::MemoryUsageInBytes() const { void* ContiguousContainerBase::Allocate(size_t object_size) { DCHECK_LE(object_size, max_object_size_); - Buffer* buffer_for_alloc = nullptr; - if (!buffers_.empty()) { - Buffer* end_buffer = buffers_[end_index_].get(); - if (end_buffer->UnusedCapacity() >= object_size) - buffer_for_alloc = end_buffer; - else if (end_index_ + 1 < buffers_.size()) - buffer_for_alloc = buffers_[++end_index_].get(); - } - - if (!buffer_for_alloc) { - size_t new_buffer_size = buffers_.empty() - ? kDefaultInitialBufferSize * max_object_size_ - : 2 * buffers_.back()->Capacity(); - buffer_for_alloc = AllocateNewBufferForNextAllocation(new_buffer_size); - } + if (buffers_.empty()) + buffers_.emplace_back(kDefaultInitialBufferSize * max_object_size_); + else if (buffers_.back().UnusedCapacity() < object_size) + buffers_.emplace_back(2 * buffers_.back().Capacity()); - void* element = buffer_for_alloc->Allocate(object_size); + void* element = buffers_.back().Allocate(object_size); elements_.push_back(element); return element; } -void ContiguousContainerBase::RemoveLast() { - void* object = elements_.back(); - elements_.pop_back(); - - Buffer* end_buffer = buffers_[end_index_].get(); - end_buffer->DeallocateLastObject(object); - - if (end_buffer->empty()) { - if (end_index_ > 0) - end_index_--; - if (end_index_ + 2 < buffers_.size()) - buffers_.pop_back(); - } -} - -void ContiguousContainerBase::Clear() { - elements_.clear(); - buffers_.clear(); - end_index_ = 0; -} - -void ContiguousContainerBase::Swap(ContiguousContainerBase& other) { - elements_.swap(other.elements_); - buffers_.swap(other.buffers_); - std::swap(end_index_, other.end_index_); - std::swap(max_object_size_, other.max_object_size_); -} - -ContiguousContainerBase::Buffer* -ContiguousContainerBase::AllocateNewBufferForNextAllocation( - size_t buffer_size) { - DCHECK(buffers_.empty() || end_index_ == buffers_.size() - 1); - std::unique_ptr<Buffer> new_buffer(new Buffer(buffer_size)); - Buffer* buffer_to_return = new_buffer.get(); - buffers_.push_back(std::move(new_buffer)); - end_index_ = buffers_.size() - 1; - return buffer_to_return; -} - } // namespace cc diff --git a/chromium/cc/base/contiguous_container.h b/chromium/cc/base/contiguous_container.h index d0285fcf8f0..3dd3fecde74 100644 --- a/chromium/cc/base/contiguous_container.h +++ b/chromium/cc/base/contiguous_container.h @@ -14,7 +14,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" namespace cc { @@ -36,7 +36,7 @@ namespace cc { // Clients should instantiate ContiguousContainer; ContiguousContainerBase is an // artifact of the implementation. -class CC_EXPORT ContiguousContainerBase { +class CC_BASE_EXPORT ContiguousContainerBase { protected: explicit ContiguousContainerBase(size_t max_object_size); ContiguousContainerBase(size_t max_object_size, size_t initial_size_bytes); @@ -50,20 +50,14 @@ class CC_EXPORT ContiguousContainerBase { // These do not invoke constructors or destructors. void* Allocate(size_t object_size); - void Clear(); - void RemoveLast(); - void Swap(ContiguousContainerBase& other); std::vector<void*> elements_; private: - class Buffer; - - Buffer* AllocateNewBufferForNextAllocation(size_t buffer_size); + const size_t max_object_size_; - std::vector<std::unique_ptr<Buffer>> buffers_; - size_t end_index_; - size_t max_object_size_; + class Buffer; + std::vector<Buffer> buffers_; DISALLOW_COPY_AND_ASSIGN(ContiguousContainerBase); }; @@ -175,35 +169,6 @@ class ContiguousContainer : public ContiguousContainerBase { DerivedElementType(std::forward<Args>(args)...); } - void RemoveLast() { - DCHECK(!empty()); - last().~BaseElementType(); - ContiguousContainerBase::RemoveLast(); - } - - void Clear() { - for (auto& element : *this) { - // MSVC incorrectly reports this variable as unused. - (void)element; - element.~BaseElementType(); - } - ContiguousContainerBase::Clear(); - } - - void Swap(ContiguousContainer& other) { - ContiguousContainerBase::Swap(other); - } - - // Appends a new element using memcpy, then default-constructs a base - // element in its place. Use with care. - BaseElementType& AppendByMoving(BaseElementType* item, size_t size) { - DCHECK_GE(size, sizeof(BaseElementType)); - void* new_item = AlignedAllocate(size); - memcpy(new_item, static_cast<void*>(item), size); - new (item) BaseElementType; - return *static_cast<BaseElementType*>(new_item); - } - private: void* AlignedAllocate(size_t size) { void* result = ContiguousContainerBase::Allocate(Align(size)); diff --git a/chromium/cc/base/contiguous_container_unittest.cc b/chromium/cc/base/contiguous_container_unittest.cc index d617d4af55b..9e5e87b0e69 100644 --- a/chromium/cc/base/contiguous_container_unittest.cc +++ b/chromium/cc/base/contiguous_container_unittest.cc @@ -52,11 +52,8 @@ TEST(ContiguousContainerTest, SimpleStructs) { TEST(ContiguousContainerTest, AllocateLots) { ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); - for (int i = 0; i < (int)kNumElements; i++) { - list.AllocateAndConstruct<Point2D>(i, i); + for (int i = 0; i < (int)kNumElements; i++) list.AllocateAndConstruct<Point2D>(i, i); - list.RemoveLast(); - } ASSERT_EQ(kNumElements, list.size()); for (int i = 0; i < (int)kNumElements; i++) { ASSERT_EQ(i, list[i].x); @@ -77,97 +74,6 @@ TEST(ContiguousContainerTest, DestructorCalled) { EXPECT_CALL(destructible, Destruct()); } -TEST(ContiguousContainerTest, DestructorCalledOnceWhenClear) { - ContiguousContainer<MockDestructible> list(sizeof(MockDestructible)); - auto& destructible = list.AllocateAndConstruct<MockDestructible>(); - EXPECT_EQ(&destructible, &list.first()); - - testing::MockFunction<void()> separator; - { - testing::InSequence s; - EXPECT_CALL(destructible, Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(destructible, Destruct()).Times(0); - } - - list.Clear(); - separator.Call(); -} - -TEST(ContiguousContainerTest, DestructorCalledOnceWhenRemoveLast) { - ContiguousContainer<MockDestructible> list(sizeof(MockDestructible)); - auto& destructible = list.AllocateAndConstruct<MockDestructible>(); - EXPECT_EQ(&destructible, &list.first()); - - testing::MockFunction<void()> separator; - { - testing::InSequence s; - EXPECT_CALL(destructible, Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(destructible, Destruct()).Times(0); - } - - list.RemoveLast(); - separator.Call(); -} - -TEST(ContiguousContainerTest, DestructorCalledWithMultipleRemoveLastCalls) { - // This container only requests space for one, but the implementation is - // free to use more space if the allocator provides it. - ContiguousContainer<MockDestructible> list(sizeof(MockDestructible), - 1 * sizeof(MockDestructible)); - testing::MockFunction<void()> separator; - - // We should be okay to allocate and remove a single one, like before. - list.AllocateAndConstruct<MockDestructible>(); - EXPECT_EQ(1u, list.size()); - { - testing::InSequence s; - EXPECT_CALL(list[0], Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(list[0], Destruct()).Times(0); - } - list.RemoveLast(); - separator.Call(); - EXPECT_EQ(0u, list.size()); - - testing::Mock::VerifyAndClearExpectations(&separator); - - // We should also be okay to allocate and remove multiple. - list.AllocateAndConstruct<MockDestructible>(); - list.AllocateAndConstruct<MockDestructible>(); - list.AllocateAndConstruct<MockDestructible>(); - list.AllocateAndConstruct<MockDestructible>(); - list.AllocateAndConstruct<MockDestructible>(); - list.AllocateAndConstruct<MockDestructible>(); - EXPECT_EQ(6u, list.size()); - { - // The last three should be destroyed by removeLast. - testing::InSequence s; - EXPECT_CALL(list[5], Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(list[5], Destruct()).Times(0); - EXPECT_CALL(list[4], Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(list[4], Destruct()).Times(0); - EXPECT_CALL(list[3], Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(list[3], Destruct()).Times(0); - } - list.RemoveLast(); - separator.Call(); - list.RemoveLast(); - separator.Call(); - list.RemoveLast(); - separator.Call(); - EXPECT_EQ(3u, list.size()); - - // The remaining ones are destroyed when the test finishes. - EXPECT_CALL(list[2], Destruct()); - EXPECT_CALL(list[1], Destruct()); - EXPECT_CALL(list[0], Destruct()); -} - TEST(ContiguousContainerTest, InsertionAndIndexedAccess) { ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); @@ -183,24 +89,6 @@ TEST(ContiguousContainerTest, InsertionAndIndexedAccess) { EXPECT_EQ(&point3, &list[2]); } -TEST(ContiguousContainerTest, InsertionAndClear) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); - EXPECT_TRUE(list.empty()); - EXPECT_EQ(0u, list.size()); - - list.AllocateAndConstruct<Point2D>(); - EXPECT_FALSE(list.empty()); - EXPECT_EQ(1u, list.size()); - - list.Clear(); - EXPECT_TRUE(list.empty()); - EXPECT_EQ(0u, list.size()); - - list.AllocateAndConstruct<Point2D>(); - EXPECT_FALSE(list.empty()); - EXPECT_EQ(1u, list.size()); -} - TEST(ContiguousContainerTest, ElementAddressesAreStable) { ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); std::vector<Point2D*> pointers; @@ -273,206 +161,6 @@ TEST(ContiguousContainerTest, ReverseIteration) { "Non-const iteration should produce non-const references."); } -// Checks that the latter list has pointers to the elements of the former. -template <typename It1, typename It2> -bool EqualPointers(It1 it1, const It1& end1, It2 it2) { - for (; it1 != end1; ++it1, ++it2) { - if (&*it1 != *it2) - return false; - } - return true; -} - -TEST(ContiguousContainerTest, IterationAfterRemoveLast) { - struct SmallStruct { - char dummy[16]; - }; - ContiguousContainer<SmallStruct> list(sizeof(SmallStruct), - 1 * sizeof(SmallStruct)); - 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. - const auto& const_list = list; - const auto& const_pointers = pointers; - ASSERT_EQ(list.size(), pointers.size()); - ASSERT_TRUE(EqualPointers(list.begin(), list.end(), pointers.begin())); - ASSERT_TRUE(EqualPointers(const_list.begin(), const_list.end(), - const_pointers.begin())); - ASSERT_TRUE(EqualPointers(list.rbegin(), list.rend(), pointers.rbegin())); - ASSERT_TRUE(EqualPointers(const_list.rbegin(), const_list.rend(), - const_pointers.rbegin())); - }; - - // Note that the allocations that actually happen may not match the - // idealized descriptions here, since the implementation takes advantage of - // space available in the underlying allocator. - 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(ContiguousContainerTest, AppendByMovingSameList) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); - list.AllocateAndConstruct<Point3D>(1, 2, 3); - - // Moves the Point3D to the end, and default-constructs a Point2D in its - // place. - list.AppendByMoving(&list.first(), sizeof(Point3D)); - EXPECT_EQ(1, list.last().x); - EXPECT_EQ(2, list.last().y); - EXPECT_EQ(3, static_cast<const Point3D&>(list.last()).z); - EXPECT_EQ(2u, list.size()); - - // Moves that Point2D to the end, and default-constructs another in its - // place. - list.first().x = 4; - list.AppendByMoving(&list.first(), sizeof(Point2D)); - EXPECT_EQ(4, list.last().x); - EXPECT_EQ(3u, list.size()); -} - -TEST(ContiguousContainerTest, AppendByMovingDoesNotDestruct) { - // GMock mock objects (e.g. MockDestructible) aren't guaranteed to be safe - // to memcpy (which is required for AppendByMoving). - class DestructionNotifier { - public: - explicit DestructionNotifier(bool* flag = nullptr) : flag_(flag) {} - ~DestructionNotifier() { - if (flag_) - *flag_ = true; - } - - private: - bool* flag_; - }; - - bool destroyed = false; - ContiguousContainer<DestructionNotifier> list1(sizeof(DestructionNotifier)); - list1.AllocateAndConstruct<DestructionNotifier>(&destroyed); - { - // Make sure destructor isn't called during AppendByMoving. - ContiguousContainer<DestructionNotifier> list2(sizeof(DestructionNotifier)); - list2.AppendByMoving(&list1.last(), sizeof(DestructionNotifier)); - EXPECT_FALSE(destroyed); - } - // But it should be destroyed when list2 is. - EXPECT_TRUE(destroyed); -} - -TEST(ContiguousContainerTest, AppendByMovingReturnsMovedPointer) { - ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); - ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); - - Point2D& point = list1.AllocateAndConstruct<Point2D>(); - Point2D& moved_point1 = list2.AppendByMoving(&point, sizeof(Point2D)); - EXPECT_EQ(&moved_point1, &list2.last()); - - Point2D& moved_point2 = list1.AppendByMoving(&moved_point1, sizeof(Point2D)); - EXPECT_EQ(&moved_point2, &list1.last()); - EXPECT_NE(&moved_point1, &moved_point2); -} - -TEST(ContiguousContainerTest, AppendByMovingReplacesSourceWithNewElement) { - ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); - ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); - - list1.AllocateAndConstruct<Point2D>(1, 2); - EXPECT_EQ(1, list1.first().x); - EXPECT_EQ(2, list1.first().y); - - list2.AppendByMoving(&list1.first(), sizeof(Point2D)); - EXPECT_EQ(0, list1.first().x); - EXPECT_EQ(0, list1.first().y); - EXPECT_EQ(1, list2.first().x); - EXPECT_EQ(2, list2.first().y); - - EXPECT_EQ(1u, list1.size()); - EXPECT_EQ(1u, list2.size()); -} - -TEST(ContiguousContainerTest, AppendByMovingElementsOfDifferentSizes) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); - list.AllocateAndConstruct<Point3D>(1, 2, 3); - list.AllocateAndConstruct<Point2D>(4, 5); - - EXPECT_EQ(1, list[0].x); - EXPECT_EQ(2, list[0].y); - EXPECT_EQ(3, static_cast<const Point3D&>(list[0]).z); - EXPECT_EQ(4, list[1].x); - EXPECT_EQ(5, list[1].y); - - // Test that moving the first element actually moves the entire object, not - // just the base element. - list.AppendByMoving(&list[0], sizeof(Point3D)); - EXPECT_EQ(1, list[2].x); - EXPECT_EQ(2, list[2].y); - EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z); - EXPECT_EQ(4, list[1].x); - EXPECT_EQ(5, list[1].y); - - list.AppendByMoving(&list[1], sizeof(Point2D)); - EXPECT_EQ(1, list[2].x); - EXPECT_EQ(2, list[2].y); - EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z); - EXPECT_EQ(4, list[3].x); - EXPECT_EQ(5, list[3].y); -} - -TEST(ContiguousContainerTest, Swap) { - ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); - list1.AllocateAndConstruct<Point2D>(1, 2); - ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); - list2.AllocateAndConstruct<Point2D>(3, 4); - list2.AllocateAndConstruct<Point2D>(5, 6); - - EXPECT_EQ(1u, list1.size()); - EXPECT_EQ(1, list1[0].x); - EXPECT_EQ(2, list1[0].y); - EXPECT_EQ(2u, list2.size()); - EXPECT_EQ(3, list2[0].x); - EXPECT_EQ(4, list2[0].y); - EXPECT_EQ(5, list2[1].x); - EXPECT_EQ(6, list2[1].y); - - list2.Swap(list1); - - EXPECT_EQ(1u, list2.size()); - EXPECT_EQ(1, list2[0].x); - EXPECT_EQ(2, list2[0].y); - EXPECT_EQ(2u, list1.size()); - EXPECT_EQ(3, list1[0].x); - EXPECT_EQ(4, list1[0].y); - EXPECT_EQ(5, list1[1].x); - EXPECT_EQ(6, list1[1].y); -} - TEST(ContiguousContainerTest, CapacityInBytes) { const int iterations = 500; const size_t initial_capacity = 10 * kMaxPointSize; @@ -499,27 +187,6 @@ TEST(ContiguousContainerTest, CapacityInBytes) { max_waste_factor); list.AllocateAndConstruct<Point2D>(); } - - // The capacity should shrink with the list. - for (int i = 0; i < iterations; i++) { - size_t capacity = list.GetCapacityInBytes(); - ASSERT_GE(capacity, list.size() * sizeof(Point2D)); - ASSERT_LE(capacity, std::max(list.size() * sizeof(Point2D), - upper_bound_on_min_capacity) * - max_waste_factor); - list.RemoveLast(); - } -} - -TEST(ContiguousContainerTest, CapacityInBytesAfterClear) { - // Clearing should restore the capacity of the container to the same as a - // newly allocated one (without reserved capacity requested). - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); - size_t empty_capacity = list.GetCapacityInBytes(); - list.AllocateAndConstruct<Point2D>(); - list.AllocateAndConstruct<Point2D>(); - list.Clear(); - EXPECT_EQ(empty_capacity, list.GetCapacityInBytes()); } TEST(ContiguousContainerTest, MemoryUsageInBytes) { @@ -562,17 +229,6 @@ TEST(ContiguousContainerTest, Alignment) { EXPECT_EQ(0u, reinterpret_cast<intptr_t>(&list.last()) & (max_align - 1)); list.AllocateAndConstruct<Point2D>(); EXPECT_EQ(0u, reinterpret_cast<intptr_t>(&list.last()) & (max_align - 1)); - - list.AppendByMoving(&list[0], sizeof(Point2D)); - EXPECT_EQ(0u, reinterpret_cast<intptr_t>(&list.last()) & (max_align - 1)); - list.AppendByMoving(&list[1], sizeof(Point2D)); - EXPECT_EQ(0u, reinterpret_cast<intptr_t>(&list.last()) & (max_align - 1)); - list.AppendByMoving(&list[2], sizeof(Point3D)); - EXPECT_EQ(0u, reinterpret_cast<intptr_t>(&list.last()) & (max_align - 1)); - list.AppendByMoving(&list[3], sizeof(Point3D)); - EXPECT_EQ(0u, reinterpret_cast<intptr_t>(&list.last()) & (max_align - 1)); - list.AppendByMoving(&list[4], sizeof(Point2D)); - EXPECT_EQ(0u, reinterpret_cast<intptr_t>(&list.last()) & (max_align - 1)); } } // namespace diff --git a/chromium/cc/base/delayed_unique_notifier.cc b/chromium/cc/base/delayed_unique_notifier.cc index ceb795123b2..4cdd06a3961 100644 --- a/chromium/cc/base/delayed_unique_notifier.cc +++ b/chromium/cc/base/delayed_unique_notifier.cc @@ -34,10 +34,11 @@ void DelayedUniqueNotifier::Schedule() { } next_notification_time_ = Now() + delay_; - task_runner_->PostDelayedTask(FROM_HERE, - base::Bind(&DelayedUniqueNotifier::NotifyIfTime, - weak_ptr_factory_.GetWeakPtr()), - delay_); + task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&DelayedUniqueNotifier::NotifyIfTime, + weak_ptr_factory_.GetWeakPtr()), + delay_); notification_pending_ = true; } @@ -82,8 +83,9 @@ void DelayedUniqueNotifier::NotifyIfTime() { base::TimeTicks now = Now(); if (next_notification_time_ > now) { task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(&DelayedUniqueNotifier::NotifyIfTime, - weak_ptr_factory_.GetWeakPtr()), + FROM_HERE, + base::BindOnce(&DelayedUniqueNotifier::NotifyIfTime, + weak_ptr_factory_.GetWeakPtr()), next_notification_time_ - now); return; } diff --git a/chromium/cc/base/delayed_unique_notifier.h b/chromium/cc/base/delayed_unique_notifier.h index 8272d343871..86d2e37e1b8 100644 --- a/chromium/cc/base/delayed_unique_notifier.h +++ b/chromium/cc/base/delayed_unique_notifier.h @@ -8,7 +8,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" namespace base { class SequencedTaskRunner; @@ -16,7 +16,7 @@ class SequencedTaskRunner; namespace cc { -class CC_EXPORT DelayedUniqueNotifier { +class CC_BASE_EXPORT DelayedUniqueNotifier { public: // Configure this notifier to issue the |closure| notification in |delay| time // from Schedule() call. diff --git a/chromium/cc/debug/devtools_instrumentation.cc b/chromium/cc/base/devtools_instrumentation.cc index e5743405feb..010b16149f1 100644 --- a/chromium/cc/debug/devtools_instrumentation.cc +++ b/chromium/cc/base/devtools_instrumentation.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" namespace cc { namespace devtools_instrumentation { diff --git a/chromium/cc/debug/devtools_instrumentation.h b/chromium/cc/base/devtools_instrumentation.h index 3aa18632573..40e2d9efd70 100644 --- a/chromium/cc/debug/devtools_instrumentation.h +++ b/chromium/cc/base/devtools_instrumentation.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_DEVTOOLS_INSTRUMENTATION_H_ -#define CC_DEBUG_DEVTOOLS_INSTRUMENTATION_H_ +#ifndef CC_BASE_DEVTOOLS_INSTRUMENTATION_H_ +#define CC_BASE_DEVTOOLS_INSTRUMENTATION_H_ #include <stdint.h> @@ -13,49 +13,49 @@ #include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/base_export.h" namespace cc { namespace devtools_instrumentation { namespace internal { -extern const char kCategory[]; -extern const char kCategoryFrame[]; -extern const char kData[]; -extern const char kFrameId[]; -extern const char kLayerId[]; -extern const char kLayerTreeId[]; -extern const char kPixelRefId[]; - -extern const char kImageDecodeTask[]; -extern const char kBeginFrame[]; -extern const char kNeedsBeginFrameChanged[]; -extern const char kActivateLayerTree[]; -extern const char kRequestMainThreadFrame[]; -extern const char kBeginMainThreadFrame[]; -extern const char kDrawFrame[]; -extern const char kCompositeLayers[]; +CC_BASE_EXPORT extern const char kCategory[]; +CC_BASE_EXPORT extern const char kCategoryFrame[]; +CC_BASE_EXPORT extern const char kData[]; +CC_BASE_EXPORT extern const char kFrameId[]; +CC_BASE_EXPORT extern const char kLayerId[]; +CC_BASE_EXPORT extern const char kLayerTreeId[]; +CC_BASE_EXPORT extern const char kPixelRefId[]; + +CC_BASE_EXPORT extern const char kImageDecodeTask[]; +CC_BASE_EXPORT extern const char kBeginFrame[]; +CC_BASE_EXPORT extern const char kNeedsBeginFrameChanged[]; +CC_BASE_EXPORT extern const char kActivateLayerTree[]; +CC_BASE_EXPORT extern const char kRequestMainThreadFrame[]; +CC_BASE_EXPORT extern const char kBeginMainThreadFrame[]; +CC_BASE_EXPORT extern const char kDrawFrame[]; +CC_BASE_EXPORT extern const char kCompositeLayers[]; } // namespace internal extern const char kPaintSetup[]; -extern const char kUpdateLayer[]; +CC_BASE_EXPORT extern const char kUpdateLayer[]; -class ScopedLayerTask { +class CC_BASE_EXPORT ScopedLayerTask { public: ScopedLayerTask(const char* event_name, int layer_id) - : event_name_(event_name) { - TRACE_EVENT_BEGIN1(internal::kCategory, event_name_, - internal::kLayerId, layer_id); - } - ~ScopedLayerTask() { - TRACE_EVENT_END0(internal::kCategory, event_name_); + : event_name_(event_name) { + TRACE_EVENT_BEGIN1(internal::kCategory, event_name_, internal::kLayerId, + layer_id); } + ~ScopedLayerTask() { TRACE_EVENT_END0(internal::kCategory, event_name_); } + private: const char* event_name_; DISALLOW_COPY_AND_ASSIGN(ScopedLayerTask); }; -class ScopedImageDecodeTask { +class CC_BASE_EXPORT ScopedImageDecodeTask { public: enum Type { SOFTWARE, GPU }; @@ -86,26 +86,24 @@ class ScopedImageDecodeTask { DISALLOW_COPY_AND_ASSIGN(ScopedImageDecodeTask); }; -class ScopedLayerTreeTask { +class CC_BASE_EXPORT ScopedLayerTreeTask { public: ScopedLayerTreeTask(const char* event_name, int layer_id, int layer_tree_host_id) - : event_name_(event_name) { - TRACE_EVENT_BEGIN2(internal::kCategory, event_name_, - internal::kLayerId, layer_id, - internal::kLayerTreeId, layer_tree_host_id); - } - ~ScopedLayerTreeTask() { - TRACE_EVENT_END0(internal::kCategory, event_name_); + : event_name_(event_name) { + TRACE_EVENT_BEGIN2(internal::kCategory, event_name_, internal::kLayerId, + layer_id, internal::kLayerTreeId, layer_tree_host_id); } + ~ScopedLayerTreeTask() { TRACE_EVENT_END0(internal::kCategory, event_name_); } + private: const char* event_name_; DISALLOW_COPY_AND_ASSIGN(ScopedLayerTreeTask); }; -struct ScopedCommitTrace { +struct CC_BASE_EXPORT ScopedCommitTrace { public: explicit ScopedCommitTrace(int layer_tree_host_id) { TRACE_EVENT_BEGIN1(internal::kCategory, internal::kCompositeLayers, @@ -119,51 +117,40 @@ struct ScopedCommitTrace { DISALLOW_COPY_AND_ASSIGN(ScopedCommitTrace); }; -struct ScopedLayerObjectTracker +struct CC_BASE_EXPORT ScopedLayerObjectTracker : public base::trace_event::TraceScopedTrackableObject<int> { explicit ScopedLayerObjectTracker(int layer_id) - : base::trace_event::TraceScopedTrackableObject<int>( - internal::kCategory, - internal::kLayerId, - layer_id) { - } + : base::trace_event::TraceScopedTrackableObject<int>(internal::kCategory, + internal::kLayerId, + layer_id) {} private: DISALLOW_COPY_AND_ASSIGN(ScopedLayerObjectTracker); }; -inline void DidActivateLayerTree(int layer_tree_host_id, int frame_id) { - TRACE_EVENT_INSTANT2(internal::kCategoryFrame, - internal::kActivateLayerTree, - TRACE_EVENT_SCOPE_THREAD, - internal::kLayerTreeId, - layer_tree_host_id, - internal::kFrameId, - frame_id); +inline void CC_BASE_EXPORT DidActivateLayerTree(int layer_tree_host_id, + int frame_id) { + TRACE_EVENT_INSTANT2(internal::kCategoryFrame, internal::kActivateLayerTree, + TRACE_EVENT_SCOPE_THREAD, internal::kLayerTreeId, + layer_tree_host_id, internal::kFrameId, frame_id); } -inline void DidBeginFrame(int layer_tree_host_id) { - TRACE_EVENT_INSTANT1(internal::kCategoryFrame, - internal::kBeginFrame, - TRACE_EVENT_SCOPE_THREAD, - internal::kLayerTreeId, +inline void CC_BASE_EXPORT DidBeginFrame(int layer_tree_host_id) { + TRACE_EVENT_INSTANT1(internal::kCategoryFrame, internal::kBeginFrame, + TRACE_EVENT_SCOPE_THREAD, internal::kLayerTreeId, layer_tree_host_id); } -inline void DidDrawFrame(int layer_tree_host_id) { - TRACE_EVENT_INSTANT1(internal::kCategoryFrame, - internal::kDrawFrame, - TRACE_EVENT_SCOPE_THREAD, - internal::kLayerTreeId, +inline void CC_BASE_EXPORT DidDrawFrame(int layer_tree_host_id) { + TRACE_EVENT_INSTANT1(internal::kCategoryFrame, internal::kDrawFrame, + TRACE_EVENT_SCOPE_THREAD, internal::kLayerTreeId, layer_tree_host_id); } -inline void DidRequestMainThreadFrame(int layer_tree_host_id) { - TRACE_EVENT_INSTANT1(internal::kCategoryFrame, - internal::kRequestMainThreadFrame, - TRACE_EVENT_SCOPE_THREAD, - internal::kLayerTreeId, - layer_tree_host_id); +inline void CC_BASE_EXPORT DidRequestMainThreadFrame(int layer_tree_host_id) { + TRACE_EVENT_INSTANT1( + internal::kCategoryFrame, internal::kRequestMainThreadFrame, + TRACE_EVENT_SCOPE_THREAD, internal::kLayerTreeId, layer_tree_host_id); } inline std::unique_ptr<base::trace_event::ConvertableToTraceFormat> @@ -174,7 +161,8 @@ BeginMainThreadFrameData(int frame_id) { return std::move(value); } -inline void WillBeginMainThreadFrame(int layer_tree_host_id, int frame_id) { +inline void CC_BASE_EXPORT WillBeginMainThreadFrame(int layer_tree_host_id, + int frame_id) { TRACE_EVENT_INSTANT2( internal::kCategoryFrame, internal::kBeginMainThreadFrame, TRACE_EVENT_SCOPE_THREAD, internal::kLayerTreeId, layer_tree_host_id, @@ -189,7 +177,8 @@ NeedsBeginFrameData(bool needs_begin_frame) { return std::move(value); } -inline void NeedsBeginFrameChanged(int layer_tree_host_id, bool new_value) { +inline void CC_BASE_EXPORT 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, @@ -199,4 +188,4 @@ inline void NeedsBeginFrameChanged(int layer_tree_host_id, bool new_value) { } // namespace devtools_instrumentation } // namespace cc -#endif // CC_DEBUG_DEVTOOLS_INSTRUMENTATION_H_ +#endif // CC_BASE_DEVTOOLS_INSTRUMENTATION_H_ diff --git a/chromium/cc/output/filter_operation.cc b/chromium/cc/base/filter_operation.cc index e75b41707ba..aed4b024936 100644 --- a/chromium/cc/output/filter_operation.cc +++ b/chromium/cc/base/filter_operation.cc @@ -8,8 +8,8 @@ #include "base/trace_event/trace_event_argument.h" #include "base/values.h" +#include "cc/base/filter_operation.h" #include "cc/base/math_util.h" -#include "cc/output/filter_operation.h" #include "ui/gfx/animation/tween.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -31,9 +31,8 @@ bool FilterOperation::operator==(const FilterOperation& other) const { return image_filter_.get() == other.image_filter_.get(); } if (type_ == ALPHA_THRESHOLD) { - return region_ == other.region_ && - amount_ == other.amount_ && - outer_threshold_ == other.outer_threshold_; + return region_ == other.region_ && amount_ == other.amount_ && + outer_threshold_ == other.outer_threshold_; } return amount_ == other.amount_; } @@ -129,8 +128,7 @@ FilterOperation::FilterOperation(const FilterOperation& other) memcpy(matrix_, other.matrix_, sizeof(matrix_)); } -FilterOperation::~FilterOperation() { -} +FilterOperation::~FilterOperation() {} static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) { switch (type) { @@ -153,8 +151,8 @@ static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) { case FilterOperation::BLUR: return FilterOperation::CreateBlurFilter(0.f); case FilterOperation::DROP_SHADOW: - return FilterOperation::CreateDropShadowFilter( - gfx::Point(0, 0), 0.f, SK_ColorTRANSPARENT); + return FilterOperation::CreateDropShadowFilter(gfx::Point(0, 0), 0.f, + SK_ColorTRANSPARENT); case FilterOperation::COLOR_MATRIX: { SkScalar matrix[20]; memset(matrix, 0, 20 * sizeof(SkScalar)); @@ -234,13 +232,12 @@ FilterOperation FilterOperation::Blend(const FilterOperation* from, to_op.type())); if (to_op.type() == FilterOperation::DROP_SHADOW) { - gfx::Point blended_offset( - gfx::Tween::LinearIntValueBetween(progress, - from_op.drop_shadow_offset().x(), - to_op.drop_shadow_offset().x()), - gfx::Tween::LinearIntValueBetween(progress, - from_op.drop_shadow_offset().y(), - to_op.drop_shadow_offset().y())); + gfx::Point blended_offset(gfx::Tween::LinearIntValueBetween( + progress, from_op.drop_shadow_offset().x(), + to_op.drop_shadow_offset().x()), + gfx::Tween::LinearIntValueBetween( + progress, from_op.drop_shadow_offset().y(), + to_op.drop_shadow_offset().y())); blended_filter.set_drop_shadow_offset(blended_offset); blended_filter.set_drop_shadow_color(gfx::Tween::ColorValueBetween( progress, from_op.drop_shadow_color(), to_op.drop_shadow_color())); @@ -251,10 +248,9 @@ FilterOperation FilterOperation::Blend(const FilterOperation* from, 0)); } else if (to_op.type() == FilterOperation::ALPHA_THRESHOLD) { blended_filter.set_outer_threshold(ClampAmountForFilterType( - gfx::Tween::FloatValueBetween(progress, - from_op.outer_threshold(), - to_op.outer_threshold()), - to_op.type())); + gfx::Tween::FloatValueBetween(progress, from_op.outer_threshold(), + to_op.outer_threshold()), + to_op.type())); blended_filter.set_region(to_op.region()); } @@ -302,19 +298,18 @@ void FilterOperation::AsValueInto(base::trace_event::TracedValue* value) const { break; } case FilterOperation::ALPHA_THRESHOLD: { - value->SetDouble("inner_threshold", amount_); - value->SetDouble("outer_threshold", outer_threshold_); - std::unique_ptr<base::ListValue> region_value(new base::ListValue()); - value->BeginArray("region"); - for (SkRegion::Iterator it(region_); !it.done(); it.next()) { - value->AppendInteger(it.rect().x()); - value->AppendInteger(it.rect().y()); - value->AppendInteger(it.rect().width()); - value->AppendInteger(it.rect().height()); - } - value->EndArray(); + value->SetDouble("inner_threshold", amount_); + value->SetDouble("outer_threshold", outer_threshold_); + std::unique_ptr<base::ListValue> region_value(new base::ListValue()); + value->BeginArray("region"); + for (SkRegion::Iterator it(region_); !it.done(); it.next()) { + value->AppendInteger(it.rect().x()); + value->AppendInteger(it.rect().y()); + value->AppendInteger(it.rect().width()); + value->AppendInteger(it.rect().height()); } - break; + value->EndArray(); + } break; } } diff --git a/chromium/cc/output/filter_operation.h b/chromium/cc/base/filter_operation.h index 63edc3a6b24..2508870bdb0 100644 --- a/chromium/cc/output/filter_operation.h +++ b/chromium/cc/base/filter_operation.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_OUTPUT_FILTER_OPERATION_H_ -#define CC_OUTPUT_FILTER_OPERATION_H_ +#ifndef CC_BASE_FILTER_OPERATION_H_ +#define CC_BASE_FILTER_OPERATION_H_ #include <memory> #include "base/logging.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/core/SkRegion.h" @@ -27,7 +27,7 @@ class Rect; namespace cc { -class CC_EXPORT FilterOperation { +class CC_BASE_EXPORT FilterOperation { public: enum FilterType { GRAYSCALE, @@ -44,7 +44,7 @@ class CC_EXPORT FilterOperation { ZOOM, REFERENCE, SATURATING_BRIGHTNESS, // Not used in CSS/SVG. - ALPHA_THRESHOLD, // Not used in CSS/SVG. + ALPHA_THRESHOLD, // Not used in CSS/SVG. FILTER_TYPE_LAST = ALPHA_THRESHOLD }; @@ -159,8 +159,8 @@ class CC_EXPORT FilterOperation { static FilterOperation CreateAlphaThresholdFilter(const SkRegion& region, float inner_threshold, float outer_threshold) { - return FilterOperation(ALPHA_THRESHOLD, region, - inner_threshold, outer_threshold); + return FilterOperation(ALPHA_THRESHOLD, region, inner_threshold, + outer_threshold); } bool operator==(const FilterOperation& other) const; @@ -270,4 +270,4 @@ class CC_EXPORT FilterOperation { } // namespace cc -#endif // CC_OUTPUT_FILTER_OPERATION_H_ +#endif // CC_BASE_FILTER_OPERATION_H_ diff --git a/chromium/cc/output/filter_operations.cc b/chromium/cc/base/filter_operations.cc index dc18a228d16..b9ccb8d0b31 100644 --- a/chromium/cc/output/filter_operations.cc +++ b/chromium/cc/base/filter_operations.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/output/filter_operations.h" +#include "cc/base/filter_operations.h" #include <stddef.h> @@ -11,7 +11,7 @@ #include "base/trace_event/trace_event_argument.h" #include "base/values.h" -#include "cc/output/filter_operation.h" +#include "cc/base/filter_operation.h" #include "ui/gfx/geometry/rect.h" namespace cc { @@ -164,10 +164,7 @@ bool FilterOperations::HasFilterThatAffectsOpacity() const { return true; case FilterOperation::COLOR_MATRIX: { const SkScalar* matrix = op.matrix(); - if (matrix[15] || - matrix[16] || - matrix[17] || - matrix[18] != 1 || + if (matrix[15] || matrix[16] || matrix[17] || matrix[18] != 1 || matrix[19]) return true; break; @@ -204,7 +201,7 @@ FilterOperations FilterOperations::Blend(const FilterOperations& from, size_t shorter_size, longer_size; if (size() == from.size()) { shorter_size = longer_size = size(); - } else if (from_is_longer) { + } else if (from_is_longer) { longer_size = from.size(); shorter_size = size(); } else { diff --git a/chromium/cc/output/filter_operations.h b/chromium/cc/base/filter_operations.h index b5eb7802675..a7be88d122b 100644 --- a/chromium/cc/output/filter_operations.h +++ b/chromium/cc/base/filter_operations.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_OUTPUT_FILTER_OPERATIONS_H_ -#define CC_OUTPUT_FILTER_OPERATIONS_H_ +#ifndef CC_BASE_FILTER_OPERATIONS_H_ +#define CC_BASE_FILTER_OPERATIONS_H_ #include <stddef.h> @@ -11,7 +11,7 @@ #include <vector> #include "base/logging.h" -#include "cc/output/filter_operation.h" +#include "cc/base/filter_operation.h" namespace base { namespace trace_event { @@ -26,7 +26,7 @@ class Rect; namespace cc { // An ordered list of filter operations. -class CC_EXPORT FilterOperations { +class CC_BASE_EXPORT FilterOperations { public: FilterOperations(); @@ -66,9 +66,7 @@ class CC_EXPORT FilterOperations { bool HasFilterThatAffectsOpacity() const; bool HasReferenceFilter() const; - size_t size() const { - return operations_.size(); - } + size_t size() const { return operations_.size(); } const std::vector<FilterOperation>& operations() const { return operations_; } @@ -98,4 +96,4 @@ class CC_EXPORT FilterOperations { } // namespace cc -#endif // CC_OUTPUT_FILTER_OPERATIONS_H_ +#endif // CC_BASE_FILTER_OPERATIONS_H_ diff --git a/chromium/cc/output/filter_operations_unittest.cc b/chromium/cc/base/filter_operations_unittest.cc index fe86feb4efb..9eb852db5e7 100644 --- a/chromium/cc/output/filter_operations_unittest.cc +++ b/chromium/cc/base/filter_operations_unittest.cc @@ -4,7 +4,7 @@ #include <stddef.h> -#include "cc/output/filter_operations.h" +#include "cc/base/filter_operations.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/effects/SkBlurImageFilter.h" #include "third_party/skia/include/effects/SkDropShadowImageFilter.h" @@ -396,11 +396,11 @@ TEST(FilterOperationsTest, SaveAndRestore) { SAVE_RESTORE_AMOUNT(Opacity, OPACITY, 0.6f); SAVE_RESTORE_AMOUNT(Blur, BLUR, 0.6f); SAVE_RESTORE_AMOUNT(SaturatingBrightness, SATURATING_BRIGHTNESS, 0.6f); - SAVE_RESTORE_OFFSET_AMOUNT_COLOR( - DropShadow, DROP_SHADOW, gfx::Point(3, 4), 0.4f, 0xffffff00); + SAVE_RESTORE_OFFSET_AMOUNT_COLOR(DropShadow, DROP_SHADOW, gfx::Point(3, 4), + 0.4f, 0xffffff00); - SkScalar matrix[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20}; + SkScalar matrix[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; SAVE_RESTORE_MATRIX(ColorMatrix, COLOR_MATRIX, matrix); SAVE_RESTORE_AMOUNT_INSET(Zoom, ZOOM, 0.5f, 32); diff --git a/chromium/cc/base/histograms.h b/chromium/cc/base/histograms.h index 16e059c4d43..5c634b9cc11 100644 --- a/chromium/cc/base/histograms.h +++ b/chromium/cc/base/histograms.h @@ -13,7 +13,7 @@ #include "base/strings/stringprintf.h" #include "base/time/time.h" #include "base/timer/elapsed_timer.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" namespace cc { @@ -22,7 +22,7 @@ namespace cc { // // We currently assume that there is only one distinct client per process. // Not thread-safe. If called multiple times, warns and skips metrics. -CC_EXPORT void SetClientNameForMetrics(const char* client_name); +CC_BASE_EXPORT void SetClientNameForMetrics(const char* client_name); // Returns the client name, for use by applicable cc metrics code. // May return null, in which case no clients, or at least two clients, set the @@ -30,7 +30,7 @@ CC_EXPORT void SetClientNameForMetrics(const char* client_name); // // This method guarantees that it will never return two distinct non-null // values over the lifetime of the process. -const char* GetClientNameForMetrics(); +CC_BASE_EXPORT const char* GetClientNameForMetrics(); // 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 @@ -90,7 +90,7 @@ const char* GetClientNameForMetrics(); } \ } -class CC_EXPORT ScopedUMAHistogramAreaTimerBase { +class CC_BASE_EXPORT ScopedUMAHistogramAreaTimerBase { public: void AddArea(const base::CheckedNumeric<int>& area) { area_ += area; } void SetArea(const base::CheckedNumeric<int>& area) { area_ = area; } diff --git a/chromium/cc/base/index_rect.h b/chromium/cc/base/index_rect.h index d6d2d917828..ea252833eab 100644 --- a/chromium/cc/base/index_rect.h +++ b/chromium/cc/base/index_rect.h @@ -7,7 +7,7 @@ #include <string> -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" namespace cc { @@ -58,7 +58,7 @@ namespace cc { // ├───┼───┼───┼───┼───┤ // 4 │ │ │ │ │ │ // └───┴───┴───┴───┴───┘ -class CC_EXPORT IndexRect { +class CC_BASE_EXPORT IndexRect { public: constexpr IndexRect(int left, int right, int top, int bottom) : left_(left), right_(right), top_(top), bottom_(bottom) {} diff --git a/chromium/cc/base/invalidation_region.h b/chromium/cc/base/invalidation_region.h index a9a0762bb44..1c137e89b0c 100644 --- a/chromium/cc/base/invalidation_region.h +++ b/chromium/cc/base/invalidation_region.h @@ -7,7 +7,7 @@ #include <vector> -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "cc/base/region.h" #include "ui/gfx/geometry/rect.h" @@ -16,7 +16,7 @@ namespace cc { // This class behaves similarly to Region, but it may have false positives. That // is, InvalidationRegion can be simplified to encompass a larger area than the // collection of rects unioned. -class CC_EXPORT InvalidationRegion { +class CC_BASE_EXPORT InvalidationRegion { public: InvalidationRegion(); ~InvalidationRegion(); diff --git a/chromium/cc/debug/lap_timer.cc b/chromium/cc/base/lap_timer.cc index 2c5d3810b39..6702311f6d4 100644 --- a/chromium/cc/debug/lap_timer.cc +++ b/chromium/cc/base/lap_timer.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "base/logging.h" @@ -58,7 +58,9 @@ void LapTimer::Start() { start_time_ = Now(); } -bool LapTimer::IsWarmedUp() { return remaining_warmups_ <= 0; } +bool LapTimer::IsWarmedUp() { + return remaining_warmups_ <= 0; +} void LapTimer::NextLap() { if (!IsWarmedUp()) { @@ -78,9 +80,13 @@ void LapTimer::NextLap() { } } -bool LapTimer::HasTimeLimitExpired() { return accumulator_ >= time_limit_; } +bool LapTimer::HasTimeLimitExpired() { + return accumulator_ >= time_limit_; +} -bool LapTimer::HasTimedAllLaps() { return !(num_laps_ % check_interval_); } +bool LapTimer::HasTimedAllLaps() { + return !(num_laps_ % check_interval_); +} float LapTimer::MsPerLap() { DCHECK(HasTimedAllLaps()); @@ -92,6 +98,8 @@ float LapTimer::LapsPerSecond() { return num_laps_ / accumulator_.InSecondsF(); } -int LapTimer::NumLaps() { return num_laps_; } +int LapTimer::NumLaps() { + return num_laps_; +} } // namespace cc diff --git a/chromium/cc/debug/lap_timer.h b/chromium/cc/base/lap_timer.h index bd1ba4fdb88..5b27e257854 100644 --- a/chromium/cc/debug/lap_timer.h +++ b/chromium/cc/base/lap_timer.h @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_LAP_TIMER_H_ -#define CC_DEBUG_LAP_TIMER_H_ +#ifndef CC_BASE_LAP_TIMER_H_ +#define CC_BASE_LAP_TIMER_H_ #include "base/macros.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" namespace cc { @@ -21,7 +21,7 @@ namespace cc { // If you set the time_limit then you can use HasTimeLimitExpired() to see if // the current accumulated time has crossed that threshold, with an optimization // that it only tests this every check_interval laps. -class CC_EXPORT LapTimer { +class CC_BASE_EXPORT LapTimer { public: LapTimer(int warmup_laps, base::TimeDelta time_limit, int check_interval); // Create LapTimer with sensible default values. @@ -64,4 +64,4 @@ class CC_EXPORT LapTimer { } // namespace cc -#endif // CC_DEBUG_LAP_TIMER_H_ +#endif // CC_BASE_LAP_TIMER_H_ diff --git a/chromium/cc/base/list_container.h b/chromium/cc/base/list_container.h index 07e7d321feb..cb386f9b343 100644 --- a/chromium/cc/base/list_container.h +++ b/chromium/cc/base/list_container.h @@ -11,7 +11,6 @@ #include "base/logging.h" #include "base/macros.h" -#include "cc/base/cc_export.h" #include "cc/base/list_container_helper.h" namespace cc { diff --git a/chromium/cc/base/list_container_helper.h b/chromium/cc/base/list_container_helper.h index d4f5ead8ac7..ce98c1ec4ef 100644 --- a/chromium/cc/base/list_container_helper.h +++ b/chromium/cc/base/list_container_helper.h @@ -10,14 +10,14 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" namespace cc { // Helper class for ListContainer non-templated logic. All methods are private, // and only exposed to friend classes. // For usage, see comments in ListContainer (list_container.h). -class CC_EXPORT ListContainerHelper final { +class CC_BASE_EXPORT ListContainerHelper final { private: template <typename T> friend class ListContainer; @@ -36,7 +36,7 @@ class CC_EXPORT ListContainerHelper final { // This class points to a certain position inside memory of // CharAllocator. It is a base class for ListContainer iterators. - struct CC_EXPORT PositionInCharAllocator { + struct CC_BASE_EXPORT PositionInCharAllocator { CharAllocator* ptr_to_container; size_t vector_index; char* item_iterator; @@ -56,7 +56,7 @@ class CC_EXPORT ListContainerHelper final { // Iterator classes that can be used to access data. ///////////////////////////////////////////////////////////////// - class CC_EXPORT Iterator : public PositionInCharAllocator { + class CC_BASE_EXPORT Iterator : public PositionInCharAllocator { // This class is only defined to forward iterate through // CharAllocator. public: @@ -76,7 +76,7 @@ class CC_EXPORT ListContainerHelper final { size_t index_; }; - class CC_EXPORT ConstIterator : public PositionInCharAllocator { + class CC_BASE_EXPORT ConstIterator : public PositionInCharAllocator { // This class is only defined to forward iterate through // CharAllocator. public: @@ -97,7 +97,7 @@ class CC_EXPORT ListContainerHelper final { size_t index_; }; - class CC_EXPORT ReverseIterator : public PositionInCharAllocator { + class CC_BASE_EXPORT ReverseIterator : public PositionInCharAllocator { // This class is only defined to reverse iterate through // CharAllocator. public: @@ -117,7 +117,7 @@ class CC_EXPORT ListContainerHelper final { size_t index_; }; - class CC_EXPORT ConstReverseIterator : public PositionInCharAllocator { + class CC_BASE_EXPORT ConstReverseIterator : public PositionInCharAllocator { // This class is only defined to reverse iterate through // CharAllocator. public: diff --git a/chromium/cc/base/math_util.cc b/chromium/cc/base/math_util.cc index c1f2614d110..262f6586dba 100644 --- a/chromium/cc/base/math_util.cc +++ b/chromium/cc/base/math_util.cc @@ -490,47 +490,6 @@ gfx::QuadF MathUtil::MapQuad(const gfx::Transform& transform, h4.CartesianPoint2d()); } -gfx::QuadF MathUtil::MapQuad3d(const gfx::Transform& transform, - const gfx::QuadF& q, - gfx::Point3F* p, - bool* clipped) { - if (transform.IsIdentityOrTranslation()) { - gfx::QuadF mapped_quad(q); - mapped_quad += gfx::Vector2dF(transform.matrix().getFloat(0, 3), - transform.matrix().getFloat(1, 3)); - *clipped = false; - p[0] = gfx::Point3F(mapped_quad.p1().x(), mapped_quad.p1().y(), 0.0f); - p[1] = gfx::Point3F(mapped_quad.p2().x(), mapped_quad.p2().y(), 0.0f); - p[2] = gfx::Point3F(mapped_quad.p3().x(), mapped_quad.p3().y(), 0.0f); - p[3] = gfx::Point3F(mapped_quad.p4().x(), mapped_quad.p4().y(), 0.0f); - return mapped_quad; - } - - HomogeneousCoordinate h1 = - MapHomogeneousPoint(transform, gfx::Point3F(q.p1())); - HomogeneousCoordinate h2 = - MapHomogeneousPoint(transform, gfx::Point3F(q.p2())); - HomogeneousCoordinate h3 = - MapHomogeneousPoint(transform, gfx::Point3F(q.p3())); - HomogeneousCoordinate h4 = - MapHomogeneousPoint(transform, gfx::Point3F(q.p4())); - - *clipped = h1.ShouldBeClipped() || h2.ShouldBeClipped() || - h3.ShouldBeClipped() || h4.ShouldBeClipped(); - - // Result will be invalid if clipped == true. But, compute it anyway just in - // case, to emulate existing behavior. - p[0] = h1.CartesianPoint3d(); - p[1] = h2.CartesianPoint3d(); - p[2] = h3.CartesianPoint3d(); - p[3] = h4.CartesianPoint3d(); - - return gfx::QuadF(h1.CartesianPoint2d(), - h2.CartesianPoint2d(), - h3.CartesianPoint2d(), - h4.CartesianPoint2d()); -} - gfx::PointF MathUtil::MapPoint(const gfx::Transform& transform, const gfx::PointF& p, bool* clipped) { @@ -555,47 +514,6 @@ gfx::PointF MathUtil::MapPoint(const gfx::Transform& transform, return h.CartesianPoint2d(); } -gfx::Point3F MathUtil::MapPoint(const gfx::Transform& transform, - const gfx::Point3F& p, - bool* clipped) { - HomogeneousCoordinate h = MapHomogeneousPoint(transform, p); - - if (h.w() > 0) { - *clipped = false; - return h.CartesianPoint3d(); - } - - // The cartesian coordinates will be invalid after dividing by w. - *clipped = true; - - // Avoid dividing by w if w == 0. - if (!h.w()) - return gfx::Point3F(); - - // This return value will be invalid because clipped == true, but (1) users of - // this code should be ignoring the return value when clipped == true anyway, - // and (2) this behavior is more consistent with existing behavior of WebKit - // transforms if the user really does not ignore the return value. - return h.CartesianPoint3d(); -} - -gfx::QuadF MathUtil::ProjectQuad(const gfx::Transform& transform, - const gfx::QuadF& q, - bool* clipped) { - gfx::QuadF projected_quad; - bool clipped_point; - projected_quad.set_p1(ProjectPoint(transform, q.p1(), &clipped_point)); - *clipped = clipped_point; - projected_quad.set_p2(ProjectPoint(transform, q.p2(), &clipped_point)); - *clipped |= clipped_point; - projected_quad.set_p3(ProjectPoint(transform, q.p3(), &clipped_point)); - *clipped |= clipped_point; - projected_quad.set_p4(ProjectPoint(transform, q.p4(), &clipped_point)); - *clipped |= clipped_point; - - return projected_quad; -} - gfx::PointF MathUtil::ProjectPoint(const gfx::Transform& transform, const gfx::PointF& p, bool* clipped) { diff --git a/chromium/cc/base/math_util.h b/chromium/cc/base/math_util.h index 59f28ece419..7bccfea3718 100644 --- a/chromium/cc/base/math_util.h +++ b/chromium/cc/base/math_util.h @@ -11,7 +11,7 @@ #include <vector> #include "base/logging.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "ui/gfx/geometry/box_f.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/point_f.h" @@ -79,7 +79,7 @@ struct HomogeneousCoordinate { SkMScalar vec[4]; }; -class CC_EXPORT MathUtil { +class CC_BASE_EXPORT MathUtil { public: static const double kPiDouble; static const float kPiFloat; @@ -205,19 +205,9 @@ class CC_EXPORT MathUtil { static gfx::QuadF MapQuad(const gfx::Transform& transform, const gfx::QuadF& quad, bool* clipped); - static gfx::QuadF MapQuad3d(const gfx::Transform& transform, - const gfx::QuadF& q, - gfx::Point3F* p, - bool* clipped); static gfx::PointF MapPoint(const gfx::Transform& transform, const gfx::PointF& point, bool* clipped); - static gfx::Point3F MapPoint(const gfx::Transform&, - const gfx::Point3F&, - bool* clipped); - static gfx::QuadF ProjectQuad(const gfx::Transform& transform, - const gfx::QuadF& quad, - bool* clipped); static gfx::PointF ProjectPoint(const gfx::Transform& transform, const gfx::PointF& point, bool* clipped); @@ -325,7 +315,7 @@ class CC_EXPORT MathUtil { } }; -class ScopedSubnormalFloatDisabler { +class CC_BASE_EXPORT ScopedSubnormalFloatDisabler { public: ScopedSubnormalFloatDisabler(); ~ScopedSubnormalFloatDisabler(); diff --git a/chromium/cc/base/region.h b/chromium/cc/base/region.h index 87d79737752..6b5ceaf60f0 100644 --- a/chromium/cc/base/region.h +++ b/chromium/cc/base/region.h @@ -8,7 +8,7 @@ #include <memory> #include <string> -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "third_party/skia/include/core/SkRegion.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/skia_util.h" @@ -23,7 +23,7 @@ class TracedValue; namespace cc { class SimpleEnclosedRegion; -class CC_EXPORT Region { +class CC_BASE_EXPORT Region { public: Region(); Region(const Region& region); @@ -65,7 +65,7 @@ class CC_EXPORT Region { std::unique_ptr<base::Value> AsValue() const; void AsValueInto(base::trace_event::TracedValue* array) const; - class CC_EXPORT Iterator { + class CC_BASE_EXPORT Iterator { public: Iterator(); explicit Iterator(const Region& region); diff --git a/chromium/cc/output/render_surface_filters.cc b/chromium/cc/base/render_surface_filters.cc index efbdff30c5a..9eea63b258d 100644 --- a/chromium/cc/output/render_surface_filters.cc +++ b/chromium/cc/base/render_surface_filters.cc @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/output/render_surface_filters.h" +#include "cc/base/render_surface_filters.h" #include <stddef.h> #include <algorithm> -#include "cc/output/filter_operation.h" -#include "cc/output/filter_operations.h" +#include "cc/base/filter_operation.h" +#include "cc/base/filter_operations.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/effects/SkAlphaThresholdFilter.h" #include "third_party/skia/include/effects/SkBlurImageFilter.h" diff --git a/chromium/cc/output/render_surface_filters.h b/chromium/cc/base/render_surface_filters.h index 6882b0b5928..1a5a5ec0518 100644 --- a/chromium/cc/output/render_surface_filters.h +++ b/chromium/cc/base/render_surface_filters.h @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef CC_OUTPUT_RENDER_SURFACE_FILTERS_H_ -#define CC_OUTPUT_RENDER_SURFACE_FILTERS_H_ +#ifndef CC_BASE_RENDER_SURFACE_FILTERS_H_ +#define CC_BASE_RENDER_SURFACE_FILTERS_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -23,7 +22,7 @@ namespace cc { class FilterOperations; -class CC_EXPORT RenderSurfaceFilters { +class CC_BASE_EXPORT RenderSurfaceFilters { public: static SkBitmap Apply(const FilterOperations& filters, unsigned texture_id, @@ -42,4 +41,4 @@ class CC_EXPORT RenderSurfaceFilters { } // namespace cc -#endif // CC_OUTPUT_RENDER_SURFACE_FILTERS_H_ +#endif // CC_BASE_RENDER_SURFACE_FILTERS_H_ diff --git a/chromium/cc/base/reverse_spiral_iterator.h b/chromium/cc/base/reverse_spiral_iterator.h index d6c5d9e1d85..3fef364871d 100644 --- a/chromium/cc/base/reverse_spiral_iterator.h +++ b/chromium/cc/base/reverse_spiral_iterator.h @@ -6,7 +6,7 @@ #define CC_BASE_REVERSE_SPIRAL_ITERATOR_H_ #include "base/logging.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "cc/base/index_rect.h" namespace cc { @@ -27,7 +27,7 @@ namespace cc { // ├───┼───┼───┼───┼───┤ // 4 │ 5│ 4│ 3│ 2│ 1│ // └───┴───┴───┴───┴───┘ -class CC_EXPORT ReverseSpiralIterator { +class CC_BASE_EXPORT ReverseSpiralIterator { public: ReverseSpiralIterator(); ReverseSpiralIterator(const IndexRect& around_index_rect, @@ -36,6 +36,8 @@ class CC_EXPORT ReverseSpiralIterator { ~ReverseSpiralIterator() = default; + ReverseSpiralIterator& operator=(ReverseSpiralIterator&& other) = default; + operator bool() const; ReverseSpiralIterator& operator++(); int index_x() const { return index_x_; } diff --git a/chromium/cc/debug/ring_buffer.h b/chromium/cc/base/ring_buffer.h index 5f7d49ae62e..e4b03cb449e 100644 --- a/chromium/cc/debug/ring_buffer.h +++ b/chromium/cc/base/ring_buffer.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_RING_BUFFER_H_ -#define CC_DEBUG_RING_BUFFER_H_ +#ifndef CC_BASE_RING_BUFFER_H_ +#define CC_BASE_RING_BUFFER_H_ #include <stddef.h> @@ -12,23 +12,17 @@ namespace cc { -template<typename T, size_t kSize> +template <typename T, size_t kSize> class RingBuffer { public: RingBuffer() : current_index_(0) {} - size_t BufferSize() const { - return kSize; - } + size_t BufferSize() const { return kSize; } - size_t CurrentIndex() const { - return current_index_; - } + size_t CurrentIndex() const { return current_index_; } // tests if a value was saved to this index - bool IsFilledIndex(size_t n) const { - return BufferIndex(n) < current_index_; - } + bool IsFilledIndex(size_t n) const { return BufferIndex(n) < current_index_; } // n = 0 returns the oldest value and // n = bufferSize() - 1 returns the most recent value. @@ -47,9 +41,7 @@ class RingBuffer { current_index_++; } - void Clear() { - current_index_ = 0; - } + void Clear() { current_index_ = 0; } // Iterator has const access to the RingBuffer it got retrieved from. class Iterator { @@ -79,10 +71,7 @@ class RingBuffer { private: Iterator(const RingBuffer<T, kSize>& buffer, size_t index) - : buffer_(buffer), - index_(index), - out_of_range_(false) { - } + : buffer_(buffer), index_(index), out_of_range_(false) {} const RingBuffer<T, kSize>& buffer_; size_t index_; @@ -103,9 +92,7 @@ class RingBuffer { // Returns an Iterator pointing to the newest value in the buffer. // Example usage (iterate backwards from newest to oldest value): // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.End(); it; --it) {} - Iterator End() const { - return Iterator(*this, kSize - 1); - } + Iterator End() const { return Iterator(*this, kSize - 1); } private: inline size_t BufferIndex(size_t n) const { @@ -120,4 +107,4 @@ class RingBuffer { } // namespace cc -#endif // CC_DEBUG_RING_BUFFER_H_ +#endif // CC_BASE_RING_BUFFER_H_ diff --git a/chromium/cc/base/rolling_time_delta_history.h b/chromium/cc/base/rolling_time_delta_history.h index 61ed339f740..b45be0e5ec5 100644 --- a/chromium/cc/base/rolling_time_delta_history.h +++ b/chromium/cc/base/rolling_time_delta_history.h @@ -12,13 +12,13 @@ #include "base/macros.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" namespace cc { // Stores a limited number of samples. When the maximum size is reached, each // insertion results in the deletion of the oldest remaining sample. -class CC_EXPORT RollingTimeDeltaHistory { +class CC_BASE_EXPORT RollingTimeDeltaHistory { public: explicit RollingTimeDeltaHistory(size_t max_size); diff --git a/chromium/cc/base/rtree.h b/chromium/cc/base/rtree.h index 31250b2e810..3a19c29ac3d 100644 --- a/chromium/cc/base/rtree.h +++ b/chromium/cc/base/rtree.h @@ -10,7 +10,7 @@ #include <vector> -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "ui/gfx/geometry/rect.h" namespace cc { @@ -35,7 +35,7 @@ namespace cc { // Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990). // "The R*-tree: an efficient and robust access method for points and // rectangles" -class CC_EXPORT RTree { +class CC_BASE_EXPORT RTree { public: RTree(); ~RTree(); @@ -135,6 +135,8 @@ class CC_EXPORT RTree { size_t num_data_elements_; Branch root_; std::vector<Node> nodes_; + + DISALLOW_COPY_AND_ASSIGN(RTree); }; } // namespace cc diff --git a/chromium/cc/base/rtree_perftest.cc b/chromium/cc/base/rtree_perftest.cc index 85aee076691..d18d0f66fdf 100644 --- a/chromium/cc/base/rtree_perftest.cc +++ b/chromium/cc/base/rtree_perftest.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "cc/base/lap_timer.h" #include "cc/base/rtree.h" -#include "cc/debug/lap_timer.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" diff --git a/chromium/cc/base/simple_enclosed_region.h b/chromium/cc/base/simple_enclosed_region.h index e7bb9952eb3..51c137a44e9 100644 --- a/chromium/cc/base/simple_enclosed_region.h +++ b/chromium/cc/base/simple_enclosed_region.h @@ -9,7 +9,7 @@ #include <string> -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "ui/gfx/geometry/rect.h" namespace cc { @@ -19,7 +19,7 @@ class Region; // A constant-sized approximation of a Region. The SimpleEnclosedRegion may // exclude points in its approximation (may have false negatives) but will never // include a point that would not be in the actual Region (no false positives). -class CC_EXPORT SimpleEnclosedRegion { +class CC_BASE_EXPORT SimpleEnclosedRegion { public: SimpleEnclosedRegion() : rect_() {} SimpleEnclosedRegion(const SimpleEnclosedRegion& region) diff --git a/chromium/cc/base/spiral_iterator.h b/chromium/cc/base/spiral_iterator.h index d30176d0037..af64b76afde 100644 --- a/chromium/cc/base/spiral_iterator.h +++ b/chromium/cc/base/spiral_iterator.h @@ -6,7 +6,7 @@ #define CC_BASE_SPIRAL_ITERATOR_H_ #include "base/logging.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "cc/base/index_rect.h" namespace cc { @@ -27,7 +27,7 @@ namespace cc { // ├───┼───┼───┼───┼───┤ // 4 │ 20│ 21│ 22│ 23│ 24│ // └───┴───┴───┴───┴───┘ -class CC_EXPORT SpiralIterator { +class CC_BASE_EXPORT SpiralIterator { public: SpiralIterator(); SpiralIterator(const IndexRect& around_index_rect, diff --git a/chromium/cc/base/switches.cc b/chromium/cc/base/switches.cc index e0b567d6a63..1c562c9b4d7 100644 --- a/chromium/cc/base/switches.cc +++ b/chromium/cc/base/switches.cc @@ -50,14 +50,18 @@ const char kEnableColorCorrectRendering[] = "enable-color-correct-rendering"; // Enables the GPU benchmarking extension const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking"; -// Force all rasterization and compositing to be done in linear color space, -// with physically correct blending and interpolation. -const char kEnableTrueColorRendering[] = "enable-true-color-rendering"; +// Enables multi-client Surface synchronization. In practice, this indicates +// that LayerTreeHost expects to be given a valid LocalSurfaceId provided by +// the parent compositor. +const char kEnableSurfaceSynchronization[] = "enable-surface-synchronization"; // Renders a border around compositor layers to help debug and study // layer compositing. const char kShowCompositedLayerBorders[] = "show-composited-layer-borders"; const char kUIShowCompositedLayerBorders[] = "ui-show-layer-borders"; +const char kCompositedRenderPassBorders[] = "renderpass"; +const char kCompositedSurfaceBorders[] = "surface"; +const char kCompositedLayerBorders[] = "layer"; // Renders a green border around GL composited texture quads to help // debug and study overlay support. diff --git a/chromium/cc/base/switches.h b/chromium/cc/base/switches.h index 0aa1e356486..81177019bdb 100644 --- a/chromium/cc/base/switches.h +++ b/chromium/cc/base/switches.h @@ -7,7 +7,7 @@ #ifndef CC_BASE_SWITCHES_H_ #define CC_BASE_SWITCHES_H_ -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" // Since cc is used from the render process, anything that goes here also needs // to be added to render_process_host_impl.cc. @@ -16,44 +16,47 @@ namespace cc { namespace switches { // Switches for the renderer compositor only. -CC_EXPORT extern const char kDisableThreadedAnimation[]; -CC_EXPORT extern const char kDisableCompositedAntialiasing[]; -CC_EXPORT extern const char kDisableMainFrameBeforeActivation[]; -CC_EXPORT extern const char kEnableCheckerImaging[]; -CC_EXPORT extern const char kEnableMainFrameBeforeActivation[]; -CC_EXPORT extern const char kBrowserControlsHideThreshold[]; -CC_EXPORT extern const char kBrowserControlsShowThreshold[]; -CC_EXPORT extern const char kSlowDownRasterScaleFactor[]; -CC_EXPORT extern const char kStrictLayerPropertyChangeChecking[]; -CC_EXPORT extern const char kEnableTileCompression[]; +CC_BASE_EXPORT extern const char kDisableThreadedAnimation[]; +CC_BASE_EXPORT extern const char kDisableCompositedAntialiasing[]; +CC_BASE_EXPORT extern const char kDisableMainFrameBeforeActivation[]; +CC_BASE_EXPORT extern const char kEnableMainFrameBeforeActivation[]; +CC_BASE_EXPORT extern const char kEnableCheckerImaging[]; +CC_BASE_EXPORT extern const char kBrowserControlsHideThreshold[]; +CC_BASE_EXPORT extern const char kBrowserControlsShowThreshold[]; +CC_BASE_EXPORT extern const char kSlowDownRasterScaleFactor[]; +CC_BASE_EXPORT extern const char kStrictLayerPropertyChangeChecking[]; +CC_BASE_EXPORT extern const char kEnableTileCompression[]; // Switches for both the renderer and ui compositors. -CC_EXPORT extern const char kEnableColorCorrectRendering[]; -CC_EXPORT extern const char kEnableGpuBenchmarking[]; -CC_EXPORT extern const char kEnableTrueColorRendering[]; +CC_BASE_EXPORT extern const char kEnableColorCorrectRendering[]; +CC_BASE_EXPORT extern const char kEnableGpuBenchmarking[]; +CC_BASE_EXPORT extern const char kEnableSurfaceSynchronization[]; // Debug visualizations. -CC_EXPORT extern const char kShowCompositedLayerBorders[]; -CC_EXPORT extern const char kUIShowCompositedLayerBorders[]; -CC_EXPORT extern const char kGlCompositedTextureQuadBorder[]; -CC_EXPORT extern const char kShowFPSCounter[]; -CC_EXPORT extern const char kUIShowFPSCounter[]; -CC_EXPORT extern const char kShowLayerAnimationBounds[]; -CC_EXPORT extern const char kUIShowLayerAnimationBounds[]; -CC_EXPORT extern const char kShowPropertyChangedRects[]; -CC_EXPORT extern const char kUIShowPropertyChangedRects[]; -CC_EXPORT extern const char kShowSurfaceDamageRects[]; -CC_EXPORT extern const char kUIShowSurfaceDamageRects[]; -CC_EXPORT extern const char kShowScreenSpaceRects[]; -CC_EXPORT extern const char kUIShowScreenSpaceRects[]; -CC_EXPORT extern const char kEnableLayerLists[]; -CC_EXPORT extern const char kUIEnableLayerLists[]; -CC_EXPORT extern const char kShowOverdrawFeedback[]; +CC_BASE_EXPORT extern const char kShowCompositedLayerBorders[]; +CC_BASE_EXPORT extern const char kUIShowCompositedLayerBorders[]; +CC_BASE_EXPORT extern const char kGlCompositedTextureQuadBorder[]; +CC_BASE_EXPORT extern const char kShowFPSCounter[]; +CC_BASE_EXPORT extern const char kUIShowFPSCounter[]; +CC_BASE_EXPORT extern const char kShowLayerAnimationBounds[]; +CC_BASE_EXPORT extern const char kUIShowLayerAnimationBounds[]; +CC_BASE_EXPORT extern const char kShowPropertyChangedRects[]; +CC_BASE_EXPORT extern const char kUIShowPropertyChangedRects[]; +CC_BASE_EXPORT extern const char kShowSurfaceDamageRects[]; +CC_BASE_EXPORT extern const char kUIShowSurfaceDamageRects[]; +CC_BASE_EXPORT extern const char kShowScreenSpaceRects[]; +CC_BASE_EXPORT extern const char kUIShowScreenSpaceRects[]; +CC_BASE_EXPORT extern const char kEnableLayerLists[]; +CC_BASE_EXPORT extern const char kUIEnableLayerLists[]; +CC_BASE_EXPORT extern const char kShowOverdrawFeedback[]; +CC_BASE_EXPORT extern const char kCompositedRenderPassBorders[]; +CC_BASE_EXPORT extern const char kCompositedSurfaceBorders[]; +CC_BASE_EXPORT extern const char kCompositedLayerBorders[]; // Unit test related. -CC_EXPORT extern const char kCCLayerTreeTestNoTimeout[]; -CC_EXPORT extern const char kCCLayerTreeTestLongTimeout[]; -CC_EXPORT extern const char kCCRebaselinePixeltests[]; +CC_BASE_EXPORT extern const char kCCLayerTreeTestNoTimeout[]; +CC_BASE_EXPORT extern const char kCCLayerTreeTestLongTimeout[]; +CC_BASE_EXPORT extern const char kCCRebaselinePixeltests[]; } // namespace switches } // namespace cc diff --git a/chromium/cc/base/tiling_data.h b/chromium/cc/base/tiling_data.h index 645193b5ada..a8b9ee7ec6c 100644 --- a/chromium/cc/base/tiling_data.h +++ b/chromium/cc/base/tiling_data.h @@ -8,7 +8,7 @@ #include <utility> #include "base/logging.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" #include "cc/base/index_rect.h" #include "cc/base/reverse_spiral_iterator.h" #include "cc/base/spiral_iterator.h" @@ -22,7 +22,7 @@ class Vector2d; namespace cc { -class CC_EXPORT TilingData { +class CC_BASE_EXPORT TilingData { public: TilingData(); TilingData(const gfx::Size& max_texture_size, @@ -72,7 +72,7 @@ class CC_EXPORT TilingData { // Difference between TileBound's and TileBoundWithBorder's origin(). gfx::Vector2d TextureOffset(int x_index, int y_index) const; - class CC_EXPORT BaseIterator { + class CC_BASE_EXPORT BaseIterator { public: operator bool() const { return index_x_ != -1 && index_y_ != -1; } @@ -94,7 +94,7 @@ class CC_EXPORT TilingData { }; // Iterate through tiles whose bounds + optional border intersect with |rect|. - class CC_EXPORT Iterator : public BaseIterator { + class CC_BASE_EXPORT Iterator : public BaseIterator { public: Iterator(); Iterator(const TilingData* tiling_data, @@ -106,7 +106,7 @@ class CC_EXPORT TilingData { IndexRect index_rect_; }; - class CC_EXPORT BaseDifferenceIterator : public BaseIterator { + class CC_BASE_EXPORT BaseDifferenceIterator : public BaseIterator { protected: BaseDifferenceIterator(); BaseDifferenceIterator(const TilingData* tiling_data, @@ -121,7 +121,7 @@ class CC_EXPORT TilingData { // Iterate through all indices whose bounds (not including borders) intersect // with |consider| but which also do not intersect with |ignore|. - class CC_EXPORT DifferenceIterator : public BaseDifferenceIterator { + class CC_BASE_EXPORT DifferenceIterator : public BaseDifferenceIterator { public: DifferenceIterator(); DifferenceIterator(const TilingData* tiling_data, @@ -133,7 +133,8 @@ class CC_EXPORT TilingData { // Iterate through all indices whose bounds + border intersect with // |consider| but which also do not intersect with |ignore|. The iterator // order is a counterclockwise spiral around the given center. - class CC_EXPORT SpiralDifferenceIterator : public BaseDifferenceIterator { + class CC_BASE_EXPORT SpiralDifferenceIterator + : public BaseDifferenceIterator { public: SpiralDifferenceIterator(); SpiralDifferenceIterator(const TilingData* tiling_data, @@ -146,7 +147,7 @@ class CC_EXPORT TilingData { SpiralIterator spiral_iterator_; }; - class CC_EXPORT ReverseSpiralDifferenceIterator + class CC_BASE_EXPORT ReverseSpiralDifferenceIterator : public BaseDifferenceIterator { public: ReverseSpiralDifferenceIterator(); diff --git a/chromium/cc/base/unique_notifier.cc b/chromium/cc/base/unique_notifier.cc index 15fb7b7e91a..54cb39e7ec3 100644 --- a/chromium/cc/base/unique_notifier.cc +++ b/chromium/cc/base/unique_notifier.cc @@ -34,7 +34,7 @@ void UniqueNotifier::Schedule() { task_runner_->PostTask( FROM_HERE, - base::Bind(&UniqueNotifier::Notify, weak_ptr_factory_.GetWeakPtr())); + base::BindOnce(&UniqueNotifier::Notify, weak_ptr_factory_.GetWeakPtr())); notification_pending_ = true; } diff --git a/chromium/cc/base/unique_notifier.h b/chromium/cc/base/unique_notifier.h index fc0e392d672..e4fb7b55732 100644 --- a/chromium/cc/base/unique_notifier.h +++ b/chromium/cc/base/unique_notifier.h @@ -8,7 +8,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "cc/base/cc_export.h" +#include "cc/base/base_export.h" namespace base { class SequencedTaskRunner; @@ -16,7 +16,7 @@ class SequencedTaskRunner; namespace cc { -class CC_EXPORT UniqueNotifier { +class CC_BASE_EXPORT UniqueNotifier { public: // Configure this notifier to issue the |closure| notification when scheduled. UniqueNotifier(base::SequencedTaskRunner* task_runner, diff --git a/chromium/cc/debug/benchmark_instrumentation.cc b/chromium/cc/benchmarks/benchmark_instrumentation.cc index ff2217154f4..5674c2feaf3 100644 --- a/chromium/cc/debug/benchmark_instrumentation.cc +++ b/chromium/cc/benchmarks/benchmark_instrumentation.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "cc/benchmarks/benchmark_instrumentation.h" #include "base/trace_event/trace_event.h" -#include "cc/debug/benchmark_instrumentation.h" namespace cc { namespace benchmark_instrumentation { diff --git a/chromium/cc/debug/benchmark_instrumentation.h b/chromium/cc/benchmarks/benchmark_instrumentation.h index af70156e1c2..9b5e5efef97 100644 --- a/chromium/cc/debug/benchmark_instrumentation.h +++ b/chromium/cc/benchmarks/benchmark_instrumentation.h @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_BENCHMARK_INSTRUMENTATION_H_ -#define CC_DEBUG_BENCHMARK_INSTRUMENTATION_H_ +#ifndef CC_BENCHMARKS_BENCHMARK_INSTRUMENTATION_H_ +#define CC_BENCHMARKS_BENCHMARK_INSTRUMENTATION_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "base/trace_event/trace_event.h" +#include "cc/cc_export.h" #include "cc/debug/rendering_stats.h" namespace cc { @@ -30,10 +31,8 @@ class ScopedBeginFrameTask { public: ScopedBeginFrameTask(const char* event_name, unsigned int begin_frame_id) : event_name_(event_name) { - TRACE_EVENT_BEGIN1(internal::kCategory, - event_name_, - internal::kBeginFrameId, - begin_frame_id); + TRACE_EVENT_BEGIN1(internal::kCategory, event_name_, + internal::kBeginFrameId, begin_frame_id); } ~ScopedBeginFrameTask() { TRACE_EVENT_END0(internal::kCategory, event_name_); @@ -51,4 +50,4 @@ void CC_EXPORT IssueDisplayRenderingStatsEvent(); } // namespace benchmark_instrumentation } // namespace cc -#endif // CC_DEBUG_BENCHMARK_INSTRUMENTATION_H_ +#endif // CC_BENCHMARKS_BENCHMARK_INSTRUMENTATION_H_ diff --git a/chromium/cc/debug/invalidation_benchmark.cc b/chromium/cc/benchmarks/invalidation_benchmark.cc index 6e6d343389d..c44a157396e 100644 --- a/chromium/cc/debug/invalidation_benchmark.cc +++ b/chromium/cc/benchmarks/invalidation_benchmark.cc @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/invalidation_benchmark.h" +#include "cc/benchmarks/invalidation_benchmark.h" #include <stdint.h> #include <algorithm> #include <limits> +#include "base/memory/ptr_util.h" #include "base/rand_util.h" #include "base/values.h" #include "cc/layers/layer.h" @@ -60,8 +61,7 @@ InvalidationBenchmark::InvalidationBenchmark( } } -InvalidationBenchmark::~InvalidationBenchmark() { -} +InvalidationBenchmark::~InvalidationBenchmark() {} void InvalidationBenchmark::DidUpdateLayers(LayerTreeHost* layer_tree_host) { LayerTreeHostCommon::CallFunctionForEveryLayer( @@ -72,7 +72,7 @@ void InvalidationBenchmark::DidUpdateLayers(LayerTreeHost* layer_tree_host) { void InvalidationBenchmark::RunOnLayer(PictureLayer* layer) { gfx::Rect visible_layer_rect = gfx::Rect(layer->bounds()); gfx::Transform from_screen; - bool invertible = layer->screen_space_transform().GetInverse(&from_screen); + bool invertible = layer->ScreenSpaceTransform().GetInverse(&from_screen); if (!invertible) from_screen = gfx::Transform(); gfx::Rect viewport_rect = MathUtil::ProjectEnclosingClippedRect( @@ -124,7 +124,7 @@ bool InvalidationBenchmark::ProcessMessage(std::unique_ptr<base::Value> value) { if (message->HasKey("notify_done")) { message->GetBoolean("notify_done", ¬ify_done); if (notify_done) - NotifyDone(base::Value::CreateNullValue()); + NotifyDone(base::MakeUnique<base::Value>()); return true; } return false; diff --git a/chromium/cc/debug/invalidation_benchmark.h b/chromium/cc/benchmarks/invalidation_benchmark.h index a04663d64f0..b9fbb727bb0 100644 --- a/chromium/cc/debug/invalidation_benchmark.h +++ b/chromium/cc/benchmarks/invalidation_benchmark.h @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_INVALIDATION_BENCHMARK_H_ -#define CC_DEBUG_INVALIDATION_BENCHMARK_H_ +#ifndef CC_BENCHMARKS_INVALIDATION_BENCHMARK_H_ +#define CC_BENCHMARKS_INVALIDATION_BENCHMARK_H_ #include <stdint.h> #include <string> -#include "cc/debug/micro_benchmark_controller.h" +#include "cc/benchmarks/micro_benchmark_controller.h" namespace cc { @@ -43,4 +43,4 @@ class CC_EXPORT InvalidationBenchmark : public MicroBenchmark { } // namespace cc -#endif // CC_DEBUG_INVALIDATION_BENCHMARK_H_ +#endif // CC_BENCHMARKS_INVALIDATION_BENCHMARK_H_ diff --git a/chromium/cc/debug/micro_benchmark.cc b/chromium/cc/benchmarks/micro_benchmark.cc index 4bbca390a47..456431bd79d 100644 --- a/chromium/cc/debug/micro_benchmark.cc +++ b/chromium/cc/benchmarks/micro_benchmark.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/micro_benchmark.h" +#include "cc/benchmarks/micro_benchmark.h" #include <memory> @@ -11,7 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/values.h" -#include "cc/debug/micro_benchmark_impl.h" +#include "cc/benchmarks/micro_benchmark_impl.h" namespace cc { @@ -19,8 +19,7 @@ MicroBenchmark::MicroBenchmark(const DoneCallback& callback) : callback_(callback), is_done_(false), processed_for_benchmark_impl_(false), - id_(0) { -} + id_(0) {} MicroBenchmark::~MicroBenchmark() {} diff --git a/chromium/cc/debug/micro_benchmark.h b/chromium/cc/benchmarks/micro_benchmark.h index 6703bf4ee4a..5ffadc0d0a0 100644 --- a/chromium/cc/debug/micro_benchmark.h +++ b/chromium/cc/benchmarks/micro_benchmark.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_MICRO_BENCHMARK_H_ -#define CC_DEBUG_MICRO_BENCHMARK_H_ +#ifndef CC_BENCHMARKS_MICRO_BENCHMARK_H_ +#define CC_BENCHMARKS_MICRO_BENCHMARK_H_ #include <memory> #include "base/callback.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { class SingleThreadTaskRunner; @@ -57,4 +57,4 @@ class CC_EXPORT MicroBenchmark { } // namespace cc -#endif // CC_DEBUG_MICRO_BENCHMARK_H_ +#endif // CC_BENCHMARKS_MICRO_BENCHMARK_H_ diff --git a/chromium/cc/debug/micro_benchmark_controller.cc b/chromium/cc/benchmarks/micro_benchmark_controller.cc index 94d3d2e31f2..f55a607c7ab 100644 --- a/chromium/cc/debug/micro_benchmark_controller.cc +++ b/chromium/cc/benchmarks/micro_benchmark_controller.cc @@ -2,18 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/micro_benchmark_controller.h" +#include "cc/benchmarks/micro_benchmark_controller.h" #include <limits> #include <string> #include "base/callback.h" #include "base/memory/ptr_util.h" +#include "base/stl_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" -#include "cc/debug/invalidation_benchmark.h" -#include "cc/debug/rasterize_and_record_benchmark.h" -#include "cc/debug/unittest_only_benchmark.h" +#include "cc/benchmarks/invalidation_benchmark.h" +#include "cc/benchmarks/rasterize_and_record_benchmark.h" +#include "cc/benchmarks/unittest_only_benchmark.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_host_impl.h" @@ -110,12 +111,10 @@ void MicroBenchmarkController::DidUpdateLayers() { } void MicroBenchmarkController::CleanUpFinishedBenchmarks() { - benchmarks_.erase( - std::remove_if(benchmarks_.begin(), benchmarks_.end(), - [](const std::unique_ptr<MicroBenchmark>& benchmark) { - return benchmark->IsDone(); - }), - benchmarks_.end()); + base::EraseIf(benchmarks_, + [](const std::unique_ptr<MicroBenchmark>& benchmark) { + return benchmark->IsDone(); + }); } } // namespace cc diff --git a/chromium/cc/debug/micro_benchmark_controller.h b/chromium/cc/benchmarks/micro_benchmark_controller.h index 88ccc840ab5..0f38800241c 100644 --- a/chromium/cc/debug/micro_benchmark_controller.h +++ b/chromium/cc/benchmarks/micro_benchmark_controller.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_H_ -#define CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_H_ +#ifndef CC_BENCHMARKS_MICRO_BENCHMARK_CONTROLLER_H_ +#define CC_BENCHMARKS_MICRO_BENCHMARK_CONTROLLER_H_ #include <string> #include <vector> #include "base/callback.h" #include "base/macros.h" -#include "cc/debug/micro_benchmark.h" +#include "cc/benchmarks/micro_benchmark.h" namespace base { class SingleThreadTaskRunner; @@ -51,4 +51,4 @@ class CC_EXPORT MicroBenchmarkController { } // namespace cc -#endif // CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_H_ +#endif // CC_BENCHMARKS_MICRO_BENCHMARK_CONTROLLER_H_ diff --git a/chromium/cc/debug/micro_benchmark_controller_impl.cc b/chromium/cc/benchmarks/micro_benchmark_controller_impl.cc index 7c46aedab8f..2e53c451539 100644 --- a/chromium/cc/debug/micro_benchmark_controller_impl.cc +++ b/chromium/cc/benchmarks/micro_benchmark_controller_impl.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/micro_benchmark_controller_impl.h" +#include "cc/benchmarks/micro_benchmark_controller_impl.h" #include <string> #include "base/callback.h" +#include "base/stl_util.h" #include "base/values.h" #include "cc/trees/layer_tree_host_impl.h" @@ -35,12 +36,10 @@ void MicroBenchmarkControllerImpl::DidCompleteCommit() { } void MicroBenchmarkControllerImpl::CleanUpFinishedBenchmarks() { - benchmarks_.erase( - std::remove_if(benchmarks_.begin(), benchmarks_.end(), - [](const std::unique_ptr<MicroBenchmarkImpl>& benchmark) { - return benchmark->IsDone(); - }), - benchmarks_.end()); + base::EraseIf(benchmarks_, + [](const std::unique_ptr<MicroBenchmarkImpl>& benchmark) { + return benchmark->IsDone(); + }); } } // namespace cc diff --git a/chromium/cc/debug/micro_benchmark_controller_impl.h b/chromium/cc/benchmarks/micro_benchmark_controller_impl.h index 67c8005059a..79482436486 100644 --- a/chromium/cc/debug/micro_benchmark_controller_impl.h +++ b/chromium/cc/benchmarks/micro_benchmark_controller_impl.h @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_IMPL_H_ -#define CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_IMPL_H_ +#ifndef CC_BENCHMARKS_MICRO_BENCHMARK_CONTROLLER_IMPL_H_ +#define CC_BENCHMARKS_MICRO_BENCHMARK_CONTROLLER_IMPL_H_ #include <string> #include <vector> #include "base/macros.h" -#include "cc/debug/micro_benchmark_impl.h" +#include "cc/benchmarks/micro_benchmark_impl.h" namespace cc { @@ -34,4 +34,4 @@ class CC_EXPORT MicroBenchmarkControllerImpl { } // namespace cc -#endif // CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_IMPL_H_ +#endif // CC_BENCHMARKS_MICRO_BENCHMARK_CONTROLLER_IMPL_H_ diff --git a/chromium/cc/debug/micro_benchmark_controller_unittest.cc b/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc index 4a6ce7e50ee..08f3de6e50c 100644 --- a/chromium/cc/debug/micro_benchmark_controller_unittest.cc +++ b/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/micro_benchmark_controller.h" +#include "cc/benchmarks/micro_benchmark_controller.h" #include <memory> @@ -10,7 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "cc/animation/animation_host.h" -#include "cc/debug/micro_benchmark.h" +#include "cc/benchmarks/micro_benchmark.h" #include "cc/layers/layer.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host.h" @@ -61,15 +61,15 @@ void IncrementCallCount(int* count, std::unique_ptr<base::Value> value) { } TEST_F(MicroBenchmarkControllerTest, ScheduleFail) { - int id = layer_tree_host_->ScheduleMicroBenchmark( - "non_existant_benchmark", nullptr, base::Bind(&Noop)); + int id = layer_tree_host_->ScheduleMicroBenchmark("non_existant_benchmark", + nullptr, base::Bind(&Noop)); EXPECT_EQ(id, 0); } TEST_F(MicroBenchmarkControllerTest, CommitScheduled) { EXPECT_FALSE(layer_tree_host_->needs_commit()); - int id = layer_tree_host_->ScheduleMicroBenchmark( - "unittest_only_benchmark", nullptr, base::Bind(&Noop)); + int id = layer_tree_host_->ScheduleMicroBenchmark("unittest_only_benchmark", + nullptr, base::Bind(&Noop)); EXPECT_GT(id, 0); EXPECT_TRUE(layer_tree_host_->needs_commit()); } @@ -77,8 +77,7 @@ TEST_F(MicroBenchmarkControllerTest, CommitScheduled) { TEST_F(MicroBenchmarkControllerTest, BenchmarkRan) { int run_count = 0; int id = layer_tree_host_->ScheduleMicroBenchmark( - "unittest_only_benchmark", - nullptr, + "unittest_only_benchmark", nullptr, base::Bind(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); @@ -90,13 +89,11 @@ TEST_F(MicroBenchmarkControllerTest, BenchmarkRan) { TEST_F(MicroBenchmarkControllerTest, MultipleBenchmarkRan) { int run_count = 0; int id = layer_tree_host_->ScheduleMicroBenchmark( - "unittest_only_benchmark", - nullptr, + "unittest_only_benchmark", nullptr, base::Bind(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); id = layer_tree_host_->ScheduleMicroBenchmark( - "unittest_only_benchmark", - nullptr, + "unittest_only_benchmark", nullptr, base::Bind(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); @@ -105,13 +102,11 @@ TEST_F(MicroBenchmarkControllerTest, MultipleBenchmarkRan) { EXPECT_EQ(2, run_count); id = layer_tree_host_->ScheduleMicroBenchmark( - "unittest_only_benchmark", - nullptr, + "unittest_only_benchmark", nullptr, base::Bind(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); id = layer_tree_host_->ScheduleMicroBenchmark( - "unittest_only_benchmark", - nullptr, + "unittest_only_benchmark", nullptr, base::Bind(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); @@ -157,8 +152,7 @@ TEST_F(MicroBenchmarkControllerTest, SendMessage) { // Schedule a benchmark int run_count = 0; int id = layer_tree_host_->ScheduleMicroBenchmark( - "unittest_only_benchmark", - nullptr, + "unittest_only_benchmark", nullptr, base::Bind(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); diff --git a/chromium/cc/debug/micro_benchmark_impl.cc b/chromium/cc/benchmarks/micro_benchmark_impl.cc index 8f818fd16ea..f05ebe8f97d 100644 --- a/chromium/cc/debug/micro_benchmark_impl.cc +++ b/chromium/cc/benchmarks/micro_benchmark_impl.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/micro_benchmark_impl.h" +#include "cc/benchmarks/micro_benchmark_impl.h" #include <memory> @@ -20,7 +20,6 @@ void RunCallback(const MicroBenchmarkImpl::DoneCallback& callback, std::unique_ptr<base::Value> result) { callback.Run(std::move(result)); } - } MicroBenchmarkImpl::MicroBenchmarkImpl( @@ -28,8 +27,7 @@ MicroBenchmarkImpl::MicroBenchmarkImpl( scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner) : callback_(callback), is_done_(false), - origin_task_runner_(origin_task_runner) { -} + origin_task_runner_(origin_task_runner) {} MicroBenchmarkImpl::~MicroBenchmarkImpl() {} @@ -41,7 +39,7 @@ void MicroBenchmarkImpl::DidCompleteCommit(LayerTreeHostImpl* host) {} void MicroBenchmarkImpl::NotifyDone(std::unique_ptr<base::Value> result) { origin_task_runner_->PostTask( - FROM_HERE, base::Bind(RunCallback, callback_, base::Passed(&result))); + FROM_HERE, base::BindOnce(RunCallback, callback_, base::Passed(&result))); is_done_ = true; } diff --git a/chromium/cc/debug/micro_benchmark_impl.h b/chromium/cc/benchmarks/micro_benchmark_impl.h index 457eb4dbf4d..d13ba4f97ed 100644 --- a/chromium/cc/debug/micro_benchmark_impl.h +++ b/chromium/cc/benchmarks/micro_benchmark_impl.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_MICRO_BENCHMARK_IMPL_H_ -#define CC_DEBUG_MICRO_BENCHMARK_IMPL_H_ +#ifndef CC_BENCHMARKS_MICRO_BENCHMARK_IMPL_H_ +#define CC_BENCHMARKS_MICRO_BENCHMARK_IMPL_H_ #include <memory> #include "base/callback.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { class SingleThreadTaskRunner; @@ -46,4 +46,4 @@ class CC_EXPORT MicroBenchmarkImpl { } // namespace cc -#endif // CC_DEBUG_MICRO_BENCHMARK_IMPL_H_ +#endif // CC_BENCHMARKS_MICRO_BENCHMARK_IMPL_H_ diff --git a/chromium/cc/debug/rasterize_and_record_benchmark.cc b/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc index 3b53a4ce9dd..6314fdef87e 100644 --- a/chromium/cc/debug/rasterize_and_record_benchmark.cc +++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/rasterize_and_record_benchmark.h" +#include "cc/benchmarks/rasterize_and_record_benchmark.h" #include <stddef.h> @@ -13,17 +13,16 @@ #include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" #include "base/values.h" -#include "cc/debug/lap_timer.h" -#include "cc/debug/rasterize_and_record_benchmark_impl.h" +#include "cc/base/lap_timer.h" +#include "cc/benchmarks/rasterize_and_record_benchmark_impl.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/layer.h" #include "cc/layers/picture_layer.h" -#include "cc/playback/display_item_list.h" -#include "cc/playback/recording_source.h" +#include "cc/layers/recording_source.h" +#include "cc/paint/display_item_list.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_host_common.h" #include "skia/ext/analysis_canvas.h" -#include "third_party/skia/include/utils/SkPictureUtils.h" #include "ui/gfx/geometry/rect.h" namespace cc { @@ -191,8 +190,7 @@ void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) { } RasterizeAndRecordBenchmark::RecordResults::RecordResults() - : pixels_recorded(0), bytes_used(0) { -} + : pixels_recorded(0), bytes_used(0) {} RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {} diff --git a/chromium/cc/debug/rasterize_and_record_benchmark.h b/chromium/cc/benchmarks/rasterize_and_record_benchmark.h index 91734a50c1a..14871642af2 100644 --- a/chromium/cc/debug/rasterize_and_record_benchmark.h +++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_H_ -#define CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_H_ +#ifndef CC_BENCHMARKS_RASTERIZE_AND_RECORD_BENCHMARK_H_ +#define CC_BENCHMARKS_RASTERIZE_AND_RECORD_BENCHMARK_H_ #include <stddef.h> @@ -14,8 +14,8 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/time/time.h" -#include "cc/debug/micro_benchmark_controller.h" -#include "cc/playback/recording_source.h" +#include "cc/benchmarks/micro_benchmark_controller.h" +#include "cc/layers/recording_source.h" namespace base { class DictionaryValue; @@ -66,4 +66,4 @@ class RasterizeAndRecordBenchmark : public MicroBenchmark { } // namespace cc -#endif // CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_H_ +#endif // CC_BENCHMARKS_RASTERIZE_AND_RECORD_BENCHMARK_H_ diff --git a/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc index 46123e0f5dc..203f770b7e4 100644 --- a/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc +++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/rasterize_and_record_benchmark_impl.h" +#include "cc/benchmarks/rasterize_and_record_benchmark_impl.h" #include <stddef.h> @@ -10,13 +10,14 @@ #include <limits> #include "base/values.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/layers/layer_impl.h" #include "cc/layers/picture_layer_impl.h" #include "cc/raster/raster_buffer_provider.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" +#include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect.h" namespace cc { @@ -52,9 +53,10 @@ void RunBenchmark(RasterSource* raster_source, bitmap.allocPixels(SkImageInfo::MakeN32Premul(content_rect.width(), content_rect.height())); SkCanvas canvas(bitmap); - raster_source->PlaybackToCanvas(&canvas, content_rect, content_rect, - contents_scale, - RasterSource::PlaybackSettings()); + raster_source->PlaybackToCanvas( + &canvas, gfx::ColorSpace(), content_rect, content_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + RasterSource::PlaybackSettings()); timer.NextLap(); } while (!timer.HasTimeLimitExpired()); @@ -177,7 +179,7 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) { settings.max_preraster_distance_in_screen_pixels); PictureLayerTiling* tiling = - tiling_set->AddTiling(1.f, layer->GetRasterSource()); + tiling_set->AddTiling(gfx::AxisTransform2d(), layer->GetRasterSource()); tiling->set_resolution(HIGH_RESOLUTION); tiling->CreateAllTilesForTesting(); RasterSource* raster_source = tiling->raster_source().get(); @@ -187,7 +189,7 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) { DCHECK(*it); gfx::Rect content_rect = (*it)->content_rect(); - float contents_scale = (*it)->contents_scale(); + float contents_scale = (*it)->raster_transform().scale(); base::TimeDelta min_time; bool is_solid_color = false; @@ -218,8 +220,7 @@ RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults() total_layers(0), total_picture_layers(0), total_picture_layers_with_no_content(0), - total_picture_layers_off_screen(0) { -} + total_picture_layers_off_screen(0) {} RasterizeAndRecordBenchmarkImpl::RasterizeResults::~RasterizeResults() {} diff --git a/chromium/cc/debug/rasterize_and_record_benchmark_impl.h b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h index 6d25c8affc1..2804c0149ee 100644 --- a/chromium/cc/debug/rasterize_and_record_benchmark_impl.h +++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_IMPL_H_ -#define CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_IMPL_H_ +#ifndef CC_BENCHMARKS_RASTERIZE_AND_RECORD_BENCHMARK_IMPL_H_ +#define CC_BENCHMARKS_RASTERIZE_AND_RECORD_BENCHMARK_IMPL_H_ #include <stddef.h> @@ -13,7 +13,7 @@ #include "base/single_thread_task_runner.h" #include "base/time/time.h" -#include "cc/debug/micro_benchmark_impl.h" +#include "cc/benchmarks/micro_benchmark_impl.h" #include "cc/raster/task_graph_runner.h" namespace cc { @@ -55,4 +55,4 @@ class RasterizeAndRecordBenchmarkImpl : public MicroBenchmarkImpl { } // namespace cc -#endif // CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_IMPL_H_ +#endif // CC_BENCHMARKS_RASTERIZE_AND_RECORD_BENCHMARK_IMPL_H_ diff --git a/chromium/cc/debug/unittest_only_benchmark.cc b/chromium/cc/benchmarks/unittest_only_benchmark.cc index 321444d9aa8..5ba8bcfe6f1 100644 --- a/chromium/cc/debug/unittest_only_benchmark.cc +++ b/chromium/cc/benchmarks/unittest_only_benchmark.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/unittest_only_benchmark.h" +#include "cc/benchmarks/unittest_only_benchmark.h" #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/values.h" -#include "cc/debug/unittest_only_benchmark_impl.h" +#include "cc/benchmarks/unittest_only_benchmark_impl.h" namespace cc { diff --git a/chromium/cc/debug/unittest_only_benchmark.h b/chromium/cc/benchmarks/unittest_only_benchmark.h index ffeaceb3660..277c4274dba 100644 --- a/chromium/cc/debug/unittest_only_benchmark.h +++ b/chromium/cc/benchmarks/unittest_only_benchmark.h @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_UNITTEST_ONLY_BENCHMARK_H_ -#define CC_DEBUG_UNITTEST_ONLY_BENCHMARK_H_ +#ifndef CC_BENCHMARKS_UNITTEST_ONLY_BENCHMARK_H_ +#define CC_BENCHMARKS_UNITTEST_ONLY_BENCHMARK_H_ #include "base/memory/weak_ptr.h" -#include "cc/debug/micro_benchmark.h" +#include "cc/benchmarks/micro_benchmark.h" namespace cc { @@ -32,4 +32,4 @@ class CC_EXPORT UnittestOnlyBenchmark : public MicroBenchmark { } // namespace cc -#endif // CC_DEBUG_UNITTEST_ONLY_BENCHMARK_H_ +#endif // CC_BENCHMARKS_UNITTEST_ONLY_BENCHMARK_H_ diff --git a/chromium/cc/debug/unittest_only_benchmark_impl.cc b/chromium/cc/benchmarks/unittest_only_benchmark_impl.cc index 59e3d274738..7bad5474fd3 100644 --- a/chromium/cc/debug/unittest_only_benchmark_impl.cc +++ b/chromium/cc/benchmarks/unittest_only_benchmark_impl.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/unittest_only_benchmark_impl.h" +#include "cc/benchmarks/unittest_only_benchmark_impl.h" #include "base/single_thread_task_runner.h" #include "base/values.h" @@ -13,8 +13,7 @@ UnittestOnlyBenchmarkImpl::UnittestOnlyBenchmarkImpl( scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner, base::Value* settings, const DoneCallback& callback) - : MicroBenchmarkImpl(callback, origin_task_runner) { -} + : MicroBenchmarkImpl(callback, origin_task_runner) {} UnittestOnlyBenchmarkImpl::~UnittestOnlyBenchmarkImpl() {} diff --git a/chromium/cc/debug/unittest_only_benchmark_impl.h b/chromium/cc/benchmarks/unittest_only_benchmark_impl.h index 1444850fb93..a378b9e2592 100644 --- a/chromium/cc/debug/unittest_only_benchmark_impl.h +++ b/chromium/cc/benchmarks/unittest_only_benchmark_impl.h @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_UNITTEST_ONLY_BENCHMARK_IMPL_H_ -#define CC_DEBUG_UNITTEST_ONLY_BENCHMARK_IMPL_H_ +#ifndef CC_BENCHMARKS_UNITTEST_ONLY_BENCHMARK_IMPL_H_ +#define CC_BENCHMARKS_UNITTEST_ONLY_BENCHMARK_IMPL_H_ #include "base/memory/weak_ptr.h" -#include "cc/debug/micro_benchmark_impl.h" +#include "cc/benchmarks/micro_benchmark_impl.h" namespace base { class SingleThreadTaskRunner; @@ -29,4 +29,4 @@ class CC_EXPORT UnittestOnlyBenchmarkImpl : public MicroBenchmarkImpl { } // namespace cc -#endif // CC_DEBUG_UNITTEST_ONLY_BENCHMARK_IMPL_H_ +#endif // CC_BENCHMARKS_UNITTEST_ONLY_BENCHMARK_IMPL_H_ diff --git a/chromium/cc/blink/BUILD.gn b/chromium/cc/blink/BUILD.gn index a1053c54092..27fd6c5ee76 100644 --- a/chromium/cc/blink/BUILD.gn +++ b/chromium/cc/blink/BUILD.gn @@ -53,6 +53,7 @@ cc_test("cc_blink_unittests") { # Setup. "test/cc_blink_test_suite.cc", + "test/cc_blink_test_suite.h", "test/run_all_unittests.cc", ] diff --git a/chromium/cc/blink/scrollbar_impl.cc b/chromium/cc/blink/scrollbar_impl.cc index 4ba11e33ee2..7ee40cf4339 100644 --- a/chromium/cc/blink/scrollbar_impl.cc +++ b/chromium/cc/blink/scrollbar_impl.cc @@ -24,106 +24,106 @@ ScrollbarImpl::~ScrollbarImpl() { } cc::ScrollbarOrientation ScrollbarImpl::Orientation() const { - if (scrollbar_->orientation() == WebScrollbar::Horizontal) + if (scrollbar_->GetOrientation() == WebScrollbar::kHorizontal) return cc::HORIZONTAL; return cc::VERTICAL; } bool ScrollbarImpl::IsLeftSideVerticalScrollbar() const { - return scrollbar_->isLeftSideVerticalScrollbar(); + return scrollbar_->IsLeftSideVerticalScrollbar(); } bool ScrollbarImpl::HasThumb() const { - return geometry_->hasThumb(scrollbar_.get()); + return geometry_->HasThumb(scrollbar_.get()); } bool ScrollbarImpl::IsOverlay() const { - return scrollbar_->isOverlay(); + return scrollbar_->IsOverlay(); } gfx::Point ScrollbarImpl::Location() const { - return scrollbar_->location(); + return scrollbar_->Location(); } int ScrollbarImpl::ThumbThickness() const { - gfx::Rect thumb_rect = geometry_->thumbRect(scrollbar_.get()); - if (scrollbar_->orientation() == WebScrollbar::Horizontal) + gfx::Rect thumb_rect = geometry_->ThumbRect(scrollbar_.get()); + if (scrollbar_->GetOrientation() == WebScrollbar::kHorizontal) return thumb_rect.height(); return thumb_rect.width(); } int ScrollbarImpl::ThumbLength() const { - gfx::Rect thumb_rect = geometry_->thumbRect(scrollbar_.get()); - if (scrollbar_->orientation() == WebScrollbar::Horizontal) + gfx::Rect thumb_rect = geometry_->ThumbRect(scrollbar_.get()); + if (scrollbar_->GetOrientation() == WebScrollbar::kHorizontal) return thumb_rect.width(); return thumb_rect.height(); } gfx::Rect ScrollbarImpl::TrackRect() const { - return geometry_->trackRect(scrollbar_.get()); + return geometry_->TrackRect(scrollbar_.get()); } float ScrollbarImpl::ThumbOpacity() const { - return painter_.thumbOpacity(); + return painter_.ThumbOpacity(); } bool ScrollbarImpl::NeedsPaintPart(cc::ScrollbarPart part) const { if (part == cc::THUMB) - return painter_.thumbNeedsRepaint(); - return painter_.trackNeedsRepaint(); + return painter_.ThumbNeedsRepaint(); + return painter_.TrackNeedsRepaint(); } bool ScrollbarImpl::UsesNinePatchThumbResource() const { - return painter_.usesNinePatchThumbResource(); + return painter_.UsesNinePatchThumbResource(); } gfx::Size ScrollbarImpl::NinePatchThumbCanvasSize() const { - return geometry_->ninePatchThumbCanvasSize(scrollbar_.get()); + return geometry_->NinePatchThumbCanvasSize(scrollbar_.get()); } gfx::Rect ScrollbarImpl::NinePatchThumbAperture() const { - return geometry_->ninePatchThumbAperture(scrollbar_.get()); + return geometry_->NinePatchThumbAperture(scrollbar_.get()); } void ScrollbarImpl::PaintPart(cc::PaintCanvas* canvas, cc::ScrollbarPart part, const gfx::Rect& content_rect) { if (part == cc::THUMB) { - painter_.paintThumb(canvas, content_rect); + painter_.PaintThumb(canvas, content_rect); return; } // The following is a simplification of ScrollbarThemeComposite::paint. - painter_.paintScrollbarBackground(canvas, content_rect); + painter_.PaintScrollbarBackground(canvas, content_rect); - if (geometry_->hasButtons(scrollbar_.get())) { + if (geometry_->HasButtons(scrollbar_.get())) { gfx::Rect back_button_start_paint_rect = - geometry_->backButtonStartRect(scrollbar_.get()); - painter_.paintBackButtonStart(canvas, back_button_start_paint_rect); + geometry_->BackButtonStartRect(scrollbar_.get()); + painter_.PaintBackButtonStart(canvas, back_button_start_paint_rect); gfx::Rect back_button_end_paint_rect = - geometry_->backButtonEndRect(scrollbar_.get()); - painter_.paintBackButtonEnd(canvas, back_button_end_paint_rect); + geometry_->BackButtonEndRect(scrollbar_.get()); + painter_.PaintBackButtonEnd(canvas, back_button_end_paint_rect); gfx::Rect forward_button_start_paint_rect = - geometry_->forwardButtonStartRect(scrollbar_.get()); - painter_.paintForwardButtonStart(canvas, forward_button_start_paint_rect); + geometry_->ForwardButtonStartRect(scrollbar_.get()); + painter_.PaintForwardButtonStart(canvas, forward_button_start_paint_rect); gfx::Rect forward_button_end_paint_rect = - geometry_->forwardButtonEndRect(scrollbar_.get()); - painter_.paintForwardButtonEnd(canvas, forward_button_end_paint_rect); + geometry_->ForwardButtonEndRect(scrollbar_.get()); + painter_.PaintForwardButtonEnd(canvas, forward_button_end_paint_rect); } - gfx::Rect track_paint_rect = geometry_->trackRect(scrollbar_.get()); - painter_.paintTrackBackground(canvas, track_paint_rect); + gfx::Rect track_paint_rect = geometry_->TrackRect(scrollbar_.get()); + painter_.PaintTrackBackground(canvas, track_paint_rect); - bool thumb_present = geometry_->hasThumb(scrollbar_.get()); + bool thumb_present = geometry_->HasThumb(scrollbar_.get()); if (thumb_present) { - painter_.paintForwardTrackPart(canvas, track_paint_rect); - painter_.paintBackTrackPart(canvas, track_paint_rect); + painter_.PaintForwardTrackPart(canvas, track_paint_rect); + painter_.PaintBackTrackPart(canvas, track_paint_rect); } - painter_.paintTickmarks(canvas, track_paint_rect); + painter_.PaintTickmarks(canvas, track_paint_rect); } } // namespace cc_blink diff --git a/chromium/cc/blink/web_blend_mode.h b/chromium/cc/blink/web_blend_mode.h index dcd095183a6..b02e7750af5 100644 --- a/chromium/cc/blink/web_blend_mode.h +++ b/chromium/cc/blink/web_blend_mode.h @@ -12,37 +12,37 @@ namespace cc_blink { inline SkBlendMode BlendModeToSkia(blink::WebBlendMode blend_mode) { switch (blend_mode) { - case blink::WebBlendModeNormal: + case blink::kWebBlendModeNormal: return SkBlendMode::kSrcOver; - case blink::WebBlendModeMultiply: + case blink::kWebBlendModeMultiply: return SkBlendMode::kMultiply; - case blink::WebBlendModeScreen: + case blink::kWebBlendModeScreen: return SkBlendMode::kScreen; - case blink::WebBlendModeOverlay: + case blink::kWebBlendModeOverlay: return SkBlendMode::kOverlay; - case blink::WebBlendModeDarken: + case blink::kWebBlendModeDarken: return SkBlendMode::kDarken; - case blink::WebBlendModeLighten: + case blink::kWebBlendModeLighten: return SkBlendMode::kLighten; - case blink::WebBlendModeColorDodge: + case blink::kWebBlendModeColorDodge: return SkBlendMode::kColorDodge; - case blink::WebBlendModeColorBurn: + case blink::kWebBlendModeColorBurn: return SkBlendMode::kColorBurn; - case blink::WebBlendModeHardLight: + case blink::kWebBlendModeHardLight: return SkBlendMode::kHardLight; - case blink::WebBlendModeSoftLight: + case blink::kWebBlendModeSoftLight: return SkBlendMode::kSoftLight; - case blink::WebBlendModeDifference: + case blink::kWebBlendModeDifference: return SkBlendMode::kDifference; - case blink::WebBlendModeExclusion: + case blink::kWebBlendModeExclusion: return SkBlendMode::kExclusion; - case blink::WebBlendModeHue: + case blink::kWebBlendModeHue: return SkBlendMode::kHue; - case blink::WebBlendModeSaturation: + case blink::kWebBlendModeSaturation: return SkBlendMode::kSaturation; - case blink::WebBlendModeColor: + case blink::kWebBlendModeColor: return SkBlendMode::kColor; - case blink::WebBlendModeLuminosity: + case blink::kWebBlendModeLuminosity: return SkBlendMode::kLuminosity; } return SkBlendMode::kSrcOver; @@ -51,37 +51,37 @@ inline SkBlendMode BlendModeToSkia(blink::WebBlendMode blend_mode) { inline blink::WebBlendMode BlendModeFromSkia(SkBlendMode blend_mode) { switch (blend_mode) { case SkBlendMode::kSrcOver: - return blink::WebBlendModeNormal; + return blink::kWebBlendModeNormal; case SkBlendMode::kMultiply: - return blink::WebBlendModeMultiply; + return blink::kWebBlendModeMultiply; case SkBlendMode::kScreen: - return blink::WebBlendModeScreen; + return blink::kWebBlendModeScreen; case SkBlendMode::kOverlay: - return blink::WebBlendModeOverlay; + return blink::kWebBlendModeOverlay; case SkBlendMode::kDarken: - return blink::WebBlendModeDarken; + return blink::kWebBlendModeDarken; case SkBlendMode::kLighten: - return blink::WebBlendModeLighten; + return blink::kWebBlendModeLighten; case SkBlendMode::kColorDodge: - return blink::WebBlendModeColorDodge; + return blink::kWebBlendModeColorDodge; case SkBlendMode::kColorBurn: - return blink::WebBlendModeColorBurn; + return blink::kWebBlendModeColorBurn; case SkBlendMode::kHardLight: - return blink::WebBlendModeHardLight; + return blink::kWebBlendModeHardLight; case SkBlendMode::kSoftLight: - return blink::WebBlendModeSoftLight; + return blink::kWebBlendModeSoftLight; case SkBlendMode::kDifference: - return blink::WebBlendModeDifference; + return blink::kWebBlendModeDifference; case SkBlendMode::kExclusion: - return blink::WebBlendModeExclusion; + return blink::kWebBlendModeExclusion; case SkBlendMode::kHue: - return blink::WebBlendModeHue; + return blink::kWebBlendModeHue; case SkBlendMode::kSaturation: - return blink::WebBlendModeSaturation; + return blink::kWebBlendModeSaturation; case SkBlendMode::kColor: - return blink::WebBlendModeColor; + return blink::kWebBlendModeColor; case SkBlendMode::kLuminosity: - return blink::WebBlendModeLuminosity; + return blink::kWebBlendModeLuminosity; // these value are SkBlendModes, but no blend modes. case SkBlendMode::kClear: @@ -99,7 +99,7 @@ inline blink::WebBlendMode BlendModeFromSkia(SkBlendMode blend_mode) { case SkBlendMode::kModulate: NOTREACHED(); } - return blink::WebBlendModeNormal; + return blink::kWebBlendModeNormal; } } // namespace cc_blink diff --git a/chromium/cc/blink/web_compositor_support_impl.cc b/chromium/cc/blink/web_compositor_support_impl.cc index 7bb783e5716..8ff9a83666a 100644 --- a/chromium/cc/blink/web_compositor_support_impl.cc +++ b/chromium/cc/blink/web_compositor_support_impl.cc @@ -36,51 +36,53 @@ WebCompositorSupportImpl::WebCompositorSupportImpl() { WebCompositorSupportImpl::~WebCompositorSupportImpl() { } -std::unique_ptr<WebLayer> WebCompositorSupportImpl::createLayer() { +std::unique_ptr<WebLayer> WebCompositorSupportImpl::CreateLayer() { return base::MakeUnique<WebLayerImpl>(); } -std::unique_ptr<WebLayer> WebCompositorSupportImpl::createLayerFromCCLayer( +std::unique_ptr<WebLayer> WebCompositorSupportImpl::CreateLayerFromCCLayer( cc::Layer* layer) { return base::MakeUnique<WebLayerImpl>(layer); } -std::unique_ptr<WebContentLayer> WebCompositorSupportImpl::createContentLayer( +std::unique_ptr<WebContentLayer> WebCompositorSupportImpl::CreateContentLayer( WebContentLayerClient* client) { return base::MakeUnique<WebContentLayerImpl>(client); } std::unique_ptr<WebExternalTextureLayer> -WebCompositorSupportImpl::createExternalTextureLayer( +WebCompositorSupportImpl::CreateExternalTextureLayer( cc::TextureLayerClient* client) { return base::MakeUnique<WebExternalTextureLayerImpl>(client); } std::unique_ptr<blink::WebImageLayer> -WebCompositorSupportImpl::createImageLayer() { +WebCompositorSupportImpl::CreateImageLayer() { return base::MakeUnique<WebImageLayerImpl>(); } std::unique_ptr<WebScrollbarLayer> -WebCompositorSupportImpl::createScrollbarLayer( +WebCompositorSupportImpl::CreateScrollbarLayer( std::unique_ptr<WebScrollbar> scrollbar, WebScrollbarThemePainter painter, std::unique_ptr<WebScrollbarThemeGeometry> geometry) { return base::MakeUnique<WebScrollbarLayerImpl>(std::move(scrollbar), painter, - std::move(geometry)); + std::move(geometry), + /* is overlay */ false); } std::unique_ptr<WebScrollbarLayer> -WebCompositorSupportImpl::createOverlayScrollbarLayer( +WebCompositorSupportImpl::CreateOverlayScrollbarLayer( std::unique_ptr<WebScrollbar> scrollbar, WebScrollbarThemePainter painter, std::unique_ptr<WebScrollbarThemeGeometry> geometry) { return base::MakeUnique<WebScrollbarLayerImpl>(std::move(scrollbar), painter, - std::move(geometry), true); + std::move(geometry), + /* is overlay */ true); } std::unique_ptr<WebScrollbarLayer> -WebCompositorSupportImpl::createSolidColorScrollbarLayer( +WebCompositorSupportImpl::CreateSolidColorScrollbarLayer( WebScrollbar::Orientation orientation, int thumb_thickness, int track_start, diff --git a/chromium/cc/blink/web_compositor_support_impl.h b/chromium/cc/blink/web_compositor_support_impl.h index a303b273122..d97a0dc080f 100644 --- a/chromium/cc/blink/web_compositor_support_impl.h +++ b/chromium/cc/blink/web_compositor_support_impl.h @@ -20,22 +20,22 @@ class CC_BLINK_EXPORT WebCompositorSupportImpl WebCompositorSupportImpl(); ~WebCompositorSupportImpl() override; - std::unique_ptr<blink::WebLayer> createLayer() override; - std::unique_ptr<blink::WebLayer> createLayerFromCCLayer(cc::Layer*) override; - std::unique_ptr<blink::WebContentLayer> createContentLayer( + std::unique_ptr<blink::WebLayer> CreateLayer() override; + std::unique_ptr<blink::WebLayer> CreateLayerFromCCLayer(cc::Layer*) override; + std::unique_ptr<blink::WebContentLayer> CreateContentLayer( blink::WebContentLayerClient* client) override; - std::unique_ptr<blink::WebExternalTextureLayer> createExternalTextureLayer( + std::unique_ptr<blink::WebExternalTextureLayer> CreateExternalTextureLayer( cc::TextureLayerClient* client) override; - std::unique_ptr<blink::WebImageLayer> createImageLayer() override; - std::unique_ptr<blink::WebScrollbarLayer> createScrollbarLayer( + std::unique_ptr<blink::WebImageLayer> CreateImageLayer() override; + std::unique_ptr<blink::WebScrollbarLayer> CreateScrollbarLayer( std::unique_ptr<blink::WebScrollbar> scrollbar, blink::WebScrollbarThemePainter painter, std::unique_ptr<blink::WebScrollbarThemeGeometry>) override; - std::unique_ptr<blink::WebScrollbarLayer> createOverlayScrollbarLayer( + std::unique_ptr<blink::WebScrollbarLayer> CreateOverlayScrollbarLayer( std::unique_ptr<blink::WebScrollbar> scrollbar, blink::WebScrollbarThemePainter painter, std::unique_ptr<blink::WebScrollbarThemeGeometry>) override; - std::unique_ptr<blink::WebScrollbarLayer> createSolidColorScrollbarLayer( + std::unique_ptr<blink::WebScrollbarLayer> CreateSolidColorScrollbarLayer( blink::WebScrollbar::Orientation orientation, int thumb_thickness, int track_start, diff --git a/chromium/cc/blink/web_content_layer_impl.cc b/chromium/cc/blink/web_content_layer_impl.cc index 1fc07ddba3f..ff863e62616 100644 --- a/chromium/cc/blink/web_content_layer_impl.cc +++ b/chromium/cc/blink/web_content_layer_impl.cc @@ -27,22 +27,22 @@ PaintingControlToWeb( cc::ContentLayerClient::PaintingControlSetting painting_control) { switch (painting_control) { case cc::ContentLayerClient::PAINTING_BEHAVIOR_NORMAL: - return blink::WebContentLayerClient::PaintDefaultBehavior; + return blink::WebContentLayerClient::kPaintDefaultBehavior; case cc::ContentLayerClient::PAINTING_BEHAVIOR_NORMAL_FOR_TEST: - return blink::WebContentLayerClient::PaintDefaultBehaviorForTest; + return blink::WebContentLayerClient::kPaintDefaultBehaviorForTest; case cc::ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED: - return blink::WebContentLayerClient::DisplayListConstructionDisabled; + return blink::WebContentLayerClient::kDisplayListConstructionDisabled; case cc::ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED: - return blink::WebContentLayerClient::DisplayListCachingDisabled; + return blink::WebContentLayerClient::kDisplayListCachingDisabled; case cc::ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED: - return blink::WebContentLayerClient::DisplayListPaintingDisabled; + return blink::WebContentLayerClient::kDisplayListPaintingDisabled; case cc::ContentLayerClient::SUBSEQUENCE_CACHING_DISABLED: - return blink::WebContentLayerClient::SubsequenceCachingDisabled; + return blink::WebContentLayerClient::kSubsequenceCachingDisabled; case cc::ContentLayerClient::PARTIAL_INVALIDATION: - return blink::WebContentLayerClient::PartialInvalidation; + return blink::WebContentLayerClient::kPartialInvalidation; } NOTREACHED(); - return blink::WebContentLayerClient::PaintDefaultBehavior; + return blink::WebContentLayerClient::kPaintDefaultBehavior; } WebContentLayerImpl::WebContentLayerImpl(blink::WebContentLayerClient* client) @@ -55,12 +55,17 @@ WebContentLayerImpl::~WebContentLayerImpl() { static_cast<PictureLayer*>(layer_->layer())->ClearClient(); } -blink::WebLayer* WebContentLayerImpl::layer() { +blink::WebLayer* WebContentLayerImpl::Layer() { return layer_.get(); } +void WebContentLayerImpl::SetAllowTransformedRasterization(bool allowed) { + static_cast<PictureLayer*>(layer_->layer()) + ->SetAllowTransformedRasterization(allowed); +} + gfx::Rect WebContentLayerImpl::PaintableRegion() { - return client_->paintableRegion(); + return client_->PaintableRegion(); } scoped_refptr<cc::DisplayItemList> @@ -69,7 +74,7 @@ WebContentLayerImpl::PaintContentsToDisplayList( auto display_list = make_scoped_refptr(new cc::DisplayItemList); if (client_) { WebDisplayItemListImpl list(display_list.get()); - client_->paintContents(&list, PaintingControlToWeb(painting_control)); + client_->PaintContents(&list, PaintingControlToWeb(painting_control)); } display_list->Finalize(); return display_list; @@ -80,7 +85,7 @@ bool WebContentLayerImpl::FillsBoundsCompletely() const { } size_t WebContentLayerImpl::GetApproximateUnsharedMemoryUsage() const { - return client_->approximateUnsharedMemoryUsage(); + return client_->ApproximateUnsharedMemoryUsage(); } } // namespace cc_blink diff --git a/chromium/cc/blink/web_content_layer_impl.h b/chromium/cc/blink/web_content_layer_impl.h index 5fb47b3da87..0aa9bfd4a8d 100644 --- a/chromium/cc/blink/web_content_layer_impl.h +++ b/chromium/cc/blink/web_content_layer_impl.h @@ -29,7 +29,8 @@ class WebContentLayerImpl : public blink::WebContentLayer, ~WebContentLayerImpl() override; // WebContentLayer implementation. - blink::WebLayer* layer() override; + blink::WebLayer* Layer() override; + void SetAllowTransformedRasterization(bool) override; protected: // ContentLayerClient implementation. diff --git a/chromium/cc/blink/web_display_item_list_impl.cc b/chromium/cc/blink/web_display_item_list_impl.cc index 8dc3e064775..889566b24ab 100644 --- a/chromium/cc/blink/web_display_item_list_impl.cc +++ b/chromium/cc/blink/web_display_item_list_impl.cc @@ -9,14 +9,14 @@ #include <vector> +#include "cc/paint/clip_display_item.h" +#include "cc/paint/clip_path_display_item.h" +#include "cc/paint/compositing_display_item.h" +#include "cc/paint/drawing_display_item.h" +#include "cc/paint/filter_display_item.h" +#include "cc/paint/float_clip_display_item.h" #include "cc/paint/paint_record.h" -#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/drawing_display_item.h" -#include "cc/playback/filter_display_item.h" -#include "cc/playback/float_clip_display_item.h" -#include "cc/playback/transform_display_item.h" +#include "cc/paint/transform_display_item.h" #include "third_party/WebKit/public/platform/WebFloatRect.h" #include "third_party/WebKit/public/platform/WebRect.h" #include "third_party/skia/include/core/SkColorFilter.h" @@ -39,14 +39,14 @@ WebDisplayItemListImpl::WebDisplayItemListImpl( : display_item_list_(display_list) { } -void WebDisplayItemListImpl::appendDrawingItem( +void WebDisplayItemListImpl::AppendDrawingItem( const blink::WebRect& visual_rect, sk_sp<const cc::PaintRecord> record) { display_item_list_->CreateAndAppendDrawingItem<cc::DrawingDisplayItem>( visual_rect, std::move(record)); } -void WebDisplayItemListImpl::appendClipItem( +void WebDisplayItemListImpl::AppendClipItem( const blink::WebRect& clip_rect, const blink::WebVector<SkRRect>& rounded_clip_rects) { std::vector<SkRRect> rounded_rects; @@ -58,34 +58,33 @@ void WebDisplayItemListImpl::appendClipItem( clip_rect, rounded_rects, antialias); } -void WebDisplayItemListImpl::appendEndClipItem() { +void WebDisplayItemListImpl::AppendEndClipItem() { display_item_list_->CreateAndAppendPairedEndItem<cc::EndClipDisplayItem>(); } -void WebDisplayItemListImpl::appendClipPathItem(const SkPath& clip_path, +void WebDisplayItemListImpl::AppendClipPathItem(const SkPath& clip_path, bool antialias) { display_item_list_->CreateAndAppendPairedBeginItem<cc::ClipPathDisplayItem>( clip_path, antialias); } -void WebDisplayItemListImpl::appendEndClipPathItem() { +void WebDisplayItemListImpl::AppendEndClipPathItem() { display_item_list_ ->CreateAndAppendPairedEndItem<cc::EndClipPathDisplayItem>(); } -void WebDisplayItemListImpl::appendFloatClipItem( +void WebDisplayItemListImpl::AppendFloatClipItem( const blink::WebFloatRect& clip_rect) { display_item_list_->CreateAndAppendPairedBeginItem<cc::FloatClipDisplayItem>( clip_rect); } -void WebDisplayItemListImpl::appendEndFloatClipItem() { +void WebDisplayItemListImpl::AppendEndFloatClipItem() { display_item_list_ ->CreateAndAppendPairedEndItem<cc::EndFloatClipDisplayItem>(); } -void WebDisplayItemListImpl::appendTransformItem( - const SkMatrix44& matrix) { +void WebDisplayItemListImpl::AppendTransformItem(const SkMatrix44& matrix) { gfx::Transform transform(gfx::Transform::kSkipInitialization); transform.matrix() = matrix; @@ -93,12 +92,12 @@ void WebDisplayItemListImpl::appendTransformItem( transform); } -void WebDisplayItemListImpl::appendEndTransformItem() { +void WebDisplayItemListImpl::AppendEndTransformItem() { display_item_list_ ->CreateAndAppendPairedEndItem<cc::EndTransformDisplayItem>(); } -void WebDisplayItemListImpl::appendCompositingItem( +void WebDisplayItemListImpl::AppendCompositingItem( float opacity, SkBlendMode xfermode, SkRect* bounds, @@ -115,12 +114,12 @@ void WebDisplayItemListImpl::appendCompositingItem( bounds, sk_ref_sp(color_filter), kLcdTextRequiresOpaqueLayer); } -void WebDisplayItemListImpl::appendEndCompositingItem() { +void WebDisplayItemListImpl::AppendEndCompositingItem() { display_item_list_ ->CreateAndAppendPairedEndItem<cc::EndCompositingDisplayItem>(); } -void WebDisplayItemListImpl::appendFilterItem( +void WebDisplayItemListImpl::AppendFilterItem( const cc::FilterOperations& filters, const blink::WebFloatRect& filter_bounds, const blink::WebFloatPoint& origin) { @@ -129,25 +128,25 @@ void WebDisplayItemListImpl::appendFilterItem( gfx::ToEnclosingRect(filter_bounds), filters, filter_bounds, origin); } -void WebDisplayItemListImpl::appendEndFilterItem() { +void WebDisplayItemListImpl::AppendEndFilterItem() { display_item_list_->CreateAndAppendPairedEndItem<cc::EndFilterDisplayItem>(); } -void WebDisplayItemListImpl::appendScrollItem( +void WebDisplayItemListImpl::AppendScrollItem( const blink::WebSize& scroll_offset, ScrollContainerId) { SkMatrix44 matrix(SkMatrix44::kUninitialized_Constructor); matrix.setTranslate(-scroll_offset.width, -scroll_offset.height, 0); // TODO(wkorman): http://crbug.com/633636 Should we translate the visual rect // as well? Create a test case and investigate. - appendTransformItem(matrix); + AppendTransformItem(matrix); } -void WebDisplayItemListImpl::appendEndScrollItem() { - appendEndTransformItem(); +void WebDisplayItemListImpl::AppendEndScrollItem() { + AppendEndTransformItem(); } -void WebDisplayItemListImpl::setIsSuitableForGpuRasterization(bool isSuitable) { +void WebDisplayItemListImpl::SetIsSuitableForGpuRasterization(bool isSuitable) { display_item_list_->SetIsSuitableForGpuRasterization(isSuitable); } diff --git a/chromium/cc/blink/web_display_item_list_impl.h b/chromium/cc/blink/web_display_item_list_impl.h index ecccb630c03..b540f1cd563 100644 --- a/chromium/cc/blink/web_display_item_list_impl.h +++ b/chromium/cc/blink/web_display_item_list_impl.h @@ -8,8 +8,8 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "cc/blink/cc_blink_export.h" +#include "cc/paint/display_item_list.h" #include "cc/paint/paint_record.h" -#include "cc/playback/display_item_list.h" #include "third_party/WebKit/public/platform/WebDisplayItemList.h" #include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/skia/include/core/SkBlendMode.h" @@ -40,33 +40,32 @@ class WebDisplayItemListImpl : public blink::WebDisplayItemList { ~WebDisplayItemListImpl() override; // blink::WebDisplayItemList implementation. - void appendDrawingItem(const blink::WebRect& visual_rect, + void AppendDrawingItem(const blink::WebRect& visual_rect, sk_sp<const cc::PaintRecord> record) override; - void appendClipItem( + void AppendClipItem( const blink::WebRect& clip_rect, const blink::WebVector<SkRRect>& rounded_clip_rects) override; - void appendEndClipItem() override; - void appendClipPathItem(const SkPath& clip_path, - bool antialias) override; - void appendEndClipPathItem() override; - void appendFloatClipItem(const blink::WebFloatRect& clip_rect) override; - void appendEndFloatClipItem() override; - void appendTransformItem(const SkMatrix44& matrix) override; - void appendEndTransformItem() override; - void appendCompositingItem(float opacity, + void AppendEndClipItem() override; + void AppendClipPathItem(const SkPath& clip_path, bool antialias) override; + void AppendEndClipPathItem() override; + void AppendFloatClipItem(const blink::WebFloatRect& clip_rect) override; + void AppendEndFloatClipItem() override; + void AppendTransformItem(const SkMatrix44& matrix) override; + void AppendEndTransformItem() override; + void AppendCompositingItem(float opacity, SkBlendMode, SkRect* bounds, SkColorFilter*) override; - void appendEndCompositingItem() override; - void appendFilterItem(const cc::FilterOperations& filters, + void AppendEndCompositingItem() override; + void AppendFilterItem(const cc::FilterOperations& filters, const blink::WebFloatRect& filter_bounds, const blink::WebFloatPoint& origin) override; - void appendEndFilterItem() override; - void appendScrollItem(const blink::WebSize& scrollOffset, + void AppendEndFilterItem() override; + void AppendScrollItem(const blink::WebSize& scrollOffset, ScrollContainerId) override; - void appendEndScrollItem() override; + void AppendEndScrollItem() override; - void setIsSuitableForGpuRasterization(bool isSuitable) override; + void SetIsSuitableForGpuRasterization(bool isSuitable) override; private: scoped_refptr<cc::DisplayItemList> display_item_list_; diff --git a/chromium/cc/blink/web_external_texture_layer_impl.cc b/chromium/cc/blink/web_external_texture_layer_impl.cc index afa81ca7f15..8ced36417f6 100644 --- a/chromium/cc/blink/web_external_texture_layer_impl.cc +++ b/chromium/cc/blink/web_external_texture_layer_impl.cc @@ -22,30 +22,30 @@ WebExternalTextureLayerImpl::~WebExternalTextureLayerImpl() { static_cast<TextureLayer*>(layer_->layer())->ClearClient(); } -blink::WebLayer* WebExternalTextureLayerImpl::layer() { +blink::WebLayer* WebExternalTextureLayerImpl::Layer() { return layer_.get(); } -void WebExternalTextureLayerImpl::clearTexture() { +void WebExternalTextureLayerImpl::ClearTexture() { TextureLayer* layer = static_cast<TextureLayer*>(layer_->layer()); layer->ClearTexture(); } -void WebExternalTextureLayerImpl::setOpaque(bool opaque) { +void WebExternalTextureLayerImpl::SetOpaque(bool opaque) { static_cast<TextureLayer*>(layer_->layer())->SetContentsOpaque(opaque); } -void WebExternalTextureLayerImpl::setPremultipliedAlpha( +void WebExternalTextureLayerImpl::SetPremultipliedAlpha( bool premultiplied_alpha) { static_cast<TextureLayer*>(layer_->layer()) ->SetPremultipliedAlpha(premultiplied_alpha); } -void WebExternalTextureLayerImpl::setBlendBackgroundColor(bool blend) { +void WebExternalTextureLayerImpl::SetBlendBackgroundColor(bool blend) { static_cast<TextureLayer*>(layer_->layer())->SetBlendBackgroundColor(blend); } -void WebExternalTextureLayerImpl::setNearestNeighbor(bool nearest_neighbor) { +void WebExternalTextureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { static_cast<TextureLayer*>(layer_->layer()) ->SetNearestNeighbor(nearest_neighbor); } diff --git a/chromium/cc/blink/web_external_texture_layer_impl.h b/chromium/cc/blink/web_external_texture_layer_impl.h index 1df62cf6243..dd5f3b3f3ef 100644 --- a/chromium/cc/blink/web_external_texture_layer_impl.h +++ b/chromium/cc/blink/web_external_texture_layer_impl.h @@ -24,12 +24,12 @@ class WebExternalTextureLayerImpl : public blink::WebExternalTextureLayer { ~WebExternalTextureLayerImpl() override; // blink::WebExternalTextureLayer implementation. - blink::WebLayer* layer() override; - void clearTexture() override; - void setOpaque(bool opaque) override; - void setPremultipliedAlpha(bool premultiplied) override; - void setBlendBackgroundColor(bool blend) override; - void setNearestNeighbor(bool nearest_neighbor) override; + blink::WebLayer* Layer() override; + void ClearTexture() override; + void SetOpaque(bool opaque) override; + void SetPremultipliedAlpha(bool premultiplied) override; + void SetBlendBackgroundColor(bool blend) override; + void SetNearestNeighbor(bool nearest_neighbor) override; private: std::unique_ptr<WebLayerImpl> layer_; diff --git a/chromium/cc/blink/web_image_layer_impl.cc b/chromium/cc/blink/web_image_layer_impl.cc index 32f753053b4..f9ab77718d8 100644 --- a/chromium/cc/blink/web_image_layer_impl.cc +++ b/chromium/cc/blink/web_image_layer_impl.cc @@ -18,18 +18,18 @@ WebImageLayerImpl::WebImageLayerImpl() { WebImageLayerImpl::~WebImageLayerImpl() { } -blink::WebLayer* WebImageLayerImpl::layer() { +blink::WebLayer* WebImageLayerImpl::Layer() { return layer_.get(); } -void WebImageLayerImpl::setImage(const SkImage* image) { +void WebImageLayerImpl::SetImage(const SkImage* image) { static_cast<cc::PictureImageLayer*>(layer_->layer()) ->SetImage(sk_ref_sp(image)); static_cast<WebLayerImplFixedBounds*>(layer_.get()) ->SetFixedBounds(gfx::Size(image->width(), image->height())); } -void WebImageLayerImpl::setNearestNeighbor(bool nearest_neighbor) { +void WebImageLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { static_cast<cc::PictureImageLayer*>(layer_->layer()) ->SetNearestNeighbor(nearest_neighbor); } diff --git a/chromium/cc/blink/web_image_layer_impl.h b/chromium/cc/blink/web_image_layer_impl.h index 84433bd626d..a6c3452e410 100644 --- a/chromium/cc/blink/web_image_layer_impl.h +++ b/chromium/cc/blink/web_image_layer_impl.h @@ -21,9 +21,9 @@ class WebImageLayerImpl : public blink::WebImageLayer { ~WebImageLayerImpl() override; // blink::WebImageLayer implementation. - blink::WebLayer* layer() override; - void setImage(const SkImage* image) override; - void setNearestNeighbor(bool nearest_neighbor) override; + blink::WebLayer* Layer() override; + void SetImage(const SkImage* image) override; + void SetNearestNeighbor(bool nearest_neighbor) override; private: std::unique_ptr<WebLayerImpl> layer_; diff --git a/chromium/cc/blink/web_layer_impl.cc b/chromium/cc/blink/web_layer_impl.cc index 43d7caa7f20..e44d007e6ea 100644 --- a/chromium/cc/blink/web_layer_impl.cc +++ b/chromium/cc/blink/web_layer_impl.cc @@ -52,205 +52,205 @@ WebLayerImpl::~WebLayerImpl() { layer_->SetLayerClient(nullptr); } -int WebLayerImpl::id() const { +int WebLayerImpl::Id() const { return layer_->id(); } DISABLE_CFI_PERF -void WebLayerImpl::invalidateRect(const blink::WebRect& rect) { +void WebLayerImpl::InvalidateRect(const blink::WebRect& rect) { layer_->SetNeedsDisplayRect(rect); } -void WebLayerImpl::invalidate() { +void WebLayerImpl::Invalidate() { layer_->SetNeedsDisplay(); } -void WebLayerImpl::addChild(WebLayer* child) { +void WebLayerImpl::AddChild(WebLayer* child) { layer_->AddChild(static_cast<WebLayerImpl*>(child)->layer()); } -void WebLayerImpl::insertChild(WebLayer* child, size_t index) { +void WebLayerImpl::InsertChild(WebLayer* child, size_t index) { layer_->InsertChild(static_cast<WebLayerImpl*>(child)->layer(), index); } -void WebLayerImpl::replaceChild(WebLayer* reference, WebLayer* new_layer) { +void WebLayerImpl::ReplaceChild(WebLayer* reference, WebLayer* new_layer) { layer_->ReplaceChild(static_cast<WebLayerImpl*>(reference)->layer(), static_cast<WebLayerImpl*>(new_layer)->layer()); } -void WebLayerImpl::removeFromParent() { +void WebLayerImpl::RemoveFromParent() { layer_->RemoveFromParent(); } -void WebLayerImpl::removeAllChildren() { +void WebLayerImpl::RemoveAllChildren() { layer_->RemoveAllChildren(); } -void WebLayerImpl::setBounds(const WebSize& size) { +void WebLayerImpl::SetBounds(const WebSize& size) { layer_->SetBounds(size); } -WebSize WebLayerImpl::bounds() const { +WebSize WebLayerImpl::Bounds() const { return layer_->bounds(); } -void WebLayerImpl::setMasksToBounds(bool masks_to_bounds) { +void WebLayerImpl::SetMasksToBounds(bool masks_to_bounds) { layer_->SetMasksToBounds(masks_to_bounds); } -bool WebLayerImpl::masksToBounds() const { +bool WebLayerImpl::MasksToBounds() const { return layer_->masks_to_bounds(); } -void WebLayerImpl::setMaskLayer(WebLayer* maskLayer) { +void WebLayerImpl::SetMaskLayer(WebLayer* maskLayer) { layer_->SetMaskLayer( maskLayer ? static_cast<WebLayerImpl*>(maskLayer)->layer() : 0); } -void WebLayerImpl::setOpacity(float opacity) { +void WebLayerImpl::SetOpacity(float opacity) { layer_->SetOpacity(opacity); } -float WebLayerImpl::opacity() const { +float WebLayerImpl::Opacity() const { return layer_->opacity(); } -void WebLayerImpl::setBlendMode(blink::WebBlendMode blend_mode) { +void WebLayerImpl::SetBlendMode(blink::WebBlendMode blend_mode) { layer_->SetBlendMode(BlendModeToSkia(blend_mode)); } -blink::WebBlendMode WebLayerImpl::blendMode() const { +blink::WebBlendMode WebLayerImpl::BlendMode() const { return BlendModeFromSkia(layer_->blend_mode()); } -void WebLayerImpl::setIsRootForIsolatedGroup(bool isolate) { +void WebLayerImpl::SetIsRootForIsolatedGroup(bool isolate) { layer_->SetIsRootForIsolatedGroup(isolate); } -bool WebLayerImpl::isRootForIsolatedGroup() { +bool WebLayerImpl::IsRootForIsolatedGroup() { return layer_->is_root_for_isolated_group(); } -void WebLayerImpl::setOpaque(bool opaque) { +void WebLayerImpl::SetOpaque(bool opaque) { if (contents_opaque_is_fixed_) return; layer_->SetContentsOpaque(opaque); } -bool WebLayerImpl::opaque() const { +bool WebLayerImpl::Opaque() const { return layer_->contents_opaque(); } -void WebLayerImpl::setPosition(const WebFloatPoint& position) { +void WebLayerImpl::SetPosition(const WebFloatPoint& position) { layer_->SetPosition(position); } -WebFloatPoint WebLayerImpl::position() const { +WebFloatPoint WebLayerImpl::GetPosition() const { return layer_->position(); } -void WebLayerImpl::setTransform(const SkMatrix44& matrix) { +void WebLayerImpl::SetTransform(const SkMatrix44& matrix) { gfx::Transform transform; transform.matrix() = matrix; layer_->SetTransform(transform); } -void WebLayerImpl::setTransformOrigin(const blink::WebFloatPoint3D& point) { +void WebLayerImpl::SetTransformOrigin(const blink::WebFloatPoint3D& point) { gfx::Point3F gfx_point = point; layer_->SetTransformOrigin(gfx_point); } -blink::WebFloatPoint3D WebLayerImpl::transformOrigin() const { +blink::WebFloatPoint3D WebLayerImpl::TransformOrigin() const { return layer_->transform_origin(); } -SkMatrix44 WebLayerImpl::transform() const { +SkMatrix44 WebLayerImpl::Transform() const { return layer_->transform().matrix(); } -void WebLayerImpl::setDrawsContent(bool draws_content) { +void WebLayerImpl::SetDrawsContent(bool draws_content) { layer_->SetIsDrawable(draws_content); } -bool WebLayerImpl::drawsContent() const { +bool WebLayerImpl::DrawsContent() const { return layer_->DrawsContent(); } -void WebLayerImpl::setDoubleSided(bool double_sided) { +void WebLayerImpl::SetDoubleSided(bool double_sided) { layer_->SetDoubleSided(double_sided); } -void WebLayerImpl::setShouldFlattenTransform(bool flatten) { +void WebLayerImpl::SetShouldFlattenTransform(bool flatten) { layer_->SetShouldFlattenTransform(flatten); } -void WebLayerImpl::setRenderingContext(int context) { +void WebLayerImpl::SetRenderingContext(int context) { layer_->Set3dSortingContextId(context); } -void WebLayerImpl::setUseParentBackfaceVisibility( +void WebLayerImpl::SetUseParentBackfaceVisibility( bool use_parent_backface_visibility) { layer_->SetUseParentBackfaceVisibility(use_parent_backface_visibility); } -void WebLayerImpl::setBackgroundColor(WebColor color) { +void WebLayerImpl::SetBackgroundColor(WebColor color) { layer_->SetBackgroundColor(color); } -WebColor WebLayerImpl::backgroundColor() const { +WebColor WebLayerImpl::BackgroundColor() const { return layer_->background_color(); } -void WebLayerImpl::setFilters(const cc::FilterOperations& filters) { +void WebLayerImpl::SetFilters(const cc::FilterOperations& filters) { layer_->SetFilters(filters); } -void WebLayerImpl::setFiltersOrigin(const blink::WebFloatPoint& origin) { +void WebLayerImpl::SetFiltersOrigin(const blink::WebFloatPoint& origin) { layer_->SetFiltersOrigin(origin); } -void WebLayerImpl::setBackgroundFilters(const cc::FilterOperations& filters) { +void WebLayerImpl::SetBackgroundFilters(const cc::FilterOperations& filters) { layer_->SetBackgroundFilters(filters); } -bool WebLayerImpl::hasTickingAnimationForTesting() { +bool WebLayerImpl::HasTickingAnimationForTesting() { return layer_->HasTickingAnimationForTesting(); } -void WebLayerImpl::setScrollPosition(blink::WebFloatPoint position) { +void WebLayerImpl::SetScrollPosition(blink::WebFloatPoint position) { layer_->SetScrollOffset(gfx::ScrollOffset(position.x, position.y)); } -blink::WebFloatPoint WebLayerImpl::scrollPosition() const { +blink::WebFloatPoint WebLayerImpl::ScrollPosition() const { return blink::WebFloatPoint(layer_->scroll_offset().x(), layer_->scroll_offset().y()); } -void WebLayerImpl::setScrollClipLayer(WebLayer* clip_layer) { +void WebLayerImpl::SetScrollClipLayer(WebLayer* clip_layer) { if (!clip_layer) { layer_->SetScrollClipLayerId(Layer::INVALID_ID); return; } - layer_->SetScrollClipLayerId(clip_layer->id()); + layer_->SetScrollClipLayerId(clip_layer->Id()); } -bool WebLayerImpl::scrollable() const { +bool WebLayerImpl::Scrollable() const { return layer_->scrollable(); } -void WebLayerImpl::setUserScrollable(bool horizontal, bool vertical) { +void WebLayerImpl::SetUserScrollable(bool horizontal, bool vertical) { layer_->SetUserScrollable(horizontal, vertical); } -bool WebLayerImpl::userScrollableHorizontal() const { +bool WebLayerImpl::UserScrollableHorizontal() const { return layer_->user_scrollable_horizontal(); } -bool WebLayerImpl::userScrollableVertical() const { +bool WebLayerImpl::UserScrollableVertical() const { return layer_->user_scrollable_vertical(); } -void WebLayerImpl::addMainThreadScrollingReasons( +void WebLayerImpl::AddMainThreadScrollingReasons( uint32_t main_thread_scrolling_reasons) { // WebLayerImpl should only know about non-transient scrolling // reasons. Transient scrolling reasons are computed per hit test. @@ -260,28 +260,28 @@ void WebLayerImpl::addMainThreadScrollingReasons( layer_->AddMainThreadScrollingReasons(main_thread_scrolling_reasons); } -void WebLayerImpl::clearMainThreadScrollingReasons( +void WebLayerImpl::ClearMainThreadScrollingReasons( uint32_t main_thread_scrolling_reasons_to_clear) { layer_->ClearMainThreadScrollingReasons( main_thread_scrolling_reasons_to_clear); } -uint32_t WebLayerImpl::mainThreadScrollingReasons() { +uint32_t WebLayerImpl::MainThreadScrollingReasons() { return layer_->main_thread_scrolling_reasons(); } -bool WebLayerImpl::shouldScrollOnMainThread() const { +bool WebLayerImpl::ShouldScrollOnMainThread() const { return layer_->should_scroll_on_main_thread(); } -void WebLayerImpl::setNonFastScrollableRegion(const WebVector<WebRect>& rects) { +void WebLayerImpl::SetNonFastScrollableRegion(const WebVector<WebRect>& rects) { cc::Region region; for (size_t i = 0; i < rects.size(); ++i) region.Union(rects[i]); layer_->SetNonFastScrollableRegion(region); } -WebVector<WebRect> WebLayerImpl::nonFastScrollableRegion() const { +WebVector<WebRect> WebLayerImpl::NonFastScrollableRegion() const { size_t num_rects = 0; for (cc::Region::Iterator region_rects(layer_->non_fast_scrollable_region()); region_rects.has_rect(); @@ -299,14 +299,14 @@ WebVector<WebRect> WebLayerImpl::nonFastScrollableRegion() const { return result; } -void WebLayerImpl::setTouchEventHandlerRegion(const WebVector<WebRect>& rects) { +void WebLayerImpl::SetTouchEventHandlerRegion(const WebVector<WebRect>& rects) { cc::Region region; for (size_t i = 0; i < rects.size(); ++i) region.Union(rects[i]); layer_->SetTouchEventHandlerRegion(region); } -WebVector<WebRect> WebLayerImpl::touchEventHandlerRegion() const { +WebVector<WebRect> WebLayerImpl::TouchEventHandlerRegion() const { size_t num_rects = 0; for (cc::Region::Iterator region_rects(layer_->touch_event_handler_region()); region_rects.has_rect(); @@ -324,38 +324,39 @@ WebVector<WebRect> WebLayerImpl::touchEventHandlerRegion() const { return result; } -void WebLayerImpl::setIsContainerForFixedPositionLayers(bool enable) { +void WebLayerImpl::SetIsContainerForFixedPositionLayers(bool enable) { layer_->SetIsContainerForFixedPositionLayers(enable); } -bool WebLayerImpl::isContainerForFixedPositionLayers() const { +bool WebLayerImpl::IsContainerForFixedPositionLayers() const { return layer_->IsContainerForFixedPositionLayers(); } static blink::WebLayerPositionConstraint ToWebLayerPositionConstraint( const cc::LayerPositionConstraint& constraint) { blink::WebLayerPositionConstraint web_constraint; - web_constraint.isFixedPosition = constraint.is_fixed_position(); - web_constraint.isFixedToRightEdge = constraint.is_fixed_to_right_edge(); - web_constraint.isFixedToBottomEdge = constraint.is_fixed_to_bottom_edge(); + web_constraint.is_fixed_position = constraint.is_fixed_position(); + web_constraint.is_fixed_to_right_edge = constraint.is_fixed_to_right_edge(); + web_constraint.is_fixed_to_bottom_edge = constraint.is_fixed_to_bottom_edge(); return web_constraint; } static cc::LayerPositionConstraint ToLayerPositionConstraint( const blink::WebLayerPositionConstraint& web_constraint) { cc::LayerPositionConstraint constraint; - constraint.set_is_fixed_position(web_constraint.isFixedPosition); - constraint.set_is_fixed_to_right_edge(web_constraint.isFixedToRightEdge); - constraint.set_is_fixed_to_bottom_edge(web_constraint.isFixedToBottomEdge); + constraint.set_is_fixed_position(web_constraint.is_fixed_position); + constraint.set_is_fixed_to_right_edge(web_constraint.is_fixed_to_right_edge); + constraint.set_is_fixed_to_bottom_edge( + web_constraint.is_fixed_to_bottom_edge); return constraint; } -void WebLayerImpl::setPositionConstraint( +void WebLayerImpl::SetPositionConstraint( const blink::WebLayerPositionConstraint& constraint) { layer_->SetPositionConstraint(ToLayerPositionConstraint(constraint)); } -blink::WebLayerPositionConstraint WebLayerImpl::positionConstraint() const { +blink::WebLayerPositionConstraint WebLayerImpl::PositionConstraint() const { return ToWebLayerPositionConstraint(layer_->position_constraint()); } @@ -363,57 +364,65 @@ static blink::WebLayerStickyPositionConstraint ToWebLayerStickyPositionConstraint( const cc::LayerStickyPositionConstraint& constraint) { blink::WebLayerStickyPositionConstraint web_constraint; - web_constraint.isSticky = constraint.is_sticky; - web_constraint.isAnchoredLeft = constraint.is_anchored_left; - web_constraint.isAnchoredRight = constraint.is_anchored_right; - web_constraint.isAnchoredTop = constraint.is_anchored_top; - web_constraint.isAnchoredBottom = constraint.is_anchored_bottom; - web_constraint.leftOffset = constraint.left_offset; - web_constraint.rightOffset = constraint.right_offset; - web_constraint.topOffset = constraint.top_offset; - web_constraint.bottomOffset = constraint.bottom_offset; - web_constraint.parentRelativeStickyBoxOffset = + web_constraint.is_sticky = constraint.is_sticky; + web_constraint.is_anchored_left = constraint.is_anchored_left; + web_constraint.is_anchored_right = constraint.is_anchored_right; + web_constraint.is_anchored_top = constraint.is_anchored_top; + web_constraint.is_anchored_bottom = constraint.is_anchored_bottom; + web_constraint.left_offset = constraint.left_offset; + web_constraint.right_offset = constraint.right_offset; + web_constraint.top_offset = constraint.top_offset; + web_constraint.bottom_offset = constraint.bottom_offset; + web_constraint.parent_relative_sticky_box_offset = constraint.parent_relative_sticky_box_offset; - web_constraint.scrollContainerRelativeStickyBoxRect = + web_constraint.scroll_container_relative_sticky_box_rect = constraint.scroll_container_relative_sticky_box_rect; - web_constraint.scrollContainerRelativeContainingBlockRect = + web_constraint.scroll_container_relative_containing_block_rect = constraint.scroll_container_relative_containing_block_rect; + web_constraint.nearest_layer_shifting_sticky_box = + constraint.nearest_layer_shifting_sticky_box; + web_constraint.nearest_layer_shifting_containing_block = + constraint.nearest_layer_shifting_containing_block; return web_constraint; } static cc::LayerStickyPositionConstraint ToStickyPositionConstraint( const blink::WebLayerStickyPositionConstraint& web_constraint) { cc::LayerStickyPositionConstraint constraint; - constraint.is_sticky = web_constraint.isSticky; - constraint.is_anchored_left = web_constraint.isAnchoredLeft; - constraint.is_anchored_right = web_constraint.isAnchoredRight; - constraint.is_anchored_top = web_constraint.isAnchoredTop; - constraint.is_anchored_bottom = web_constraint.isAnchoredBottom; - constraint.left_offset = web_constraint.leftOffset; - constraint.right_offset = web_constraint.rightOffset; - constraint.top_offset = web_constraint.topOffset; - constraint.bottom_offset = web_constraint.bottomOffset; + constraint.is_sticky = web_constraint.is_sticky; + constraint.is_anchored_left = web_constraint.is_anchored_left; + constraint.is_anchored_right = web_constraint.is_anchored_right; + constraint.is_anchored_top = web_constraint.is_anchored_top; + constraint.is_anchored_bottom = web_constraint.is_anchored_bottom; + constraint.left_offset = web_constraint.left_offset; + constraint.right_offset = web_constraint.right_offset; + constraint.top_offset = web_constraint.top_offset; + constraint.bottom_offset = web_constraint.bottom_offset; constraint.parent_relative_sticky_box_offset = - web_constraint.parentRelativeStickyBoxOffset; + web_constraint.parent_relative_sticky_box_offset; constraint.scroll_container_relative_sticky_box_rect = - web_constraint.scrollContainerRelativeStickyBoxRect; + web_constraint.scroll_container_relative_sticky_box_rect; constraint.scroll_container_relative_containing_block_rect = - web_constraint.scrollContainerRelativeContainingBlockRect; + web_constraint.scroll_container_relative_containing_block_rect; + constraint.nearest_layer_shifting_sticky_box = + web_constraint.nearest_layer_shifting_sticky_box; + constraint.nearest_layer_shifting_containing_block = + web_constraint.nearest_layer_shifting_containing_block; return constraint; } -void WebLayerImpl::setStickyPositionConstraint( +void WebLayerImpl::SetStickyPositionConstraint( const blink::WebLayerStickyPositionConstraint& constraint) { layer_->SetStickyPositionConstraint(ToStickyPositionConstraint(constraint)); } -blink::WebLayerStickyPositionConstraint WebLayerImpl::stickyPositionConstraint() +blink::WebLayerStickyPositionConstraint WebLayerImpl::StickyPositionConstraint() const { return ToWebLayerStickyPositionConstraint( layer_->sticky_position_constraint()); } -void WebLayerImpl::setScrollClient(blink::WebLayerScrollClient* scroll_client) { +void WebLayerImpl::SetScrollClient(blink::WebLayerScrollClient* scroll_client) { if (scroll_client) { layer_->set_did_scroll_callback( - base::Bind(&blink::WebLayerScrollClient::didScroll, + base::Bind(&blink::WebLayerScrollClient::DidScroll, base::Unretained(scroll_client))); } else { layer_->set_did_scroll_callback( @@ -421,42 +430,42 @@ void WebLayerImpl::setScrollClient(blink::WebLayerScrollClient* scroll_client) { } } -void WebLayerImpl::setLayerClient(cc::LayerClient* client) { +void WebLayerImpl::SetLayerClient(cc::LayerClient* client) { layer_->SetLayerClient(client); } -const cc::Layer* WebLayerImpl::ccLayer() const { +const cc::Layer* WebLayerImpl::CcLayer() const { return layer_.get(); } -cc::Layer* WebLayerImpl::ccLayer() { +cc::Layer* WebLayerImpl::CcLayer() { return layer_.get(); } -void WebLayerImpl::setElementId(const cc::ElementId& id) { +void WebLayerImpl::SetElementId(const cc::ElementId& id) { layer_->SetElementId(id); } -cc::ElementId WebLayerImpl::elementId() const { +cc::ElementId WebLayerImpl::GetElementId() const { return layer_->element_id(); } -void WebLayerImpl::setCompositorMutableProperties(uint32_t properties) { +void WebLayerImpl::SetCompositorMutableProperties(uint32_t properties) { layer_->SetMutableProperties(properties); } -uint32_t WebLayerImpl::compositorMutableProperties() const { +uint32_t WebLayerImpl::CompositorMutableProperties() const { return layer_->mutable_properties(); } -void WebLayerImpl::setScrollParent(blink::WebLayer* parent) { +void WebLayerImpl::SetScrollParent(blink::WebLayer* parent) { cc::Layer* scroll_parent = nullptr; if (parent) scroll_parent = static_cast<WebLayerImpl*>(parent)->layer(); layer_->SetScrollParent(scroll_parent); } -void WebLayerImpl::setClipParent(blink::WebLayer* parent) { +void WebLayerImpl::SetClipParent(blink::WebLayer* parent) { cc::Layer* clip_parent = nullptr; if (parent) clip_parent = static_cast<WebLayerImpl*>(parent)->layer(); @@ -471,16 +480,12 @@ void WebLayerImpl::SetContentsOpaqueIsFixed(bool fixed) { contents_opaque_is_fixed_ = fixed; } -void WebLayerImpl::setHasWillChangeTransformHint(bool has_will_change) { +void WebLayerImpl::SetHasWillChangeTransformHint(bool has_will_change) { layer_->SetHasWillChangeTransformHint(has_will_change); } -void WebLayerImpl::setPreferredRasterBounds(const WebSize& bounds) { - layer_->SetPreferredRasterBounds(bounds); -} - -void WebLayerImpl::clearPreferredRasterBounds() { - layer_->ClearPreferredRasterBounds(); +void WebLayerImpl::ShowScrollbars() { + layer_->ShowScrollbars(); } } // namespace cc_blink diff --git a/chromium/cc/blink/web_layer_impl.h b/chromium/cc/blink/web_layer_impl.h index 2401f1ac888..573bd2ff393 100644 --- a/chromium/cc/blink/web_layer_impl.h +++ b/chromium/cc/blink/web_layer_impl.h @@ -49,88 +49,87 @@ class CC_BLINK_EXPORT WebLayerImpl : public NON_EXPORTED_BASE(blink::WebLayer) { void SetContentsOpaqueIsFixed(bool fixed); // WebLayer implementation. - int id() const override; - void invalidateRect(const blink::WebRect&) override; - void invalidate() override; - void addChild(blink::WebLayer* child) override; - void insertChild(blink::WebLayer* child, size_t index) override; - void replaceChild(blink::WebLayer* reference, + int Id() const override; + void InvalidateRect(const blink::WebRect&) override; + void Invalidate() override; + void AddChild(blink::WebLayer* child) override; + void InsertChild(blink::WebLayer* child, size_t index) override; + void ReplaceChild(blink::WebLayer* reference, blink::WebLayer* new_layer) override; - void removeFromParent() override; - void removeAllChildren() override; - void setBounds(const blink::WebSize& bounds) override; - blink::WebSize bounds() const override; - void setMasksToBounds(bool masks_to_bounds) override; - bool masksToBounds() const override; - void setMaskLayer(blink::WebLayer* mask) override; - void setOpacity(float opacity) override; - float opacity() const override; - void setBlendMode(blink::WebBlendMode blend_mode) override; - blink::WebBlendMode blendMode() const override; - void setIsRootForIsolatedGroup(bool root) override; - bool isRootForIsolatedGroup() override; - void setOpaque(bool opaque) override; - bool opaque() const override; - void setPosition(const blink::WebFloatPoint& position) override; - blink::WebFloatPoint position() const override; - void setTransform(const SkMatrix44& transform) override; - void setTransformOrigin(const blink::WebFloatPoint3D& point) override; - blink::WebFloatPoint3D transformOrigin() const override; - SkMatrix44 transform() const override; - void setDrawsContent(bool draws_content) override; - bool drawsContent() const override; - void setDoubleSided(bool double_sided) override; - void setShouldFlattenTransform(bool flatten) override; - void setRenderingContext(int context) override; - void setUseParentBackfaceVisibility(bool visible) override; - void setBackgroundColor(blink::WebColor color) override; - blink::WebColor backgroundColor() const override; - void setFilters(const cc::FilterOperations& filters) override; - void setFiltersOrigin(const blink::WebFloatPoint& origin) override; - void setBackgroundFilters(const cc::FilterOperations& filters) override; - bool hasTickingAnimationForTesting() override; - void setScrollPosition(blink::WebFloatPoint position) override; - blink::WebFloatPoint scrollPosition() const override; - void setScrollClipLayer(blink::WebLayer* clip_layer) override; - bool scrollable() const override; - void setUserScrollable(bool horizontal, bool vertical) override; - bool userScrollableHorizontal() const override; - bool userScrollableVertical() const override; - void addMainThreadScrollingReasons( + void RemoveFromParent() override; + void RemoveAllChildren() override; + void SetBounds(const blink::WebSize& bounds) override; + blink::WebSize Bounds() const override; + void SetMasksToBounds(bool masks_to_bounds) override; + bool MasksToBounds() const override; + void SetMaskLayer(blink::WebLayer* mask) override; + void SetOpacity(float opacity) override; + float Opacity() const override; + void SetBlendMode(blink::WebBlendMode blend_mode) override; + blink::WebBlendMode BlendMode() const override; + void SetIsRootForIsolatedGroup(bool root) override; + bool IsRootForIsolatedGroup() override; + void SetOpaque(bool opaque) override; + bool Opaque() const override; + void SetPosition(const blink::WebFloatPoint& position) override; + blink::WebFloatPoint GetPosition() const override; + void SetTransform(const SkMatrix44& transform) override; + void SetTransformOrigin(const blink::WebFloatPoint3D& point) override; + blink::WebFloatPoint3D TransformOrigin() const override; + SkMatrix44 Transform() const override; + void SetDrawsContent(bool draws_content) override; + bool DrawsContent() const override; + void SetDoubleSided(bool double_sided) override; + void SetShouldFlattenTransform(bool flatten) override; + void SetRenderingContext(int context) override; + void SetUseParentBackfaceVisibility(bool visible) override; + void SetBackgroundColor(blink::WebColor color) override; + blink::WebColor BackgroundColor() const override; + void SetFilters(const cc::FilterOperations& filters) override; + void SetFiltersOrigin(const blink::WebFloatPoint& origin) override; + void SetBackgroundFilters(const cc::FilterOperations& filters) override; + bool HasTickingAnimationForTesting() override; + void SetScrollPosition(blink::WebFloatPoint position) override; + blink::WebFloatPoint ScrollPosition() const override; + void SetScrollClipLayer(blink::WebLayer* clip_layer) override; + bool Scrollable() const override; + void SetUserScrollable(bool horizontal, bool vertical) override; + bool UserScrollableHorizontal() const override; + bool UserScrollableVertical() const override; + void AddMainThreadScrollingReasons( uint32_t main_thread_scrolling_reasons) override; - void clearMainThreadScrollingReasons( + void ClearMainThreadScrollingReasons( uint32_t main_thread_scrolling_reasons_to_clear) override; - uint32_t mainThreadScrollingReasons() override; - bool shouldScrollOnMainThread() const override; - void setNonFastScrollableRegion( + uint32_t MainThreadScrollingReasons() override; + bool ShouldScrollOnMainThread() const override; + void SetNonFastScrollableRegion( const blink::WebVector<blink::WebRect>& region) override; - blink::WebVector<blink::WebRect> nonFastScrollableRegion() const override; - void setTouchEventHandlerRegion( + blink::WebVector<blink::WebRect> NonFastScrollableRegion() const override; + void SetTouchEventHandlerRegion( const blink::WebVector<blink::WebRect>& region) override; - blink::WebVector<blink::WebRect> touchEventHandlerRegion() const override; - void setIsContainerForFixedPositionLayers(bool is_container) override; - bool isContainerForFixedPositionLayers() const override; - void setPositionConstraint( + blink::WebVector<blink::WebRect> TouchEventHandlerRegion() const override; + void SetIsContainerForFixedPositionLayers(bool is_container) override; + bool IsContainerForFixedPositionLayers() const override; + void SetPositionConstraint( const blink::WebLayerPositionConstraint& constraint) override; - blink::WebLayerPositionConstraint positionConstraint() const override; - void setStickyPositionConstraint( + blink::WebLayerPositionConstraint PositionConstraint() const override; + void SetStickyPositionConstraint( const blink::WebLayerStickyPositionConstraint& constraint) override; - blink::WebLayerStickyPositionConstraint stickyPositionConstraint() + blink::WebLayerStickyPositionConstraint StickyPositionConstraint() const override; - void setScrollClient(blink::WebLayerScrollClient* client) override; - void setLayerClient(cc::LayerClient* client) override; - const cc::Layer* ccLayer() const override; - cc::Layer* ccLayer() override; - void setElementId(const cc::ElementId&) override; - cc::ElementId elementId() const override; - void setCompositorMutableProperties(uint32_t properties) override; - uint32_t compositorMutableProperties() const override; - void setHasWillChangeTransformHint(bool has_will_change) override; - void setPreferredRasterBounds(const blink::WebSize&) override; - void clearPreferredRasterBounds() override; - - void setScrollParent(blink::WebLayer* parent) override; - void setClipParent(blink::WebLayer* parent) override; + void SetScrollClient(blink::WebLayerScrollClient* client) override; + void SetLayerClient(cc::LayerClient* client) override; + const cc::Layer* CcLayer() const override; + cc::Layer* CcLayer() override; + void SetElementId(const cc::ElementId&) override; + cc::ElementId GetElementId() const override; + void SetCompositorMutableProperties(uint32_t properties) override; + uint32_t CompositorMutableProperties() const override; + void SetHasWillChangeTransformHint(bool has_will_change) override; + void ShowScrollbars() override; + + void SetScrollParent(blink::WebLayer* parent) override; + void SetClipParent(blink::WebLayer* parent) override; protected: scoped_refptr<cc::Layer> layer_; diff --git a/chromium/cc/blink/web_layer_impl_fixed_bounds.cc b/chromium/cc/blink/web_layer_impl_fixed_bounds.cc index ed4ba18d7ff..46bfbcbc7ba 100644 --- a/chromium/cc/blink/web_layer_impl_fixed_bounds.cc +++ b/chromium/cc/blink/web_layer_impl_fixed_bounds.cc @@ -23,38 +23,38 @@ WebLayerImplFixedBounds::WebLayerImplFixedBounds(scoped_refptr<Layer> layer) WebLayerImplFixedBounds::~WebLayerImplFixedBounds() { } -void WebLayerImplFixedBounds::invalidateRect(const blink::WebRect& rect) { +void WebLayerImplFixedBounds::InvalidateRect(const blink::WebRect& rect) { // Partial invalidations seldom occur for such layers. // Simply invalidate the whole layer to avoid transformation of coordinates. - invalidate(); + Invalidate(); } -void WebLayerImplFixedBounds::setTransformOrigin( +void WebLayerImplFixedBounds::SetTransformOrigin( const blink::WebFloatPoint3D& transform_origin) { - if (transform_origin != this->transformOrigin()) { + if (transform_origin != this->TransformOrigin()) { layer_->SetTransformOrigin(transform_origin); UpdateLayerBoundsAndTransform(); } } -void WebLayerImplFixedBounds::setBounds(const blink::WebSize& bounds) { +void WebLayerImplFixedBounds::SetBounds(const blink::WebSize& bounds) { if (original_bounds_ != gfx::Size(bounds)) { original_bounds_ = bounds; UpdateLayerBoundsAndTransform(); } } -blink::WebSize WebLayerImplFixedBounds::bounds() const { +blink::WebSize WebLayerImplFixedBounds::Bounds() const { return original_bounds_; } -void WebLayerImplFixedBounds::setTransform(const SkMatrix44& matrix) { +void WebLayerImplFixedBounds::SetTransform(const SkMatrix44& matrix) { gfx::Transform transform; transform.matrix() = matrix; SetTransformInternal(transform); } -SkMatrix44 WebLayerImplFixedBounds::transform() const { +SkMatrix44 WebLayerImplFixedBounds::Transform() const { return original_transform_.matrix(); } @@ -78,8 +78,7 @@ void WebLayerImplFixedBounds::UpdateLayerBoundsAndTransform() { fixed_bounds_ == original_bounds_ || // For now fall back to non-fixed bounds for non-zero transform origin. // TODO(wangxianzhu): Support non-zero anchor point for fixed bounds. - transformOrigin().x || - transformOrigin().y) { + TransformOrigin().x || TransformOrigin().y) { layer_->SetBounds(original_bounds_); layer_->SetTransform(original_transform_); return; diff --git a/chromium/cc/blink/web_layer_impl_fixed_bounds.h b/chromium/cc/blink/web_layer_impl_fixed_bounds.h index 628dfdf295b..949e47d5434 100644 --- a/chromium/cc/blink/web_layer_impl_fixed_bounds.h +++ b/chromium/cc/blink/web_layer_impl_fixed_bounds.h @@ -24,13 +24,13 @@ class CC_BLINK_EXPORT WebLayerImplFixedBounds : public WebLayerImpl { ~WebLayerImplFixedBounds() override; // WebLayerImpl overrides. - void invalidateRect(const blink::WebRect& rect) override; - void setTransformOrigin( + void InvalidateRect(const blink::WebRect& rect) override; + void SetTransformOrigin( const blink::WebFloatPoint3D& transform_origin) override; - void setBounds(const blink::WebSize& bounds) override; - blink::WebSize bounds() const override; - void setTransform(const SkMatrix44& transform) override; - SkMatrix44 transform() const override; + void SetBounds(const blink::WebSize& bounds) override; + blink::WebSize Bounds() const override; + void SetTransform(const SkMatrix44& transform) override; + SkMatrix44 Transform() const override; void SetFixedBounds(gfx::Size bounds); 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 cb4e20ac4e4..3dd88c1baa0 100644 --- a/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc +++ b/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc @@ -25,8 +25,8 @@ namespace { TEST(WebLayerImplFixedBoundsTest, IdentityBounds) { WebLayerImplFixedBounds layer; layer.SetFixedBounds(gfx::Size(100, 100)); - layer.setBounds(WebSize(100, 100)); - EXPECT_EQ(WebSize(100, 100), layer.bounds()); + layer.SetBounds(WebSize(100, 100)); + EXPECT_EQ(WebSize(100, 100), layer.Bounds()); EXPECT_EQ(gfx::Size(100, 100), layer.layer()->bounds()); EXPECT_EQ(gfx::Transform(), layer.layer()->transform()); } @@ -41,12 +41,12 @@ gfx::Point3F TransformPoint(const gfx::Transform& transform, void CheckBoundsScaleSimple(WebLayerImplFixedBounds* layer, const WebSize& bounds, const gfx::Size& fixed_bounds) { - layer->setBounds(bounds); + layer->SetBounds(bounds); layer->SetFixedBounds(fixed_bounds); - EXPECT_EQ(bounds, layer->bounds()); + EXPECT_EQ(bounds, layer->Bounds()); EXPECT_EQ(fixed_bounds, layer->layer()->bounds()); - EXPECT_TRUE(layer->transform().isIdentity()); + EXPECT_TRUE(layer->Transform().isIdentity()); // An arbitrary point to check the scale and transforms. gfx::Point3F original_point(10, 20, 1); @@ -70,10 +70,10 @@ TEST(WebLayerImplFixedBoundsTest, BoundsScaleSimple) { void ExpectEqualLayerRectsInTarget(cc::Layer* layer1, cc::Layer* layer2) { gfx::RectF layer1_rect_in_target(gfx::SizeF(layer1->bounds())); - layer1->screen_space_transform().TransformRect(&layer1_rect_in_target); + layer1->ScreenSpaceTransform().TransformRect(&layer1_rect_in_target); gfx::RectF layer2_rect_in_target(gfx::SizeF(layer2->bounds())); - layer2->screen_space_transform().TransformRect(&layer2_rect_in_target); + layer2->ScreenSpaceTransform().TransformRect(&layer2_rect_in_target); EXPECT_FLOAT_RECT_EQ(layer1_rect_in_target, layer2_rect_in_target); } @@ -91,18 +91,18 @@ void CompareFixedBoundsLayerAndNormalLayer(const WebFloatPoint& anchor_point, WebLayerImplFixedBounds root_layer; WebLayerImplFixedBounds fixed_bounds_layer(cc::PictureImageLayer::Create()); - fixed_bounds_layer.setBounds(bounds); + 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); + fixed_bounds_layer.SetTransform(transform.matrix()); + fixed_bounds_layer.SetPosition(position); + root_layer.AddChild(&fixed_bounds_layer); WebLayerImpl normal_layer(cc::PictureImageLayer::Create()); - normal_layer.setBounds(bounds); - normal_layer.setTransform(transform.matrix()); - normal_layer.setPosition(position); - root_layer.addChild(&normal_layer); + normal_layer.SetBounds(bounds); + normal_layer.SetTransform(transform.matrix()); + normal_layer.SetPosition(position); + root_layer.AddChild(&normal_layer); auto animation_host = cc::AnimationHost::CreateForTesting(cc::ThreadInstance::MAIN); diff --git a/chromium/cc/blink/web_scrollbar_layer_impl.cc b/chromium/cc/blink/web_scrollbar_layer_impl.cc index b6a759c5147..2a3f2a12f17 100644 --- a/chromium/cc/blink/web_scrollbar_layer_impl.cc +++ b/chromium/cc/blink/web_scrollbar_layer_impl.cc @@ -23,8 +23,8 @@ namespace { cc::ScrollbarOrientation ConvertOrientation( blink::WebScrollbar::Orientation orientation) { - return orientation == blink::WebScrollbar::Horizontal ? cc::HORIZONTAL - : cc::VERTICAL; + return orientation == blink::WebScrollbar::kHorizontal ? cc::HORIZONTAL + : cc::VERTICAL; } } // namespace @@ -34,23 +34,19 @@ namespace cc_blink { WebScrollbarLayerImpl::WebScrollbarLayerImpl( std::unique_ptr<blink::WebScrollbar> scrollbar, blink::WebScrollbarThemePainter painter, - std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry) - : layer_(new WebLayerImpl(PaintedScrollbarLayer::Create( - base::MakeUnique<ScrollbarImpl>(std::move(scrollbar), - painter, - std::move(geometry)), - 0))) {} - -WebScrollbarLayerImpl::WebScrollbarLayerImpl( - std::unique_ptr<blink::WebScrollbar> scrollbar, - blink::WebScrollbarThemePainter painter, std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry, - bool) - : layer_(new WebLayerImpl(PaintedOverlayScrollbarLayer::Create( - base::MakeUnique<ScrollbarImpl>(std::move(scrollbar), - painter, - std::move(geometry)), - 0))) {} + bool is_overlay) + : layer_(is_overlay + ? new WebLayerImpl(PaintedOverlayScrollbarLayer::Create( + base::MakeUnique<ScrollbarImpl>(std::move(scrollbar), + painter, + std::move(geometry)), + cc::Layer::INVALID_ID)) + : new WebLayerImpl(PaintedScrollbarLayer::Create( + base::MakeUnique<ScrollbarImpl>(std::move(scrollbar), + painter, + std::move(geometry)), + cc::Layer::INVALID_ID))) {} WebScrollbarLayerImpl::WebScrollbarLayerImpl( blink::WebScrollbar::Orientation orientation, @@ -62,16 +58,16 @@ WebScrollbarLayerImpl::WebScrollbarLayerImpl( thumb_thickness, track_start, is_left_side_vertical_scrollbar, - 0))) {} + cc::Layer::INVALID_ID))) {} WebScrollbarLayerImpl::~WebScrollbarLayerImpl() { } -blink::WebLayer* WebScrollbarLayerImpl::layer() { +blink::WebLayer* WebScrollbarLayerImpl::Layer() { return layer_.get(); } -void WebScrollbarLayerImpl::setScrollLayer(blink::WebLayer* layer) { +void WebScrollbarLayerImpl::SetScrollLayer(blink::WebLayer* layer) { cc::Layer* scroll_layer = layer ? static_cast<WebLayerImpl*>(layer)->layer() : 0; layer_->layer()->ToScrollbarLayer()->SetScrollLayer( diff --git a/chromium/cc/blink/web_scrollbar_layer_impl.h b/chromium/cc/blink/web_scrollbar_layer_impl.h index ad203e9a956..952277635c0 100644 --- a/chromium/cc/blink/web_scrollbar_layer_impl.h +++ b/chromium/cc/blink/web_scrollbar_layer_impl.h @@ -26,12 +26,8 @@ class WebScrollbarLayerImpl : public blink::WebScrollbarLayer { CC_BLINK_EXPORT WebScrollbarLayerImpl( std::unique_ptr<blink::WebScrollbar> scrollbar, blink::WebScrollbarThemePainter painter, - std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry); - CC_BLINK_EXPORT WebScrollbarLayerImpl( - std::unique_ptr<blink::WebScrollbar> scrollbar, - blink::WebScrollbarThemePainter painter, std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry, - bool temp); + bool is_overlay); CC_BLINK_EXPORT WebScrollbarLayerImpl( blink::WebScrollbar::Orientation orientation, int thumb_thickness, @@ -40,8 +36,8 @@ class WebScrollbarLayerImpl : public blink::WebScrollbarLayer { ~WebScrollbarLayerImpl() override; // blink::WebScrollbarLayer implementation. - blink::WebLayer* layer() override; - void setScrollLayer(blink::WebLayer* layer) override; + blink::WebLayer* Layer() override; + void SetScrollLayer(blink::WebLayer* layer) override; private: std::unique_ptr<WebLayerImpl> layer_; diff --git a/chromium/cc/base/cc_export.h b/chromium/cc/cc_export.h index fe0e0e369c7..87e3c9b4f05 100644 --- a/chromium/cc/base/cc_export.h +++ b/chromium/cc/cc_export.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_BASE_CC_EXPORT_H_ -#define CC_BASE_CC_EXPORT_H_ +#ifndef CC_CC_EXPORT_H_ +#define CC_CC_EXPORT_H_ #if defined(COMPONENT_BUILD) #if defined(WIN32) @@ -26,4 +26,4 @@ #define CC_EXPORT #endif -#endif // CC_BASE_CC_EXPORT_H_ +#endif // CC_CC_EXPORT_H_ diff --git a/chromium/cc/debug/BUILD.gn b/chromium/cc/debug/BUILD.gn new file mode 100644 index 00000000000..b1de28c8e1b --- /dev/null +++ b/chromium/cc/debug/BUILD.gn @@ -0,0 +1,30 @@ +# Copyright 2017 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. + +import("//cc/cc.gni") +cc_component("debug") { + output_name = "cc_debug" + sources = [ + "debug_colors.cc", + "debug_colors.h", + "debug_export.h", + "layer_tree_debug_state.cc", + "layer_tree_debug_state.h", + "picture_debug_util.cc", + "picture_debug_util.h", + "rendering_stats.cc", + "rendering_stats.h", + "rendering_stats_instrumentation.cc", + "rendering_stats_instrumentation.h", + "traced_value.cc", + "traced_value.h", + ] + deps = [ + "//base", + "//skia", + "//ui/gfx/codec", + ] + + defines = [ "CC_DEBUG_IMPLEMENTATION=1" ] +} diff --git a/chromium/cc/debug/OWNERS b/chromium/cc/debug/OWNERS deleted file mode 100644 index 0206f945099..00000000000 --- a/chromium/cc/debug/OWNERS +++ /dev/null @@ -1,7 +0,0 @@ -# Changes to this file may break telemetry benchmarks -per-file benchmark_instrumentation.h=set noparent -per-file benchmark_instrumentation.h=vmpstr@chromium.org -per-file benchmark_instrumentation.h=nduca@chromium.org -per-file benchmark_instrumentation.cc=set noparent -per-file benchmark_instrumentation.cc=vmpstr@chromium.org -per-file benchmark_instrumentation.cc=nduca@chromium.org diff --git a/chromium/cc/debug/debug_colors.cc b/chromium/cc/debug/debug_colors.cc index 1590c0477ba..db0fbd70287 100644 --- a/chromium/cc/debug/debug_colors.cc +++ b/chromium/cc/debug/debug_colors.cc @@ -2,16 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/logging.h" #include "base/macros.h" #include "cc/debug/debug_colors.h" -#include "cc/trees/layer_tree_impl.h" - namespace cc { -static float Scale(float width, const LayerTreeImpl* tree_impl) { - return width * (tree_impl ? tree_impl->device_scale_factor() : 1); +static float Scale(float width, float device_scale_factor) { + return width * device_scale_factor; } // ======= Layer border colors ======= @@ -20,56 +19,56 @@ static float Scale(float width, const LayerTreeImpl* tree_impl) { SkColor DebugColors::TiledContentLayerBorderColor() { return SkColorSetARGB(128, 255, 128, 0); } -int DebugColors::TiledContentLayerBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::TiledContentLayerBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // Image layers are olive. SkColor DebugColors::ImageLayerBorderColor() { return SkColorSetARGB(128, 128, 128, 0); } -int DebugColors::ImageLayerBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::ImageLayerBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // Non-tiled content layers area green. SkColor DebugColors::ContentLayerBorderColor() { return SkColorSetARGB(128, 0, 128, 32); } -int DebugColors::ContentLayerBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::ContentLayerBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // Masking layers are pale blue and wide. SkColor DebugColors::MaskingLayerBorderColor() { return SkColorSetARGB(48, 128, 255, 255); } -int DebugColors::MaskingLayerBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(20, tree_impl); +int DebugColors::MaskingLayerBorderWidth(float device_scale_factor) { + return Scale(20, device_scale_factor); } // Other container layers are yellow. SkColor DebugColors::ContainerLayerBorderColor() { return SkColorSetARGB(192, 255, 255, 0); } -int DebugColors::ContainerLayerBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::ContainerLayerBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // Surface layers are a blue-ish green. SkColor DebugColors::SurfaceLayerBorderColor() { return SkColorSetARGB(128, 0, 255, 136); } -int DebugColors::SurfaceLayerBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::SurfaceLayerBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // Render surfaces are blue. SkColor DebugColors::SurfaceBorderColor() { return SkColorSetARGB(100, 0, 0, 255); } -int DebugColors::SurfaceBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::SurfaceBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // ======= Tile colors ======= @@ -78,64 +77,64 @@ int DebugColors::SurfaceBorderWidth(const LayerTreeImpl* tree_impl) { SkColor DebugColors::HighResTileBorderColor() { return SkColorSetARGB(100, 80, 200, 200); } -int DebugColors::HighResTileBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(1, tree_impl); +int DebugColors::HighResTileBorderWidth(float device_scale_factor) { + return Scale(1, device_scale_factor); } // Low-res tile borders are purple. SkColor DebugColors::LowResTileBorderColor() { return SkColorSetARGB(100, 212, 83, 192); } -int DebugColors::LowResTileBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::LowResTileBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // Other high-resolution tile borders are yellow. SkColor DebugColors::ExtraHighResTileBorderColor() { return SkColorSetARGB(100, 239, 231, 20); } -int DebugColors::ExtraHighResTileBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::ExtraHighResTileBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // Other low-resolution tile borders are green. SkColor DebugColors::ExtraLowResTileBorderColor() { return SkColorSetARGB(100, 93, 186, 18); } -int DebugColors::ExtraLowResTileBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::ExtraLowResTileBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // Missing tile borders are dark grey. SkColor DebugColors::MissingTileBorderColor() { return SkColorSetARGB(64, 64, 64, 0); } -int DebugColors::MissingTileBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(1, tree_impl); +int DebugColors::MissingTileBorderWidth(float device_scale_factor) { + return Scale(1, device_scale_factor); } // Solid color tile borders are grey. SkColor DebugColors::SolidColorTileBorderColor() { return SkColorSetARGB(128, 128, 128, 128); } -int DebugColors::SolidColorTileBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(1, tree_impl); +int DebugColors::SolidColorTileBorderWidth(float device_scale_factor) { + return Scale(1, device_scale_factor); } // OOM tile borders are red. SkColor DebugColors::OOMTileBorderColor() { return SkColorSetARGB(100, 255, 0, 0); } -int DebugColors::OOMTileBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(1, tree_impl); +int DebugColors::OOMTileBorderWidth(float device_scale_factor) { + return Scale(1, device_scale_factor); } // Direct picture borders are chartreuse. SkColor DebugColors::DirectPictureBorderColor() { return SkColorSetARGB(255, 127, 255, 0); } -int DebugColors::DirectPictureBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(1, tree_impl); +int DebugColors::DirectPictureBorderWidth(float device_scale_factor) { + return Scale(1, device_scale_factor); } // Borders added to GL composited draw quads. This is useful to debug HW @@ -155,8 +154,8 @@ int DebugColors::GLCompositedTextureQuadBoderWidth() { SkColor DebugColors::CompressedTileBorderColor() { return SkColorSetARGB(100, 20, 20, 240); } -int DebugColors::CompressedTileBorderWidth(const LayerTreeImpl* tree_impl) { - return Scale(2, tree_impl); +int DebugColors::CompressedTileBorderWidth(float device_scale_factor) { + return Scale(2, device_scale_factor); } // ======= Checkerboard colors ======= diff --git a/chromium/cc/debug/debug_colors.h b/chromium/cc/debug/debug_colors.h index 154766fdafa..cdb62dc9b74 100644 --- a/chromium/cc/debug/debug_colors.h +++ b/chromium/cc/debug/debug_colors.h @@ -6,61 +6,60 @@ #define CC_DEBUG_DEBUG_COLORS_H_ #include "base/macros.h" +#include "cc/debug/debug_export.h" #include "third_party/skia/include/core/SkColor.h" namespace cc { -class LayerTreeImpl; - -class DebugColors { +class CC_DEBUG_EXPORT DebugColors { public: static SkColor TiledContentLayerBorderColor(); - static int TiledContentLayerBorderWidth(const LayerTreeImpl* tree_impl); + static int TiledContentLayerBorderWidth(float device_scale_factor); static SkColor ImageLayerBorderColor(); - static int ImageLayerBorderWidth(const LayerTreeImpl* tree_impl); + static int ImageLayerBorderWidth(float device_scale_factor); static SkColor ContentLayerBorderColor(); - static int ContentLayerBorderWidth(const LayerTreeImpl* tree_impl); + static int ContentLayerBorderWidth(float device_scale_factor); static SkColor MaskingLayerBorderColor(); - static int MaskingLayerBorderWidth(const LayerTreeImpl* tree_impl); + static int MaskingLayerBorderWidth(float device_scale_factor); static SkColor ContainerLayerBorderColor(); - static int ContainerLayerBorderWidth(const LayerTreeImpl* tree_impl); + static int ContainerLayerBorderWidth(float device_scale_factor); static SkColor SurfaceLayerBorderColor(); - static int SurfaceLayerBorderWidth(const LayerTreeImpl* tree_impl); + static int SurfaceLayerBorderWidth(float device_scale_factor); static SkColor SurfaceBorderColor(); - static int SurfaceBorderWidth(const LayerTreeImpl* tree_impl); + static int SurfaceBorderWidth(float device_scale_factor); static SkColor HighResTileBorderColor(); - static int HighResTileBorderWidth(const LayerTreeImpl* tree_impl); + static int HighResTileBorderWidth(float device_scale_factor); static SkColor LowResTileBorderColor(); - static int LowResTileBorderWidth(const LayerTreeImpl* tree_impl); + static int LowResTileBorderWidth(float device_scale_factor); static SkColor ExtraHighResTileBorderColor(); - static int ExtraHighResTileBorderWidth(const LayerTreeImpl* tree_impl); + static int ExtraHighResTileBorderWidth(float device_scale_factor); static SkColor ExtraLowResTileBorderColor(); - static int ExtraLowResTileBorderWidth(const LayerTreeImpl* tree_impl); + static int ExtraLowResTileBorderWidth(float device_scale_factor); static SkColor MissingTileBorderColor(); - static int MissingTileBorderWidth(const LayerTreeImpl* tree_impl); + static int MissingTileBorderWidth(float device_scale_factor); static SkColor SolidColorTileBorderColor(); - static int SolidColorTileBorderWidth(const LayerTreeImpl* tree_impl); + static int SolidColorTileBorderWidth(float device_scale_factor); static SkColor OOMTileBorderColor(); - static int OOMTileBorderWidth(const LayerTreeImpl* tree_impl); + static int OOMTileBorderWidth(float device_scale_factor); static SkColor DirectPictureBorderColor(); - static int DirectPictureBorderWidth(const LayerTreeImpl* tree_impl); + static int DirectPictureBorderWidth(float device_scale_factor); static SkColor CompressedTileBorderColor(); - static int CompressedTileBorderWidth(const LayerTreeImpl* tree_impl); + static int CompressedTileBorderWidth(float device_scale_factor); static SkColor DefaultCheckerboardColor(); static SkColor EvictedTileCheckerboardColor(); diff --git a/chromium/cc/debug/debug_export.h b/chromium/cc/debug/debug_export.h new file mode 100644 index 00000000000..67d446d255f --- /dev/null +++ b/chromium/cc/debug/debug_export.h @@ -0,0 +1,29 @@ +// Copyright 2017 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_DEBUG_EXPORT_H_ +#define CC_DEBUG_DEBUG_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(CC_DEBUG_IMPLEMENTATION) +#define CC_DEBUG_EXPORT __declspec(dllexport) +#else +#define CC_DEBUG_EXPORT __declspec(dllimport) +#endif // defined(CC_DEBUG_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(CC_DEBUG_IMPLEMENTATION) +#define CC_DEBUG_EXPORT __attribute__((visibility("default"))) +#else +#define CC_DEBUG_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define CC_DEBUG_EXPORT +#endif + +#endif // CC_DEBUG_DEBUG_EXPORT_H_ diff --git a/chromium/cc/debug/layer_tree_debug_state.h b/chromium/cc/debug/layer_tree_debug_state.h index 09ac66de5c8..2ea5f9c3aa9 100644 --- a/chromium/cc/debug/layer_tree_debug_state.h +++ b/chromium/cc/debug/layer_tree_debug_state.h @@ -5,7 +5,9 @@ #ifndef CC_DEBUG_LAYER_TREE_DEBUG_STATE_H_ #define CC_DEBUG_LAYER_TREE_DEBUG_STATE_H_ -#include "cc/base/cc_export.h" +#include <bitset> + +#include "cc/debug/debug_export.h" namespace cc { @@ -13,14 +15,22 @@ namespace proto { class LayerTreeDebugState; } // namespace proto -class CC_EXPORT LayerTreeDebugState { +enum DebugBorderType { + RENDERPASS = 0, + SURFACE, + LAYER, + LAST_DEBUG_BORDER_TYPE = LAYER +}; +using DebugBorderTypes = std::bitset<LAST_DEBUG_BORDER_TYPE + 1>; + +class CC_DEBUG_EXPORT LayerTreeDebugState { public: LayerTreeDebugState(); LayerTreeDebugState(const LayerTreeDebugState& other); ~LayerTreeDebugState(); bool show_fps_counter; - bool show_debug_borders; + DebugBorderTypes show_debug_borders; bool show_paint_rects; bool show_property_changed_rects; diff --git a/chromium/cc/debug/picture_debug_util.h b/chromium/cc/debug/picture_debug_util.h index 1719ea27632..3c149c22b8a 100644 --- a/chromium/cc/debug/picture_debug_util.h +++ b/chromium/cc/debug/picture_debug_util.h @@ -7,11 +7,13 @@ #include <string> +#include "cc/debug/debug_export.h" + class SkPicture; namespace cc { -class PictureDebugUtil { +class CC_DEBUG_EXPORT PictureDebugUtil { public: static void SerializeAsBase64(const SkPicture* picture, std::string* output); }; diff --git a/chromium/cc/debug/rendering_stats.h b/chromium/cc/debug/rendering_stats.h index 2585639f5c4..dfbc9264c57 100644 --- a/chromium/cc/debug/rendering_stats.h +++ b/chromium/cc/debug/rendering_stats.h @@ -13,14 +13,14 @@ #include "base/time/time.h" #include "base/trace_event/trace_event_argument.h" #include "base/values.h" -#include "cc/base/cc_export.h" +#include "cc/debug/debug_export.h" #include "cc/debug/traced_value.h" namespace cc { -struct CC_EXPORT RenderingStats { +struct CC_DEBUG_EXPORT RenderingStats { // Stores a sequence of TimeDelta objects. - class CC_EXPORT TimeDeltaList { + class CC_DEBUG_EXPORT TimeDeltaList { public: TimeDeltaList(); TimeDeltaList(const TimeDeltaList& other); diff --git a/chromium/cc/debug/rendering_stats_instrumentation.h b/chromium/cc/debug/rendering_stats_instrumentation.h index 9a588affcc3..35a07e8ad37 100644 --- a/chromium/cc/debug/rendering_stats_instrumentation.h +++ b/chromium/cc/debug/rendering_stats_instrumentation.h @@ -17,7 +17,7 @@ namespace cc { // RenderingStatsInstrumentation is shared among threads and manages conditional // recording of rendering stats into a private RenderingStats instance. -class CC_EXPORT RenderingStatsInstrumentation { +class CC_DEBUG_EXPORT RenderingStatsInstrumentation { public: static std::unique_ptr<RenderingStatsInstrumentation> Create(); virtual ~RenderingStatsInstrumentation(); diff --git a/chromium/cc/debug/traced_display_item_list.cc b/chromium/cc/debug/traced_display_item_list.cc deleted file mode 100644 index b02446e9cd4..00000000000 --- a/chromium/cc/debug/traced_display_item_list.cc +++ /dev/null @@ -1,27 +0,0 @@ -// 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 { - std::unique_ptr<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 deleted file mode 100644 index 50733485e6f..00000000000 --- a/chromium/cc/debug/traced_display_item_list.h +++ /dev/null @@ -1,44 +0,0 @@ -// 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 <memory> -#include <string> - -#include "base/macros.h" -#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 std::unique_ptr<ConvertableToTraceFormat> AsTraceableDisplayItemList( - scoped_refptr<const DisplayItemList> list, - bool include_items) { - return std::unique_ptr<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_value.h b/chromium/cc/debug/traced_value.h index 34e79a7a062..c5c4b0cef3c 100644 --- a/chromium/cc/debug/traced_value.h +++ b/chromium/cc/debug/traced_value.h @@ -5,6 +5,8 @@ #ifndef CC_DEBUG_TRACED_VALUE_H_ #define CC_DEBUG_TRACED_VALUE_H_ +#include "cc/debug/debug_export.h" + namespace base { namespace trace_event { class TracedValue; @@ -13,7 +15,7 @@ class TracedValue; namespace cc { -class TracedValue { +class CC_DEBUG_EXPORT TracedValue { public: static void AppendIDRef(const void* id, base::trace_event::TracedValue* array); diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h index 7e6124c0a07..6ffdcce5737 100644 --- a/chromium/cc/input/input_handler.h +++ b/chromium/cc/input/input_handler.h @@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/event_listener_properties.h" #include "cc/input/main_thread_scrolling_reason.h" #include "cc/input/scroll_state.h" @@ -113,7 +113,8 @@ class CC_EXPORT InputHandler { // Binds a client to this handler to receive notifications. Only one client // can be bound to an InputHandler. The client must live at least until the // handler calls WillShutdown() on the client. - virtual void BindToClient(InputHandlerClient* client) = 0; + virtual void BindToClient(InputHandlerClient* client, + bool wheel_scroll_latching_enabled) = 0; // Selects a layer to be scrolled using the |scroll_state| start position. // Returns SCROLL_STARTED if the layer at the coordinates can be scrolled, @@ -216,6 +217,8 @@ class CC_EXPORT InputHandler { gfx::ScrollOffset* offset) = 0; virtual bool ScrollLayerTo(int layer_id, const gfx::ScrollOffset& offset) = 0; + virtual bool ScrollingShouldSwitchtoMainThread() = 0; + protected: InputHandler() {} virtual ~InputHandler() {} diff --git a/chromium/cc/input/layer_selection_bound.h b/chromium/cc/input/layer_selection_bound.h index be40a562a7a..abadc3c39e4 100644 --- a/chromium/cc/input/layer_selection_bound.h +++ b/chromium/cc/input/layer_selection_bound.h @@ -5,7 +5,7 @@ #ifndef CC_INPUT_LAYER_SELECTION_BOUND_H_ #define CC_INPUT_LAYER_SELECTION_BOUND_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/selection.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/selection_bound.h" diff --git a/chromium/cc/input/main_thread_scrolling_reason.h b/chromium/cc/input/main_thread_scrolling_reason.h index a2a02222ad4..a8c586eee95 100644 --- a/chromium/cc/input/main_thread_scrolling_reason.h +++ b/chromium/cc/input/main_thread_scrolling_reason.h @@ -7,6 +7,7 @@ #include <string> +#include "base/stl_util.h" #include "base/trace_event/trace_event_argument.h" namespace cc { @@ -36,12 +37,14 @@ struct MainThreadScrollingReason { // These *AndLCDText reasons are due to subpixel text rendering which can // only be applied by blending glyphs with the background at a specific // screen position; transparency and transforms break this. + kNonCompositedReasonsFirst = 16, kHasOpacityAndLCDText = 1 << 16, kHasTransformAndLCDText = 1 << 17, kBackgroundNotOpaqueInRectAndLCDText = 1 << 18, kHasBorderRadius = 1 << 19, kHasClipRelatedProperty = 1 << 20, kHasBoxShadowFromNonRootLayer = 1 << 21, + kNonCompositedReasonsLast = 21, // Transient scrolling reasons. These are computed for each scroll begin. kNonFastScrollableRegion = 1 << 5, @@ -59,6 +62,11 @@ struct MainThreadScrollingReason { kMainThreadScrollingReasonCount = 22, }; + static const uint32_t kNonCompositedReasons = + kHasOpacityAndLCDText | kHasTransformAndLCDText | + kBackgroundNotOpaqueInRectAndLCDText | kHasBorderRadius | + kHasClipRelatedProperty | kHasBoxShadowFromNonRootLayer; + // Returns true if the given MainThreadScrollingReason can be set by the main // thread. static bool MainThreadCanSetScrollReasons(uint32_t reasons) { @@ -66,10 +74,7 @@ struct MainThreadScrollingReason { kNotScrollingOnMain | kHasBackgroundAttachmentFixedObjects | kHasNonLayerViewportConstrainedObjects | kThreadedScrollingDisabled | kScrollbarScrolling | kPageOverlay | kHandlingScrollFromMainThread | - kCustomScrollbarScrolling | kHasOpacityAndLCDText | - kHasTransformAndLCDText | kBackgroundNotOpaqueInRectAndLCDText | - kHasBorderRadius | kHasClipRelatedProperty | - kHasBoxShadowFromNonRootLayer; + kCustomScrollbarScrolling; return (reasons & reasons_set_by_main_thread) == reasons; } @@ -83,6 +88,12 @@ struct MainThreadScrollingReason { return (reasons & reasons_set_by_compositor) == reasons; } + // Returns true if there are any reasons that prevented the scroller + // from being composited. + static bool HasNonCompositedScrollReasons(uint32_t reasons) { + return (reasons & kNonCompositedReasons) != 0; + } + static std::string mainThreadScrollingReasonsAsText(uint32_t reasons) { base::trace_event::TracedValue tracedValue; mainThreadScrollingReasonsAsTracedValue(reasons, &tracedValue); @@ -90,7 +101,7 @@ struct MainThreadScrollingReason { // Remove '{main_thread_scrolling_reasons:[', ']}', and any '"' chars. std::string result = result_in_array_foramt.substr(34, result_in_array_foramt.length() - 36); - result.erase(std::remove(result.begin(), result.end(), '\"'), result.end()); + base::Erase(result, '\"'); return result; } @@ -147,20 +158,6 @@ struct MainThreadScrollingReason { tracedValue->AppendString("Page-based scrolling"); tracedValue->EndArray(); } - - // For a given reason, return its index in enum - static int getReasonIndex(uint32_t reason) { - // Multiple reasons provided - if (reason & (reason - 1)) - return -1; - - int index = -1; - while (reason > 0) { - reason = reason >> 1; - ++index; - } - return index; - } }; } // namespace cc diff --git a/chromium/cc/input/page_scale_animation.h b/chromium/cc/input/page_scale_animation.h index b58f50b315c..9d66923e76b 100644 --- a/chromium/cc/input/page_scale_animation.h +++ b/chromium/cc/input/page_scale_animation.h @@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/cubic_bezier.h" #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/geometry/vector2d.h" diff --git a/chromium/cc/input/scroll_elasticity_helper.h b/chromium/cc/input/scroll_elasticity_helper.h index 3ad28fb2cbd..0952bd02e52 100644 --- a/chromium/cc/input/scroll_elasticity_helper.h +++ b/chromium/cc/input/scroll_elasticity_helper.h @@ -6,7 +6,7 @@ #define CC_INPUT_SCROLL_ELASTICITY_HELPER_H_ #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/vector2d_f.h" diff --git a/chromium/cc/input/scroll_state.h b/chromium/cc/input/scroll_state.h index 384a934fc22..74823e4ba85 100644 --- a/chromium/cc/input/scroll_state.h +++ b/chromium/cc/input/scroll_state.h @@ -8,7 +8,7 @@ #include <list> #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/scroll_state_data.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/vector2d.h" diff --git a/chromium/cc/input/scroll_state_data.h b/chromium/cc/input/scroll_state_data.h index 90339649f5f..f3559a89d07 100644 --- a/chromium/cc/input/scroll_state_data.h +++ b/chromium/cc/input/scroll_state_data.h @@ -9,7 +9,7 @@ #include <list> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/trees/property_tree.h" namespace cc { diff --git a/chromium/cc/input/scrollbar.h b/chromium/cc/input/scrollbar.h index d159dba7b17..e0302bffcb6 100644 --- a/chromium/cc/input/scrollbar.h +++ b/chromium/cc/input/scrollbar.h @@ -5,7 +5,7 @@ #ifndef CC_INPUT_SCROLLBAR_H_ #define CC_INPUT_SCROLLBAR_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/paint/paint_canvas.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" diff --git a/chromium/cc/input/scrollbar_animation_controller.cc b/chromium/cc/input/scrollbar_animation_controller.cc index e30d8eb493a..8fb3c25a48b 100644 --- a/chromium/cc/input/scrollbar_animation_controller.cc +++ b/chromium/cc/input/scrollbar_animation_controller.cc @@ -15,44 +15,45 @@ std::unique_ptr<ScrollbarAnimationController> ScrollbarAnimationController::CreateScrollbarAnimationControllerAndroid( int scroll_layer_id, ScrollbarAnimationControllerClient* client, - base::TimeDelta fade_out_delay, + base::TimeDelta fade_delay, base::TimeDelta fade_out_resize_delay, - base::TimeDelta fade_out_duration) { - return base::WrapUnique(new ScrollbarAnimationController( - scroll_layer_id, client, fade_out_delay, fade_out_resize_delay, - fade_out_duration)); + base::TimeDelta fade_duration) { + return base::WrapUnique( + new ScrollbarAnimationController(scroll_layer_id, client, fade_delay, + fade_out_resize_delay, fade_duration)); } std::unique_ptr<ScrollbarAnimationController> ScrollbarAnimationController::CreateScrollbarAnimationControllerAuraOverlay( int scroll_layer_id, ScrollbarAnimationControllerClient* client, - base::TimeDelta show_delay, - base::TimeDelta fade_out_delay, + base::TimeDelta fade_delay, base::TimeDelta fade_out_resize_delay, - base::TimeDelta fade_out_duration, + base::TimeDelta fade_duration, base::TimeDelta thinning_duration) { return base::WrapUnique(new ScrollbarAnimationController( - scroll_layer_id, client, show_delay, fade_out_delay, - fade_out_resize_delay, fade_out_duration, thinning_duration)); + scroll_layer_id, client, fade_delay, fade_out_resize_delay, + fade_duration, thinning_duration)); } ScrollbarAnimationController::ScrollbarAnimationController( int scroll_layer_id, ScrollbarAnimationControllerClient* client, - base::TimeDelta fade_out_delay, + base::TimeDelta fade_delay, base::TimeDelta fade_out_resize_delay, - base::TimeDelta fade_out_duration) + base::TimeDelta fade_duration) : client_(client), - fade_out_delay_(fade_out_delay), + fade_delay_(fade_delay), fade_out_resize_delay_(fade_out_resize_delay), + fade_duration_(fade_duration), need_trigger_scrollbar_show_(false), is_animating_(false), + animation_change_(NONE), scroll_layer_id_(scroll_layer_id), currently_scrolling_(false), - scroll_gesture_has_scrolled_(false), + show_in_fast_scroll_(false), opacity_(0.0f), - fade_out_duration_(fade_out_duration), + show_scrollbars_on_scroll_gesture_(false), need_thinning_animation_(false), weak_factory_(this) { ApplyOpacityToScrollbars(0.0f); @@ -61,22 +62,22 @@ ScrollbarAnimationController::ScrollbarAnimationController( ScrollbarAnimationController::ScrollbarAnimationController( int scroll_layer_id, ScrollbarAnimationControllerClient* client, - base::TimeDelta show_delay, - base::TimeDelta fade_out_delay, + base::TimeDelta fade_delay, base::TimeDelta fade_out_resize_delay, - base::TimeDelta fade_out_duration, + base::TimeDelta fade_duration, base::TimeDelta thinning_duration) : client_(client), - show_delay_(show_delay), - fade_out_delay_(fade_out_delay), + fade_delay_(fade_delay), fade_out_resize_delay_(fade_out_resize_delay), + fade_duration_(fade_duration), need_trigger_scrollbar_show_(false), is_animating_(false), + animation_change_(NONE), scroll_layer_id_(scroll_layer_id), currently_scrolling_(false), - scroll_gesture_has_scrolled_(false), + show_in_fast_scroll_(false), opacity_(0.0f), - fade_out_duration_(fade_out_duration), + show_scrollbars_on_scroll_gesture_(true), need_thinning_animation_(true), weak_factory_(this) { vertical_controller_ = SingleScrollbarAnimationControllerThinning::Create( @@ -105,41 +106,39 @@ ScrollbarAnimationController::GetScrollbarAnimationController( } void ScrollbarAnimationController::StartAnimation() { - delayed_scrollbar_show_.Cancel(); - delayed_scrollbar_fade_out_.Cancel(); + DCHECK(animation_change_ != NONE); + delayed_scrollbar_animation_.Cancel(); is_animating_ = true; last_awaken_time_ = base::TimeTicks(); client_->SetNeedsAnimateForScrollbarAnimation(); } void ScrollbarAnimationController::StopAnimation() { - delayed_scrollbar_show_.Cancel(); - delayed_scrollbar_fade_out_.Cancel(); + delayed_scrollbar_animation_.Cancel(); is_animating_ = false; + animation_change_ = NONE; } -void ScrollbarAnimationController::PostDelayedShow() { - DCHECK(delayed_scrollbar_fade_out_.IsCancelled()); - delayed_scrollbar_show_.Reset(base::Bind(&ScrollbarAnimationController::Show, - weak_factory_.GetWeakPtr())); - client_->PostDelayedScrollbarAnimationTask(delayed_scrollbar_show_.callback(), - show_delay_); -} +void ScrollbarAnimationController::PostDelayedAnimation( + AnimationChange animation_change, + bool on_resize) { + animation_change_ = animation_change; + + base::TimeDelta delay = on_resize ? fade_out_resize_delay_ : fade_delay_; -void ScrollbarAnimationController::PostDelayedFadeOut(bool on_resize) { - DCHECK(delayed_scrollbar_show_.IsCancelled()); - base::TimeDelta delay = on_resize ? fade_out_resize_delay_ : fade_out_delay_; - delayed_scrollbar_fade_out_.Reset( + delayed_scrollbar_animation_.Cancel(); + delayed_scrollbar_animation_.Reset( base::Bind(&ScrollbarAnimationController::StartAnimation, weak_factory_.GetWeakPtr())); client_->PostDelayedScrollbarAnimationTask( - delayed_scrollbar_fade_out_.callback(), delay); + delayed_scrollbar_animation_.callback(), delay); } bool ScrollbarAnimationController::Animate(base::TimeTicks now) { bool animated = false; if (is_animating_) { + DCHECK(animation_change_ != NONE); if (last_awaken_time_.is_null()) last_awaken_time_ = now; @@ -162,59 +161,89 @@ bool ScrollbarAnimationController::Animate(base::TimeTicks now) { float ScrollbarAnimationController::AnimationProgressAtTime( base::TimeTicks now) { base::TimeDelta delta = now - last_awaken_time_; - float progress = delta.InSecondsF() / fade_out_duration_.InSecondsF(); + float progress = delta.InSecondsF() / fade_duration_.InSecondsF(); return std::max(std::min(progress, 1.f), 0.f); } +void ScrollbarAnimationController::RunAnimationFrame(float progress) { + float opacity; + + DCHECK(animation_change_ != NONE); + if (animation_change_ == FADE_IN) { + opacity = std::max(progress, opacity_); + } else { + opacity = std::min(1.f - progress, opacity_); + } + + ApplyOpacityToScrollbars(opacity); + if (progress == 1.f) + StopAnimation(); +} + void ScrollbarAnimationController::DidScrollBegin() { currently_scrolling_ = true; } -void ScrollbarAnimationController::RunAnimationFrame(float progress) { - ApplyOpacityToScrollbars(1.f - progress); - client_->SetNeedsRedrawForScrollbarAnimation(); - if (progress == 1.f) - StopAnimation(); +void ScrollbarAnimationController::DidScrollEnd() { + bool has_scrolled = show_in_fast_scroll_; + show_in_fast_scroll_ = false; + + currently_scrolling_ = false; + + // We don't fade out scrollbar if they need thinning animation and mouse is + // near. + if (need_thinning_animation_ && MouseIsNearAnyScrollbar()) + return; + + if (has_scrolled) + PostDelayedAnimation(FADE_OUT, false); } -void ScrollbarAnimationController::DidScrollUpdate(bool on_resize) { +void ScrollbarAnimationController::DidScrollUpdate() { if (need_thinning_animation_ && Captured()) return; StopAnimation(); + Show(); + // As an optimization, we avoid spamming fade delay tasks during active fast // scrolls. But if we're not within one, we need to post every scroll update. if (!currently_scrolling_) { // We don't fade out scrollbar if they need thinning animation and mouse is // near. - if (!need_thinning_animation_ || !mouse_is_near_any_scrollbar()) - PostDelayedFadeOut(on_resize); + if (!need_thinning_animation_ || !MouseIsNearAnyScrollbar()) + PostDelayedAnimation(FADE_OUT, false); } else { - scroll_gesture_has_scrolled_ = true; + show_in_fast_scroll_ = true; } - Show(); - if (need_thinning_animation_) { vertical_controller_->UpdateThumbThicknessScale(); horizontal_controller_->UpdateThumbThicknessScale(); } } -void ScrollbarAnimationController::DidScrollEnd() { - bool has_scrolled = scroll_gesture_has_scrolled_; - scroll_gesture_has_scrolled_ = false; +void ScrollbarAnimationController::WillUpdateScroll() { + if (show_scrollbars_on_scroll_gesture_) + DidScrollUpdate(); +} - currently_scrolling_ = false; +void ScrollbarAnimationController::DidRequestShowFromMainThread() { + // TODO(skobes): Call DidScrollUpdate here (suppressed for crbug.com/706927). +} - // We don't fade out scrollbar if they need thinning animation and mouse is - // near. - if (need_thinning_animation_ && mouse_is_near_any_scrollbar()) - return; +void ScrollbarAnimationController::DidResize() { + StopAnimation(); + Show(); - if (has_scrolled) - PostDelayedFadeOut(false); + // As an optimization, we avoid spamming fade delay tasks during active fast + // scrolls. + if (!currently_scrolling_) { + PostDelayedAnimation(FADE_OUT, true); + } else { + show_in_fast_scroll_ = true; + } } void ScrollbarAnimationController::DidMouseDown() { @@ -232,8 +261,8 @@ void ScrollbarAnimationController::DidMouseUp() { vertical_controller_->DidMouseUp(); horizontal_controller_->DidMouseUp(); - if (!mouse_is_near_any_scrollbar()) - PostDelayedFadeOut(false); + if (!MouseIsNearAnyScrollbar()) + PostDelayedAnimation(FADE_OUT, false); } void ScrollbarAnimationController::DidMouseLeave() { @@ -243,10 +272,13 @@ void ScrollbarAnimationController::DidMouseLeave() { vertical_controller_->DidMouseLeave(); horizontal_controller_->DidMouseLeave(); + delayed_scrollbar_animation_.Cancel(); + need_trigger_scrollbar_show_ = false; + if (ScrollbarsHidden() || Captured()) return; - PostDelayedFadeOut(false); + PostDelayedAnimation(FADE_OUT, false); } void ScrollbarAnimationController::DidMouseMoveNear( @@ -268,17 +300,17 @@ void ScrollbarAnimationController::DidMouseMoveNear( if (ScrollbarsHidden()) { if (need_trigger_scrollbar_show_before != need_trigger_scrollbar_show_) { if (need_trigger_scrollbar_show_) { - PostDelayedShow(); + PostDelayedAnimation(FADE_IN, false); } else { - delayed_scrollbar_show_.Cancel(); + delayed_scrollbar_animation_.Cancel(); } } } else { - if (mouse_is_near_any_scrollbar()) { + if (MouseIsNearAnyScrollbar()) { Show(); StopAnimation(); } else if (!is_animating_) { - PostDelayedFadeOut(false); + PostDelayedAnimation(FADE_OUT, false); } } } @@ -296,27 +328,26 @@ bool ScrollbarAnimationController::CalcNeedTriggerScrollbarShow( if (scrollbar->orientation() != orientation) continue; - if (distance < - (kMouseMoveDistanceToTriggerShow - scrollbar->ThumbThickness())) + if (distance < kMouseMoveDistanceToTriggerFadeIn) return true; } return false; } -bool ScrollbarAnimationController::mouse_is_over_scrollbar( +bool ScrollbarAnimationController::MouseIsOverScrollbar( ScrollbarOrientation orientation) const { DCHECK(need_thinning_animation_); return GetScrollbarAnimationController(orientation).mouse_is_over_scrollbar(); } -bool ScrollbarAnimationController::mouse_is_near_scrollbar( +bool ScrollbarAnimationController::MouseIsNearScrollbar( ScrollbarOrientation orientation) const { DCHECK(need_thinning_animation_); return GetScrollbarAnimationController(orientation).mouse_is_near_scrollbar(); } -bool ScrollbarAnimationController::mouse_is_near_any_scrollbar() const { +bool ScrollbarAnimationController::MouseIsNearAnyScrollbar() const { DCHECK(need_thinning_animation_); return vertical_controller_->mouse_is_near_scrollbar() || horizontal_controller_->mouse_is_near_scrollbar(); @@ -332,6 +363,7 @@ bool ScrollbarAnimationController::Captured() const { } void ScrollbarAnimationController::Show() { + delayed_scrollbar_animation_.Cancel(); ApplyOpacityToScrollbars(1.0f); } @@ -340,25 +372,15 @@ void ScrollbarAnimationController::ApplyOpacityToScrollbars(float opacity) { if (!scrollbar->is_overlay_scrollbar()) continue; float effective_opacity = scrollbar->CanScrollOrientation() ? opacity : 0; - PropertyTrees* property_trees = - scrollbar->layer_tree_impl()->property_trees(); - // If this method is called during LayerImpl::PushPropertiesTo, we may not - // yet have valid layer_id_to_effect_node_index entries as property trees - // are pushed after layers during activation. We can skip updating opacity - // in that case as we are only registering a scrollbar and because opacity - // will be overwritten anyway when property trees are pushed. - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, - scrollbar->id())) { - property_trees->effect_tree.OnOpacityAnimated( - effective_opacity, - property_trees->layer_id_to_effect_node_index[scrollbar->id()], - scrollbar->layer_tree_impl()); - } + scrollbar->SetOverlayScrollbarLayerOpacityAnimated(effective_opacity); } bool previouslyVisible = opacity_ > 0.0f; bool currentlyVisible = opacity > 0.0f; + if (opacity_ != opacity) + client_->SetNeedsRedrawForScrollbarAnimation(); + opacity_ = opacity; if (previouslyVisible != currentlyVisible) diff --git a/chromium/cc/input/scrollbar_animation_controller.h b/chromium/cc/input/scrollbar_animation_controller.h index 4dc68406839..60676d95044 100644 --- a/chromium/cc/input/scrollbar_animation_controller.h +++ b/chromium/cc/input/scrollbar_animation_controller.h @@ -8,7 +8,7 @@ #include "base/cancelable_callback.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/single_scrollbar_animation_controller_thinning.h" #include "cc/layers/layer_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" @@ -43,9 +43,9 @@ class CC_EXPORT ScrollbarAnimationController { CreateScrollbarAnimationControllerAndroid( int scroll_layer_id, ScrollbarAnimationControllerClient* client, - base::TimeDelta fade_out_delay, + base::TimeDelta fade_delay, base::TimeDelta fade_out_resize_delay, - base::TimeDelta fade_out_duration); + base::TimeDelta fade_duration); // ScrollbarAnimationController for Desktop Overlay Scrollbar. It has show & // fade out animation and thinning animation. @@ -53,10 +53,9 @@ class CC_EXPORT ScrollbarAnimationController { CreateScrollbarAnimationControllerAuraOverlay( int scroll_layer_id, ScrollbarAnimationControllerClient* client, - base::TimeDelta show_delay, - base::TimeDelta fade_out_delay, + base::TimeDelta fade_delay, base::TimeDelta fade_out_resize_delay, - base::TimeDelta fade_out_duration, + base::TimeDelta fade_duration, base::TimeDelta thinning_duration); ~ScrollbarAnimationController(); @@ -65,8 +64,19 @@ class CC_EXPORT ScrollbarAnimationController { bool Animate(base::TimeTicks now); + // WillUpdateScroll expects to be called even if the scroll position won't + // change as a result of the scroll. Only effect Aura Overlay Scrollbar. + void WillUpdateScroll(); + + // DidScrollUpdate expects to be called only if the scroll position change. + // Effect both Android and Aura Overlay Scrollbar. + void DidScrollUpdate(); + + // DidResize expects to be called when clip layer size changed or scroll layer + // size changed. + void DidResize(); + void DidScrollBegin(); - void DidScrollUpdate(bool on_resize); void DidScrollEnd(); void DidMouseDown(); @@ -74,25 +84,31 @@ class CC_EXPORT ScrollbarAnimationController { void DidMouseLeave(); void DidMouseMoveNear(ScrollbarOrientation, float); - bool mouse_is_over_scrollbar(ScrollbarOrientation orientation) const; - bool mouse_is_near_scrollbar(ScrollbarOrientation orientation) const; - bool mouse_is_near_any_scrollbar() const; + // Called when Blink wants to show the scrollbars (via + // ScrollableArea::showOverlayScrollbars). + void DidRequestShowFromMainThread(); - static constexpr float kMouseMoveDistanceToTriggerShow = 30.0f; + bool MouseIsOverScrollbar(ScrollbarOrientation orientation) const; + bool MouseIsNearScrollbar(ScrollbarOrientation orientation) const; + bool MouseIsNearAnyScrollbar() const; + + static constexpr float kMouseMoveDistanceToTriggerFadeIn = 30.0f; private: + // Describes whether the current animation should FadeIn or FadeOut. + enum AnimationChange { NONE, FADE_IN, FADE_OUT }; + ScrollbarAnimationController(int scroll_layer_id, ScrollbarAnimationControllerClient* client, - base::TimeDelta fade_out_delay, + base::TimeDelta fade_delay, base::TimeDelta fade_out_resize_delay, - base::TimeDelta fade_out_duration); + base::TimeDelta fade_duration); ScrollbarAnimationController(int scroll_layer_id, ScrollbarAnimationControllerClient* client, - base::TimeDelta show_delay, - base::TimeDelta fade_out_delay, + base::TimeDelta fade_delay, base::TimeDelta fade_out_resize_delay, - base::TimeDelta fade_out_duration, + base::TimeDelta fade_duration, base::TimeDelta thinning_duration); ScrollbarSet Scrollbars() const; @@ -109,8 +125,7 @@ class CC_EXPORT ScrollbarAnimationController { void Show(); - void PostDelayedShow(); - void PostDelayedFadeOut(bool on_resize); + void PostDelayedAnimation(AnimationChange animation_change, bool on_resize); bool Captured() const; @@ -123,26 +138,25 @@ class CC_EXPORT ScrollbarAnimationController { base::TimeTicks last_awaken_time_; - // show_delay_ is only for the case where the mouse hovers near the screen - // edge. - base::TimeDelta show_delay_; - base::TimeDelta fade_out_delay_; + base::TimeDelta fade_delay_; base::TimeDelta fade_out_resize_delay_; + base::TimeDelta fade_duration_; + bool need_trigger_scrollbar_show_; bool is_animating_; + AnimationChange animation_change_; const int scroll_layer_id_; bool currently_scrolling_; - bool scroll_gesture_has_scrolled_; + bool show_in_fast_scroll_; - base::CancelableClosure delayed_scrollbar_show_; - base::CancelableClosure delayed_scrollbar_fade_out_; + base::CancelableClosure delayed_scrollbar_animation_; float opacity_; - base::TimeDelta fade_out_duration_; + const bool show_scrollbars_on_scroll_gesture_; const bool need_thinning_animation_; std::unique_ptr<SingleScrollbarAnimationControllerThinning> vertical_controller_; diff --git a/chromium/cc/input/scrollbar_animation_controller_unittest.cc b/chromium/cc/input/scrollbar_animation_controller_unittest.cc index c8ee16ecf75..ebb22757703 100644 --- a/chromium/cc/input/scrollbar_animation_controller_unittest.cc +++ b/chromium/cc/input/scrollbar_animation_controller_unittest.cc @@ -26,8 +26,8 @@ const float kIdleThicknessScale = const float kDefaultMouseMoveDistanceToTriggerAnimation = SingleScrollbarAnimationControllerThinning:: kDefaultMouseMoveDistanceToTriggerAnimation; -const float kMouseMoveDistanceToTriggerShow = - ScrollbarAnimationController::kMouseMoveDistanceToTriggerShow; +const float kMouseMoveDistanceToTriggerFadeIn = + ScrollbarAnimationController::kMouseMoveDistanceToTriggerFadeIn; const int kThumbThickness = 10; class MockScrollbarAnimationControllerClient @@ -70,10 +70,9 @@ class ScrollbarAnimationControllerAuraOverlayTest : public testing::Test { } protected: - const base::TimeDelta kShowDelay = base::TimeDelta::FromSeconds(4); - const base::TimeDelta kFadeOutDelay = base::TimeDelta::FromSeconds(2); + const base::TimeDelta kFadeDelay = base::TimeDelta::FromSeconds(4); const base::TimeDelta kResizeFadeOutDelay = base::TimeDelta::FromSeconds(5); - const base::TimeDelta kFadeOutDuration = base::TimeDelta::FromSeconds(3); + const base::TimeDelta kFadeDuration = base::TimeDelta::FromSeconds(3); const base::TimeDelta kThinningDuration = base::TimeDelta::FromSeconds(2); void SetUp() override { @@ -115,8 +114,8 @@ class ScrollbarAnimationControllerAuraOverlayTest : public testing::Test { scrollbar_controller_ = ScrollbarAnimationController:: CreateScrollbarAnimationControllerAuraOverlay( - scroll_layer_ptr->id(), &client_, kShowDelay, kFadeOutDelay, - kResizeFadeOutDelay, kFadeOutDuration, kThinningDuration); + scroll_layer_ptr->id(), &client_, kFadeDelay, + kResizeFadeOutDelay, kFadeDuration, kThinningDuration); } FakeImplTaskRunnerProvider task_runner_provider_; @@ -145,18 +144,18 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, AppearOnResize) { time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); ExpectScrollbarsOpacity(1); // Make the Layer non-scrollable, scrollbar disappears. clip_layer_->SetBounds(gfx::Size(200, 200)); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); ExpectScrollbarsOpacity(0); // Make the layer scrollable, scrollbar appears again. clip_layer_->SetBounds(gfx::Size(100, 100)); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); ExpectScrollbarsOpacity(1); } @@ -175,7 +174,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, HideOnResize) { scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -187,7 +186,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, HideOnResize) { scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, h_scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -207,7 +206,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, BasicAppearAndFadeOut) { ExpectScrollbarsOpacity(0); EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); ExpectScrollbarsOpacity(1); EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); @@ -216,13 +215,42 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, BasicAppearAndFadeOut) { EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); // An fade out animation should have been enqueued. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); client_.start_fade().Run(); - // Scrollbar should fade out over kFadeOutDuration. + // Scrollbar should fade out over kFadeDuration. scrollbar_controller_->Animate(time); - time += kFadeOutDuration; + time += kFadeDuration; + scrollbar_controller_->Animate(time); + + ExpectScrollbarsOpacity(0); + EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); +} + +// Confirm the scrollbar appears by WillUpdateScroll and fade out. +TEST_F(ScrollbarAnimationControllerAuraOverlayTest, + BasicAppearByWillUpdateScrollThenFadeOut) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + // Scrollbar should be invisible. + ExpectScrollbarsOpacity(0); + EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); + + // Scrollbar should appear when scroll will update. + scrollbar_controller_->WillUpdateScroll(); + ExpectScrollbarsOpacity(1); + EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); + + // An fade out animation should have been enqueued. + EXPECT_EQ(kFadeDelay, client_.delay()); + EXPECT_FALSE(client_.start_fade().is_null()); + client_.start_fade().Run(); + + // Scrollbar should fade out over kFadeDuration. + scrollbar_controller_->Animate(time); + time += kFadeDuration; scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(0); @@ -236,11 +264,11 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MoveNearAndDontFadeOut) { time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // An fade out animation should have been enqueued. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); @@ -277,11 +305,11 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MoveOverAndDontFadeOut) { time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // An fade out animation should have been enqueued. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); @@ -319,11 +347,11 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // An fade out animation should have been enqueued. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); // Now move the mouse over the scrollbar and capture it. It should become @@ -347,11 +375,11 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // An fade out animation should have been enqueued. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); // Now move the mouse over the scrollbar and capture it. It should become @@ -383,11 +411,11 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, DontFadeWhileCaptured) { time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // An fade out animation should have been enqueued. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); @@ -420,11 +448,11 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, FadeAfterReleasedFar) { time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // An fade out animation should have been enqueued. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); @@ -471,11 +499,11 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, DontFadeAfterReleasedNear) { time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // An fade out animation should have been enqueued. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); @@ -510,11 +538,11 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // A fade out animation should have been enqueued. Start it. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); client_.start_fade().Run(); @@ -522,7 +550,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, ExpectScrollbarsOpacity(1); // Proceed half way through the fade out animation. - time += kFadeOutDuration / 2; + time += kFadeDuration / 2; scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(.5f); @@ -550,10 +578,10 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, TestCantCaptureWhenFaded) { time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); client_.start_fade().Run(); @@ -561,7 +589,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, TestCantCaptureWhenFaded) { ExpectScrollbarsOpacity(1); // Fade the scrollbar out completely. - time += kFadeOutDuration; + time += kFadeDuration; scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(0); @@ -614,7 +642,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, ScrollWithMouseNear) { h_scrollbar_layer_->thumb_thickness_scale_factor()); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); // Now that we've received a scroll, we should be thick without an animation. ExpectScrollbarsOpacity(1); @@ -632,7 +660,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, ScrollWithMouseNear) { h_scrollbar_layer_->thumb_thickness_scale_factor()); // Scrollbar should still be thick and visible. - time += kFadeOutDuration; + time += kFadeDuration; scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(1); EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); @@ -649,20 +677,20 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, // A ScrollUpdate without a ScrollBegin indicates a main thread scroll update // so we should schedule a fade out animation without waiting for a ScrollEnd // (which will never come). - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(client_.start_fade().is_null()); - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); client_.start_fade().Reset(); // If we got a ScrollBegin, we shouldn't schedule the fade out animation until // we get a corresponding ScrollEnd. scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_TRUE(client_.start_fade().is_null()); scrollbar_controller_->DidScrollEnd(); EXPECT_FALSE(client_.start_fade().is_null()); - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); } // Make sure that if the scroll update is as a result of a resize, we use the @@ -670,20 +698,20 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, TEST_F(ScrollbarAnimationControllerAuraOverlayTest, ResizeFadeDuration) { ASSERT_TRUE(client_.delay().is_zero()); - scrollbar_controller_->DidScrollUpdate(true); + scrollbar_controller_->DidResize(); EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_EQ(kResizeFadeOutDelay, client_.delay()); client_.delay() = base::TimeDelta(); // We should use the gesture delay rather than the resize delay if we're in a - // gesture scroll, even if the resize param is set. + // gesture scroll, even if it is resizing. scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(true); + scrollbar_controller_->DidResize(); scrollbar_controller_->DidScrollEnd(); EXPECT_FALSE(client_.start_fade().is_null()); - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); } // Tests that the fade effect is animated. @@ -693,14 +721,14 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, FadeAnimated) { // Scroll to make the scrollbars visible. scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // Appearance is instant. ExpectScrollbarsOpacity(1); // An fade out animation should have been enqueued. - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); client_.start_fade().Run(); @@ -708,11 +736,11 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, FadeAnimated) { scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(1); - time += kFadeOutDuration / 2; + time += kFadeDuration / 2; scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(.5f); - time += kFadeOutDuration / 2; + time += kFadeDuration / 2; scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(0); } @@ -725,7 +753,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, NotifyChangedVisibility) { EXPECT_CALL(client_, DidChangeScrollbarVisibility()).Times(1); // Scroll to make the scrollbars visible. scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); Mock::VerifyAndClearExpectations(&client_); @@ -738,20 +766,20 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, NotifyChangedVisibility) { ASSERT_FALSE(client_.start_fade().is_null()); client_.start_fade().Run(); scrollbar_controller_->Animate(time); - time += kFadeOutDuration / 4; + time += kFadeDuration / 4; EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); scrollbar_controller_->Animate(time); - time += kFadeOutDuration / 4; + time += kFadeDuration / 4; EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); scrollbar_controller_->Animate(time); - time += kFadeOutDuration / 4; + time += kFadeDuration / 4; EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(.25f); Mock::VerifyAndClearExpectations(&client_); EXPECT_CALL(client_, DidChangeScrollbarVisibility()).Times(1); - time += kFadeOutDuration / 4; + time += kFadeDuration / 4; scrollbar_controller_->Animate(time); EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); ExpectScrollbarsOpacity(0); @@ -760,7 +788,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, NotifyChangedVisibility) { // Calling DidScrollUpdate without a begin (i.e. update from commit) should // also notify. EXPECT_CALL(client_, DidChangeScrollbarVisibility()).Times(1); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); Mock::VerifyAndClearExpectations(&client_); } @@ -773,7 +801,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MouseNearEach) { // Scroll to make the scrollbars visible. scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // Near vertical scrollbar @@ -856,7 +884,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MouseNearEach) { // An fade out animation should have been enqueued. EXPECT_FALSE(client_.start_fade().is_null()); - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); } // Move mouse near both scrollbars at the same time. @@ -866,7 +894,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MouseNearBoth) { // Scroll to make the scrollbars visible. scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // Near both Scrollbar @@ -896,7 +924,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, // Scroll to make the scrollbars visible. scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // Near vertical scrollbar. @@ -948,7 +976,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, // An fade out animation should have been enqueued. EXPECT_FALSE(client_.start_fade().is_null()); - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); } // Ensure we have a delay fadeout animation after mouse leave without a mouse @@ -962,7 +990,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MouseLeaveFadeOut) { // Scroll to make the scrollbars visible. scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); // Should not have delay fadeout animation. @@ -974,70 +1002,129 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MouseLeaveFadeOut) { // An fade out animation should have been enqueued. EXPECT_FALSE(client_.start_fade().is_null()); - EXPECT_EQ(kFadeOutDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); } -// Scrollbars should schedule a delay show when mouse hover hidden scrollbar. -TEST_F(ScrollbarAnimationControllerAuraOverlayTest, BasicMouseHoverShow) { +// Scrollbars should schedule a delay fade in when mouse hover the show +// scrollbar region of a hidden scrollbar. +TEST_F(ScrollbarAnimationControllerAuraOverlayTest, BasicMouseHoverFadeIn) { base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - // Move mouse over scrollbar. - scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); + // Move mouse hover the fade in scrollbar region of scrollbar. + scrollbar_controller_->DidMouseMoveNear( + VERTICAL, kMouseMoveDistanceToTriggerFadeIn - 1); - // An show animation should have been enqueued. + // An fade in animation should have been enqueued. EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); - EXPECT_EQ(kShowDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); // Play the delay animation. client_.start_fade().Run(); + EXPECT_TRUE(client_.start_fade().IsCancelled()); + + scrollbar_controller_->Animate(time); + time += kFadeDuration / 2; + scrollbar_controller_->Animate(time); + + ExpectScrollbarsOpacity(0.5); + EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); + + time += kFadeDuration / 2; + scrollbar_controller_->Animate(time); + + ExpectScrollbarsOpacity(1); EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); } -// Scrollbars should not schedule a new delay show when the mouse hovers inside -// a scrollbar already scheduled a delay show. +// Scrollbars should not schedule a new delay fade in when the mouse hovers +// inside a scrollbar already scheduled a delay fade in. TEST_F(ScrollbarAnimationControllerAuraOverlayTest, MouseHoverScrollbarAndMoveInside) { base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - // Move mouse over scrollbar. - scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); + // Move mouse hover the fade in scrollbar region of scrollbar. + scrollbar_controller_->DidMouseMoveNear( + VERTICAL, kMouseMoveDistanceToTriggerFadeIn - 1); - // An show animation should have been enqueued. + // An fade in animation should have been enqueued. EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); - EXPECT_EQ(kShowDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); base::Closure& fade = client_.start_fade(); - // Move mouse inside scrollbar. should not post a new show. + // Move mouse still hover the fade in scrollbar region of scrollbar should not + // post a new fade in. scrollbar_controller_->DidMouseMoveNear( - VERTICAL, kMouseMoveDistanceToTriggerShow - kThumbThickness - 1); + VERTICAL, kMouseMoveDistanceToTriggerFadeIn - 2); EXPECT_TRUE(fade.Equals(client_.start_fade())); } -// Scrollbars should cancel delay show when mouse hover hidden scrollbar then -// move out. +// Scrollbars should cancel delay fade in when mouse hover hidden scrollbar then +// move far away. TEST_F(ScrollbarAnimationControllerAuraOverlayTest, - MouseHoverThenOutShouldCancelShow) { + MouseHoverThenOutShouldCancelFadeIn) { base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - // Move mouse over scrollbar. - scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); + // Move mouse hover the fade in scrollbar region of scrollbar. + scrollbar_controller_->DidMouseMoveNear( + VERTICAL, kMouseMoveDistanceToTriggerFadeIn - 1); - // An show animation should have been enqueued. + // An fade in animation should have been enqueued. EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); - EXPECT_EQ(kShowDelay, client_.delay()); + EXPECT_EQ(kFadeDelay, client_.delay()); + + // Move mouse far away,delay fade in should be canceled. + scrollbar_controller_->DidMouseMoveNear(VERTICAL, + kMouseMoveDistanceToTriggerFadeIn); + EXPECT_TRUE(client_.start_fade().is_null() || + client_.start_fade().IsCancelled()); +} + +// Scrollbars should cancel delay fade in when mouse hover hidden scrollbar then +// move out of window. +TEST_F(ScrollbarAnimationControllerAuraOverlayTest, + MouseHoverThenLeaveShouldCancelShowThenEnterShouldFadeIn) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); - // Move mouse out of scrollbar,delay show should be canceled. + // Move mouse hover the fade in scrollbar region of scrollbar. scrollbar_controller_->DidMouseMoveNear( - VERTICAL, kMouseMoveDistanceToTriggerShow - kThumbThickness); + VERTICAL, kMouseMoveDistanceToTriggerFadeIn - 1); + + // An fade in animation should have been enqueued. + EXPECT_FALSE(client_.start_fade().is_null()); + EXPECT_FALSE(client_.start_fade().IsCancelled()); + EXPECT_EQ(kFadeDelay, client_.delay()); + + // Move mouse out of window,delay fade in should be canceled. + scrollbar_controller_->DidMouseLeave(); EXPECT_TRUE(client_.start_fade().is_null() || client_.start_fade().IsCancelled()); + + // Move mouse hover the fade in scrollbar region of scrollbar. + scrollbar_controller_->DidMouseMoveNear( + VERTICAL, kMouseMoveDistanceToTriggerFadeIn - 1); + + // An fade in animation should have been enqueued. + EXPECT_FALSE(client_.start_fade().is_null()); + EXPECT_FALSE(client_.start_fade().IsCancelled()); + EXPECT_EQ(kFadeDelay, client_.delay()); + + // Play the delay animation. + client_.start_fade().Run(); + EXPECT_TRUE(client_.start_fade().IsCancelled()); + + scrollbar_controller_->Animate(time); + time += kFadeDuration; + scrollbar_controller_->Animate(time); + + EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); } class ScrollbarAnimationControllerAndroidTest @@ -1121,46 +1208,32 @@ class VerticalScrollbarAnimationControllerAndroidTest }; TEST_F(ScrollbarAnimationControllerAndroidTest, DelayAnimationOnResize) { - scrollbar_layer_->layer_tree_impl() - ->property_trees() - ->effect_tree.OnOpacityAnimated(0.0f, - scrollbar_layer_->effect_tree_index(), - scrollbar_layer_->layer_tree_impl()); + scrollbar_layer_->SetOverlayScrollbarLayerOpacityAnimated(0.f); + // We should use the gesture delay rather than the resize delay if we're in a + // gesture scroll, even if it is resizing. scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(true); + scrollbar_controller_->DidResize(); scrollbar_controller_->DidScrollEnd(); // Normal Animation delay of 2 seconds. EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); EXPECT_EQ(delay_, base::TimeDelta::FromSeconds(2)); - scrollbar_layer_->layer_tree_impl() - ->property_trees() - ->effect_tree.OnOpacityAnimated(0.0f, - scrollbar_layer_->effect_tree_index(), - scrollbar_layer_->layer_tree_impl()); - scrollbar_controller_->DidScrollUpdate(true); + scrollbar_layer_->SetOverlayScrollbarLayerOpacityAnimated(0.f); + scrollbar_controller_->DidResize(); // Delay animation on resize to 5 seconds. EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); EXPECT_EQ(delay_, base::TimeDelta::FromSeconds(5)); } TEST_F(ScrollbarAnimationControllerAndroidTest, HiddenInBegin) { - scrollbar_layer_->layer_tree_impl() - ->property_trees() - ->effect_tree.OnOpacityAnimated(0.0f, - scrollbar_layer_->effect_tree_index(), - scrollbar_layer_->layer_tree_impl()); + scrollbar_layer_->SetOverlayScrollbarLayerOpacityAnimated(0.f); scrollbar_controller_->Animate(base::TimeTicks()); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); } TEST_F(ScrollbarAnimationControllerAndroidTest, HiddenAfterNonScrollingGesture) { - scrollbar_layer_->layer_tree_impl() - ->property_trees() - ->effect_tree.OnOpacityAnimated(0.0f, - scrollbar_layer_->effect_tree_index(), - scrollbar_layer_->layer_tree_impl()); + scrollbar_layer_->SetOverlayScrollbarLayerOpacityAnimated(0.f); scrollbar_controller_->DidScrollBegin(); base::TimeTicks time; @@ -1176,6 +1249,25 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); } +// Confirm the scrollbar does not appear on WillUpdateScroll on Android. +TEST_F(ScrollbarAnimationControllerAndroidTest, + WillUpdateScrollNotAppearScrollbar) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + // Scrollbar should be invisible. + EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); + + // Scrollbar should appear when scroll will update. + scrollbar_controller_->WillUpdateScroll(); + EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); + + // No fade out animation should have been enqueued. + EXPECT_TRUE(start_fade_.Equals(base::Closure())); +} + TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnResize) { LayerImpl* scroll_layer = host_impl_.active_tree()->LayerById(1); ASSERT_TRUE(scroll_layer); @@ -1189,7 +1281,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnResize) { scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -1201,7 +1293,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnResize) { scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -1220,7 +1312,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, HideOnResize) { scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -1231,7 +1323,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, HideOnResize) { scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -1246,7 +1338,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnUserNonScrollableHorz) { scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -1261,7 +1353,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, ShowOnUserNonScrollableVert) { scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -1277,7 +1369,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -1293,7 +1385,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -1305,7 +1397,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByScrollingGesture) { scrollbar_controller_->DidScrollBegin(); EXPECT_FALSE(did_request_animate_); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(did_request_animate_); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); @@ -1343,7 +1435,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByScrollingGesture) { time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); start_fade_.Run(); @@ -1377,7 +1469,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByScrollingGesture) { TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByProgrammaticScroll) { base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(did_request_animate_); start_fade_.Run(); @@ -1393,7 +1485,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByProgrammaticScroll) { EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->Opacity()); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(did_request_animate_); start_fade_.Run(); @@ -1418,7 +1510,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByProgrammaticScroll) { EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->Opacity()); time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); start_fade_.Run(); time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); @@ -1448,7 +1540,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AnimationPreservedByNonScrollingGesture) { base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); start_fade_.Run(); EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; @@ -1487,7 +1579,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AnimationOverriddenByScrollingGesture) { base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(did_request_animate_); start_fade_.Run(); EXPECT_TRUE(did_request_animate_); @@ -1513,7 +1605,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->Opacity()); time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(did_request_animate_); EXPECT_FLOAT_EQ(1, scrollbar_layer_->Opacity()); diff --git a/chromium/cc/input/selection.h b/chromium/cc/input/selection.h index bbd189a2295..1b95ec9b6c6 100644 --- a/chromium/cc/input/selection.h +++ b/chromium/cc/input/selection.h @@ -5,7 +5,7 @@ #ifndef CC_INPUT_SELECTION_H_ #define CC_INPUT_SELECTION_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/input/single_scrollbar_animation_controller_thinning.h b/chromium/cc/input/single_scrollbar_animation_controller_thinning.h index 1437ccde896..32ba069a12b 100644 --- a/chromium/cc/input/single_scrollbar_animation_controller_thinning.h +++ b/chromium/cc/input/single_scrollbar_animation_controller_thinning.h @@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/layer_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" diff --git a/chromium/cc/ipc/BUILD.gn b/chromium/cc/ipc/BUILD.gn index 72b50bdc120..13e4325fad2 100644 --- a/chromium/cc/ipc/BUILD.gn +++ b/chromium/cc/ipc/BUILD.gn @@ -28,12 +28,12 @@ cc_component("ipc") { "//base", "//gpu/ipc/common", "//ipc", - "//ui/events/ipc", "//ui/gfx", "//ui/gfx/ipc", "//ui/gfx/ipc/color", "//ui/gfx/ipc/geometry", "//ui/gfx/ipc/skia", + "//ui/latency/ipc", ] } @@ -44,16 +44,17 @@ mojom("interfaces") { "compositor_frame_metadata.mojom", "copy_output_request.mojom", "copy_output_result.mojom", - "display_compositor.mojom", "filter_operation.mojom", "filter_operations.mojom", "frame_sink_id.mojom", + "frame_sink_manager.mojom", "local_surface_id.mojom", "mojo_compositor_frame_sink.mojom", "quads.mojom", "render_pass.mojom", "returned_resource.mojom", "selection.mojom", + "shared_bitmap_manager.mojom", "shared_quad_state.mojom", "surface_id.mojom", "surface_info.mojom", @@ -68,9 +69,9 @@ mojom("interfaces") { "//gpu/ipc/common:interfaces", "//mojo/common:common_custom_types", "//skia/public/interfaces", - "//ui/events/mojo:interfaces", "//ui/gfx/geometry/mojo", "//ui/gfx/mojo", + "//ui/latency/mojo:interfaces", ] } diff --git a/chromium/cc/ipc/DEPS b/chromium/cc/ipc/DEPS index 32a63b8414a..44e573a76e4 100644 --- a/chromium/cc/ipc/DEPS +++ b/chromium/cc/ipc/DEPS @@ -3,7 +3,7 @@ include_rules = [ "+mojo/common", "+mojo/public", "+skia/public", - "+ui/events/ipc", - "+ui/events/mojo", "+ui/gfx/geometry/mojo", + "+ui/latency/ipc", + "+ui/latency/mojo", ] diff --git a/chromium/cc/ipc/begin_frame_args.mojom b/chromium/cc/ipc/begin_frame_args.mojom index ad53658a220..456aa27431c 100644 --- a/chromium/cc/ipc/begin_frame_args.mojom +++ b/chromium/cc/ipc/begin_frame_args.mojom @@ -23,3 +23,11 @@ struct BeginFrameArgs { BeginFrameArgsType type; bool on_critical_path; }; + +// See cc/output/begin_frame_args.h. +struct BeginFrameAck { + uint64 sequence_number; + uint64 latest_confirmed_sequence_number; + uint32 source_id; + // |has_damage| is implicit through IPC message name, so not transmitted. +}; diff --git a/chromium/cc/ipc/begin_frame_args.typemap b/chromium/cc/ipc/begin_frame_args.typemap index 6b32996247c..0aa52bfda1d 100644 --- a/chromium/cc/ipc/begin_frame_args.typemap +++ b/chromium/cc/ipc/begin_frame_args.typemap @@ -5,5 +5,14 @@ mojom = "//cc/ipc/begin_frame_args.mojom" public_headers = [ "//cc/output/begin_frame_args.h" ] traits_headers = [ "//cc/ipc/begin_frame_args_struct_traits.h" ] -deps = [ "//cc", ] -type_mappings = [ "cc.mojom.BeginFrameArgs=cc::BeginFrameArgs" ] +deps = [ + "//cc", + "//mojo/common:struct_traits", +] +sources = [ + "begin_frame_args_struct_traits.cc", +] +type_mappings = [ + "cc.mojom.BeginFrameArgs=cc::BeginFrameArgs", + "cc.mojom.BeginFrameAck=cc::BeginFrameAck", +] diff --git a/chromium/cc/ipc/begin_frame_args_for_blink.typemap b/chromium/cc/ipc/begin_frame_args_for_blink.typemap new file mode 100644 index 00000000000..dedecc1576e --- /dev/null +++ b/chromium/cc/ipc/begin_frame_args_for_blink.typemap @@ -0,0 +1,15 @@ +# Copyright 2016 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. + +mojom = "//cc/ipc/begin_frame_args.mojom" +public_headers = [ "//cc/output/begin_frame_args.h" ] +traits_headers = [ "//cc/ipc/begin_frame_args_struct_traits.h" ] +deps = [ + "//cc", + "//mojo/common:struct_traits", +] +type_mappings = [ + "cc.mojom.BeginFrameArgs=cc::BeginFrameArgs", + "cc.mojom.BeginFrameAck=cc::BeginFrameAck", +] diff --git a/chromium/cc/ipc/begin_frame_args_struct_traits.cc b/chromium/cc/ipc/begin_frame_args_struct_traits.cc new file mode 100644 index 00000000000..8ba827dbe1b --- /dev/null +++ b/chromium/cc/ipc/begin_frame_args_struct_traits.cc @@ -0,0 +1,39 @@ +// Copyright 2017 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/ipc/begin_frame_args_struct_traits.h" +#include "ipc/ipc_message_utils.h" +#include "mojo/common/common_custom_types_struct_traits.h" + +namespace mojo { + +// static +bool StructTraits<cc::mojom::BeginFrameArgsDataView, cc::BeginFrameArgs>::Read( + cc::mojom::BeginFrameArgsDataView data, + cc::BeginFrameArgs* out) { + if (!data.ReadFrameTime(&out->frame_time) || + !data.ReadDeadline(&out->deadline) || + !data.ReadInterval(&out->interval)) { + return false; + } + out->source_id = data.source_id(); + out->sequence_number = data.sequence_number(); + // TODO(eseckler): Use EnumTraits for |type|. + out->type = static_cast<cc::BeginFrameArgs::BeginFrameArgsType>(data.type()); + out->on_critical_path = data.on_critical_path(); + return true; +} + +// static +bool StructTraits<cc::mojom::BeginFrameAckDataView, cc::BeginFrameAck>::Read( + cc::mojom::BeginFrameAckDataView data, + cc::BeginFrameAck* out) { + out->source_id = data.source_id(); + out->sequence_number = data.sequence_number(); + out->latest_confirmed_sequence_number = + data.latest_confirmed_sequence_number(); + return true; +} + +} // namespace mojo diff --git a/chromium/cc/ipc/begin_frame_args_struct_traits.h b/chromium/cc/ipc/begin_frame_args_struct_traits.h index 4d813395c28..35a9181d78d 100644 --- a/chromium/cc/ipc/begin_frame_args_struct_traits.h +++ b/chromium/cc/ipc/begin_frame_args_struct_traits.h @@ -41,19 +41,26 @@ struct StructTraits<cc::mojom::BeginFrameArgsDataView, cc::BeginFrameArgs> { } static bool Read(cc::mojom::BeginFrameArgsDataView data, - cc::BeginFrameArgs* out) { - if (!data.ReadFrameTime(&out->frame_time) || - !data.ReadDeadline(&out->deadline) || - !data.ReadInterval(&out->interval)) { - return false; - } - out->source_id = data.source_id(); - out->sequence_number = data.sequence_number(); - out->type = - static_cast<cc::BeginFrameArgs::BeginFrameArgsType>(data.type()); - out->on_critical_path = data.on_critical_path(); - return true; + cc::BeginFrameArgs* out); +}; + +template <> +struct StructTraits<cc::mojom::BeginFrameAckDataView, cc::BeginFrameAck> { + static uint64_t sequence_number(const cc::BeginFrameAck& ack) { + return ack.sequence_number; + } + + static uint64_t latest_confirmed_sequence_number( + const cc::BeginFrameAck& ack) { + return ack.latest_confirmed_sequence_number; + } + + static uint32_t source_id(const cc::BeginFrameAck& ack) { + return ack.source_id; } + + static bool Read(cc::mojom::BeginFrameAckDataView data, + cc::BeginFrameAck* out); }; } // namespace mojo diff --git a/chromium/cc/ipc/cc_param_traits.cc b/chromium/cc/ipc/cc_param_traits.cc index 216af8f2d14..3b04eb68511 100644 --- a/chromium/cc/ipc/cc_param_traits.cc +++ b/chromium/cc/ipc/cc_param_traits.cc @@ -10,8 +10,8 @@ #include "base/numerics/safe_conversions.h" #include "base/time/time.h" #include "base/unguessable_token.h" +#include "cc/base/filter_operations.h" #include "cc/output/compositor_frame.h" -#include "cc/output/filter_operations.h" #include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/draw_quad.h" #include "cc/quads/largest_draw_quad.h" diff --git a/chromium/cc/ipc/cc_param_traits.h b/chromium/cc/ipc/cc_param_traits.h index 292c1f53c91..14e3dbacd99 100644 --- a/chromium/cc/ipc/cc_param_traits.h +++ b/chromium/cc/ipc/cc_param_traits.h @@ -7,10 +7,10 @@ #ifndef CC_IPC_CC_PARAM_TRAITS_H_ #define CC_IPC_CC_PARAM_TRAITS_H_ +#include "cc/base/filter_operation.h" #include "cc/ipc/cc_ipc_export.h" #include "cc/ipc/cc_param_traits_macros.h" #include "cc/output/compositor_frame.h" -#include "cc/output/filter_operation.h" #include "cc/quads/draw_quad.h" #include "cc/quads/stream_video_draw_quad.h" #include "cc/quads/texture_draw_quad.h" diff --git a/chromium/cc/ipc/cc_param_traits_macros.h b/chromium/cc/ipc/cc_param_traits_macros.h index 42e97e419e1..39a4ecf2fe2 100644 --- a/chromium/cc/ipc/cc_param_traits_macros.h +++ b/chromium/cc/ipc/cc_param_traits_macros.h @@ -5,9 +5,9 @@ #ifndef CC_IPC_CC_PARAM_TRAITS_MACROS_H_ #define CC_IPC_CC_PARAM_TRAITS_MACROS_H_ +#include "cc/base/filter_operation.h" #include "cc/output/begin_frame_args.h" #include "cc/output/compositor_frame.h" -#include "cc/output/filter_operation.h" #include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/draw_quad.h" #include "cc/quads/render_pass.h" @@ -24,10 +24,10 @@ #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_info.h" #include "cc/surfaces/surface_sequence.h" -#include "ui/events/ipc/latency_info_param_traits.h" #include "ui/gfx/ipc/color/gfx_param_traits.h" #include "ui/gfx/ipc/gfx_param_traits.h" #include "ui/gfx/ipc/skia/gfx_skia_param_traits.h" +#include "ui/latency/ipc/latency_info_param_traits.h" #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT CC_IPC_EXPORT @@ -138,6 +138,7 @@ IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(cc::TransferableResource) IPC_STRUCT_TRAITS_MEMBER(id) IPC_STRUCT_TRAITS_MEMBER(format) + IPC_STRUCT_TRAITS_MEMBER(buffer_format) IPC_STRUCT_TRAITS_MEMBER(filter) IPC_STRUCT_TRAITS_MEMBER(size) IPC_STRUCT_TRAITS_MEMBER(mailbox_holder) @@ -175,6 +176,13 @@ IPC_STRUCT_TRAITS_BEGIN(cc::BeginFrameArgs) IPC_STRUCT_TRAITS_MEMBER(type) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(cc::BeginFrameAck) + IPC_STRUCT_TRAITS_MEMBER(sequence_number) + IPC_STRUCT_TRAITS_MEMBER(latest_confirmed_sequence_number) + IPC_STRUCT_TRAITS_MEMBER(source_id) +// |has_damage| is implicit through IPC message name, so not transmitted. +IPC_STRUCT_TRAITS_END() + IPC_STRUCT_TRAITS_BEGIN(cc::CompositorFrameMetadata) IPC_STRUCT_TRAITS_MEMBER(device_scale_factor) IPC_STRUCT_TRAITS_MEMBER(root_scroll_offset) @@ -197,7 +205,10 @@ IPC_STRUCT_TRAITS_BEGIN(cc::CompositorFrameMetadata) IPC_STRUCT_TRAITS_MEMBER(selection) IPC_STRUCT_TRAITS_MEMBER(latency_info) IPC_STRUCT_TRAITS_MEMBER(referenced_surfaces) + IPC_STRUCT_TRAITS_MEMBER(embedded_surfaces) IPC_STRUCT_TRAITS_MEMBER(content_source_id) + IPC_STRUCT_TRAITS_MEMBER(begin_frame_ack) + IPC_STRUCT_TRAITS_MEMBER(frame_token) IPC_STRUCT_TRAITS_END() #endif // CC_IPC_CC_PARAM_TRAITS_MACROS_H_ diff --git a/chromium/cc/ipc/cc_serialization_perftest.cc b/chromium/cc/ipc/cc_serialization_perftest.cc index df6a2c80009..ee90e503630 100644 --- a/chromium/cc/ipc/cc_serialization_perftest.cc +++ b/chromium/cc/ipc/cc_serialization_perftest.cc @@ -6,6 +6,7 @@ #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" +#include "cc/ipc/begin_frame_args_struct_traits.h" #include "cc/ipc/cc_param_traits.h" #include "cc/ipc/compositor_frame.mojom.h" #include "cc/ipc/compositor_frame_metadata_struct_traits.h" @@ -23,10 +24,11 @@ #include "ipc/ipc_message.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" -#include "ui/events/mojo/latency_info_struct_traits.h" +#include "third_party/skia/include/effects/SkBlurImageFilter.h" #include "ui/gfx/geometry/mojo/geometry.mojom.h" #include "ui/gfx/geometry/mojo/geometry_struct_traits.h" #include "ui/gfx/mojo/selection_bound_struct_traits.h" +#include "ui/latency/mojo/latency_info_struct_traits.h" namespace cc { namespace { @@ -225,6 +227,171 @@ class CCSerializationPerfTest : public testing::Test { test_name, count, "", true); } + static void RunComplexCompositorFrameTest(const std::string& test_name) { + CompositorFrame frame; + + TransferableResourceArray& resource_list = frame.resource_list; + for (uint32_t i = 0; i < 80; ++i) { + TransferableResource arbitrary_resource; + resource_list.push_back(arbitrary_resource); + } + + RenderPassList& render_pass_list = frame.render_pass_list; + + gfx::Transform arbitrary_matrix1; + arbitrary_matrix1.Scale(3, 3); + arbitrary_matrix1.Translate(-5, 20); + arbitrary_matrix1.Rotate(15); + gfx::Transform arbitrary_matrix2; + arbitrary_matrix2.Scale(10, -1); + arbitrary_matrix2.Translate(20, 3); + arbitrary_matrix2.Rotate(24); + gfx::Rect arbitrary_rect1(-5, 9, 3, 15); + gfx::Rect arbitrary_rect1_inside_rect1(-4, 12, 2, 8); + gfx::Rect arbitrary_rect2_inside_rect1(-5, 11, 1, 2); + gfx::Rect arbitrary_rect2(40, 23, 11, 7); + gfx::Rect arbitrary_rect1_inside_rect2(44, 23, 4, 2); + gfx::Rect arbitrary_rect2_inside_rect2(41, 25, 3, 5); + gfx::Rect arbitrary_rect3(7, -53, 22, 19); + gfx::Rect arbitrary_rect1_inside_rect3(10, -40, 6, 3); + gfx::Rect arbitrary_rect2_inside_rect3(12, -51, 5, 12); + gfx::Size arbitrary_size1(15, 19); + gfx::Size arbitrary_size2(3, 99); + gfx::Size arbitrary_size3(75, 1281); + gfx::RectF arbitrary_rectf1(4.2f, -922.1f, 15.6f, 29.5f); + gfx::RectF arbitrary_rectf2(2.1f, -411.05f, 7.8f, 14.75f); + gfx::SizeF arbitrary_sizef1(15.2f, 104.6f); + gfx::PointF arbitrary_pointf1(31.4f, 15.9f); + gfx::PointF arbitrary_pointf2(26.5f, -35.8f); + gfx::Vector2dF arbitrary_vector2df1(16.2f, -85.1f); + gfx::Vector2dF arbitrary_vector2df2(-8.3f, 0.47f); + float arbitrary_float1 = 0.7f; + float arbitrary_float2 = 0.3f; + float arbitrary_float3 = 0.9f; + float arbitrary_float_array[4] = {3.5f, 6.2f, 9.3f, 12.3f}; + bool arbitrary_bool1 = true; + bool arbitrary_bool2 = false; + bool arbitrary_bool3 = true; + bool arbitrary_bool4 = true; + bool arbitrary_bool5 = false; + bool arbitrary_bool6 = true; + int arbitrary_context_id1 = 12; + int arbitrary_context_id2 = 57; + int arbitrary_context_id3 = -503; + SkColor arbitrary_color = SkColorSetARGB(25, 36, 47, 58); + SkBlendMode arbitrary_blend_mode1 = SkBlendMode::kScreen; + SkBlendMode arbitrary_blend_mode2 = SkBlendMode::kLighten; + SkBlendMode arbitrary_blend_mode3 = SkBlendMode::kOverlay; + ResourceId arbitrary_resourceid1 = 55; + ResourceId arbitrary_resourceid2 = 47; + ResourceId arbitrary_resourceid3 = 23; + ResourceId arbitrary_resourceid4 = 16; + SkScalar arbitrary_sigma = SkFloatToScalar(2.0f); + gfx::ColorSpace arbitrary_color_space = gfx::ColorSpace::CreateXYZD50(); + int root_id = 14; + + FilterOperations arbitrary_filters1; + arbitrary_filters1.Append( + FilterOperation::CreateGrayscaleFilter(arbitrary_float1)); + arbitrary_filters1.Append(FilterOperation::CreateReferenceFilter( + SkBlurImageFilter::Make(arbitrary_sigma, arbitrary_sigma, nullptr))); + + FilterOperations arbitrary_filters2; + arbitrary_filters2.Append( + FilterOperation::CreateBrightnessFilter(arbitrary_float2)); + + std::unique_ptr<RenderPass> pass_in = RenderPass::Create(); + pass_in->SetAll(root_id, arbitrary_rect1, arbitrary_rect2, + arbitrary_matrix1, arbitrary_filters2, arbitrary_filters1, + arbitrary_color_space, arbitrary_bool1); + + // Texture quads + for (uint32_t i = 0; i < 10; ++i) { + SharedQuadState* shared_state1_in = + pass_in->CreateAndAppendSharedQuadState(); + shared_state1_in->SetAll(arbitrary_matrix1, arbitrary_size1, + arbitrary_rect1, arbitrary_rect2, + arbitrary_bool1, arbitrary_float1, + arbitrary_blend_mode1, arbitrary_context_id1); + + TextureDrawQuad* texture_in = + pass_in->CreateAndAppendDrawQuad<TextureDrawQuad>(); + texture_in->SetAll( + shared_state1_in, arbitrary_rect2, arbitrary_rect2_inside_rect2, + arbitrary_rect1_inside_rect2, arbitrary_bool1, arbitrary_resourceid1, + arbitrary_size1, arbitrary_bool1, arbitrary_pointf1, + arbitrary_pointf2, arbitrary_color, arbitrary_float_array, + arbitrary_bool4, arbitrary_bool5, arbitrary_bool6); + + TextureDrawQuad* texture_in2 = + pass_in->CreateAndAppendDrawQuad<TextureDrawQuad>(); + texture_in2->SetAll( + shared_state1_in, arbitrary_rect2, arbitrary_rect2_inside_rect2, + arbitrary_rect1_inside_rect2, arbitrary_bool1, arbitrary_resourceid2, + arbitrary_size1, arbitrary_bool3, arbitrary_pointf1, + arbitrary_pointf2, arbitrary_color, arbitrary_float_array, + arbitrary_bool4, arbitrary_bool5, arbitrary_bool6); + + TextureDrawQuad* texture_in3 = + pass_in->CreateAndAppendDrawQuad<TextureDrawQuad>(); + texture_in3->SetAll( + shared_state1_in, arbitrary_rect2, arbitrary_rect2_inside_rect2, + arbitrary_rect1_inside_rect2, arbitrary_bool1, arbitrary_resourceid3, + arbitrary_size1, arbitrary_bool2, arbitrary_pointf1, + arbitrary_pointf2, arbitrary_color, arbitrary_float_array, + arbitrary_bool4, arbitrary_bool6, arbitrary_bool6); + + TextureDrawQuad* texture_in4 = + pass_in->CreateAndAppendDrawQuad<TextureDrawQuad>(); + texture_in4->SetAll( + shared_state1_in, arbitrary_rect2, arbitrary_rect2_inside_rect2, + arbitrary_rect1_inside_rect2, arbitrary_bool1, arbitrary_resourceid4, + arbitrary_size2, arbitrary_bool4, arbitrary_pointf1, + arbitrary_pointf2, arbitrary_color, arbitrary_float_array, + arbitrary_bool4, arbitrary_bool5, arbitrary_bool6); + } + + // Tiled quads + for (uint32_t i = 0; i < 10; ++i) { + SharedQuadState* shared_state2_in = + pass_in->CreateAndAppendSharedQuadState(); + shared_state2_in->SetAll(arbitrary_matrix2, arbitrary_size2, + arbitrary_rect2, arbitrary_rect3, + arbitrary_bool1, arbitrary_float2, + arbitrary_blend_mode2, arbitrary_context_id2); + for (uint32_t j = 0; j < 6; ++j) { + TileDrawQuad* tile_in = + pass_in->CreateAndAppendDrawQuad<TileDrawQuad>(); + tile_in->SetAll(shared_state2_in, arbitrary_rect2, + arbitrary_rect2_inside_rect2, + arbitrary_rect1_inside_rect2, arbitrary_bool1, + arbitrary_resourceid3, arbitrary_rectf1, + arbitrary_size1, arbitrary_bool2, arbitrary_bool3); + } + } + + // Solid color quads + for (uint32_t i = 0; i < 5; ++i) { + SharedQuadState* shared_state3_in = + pass_in->CreateAndAppendSharedQuadState(); + shared_state3_in->SetAll(arbitrary_matrix1, arbitrary_size3, + arbitrary_rect3, arbitrary_rect1, + arbitrary_bool1, arbitrary_float3, + arbitrary_blend_mode3, arbitrary_context_id3); + for (uint32_t j = 0; j < 5; ++j) { + SolidColorDrawQuad* solidcolor_in = + pass_in->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + solidcolor_in->SetAll(shared_state3_in, arbitrary_rect3, + arbitrary_rect1_inside_rect3, + arbitrary_rect2_inside_rect3, arbitrary_bool1, + arbitrary_color, arbitrary_bool2); + } + } + + render_pass_list.push_back(std::move(pass_in)); + RunTest(test_name, std::move(frame), UseSingleSharedQuadState::NO); + } + static void RunCompositorFrameTest(const std::string& test_name, uint32_t num_quads, uint32_t num_passes, @@ -259,6 +426,14 @@ class CCSerializationPerfTest : public testing::Test { } }; +// Test for compositor frames with one render pass, 80 resources in resource +// list, 10 shared quad states with 4 texture quads each, 10 shared quad states +// with 6 tiled quads each, and 5 shared quad states with 5 solid color quads +// each. +TEST_F(CCSerializationPerfTest, DelegatedFrame_Complex) { + RunComplexCompositorFrameTest("DelegatedFrame_Complex"); +} + // Test for compositor frames with one render pass and 4000 quads. TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyQuads_1_4000) { // Case 1: One shared quad state for all quads in one render pass. @@ -269,38 +444,6 @@ TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyQuads_1_4000) { UseSingleSharedQuadState::NO); } -// Test for compositor frames with one render pass and 100000 quads. -TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyQuads_1_100000) { - // Case 1: One shared quad state for all quads in one render pass. - RunCompositorFrameTest("DelegatedFrame_ManyQuads_1_100000", 100000, 1, - UseSingleSharedQuadState::YES); - // Case 2: One shared quad state for each quad. - RunCompositorFrameTest("DelegatedFrame_ManyQuads_1_100000", 100000, 1, - UseSingleSharedQuadState::NO); -} - -// Test for compositor frames with 100 render pass and each with 4000 quads. -TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyQuads_100_4000) { - // One shared quad state for all quads in one render pass. - RunCompositorFrameTest("DelegatedFrame_ManyQuads_100_4000", 4000, 100, - UseSingleSharedQuadState::YES); -} - -// Done for https://crbug.com/691730. Test is too slow as is. -#if defined(OS_ANDROID) -#define MAYBE_DelegatedFrame_ManyQuads_10_100000 \ - DISABLED_DelegatedFrame_ManyQuads_10_100000 -#else -#define MAYBE_DelegatedFrame_ManyQuads_10_100000 \ - DelegatedFrame_ManyQuads_10_100000 -#endif -// Test for compositor frames with 10 render pass and each with 100000 quads. -TEST_F(CCSerializationPerfTest, MAYBE_DelegatedFrame_ManyQuads_10_100000) { - // One shared quad state for all quads in one render pass. - RunCompositorFrameTest("DelegatedFrame_ManyQuads_10_100000", 100000, 10, - UseSingleSharedQuadState::YES); -} - // Test for compositor frames with 5 render pass and each with 100 quads. TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyRenderPasses_5_100) { // Case 1: One shared quad state for all quads in one render pass. @@ -321,15 +464,5 @@ TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyRenderPasses_10_500) { UseSingleSharedQuadState::NO); } -// Test for compositor frames with 1000 render pass and each with 100 quads. -TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyRenderPasses_1000_100) { - // Case 1: One shared quad state for all quads in one render pass. - RunCompositorFrameTest("DelegatedFrame_ManyRenderPasses_1000_100", 100, 1000, - UseSingleSharedQuadState::YES); - // Case 2: One shared quad state for each quad. - RunCompositorFrameTest("DelegatedFrame_ManyRenderPasses_1000_100", 100, 1000, - UseSingleSharedQuadState::NO); -} - } // namespace } // namespace cc diff --git a/chromium/cc/ipc/compositor_frame_for_blink.typemap b/chromium/cc/ipc/compositor_frame_for_blink.typemap index 49f3df4c5a7..9fbd8a96723 100644 --- a/chromium/cc/ipc/compositor_frame_for_blink.typemap +++ b/chromium/cc/ipc/compositor_frame_for_blink.typemap @@ -22,7 +22,7 @@ traits_headers = [ "//skia/public/interfaces/image_filter_struct_traits.h", "//ui/gfx/mojo/selection_bound_struct_traits.h", "//ui/gfx/mojo/transform_struct_traits.h", - "//ui/events/mojo/latency_info_struct_traits.h", + "//ui/latency/mojo/latency_info_struct_traits.h", ] public_deps = [ "//cc", @@ -30,8 +30,8 @@ public_deps = [ "//gpu/ipc/common:interfaces", "//mojo/common:common_custom_types", "//skia/public/interfaces", - "//ui/events/mojo:interfaces", "//ui/gfx/geometry/mojo", "//ui/gfx/mojo", + "//ui/latency/mojo:interfaces", ] type_mappings = [ "cc.mojom.CompositorFrame=cc::CompositorFrame[move_only]" ] diff --git a/chromium/cc/ipc/compositor_frame_metadata.mojom b/chromium/cc/ipc/compositor_frame_metadata.mojom index 74deb837054..0b1a3d7b388 100644 --- a/chromium/cc/ipc/compositor_frame_metadata.mojom +++ b/chromium/cc/ipc/compositor_frame_metadata.mojom @@ -4,9 +4,10 @@ module cc.mojom; +import "cc/ipc/begin_frame_args.mojom"; import "cc/ipc/selection.mojom"; import "cc/ipc/surface_id.mojom"; -import "ui/events/mojo/latency_info.mojom"; +import "ui/latency/mojo/latency_info.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; // See cc/output/compositor_frame_metadata.h. @@ -30,6 +31,9 @@ struct CompositorFrameMetadata { Selection selection; array<ui.mojom.LatencyInfo> latency_info; array<SurfaceId> referenced_surfaces; + array<SurfaceId> embedded_surfaces; bool can_activate_before_dependencies; uint32 content_source_id; + BeginFrameAck begin_frame_ack; + uint32 frame_token; }; diff --git a/chromium/cc/ipc/compositor_frame_metadata_struct_traits.cc b/chromium/cc/ipc/compositor_frame_metadata_struct_traits.cc index cdef417d159..ab79ed7eb63 100644 --- a/chromium/cc/ipc/compositor_frame_metadata_struct_traits.cc +++ b/chromium/cc/ipc/compositor_frame_metadata_struct_traits.cc @@ -3,10 +3,11 @@ // found in the LICENSE file. #include "cc/ipc/compositor_frame_metadata_struct_traits.h" +#include "cc/ipc/begin_frame_args_struct_traits.h" #include "cc/ipc/selection_struct_traits.h" #include "cc/ipc/surface_id_struct_traits.h" -#include "ui/events/mojo/latency_info_struct_traits.h" #include "ui/gfx/mojo/selection_bound_struct_traits.h" +#include "ui/latency/mojo/latency_info_struct_traits.h" namespace mojo { @@ -37,13 +38,15 @@ bool StructTraits<cc::mojom::CompositorFrameMetadataDataView, out->bottom_controls_height = data.bottom_controls_height(); out->bottom_controls_shown_ratio = data.bottom_controls_shown_ratio(); out->content_source_id = data.content_source_id(); - + out->frame_token = data.frame_token(); out->root_background_color = data.root_background_color(); out->can_activate_before_dependencies = data.can_activate_before_dependencies(); return data.ReadSelection(&out->selection) && data.ReadLatencyInfo(&out->latency_info) && - data.ReadReferencedSurfaces(&out->referenced_surfaces); + data.ReadReferencedSurfaces(&out->referenced_surfaces) && + data.ReadEmbeddedSurfaces(&out->embedded_surfaces) && + data.ReadBeginFrameAck(&out->begin_frame_ack); } } // namespace mojo diff --git a/chromium/cc/ipc/compositor_frame_metadata_struct_traits.h b/chromium/cc/ipc/compositor_frame_metadata_struct_traits.h index c58ba45b4b2..f3077ce9495 100644 --- a/chromium/cc/ipc/compositor_frame_metadata_struct_traits.h +++ b/chromium/cc/ipc/compositor_frame_metadata_struct_traits.h @@ -106,6 +106,11 @@ struct StructTraits<cc::mojom::CompositorFrameMetadataDataView, return metadata.referenced_surfaces; } + static const std::vector<cc::SurfaceId>& embedded_surfaces( + const cc::CompositorFrameMetadata& metadata) { + return metadata.embedded_surfaces; + } + static bool can_activate_before_dependencies( const cc::CompositorFrameMetadata& metadata) { return metadata.can_activate_before_dependencies; @@ -116,6 +121,15 @@ struct StructTraits<cc::mojom::CompositorFrameMetadataDataView, return metadata.content_source_id; } + static const cc::BeginFrameAck& begin_frame_ack( + const cc::CompositorFrameMetadata& metadata) { + return metadata.begin_frame_ack; + } + + static uint32_t frame_token(const cc::CompositorFrameMetadata& metadata) { + return metadata.frame_token; + } + static bool Read(cc::mojom::CompositorFrameMetadataDataView data, cc::CompositorFrameMetadata* out); }; diff --git a/chromium/cc/ipc/filter_operation.mojom b/chromium/cc/ipc/filter_operation.mojom index 9afefd91aa4..06bca2adea4 100644 --- a/chromium/cc/ipc/filter_operation.mojom +++ b/chromium/cc/ipc/filter_operation.mojom @@ -26,7 +26,7 @@ enum FilterType { FILTER_TYPE_LAST = ALPHA_THRESHOLD }; -// See cc/output/filter_operation.h. +// See cc/base/filter_operation.h. struct FilterOperation { FilterType type; float amount; diff --git a/chromium/cc/ipc/filter_operation.typemap b/chromium/cc/ipc/filter_operation.typemap index 1acfef08e33..b892dc323c1 100644 --- a/chromium/cc/ipc/filter_operation.typemap +++ b/chromium/cc/ipc/filter_operation.typemap @@ -3,6 +3,6 @@ # found in the LICENSE file. mojom = "//cc/ipc/filter_operation.mojom" -public_headers = [ "//cc/output/filter_operation.h" ] +public_headers = [ "//cc/base/filter_operation.h" ] traits_headers = [ "//cc/ipc/filter_operation_struct_traits.h" ] type_mappings = [ "cc.mojom.FilterOperation=cc::FilterOperation" ] diff --git a/chromium/cc/ipc/filter_operation_struct_traits.h b/chromium/cc/ipc/filter_operation_struct_traits.h index 9687d961162..6ec2a669b20 100644 --- a/chromium/cc/ipc/filter_operation_struct_traits.h +++ b/chromium/cc/ipc/filter_operation_struct_traits.h @@ -5,8 +5,8 @@ #ifndef CC_IPC_FILTER_OPERATION_STRUCT_TRAITS_H_ #define CC_IPC_FILTER_OPERATION_STRUCT_TRAITS_H_ +#include "cc/base/filter_operation.h" #include "cc/ipc/filter_operation.mojom-shared.h" -#include "cc/output/filter_operation.h" #include "skia/public/interfaces/image_filter_struct_traits.h" namespace mojo { diff --git a/chromium/cc/ipc/filter_operations.mojom b/chromium/cc/ipc/filter_operations.mojom index 9e94216aefe..6e62890ff5b 100644 --- a/chromium/cc/ipc/filter_operations.mojom +++ b/chromium/cc/ipc/filter_operations.mojom @@ -6,7 +6,7 @@ module cc.mojom; import "cc/ipc/filter_operation.mojom"; -// See cc/output/filter_operations.h. +// See cc/base/filter_operations.h. struct FilterOperations { array<cc.mojom.FilterOperation> operations; }; diff --git a/chromium/cc/ipc/filter_operations.typemap b/chromium/cc/ipc/filter_operations.typemap index 5c0cc0e99e0..e675a1a499b 100644 --- a/chromium/cc/ipc/filter_operations.typemap +++ b/chromium/cc/ipc/filter_operations.typemap @@ -3,6 +3,6 @@ # found in the LICENSE file. mojom = "//cc/ipc/filter_operations.mojom" -public_headers = [ "//cc/output/filter_operations.h" ] +public_headers = [ "//cc/base/filter_operations.h" ] traits_headers = [ "//cc/ipc/filter_operations_struct_traits.h" ] type_mappings = [ "cc.mojom.FilterOperations=cc::FilterOperations" ] diff --git a/chromium/cc/ipc/filter_operations_struct_traits.h b/chromium/cc/ipc/filter_operations_struct_traits.h index 4d188cbde1f..5e77f8144a9 100644 --- a/chromium/cc/ipc/filter_operations_struct_traits.h +++ b/chromium/cc/ipc/filter_operations_struct_traits.h @@ -5,8 +5,8 @@ #ifndef CC_IPC_FILTER_OPERATIONS_STRUCT_TRAITS_H_ #define CC_IPC_FILTER_OPERATIONS_STRUCT_TRAITS_H_ +#include "cc/base/filter_operations.h" #include "cc/ipc/filter_operations.mojom-shared.h" -#include "cc/output/filter_operations.h" namespace mojo { diff --git a/chromium/cc/ipc/display_compositor.mojom b/chromium/cc/ipc/frame_sink_manager.mojom index 9af5fad5ace..584d614feb9 100644 --- a/chromium/cc/ipc/display_compositor.mojom +++ b/chromium/cc/ipc/frame_sink_manager.mojom @@ -26,18 +26,19 @@ interface DisplayPrivate { float scale_factor); }; -// The DisplayCompositor interface is a privileged interface that allows -// the display compositor host (browser or window server) to create +// The FrameSinkManager interface is a privileged interface that allows the +// frame sink manager host (browser or window server) to create // CompositorFrameSinks. Clients acquire a CompositorFrameSink connection -// through the display compositor host. Clients request a +// through the frame sink manager host. Clients request a // MojoCompositorFrameSink interface, and implement a -// MojoCompositorFrameSinkClient interface. The display compositor host -// holds one or more root CompositorFrameSinks that are tied to a valid -// |surface_handle|. All other CompositorFrameSinks are offscreen. FrameSinkIds -// are fixed for a given client and are determined ahead of time. Thus, a client -// will typically simply request a CompositorFrameSink from the display -// compositor host which will forward the request to the display compositor. -interface DisplayCompositor { +// MojoCompositorFrameSinkClient interface. The frame sink manager host +// holds one or more display CompositorFrameSinks that are tied to a valid +// |surface_handle| and cc::Display. All other CompositorFrameSinks must be +// parented by another CompositorFrameSink. FrameSinkIds are fixed for a given +// client and are determined ahead of time. Thus, a client will typically simply +// request a CompositorFrameSink from the frame sink manager host which will +// forward the request to the frame sink manager. +interface FrameSinkManager { // Create a CompositorFrameSink for a privileged client (e.g. WindowServer). // This is only used by privileged clients. The client can call methods that // talks to the Display (e.g. ResizeDisplay(), SetDisplayVisible(), etc) @@ -49,8 +50,8 @@ interface DisplayCompositor { cc.mojom.MojoCompositorFrameSinkClient compositor_frame_sink_client, associated DisplayPrivate& display_private); - // CreateCompositorFrameSink is used by unprivileged clients. - // This CompositorFrameSink is not a root, and has to be parented by another + // CreateCompositorFrameSink is used by unprivileged clients. This + // CompositorFrameSink is not a root, and has to be parented by another // CompositorFrameSink in order to appear on screen. CreateCompositorFrameSink( cc.mojom.FrameSinkId frame_sink_id, @@ -69,16 +70,16 @@ interface DisplayCompositor { cc.mojom.FrameSinkId child_frame_sink_id); // Drops the temporary reference for |surface_id|. This will get called when - // the DisplayCompositorClient doesn't think |surface_id| will be embedded. + // the FrameSinkManagerClient doesn't think |surface_id| will be embedded. DropTemporaryReference(cc.mojom.SurfaceId surface_id); }; -// The DisplayCompositorClient interface is implemented by the Display +// The FrameSinkManagerClient interface is implemented by the Display // Compositor Host, a stable, and privileged peer service to the display -// compositor. The display compositor host is either the browser process in +// compositor. The frame sink manager host is either the browser process in // Chrome or the window server process. -interface DisplayCompositorClient { - // Called by the display compositor immediately upon receiving a +interface FrameSinkManagerClient { + // Called by the frame sink manager immediately upon receiving a // CompositorFrame with a new SurfaceId for the first time. OnSurfaceCreated(SurfaceInfo surface_info); }; diff --git a/chromium/cc/ipc/mojo_compositor_frame_sink.mojom b/chromium/cc/ipc/mojo_compositor_frame_sink.mojom index 96aff284e98..1ad4ae14d5e 100644 --- a/chromium/cc/ipc/mojo_compositor_frame_sink.mojom +++ b/chromium/cc/ipc/mojo_compositor_frame_sink.mojom @@ -35,6 +35,10 @@ interface MojoCompositorFrameSink { SubmitCompositorFrame(cc.mojom.LocalSurfaceId local_surface_id, cc.mojom.CompositorFrame frame); + // Notifies the frame sink that a BeginFrame was completed, but that no + // CompositorFrame was produced as a result of it. + BeginFrameDidNotSwap(cc.mojom.BeginFrameAck ack); + // Notify that the surface is no longer in use (and is okay to be evicted) so // that its resources gets returned in time. EvictFrame(); @@ -48,16 +52,13 @@ interface MojoCompositorFrameSinkClient { // TODO(fsamuel): This method ought not be necessary with unified BeginFrame. // However, there's a fair amount of cleanup and refactoring necessary to get // rid of it. - DidReceiveCompositorFrameAck(); + DidReceiveCompositorFrameAck(ReturnedResourceArray resources); // Notification for the client to generate a CompositorFrame. OnBeginFrame(BeginFrameArgs args); // Returns resources sent to SubmitCompositorFrame to be reused or freed. ReclaimResources(ReturnedResourceArray resources); - - // Called when surface is being scheduled for a draw. - WillDrawSurface(LocalSurfaceId local_surface_id, gfx.mojom.Rect damage_rect); }; // MojoCompositorFrameSinkPrivate is used by the display compositor host to diff --git a/chromium/cc/ipc/shared_bitmap_manager.mojom b/chromium/cc/ipc/shared_bitmap_manager.mojom new file mode 100644 index 00000000000..6b2d54dd481 --- /dev/null +++ b/chromium/cc/ipc/shared_bitmap_manager.mojom @@ -0,0 +1,21 @@ +// Copyright 2017 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. + +module cc.mojom; + +import "gpu/ipc/common/mailbox.mojom"; + +// This interface is used when allocating shared bitmap memory to be shared +// with a display compositor. +// This interface needs to be associated with the RenderMessageFilter interface +// to prevent running into message ordering issues (CC trying to access a +// shared bitmap before the registration message below made it to the display +// compositor). +interface SharedBitmapManager { + // Informs the display compositor that the child allocated a shared bitmap. + DidAllocateSharedBitmap(handle<shared_buffer> buffer, gpu.mojom.Mailbox id); + + // Informs the display compositor that the child deleted a shared bitmap. + DidDeleteSharedBitmap(gpu.mojom.Mailbox id); +}; diff --git a/chromium/cc/ipc/struct_traits_unittest.cc b/chromium/cc/ipc/struct_traits_unittest.cc index 5647cb51ba8..d132d29b7bb 100644 --- a/chromium/cc/ipc/struct_traits_unittest.cc +++ b/chromium/cc/ipc/struct_traits_unittest.cc @@ -16,6 +16,7 @@ #include "cc/quads/surface_draw_quad.h" #include "cc/quads/texture_draw_quad.h" #include "cc/quads/yuv_video_draw_quad.h" +#include "cc/test/begin_frame_args_test.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkString.h" @@ -41,6 +42,11 @@ class StructTraitsTest : public testing::Test, public mojom::TraitsTestService { callback.Run(b); } + void EchoBeginFrameAck(const BeginFrameAck& b, + const EchoBeginFrameAckCallback& callback) override { + callback.Run(b); + } + void EchoCompositorFrame( CompositorFrame c, const EchoCompositorFrameCallback& callback) override { @@ -169,7 +175,11 @@ TEST_F(StructTraitsTest, BeginFrameArgs) { const base::TimeDelta interval = base::TimeDelta::FromMilliseconds(1337); const BeginFrameArgs::BeginFrameArgsType type = BeginFrameArgs::NORMAL; const bool on_critical_path = true; + const uint32_t source_id = 5; + const uint64_t sequence_number = 10; BeginFrameArgs input; + input.source_id = source_id; + input.sequence_number = sequence_number; input.frame_time = frame_time; input.deadline = deadline; input.interval = interval; @@ -178,6 +188,8 @@ TEST_F(StructTraitsTest, BeginFrameArgs) { mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); BeginFrameArgs output; proxy->EchoBeginFrameArgs(input, &output); + EXPECT_EQ(source_id, output.source_id); + EXPECT_EQ(sequence_number, output.sequence_number); EXPECT_EQ(frame_time, output.frame_time); EXPECT_EQ(deadline, output.deadline); EXPECT_EQ(interval, output.interval); @@ -185,6 +197,27 @@ TEST_F(StructTraitsTest, BeginFrameArgs) { EXPECT_EQ(on_critical_path, output.on_critical_path); } +TEST_F(StructTraitsTest, BeginFrameAck) { + const uint32_t source_id = 5; + const uint64_t sequence_number = 10; + const uint64_t latest_confirmed_sequence_number = 8; + const bool has_damage = true; + BeginFrameAck input; + input.source_id = source_id; + input.sequence_number = sequence_number; + input.latest_confirmed_sequence_number = latest_confirmed_sequence_number; + input.has_damage = has_damage; + mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); + BeginFrameAck output; + proxy->EchoBeginFrameAck(input, &output); + EXPECT_EQ(source_id, output.source_id); + EXPECT_EQ(sequence_number, output.sequence_number); + EXPECT_EQ(latest_confirmed_sequence_number, + output.latest_confirmed_sequence_number); + // |has_damage| is not transmitted. + EXPECT_FALSE(output.has_damage); +} + // Note that this is a fairly trivial test of CompositorFrame serialization as // most of the heavy lifting has already been done by CompositorFrameMetadata, // RenderPass, and QuadListBasic unit tests. @@ -227,11 +260,13 @@ TEST_F(StructTraitsTest, CompositorFrame) { // TransferableResource constants. const uint32_t tr_id = 1337; const ResourceFormat tr_format = ALPHA_8; + const gfx::BufferFormat tr_buffer_format = gfx::BufferFormat::R_8; const uint32_t tr_filter = 1234; const gfx::Size tr_size(1234, 5678); TransferableResource resource; resource.id = tr_id; resource.format = tr_format; + resource.buffer_format = tr_buffer_format; resource.filter = tr_filter; resource.size = tr_size; @@ -241,6 +276,7 @@ TEST_F(StructTraitsTest, CompositorFrame) { const float page_scale_factor = 1337.5f; const gfx::SizeF scrollable_viewport_size(1337.7f, 1234.5f); const uint32_t content_source_id = 3; + const BeginFrameAck begin_frame_ack(5, 10, 8, false); CompositorFrame input; input.metadata.device_scale_factor = device_scale_factor; @@ -250,6 +286,7 @@ TEST_F(StructTraitsTest, CompositorFrame) { input.render_pass_list.push_back(std::move(render_pass)); input.resource_list.push_back(resource); input.metadata.content_source_id = content_source_id; + input.metadata.begin_frame_ack = begin_frame_ack; mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); CompositorFrame output; @@ -260,11 +297,13 @@ TEST_F(StructTraitsTest, CompositorFrame) { EXPECT_EQ(page_scale_factor, output.metadata.page_scale_factor); EXPECT_EQ(scrollable_viewport_size, output.metadata.scrollable_viewport_size); EXPECT_EQ(content_source_id, output.metadata.content_source_id); + EXPECT_EQ(begin_frame_ack, output.metadata.begin_frame_ack); ASSERT_EQ(1u, output.resource_list.size()); TransferableResource out_resource = output.resource_list[0]; EXPECT_EQ(tr_id, out_resource.id); EXPECT_EQ(tr_format, out_resource.format); + EXPECT_EQ(tr_buffer_format, out_resource.buffer_format); EXPECT_EQ(tr_filter, out_resource.filter); EXPECT_EQ(tr_size, out_resource.size); @@ -335,6 +374,11 @@ TEST_F(StructTraitsTest, CompositorFrameMetadata) { SurfaceId id(FrameSinkId(1234, 4321), LocalSurfaceId(5678, base::UnguessableToken::Create())); referenced_surfaces.push_back(id); + std::vector<SurfaceId> embedded_surfaces; + SurfaceId id2(FrameSinkId(4321, 1234), + LocalSurfaceId(8765, base::UnguessableToken::Create())); + embedded_surfaces.push_back(id2); + uint32_t frame_token = 0xdeadbeef; CompositorFrameMetadata input; input.device_scale_factor = device_scale_factor; @@ -357,6 +401,8 @@ TEST_F(StructTraitsTest, CompositorFrameMetadata) { input.selection = selection; input.latency_info = latency_infos; input.referenced_surfaces = referenced_surfaces; + input.embedded_surfaces = embedded_surfaces; + input.frame_token = frame_token; mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); CompositorFrameMetadata output; @@ -388,6 +434,10 @@ TEST_F(StructTraitsTest, CompositorFrameMetadata) { EXPECT_EQ(referenced_surfaces.size(), output.referenced_surfaces.size()); for (uint32_t i = 0; i < referenced_surfaces.size(); ++i) EXPECT_EQ(referenced_surfaces[i], output.referenced_surfaces[i]); + EXPECT_EQ(embedded_surfaces.size(), output.embedded_surfaces.size()); + for (uint32_t i = 0; i < embedded_surfaces.size(); ++i) + EXPECT_EQ(embedded_surfaces[i], output.embedded_surfaces[i]); + EXPECT_EQ(frame_token, output.frame_token); } TEST_F(StructTraitsTest, CopyOutputRequest_BitmapRequest) { diff --git a/chromium/cc/ipc/traits_test_service.mojom b/chromium/cc/ipc/traits_test_service.mojom index 1acde1b5ace..0f994dc652a 100644 --- a/chromium/cc/ipc/traits_test_service.mojom +++ b/chromium/cc/ipc/traits_test_service.mojom @@ -29,6 +29,9 @@ interface TraitsTestService { EchoBeginFrameArgs(BeginFrameArgs b) => (BeginFrameArgs pass); [Sync] + EchoBeginFrameAck(BeginFrameAck b) => (BeginFrameAck pass); + + [Sync] EchoCompositorFrame(CompositorFrame c) => (CompositorFrame pass); [Sync] diff --git a/chromium/cc/ipc/transferable_resource.mojom b/chromium/cc/ipc/transferable_resource.mojom index d7329a6b93b..971536c3b94 100644 --- a/chromium/cc/ipc/transferable_resource.mojom +++ b/chromium/cc/ipc/transferable_resource.mojom @@ -6,6 +6,7 @@ module cc.mojom; import "gpu/ipc/common/mailbox_holder.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; +import "ui/gfx/mojo/buffer_types.mojom"; enum ResourceFormat { RGBA_8888, @@ -21,6 +22,7 @@ enum ResourceFormat { struct TransferableResource { uint32 id; ResourceFormat format; + gfx.mojom.BufferFormat buffer_format; uint32 filter; gfx.mojom.Size size; gpu.mojom.MailboxHolder mailbox_holder; diff --git a/chromium/cc/ipc/transferable_resource_struct_traits.cc b/chromium/cc/ipc/transferable_resource_struct_traits.cc index b0f648ea839..140276a32b0 100644 --- a/chromium/cc/ipc/transferable_resource_struct_traits.cc +++ b/chromium/cc/ipc/transferable_resource_struct_traits.cc @@ -20,6 +20,7 @@ bool StructTraits<cc::mojom::TransferableResourceDataView, return false; out->id = data.id(); out->format = static_cast<cc::ResourceFormat>(data.format()); + out->buffer_format = static_cast<gfx::BufferFormat>(data.buffer_format()); out->filter = data.filter(); out->read_lock_fences_enabled = data.read_lock_fences_enabled(); out->is_software = data.is_software(); diff --git a/chromium/cc/ipc/transferable_resource_struct_traits.h b/chromium/cc/ipc/transferable_resource_struct_traits.h index a85f054e584..1e3f24b7567 100644 --- a/chromium/cc/ipc/transferable_resource_struct_traits.h +++ b/chromium/cc/ipc/transferable_resource_struct_traits.h @@ -22,6 +22,11 @@ struct StructTraits<cc::mojom::TransferableResourceDataView, return static_cast<cc::mojom::ResourceFormat>(resource.format); } + static gfx::mojom::BufferFormat buffer_format( + const cc::TransferableResource& resource) { + return static_cast<gfx::mojom::BufferFormat>(resource.buffer_format); + } + static uint32_t filter(const cc::TransferableResource& resource) { return resource.filter; } diff --git a/chromium/cc/layers/append_quads_data.cc b/chromium/cc/layers/append_quads_data.cc new file mode 100644 index 00000000000..63d6d17492a --- /dev/null +++ b/chromium/cc/layers/append_quads_data.cc @@ -0,0 +1,13 @@ +// Copyright 2017 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/append_quads_data.h" + +namespace cc { + +AppendQuadsData::AppendQuadsData() = default; + +AppendQuadsData::~AppendQuadsData() = default; + +} // namespace cc diff --git a/chromium/cc/layers/append_quads_data.h b/chromium/cc/layers/append_quads_data.h index cf17b5b28c5..45afa469072 100644 --- a/chromium/cc/layers/append_quads_data.h +++ b/chromium/cc/layers/append_quads_data.h @@ -6,11 +6,19 @@ #define CC_LAYERS_APPEND_QUADS_DATA_H_ #include <stdint.h> +#include <vector> + +#include "cc/cc_export.h" +#include "cc/surfaces/surface_id.h" namespace cc { // Set by the layer appending quads. -struct AppendQuadsData { +class CC_EXPORT AppendQuadsData { + public: + AppendQuadsData(); + ~AppendQuadsData(); + int64_t num_incomplete_tiles = 0; int64_t num_missing_tiles = 0; int64_t visible_layer_area = 0; @@ -22,6 +30,8 @@ struct AppendQuadsData { int64_t checkerboarded_no_recording_content_area = 0; // This is the area within interest rect. int64_t checkerboarded_needs_raster_content_area = 0; + // This is the set of surface IDs embedded in SurfaceDrawQuads. + std::vector<SurfaceId> embedded_surfaces; }; } // namespace cc diff --git a/chromium/cc/layers/content_layer_client.h b/chromium/cc/layers/content_layer_client.h index 26602805c5f..c5d005f85a2 100644 --- a/chromium/cc/layers/content_layer_client.h +++ b/chromium/cc/layers/content_layer_client.h @@ -7,8 +7,8 @@ #include <stddef.h> -#include "cc/base/cc_export.h" -#include "cc/playback/display_item_list.h" +#include "cc/cc_export.h" +#include "cc/paint/display_item_list.h" namespace gfx { class Rect; diff --git a/chromium/cc/layers/draw_properties.h b/chromium/cc/layers/draw_properties.h index d16b40b234c..f5c7a6cfead 100644 --- a/chromium/cc/layers/draw_properties.h +++ b/chromium/cc/layers/draw_properties.h @@ -36,10 +36,9 @@ struct CC_EXPORT DrawProperties { // opacity, or when opacity is compounded by the hierarchy. float opacity; - // xxx_is_animating flags are used to indicate whether the DrawProperties - // are actually meaningful on the main thread. When the properties are - // animating, the main thread may not have the same values that are used - // to draw. + // Whether the layer has a potentially animating transform in its chain of + // transforms to the screen. This is essentially a cache of the transform + // node's potentially-animated status. bool screen_space_transform_is_animating; // True if the layer needs to be clipped by clip_rect. diff --git a/chromium/cc/layers/effect_tree_layer_list_iterator.cc b/chromium/cc/layers/effect_tree_layer_list_iterator.cc new file mode 100644 index 00000000000..a5228dcb851 --- /dev/null +++ b/chromium/cc/layers/effect_tree_layer_list_iterator.cc @@ -0,0 +1,139 @@ +// Copyright 2017 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/effect_tree_layer_list_iterator.h" + +namespace cc { + +EffectTreeLayerListIterator::EffectTreeLayerListIterator( + LayerTreeImpl* layer_tree_impl) + : state_(EffectTreeLayerListIterator::State::END), + current_effect_tree_index_(EffectTree::kInvalidNodeId), + next_effect_tree_index_(EffectTree::kInvalidNodeId), + lowest_common_effect_tree_ancestor_index_(EffectTree::kInvalidNodeId), + layer_tree_impl_(layer_tree_impl), + effect_tree_(&layer_tree_impl->property_trees()->effect_tree) { + layer_list_iterator_ = layer_tree_impl->rbegin(); + + // Find the front-most drawn layer. + while ( + layer_list_iterator_ != layer_tree_impl->rend() && + !(*layer_list_iterator_)->is_drawn_render_surface_layer_list_member()) { + layer_list_iterator_++; + } + + // If there are no drawn layers, start at the root render surface, if it + // exists. + if (layer_list_iterator_ == layer_tree_impl->rend()) { + DCHECK(effect_tree_->size() > EffectTree::kContentsRootNodeId); + state_ = State::TARGET_SURFACE; + current_effect_tree_index_ = EffectTree::kContentsRootNodeId; + } else { + state_ = State::LAYER; + current_effect_tree_index_ = + (*layer_list_iterator_)->render_target_effect_tree_index(); + next_effect_tree_index_ = current_effect_tree_index_; + lowest_common_effect_tree_ancestor_index_ = current_effect_tree_index_; + } +} + +EffectTreeLayerListIterator::EffectTreeLayerListIterator( + const EffectTreeLayerListIterator& iterator) = default; + +EffectTreeLayerListIterator::~EffectTreeLayerListIterator() {} + +// Finds the lowest common ancestor that has a render surface. +static int LowestCommonAncestor(int effect_id_1, + int effect_id_2, + const EffectTree* effect_tree) { + while (effect_id_1 != effect_id_2) { + if (effect_id_1 < effect_id_2) + effect_id_2 = effect_tree->Node(effect_id_2)->target_id; + else + effect_id_1 = effect_tree->Node(effect_id_1)->target_id; + } + + return effect_id_1; +} + +void EffectTreeLayerListIterator::operator++() { + switch (state_) { + case State::LAYER: + // Find the next drawn layer. + layer_list_iterator_++; + while (layer_list_iterator_ != layer_tree_impl_->rend() && + !(*layer_list_iterator_) + ->is_drawn_render_surface_layer_list_member()) { + layer_list_iterator_++; + } + if (layer_list_iterator_ == layer_tree_impl_->rend()) { + next_effect_tree_index_ = EffectTree::kInvalidNodeId; + lowest_common_effect_tree_ancestor_index_ = EffectTree::kInvalidNodeId; + state_ = State::TARGET_SURFACE; + break; + } + + next_effect_tree_index_ = + (*layer_list_iterator_)->render_target_effect_tree_index(); + + // If the next drawn layer has a different target effect tree index, check + // for surfaces whose contributors have all been visited. + if (next_effect_tree_index_ != current_effect_tree_index_) { + lowest_common_effect_tree_ancestor_index_ = LowestCommonAncestor( + current_effect_tree_index_, next_effect_tree_index_, effect_tree_); + // If the current layer's target effect node is an ancestor of the next + // layer's target effect node, then the current effect node still has + // more contributors that need to be visited. Otherwise, all + // contributors have been visited, so we visit the node's surface next. + if (current_effect_tree_index_ == + lowest_common_effect_tree_ancestor_index_) { + current_effect_tree_index_ = next_effect_tree_index_; + lowest_common_effect_tree_ancestor_index_ = next_effect_tree_index_; + } else { + state_ = State::TARGET_SURFACE; + } + } + break; + case State::TARGET_SURFACE: + if (current_effect_tree_index_ == EffectTree::kContentsRootNodeId) { + current_effect_tree_index_ = EffectTree::kInvalidNodeId; + state_ = State::END; + DCHECK(next_effect_tree_index_ == EffectTree::kInvalidNodeId); + DCHECK(layer_list_iterator_ == layer_tree_impl_->rend()); + } else { + state_ = State::CONTRIBUTING_SURFACE; + } + break; + case State::CONTRIBUTING_SURFACE: + DCHECK(current_effect_tree_index_ != + lowest_common_effect_tree_ancestor_index_); + // Step towards the lowest common ancestor. + current_effect_tree_index_ = + effect_tree_->Node(current_effect_tree_index_)->target_id; + if (current_effect_tree_index_ == next_effect_tree_index_) { + state_ = State::LAYER; + } else if (current_effect_tree_index_ == + lowest_common_effect_tree_ancestor_index_) { + // In this case, we know that more content contributes to the current + // effect node (since the next effect node is a descendant), so we're + // not yet ready to visit it as a target surface. The same holds for all + // effect nodes on the path from the current node to the next effect + // tree node. + state_ = State::LAYER; + current_effect_tree_index_ = next_effect_tree_index_; + lowest_common_effect_tree_ancestor_index_ = next_effect_tree_index_; + } else { + // In this case, the lowest common ancestor is a proper ancestor of the + // current effect node. This means that all contributors to the current + // effect node have been visited, so we're ready to visit it as a target + // surface. + state_ = State::TARGET_SURFACE; + } + break; + case State::END: + NOTREACHED(); + } +} + +} // namespace cc diff --git a/chromium/cc/layers/effect_tree_layer_list_iterator.h b/chromium/cc/layers/effect_tree_layer_list_iterator.h new file mode 100644 index 00000000000..c9991638ed0 --- /dev/null +++ b/chromium/cc/layers/effect_tree_layer_list_iterator.h @@ -0,0 +1,124 @@ +// Copyright 2017 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_EFFECT_TREE_LAYER_LIST_ITERATOR_H_ +#define CC_LAYERS_EFFECT_TREE_LAYER_LIST_ITERATOR_H_ + +#include "cc/cc_export.h" +#include "cc/trees/effect_node.h" +#include "cc/trees/layer_tree_impl.h" +#include "cc/trees/property_tree.h" + +namespace cc { + +class LayerImpl; +class LayerTreeImpl; + +// This iterates over layers and render surfaces in front-to-back order (that +// is, in reverse-draw-order). Only layers that draw content to some render +// surface are visited. A render surface is visited immediately after all +// layers and surfaces that contribute content to that surface are visited. +// Surfaces are first visited in state TARGET_SURFACE. Immediately after that, +// every surface other than the root surface is visited in state +// CONTRIBUTING_SURFACE, as it contributes to the next target surface. +// +// The iterator takes on the following states: +// 1. LAYER: The iterator is visiting layer |current_layer()| that contributes +// to surface |target_render_surface()|. +// 2. TARGET_SURFACE: The iterator is visiting render surface +// |target_render_surface()|. +// 3. CONTRIBUTING_SURFACE: The iterator is visiting render surface +// |current_render_surface()| that contributes to surface +// |target_render_surface()|. +// 4. END: All layers and render surfaces have already been visited. +class CC_EXPORT EffectTreeLayerListIterator { + public: + enum class State { LAYER, TARGET_SURFACE, CONTRIBUTING_SURFACE, END }; + + explicit EffectTreeLayerListIterator(LayerTreeImpl* layer_tree_impl); + EffectTreeLayerListIterator(const EffectTreeLayerListIterator& iterator); + ~EffectTreeLayerListIterator(); + + void operator++(); + + State state() { return state_; } + + LayerImpl* current_layer() const { + DCHECK(state_ == State::LAYER); + return *layer_list_iterator_; + } + + RenderSurfaceImpl* current_render_surface() const { + DCHECK(state_ == State::CONTRIBUTING_SURFACE); + return effect_tree_->GetRenderSurface(current_effect_tree_index_); + } + + RenderSurfaceImpl* target_render_surface() const { + switch (state_) { + case State::LAYER: + case State::TARGET_SURFACE: + return effect_tree_->GetRenderSurface(current_effect_tree_index_); + case State::CONTRIBUTING_SURFACE: { + int target_node_id = + effect_tree_->Node(current_effect_tree_index_)->target_id; + return effect_tree_->GetRenderSurface(target_node_id); + } + case State::END: + NOTREACHED(); + } + NOTREACHED(); + return nullptr; + } + + struct Position { + State state = State::END; + LayerImpl* current_layer = nullptr; + RenderSurfaceImpl* current_render_surface = nullptr; + RenderSurfaceImpl* target_render_surface = nullptr; + }; + + operator const Position() const { + Position position; + if (state_ == State::END) + return position; + + position.state = state_; + position.target_render_surface = target_render_surface(); + if (state_ == State::LAYER) + position.current_layer = current_layer(); + else if (state_ == State::CONTRIBUTING_SURFACE) + position.current_render_surface = current_render_surface(); + + return position; + } + + private: + State state_; + + // When in state LAYER, this is the layer that's currently being visited. + // Otherwise, this is the layer that will be visited the next time we're in + // state LAYER. + LayerImplList::reverse_iterator layer_list_iterator_; + + // When in state LAYER, this is the render target effect tree index for the + // currently visited layer. Otherwise, this is the the effect tree index of + // the currently visited render surface. + int current_effect_tree_index_; + + // Render target effect tree index for the layer currently visited by + // layer_list_iterator_. + int next_effect_tree_index_; + + // The index in the effect tree of the lowest common ancestor + // current_effect_tree_index_ and next_effect_tree_index_, that has a + // render surface. + int lowest_common_effect_tree_ancestor_index_; + + LayerTreeImpl* layer_tree_impl_; + EffectTree* effect_tree_; +}; + +} // namespace cc + +#endif // CC_LAYERS_EFFECT_TREE_LAYER_LIST_ITERATOR_H_ diff --git a/chromium/cc/layers/layer_iterator_unittest.cc b/chromium/cc/layers/effect_tree_layer_list_iterator_unittest.cc index 4b93ea6e755..6d6fb8d0a9b 100644 --- a/chromium/cc/layers/layer_iterator_unittest.cc +++ b/chromium/cc/layers/effect_tree_layer_list_iterator_unittest.cc @@ -1,8 +1,8 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2017 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/layer_iterator.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include <vector> @@ -15,11 +15,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/transform.h" -using ::testing::Mock; -using ::testing::_; -using ::testing::AtLeast; -using ::testing::AnyNumber; - namespace cc { namespace { @@ -30,92 +25,99 @@ class TestLayerImpl : public LayerImpl { } ~TestLayerImpl() override {} - int count_representing_target_surface_; - int count_representing_contributing_surface_; - int count_representing_itself_; + int count_; private: explicit TestLayerImpl(LayerTreeImpl* tree, int id) - : LayerImpl(tree, id), - count_representing_target_surface_(-1), - count_representing_contributing_surface_(-1), - count_representing_itself_(-1) { + : LayerImpl(tree, id), count_(-1) { SetBounds(gfx::Size(100, 100)); SetPosition(gfx::PointF()); SetDrawsContent(true); } }; -#define EXPECT_COUNT(layer, target, contrib, itself) \ - EXPECT_EQ(target, layer->count_representing_target_surface_); \ - EXPECT_EQ(contrib, layer->count_representing_contributing_surface_); \ - EXPECT_EQ(itself, layer->count_representing_itself_); - -void ResetCounts(LayerImplList* render_surface_layer_list) { - for (unsigned surface_index = 0; - surface_index < render_surface_layer_list->size(); - ++surface_index) { - TestLayerImpl* render_surface_layer = static_cast<TestLayerImpl*>( - render_surface_layer_list->at(surface_index)); - RenderSurfaceImpl* render_surface = - render_surface_layer->GetRenderSurface(); - - render_surface_layer->count_representing_target_surface_ = -1; - render_surface_layer->count_representing_contributing_surface_ = -1; - render_surface_layer->count_representing_itself_ = -1; - - for (unsigned layer_index = 0; - layer_index < render_surface->layer_list().size(); - ++layer_index) { - TestLayerImpl* layer = static_cast<TestLayerImpl*>( - render_surface->layer_list()[layer_index]); - - layer->count_representing_target_surface_ = -1; - layer->count_representing_contributing_surface_ = -1; - layer->count_representing_itself_ = -1; - } - } -} - -void IterateFrontToBack(LayerImplList* render_surface_layer_list) { - ResetCounts(render_surface_layer_list); - int count = 0; - 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()) - layer->count_representing_contributing_surface_ = count; - if (it.represents_itself()) - layer->count_representing_itself_ = count; - } -} +#define EXPECT_COUNT(layer, target, contrib, itself) \ + if (layer->GetRenderSurface()) { \ + EXPECT_EQ(target, target_surface_count_[layer->effect_tree_index()]); \ + EXPECT_EQ(contrib, \ + contributing_surface_count_[layer->effect_tree_index()]); \ + } \ + EXPECT_EQ(itself, layer->count_); -class LayerIteratorTest : public testing::Test { +class EffectTreeLayerListIteratorTest : public testing::Test { public: - LayerIteratorTest() + EffectTreeLayerListIteratorTest() : host_impl_(&task_runner_provider_, &task_graph_runner_), id_(1) {} std::unique_ptr<TestLayerImpl> CreateLayer() { return TestLayerImpl::Create(host_impl_.active_tree(), id_++); } + void IterateFrontToBack() { + ResetCounts(); + int count = 0; + for (EffectTreeLayerListIterator it(host_impl_.active_tree()); + it.state() != EffectTreeLayerListIterator::State::END; ++it, ++count) { + switch (it.state()) { + case EffectTreeLayerListIterator::State::LAYER: + static_cast<TestLayerImpl*>(it.current_layer())->count_ = count; + break; + case EffectTreeLayerListIterator::State::TARGET_SURFACE: + target_surface_count_[it.target_render_surface()->EffectTreeIndex()] = + count; + break; + case EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE: + contributing_surface_count_[it.current_render_surface() + ->EffectTreeIndex()] = count; + break; + default: + NOTREACHED(); + } + } + } + + void ResetCounts() { + for (LayerImpl* layer : *host_impl_.active_tree()) { + static_cast<TestLayerImpl*>(layer)->count_ = -1; + } + + target_surface_count_ = std::vector<int>( + host_impl_.active_tree()->property_trees()->effect_tree.size(), -1); + contributing_surface_count_ = std::vector<int>( + host_impl_.active_tree()->property_trees()->effect_tree.size(), -1); + } + protected: FakeImplTaskRunnerProvider task_runner_provider_; TestTaskGraphRunner task_graph_runner_; FakeLayerTreeHostImpl host_impl_; int id_; + + // Tracks when each render surface is visited as a target surface or + // contributing surface. Indexed by effect node id. + std::vector<int> target_surface_count_; + std::vector<int> contributing_surface_count_; }; -TEST_F(LayerIteratorTest, EmptyTree) { +TEST_F(EffectTreeLayerListIteratorTest, TreeWithNoDrawnLayers) { + std::unique_ptr<TestLayerImpl> root_layer = CreateLayer(); + root_layer->SetDrawsContent(false); + + TestLayerImpl* root_ptr = root_layer.get(); + + host_impl_.active_tree()->SetRootLayerForTesting(std::move(root_layer)); + LayerImplList render_surface_layer_list; + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root_ptr, root_ptr->bounds(), &render_surface_layer_list); + LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); - IterateFrontToBack(&render_surface_layer_list); + IterateFrontToBack(); + EXPECT_COUNT(root_ptr, 0, -1, -1); } -TEST_F(LayerIteratorTest, SimpleTree) { +TEST_F(EffectTreeLayerListIteratorTest, SimpleTree) { std::unique_ptr<TestLayerImpl> root_layer = CreateLayer(); std::unique_ptr<TestLayerImpl> first = CreateLayer(); std::unique_ptr<TestLayerImpl> second = CreateLayer(); @@ -140,7 +142,7 @@ TEST_F(LayerIteratorTest, SimpleTree) { root_ptr, root_ptr->bounds(), &render_surface_layer_list); LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); - IterateFrontToBack(&render_surface_layer_list); + IterateFrontToBack(); EXPECT_COUNT(root_ptr, 5, -1, 4); EXPECT_COUNT(first_ptr, -1, -1, 3); EXPECT_COUNT(second_ptr, -1, -1, 2); @@ -148,7 +150,7 @@ TEST_F(LayerIteratorTest, SimpleTree) { EXPECT_COUNT(fourth_ptr, -1, -1, 0); } -TEST_F(LayerIteratorTest, ComplexTree) { +TEST_F(EffectTreeLayerListIteratorTest, ComplexTree) { std::unique_ptr<TestLayerImpl> root_layer = CreateLayer(); std::unique_ptr<TestLayerImpl> root1 = CreateLayer(); std::unique_ptr<TestLayerImpl> root2 = CreateLayer(); @@ -185,7 +187,7 @@ TEST_F(LayerIteratorTest, ComplexTree) { root_ptr, root_ptr->bounds(), &render_surface_layer_list); LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); - IterateFrontToBack(&render_surface_layer_list); + IterateFrontToBack(); EXPECT_COUNT(root_ptr, 9, -1, 8); EXPECT_COUNT(root1_ptr, -1, -1, 7); EXPECT_COUNT(root2_ptr, -1, -1, 6); @@ -197,7 +199,7 @@ TEST_F(LayerIteratorTest, ComplexTree) { EXPECT_COUNT(root3_ptr, -1, -1, 0); } -TEST_F(LayerIteratorTest, ComplexTreeMultiSurface) { +TEST_F(EffectTreeLayerListIteratorTest, ComplexTreeMultiSurface) { std::unique_ptr<TestLayerImpl> root_layer = CreateLayer(); std::unique_ptr<TestLayerImpl> root1 = CreateLayer(); std::unique_ptr<TestLayerImpl> root2 = CreateLayer(); @@ -238,7 +240,7 @@ TEST_F(LayerIteratorTest, ComplexTreeMultiSurface) { root_ptr, root_ptr->bounds(), &render_surface_layer_list); LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); - IterateFrontToBack(&render_surface_layer_list); + IterateFrontToBack(); EXPECT_COUNT(root_ptr, 14, -1, 13); EXPECT_COUNT(root1_ptr, -1, -1, 12); EXPECT_COUNT(root2_ptr, 10, 11, -1); diff --git a/chromium/cc/layers/empty_content_layer_client.cc b/chromium/cc/layers/empty_content_layer_client.cc deleted file mode 100644 index 3e1ef402228..00000000000 --- a/chromium/cc/layers/empty_content_layer_client.cc +++ /dev/null @@ -1,44 +0,0 @@ -// 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/empty_content_layer_client.h" - -#include "cc/playback/display_item_list.h" -#include "ui/gfx/geometry/rect.h" - -namespace cc { - -namespace { -base::LazyInstance<EmptyContentLayerClient> g_empty_content_layer_client = - LAZY_INSTANCE_INITIALIZER; -} - -// static -ContentLayerClient* EmptyContentLayerClient::GetInstance() { - return g_empty_content_layer_client.Pointer(); -} - -EmptyContentLayerClient::EmptyContentLayerClient() {} - -EmptyContentLayerClient::~EmptyContentLayerClient() {} - -gfx::Rect EmptyContentLayerClient::PaintableRegion() { - return gfx::Rect(); -} - -scoped_refptr<DisplayItemList> -EmptyContentLayerClient::PaintContentsToDisplayList( - PaintingControlSetting painting_status) { - return make_scoped_refptr(new DisplayItemList); -} - -bool EmptyContentLayerClient::FillsBoundsCompletely() const { - return false; -} - -size_t EmptyContentLayerClient::GetApproximateUnsharedMemoryUsage() const { - return 0u; -} - -} // namespace cc diff --git a/chromium/cc/layers/empty_content_layer_client.h b/chromium/cc/layers/empty_content_layer_client.h deleted file mode 100644 index 0d831b6e6d6..00000000000 --- a/chromium/cc/layers/empty_content_layer_client.h +++ /dev/null @@ -1,48 +0,0 @@ -// 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_LAYERS_EMPTY_CONTENT_LAYER_CLIENT_H_ -#define CC_LAYERS_EMPTY_CONTENT_LAYER_CLIENT_H_ - -#include <memory> - -#include "base/lazy_instance.h" -#include "base/macros.h" -#include "cc/base/cc_export.h" -#include "cc/layers/content_layer_client.h" -#include "ui/gfx/geometry/rect.h" - -namespace cc { - -class DisplayItemList; - -// This is used by deserialized PictureLayers which have no local -// ContentLayerClient but still have valid content from the original serialized -// PictureLayer. The PictureLayer class requires a valid ContentLayerClient to -// determine if it can draw. This is a dummy client to keep the logic fairly -// straightforward. This is also used by unit tests for creating dummy -// PictureLayers. -class CC_EXPORT EmptyContentLayerClient : public ContentLayerClient { - public: - static ContentLayerClient* GetInstance(); - - // ContentLayerClient implementation. - gfx::Rect PaintableRegion() override; - scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting painting_status) override; - bool FillsBoundsCompletely() const override; - size_t GetApproximateUnsharedMemoryUsage() const override; - - private: - friend struct base::DefaultLazyInstanceTraits<EmptyContentLayerClient>; - - EmptyContentLayerClient(); - ~EmptyContentLayerClient() override; - - DISALLOW_COPY_AND_ASSIGN(EmptyContentLayerClient); -}; - -} // namespace cc - -#endif // CC_LAYERS_EMPTY_CONTENT_LAYER_CLIENT_H_ diff --git a/chromium/cc/layers/heads_up_display_layer.h b/chromium/cc/layers/heads_up_display_layer.h index 2cde7e87beb..4cb2946dbdf 100644 --- a/chromium/cc/layers/heads_up_display_layer.h +++ b/chromium/cc/layers/heads_up_display_layer.h @@ -9,7 +9,7 @@ #include <string> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkTypeface.h" diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc index 6aae1bd3bdd..7340f184c1f 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.cc +++ b/chromium/cc/layers/heads_up_display_layer_impl.cc @@ -11,14 +11,15 @@ #include <vector> #include "base/numerics/safe_conversions.h" +#include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/debug/debug_colors.h" -#include "cc/debug/frame_rate_counter.h" #include "cc/output/begin_frame_args.h" #include "cc/quads/texture_draw_quad.h" #include "cc/resources/memory_history.h" +#include "cc/trees/frame_rate_counter.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" #include "skia/ext/platform_canvas.h" @@ -102,12 +103,10 @@ void HeadsUpDisplayLayerImpl::AcquireResource( void HeadsUpDisplayLayerImpl::ReleaseUnmatchedSizeResources( ResourceProvider* resource_provider) { - auto it_erase = - std::remove_if(resources_.begin(), resources_.end(), - [this](const std::unique_ptr<ScopedResource>& resource) { - return internal_content_bounds_ != resource->size(); - }); - resources_.erase(it_erase, resources_.end()); + base::EraseIf(resources_, + [this](const std::unique_ptr<ScopedResource>& resource) { + return internal_content_bounds_ != resource->size(); + }); } bool HeadsUpDisplayLayerImpl::WillDraw(DrawMode draw_mode, diff --git a/chromium/cc/layers/heads_up_display_layer_impl.h b/chromium/cc/layers/heads_up_display_layer_impl.h index 68175009367..b808ebc911c 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.h +++ b/chromium/cc/layers/heads_up_display_layer_impl.h @@ -12,11 +12,11 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" -#include "cc/debug/debug_rect_history.h" +#include "cc/cc_export.h" #include "cc/layers/layer_impl.h" #include "cc/resources/memory_history.h" #include "cc/resources/scoped_resource.h" +#include "cc/trees/debug_rect_history.h" #include "third_party/skia/include/core/SkRefCnt.h" class SkCanvas; diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc index 04fa7f4a423..72a530a3bf3 100644 --- a/chromium/cc/layers/layer.cc +++ b/chromium/cc/layers/layer.cc @@ -16,19 +16,20 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "cc/base/simple_enclosed_region.h" -#include "cc/debug/frame_viewer_instrumentation.h" #include "cc/input/main_thread_scrolling_reason.h" #include "cc/layers/layer_client.h" #include "cc/layers/layer_impl.h" #include "cc/layers/scrollbar_layer_interface.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" +#include "cc/tiles/frame_viewer_instrumentation.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/mutable_properties.h" #include "cc/trees/mutator_host.h" +#include "cc/trees/scroll_node.h" #include "cc/trees/transform_node.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -62,7 +63,6 @@ Layer::Inputs::Inputs(int layer_id) scroll_parent(nullptr), clip_parent(nullptr), has_will_change_transform_hint(false), - has_preferred_raster_bounds(false), hide_layer_and_subtree(false), client(nullptr) {} @@ -91,8 +91,9 @@ Layer::Layer() force_render_surface_for_testing_(false), subtree_property_changed_(false), may_contain_video_(false), + is_scroll_clip_layer_(false), + needs_show_scrollbars_(false), safe_opaque_background_color_(0), - draw_blend_mode_(SkBlendMode::kSrcOver), num_unclipped_descendants_(0) {} Layer::~Layer() { @@ -161,19 +162,6 @@ void Layer::SetNeedsCommit() { return; SetNeedsPushProperties(); - layer_tree_host_->property_trees()->needs_rebuild = true; - - if (ignore_set_needs_commit_) - return; - - layer_tree_host_->SetNeedsCommit(); -} - -void Layer::SetNeedsCommitNoRebuild() { - if (!layer_tree_host_) - return; - - SetNeedsPushProperties(); if (ignore_set_needs_commit_) return; @@ -222,10 +210,7 @@ void Layer::SetParent(Layer* layer) { parent_ = layer; SetLayerTreeHost(parent_ ? parent_->layer_tree_host() : nullptr); - if (!layer_tree_host_) - return; - - layer_tree_host_->property_trees()->needs_rebuild = true; + SetPropertyTreesNeedRebuild(); } void Layer::AddChild(scoped_refptr<Layer> child) { @@ -306,8 +291,22 @@ void Layer::SetBounds(const gfx::Size& size) { if (!layer_tree_host_) return; - if (masks_to_bounds()) + if (masks_to_bounds()) { SetSubtreePropertyChanged(); + SetPropertyTreesNeedRebuild(); + } + + if (scrollable()) { + if (ScrollNode* node = + layer_tree_host_->property_trees() + ->scroll_tree.UpdateNodeFromOwningLayerId(id())) { + node->bounds = inputs_.bounds; + } + } + + if (is_scroll_clip_layer_) + layer_tree_host_->property_trees()->scroll_tree.set_needs_update(true); + SetNeedsCommit(); } @@ -361,6 +360,7 @@ void Layer::RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> request) { return; inputs_.copy_requests.push_back(std::move(request)); SetSubtreePropertyChanged(); + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -369,6 +369,7 @@ void Layer::SetBackgroundColor(SkColor background_color) { if (inputs_.background_color == background_color) return; inputs_.background_color = background_color; + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -395,6 +396,7 @@ void Layer::SetMasksToBounds(bool masks_to_bounds) { return; inputs_.masks_to_bounds = masks_to_bounds; SetNeedsCommit(); + SetPropertyTreesNeedRebuild(); SetSubtreePropertyChanged(); } @@ -437,6 +439,7 @@ void Layer::SetFilters(const FilterOperations& filters) { inputs_.mask_layer->SetLayerMaskType( Layer::LayerMaskType::SINGLE_TEXTURE_MASK); SetSubtreePropertyChanged(); + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -446,6 +449,7 @@ void Layer::SetBackgroundFilters(const FilterOperations& filters) { return; inputs_.background_filters = filters; SetSubtreePropertyChanged(); + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -455,6 +459,7 @@ void Layer::SetFiltersOrigin(const gfx::PointF& filters_origin) { return; inputs_.filters_origin = filters_origin; SetSubtreePropertyChanged(); + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -472,19 +477,15 @@ void Layer::SetOpacity(float opacity) { SetSubtreePropertyChanged(); if (layer_tree_host_ && !force_rebuild) { PropertyTrees* property_trees = layer_tree_host_->property_trees(); - auto effect_id_to_index = - property_trees->layer_id_to_effect_node_index.find(id()); - if (effect_id_to_index != - property_trees->layer_id_to_effect_node_index.end()) { - EffectNode* node = - property_trees->effect_tree.Node(effect_id_to_index->second); + if (EffectNode* node = + property_trees->effect_tree.UpdateNodeFromOwningLayerId(id())) { node->opacity = opacity; node->effect_changed = true; property_trees->effect_tree.set_needs_update(true); - SetNeedsCommitNoRebuild(); - return; } } + if (force_rebuild) + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -549,6 +550,7 @@ void Layer::SetBlendMode(SkBlendMode blend_mode) { inputs_.blend_mode = blend_mode; SetNeedsCommit(); SetSubtreePropertyChanged(); + SetPropertyTreesNeedRebuild(); } void Layer::SetIsRootForIsolatedGroup(bool root) { @@ -556,6 +558,7 @@ void Layer::SetIsRootForIsolatedGroup(bool root) { if (inputs_.is_root_for_isolated_group == root) return; inputs_.is_root_for_isolated_group = root; + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -566,6 +569,7 @@ void Layer::SetContentsOpaque(bool opaque) { inputs_.contents_opaque = opaque; SetNeedsCommit(); SetSubtreePropertyChanged(); + SetPropertyTreesNeedRebuild(); } void Layer::SetPosition(const gfx::PointF& position) { @@ -579,17 +583,17 @@ void Layer::SetPosition(const gfx::PointF& position) { SetSubtreePropertyChanged(); PropertyTrees* property_trees = layer_tree_host_->property_trees(); - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id())) { - DCHECK_EQ(transform_tree_index(), - property_trees->layer_id_to_transform_node_index[id()]); - TransformNode* transform_node = - property_trees->transform_tree.Node(transform_tree_index()); + if (TransformNode* transform_node = + property_trees->transform_tree.UpdateNodeFromOwningLayerId(id())) { + DCHECK_EQ(transform_tree_index(), transform_node->id); transform_node->update_post_local_transform(position, transform_origin()); if (transform_node->sticky_position_constraint_id >= 0) { StickyPositionNodeData* sticky_data = property_trees->transform_tree.StickyPositionData( transform_tree_index()); + // TODO(smcgruer): Pass main thread sticky-shifting offsets of + // non-promoted ancestors, or promote all ancestor sticky elements. + // See http://crbug.com/702229 sticky_data->main_thread_offset = position.OffsetFromOrigin() - sticky_data->constraints.parent_relative_sticky_box_offset @@ -598,8 +602,6 @@ void Layer::SetPosition(const gfx::PointF& position) { transform_node->needs_local_transform_update = true; transform_node->transform_changed = true; layer_tree_host_->property_trees()->transform_tree.set_needs_update(true); - SetNeedsCommitNoRebuild(); - return; } SetNeedsCommit(); @@ -632,28 +634,20 @@ void Layer::SetTransform(const gfx::Transform& transform) { SetSubtreePropertyChanged(); if (layer_tree_host_) { PropertyTrees* property_trees = layer_tree_host_->property_trees(); - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id())) { + if (TransformNode* transform_node = + property_trees->transform_tree.UpdateNodeFromOwningLayerId(id())) { // We need to trigger a rebuild if we could have affected 2d axis - // alignment. We'll check to see if transform and inputs_.transform - // are axis - // align with respect to one another. - DCHECK_EQ(transform_tree_index(), - property_trees->layer_id_to_transform_node_index[id()]); - TransformNode* transform_node = - property_trees->transform_tree.Node(transform_tree_index()); + // alignment. We'll check to see if transform and inputs_.transform are + // axis align with respect to one another. + DCHECK_EQ(transform_tree_index(), transform_node->id); bool preserves_2d_axis_alignment = Are2dAxisAligned(inputs_.transform, transform); transform_node->local = transform; transform_node->needs_local_transform_update = true; transform_node->transform_changed = true; layer_tree_host_->property_trees()->transform_tree.set_needs_update(true); - if (preserves_2d_axis_alignment) - SetNeedsCommitNoRebuild(); - else - SetNeedsCommit(); - inputs_.transform = transform; - return; + if (!preserves_2d_axis_alignment) + SetPropertyTreesNeedRebuild(); } } @@ -673,19 +667,14 @@ void Layer::SetTransformOrigin(const gfx::Point3F& transform_origin) { SetSubtreePropertyChanged(); PropertyTrees* property_trees = layer_tree_host_->property_trees(); - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id())) { - DCHECK_EQ(transform_tree_index(), - property_trees->layer_id_to_transform_node_index[id()]); - TransformNode* transform_node = - property_trees->transform_tree.Node(transform_tree_index()); + if (TransformNode* transform_node = + property_trees->transform_tree.UpdateNodeFromOwningLayerId(id())) { + DCHECK_EQ(transform_tree_index(), transform_node->id); transform_node->update_pre_local_transform(transform_origin); transform_node->update_post_local_transform(position(), transform_origin); transform_node->needs_local_transform_update = true; transform_node->transform_changed = true; layer_tree_host_->property_trees()->transform_tree.set_needs_update(true); - SetNeedsCommitNoRebuild(); - return; } SetNeedsCommit(); @@ -713,6 +702,7 @@ void Layer::SetScrollParent(Layer* parent) { if (inputs_.scroll_parent) inputs_.scroll_parent->AddScrollChild(this); + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -743,9 +733,8 @@ void Layer::SetClipParent(Layer* ancestor) { if (inputs_.clip_parent) inputs_.clip_parent->AddClipChild(this); + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); - if (layer_tree_host_) - layer_tree_host_->SetNeedsMetaInfoRecomputation(true); } void Layer::AddClipChild(Layer* child) { @@ -776,17 +765,12 @@ void Layer::SetScrollOffset(const gfx::ScrollOffset& scroll_offset) { if (scroll_tree_index() != ScrollTree::kInvalidNodeId && scrollable()) property_trees->scroll_tree.SetScrollOffset(id(), scroll_offset); - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id())) { - DCHECK_EQ(transform_tree_index(), - property_trees->layer_id_to_transform_node_index[id()]); - TransformNode* transform_node = - property_trees->transform_tree.Node(transform_tree_index()); + if (TransformNode* transform_node = + property_trees->transform_tree.UpdateNodeFromOwningLayerId(id())) { + DCHECK_EQ(transform_tree_index(), transform_node->id); transform_node->scroll_offset = CurrentScrollOffset(); transform_node->needs_local_transform_update = true; property_trees->transform_tree.set_needs_update(true); - SetNeedsCommitNoRebuild(); - return; } SetNeedsCommit(); @@ -803,27 +787,18 @@ void Layer::SetScrollOffsetFromImplSide( inputs_.scroll_offset = scroll_offset; SetNeedsPushProperties(); - bool needs_rebuild = true; - PropertyTrees* property_trees = layer_tree_host_->property_trees(); if (scroll_tree_index() != ScrollTree::kInvalidNodeId && scrollable()) property_trees->scroll_tree.SetScrollOffset(id(), scroll_offset); - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id())) { - DCHECK_EQ(transform_tree_index(), - property_trees->layer_id_to_transform_node_index[id()]); - TransformNode* transform_node = - property_trees->transform_tree.Node(transform_tree_index()); + if (TransformNode* transform_node = + property_trees->transform_tree.UpdateNodeFromOwningLayerId(id())) { + DCHECK_EQ(transform_tree_index(), transform_node->id); transform_node->scroll_offset = CurrentScrollOffset(); transform_node->needs_local_transform_update = true; property_trees->transform_tree.set_needs_update(true); - needs_rebuild = false; } - if (needs_rebuild) - property_trees->needs_rebuild = true; - if (!inputs_.did_scroll_callback.is_null()) inputs_.did_scroll_callback.Run(scroll_offset); @@ -836,6 +811,7 @@ void Layer::SetScrollClipLayerId(int clip_layer_id) { if (inputs_.scroll_clip_layer_id == clip_layer_id) return; inputs_.scroll_clip_layer_id = clip_layer_id; + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -851,6 +827,14 @@ void Layer::SetUserScrollable(bool horizontal, bool vertical) { return; inputs_.user_scrollable_horizontal = horizontal; inputs_.user_scrollable_vertical = vertical; + if (!layer_tree_host_) + return; + + if (ScrollNode* node = layer_tree_host_->property_trees() + ->scroll_tree.UpdateNodeFromOwningLayerId(id())) { + node->user_scrollable_horizontal = horizontal; + node->user_scrollable_vertical = vertical; + } SetNeedsCommit(); } @@ -864,6 +848,7 @@ void Layer::AddMainThreadScrollingReasons( return; inputs_.main_thread_scrolling_reasons = new_reasons; didUpdateMainThreadScrollingReasons(); + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -877,6 +862,7 @@ void Layer::ClearMainThreadScrollingReasons( return; inputs_.main_thread_scrolling_reasons = new_reasons; didUpdateMainThreadScrollingReasons(); + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -885,6 +871,7 @@ void Layer::SetNonFastScrollableRegion(const Region& region) { if (inputs_.non_fast_scrollable_region == region) return; inputs_.non_fast_scrollable_region = region; + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -894,6 +881,7 @@ void Layer::SetTouchEventHandlerRegion(const Region& region) { return; inputs_.touch_event_handler_region = region; + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -902,6 +890,7 @@ void Layer::SetForceRenderSurfaceForTesting(bool force) { if (force_render_surface_for_testing_ == force) return; force_render_surface_for_testing_ = force; + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -911,6 +900,7 @@ void Layer::SetDoubleSided(bool double_sided) { return; inputs_.double_sided = double_sided; SetNeedsCommit(); + SetPropertyTreesNeedRebuild(); SetSubtreePropertyChanged(); } @@ -920,6 +910,7 @@ void Layer::Set3dSortingContextId(int id) { return; inputs_.sorting_context_id = id; SetNeedsCommit(); + SetPropertyTreesNeedRebuild(); SetSubtreePropertyChanged(); } @@ -998,12 +989,18 @@ void Layer::InvalidatePropertyTreesIndices() { SetScrollTreeIndex(ScrollTree::kInvalidNodeId); } +void Layer::SetPropertyTreesNeedRebuild() { + if (layer_tree_host_) + layer_tree_host_->property_trees()->needs_rebuild = true; +} + void Layer::SetShouldFlattenTransform(bool should_flatten) { DCHECK(IsPropertyChangeAllowed()); if (inputs_.should_flatten_transform == should_flatten) return; inputs_.should_flatten_transform = should_flatten; SetNeedsCommit(); + SetPropertyTreesNeedRebuild(); SetSubtreePropertyChanged(); } @@ -1046,6 +1043,7 @@ void Layer::SetHideLayerAndSubtree(bool hide) { inputs_.hide_layer_and_subtree = hide; SetNeedsCommit(); + SetPropertyTreesNeedRebuild(); SetSubtreePropertyChanged(); } @@ -1078,8 +1076,10 @@ void Layer::SetIsContainerForFixedPositionLayers(bool container) { return; // Only request a commit if we have a fixed positioned descendant. - if (DescendantIsFixedToContainerLayer()) + if (DescendantIsFixedToContainerLayer()) { + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); + } } void Layer::SetPositionConstraint(const LayerPositionConstraint& constraint) { @@ -1087,6 +1087,7 @@ void Layer::SetPositionConstraint(const LayerPositionConstraint& constraint) { if (inputs_.position_constraint == constraint) return; inputs_.position_constraint = constraint; + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -1096,6 +1097,7 @@ void Layer::SetStickyPositionConstraint( if (inputs_.sticky_position_constraint == constraint) return; inputs_.sticky_position_constraint = constraint; + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -1109,10 +1111,9 @@ static void PostCopyCallbackToMainThread( scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, std::unique_ptr<CopyOutputRequest> request, std::unique_ptr<CopyOutputResult> result) { - main_thread_task_runner->PostTask(FROM_HERE, - base::Bind(&RunCopyCallbackOnMainThread, - base::Passed(&request), - base::Passed(&result))); + main_thread_task_runner->PostTask( + FROM_HERE, base::BindOnce(&RunCopyCallbackOnMainThread, + base::Passed(&request), base::Passed(&result))); } bool Layer::IsSnapped() { @@ -1160,7 +1161,6 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->SetPosition(inputs_.position); layer->set_should_flatten_transform_from_property_tree( should_flatten_transform_from_property_tree_); - layer->set_draw_blend_mode(draw_blend_mode_); layer->SetUseParentBackfaceVisibility(inputs_.use_parent_backface_visibility); layer->SetUseLocalTransformForBackfaceVisibility( use_local_transform_for_backface_visibility_); @@ -1181,6 +1181,9 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { ->property_trees() ->scroll_tree.SetScrollOffsetClobberActiveValue(layer->id()); + if (needs_show_scrollbars_) + layer->set_needs_show_scrollbars(true); + // If the main thread commits multiple times before the impl thread actually // draws, then damage tracking will become incorrect if we simply clobber the // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e. @@ -1189,13 +1192,10 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->SetUpdateRect(inputs_.update_rect); layer->SetHasWillChangeTransformHint(has_will_change_transform_hint()); - if (has_preferred_raster_bounds()) - layer->SetPreferredRasterBounds(preferred_raster_bounds()); - else - layer->ClearPreferredRasterBounds(); layer->SetNeedsPushProperties(); // Reset any state that should be cleared for the next update. + needs_show_scrollbars_ = false; subtree_property_changed_ = false; inputs_.update_rect = gfx::Rect(); @@ -1246,6 +1246,7 @@ void Layer::UpdateDrawsContent(bool has_drawable_content) { parent()->AddDrawableDescendants(draws_content ? 1 : -1); draws_content_ = draws_content; + SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -1342,77 +1343,6 @@ void Layer::OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) { // compositor-driven scrolling. } -void Layer::OnIsAnimatingChanged(const PropertyAnimationState& mask, - const PropertyAnimationState& state) { - DCHECK(layer_tree_host_); - PropertyTrees* property_trees = layer_tree_host_->property_trees(); - - TransformNode* transform_node = nullptr; - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id())) { - DCHECK_EQ(transform_tree_index(), - property_trees->layer_id_to_transform_node_index[id()]); - transform_node = - property_trees->transform_tree.Node(transform_tree_index()); - } - - EffectNode* effect_node = nullptr; - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, id())) { - DCHECK_EQ(effect_tree_index(), - property_trees->layer_id_to_effect_node_index[id()]); - effect_node = property_trees->effect_tree.Node(effect_tree_index()); - } - - for (int property = TargetProperty::FIRST_TARGET_PROPERTY; - property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) { - switch (property) { - case TargetProperty::TRANSFORM: - if (transform_node) { - if (mask.currently_running[property]) - transform_node->is_currently_animating = - state.currently_running[property]; - if (mask.potentially_animating[property]) { - transform_node->has_potential_animation = - state.potentially_animating[property]; - if (state.potentially_animating[property]) { - transform_node->has_only_translation_animations = - HasOnlyTranslationTransforms(); - } else { - transform_node->has_only_translation_animations = true; - } - property_trees->transform_tree.set_needs_update(true); - } - } - break; - case TargetProperty::OPACITY: - if (effect_node) { - if (mask.currently_running[property]) - effect_node->is_currently_animating_opacity = - state.currently_running[property]; - if (mask.potentially_animating[property]) { - effect_node->has_potential_opacity_animation = - state.potentially_animating[property] || - OpacityCanAnimateOnImplThread(); - property_trees->effect_tree.set_needs_update(true); - } - } - break; - case TargetProperty::FILTER: - if (effect_node) { - if (mask.currently_running[property]) - effect_node->is_currently_animating_filter = - state.currently_running[property]; - if (mask.potentially_animating[property]) - effect_node->has_potential_filter_animation = - state.potentially_animating[property]; - } - break; - default: - break; - } - } -} - bool Layer::HasTickingAnimationForTesting() const { return layer_tree_host_ ? GetMutatorHost()->HasTickingAnimationForTesting(element_id()) @@ -1426,24 +1356,6 @@ void Layer::SetHasWillChangeTransformHint(bool has_will_change) { SetNeedsCommit(); } -void Layer::SetPreferredRasterBounds(const gfx::Size& preferred_raster_bounds) { - if (inputs_.has_preferred_raster_bounds && - inputs_.preferred_raster_bounds == preferred_raster_bounds) - return; - - inputs_.has_preferred_raster_bounds = true; - inputs_.preferred_raster_bounds = preferred_raster_bounds; - SetNeedsCommit(); -} - -void Layer::ClearPreferredRasterBounds() { - if (!inputs_.has_preferred_raster_bounds) - return; - inputs_.has_preferred_raster_bounds = false; - inputs_.preferred_raster_bounds = gfx::Size(); - SetNeedsCommit(); -} - MutatorHost* Layer::GetMutatorHost() const { return layer_tree_host_ ? layer_tree_host_->mutator_host() : nullptr; } @@ -1530,7 +1442,7 @@ int Layer::num_copy_requests_in_target_subtree() { ->num_copy_requests_in_subtree; } -gfx::Transform Layer::screen_space_transform() const { +gfx::Transform Layer::ScreenSpaceTransform() const { DCHECK_NE(transform_tree_index_, TransformTree::kInvalidNodeId); return draw_property_utils::ScreenSpaceTransform( this, layer_tree_host_->property_trees()->transform_tree); diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h index c310377ed02..58dde9c4577 100644 --- a/chromium/cc/layers/layer.h +++ b/chromium/cc/layers/layer.h @@ -17,14 +17,14 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" -#include "cc/base/cc_export.h" +#include "cc/base/filter_operations.h" #include "cc/base/region.h" -#include "cc/debug/micro_benchmark.h" +#include "cc/benchmarks/micro_benchmark.h" +#include "cc/cc_export.h" #include "cc/input/input_handler.h" #include "cc/layers/layer_collections.h" #include "cc/layers/layer_position_constraint.h" #include "cc/layers/paint_properties.h" -#include "cc/output/filter_operations.h" #include "cc/paint/paint_record.h" #include "cc/trees/element_id.h" #include "cc/trees/mutator_host_client.h" @@ -132,14 +132,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { void SetBlendMode(SkBlendMode blend_mode); SkBlendMode blend_mode() const { return inputs_.blend_mode; } - void set_draw_blend_mode(SkBlendMode blend_mode) { - if (draw_blend_mode_ == blend_mode) - return; - draw_blend_mode_ = blend_mode; - SetNeedsPushProperties(); - } - SkBlendMode draw_blend_mode() const { return draw_blend_mode_; } - // A layer is root for an isolated group when it and all its descendants are // drawn over a black and fully transparent background, creating an isolated // group. It should be used along with SetBlendMode(), in order to restrict @@ -210,8 +202,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { return clip_children_.get(); } - // TODO(enne): Fix style here (and everywhere) once LayerImpl does the same. - gfx::Transform screen_space_transform() const; + gfx::Transform ScreenSpaceTransform() const; void set_num_unclipped_descendants(size_t descendants) { num_unclipped_descendants_ = descendants; @@ -404,6 +395,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { visible_layer_rect_ = rect; } + // This is for tracking damage. void SetSubtreePropertyChanged(); bool subtree_property_changed() const { return subtree_property_changed_; } @@ -424,30 +416,21 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { return inputs_.has_will_change_transform_hint; } - // The preferred raster bounds are the ideal resolution at which to raster the - // contents of this Layer's bitmap. This may not be the same size as the Layer - // bounds, in cases where the contents have an "intrinsic" size that differs. - // Consider for example an image with a given intrinsic size that is being - // scaled into a Layer of a different size. - void SetPreferredRasterBounds(const gfx::Size& preferred_Raster_bounds); - bool has_preferred_raster_bounds() const { - return inputs_.has_preferred_raster_bounds; - } - const gfx::Size& preferred_raster_bounds() const { - return inputs_.preferred_raster_bounds; - } - void ClearPreferredRasterBounds(); - MutatorHost* GetMutatorHost() const; ElementListType GetElementTypeForAnimation() const; void SetScrollbarsHiddenFromImplSide(bool hidden); + void set_is_scroll_clip_layer() { is_scroll_clip_layer_ = true; } + const gfx::Rect& update_rect() const { return inputs_.update_rect; } LayerTreeHost* layer_tree_host() const { return layer_tree_host_; } + // Called on the scroll layer to trigger showing the overlay scrollbars. + void ShowScrollbars() { needs_show_scrollbars_ = true; } + protected: friend class LayerImpl; friend class TreeSynchronizer; @@ -460,9 +443,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // immediately that a commit is required. This implies SetNeedsPushProperties // to push that property. void SetNeedsCommit(); - // This is identical to SetNeedsCommit, but the former requests a rebuild of - // the property trees. - void SetNeedsCommitNoRebuild(); + // Called when there's been a change in layer structure. Implies // SetNeedsCommit and property tree rebuld, but not SetNeedsPushProperties // (the full tree is synced over). @@ -491,7 +472,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { friend class base::RefCounted<Layer>; friend class LayerTreeHostCommon; friend class LayerTreeHost; - friend class LayerInternalsForTest; // Interactions with attached animations. gfx::ScrollOffset ScrollOffsetForAnimation() const; @@ -500,9 +480,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { void OnTransformAnimated(const gfx::Transform& transform); void OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset); - void OnIsAnimatingChanged(const PropertyAnimationState& mask, - const PropertyAnimationState& state); - bool FilterIsAnimating() const; bool TransformIsAnimating() const; bool ScrollOffsetAnimationWasInterrupted() const; @@ -532,6 +509,10 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // indices becomes invalid. void InvalidatePropertyTreesIndices(); + // This is set whenever a property changed on layer that affects whether this + // layer should own a property tree node or not. + void SetPropertyTreesNeedRebuild(); + // Encapsulates all data, callbacks or interfaces received from the embedder. // TODO(khushalsagar): This is only valid when PropertyTrees are built // internally in cc. Update this for the SPv2 path where blink generates @@ -612,7 +593,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { Layer* clip_parent; bool has_will_change_transform_hint : 1; - bool has_preferred_raster_bounds : 1; bool hide_layer_and_subtree : 1; @@ -620,8 +600,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { LayerClient* client; base::Callback<void(const gfx::ScrollOffset&)> did_scroll_callback; std::vector<std::unique_ptr<CopyOutputRequest>> copy_requests; - - gfx::Size preferred_raster_bounds; }; Layer* parent_; @@ -647,10 +625,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { bool force_render_surface_for_testing_ : 1; bool subtree_property_changed_ : 1; bool may_contain_video_ : 1; + bool is_scroll_clip_layer_ : 1; + bool needs_show_scrollbars_ : 1; SkColor safe_opaque_background_color_; - // draw_blend_mode may be different than blend_mode_, - // when a RenderSurface re-parents the layer's blend_mode. - SkBlendMode draw_blend_mode_; std::unique_ptr<std::set<Layer*>> scroll_children_; std::unique_ptr<std::set<Layer*>> clip_children_; diff --git a/chromium/cc/layers/layer_client.h b/chromium/cc/layers/layer_client.h index 165c4367389..85c97722c0d 100644 --- a/chromium/cc/layers/layer_client.h +++ b/chromium/cc/layers/layer_client.h @@ -7,7 +7,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { namespace trace_event { diff --git a/chromium/cc/layers/layer_collections.h b/chromium/cc/layers/layer_collections.h index 23c6c10d0a1..c7a2b746205 100644 --- a/chromium/cc/layers/layer_collections.h +++ b/chromium/cc/layers/layer_collections.h @@ -10,7 +10,7 @@ #include <vector> #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { class Layer; diff --git a/chromium/cc/layers/layer_impl.cc b/chromium/cc/layers/layer_impl.cc index 010df135a98..b9f9b993e91 100644 --- a/chromium/cc/layers/layer_impl.cc +++ b/chromium/cc/layers/layer_impl.cc @@ -18,9 +18,9 @@ #include "base/trace_event/trace_event_argument.h" #include "cc/base/math_util.h" #include "cc/base/simple_enclosed_region.h" +#include "cc/benchmarks/micro_benchmark_impl.h" #include "cc/debug/debug_colors.h" #include "cc/debug/layer_tree_debug_state.h" -#include "cc/debug/micro_benchmark_impl.h" #include "cc/debug/traced_value.h" #include "cc/input/main_thread_scrolling_reason.h" #include "cc/input/scroll_state.h" @@ -70,7 +70,6 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id) was_ever_ready_since_last_transform_animation_(true), background_color_(0), safe_opaque_background_color_(0), - draw_blend_mode_(SkBlendMode::kSrcOver), transform_tree_index_(TransformTree::kInvalidNodeId), effect_tree_index_(EffectTree::kInvalidNodeId), clip_tree_index_(ClipTree::kInvalidNodeId), @@ -78,10 +77,10 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id) current_draw_mode_(DRAW_MODE_NONE), mutable_properties_(MutableProperty::kNone), debug_info_(nullptr), - has_preferred_raster_bounds_(false), has_will_change_transform_hint_(false), needs_push_properties_(false), - scrollbars_hidden_(false) { + scrollbars_hidden_(false), + needs_show_scrollbars_(false) { DCHECK_GT(layer_id_, 0); DCHECK(layer_tree_impl_); @@ -107,16 +106,6 @@ void LayerImpl::SetHasWillChangeTransformHint(bool has_will_change) { has_will_change_transform_hint_ = has_will_change; } -void LayerImpl::SetPreferredRasterBounds( - const gfx::Size& preferred_raster_bounds) { - has_preferred_raster_bounds_ = true; - preferred_raster_bounds_ = preferred_raster_bounds; -} - -void LayerImpl::ClearPreferredRasterBounds() { - has_preferred_raster_bounds_ = false; - preferred_raster_bounds_ = gfx::Size(); -} MutatorHost* LayerImpl::GetMutatorHost() const { return layer_tree_impl_ ? layer_tree_impl_->mutator_host() : nullptr; @@ -161,7 +150,7 @@ void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const { 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_blend_mode_, GetSortingContextId()); + SkBlendMode::kSrcOver, GetSortingContextId()); } void LayerImpl::PopulateScaledSharedQuadState( @@ -180,7 +169,7 @@ void LayerImpl::PopulateScaledSharedQuadState( state->SetAll(scaled_draw_transform, scaled_bounds, scaled_visible_layer_rect, draw_properties().clip_rect, draw_properties().is_clipped, - draw_properties().opacity, draw_blend_mode_, + draw_properties().opacity, SkBlendMode::kSrcOver, GetSortingContextId()); } @@ -198,25 +187,28 @@ void LayerImpl::DidDraw(ResourceProvider* resource_provider) { current_draw_mode_ = DRAW_MODE_NONE; } -bool LayerImpl::ShowDebugBorders() const { - return layer_tree_impl()->debug_state().show_debug_borders; +bool LayerImpl::ShowDebugBorders(DebugBorderType type) const { + return layer_tree_impl()->debug_state().show_debug_borders.test(type); } void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const { + float device_scale_factor = + layer_tree_impl() ? layer_tree_impl()->device_scale_factor() : 1; + if (draws_content_) { *color = DebugColors::ContentLayerBorderColor(); - *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl()); + *width = DebugColors::ContentLayerBorderWidth(device_scale_factor); return; } if (masks_to_bounds_) { *color = DebugColors::MaskingLayerBorderColor(); - *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl()); + *width = DebugColors::MaskingLayerBorderWidth(device_scale_factor); return; } *color = DebugColors::ContainerLayerBorderColor(); - *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl()); + *width = DebugColors::ContainerLayerBorderWidth(device_scale_factor); } void LayerImpl::AppendDebugBorderQuad( @@ -237,7 +229,7 @@ void LayerImpl::AppendDebugBorderQuad(RenderPass* render_pass, AppendQuadsData* append_quads_data, SkColor color, float width) const { - if (!ShowDebugBorders()) + if (!ShowDebugBorders(DebugBorderType::LAYER)) return; gfx::Rect quad_rect(bounds); @@ -338,7 +330,6 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->touch_event_handler_region_ = touch_event_handler_region_; layer->background_color_ = background_color_; layer->safe_opaque_background_color_ = safe_opaque_background_color_; - layer->draw_blend_mode_ = draw_blend_mode_; layer->position_ = position_; layer->transform_tree_index_ = transform_tree_index_; layer->effect_tree_index_ = effect_tree_index_; @@ -346,6 +337,7 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->scroll_tree_index_ = scroll_tree_index_; layer->has_will_change_transform_hint_ = has_will_change_transform_hint_; layer->scrollbars_hidden_ = scrollbars_hidden_; + layer->needs_show_scrollbars_ = needs_show_scrollbars_; if (layer_property_changed_) { layer->layer_tree_impl()->set_needs_update_draw_properties(); @@ -368,6 +360,7 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->SetDebugInfo(std::move(owned_debug_info_)); // Reset any state that should be cleared for the next update. + needs_show_scrollbars_ = false; layer_property_changed_ = false; needs_push_properties_ = false; update_rect_ = gfx::Rect(); @@ -394,23 +387,23 @@ std::unique_ptr<base::DictionaryValue> LayerImpl::LayerTreeAsJson() { result->SetInteger("LayerId", id()); result->SetString("LayerType", LayerTypeAsString()); - base::ListValue* list = new base::ListValue; + auto list = base::MakeUnique<base::ListValue>(); list->AppendInteger(bounds().width()); list->AppendInteger(bounds().height()); - result->Set("Bounds", list); + result->Set("Bounds", std::move(list)); - list = new base::ListValue; + list = base::MakeUnique<base::ListValue>(); list->AppendDouble(position_.x()); list->AppendDouble(position_.y()); - result->Set("Position", list); + result->Set("Position", std::move(list)); const gfx::Transform& gfx_transform = test_properties()->transform; double transform[16]; gfx_transform.matrix().asColMajord(transform); - list = new base::ListValue; + list = base::MakeUnique<base::ListValue>(); for (int i = 0; i < 16; ++i) list->AppendDouble(transform[i]); - result->Set("Transform", list); + result->Set("Transform", std::move(list)); result->SetBoolean("DrawsContent", draws_content_); result->SetBoolean("Is3dSorted", Is3dSorted()); @@ -422,13 +415,13 @@ std::unique_ptr<base::DictionaryValue> LayerImpl::LayerTreeAsJson() { if (!touch_event_handler_region_.IsEmpty()) { std::unique_ptr<base::Value> region = touch_event_handler_region_.AsValue(); - result->Set("TouchRegion", region.release()); + result->Set("TouchRegion", std::move(region)); } - list = new base::ListValue; + list = base::MakeUnique<base::ListValue>(); for (size_t i = 0; i < test_properties()->children.size(); ++i) list->Append(test_properties()->children[i]->LayerTreeAsJson()); - result->Set("Children", list); + result->Set("Children", std::move(list)); return result; } @@ -483,43 +476,21 @@ int LayerImpl::num_copy_requests_in_target_subtree() { ->num_copy_requests_in_subtree; } -void LayerImpl::UpdatePropertyTreeTransformIsAnimated(bool is_animated) { - PropertyTrees* property_trees = GetPropertyTrees(); - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id())) { - TransformTree& transform_tree = GetTransformTree(); - TransformNode* node = transform_tree.Node( - property_trees->layer_id_to_transform_node_index[id()]); - // A LayerImpl's own current state is insufficient for determining whether - // it owns a TransformNode, since this depends on the state of the - // corresponding Layer at the time of the last commit. For example, if - // |is_animated| is false, this might mean a transform animation just ticked - // past its finish point (so the LayerImpl still owns a TransformNode) or it - // might mean that a transform animation was removed during commit or - // activation (and, in that case, the LayerImpl will no longer own a - // TransformNode, unless it has non-animation-related reasons for owning a - // node). - if (node->has_potential_animation != is_animated) { - node->has_potential_animation = is_animated; - if (is_animated) { - node->has_only_translation_animations = HasOnlyTranslationTransforms(); - } else { - node->has_only_translation_animations = true; - } - - transform_tree.set_needs_update(true); - layer_tree_impl()->set_needs_update_draw_properties(); - } - } -} - void LayerImpl::UpdatePropertyTreeForScrollingAndAnimationIfNeeded() { if (scrollable()) UpdatePropertyTreeScrollOffset(); if (HasAnyAnimationTargetingProperty(TargetProperty::TRANSFORM)) { - UpdatePropertyTreeTransformIsAnimated( - HasPotentiallyRunningTransformAnimation()); + if (TransformNode* node = + GetTransformTree().FindNodeFromElementId(element_id())) { + bool has_potential_animation = HasPotentiallyRunningTransformAnimation(); + if (node->has_potential_animation != has_potential_animation) { + node->has_potential_animation = has_potential_animation; + node->has_only_translation_animations = HasOnlyTranslationTransforms(); + GetTransformTree().set_needs_update(true); + layer_tree_impl()->set_needs_update_draw_properties(); + } + } } } @@ -527,67 +498,6 @@ gfx::ScrollOffset LayerImpl::ScrollOffsetForAnimation() const { return CurrentScrollOffset(); } -void LayerImpl::OnIsAnimatingChanged(const PropertyAnimationState& mask, - const PropertyAnimationState& state) { - DCHECK(layer_tree_impl_); - PropertyTrees* property_trees = GetPropertyTrees(); - - TransformNode* transform_node = nullptr; - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id())) { - transform_node = GetTransformTree().Node( - property_trees->layer_id_to_transform_node_index[id()]); - } - - EffectNode* effect_node = nullptr; - if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, id())) { - effect_node = GetEffectTree().Node( - property_trees->layer_id_to_effect_node_index[id()]); - } - - for (int property = TargetProperty::FIRST_TARGET_PROPERTY; - property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) { - switch (property) { - case TargetProperty::TRANSFORM: - if (transform_node) { - if (mask.currently_running[property]) - transform_node->is_currently_animating = - state.currently_running[property]; - if (mask.potentially_animating[property]) { - UpdatePropertyTreeTransformIsAnimated( - state.potentially_animating[property]); - was_ever_ready_since_last_transform_animation_ = false; - } - } - break; - case TargetProperty::OPACITY: - if (effect_node) { - if (mask.currently_running[property]) - effect_node->is_currently_animating_opacity = - state.currently_running[property]; - if (mask.potentially_animating[property]) { - effect_node->has_potential_opacity_animation = - state.potentially_animating[property]; - GetEffectTree().set_needs_update(true); - } - } - break; - case TargetProperty::FILTER: - if (effect_node) { - if (mask.currently_running[property]) - effect_node->is_currently_animating_filter = - state.currently_running[property]; - if (mask.potentially_animating[property]) - effect_node->has_potential_filter_animation = - state.potentially_animating[property]; - } - break; - default: - break; - } - } -} - bool LayerImpl::IsActive() const { return layer_tree_impl_->IsActiveTree(); } @@ -633,10 +543,9 @@ void LayerImpl::SetBoundsDelta(const gfx::Vector2dF& bounds_delta) { if (masks_to_bounds()) { // If layer is clipping, then update the clip node using the new bounds. - ClipNode* clip_node = property_trees->clip_tree.Node(clip_tree_index()); - if (clip_node) { - DCHECK(property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::CLIP, - id())); + if (ClipNode* clip_node = + property_trees->clip_tree.UpdateNodeFromOwningLayerId(id())) { + DCHECK_EQ(clip_node->id, clip_tree_index()); clip_node->clip = gfx::RectF(gfx::PointF() + offset_to_transform_parent(), gfx::SizeF(bounds())); property_trees->clip_tree.set_needs_update(true); @@ -700,21 +609,15 @@ void LayerImpl::SetContentsOpaque(bool opaque) { } float LayerImpl::Opacity() const { - PropertyTrees* property_trees = GetPropertyTrees(); - if (!property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, id())) + if (const EffectNode* node = GetEffectTree().FindNodeFromOwningLayerId(id())) + return node->opacity; + else return 1.f; - EffectNode* node = - GetEffectTree().Node(property_trees->layer_id_to_effect_node_index[id()]); - return node->opacity; } const gfx::Transform& LayerImpl::Transform() const { - PropertyTrees* property_trees = GetPropertyTrees(); - DCHECK(property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id())); - TransformNode* node = GetTransformTree().Node( - property_trees->layer_id_to_transform_node_index[id()]); - return node->local; + DCHECK_NE(GetTransformTree().FindNodeFromOwningLayerId(id()), nullptr); + return GetTransformTree().FindNodeFromOwningLayerId(id())->local; } void LayerImpl::SetElementId(ElementId element_id) { @@ -818,6 +721,11 @@ void LayerImpl::UpdatePropertyTreeScrollOffset() { // directly instead of going through layers. TransformTree& transform_tree = GetTransformTree(); TransformNode* node = transform_tree.Node(transform_tree_index_); + DCHECK(node); + // TODO(pdr): This is a workaround for https://crbug.com/712298 to avoid + // crashing when there's no transform node. This workaround should be removed. + if (!node) + return; gfx::ScrollOffset current_offset = CurrentScrollOffset(); if (node->scroll_offset != current_offset) { node->scroll_offset = current_offset; @@ -1039,11 +947,6 @@ const RenderSurfaceImpl* LayerImpl::render_target() const { return GetEffectTree().GetRenderSurface(render_target_effect_tree_index()); } -bool LayerImpl::IsHidden() const { - EffectNode* node = GetEffectTree().Node(effect_tree_index_); - return node->screen_space_opacity == 0.f; -} - float LayerImpl::GetIdealContentsScale() const { float page_scale = IsAffectedByPageScale() ? layer_tree_impl()->current_page_scale_factor() @@ -1066,6 +969,10 @@ PropertyTrees* LayerImpl::GetPropertyTrees() const { return layer_tree_impl_->property_trees(); } +ClipTree& LayerImpl::GetClipTree() const { + return GetPropertyTrees()->clip_tree; +} + EffectTree& LayerImpl::GetEffectTree() const { return GetPropertyTrees()->effect_tree; } @@ -1078,4 +985,26 @@ TransformTree& LayerImpl::GetTransformTree() const { return GetPropertyTrees()->transform_tree; } +bool LayerImpl::HasValidPropertyTreeIndices() const { + // TODO(crbug.com/726423): LayerImpls should never have invalid PropertyTree + // indices. + const bool has_valid_transform_node = + !!GetTransformTree().Node(transform_tree_index()); + DCHECK(has_valid_transform_node); + + const bool has_valid_effect_node = + !!GetEffectTree().Node(effect_tree_index()); + DCHECK(has_valid_effect_node); + + const bool has_valid_clip_node = !!GetClipTree().Node(clip_tree_index()); + DCHECK(has_valid_clip_node); + + const bool has_valid_scroll_node = + !!GetScrollTree().Node(scroll_tree_index()); + DCHECK(has_valid_scroll_node); + + return has_valid_transform_node && has_valid_effect_node && + has_valid_clip_node && has_valid_scroll_node; +} + } // namespace cc diff --git a/chromium/cc/layers/layer_impl.h b/chromium/cc/layers/layer_impl.h index 396cda82c13..d976ae50045 100644 --- a/chromium/cc/layers/layer_impl.h +++ b/chromium/cc/layers/layer_impl.h @@ -18,9 +18,10 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/values.h" -#include "cc/base/cc_export.h" #include "cc/base/region.h" #include "cc/base/synced_property.h" +#include "cc/cc_export.h" +#include "cc/debug/layer_tree_debug_state.h" #include "cc/input/input_handler.h" #include "cc/layers/draw_properties.h" #include "cc/layers/layer_collections.h" @@ -51,6 +52,7 @@ class DictionaryValue; namespace cc { +class AppendQuadsData; class LayerTreeImpl; class MicroBenchmarkImpl; class MutatorHost; @@ -60,7 +62,6 @@ class ScrollbarLayerImplBase; class SimpleEnclosedRegion; class Tile; -struct AppendQuadsData; enum DrawMode { DRAW_MODE_NONE, @@ -85,8 +86,6 @@ class CC_EXPORT LayerImpl { // Interactions with attached animations. gfx::ScrollOffset ScrollOffsetForAnimation() const; - void OnIsAnimatingChanged(const PropertyAnimationState& mask, - const PropertyAnimationState& state); bool IsActive() const; void set_property_tree_sequence_number(int sequence_number) {} @@ -120,7 +119,6 @@ class CC_EXPORT LayerImpl { bool is_clipped() const { return draw_properties_.is_clipped; } - void UpdatePropertyTreeTransformIsAnimated(bool is_animated); void UpdatePropertyTreeScrollOffset(); LayerTreeImpl* layer_tree_impl() const { return layer_tree_impl_; } @@ -190,11 +188,6 @@ class CC_EXPORT LayerImpl { void SetMutableProperties(uint32_t properties); uint32_t mutable_properties() const { return mutable_properties_; } - void set_draw_blend_mode(SkBlendMode blend_mode) { - draw_blend_mode_ = blend_mode; - } - SkBlendMode draw_blend_mode() const { return draw_blend_mode_; } - void SetPosition(const gfx::PointF& position); gfx::PointF position() const { return position_; } @@ -225,8 +218,11 @@ class CC_EXPORT LayerImpl { return should_check_backface_visibility_; } - bool ShowDebugBorders() const; + bool ShowDebugBorders(DebugBorderType type) const; + // TODO(http://crbug.com/557160): Currently SPv2 creates dummy layers for the + // sole purpose of representing a render surface. Once that dependency is + // removed, also remove dummy layers from PaintArtifactCompositor. RenderSurfaceImpl* GetRenderSurface() const; // The render surface which this layer draws into. This can be either owned by @@ -416,8 +412,6 @@ class CC_EXPORT LayerImpl { void UpdatePropertyTreeForScrollingAndAnimationIfNeeded(); - bool IsHidden() const; - float GetIdealContentsScale() const; bool was_ever_ready_since_last_transform_animation() const { @@ -435,19 +429,15 @@ class CC_EXPORT LayerImpl { return has_will_change_transform_hint_; } - void SetPreferredRasterBounds(const gfx::Size& preferred_raster_bounds); - bool has_preferred_raster_bounds() const { - return has_preferred_raster_bounds_; - } - const gfx::Size& preferred_raster_scale() const { - return preferred_raster_bounds_; - } - void ClearPreferredRasterBounds(); - MutatorHost* GetMutatorHost() const; ElementListType GetElementTypeForAnimation() const; + void set_needs_show_scrollbars(bool yes) { needs_show_scrollbars_ = yes; } + bool needs_show_scrollbars() { return needs_show_scrollbars_; } + + bool HasValidPropertyTreeIndices() const; + protected: LayerImpl(LayerTreeImpl* layer_impl, int id, @@ -520,7 +510,6 @@ class CC_EXPORT LayerImpl { SkColor background_color_; SkColor safe_opaque_background_color_; - SkBlendMode draw_blend_mode_; gfx::PointF position_; gfx::Rect clip_rect_in_target_space_; @@ -536,6 +525,7 @@ class CC_EXPORT LayerImpl { private: PropertyTrees* GetPropertyTrees() const; + ClipTree& GetClipTree() const; EffectTree& GetEffectTree() const; ScrollTree& GetScrollTree() const; TransformTree& GetTransformTree() const; @@ -559,18 +549,16 @@ class CC_EXPORT LayerImpl { std::unique_ptr<base::trace_event::ConvertableToTraceFormat> owned_debug_info_; base::trace_event::ConvertableToTraceFormat* debug_info_; - // TODO(http://crbug.com/557160): EffectNode instead of LayerImpl should - // own RenderSurfaceImpl. Currently SPv2 creates dummy layers for the sole - // purpose of holding a render surface. Once done, remember to remove dummy - // layers from PaintArtifactCompositor as well - std::unique_ptr<RenderSurfaceImpl> render_surface_; - gfx::Size preferred_raster_bounds_; - - bool has_preferred_raster_bounds_ : 1; + bool has_will_change_transform_hint_ : 1; bool needs_push_properties_ : 1; bool scrollbars_hidden_ : 1; + // The needs_show_scrollbars_ bit tracks a pending request from Blink to show + // the overlay scrollbars. It's set on the scroll layer (not the scrollbar + // layers) and consumed by LayerTreeImpl::PushPropertiesTo during activation. + bool needs_show_scrollbars_ : 1; + DISALLOW_COPY_AND_ASSIGN(LayerImpl); }; diff --git a/chromium/cc/layers/layer_impl_test_properties.cc b/chromium/cc/layers/layer_impl_test_properties.cc index ee0339b3aa6..2ae194db2aa 100644 --- a/chromium/cc/layers/layer_impl_test_properties.cc +++ b/chromium/cc/layers/layer_impl_test_properties.cc @@ -18,9 +18,7 @@ LayerImplTestProperties::LayerImplTestProperties(LayerImpl* owning_layer) should_flatten_transform(true), hide_layer_and_subtree(false), opacity_can_animate(false), - num_descendants_that_draw_content(0), sorting_context_id(0), - num_unclipped_descendants(0), opacity(1.f), blend_mode(SkBlendMode::kSrcOver), scroll_parent(nullptr), diff --git a/chromium/cc/layers/layer_impl_test_properties.h b/chromium/cc/layers/layer_impl_test_properties.h index 6ca6d759ae6..5f4fd66f2db 100644 --- a/chromium/cc/layers/layer_impl_test_properties.h +++ b/chromium/cc/layers/layer_impl_test_properties.h @@ -9,10 +9,10 @@ #include <vector> #include "base/memory/ptr_util.h" +#include "cc/base/filter_operations.h" #include "cc/layers/layer_collections.h" #include "cc/layers/layer_position_constraint.h" #include "cc/layers/layer_sticky_position_constraint.h" -#include "cc/output/filter_operations.h" #include "third_party/skia/include/core/SkBlendMode.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/transform.h" @@ -37,9 +37,7 @@ struct CC_EXPORT LayerImplTestProperties { bool should_flatten_transform; bool hide_layer_and_subtree; bool opacity_can_animate; - int num_descendants_that_draw_content; int sorting_context_id; - size_t num_unclipped_descendants; float opacity; FilterOperations filters; FilterOperations background_filters; diff --git a/chromium/cc/layers/layer_impl_unittest.cc b/chromium/cc/layers/layer_impl_unittest.cc index b51fae0069a..2180d540d58 100644 --- a/chromium/cc/layers/layer_impl_unittest.cc +++ b/chromium/cc/layers/layer_impl_unittest.cc @@ -4,10 +4,10 @@ #include "cc/layers/layer_impl.h" +#include "cc/base/filter_operation.h" +#include "cc/base/filter_operations.h" #include "cc/layers/painted_scrollbar_layer_impl.h" #include "cc/layers/solid_color_scrollbar_layer_impl.h" -#include "cc/output/filter_operation.h" -#include "cc/output/filter_operations.h" #include "cc/test/animation_test_common.h" #include "cc/test/fake_compositor_frame_sink.h" #include "cc/test/fake_impl_task_runner_provider.h" @@ -139,6 +139,7 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { host_impl.active_tree()->SetRootLayerForTesting(std::move(root_clip_ptr)); root->test_properties()->force_render_surface = true; + root->SetMasksToBounds(true); root->layer_tree_impl()->ResetAllChangeTracking(); root->test_properties()->AddChild( @@ -178,23 +179,17 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { // Changing these properties affects the entire subtree of layers. EXECUTE_AND_VERIFY_NO_NEED_TO_PUSH_PROPERTIES_AND_SUBTREE_CHANGED( - host_impl.active_tree()->property_trees()->effect_tree.OnFilterAnimated( - arbitrary_filters, root->effect_tree_index(), - host_impl.active_tree())); + host_impl.active_tree()->SetFilterMutated(root->element_id(), + arbitrary_filters)); EXECUTE_AND_VERIFY_NO_NEED_TO_PUSH_PROPERTIES_AND_SUBTREE_CHANGED( - host_impl.active_tree()->property_trees()->effect_tree.OnFilterAnimated( - FilterOperations(), root->effect_tree_index(), - host_impl.active_tree())); + host_impl.active_tree()->SetFilterMutated(root->element_id(), + FilterOperations())); EXECUTE_AND_VERIFY_NO_NEED_TO_PUSH_PROPERTIES_AND_SUBTREE_CHANGED( - host_impl.active_tree()->property_trees()->effect_tree.OnOpacityAnimated( - arbitrary_number, root->effect_tree_index(), - host_impl.active_tree())); + host_impl.active_tree()->SetOpacityMutated(root->element_id(), + arbitrary_number)); EXECUTE_AND_VERIFY_NO_NEED_TO_PUSH_PROPERTIES_AND_SUBTREE_CHANGED( - host_impl.active_tree() - ->property_trees() - ->transform_tree.OnTransformAnimated(arbitrary_transform, - root->transform_tree_index(), - host_impl.active_tree())); + host_impl.active_tree()->SetTransformMutated(root->element_id(), + arbitrary_transform)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->ScrollBy(arbitrary_vector2d); root->SetNeedsPushProperties()); // SetBoundsDelta changes subtree only when masks_to_bounds is true and it @@ -283,22 +278,15 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { host_impl.active_tree()->BuildLayerListAndPropertyTreesForTesting(); // Related filter functions. - VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( - host_impl.active_tree()->property_trees()->effect_tree.OnFilterAnimated( - arbitrary_filters, root->effect_tree_index(), - host_impl.active_tree())); + VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(host_impl.active_tree()->SetFilterMutated( + root->element_id(), arbitrary_filters)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( - host_impl.active_tree()->property_trees()->effect_tree.OnFilterAnimated( - arbitrary_filters, root->effect_tree_index(), - host_impl.active_tree())); - VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( - host_impl.active_tree()->property_trees()->effect_tree.OnFilterAnimated( - FilterOperations(), root->effect_tree_index(), - host_impl.active_tree())); - VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( - host_impl.active_tree()->property_trees()->effect_tree.OnFilterAnimated( - arbitrary_filters, root->effect_tree_index(), - host_impl.active_tree())); + host_impl.active_tree()->SetFilterMutated(root->element_id(), + arbitrary_filters)); + VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(host_impl.active_tree()->SetFilterMutated( + root->element_id(), FilterOperations())); + VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(host_impl.active_tree()->SetFilterMutated( + root->element_id(), arbitrary_filters)); // Related scrolling functions. VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetBounds(large_size)); @@ -332,15 +320,11 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( layer->SetBackgroundColor(arbitrary_color)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( - host_impl.active_tree()->property_trees()->effect_tree.OnOpacityAnimated( - arbitrary_number, layer->effect_tree_index(), - host_impl.active_tree())); + host_impl.active_tree()->SetOpacityMutated(layer->element_id(), + arbitrary_number)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( - host_impl.active_tree() - ->property_trees() - ->transform_tree.OnTransformAnimated(arbitrary_transform, - layer->transform_tree_index(), - host_impl.active_tree())); + host_impl.active_tree()->SetTransformMutated(layer->element_id(), + arbitrary_transform)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetBounds(arbitrary_size); layer->NoteLayerPropertyChanged()); @@ -348,9 +332,8 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { layer->test_properties()->filters = arbitrary_filters; host_impl.active_tree()->BuildLayerListAndPropertyTreesForTesting(); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( - host_impl.active_tree()->property_trees()->effect_tree.OnFilterAnimated( - arbitrary_filters, layer->effect_tree_index(), - host_impl.active_tree())); + host_impl.active_tree()->SetFilterMutated(layer->element_id(), + arbitrary_filters)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetMasksToBounds(true)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetContentsOpaque(true)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( @@ -443,7 +426,6 @@ class LayerImplScrollTest : public testing::Test { LayerTreeSettings settings() { LayerTreeSettings settings; - settings.verify_clip_tree_calculations = true; return settings; } diff --git a/chromium/cc/layers/layer_iterator.h b/chromium/cc/layers/layer_iterator.h deleted file mode 100644 index 9eb822415fa..00000000000 --- a/chromium/cc/layers/layer_iterator.h +++ /dev/null @@ -1,291 +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_LAYER_ITERATOR_H_ -#define CC_LAYERS_LAYER_ITERATOR_H_ - -#include <stddef.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 -// RenderSurfaceImpl-LayerImpl tree. - -// Example code follows, for a tree of LayerImpl/RenderSurfaceImpl objects. -// See below for details. -// -// void DoStuffOnLayers( -// const LayerImplList& 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 -// if (it.represents_target_render_surface()) -// foo(*it); // *it is a layer representing a target RenderSurface -// if (it.represents_contributing_render_surface()) -// bar(*it); // *it is a layer representing a RenderSurface that -// // contributes to the layer's target RenderSurface -// if (it.represents_itself()) -// baz(*it); // *it is a layer representing itself, -// // as it contributes to its own target RenderSurface -// } -// } - -// A RenderSurface R may be referred to in one of two different contexts. -// One RenderSurface is "current" at any time, for whatever operation -// is being performed. This current surface is referred to as a target surface. -// For example, when R is being painted it would be the target surface. -// Once R has been painted, its contents may be included into another -// surface S. While S is considered the target surface when it is being -// painted, R is called a contributing surface in this context as it -// contributes to the content of the target surface S. -// -// The iterator's current position in the tree always points to some layer. -// The state of the iterator indicates the role of the layer, -// and will be one of the following three states. -// A single layer L will appear in the iteration process in at least one, -// and possibly all, of these states. -// 1. Representing the target surface: The iterator in this state, -// pointing at layer L, indicates that the target RenderSurface -// is now the surface owned by L. This will occur exactly once for each -// RenderSurface in the tree. -// 2. Representing a contributing surface: The iterator in this state, -// pointing at layer L, refers to the RenderSurface owned -// by L as a contributing surface, without changing the current -// target RenderSurface. -// 3. Representing itself: The iterator in this state, pointing at layer L, -// refers to the layer itself, as a child of the -// current target RenderSurface. -// -// The FrontToBack iterator will iterate over children layers of a surface -// before the layer representing the surface as a target surface. -// -// To use the iterators: -// -// Create a stepping iterator and end iterator by calling -// LayerIterator::Begin() and LayerIterator::End() and passing in the -// list of layers owning target RenderSurfaces. Step through the tree -// by incrementing the stepping iterator while it is != to -// the end iterator. At each step the iterator knows what the layer -// is representing, and you can query the iterator to decide -// what actions to perform with the layer given what it represents. - -//////////////////////////////////////////////////////////////////////////////// - -struct LayerIteratorValue { - static const int kInvalidTargetRenderSurfaceLayerIndex = -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. -struct LayerIteratorPosition { - bool represents_target_render_surface; - bool represents_contributing_render_surface; - bool represents_itself; - LayerImpl* target_render_surface_layer; - LayerImpl* current_layer; -}; - -// An iterator class for walking over layers in the -// RenderSurface-Layer tree. -// TODO(enne): This class probably shouldn't be entirely inline and -// should get moved to a .cc file where it makes sense. -class LayerIterator { - public: - LayerIterator() : render_surface_layer_list_(nullptr) {} - - static LayerIterator Begin(const LayerImplList* render_surface_layer_list) { - return LayerIterator(render_surface_layer_list, true); - } - static LayerIterator End(const LayerImplList* render_surface_layer_list) { - return LayerIterator(render_surface_layer_list, false); - } - - LayerIterator& operator++() { - MoveToNext(); - return *this; - } - bool operator==(const LayerIterator& other) const { - return target_render_surface_layer_index_ == - other.target_render_surface_layer_index_ && - current_layer_index_ == other.current_layer_index_; - } - bool operator!=(const LayerIterator& other) const { - return !(*this == other); - } - - 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(); - } - bool represents_contributing_render_surface() const { - return !represents_target_render_surface() && - current_layer_represents_contributing_render_surface(); - } - bool represents_itself() const { - return !represents_target_render_surface() && - !represents_contributing_render_surface(); - } - - LayerImpl* target_render_surface_layer() const { - return render_surface_layer_list_->at(target_render_surface_layer_index_); - } - - operator const LayerIteratorPosition() const { - LayerIteratorPosition position; - position.represents_target_render_surface = - represents_target_render_surface(); - position.represents_contributing_render_surface = - represents_contributing_render_surface(); - position.represents_itself = represents_itself(); - position.target_render_surface_layer = target_render_surface_layer(); - position.current_layer = current_layer(); - return position; - } - - private: - 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) { - if (!render_surface_layer_list->at(i)->GetRenderSurface()) { - NOTREACHED(); - MoveToEnd(); - return; - } - } - - if (start && !render_surface_layer_list->empty()) - MoveToBegin(); - else - MoveToEnd(); - } - - void MoveToBegin() { - target_render_surface_layer_index_ = 0; - current_layer_index_ = target_render_surface_children().size() - 1; - MoveToHighestInSubtree(); - } - - void MoveToEnd() { - target_render_surface_layer_index_ = - LayerIteratorValue::kInvalidTargetRenderSurfaceLayerIndex; - current_layer_index_ = 0; - } - - void MoveToNext() { - // Moves to the previous layer in the current RS layer list. - // Then we check if the new current layer has its own RS, - // in which case there are things in that RS layer list that are higher, - // so we find the highest layer in that subtree. - // If we move back past the front of the list, - // we jump up to the previous RS layer list, picking up again where we - // had previously recursed into the current RS layer list. - - if (!current_layer_represents_target_render_surface()) { - // Subtracting one here will eventually cause the current layer - // to become that layer representing the target render surface. - --current_layer_index_; - MoveToHighestInSubtree(); - } else { - while (current_layer_represents_target_render_surface()) { - if (!target_render_surface_layer_index_) { - // End of the list. - target_render_surface_layer_index_ = - LayerIteratorValue::kInvalidTargetRenderSurfaceLayerIndex; - current_layer_index_ = 0; - return; - } - target_render_surface_layer_index_ = - target_render_surface()->target_render_surface_layer_index_history_; - current_layer_index_ = - target_render_surface()->current_layer_index_history_; - } - } - } - - void MoveToHighestInSubtree() { - if (current_layer_represents_target_render_surface()) - return; - while (current_layer_represents_contributing_render_surface()) { - // Save where we were in the current target surface, move to the next one, - // and save the target surface that we came from there - // so we can go back to it. - target_render_surface()->current_layer_index_history_ = - current_layer_index_; - int previous_target_render_surface_layer = - target_render_surface_layer_index_; - - for (LayerImpl* layer = current_layer(); - target_render_surface_layer() != layer; - ++target_render_surface_layer_index_) { - } - current_layer_index_ = target_render_surface_children().size() - 1; - - target_render_surface()->target_render_surface_layer_index_history_ = - previous_target_render_surface_layer; - } - } - - inline LayerImpl* current_layer() const { - return current_layer_represents_target_render_surface() - ? target_render_surface_layer() - : target_render_surface_children().at(current_layer_index_); - } - - inline bool current_layer_represents_contributing_render_surface() const { - RenderSurfaceImpl* render_surface = current_layer()->GetRenderSurface(); - return render_surface && render_surface != target_render_surface(); - } - inline bool current_layer_represents_target_render_surface() const { - return current_layer_index_ == - LayerIteratorValue::kLayerIndexRepresentingTargetRenderSurface; - } - - inline RenderSurfaceImpl* target_render_surface() const { - return target_render_surface_layer()->GetRenderSurface(); - } - inline const LayerImplList& target_render_surface_children() const { - return target_render_surface()->layer_list(); - } - - const LayerImplList* render_surface_layer_list_; - - // The iterator's current position. - - // A position in the render_surface_layer_list. This points to a layer which - // owns the current target surface. This is a value from 0 to n-1 - // (n = size of render_surface_layer_list = number of surfaces). - // A value outside of this range - // (for example, LayerIteratorValue::kInvalidTargetRenderSurfaceLayerIndex) - // is used to indicate a position outside the bounds of the tree. - int target_render_surface_layer_index_; - // A position in the list of layers that are children of the - // 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_layer_index - // to a value of - // LayerIteratorValue::kLayerIndexRepresentingTargetRenderSurface. - size_t current_layer_index_; -}; - -} // namespace cc - -#endif // CC_LAYERS_LAYER_ITERATOR_H_ diff --git a/chromium/cc/layers/layer_list_iterator.h b/chromium/cc/layers/layer_list_iterator.h index bde0ffb3282..da092b951ec 100644 --- a/chromium/cc/layers/layer_list_iterator.h +++ b/chromium/cc/layers/layer_list_iterator.h @@ -8,17 +8,12 @@ #include <stdlib.h> #include <vector> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { -class LayerImpl; - -// Unlike LayerIterator and friends, these iterators are not intended to permit -// traversing the RSLL. Rather, they visit a collection of LayerImpls in -// stacking order. All recursive walks over the LayerImpl tree should be -// switched to use these classes instead as the concept of a LayerImpl tree is -// deprecated. +// This visits a tree of layers in drawing order. For LayerImpls, this is only +// useful for tests, since there's no LayerImpl tree outside unit tests. template <typename LayerType> class CC_EXPORT LayerListIterator { public: diff --git a/chromium/cc/layers/layer_perftest.cc b/chromium/cc/layers/layer_perftest.cc index adb86ece63e..61086a0d56e 100644 --- a/chromium/cc/layers/layer_perftest.cc +++ b/chromium/cc/layers/layer_perftest.cc @@ -6,7 +6,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/animation_host.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" diff --git a/chromium/cc/layers/layer_position_constraint.h b/chromium/cc/layers/layer_position_constraint.h index 9a575137736..9fef26b66ad 100644 --- a/chromium/cc/layers/layer_position_constraint.h +++ b/chromium/cc/layers/layer_position_constraint.h @@ -5,7 +5,7 @@ #ifndef CC_LAYERS_LAYER_POSITION_CONSTRAINT_H_ #define CC_LAYERS_LAYER_POSITION_CONSTRAINT_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/layers/layer_sticky_position_constraint.cc b/chromium/cc/layers/layer_sticky_position_constraint.cc index 79414d6a877..7168e26169c 100644 --- a/chromium/cc/layers/layer_sticky_position_constraint.cc +++ b/chromium/cc/layers/layer_sticky_position_constraint.cc @@ -4,6 +4,8 @@ #include "cc/layers/layer_sticky_position_constraint.h" +#include "cc/layers/layer.h" + namespace cc { LayerStickyPositionConstraint::LayerStickyPositionConstraint() @@ -15,7 +17,9 @@ LayerStickyPositionConstraint::LayerStickyPositionConstraint() left_offset(0.f), right_offset(0.f), top_offset(0.f), - bottom_offset(0.f) {} + bottom_offset(0.f), + nearest_layer_shifting_sticky_box(Layer::INVALID_ID), + nearest_layer_shifting_containing_block(Layer::INVALID_ID) {} LayerStickyPositionConstraint::LayerStickyPositionConstraint( const LayerStickyPositionConstraint& other) @@ -33,7 +37,11 @@ LayerStickyPositionConstraint::LayerStickyPositionConstraint( scroll_container_relative_sticky_box_rect( other.scroll_container_relative_sticky_box_rect), scroll_container_relative_containing_block_rect( - other.scroll_container_relative_containing_block_rect) {} + other.scroll_container_relative_containing_block_rect), + nearest_layer_shifting_sticky_box( + other.nearest_layer_shifting_sticky_box), + nearest_layer_shifting_containing_block( + other.nearest_layer_shifting_containing_block) {} bool LayerStickyPositionConstraint::operator==( const LayerStickyPositionConstraint& other) const { @@ -52,7 +60,11 @@ bool LayerStickyPositionConstraint::operator==( scroll_container_relative_sticky_box_rect == other.scroll_container_relative_sticky_box_rect && scroll_container_relative_containing_block_rect == - other.scroll_container_relative_containing_block_rect; + other.scroll_container_relative_containing_block_rect && + nearest_layer_shifting_sticky_box == + other.nearest_layer_shifting_sticky_box && + nearest_layer_shifting_containing_block == + other.nearest_layer_shifting_containing_block; } bool LayerStickyPositionConstraint::operator!=( @@ -60,4 +72,10 @@ bool LayerStickyPositionConstraint::operator!=( return !(*this == other); } +int LayerStickyPositionConstraint::NearestStickyAncestor() { + return (nearest_layer_shifting_sticky_box != Layer::INVALID_ID) + ? nearest_layer_shifting_sticky_box + : nearest_layer_shifting_containing_block; +} + } // namespace cc diff --git a/chromium/cc/layers/layer_sticky_position_constraint.h b/chromium/cc/layers/layer_sticky_position_constraint.h index 3f43bc7751a..adf053528f5 100644 --- a/chromium/cc/layers/layer_sticky_position_constraint.h +++ b/chromium/cc/layers/layer_sticky_position_constraint.h @@ -5,8 +5,9 @@ #ifndef CC_LAYERS_LAYER_STICKY_POSITION_CONSTRAINT_H_ #define CC_LAYERS_LAYER_STICKY_POSITION_CONSTRAINT_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" +#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" namespace cc { @@ -44,6 +45,16 @@ struct CC_EXPORT LayerStickyPositionConstraint { // block boundary. gfx::Rect scroll_container_relative_containing_block_rect; + // The nearest ancestor sticky layer ids that affect the sticky box constraint + // rect and the containing block constraint rect respectively. If no such + // layer exists, these are set to Layer::INVALID_ID. + int nearest_layer_shifting_sticky_box; + int nearest_layer_shifting_containing_block; + + // Returns the nearest sticky ancestor layer, or Layer::INVALID_ID if no such + // layer exists. + int NearestStickyAncestor(); + bool operator==(const LayerStickyPositionConstraint&) const; bool operator!=(const LayerStickyPositionConstraint&) const; }; diff --git a/chromium/cc/layers/layer_utils.h b/chromium/cc/layers/layer_utils.h index bef37f4c7c6..e4a20888ee1 100644 --- a/chromium/cc/layers/layer_utils.h +++ b/chromium/cc/layers/layer_utils.h @@ -5,7 +5,7 @@ #ifndef CC_LAYERS_LAYER_UTILS_H_ #define CC_LAYERS_LAYER_UTILS_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace gfx { class BoxF; diff --git a/chromium/cc/layers/nine_patch_layer.h b/chromium/cc/layers/nine_patch_layer.h index cf9edf99c72..ca9fb929eb5 100644 --- a/chromium/cc/layers/nine_patch_layer.h +++ b/chromium/cc/layers/nine_patch_layer.h @@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/layers/ui_resource_layer.h" #include "cc/resources/ui_resource_client.h" diff --git a/chromium/cc/layers/nine_patch_layer_impl.h b/chromium/cc/layers/nine_patch_layer_impl.h index 69b039a54e7..1422d9672c3 100644 --- a/chromium/cc/layers/nine_patch_layer_impl.h +++ b/chromium/cc/layers/nine_patch_layer_impl.h @@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_impl.h" #include "cc/layers/ui_resource_layer_impl.h" #include "cc/quads/nine_patch_generator.h" diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer.cc b/chromium/cc/layers/painted_overlay_scrollbar_layer.cc index ab8643ecac0..81a515edf1c 100644 --- a/chromium/cc/layers/painted_overlay_scrollbar_layer.cc +++ b/chromium/cc/layers/painted_overlay_scrollbar_layer.cc @@ -9,6 +9,7 @@ #include "base/auto_reset.h" #include "cc/base/math_util.h" #include "cc/layers/painted_overlay_scrollbar_layer_impl.h" +#include "cc/paint/skia_paint_canvas.h" #include "cc/resources/ui_resource_bitmap.h" #include "cc/resources/ui_resource_manager.h" #include "cc/trees/layer_tree_host.h" @@ -137,7 +138,7 @@ bool PaintedOverlayScrollbarLayer::Update() { } bool PaintedOverlayScrollbarLayer::PaintThumbIfNeeded() { - if (!scrollbar_->NeedsPaintPart(THUMB)) + if (!scrollbar_->NeedsPaintPart(THUMB) && thumb_resource_) return false; gfx::Rect paint_rect = OriginThumbRectForPainting(); @@ -148,16 +149,16 @@ bool PaintedOverlayScrollbarLayer::PaintThumbIfNeeded() { SkBitmap skbitmap; skbitmap.allocN32Pixels(paint_rect.width(), paint_rect.height()); - SkCanvas skcanvas(skbitmap); + SkiaPaintCanvas canvas(skbitmap); SkRect content_skrect = RectToSkRect(paint_rect); - SkPaint paint; - paint.setAntiAlias(false); - paint.setBlendMode(SkBlendMode::kClear); - skcanvas.drawRect(content_skrect, paint); - skcanvas.clipRect(content_skrect); + PaintFlags flags; + flags.setAntiAlias(false); + flags.setBlendMode(SkBlendMode::kClear); + canvas.drawRect(content_skrect, flags); + canvas.clipRect(content_skrect); - scrollbar_->PaintPart(&skcanvas, THUMB, paint_rect); + scrollbar_->PaintPart(&canvas, THUMB, paint_rect); // Make sure that the pixels are no longer mutable to unavoid unnecessary // allocation and copying. skbitmap.setImmutable(); diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer.h b/chromium/cc/layers/painted_overlay_scrollbar_layer.h index 6888bec7ce6..f7cd66e5fd5 100644 --- a/chromium/cc/layers/painted_overlay_scrollbar_layer.h +++ b/chromium/cc/layers/painted_overlay_scrollbar_layer.h @@ -6,7 +6,7 @@ #define CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/layer.h" #include "cc/layers/scrollbar_layer_interface.h" diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.cc b/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.cc index c14b93be585..68cbfd45cd3 100644 --- a/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.cc +++ b/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.cc @@ -66,6 +66,9 @@ bool PaintedOverlayScrollbarLayerImpl::WillDraw( void PaintedOverlayScrollbarLayerImpl::AppendQuads( RenderPass* render_pass, AppendQuadsData* append_quads_data) { + if (aperture_.IsEmpty()) + return; + // For overlay scrollbars, the border should match the inset of the aperture // and be symmetrical. gfx::Rect border(aperture_.x(), aperture_.y(), aperture_.x() * 2, @@ -75,6 +78,12 @@ void PaintedOverlayScrollbarLayerImpl::AppendQuads( bool fill_center = true; bool nearest_neighbor = false; + // Avoid drawing a scrollber in the degenerate case where the scroller is + // smaller than the border size. + if (thumb_quad_rect.height() < border.height() || + thumb_quad_rect.width() < border.width()) + return; + quad_generator_.SetLayout(image_bounds_, thumb_quad_rect.size(), aperture_, border, layer_occlusion, fill_center, nearest_neighbor); diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.h b/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.h index fef31208864..51858947383 100644 --- a/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.h +++ b/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.h @@ -6,7 +6,7 @@ #define CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_IMPL_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/scrollbar_layer_impl_base.h" #include "cc/quads/nine_patch_generator.h" diff --git a/chromium/cc/layers/painted_scrollbar_layer.cc b/chromium/cc/layers/painted_scrollbar_layer.cc index 7fc6e9c1ae8..98aca6dbe19 100644 --- a/chromium/cc/layers/painted_scrollbar_layer.cc +++ b/chromium/cc/layers/painted_scrollbar_layer.cc @@ -10,8 +10,8 @@ #include "cc/base/math_util.h" #include "cc/input/main_thread_scrolling_reason.h" #include "cc/layers/painted_scrollbar_layer_impl.h" -#include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" +#include "cc/paint/skia_paint_canvas.h" #include "cc/resources/ui_resource_bitmap.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/layer_tree_host.h" @@ -265,7 +265,7 @@ UIResourceBitmap PaintedScrollbarLayer::RasterizeScrollbarPart( SkBitmap skbitmap; skbitmap.allocN32Pixels(content_rect.width(), content_rect.height()); - PaintCanvas canvas(skbitmap); + SkiaPaintCanvas canvas(skbitmap); float scale_x = content_rect.width() / static_cast<float>(layer_rect.width()); diff --git a/chromium/cc/layers/painted_scrollbar_layer.h b/chromium/cc/layers/painted_scrollbar_layer.h index 8446a390202..8e1884f44f5 100644 --- a/chromium/cc/layers/painted_scrollbar_layer.h +++ b/chromium/cc/layers/painted_scrollbar_layer.h @@ -6,7 +6,7 @@ #define CC_LAYERS_PAINTED_SCROLLBAR_LAYER_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/layer.h" #include "cc/layers/scrollbar_layer_interface.h" diff --git a/chromium/cc/layers/painted_scrollbar_layer_impl.h b/chromium/cc/layers/painted_scrollbar_layer_impl.h index 4e12371cf34..9ff7e89691f 100644 --- a/chromium/cc/layers/painted_scrollbar_layer_impl.h +++ b/chromium/cc/layers/painted_scrollbar_layer_impl.h @@ -6,7 +6,7 @@ #define CC_LAYERS_PAINTED_SCROLLBAR_LAYER_IMPL_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/scrollbar_layer_impl_base.h" #include "cc/resources/ui_resource_client.h" diff --git a/chromium/cc/layers/picture_image_layer.cc b/chromium/cc/layers/picture_image_layer.cc index 0e909d6b8a6..c219d8d906d 100644 --- a/chromium/cc/layers/picture_image_layer.cc +++ b/chromium/cc/layers/picture_image_layer.cc @@ -7,9 +7,9 @@ #include <stddef.h> #include "cc/layers/picture_layer_impl.h" +#include "cc/paint/drawing_display_item.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_recorder.h" -#include "cc/playback/drawing_display_item.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_settings.h" @@ -75,7 +75,7 @@ scoped_refptr<DisplayItemList> PictureImageLayer::PaintContentsToDisplayList( // Because Android WebView resourceless software draw mode rasters directly // to the root canvas, this draw must use the kSrcOver_Mode so that // transparent images blend correctly. - canvas->drawImage(image_.get(), 0, 0); + canvas->drawImage(image_, 0, 0); display_list->CreateAndAppendDrawingItem<DrawingDisplayItem>( PaintableRegion(), recorder.finishRecordingAsPicture()); diff --git a/chromium/cc/layers/picture_image_layer.h b/chromium/cc/layers/picture_image_layer.h index 7c27fd89ae4..d07e6cae731 100644 --- a/chromium/cc/layers/picture_image_layer.h +++ b/chromium/cc/layers/picture_image_layer.h @@ -8,7 +8,7 @@ #include <stddef.h> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_layer.h" #include "third_party/skia/include/core/SkRefCnt.h" diff --git a/chromium/cc/layers/picture_image_layer_unittest.cc b/chromium/cc/layers/picture_image_layer_unittest.cc index 0a9f7a10e49..8701d316cdf 100644 --- a/chromium/cc/layers/picture_image_layer_unittest.cc +++ b/chromium/cc/layers/picture_image_layer_unittest.cc @@ -5,7 +5,7 @@ #include "cc/layers/picture_image_layer.h" #include "cc/animation/animation_host.h" -#include "cc/playback/display_item.h" +#include "cc/paint/display_item.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/skia_common.h" #include "cc/test/test_task_graph_runner.h" diff --git a/chromium/cc/layers/picture_layer.cc b/chromium/cc/layers/picture_layer.cc index e5bd641e8e7..d853f13ae1a 100644 --- a/chromium/cc/layers/picture_layer.cc +++ b/chromium/cc/layers/picture_layer.cc @@ -8,10 +8,11 @@ #include "base/trace_event/trace_event.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_layer_impl.h" +#include "cc/layers/recording_source.h" #include "cc/paint/paint_record.h" -#include "cc/playback/recording_source.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/transform_node.h" #include "ui/gfx/geometry/rect_conversions.h" namespace cc { @@ -54,6 +55,8 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { DropRecordingSourceContentIfInvalid(); layer_impl->SetNearestNeighbor(picture_layer_inputs_.nearest_neighbor); + layer_impl->SetUseTransformedRasterization( + ShouldUseTransformedRasterization()); // Preserve lcd text settings from the current raster source. bool can_use_lcd_text = layer_impl->RasterSourceUsesLCDText(); @@ -61,8 +64,8 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { recording_source_->CreateRasterSource(can_use_lcd_text); layer_impl->set_gpu_raster_max_texture_size( layer_tree_host()->device_viewport_size()); - layer_impl->UpdateRasterSource(raster_source, &last_updated_invalidation_, - nullptr); + layer_impl->UpdateRasterSource(std::move(raster_source), + &last_updated_invalidation_, nullptr); DCHECK(last_updated_invalidation_.IsEmpty()); } @@ -143,6 +146,11 @@ bool PictureLayer::Update() { } void PictureLayer::SetLayerMaskType(LayerMaskType mask_type) { + // We do not allow converting SINGLE_TEXTURE_MASK to MULTI_TEXTURE_MASK in + // order to avoid rerastering when a mask's transform is being animated. + if (mask_type_ == LayerMaskType::SINGLE_TEXTURE_MASK && + mask_type == LayerMaskType::MULTI_TEXTURE_MASK) + return; mask_type_ = mask_type; } @@ -198,6 +206,14 @@ void PictureLayer::SetNearestNeighbor(bool nearest_neighbor) { SetNeedsCommit(); } +void PictureLayer::SetAllowTransformedRasterization(bool allowed) { + if (picture_layer_inputs_.allow_transformed_rasterization == allowed) + return; + + picture_layer_inputs_.allow_transformed_rasterization = allowed; + SetNeedsCommit(); +} + bool PictureLayer::HasDrawableContent() const { return picture_layer_inputs_.client && Layer::HasDrawableContent(); } @@ -233,6 +249,46 @@ void PictureLayer::DropRecordingSourceContentIfInvalid() { } } +bool PictureLayer::ShouldUseTransformedRasterization() const { + if (!picture_layer_inputs_.allow_transformed_rasterization) + return false; + + // Background color overfill is undesirable with transformed rasterization. + // However, without background overfill, the tiles will be non-opaque on + // external edges, and layer opaque region can't be computed in layer space + // due to rounding under extreme scaling. This defeats many opaque layer + // optimization. Prefer optimization over quality for this particular case. + if (contents_opaque()) + return false; + + const TransformTree& transform_tree = + layer_tree_host()->property_trees()->transform_tree; + DCHECK(!transform_tree.needs_update()); + auto* transform_node = transform_tree.Node(transform_tree_index()); + DCHECK(transform_node); + // TODO(pdr): This is a workaround for https://crbug.com/708951 to avoid + // crashing when there's no transform node. This workaround should be removed. + if (!transform_node) + return false; + + if (transform_node->to_screen_is_potentially_animated) + return false; + + const gfx::Transform& to_screen = + transform_tree.ToScreen(transform_tree_index()); + if (!to_screen.IsScaleOrTranslation()) + return false; + + float origin_x = + to_screen.matrix().getFloat(0, 3) + offset_to_transform_parent().x(); + float origin_y = + to_screen.matrix().getFloat(1, 3) + offset_to_transform_parent().y(); + if (origin_x - floorf(origin_x) == 0.f && origin_y - floorf(origin_y) == 0.f) + return false; + + return true; +} + const DisplayItemList* PictureLayer::GetDisplayItemList() { return picture_layer_inputs_.display_list.get(); } diff --git a/chromium/cc/layers/picture_layer.h b/chromium/cc/layers/picture_layer.h index 71209fb77a1..5b8adf0bf57 100644 --- a/chromium/cc/layers/picture_layer.h +++ b/chromium/cc/layers/picture_layer.h @@ -6,9 +6,9 @@ #define CC_LAYERS_PICTURE_LAYER_H_ #include "base/macros.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/base/invalidation_region.h" -#include "cc/debug/devtools_instrumentation.h" -#include "cc/debug/micro_benchmark_controller.h" +#include "cc/benchmarks/micro_benchmark_controller.h" #include "cc/layers/layer.h" namespace cc { @@ -28,6 +28,8 @@ class CC_EXPORT PictureLayer : public Layer { return picture_layer_inputs_.nearest_neighbor; } + void SetAllowTransformedRasterization(bool allowed); + // Layer interface. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void SetLayerTreeHost(LayerTreeHost* host) override; @@ -57,6 +59,7 @@ class CC_EXPORT PictureLayer : public Layer { ContentLayerClient* client = nullptr; bool nearest_neighbor = false; + bool allow_transformed_rasterization = false; gfx::Rect recorded_viewport; scoped_refptr<DisplayItemList> display_list; size_t painter_reported_memory_usage = 0; @@ -79,6 +82,8 @@ class CC_EXPORT PictureLayer : public Layer { void DropRecordingSourceContentIfInvalid(); + bool ShouldUseTransformedRasterization() const; + std::unique_ptr<RecordingSource> recording_source_; devtools_instrumentation:: ScopedLayerObjectTracker instrumentation_object_tracker_; diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc index f112497b5d1..a85580bf3cd 100644 --- a/chromium/cc/layers/picture_layer_impl.cc +++ b/chromium/cc/layers/picture_layer_impl.cc @@ -16,8 +16,8 @@ #include "base/time/time.h" #include "base/trace_event/trace_event_argument.h" #include "cc/base/math_util.h" +#include "cc/benchmarks/micro_benchmark_impl.h" #include "cc/debug/debug_colors.h" -#include "cc/debug/micro_benchmark_impl.h" #include "cc/debug/traced_value.h" #include "cc/layers/append_quads_data.h" #include "cc/layers/solid_color_layer_impl.h" @@ -109,6 +109,7 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, only_used_low_res_last_append_quads_(false), mask_type_(mask_type), nearest_neighbor_(false), + use_transformed_rasterization_(false), is_directly_composited_image_(false) { layer_tree_impl()->RegisterPictureLayerImpl(this); } @@ -145,6 +146,7 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { layer_impl->twin_layer_ = this; layer_impl->SetNearestNeighbor(nearest_neighbor_); + layer_impl->SetUseTransformedRasterization(use_transformed_rasterization_); // Solid color layers have no tilings. DCHECK(!raster_source_->IsSolidColor() || tilings_->num_tilings() == 0); @@ -201,6 +203,8 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, return; } + float device_scale_factor = + layer_tree_impl() ? layer_tree_impl()->device_scale_factor() : 1; float max_contents_scale = MaximumTilingContentsScale(); PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale, max_contents_scale); @@ -213,7 +217,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, AppendDebugBorderQuad( render_pass, shared_quad_state->quad_layer_bounds, shared_quad_state, append_quads_data, DebugColors::DirectPictureBorderColor(), - DebugColors::DirectPictureBorderWidth(layer_tree_impl())); + DebugColors::DirectPictureBorderWidth(device_scale_factor)); gfx::Rect geometry_rect = shared_quad_state->visible_quad_layer_rect; gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect(); @@ -249,7 +253,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, AppendDebugBorderQuad(render_pass, shared_quad_state->quad_layer_bounds, shared_quad_state, append_quads_data); - if (ShowDebugBorders()) { + if (ShowDebugBorders(DebugBorderType::LAYER)) { for (PictureLayerTilingSet::CoverageIterator iter( tilings_.get(), max_contents_scale, shared_quad_state->visible_quad_layer_rect, ideal_contents_scale_); @@ -260,29 +264,29 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, TileDrawInfo::Mode mode = iter->draw_info().mode(); if (mode == TileDrawInfo::SOLID_COLOR_MODE) { color = DebugColors::SolidColorTileBorderColor(); - width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl()); + width = DebugColors::SolidColorTileBorderWidth(device_scale_factor); } else if (mode == TileDrawInfo::OOM_MODE) { color = DebugColors::OOMTileBorderColor(); - width = DebugColors::OOMTileBorderWidth(layer_tree_impl()); + width = DebugColors::OOMTileBorderWidth(device_scale_factor); } else if (iter->draw_info().has_compressed_resource()) { color = DebugColors::CompressedTileBorderColor(); - width = DebugColors::CompressedTileBorderWidth(layer_tree_impl()); + width = DebugColors::CompressedTileBorderWidth(device_scale_factor); } else if (iter.resolution() == HIGH_RESOLUTION) { color = DebugColors::HighResTileBorderColor(); - width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); + width = DebugColors::HighResTileBorderWidth(device_scale_factor); } else if (iter.resolution() == LOW_RESOLUTION) { color = DebugColors::LowResTileBorderColor(); - width = DebugColors::LowResTileBorderWidth(layer_tree_impl()); - } else if (iter->contents_scale() > max_contents_scale) { + width = DebugColors::LowResTileBorderWidth(device_scale_factor); + } else if (iter->contents_scale_key() > max_contents_scale) { color = DebugColors::ExtraHighResTileBorderColor(); - width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl()); + width = DebugColors::ExtraHighResTileBorderWidth(device_scale_factor); } else { color = DebugColors::ExtraLowResTileBorderColor(); - width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl()); + width = DebugColors::ExtraLowResTileBorderWidth(device_scale_factor); } } else { color = DebugColors::MissingTileBorderColor(); - width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); + width = DebugColors::MissingTileBorderWidth(device_scale_factor); } DebugBorderDrawQuad* debug_border_quad = @@ -341,8 +345,8 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, // complete. But if a tile is ideal scale, we don't want to consider // it incomplete and trying to replace it with a tile at a worse // scale. - if (iter->contents_scale() != raster_contents_scale_ && - iter->contents_scale() != ideal_contents_scale_ && + if (iter->contents_scale_key() != raster_contents_scale_ && + iter->contents_scale_key() != ideal_contents_scale_ && geometry_rect.Intersects(scaled_viewport_for_tile_priority)) { append_quads_data->num_incomplete_tiles++; } @@ -358,11 +362,16 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, break; } case TileDrawInfo::SOLID_COLOR_MODE: { - SolidColorDrawQuad* quad = - render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect, - draw_info.solid_color(), false); - ValidateQuadResources(quad); + float alpha = + (SkColorGetA(draw_info.solid_color()) * (1.0f / 255.0f)) * + shared_quad_state->opacity; + if (alpha >= std::numeric_limits<float>::epsilon()) { + SolidColorDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + quad->SetNew(shared_quad_state, geometry_rect, + visible_geometry_rect, draw_info.solid_color(), false); + ValidateQuadResources(quad); + } has_draw_quad = true; break; } @@ -374,7 +383,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, if (!has_draw_quad) { // Checkerboard. SkColor color = SafeOpaqueBackgroundColor(); - if (ShowDebugBorders()) { + if (ShowDebugBorders(DebugBorderType::LAYER)) { // Fill the whole tile with the missing tile color. color = DebugColors::OOMTileBorderColor(); } @@ -642,14 +651,11 @@ bool PictureLayerImpl::RasterSourceUsesLCDText() const { } void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) { - if (layer_tree_impl()->IsActiveTree()) { - gfx::Rect layer_damage_rect = gfx::ScaleToEnclosingRect( - tile->content_rect(), 1.f / tile->contents_scale()); - AddDamageRect(layer_damage_rect); - } + if (layer_tree_impl()->IsActiveTree()) + AddDamageRect(tile->enclosing_layer_rect()); if (tile->draw_info().NeedsRaster()) { PictureLayerTiling* tiling = - tilings_->FindTilingWithScaleKey(tile->contents_scale()); + tilings_->FindTilingWithScaleKey(tile->contents_scale_key()); if (tiling) tiling->set_all_tiles_done(false); } @@ -722,7 +728,13 @@ const PictureLayerTiling* PictureLayerImpl::GetPendingOrActiveTwinTiling( PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer(); if (!twin_layer) return nullptr; - return twin_layer->tilings_->FindTilingWithScaleKey(tiling->contents_scale()); + const PictureLayerTiling* twin_tiling = + twin_layer->tilings_->FindTilingWithScaleKey( + tiling->contents_scale_key()); + DCHECK(tiling->raster_transform().translation() == gfx::Vector2dF()); + DCHECK(!twin_tiling || + twin_tiling->raster_transform().translation() == gfx::Vector2dF()); + return twin_tiling; } bool PictureLayerImpl::RequiresHighResToDraw() const { @@ -870,12 +882,21 @@ void PictureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { NoteLayerPropertyChanged(); } +void PictureLayerImpl::SetUseTransformedRasterization(bool use) { + if (use_transformed_rasterization_ == use) + return; + + use_transformed_rasterization_ = use; + NoteLayerPropertyChanged(); +} + PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) { DCHECK(CanHaveTilings()); DCHECK_GE(contents_scale, MinimumContentsScale()); DCHECK_LE(contents_scale, MaximumContentsScale()); DCHECK(raster_source_->HasRecordings()); - return tilings_->AddTiling(contents_scale, raster_source_); + return tilings_->AddTiling( + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), raster_source_); } void PictureLayerImpl::RemoveAllTilings() { @@ -1268,12 +1289,15 @@ void PictureLayerImpl::UpdateIdealScales() { void PictureLayerImpl::GetDebugBorderProperties( SkColor* color, float* width) const { + float device_scale_factor = + layer_tree_impl() ? layer_tree_impl()->device_scale_factor() : 1; + if (is_directly_composited_image_) { *color = DebugColors::ImageLayerBorderColor(); - *width = DebugColors::ImageLayerBorderWidth(layer_tree_impl()); + *width = DebugColors::ImageLayerBorderWidth(device_scale_factor); } else { *color = DebugColors::TiledContentLayerBorderColor(); - *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl()); + *width = DebugColors::TiledContentLayerBorderWidth(device_scale_factor); } } diff --git a/chromium/cc/layers/picture_layer_impl.h b/chromium/cc/layers/picture_layer_impl.h index 93a703e036b..0e85d8d4208 100644 --- a/chromium/cc/layers/picture_layer_impl.h +++ b/chromium/cc/layers/picture_layer_impl.h @@ -13,17 +13,17 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" -#include "cc/playback/image_id.h" +#include "cc/paint/image_id.h" #include "cc/tiles/picture_layer_tiling.h" #include "cc/tiles/picture_layer_tiling_set.h" #include "cc/tiles/tiling_set_eviction_queue.h" namespace cc { -struct AppendQuadsData; +class AppendQuadsData; class MicroBenchmarkImpl; class Tile; @@ -80,6 +80,8 @@ class CC_EXPORT PictureLayerImpl void SetNearestNeighbor(bool nearest_neighbor); + void SetUseTransformedRasterization(bool use); + size_t GPUMemoryUsageInBytes() const override; void RunMicroBenchmark(MicroBenchmarkImpl* benchmark) override; @@ -151,6 +153,7 @@ class CC_EXPORT PictureLayerImpl const Layer::LayerMaskType mask_type_; bool nearest_neighbor_; + bool use_transformed_rasterization_; bool is_directly_composited_image_; // Use this instead of |visible_layer_rect()| for tiling calculations. This diff --git a/chromium/cc/layers/picture_layer_impl_perftest.cc b/chromium/cc/layers/picture_layer_impl_perftest.cc index f0c113ddda5..a434297fbc9 100644 --- a/chromium/cc/layers/picture_layer_impl_perftest.cc +++ b/chromium/cc/layers/picture_layer_impl_perftest.cc @@ -6,7 +6,7 @@ #include "base/macros.h" #include "base/threading/thread_task_runner_handle.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/test/fake_compositor_frame_sink.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host_impl.h" diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc index a9e71b32b1e..6ccf44a18d5 100644 --- a/chromium/cc/layers/picture_layer_impl_unittest.cc +++ b/chromium/cc/layers/picture_layer_impl_unittest.cc @@ -81,7 +81,6 @@ class PictureLayerImplTest : public TestLayerTreeHostBase { LayerTreeSettings settings; settings.layer_transforms_should_scale_layer_contents = true; settings.create_low_res_tiling = true; - settings.verify_clip_tree_calculations = true; settings.renderer_settings.buffer_to_texture_target_map = DefaultBufferToTextureTargetMapForTesting(); return settings; @@ -192,7 +191,7 @@ class PictureLayerImplTest : public TestLayerTreeHostBase { auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting(); for (PictureLayerTiling::CoverageIterator iter( - tiling, tiling->contents_scale(), + tiling, tiling->contents_scale_key(), gfx::Rect(tiling->tiling_size())); iter; ++iter) { EXPECT_TRUE(*iter); @@ -267,7 +266,7 @@ class PictureLayerImplTest : public TestLayerTreeHostBase { host_impl()->active_tree()->SetDeviceScaleFactor(device_scale_factor); } - void TestQuadsForSolidColor(bool test_for_solid); + void TestQuadsForSolidColor(bool test_for_solid, bool partial_opaque); }; class NoLowResPictureLayerImplTest : public PictureLayerImplTest { @@ -324,7 +323,7 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) { EXPECT_EQ( tiling->GetCurrentVisibleRectForTesting(), gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority_in_view_space, - tiling->contents_scale())); + tiling->contents_scale_key())); } // Update tiles with viewport for tile priority as (200, 200, 100, 100) in @@ -360,7 +359,7 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) { EXPECT_EQ( tiling->GetCurrentVisibleRectForTesting(), gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority_in_view_space, - tiling->contents_scale())); + tiling->contents_scale_key())); } } @@ -436,12 +435,12 @@ TEST_F(PictureLayerImplTest, ClonePartialInvalidation) { EXPECT_GT(tilings->num_tilings(), 0u); for (size_t i = 0; i < tilings->num_tilings(); ++i) { const PictureLayerTiling* tiling = tilings->tiling_at(i); - gfx::Rect content_invalidation = - gfx::ScaleToEnclosingRect(layer_invalidation, tiling->contents_scale()); + gfx::Rect content_invalidation = gfx::ScaleToEnclosingRect( + layer_invalidation, tiling->contents_scale_key()); auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting(); for (PictureLayerTiling::CoverageIterator iter( - tiling, tiling->contents_scale(), + tiling, tiling->contents_scale_key(), gfx::Rect(tiling->tiling_size())); iter; ++iter) { // We don't always have a tile, but when we do it's because it was @@ -465,7 +464,7 @@ TEST_F(PictureLayerImplTest, ClonePartialInvalidation) { auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting(); for (PictureLayerTiling::CoverageIterator iter( - tiling, tiling->contents_scale(), + tiling, tiling->contents_scale_key(), gfx::Rect(tiling->tiling_size())); iter; ++iter) { EXPECT_TRUE(*iter); @@ -519,10 +518,11 @@ TEST_F(PictureLayerImplTest, UpdateTilesCreatesTilings) { 0.f, // starting animation scale false); ASSERT_EQ(2u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(6.f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(6.f * low_res_factor, - active_layer()->tilings()->tiling_at(1)->contents_scale()); + EXPECT_FLOAT_EQ( + 6.f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 6.f * low_res_factor, + active_layer()->tilings()->tiling_at(1)->contents_scale_key()); // If we change the page scale factor, then we should get new tilings. SetupDrawPropertiesAndUpdateTiles(active_layer(), @@ -533,10 +533,11 @@ TEST_F(PictureLayerImplTest, UpdateTilesCreatesTilings) { 0.f, // starting animation scale false); ASSERT_EQ(4u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(6.6f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(6.6f * low_res_factor, - active_layer()->tilings()->tiling_at(2)->contents_scale()); + EXPECT_FLOAT_EQ( + 6.6f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 6.6f * low_res_factor, + active_layer()->tilings()->tiling_at(2)->contents_scale_key()); // If we change the device scale factor, then we should get new tilings. SetupDrawPropertiesAndUpdateTiles(active_layer(), @@ -547,10 +548,11 @@ TEST_F(PictureLayerImplTest, UpdateTilesCreatesTilings) { 0.f, // starting animation scale false); ASSERT_EQ(6u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(7.26f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(7.26f * low_res_factor, - active_layer()->tilings()->tiling_at(3)->contents_scale()); + EXPECT_FLOAT_EQ( + 7.26f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 7.26f * low_res_factor, + active_layer()->tilings()->tiling_at(3)->contents_scale_key()); // If we change the device scale factor, but end up at the same total scale // factor somehow, then we don't get new tilings. @@ -562,10 +564,11 @@ TEST_F(PictureLayerImplTest, UpdateTilesCreatesTilings) { 0.f, // starting animation scale false); ASSERT_EQ(6u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(7.26f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(7.26f * low_res_factor, - active_layer()->tilings()->tiling_at(3)->contents_scale()); + EXPECT_FLOAT_EQ( + 7.26f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 7.26f * low_res_factor, + active_layer()->tilings()->tiling_at(3)->contents_scale_key()); } TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { @@ -588,8 +591,8 @@ TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { 0.f, // starting animation scale false); ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(6.f, - pending_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 6.f, pending_layer()->tilings()->tiling_at(0)->contents_scale_key()); // If we change the page scale factor, then we should get new tilings. SetupDrawPropertiesAndUpdateTiles(pending_layer(), @@ -600,8 +603,8 @@ TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { 0.f, // starting animation scale false); ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(6.6f, - pending_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 6.6f, pending_layer()->tilings()->tiling_at(0)->contents_scale_key()); // If we change the device scale factor, then we should get new tilings. SetupDrawPropertiesAndUpdateTiles(pending_layer(), @@ -612,8 +615,8 @@ TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { 0.f, // starting animation scale false); ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(7.26f, - pending_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 7.26f, pending_layer()->tilings()->tiling_at(0)->contents_scale_key()); // If we change the device scale factor, but end up at the same total scale // factor somehow, then we don't get new tilings. @@ -625,8 +628,8 @@ TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { 0.f, // starting animation scale false); ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(7.26f, - pending_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 7.26f, pending_layer()->tilings()->tiling_at(0)->contents_scale_key()); } TEST_F(PictureLayerImplTest, CreateTilingsEvenIfTwinHasNone) { @@ -693,7 +696,7 @@ TEST_F(PictureLayerImplTest, ZoomOutCrash) { ResetTilingsAndRasterScales(); EXPECT_EQ(0u, active_layer()->tilings()->num_tilings()); SetContentsScaleOnBothLayers(32.0f, 1.0f, 32.0f, 1.0f, 0.f, false); - EXPECT_EQ(32.f, active_layer()->HighResTiling()->contents_scale()); + EXPECT_EQ(32.f, active_layer()->HighResTiling()->contents_scale_key()); host_impl()->PinchGestureBegin(); SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, 1.0f, 0.f, false); SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, 1.0f, 0.f, false); @@ -718,7 +721,7 @@ TEST_F(PictureLayerImplTest, ScaledBoundsOverflowInt) { static_cast<float>(std::numeric_limits<int>::max())); SetContentsScaleOnBothLayers(scale, 1.0f, scale, 1.0f, 0.f, false); - float adjusted_scale = active_layer()->HighResTiling()->contents_scale(); + float adjusted_scale = active_layer()->HighResTiling()->contents_scale_key(); EXPECT_LT(adjusted_scale, scale); // PopulateSharedQuadState CHECKs for overflows. @@ -741,8 +744,8 @@ TEST_F(PictureLayerImplTest, PinchGestureTilings) { SetContentsScaleOnBothLayers(2.f, 1.0f, 2.f, 1.0f, 0.f, false); EXPECT_EQ(active_layer()->num_tilings(), 2u); EXPECT_EQ(pending_layer()->num_tilings(), 1u); - EXPECT_EQ(active_layer()->tilings()->tiling_at(0)->contents_scale(), 2.f); - EXPECT_EQ(active_layer()->tilings()->tiling_at(1)->contents_scale(), + EXPECT_EQ(active_layer()->tilings()->tiling_at(0)->contents_scale_key(), 2.f); + EXPECT_EQ(active_layer()->tilings()->tiling_at(1)->contents_scale_key(), 2.f * low_res_factor); // One of the tilings has to be a low resolution one. EXPECT_EQ(LOW_RESOLUTION, @@ -758,12 +761,13 @@ TEST_F(PictureLayerImplTest, PinchGestureTilings) { // the scale (2/kMaxScaleRatioDuringPinch). SetContentsScaleOnBothLayers(1.8f, 1.0f, 1.8f, 1.0f, 0.f, false); EXPECT_EQ(3u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(2.0f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.0f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); - EXPECT_FLOAT_EQ(2.0f * low_res_factor, - active_layer()->tilings()->tiling_at(2)->contents_scale()); + EXPECT_FLOAT_EQ( + 2.0f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.0f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 2.0f * low_res_factor, + active_layer()->tilings()->tiling_at(2)->contents_scale_key()); // Since we're pinching, we shouldn't create a low resolution tiling. EXPECT_FALSE( active_layer()->tilings()->FindTilingWithResolution(LOW_RESOLUTION)); @@ -783,8 +787,8 @@ TEST_F(PictureLayerImplTest, PinchGestureTilings) { // kMaxScaleRatioDuringPinch, this will create a new tiling at 4.0. SetContentsScaleOnBothLayers(3.8f, 1.0f, 3.8f, 1.f, 0.f, false); EXPECT_EQ(4u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(4.0f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 4.0f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); // Although one of the tilings matches the low resolution scale, it still // shouldn't be marked as low resolution since we're pinching. auto* low_res_tiling = @@ -802,8 +806,8 @@ TEST_F(PictureLayerImplTest, PinchGestureTilings) { // (checked above). SetContentsScaleOnBothLayers(4.0f, 1.0f, 4.0f, 1.f, 0.f, false); EXPECT_EQ(4u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(4.0f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 4.0f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); // Now that we stopped pinching, the low resolution tiling that existed should // now be marked as low resolution. low_res_tiling = @@ -822,10 +826,10 @@ TEST_F(PictureLayerImplTest, SnappedTilingDuringZoom) { // Set up the high and low res tilings before pinch zoom. SetContentsScaleOnBothLayers(0.24f, 1.0f, 0.24f, 1.0f, 0.f, false); EXPECT_EQ(2u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(0.24f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(0.0625f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); + EXPECT_FLOAT_EQ( + 0.24f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 0.0625f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); // Ensure UpdateTiles won't remove any tilings. active_layer()->MarkAllTilingsUsed(); @@ -837,12 +841,12 @@ TEST_F(PictureLayerImplTest, SnappedTilingDuringZoom) { // the scale (1/kMaxScaleRatioDuringPinch). SetContentsScaleOnBothLayers(0.2f, 1.0f, 0.2f, 1.0f, 0.f, false); EXPECT_EQ(3u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(0.24f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(0.12f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); - EXPECT_FLOAT_EQ(0.0625, - active_layer()->tilings()->tiling_at(2)->contents_scale()); + EXPECT_FLOAT_EQ( + 0.24f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 0.12f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 0.0625, active_layer()->tilings()->tiling_at(2)->contents_scale_key()); // Ensure UpdateTiles won't remove any tilings. active_layer()->MarkAllTilingsUsed(); @@ -861,8 +865,8 @@ TEST_F(PictureLayerImplTest, SnappedTilingDuringZoom) { // is a power of 2 times 0.24. SetContentsScaleOnBothLayers(1.f, 1.0f, 1.f, 1.0f, 0.f, false); EXPECT_EQ(4u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.92f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.92f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); } TEST_F(PictureLayerImplTest, CleanUpTilings) { @@ -879,10 +883,11 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) { SetupDefaultTrees(layer_bounds); active_layer()->SetHasWillChangeTransformHint(true); EXPECT_FLOAT_EQ(2u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f * low_res_factor, - active_layer()->tilings()->tiling_at(1)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f * low_res_factor, + active_layer()->tilings()->tiling_at(1)->contents_scale_key()); // Ensure UpdateTiles won't remove any tilings. Note this is unrelated to // |used_tilings| variable, and it's here only to ensure that active_layer() @@ -893,10 +898,11 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) { used_tilings.clear(); active_layer()->CleanUpTilingsOnActiveLayer(used_tilings); EXPECT_FLOAT_EQ(2u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f * low_res_factor, - active_layer()->tilings()->tiling_at(1)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f * low_res_factor, + active_layer()->tilings()->tiling_at(1)->contents_scale_key()); host_impl()->PinchGestureBegin(); @@ -905,19 +911,21 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) { page_scale = 1.5f; SetContentsScaleOnBothLayers(scale, 1.f, page_scale, 1.f, 0.f, false); EXPECT_FLOAT_EQ(2u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f * low_res_factor, - active_layer()->tilings()->tiling_at(1)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f * low_res_factor, + active_layer()->tilings()->tiling_at(1)->contents_scale_key()); // The tilings are still our target scale, so they aren't removed. used_tilings.clear(); active_layer()->CleanUpTilingsOnActiveLayer(used_tilings); ASSERT_EQ(2u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f * low_res_factor, - active_layer()->tilings()->tiling_at(1)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f * low_res_factor, + active_layer()->tilings()->tiling_at(1)->contents_scale_key()); host_impl()->PinchGestureEnd(); @@ -926,14 +934,16 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) { page_scale = 1.2f; SetContentsScaleOnBothLayers(1.2f, 1.f, page_scale, 1.f, 0.f, false); ASSERT_EQ(4u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.2f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); - EXPECT_FLOAT_EQ(1.2f * low_res_factor, - active_layer()->tilings()->tiling_at(2)->contents_scale()); - EXPECT_FLOAT_EQ(1.f * low_res_factor, - active_layer()->tilings()->tiling_at(3)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.2f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.2f * low_res_factor, + active_layer()->tilings()->tiling_at(2)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f * low_res_factor, + active_layer()->tilings()->tiling_at(3)->contents_scale_key()); // Ensure UpdateTiles won't remove any tilings. active_layer()->MarkAllTilingsUsed(); @@ -944,14 +954,16 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) { used_tilings.push_back(active_layer()->tilings()->tiling_at(3)); active_layer()->CleanUpTilingsOnActiveLayer(used_tilings); ASSERT_EQ(4u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.2f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); - EXPECT_FLOAT_EQ(1.2f * low_res_factor, - active_layer()->tilings()->tiling_at(2)->contents_scale()); - EXPECT_FLOAT_EQ(1.f * low_res_factor, - active_layer()->tilings()->tiling_at(3)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.2f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.2f * low_res_factor, + active_layer()->tilings()->tiling_at(2)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f * low_res_factor, + active_layer()->tilings()->tiling_at(3)->contents_scale_key()); // Now move the ideal scale to 0.5. Our target stays 1.2. SetContentsScaleOnBothLayers(0.5f, 1.f, page_scale, 1.f, 0.f, false); @@ -961,12 +973,13 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) { used_tilings.clear(); active_layer()->CleanUpTilingsOnActiveLayer(used_tilings); ASSERT_EQ(3u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.2f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); - EXPECT_FLOAT_EQ(1.2f * low_res_factor, - active_layer()->tilings()->tiling_at(2)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.2f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.2f * low_res_factor, + active_layer()->tilings()->tiling_at(2)->contents_scale_key()); // Now move the ideal scale to 1.0. Our target stays 1.2. SetContentsScaleOnBothLayers(1.f, 1.f, page_scale, 1.f, 0.f, false); @@ -976,12 +989,13 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) { used_tilings.clear(); active_layer()->CleanUpTilingsOnActiveLayer(used_tilings); ASSERT_EQ(3u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.2f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); - EXPECT_FLOAT_EQ(1.2f * low_res_factor, - active_layer()->tilings()->tiling_at(2)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.2f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.2f * low_res_factor, + active_layer()->tilings()->tiling_at(2)->contents_scale_key()); // Now move the ideal scale to 1.1 on the active layer. Our target stays 1.2. SetupDrawPropertiesAndUpdateTiles(active_layer(), 1.1f, 1.f, page_scale, 1.f, @@ -992,12 +1006,13 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) { used_tilings.clear(); active_layer()->CleanUpTilingsOnActiveLayer(used_tilings); ASSERT_EQ(3u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.2f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); - EXPECT_FLOAT_EQ(1.2f * low_res_factor, - active_layer()->tilings()->tiling_at(2)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.2f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.2f * low_res_factor, + active_layer()->tilings()->tiling_at(2)->contents_scale_key()); // Move the ideal scale on the pending layer to 1.1 as well. Our target stays // 1.2 still. @@ -1011,22 +1026,24 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) { used_tilings.push_back(active_layer()->tilings()->tiling_at(1)); active_layer()->CleanUpTilingsOnActiveLayer(used_tilings); ASSERT_EQ(3u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.2f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); - EXPECT_FLOAT_EQ(1.2f * low_res_factor, - active_layer()->tilings()->tiling_at(2)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.2f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.2f * low_res_factor, + active_layer()->tilings()->tiling_at(2)->contents_scale_key()); // If we remove it from our used tilings set, it is outside the range to keep // so it is deleted. used_tilings.clear(); active_layer()->CleanUpTilingsOnActiveLayer(used_tilings); ASSERT_EQ(2u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.2f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(1.2 * low_res_factor, - active_layer()->tilings()->tiling_at(1)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.2f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_FLOAT_EQ( + 1.2 * low_res_factor, + active_layer()->tilings()->tiling_at(1)->contents_scale_key()); } TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) { @@ -1051,7 +1068,7 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 1.f); EXPECT_BOTH_EQ(num_tilings(), 1u); // Stop animating, low res gets created. @@ -1059,8 +1076,9 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f); - EXPECT_EQ(active_layer()->LowResTiling()->contents_scale(), low_res_factor); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 1.f); + EXPECT_EQ(active_layer()->LowResTiling()->contents_scale_key(), + low_res_factor); EXPECT_EQ(active_layer()->num_tilings(), 2u); EXPECT_EQ(pending_layer()->num_tilings(), 1u); @@ -1077,7 +1095,7 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f); EXPECT_FALSE(active_layer()->LowResTiling()); EXPECT_FALSE(pending_layer()->LowResTiling()); EXPECT_EQ(3u, active_layer()->num_tilings()); @@ -1088,8 +1106,8 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); - EXPECT_EQ(active_layer()->LowResTiling()->contents_scale(), + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f); + EXPECT_EQ(active_layer()->LowResTiling()->contents_scale_key(), 2.f * low_res_factor); EXPECT_EQ(4u, active_layer()->num_tilings()); EXPECT_EQ(1u, pending_layer()->num_tilings()); @@ -1117,7 +1135,7 @@ TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), contents_scale); EXPECT_BOTH_EQ(num_tilings(), 1u); ResetTilingsAndRasterScales(); @@ -1127,7 +1145,7 @@ TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), contents_scale); EXPECT_BOTH_EQ(num_tilings(), 1u); // TODO(danakj): Remove these when raster scale doesn't get fixed? @@ -1139,8 +1157,8 @@ TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale); - EXPECT_EQ(active_layer()->LowResTiling()->contents_scale(), + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), contents_scale); + EXPECT_EQ(active_layer()->LowResTiling()->contents_scale_key(), contents_scale * low_res_factor); EXPECT_FALSE(pending_layer()->LowResTiling()); EXPECT_EQ(active_layer()->num_tilings(), 2u); @@ -1167,7 +1185,7 @@ TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) { SetupDrawPropertiesAndUpdateTiles( mask_raw, contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_EQ(mask_raw->HighResTiling()->contents_scale(), contents_scale); + EXPECT_EQ(mask_raw->HighResTiling()->contents_scale_key(), contents_scale); EXPECT_EQ(mask_raw->num_tilings(), 1u); } @@ -1196,7 +1214,7 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) { FakePictureLayerImpl* pending_mask = static_cast<FakePictureLayerImpl*>( pending_layer()->test_properties()->mask_layer); - EXPECT_EQ(1.f, pending_mask->HighResTiling()->contents_scale()); + EXPECT_EQ(1.f, pending_mask->HighResTiling()->contents_scale_key()); EXPECT_EQ(1u, pending_mask->num_tilings()); host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting( @@ -1242,7 +1260,7 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) { host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text); // The mask tiling gets scaled down. - EXPECT_LT(pending_mask->HighResTiling()->contents_scale(), 1.f); + EXPECT_LT(pending_mask->HighResTiling()->contents_scale_key(), 1.f); EXPECT_EQ(1u, pending_mask->num_tilings()); host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting( @@ -1326,7 +1344,7 @@ TEST_F(PictureLayerImplTest, ScaledMaskLayer) { pending_layer()->test_properties()->mask_layer); // Masks are scaled, and do not have a low res tiling. - EXPECT_EQ(1.3f, pending_mask->HighResTiling()->contents_scale()); + EXPECT_EQ(1.3f, pending_mask->HighResTiling()->contents_scale_key()); EXPECT_EQ(1u, pending_mask->num_tilings()); host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting( @@ -1661,7 +1679,7 @@ TEST_F(NoLowResPictureLayerImplTest, SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region()); ASSERT_EQ(1u, pending_layer()->num_tilings()); - ASSERT_EQ(1.f, pending_layer()->HighResTiling()->contents_scale()); + ASSERT_EQ(1.f, pending_layer()->HighResTiling()->contents_scale_key()); // Set external viewport for tile priority. gfx::Transform transform; @@ -1859,7 +1877,7 @@ TEST_F(PictureLayerImplTest, // One ideal tile exists, this will get used when drawing. std::vector<Tile*> ideal_tiles; - EXPECT_EQ(2.f, active_layer()->HighResTiling()->contents_scale()); + EXPECT_EQ(2.f, active_layer()->HighResTiling()->contents_scale_key()); ideal_tiles.push_back(active_layer()->HighResTiling()->TileAt(0, 0)); host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting( ideal_tiles); @@ -1871,13 +1889,13 @@ TEST_F(PictureLayerImplTest, SetupDrawPropertiesAndUpdateTiles(active_layer(), 2.f, 1.f, 1.f, 1.f, 0.f, false); - EXPECT_EQ(1.f, active_layer()->HighResTiling()->contents_scale()); + EXPECT_EQ(1.f, active_layer()->HighResTiling()->contents_scale_key()); EXPECT_EQ(1.f, active_layer()->raster_contents_scale()); EXPECT_EQ(2.f, active_layer()->ideal_contents_scale()); // Both tilings still exist. - EXPECT_EQ(2.f, active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_EQ(1.f, active_layer()->tilings()->tiling_at(1)->contents_scale()); + EXPECT_EQ(2.f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_EQ(1.f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); // All high res tiles have resources. std::vector<Tile*> high_tiles = @@ -2451,7 +2469,7 @@ TEST_F(PictureLayerImplTest, FirstTilingDuringPinch) { SetupDefaultTrees(gfx::Size(10, 10)); // We start with a tiling at scale 1. - EXPECT_EQ(1.f, pending_layer()->HighResTiling()->contents_scale()); + EXPECT_EQ(1.f, pending_layer()->HighResTiling()->contents_scale_key()); // When we page scale up by 2.3, we get a new tiling that is a power of 2, in // this case 4. @@ -2459,14 +2477,14 @@ TEST_F(PictureLayerImplTest, FirstTilingDuringPinch) { float high_res_scale = 2.3f; SetContentsScaleOnBothLayers(high_res_scale, 1.f, high_res_scale, 1.f, 0.f, false); - EXPECT_EQ(4.f, pending_layer()->HighResTiling()->contents_scale()); + EXPECT_EQ(4.f, pending_layer()->HighResTiling()->contents_scale_key()); } TEST_F(PictureLayerImplTest, PinchingTooSmall) { SetupDefaultTrees(gfx::Size(10, 10)); // We start with a tiling at scale 1. - EXPECT_EQ(1.f, pending_layer()->HighResTiling()->contents_scale()); + EXPECT_EQ(1.f, pending_layer()->HighResTiling()->contents_scale_key()); host_impl()->PinchGestureBegin(); float high_res_scale = 0.0001f; @@ -2475,7 +2493,7 @@ TEST_F(PictureLayerImplTest, PinchingTooSmall) { SetContentsScaleOnBothLayers(high_res_scale, 1.f, high_res_scale, 1.f, 0.f, false); EXPECT_FLOAT_EQ(pending_layer()->MinimumContentsScale(), - pending_layer()->HighResTiling()->contents_scale()); + pending_layer()->HighResTiling()->contents_scale_key()); } TEST_F(PictureLayerImplTest, PinchingTooSmallWithContentsScale) { @@ -2488,7 +2506,7 @@ TEST_F(PictureLayerImplTest, PinchingTooSmallWithContentsScale) { ASSERT_GE(pending_layer()->num_tilings(), 0u); EXPECT_FLOAT_EQ(contents_scale, - pending_layer()->HighResTiling()->contents_scale()); + pending_layer()->HighResTiling()->contents_scale_key()); host_impl()->PinchGestureBegin(); @@ -2500,7 +2518,7 @@ TEST_F(PictureLayerImplTest, PinchingTooSmallWithContentsScale) { 1.f, 0.f, false); ASSERT_GE(pending_layer()->num_tilings(), 0u); EXPECT_FLOAT_EQ(pending_layer()->MinimumContentsScale(), - pending_layer()->HighResTiling()->contents_scale()); + pending_layer()->HighResTiling()->contents_scale_key()); } TEST_F(PictureLayerImplTest, ConsiderAnimationStartScaleForRasterScale) { @@ -2517,13 +2535,13 @@ TEST_F(PictureLayerImplTest, ConsiderAnimationStartScaleForRasterScale) { float starting_animation_scale = 1.f; bool animating_transform = true; - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 1.f); // Maximum animation scale is greater than starting animation scale SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 3.f); animating_transform = false; @@ -2531,7 +2549,7 @@ TEST_F(PictureLayerImplTest, ConsiderAnimationStartScaleForRasterScale) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f); // Starting animation scale greater than maximum animation scale // Bounds at starting scale within the viewport @@ -2541,14 +2559,14 @@ TEST_F(PictureLayerImplTest, ConsiderAnimationStartScaleForRasterScale) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 5.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 5.f); // Once we stop animating, a new high-res tiling should be created. animating_transform = false; SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f); // Starting Animation scale greater than maximum animation scale // Bounds at starting scale outisde the viewport @@ -2558,7 +2576,7 @@ TEST_F(PictureLayerImplTest, ConsiderAnimationStartScaleForRasterScale) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 3.f); } TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { @@ -2575,7 +2593,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { float starting_animation_scale = 0.f; bool animating_transform = false; - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 1.f); // Starting an animation should cause tiling resolution to get set to the // maximum animation scale factor. @@ -2586,7 +2604,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 3.f); // Further changes to scale during the animation should not cause a new // high-res tiling to get created. @@ -2596,7 +2614,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 3.f); // Once we stop animating, a new high-res tiling should be created. animating_transform = false; @@ -2604,7 +2622,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 4.f); // When animating with an unknown maximum animation scale factor, a new // high-res tiling should be created at a source scale of 1. @@ -2615,7 +2633,8 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), page_scale * device_scale); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), + page_scale * device_scale); // Further changes to scale during the animation should not cause a new // high-res tiling to get created. @@ -2624,7 +2643,8 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), page_scale * device_scale); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), + page_scale * device_scale); // Once we stop animating, a new high-res tiling should be created. animating_transform = false; @@ -2633,7 +2653,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 4.f); // When animating with a maxmium animation scale factor that is so large // that the layer grows larger than the viewport at this scale, a new @@ -2646,7 +2666,8 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), page_scale * device_scale); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), + page_scale * device_scale); // Once we stop animating, a new high-res tiling should be created. animating_transform = false; @@ -2655,7 +2676,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 11.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 11.f); // When animating with a maxmium animation scale factor that is so large // that the layer grows larger than the viewport at this scale, and where @@ -2668,7 +2689,8 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), device_scale * page_scale); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), + device_scale * page_scale); // Once we stop animating, a new high-res tiling should be created. animating_transform = false; @@ -2677,7 +2699,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 12.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 12.f); // When animating toward a smaller scale, but that is still so large that the // layer grows larger than the viewport at this scale, a new high-res tiling @@ -2689,7 +2711,8 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), device_scale * page_scale); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), + device_scale * page_scale); // Once we stop animating, a new high-res tiling should be created. animating_transform = false; @@ -2698,7 +2721,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 11.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 11.f); } TEST_F(PictureLayerImplTest, TilingSetRasterQueue) { @@ -2963,18 +2986,19 @@ TEST_F(PictureLayerImplTest, TilingSetEvictionQueue) { EXPECT_FALSE(tile->required_for_activation()); - while (std::abs(tile->contents_scale() - expected_scales[scale_index]) > + while (std::abs(tile->contents_scale_key() - expected_scales[scale_index]) > std::numeric_limits<float>::epsilon()) { ++scale_index; ASSERT_LT(scale_index, arraysize(expected_scales)); } - EXPECT_FLOAT_EQ(tile->contents_scale(), expected_scales[scale_index]); + EXPECT_FLOAT_EQ(tile->contents_scale_key(), expected_scales[scale_index]); unique_tiles.insert(tile); if (tile->required_for_activation() == last_tile.tile()->required_for_activation() && - std::abs(tile->contents_scale() - last_tile.tile()->contents_scale()) < + std::abs(tile->contents_scale_key() - + last_tile.tile()->contents_scale_key()) < std::numeric_limits<float>::epsilon()) { if (priority.distance_to_visible <= last_tile.priority().distance_to_visible) @@ -3010,13 +3034,13 @@ TEST_F(PictureLayerImplTest, TilingSetEvictionQueue) { scale_index = 0; } - while (std::abs(tile->contents_scale() - expected_scales[scale_index]) > + while (std::abs(tile->contents_scale_key() - expected_scales[scale_index]) > std::numeric_limits<float>::epsilon()) { ++scale_index; ASSERT_LT(scale_index, arraysize(expected_scales)); } - EXPECT_FLOAT_EQ(tile->contents_scale(), expected_scales[scale_index]); + EXPECT_FLOAT_EQ(tile->contents_scale_key(), expected_scales[scale_index]); unique_tiles.insert(tile); queue->Pop(); } @@ -3091,7 +3115,7 @@ TEST_F(PictureLayerImplTest, RasterScaleChangeWithoutAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f); // Changing the source scale without being in an animation will cause // the layer to change scale. @@ -3100,14 +3124,14 @@ TEST_F(PictureLayerImplTest, RasterScaleChangeWithoutAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 3.f); contents_scale = 0.5f; SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 0.5f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 0.5f); // However, if the layer has a will-change property, then the raster scale // will get fixed at the last value. @@ -3119,7 +3143,7 @@ TEST_F(PictureLayerImplTest, RasterScaleChangeWithoutAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 0.5f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 0.5f); // Further changes to the source scale will no longer be reflected in the // contents scale. @@ -3128,7 +3152,7 @@ TEST_F(PictureLayerImplTest, RasterScaleChangeWithoutAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 0.5f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 0.5f); // Disabling the will-change hint will once again make the raster scale update // with the ideal scale. @@ -3140,7 +3164,7 @@ TEST_F(PictureLayerImplTest, RasterScaleChangeWithoutAnimation) { SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, starting_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 3.f); } TEST_F(PictureLayerImplTest, LowResReadyToDrawNotEnoughToActivate) { @@ -3223,8 +3247,8 @@ TEST_F(NoLowResPictureLayerImplTest, ManageTilingsCreatesTilings) { 0.f, // starting animation scale false); ASSERT_EQ(1u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(6.f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 6.f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); // If we change the page scale factor, then we should get new tilings. SetupDrawPropertiesAndUpdateTiles(active_layer(), @@ -3235,8 +3259,8 @@ TEST_F(NoLowResPictureLayerImplTest, ManageTilingsCreatesTilings) { 0.f, // starting animation scale false); ASSERT_EQ(2u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(6.6f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 6.6f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); // If we change the device scale factor, then we should get new tilings. SetupDrawPropertiesAndUpdateTiles(active_layer(), @@ -3247,8 +3271,8 @@ TEST_F(NoLowResPictureLayerImplTest, ManageTilingsCreatesTilings) { 0.f, // starting animation scale false); ASSERT_EQ(3u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(7.26f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 7.26f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); // If we change the device scale factor, but end up at the same total scale // factor somehow, then we don't get new tilings. @@ -3260,8 +3284,8 @@ TEST_F(NoLowResPictureLayerImplTest, ManageTilingsCreatesTilings) { 0.f, // starting animation scale false); ASSERT_EQ(3u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(7.26f, - active_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 7.26f, active_layer()->tilings()->tiling_at(0)->contents_scale_key()); } TEST_F(NoLowResPictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { @@ -3281,8 +3305,8 @@ TEST_F(NoLowResPictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { 0.f, // starting animation scale false); ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(6.f, - pending_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 6.f, pending_layer()->tilings()->tiling_at(0)->contents_scale_key()); // If we change the page scale factor, then we should get new tilings. SetupDrawPropertiesAndUpdateTiles(pending_layer(), @@ -3293,8 +3317,8 @@ TEST_F(NoLowResPictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { 0.f, // starting animation scale false); ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(6.6f, - pending_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 6.6f, pending_layer()->tilings()->tiling_at(0)->contents_scale_key()); // If we change the device scale factor, then we should get new tilings. SetupDrawPropertiesAndUpdateTiles(pending_layer(), @@ -3305,8 +3329,8 @@ TEST_F(NoLowResPictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { 0.f, // starting animation scale false); ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(7.26f, - pending_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 7.26f, pending_layer()->tilings()->tiling_at(0)->contents_scale_key()); // If we change the device scale factor, but end up at the same total scale // factor somehow, then we don't get new tilings. @@ -3318,8 +3342,8 @@ TEST_F(NoLowResPictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { 0.f, // starting animation scale false); ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(7.26f, - pending_layer()->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ( + 7.26f, pending_layer()->tilings()->tiling_at(0)->contents_scale_key()); } TEST_F(NoLowResPictureLayerImplTest, AllHighResRequiredEvenIfNotChanged) { @@ -3429,8 +3453,8 @@ TEST_F(NoLowResPictureLayerImplTest, CleanUpTilings) { page_scale /= 4.f; SetContentsScaleOnBothLayers(1.2f, device_scale, page_scale, 1.f, 0.f, false); ASSERT_EQ(2u, active_layer()->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(1.f, - active_layer()->tilings()->tiling_at(1)->contents_scale()); + EXPECT_FLOAT_EQ( + 1.f, active_layer()->tilings()->tiling_at(1)->contents_scale_key()); // Ensure UpdateTiles won't remove any tilings. active_layer()->MarkAllTilingsUsed(); @@ -3651,8 +3675,8 @@ class OcclusionTrackingPictureLayerImplTest : public PictureLayerImplTest { EXPECT_TRUE(tile_priority_bin < last_tile_priority_bin || tile->required_for_activation() || - tile->contents_scale() != - last_tile.tile()->contents_scale()) + tile->contents_scale_key() != + last_tile.tile()->contents_scale_key()) << "line: " << source_line; } } @@ -3930,7 +3954,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) { for (size_t j = 0; j < tiles.size(); ++j) { if (prioritized_tiles[tiles[j]].is_occluded()) { gfx::Rect scaled_content_rect = ScaleToEnclosingRect( - tiles[j]->content_rect(), 1.f / tiles[j]->contents_scale()); + tiles[j]->content_rect(), 1.f / tiles[j]->contents_scale_key()); EXPECT_GE(scaled_content_rect.x(), occluding_layer_position.x()); occluded_tile_count++; } @@ -3994,7 +4018,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) { const Tile* tile = *iter; gfx::Rect scaled_content_rect = ScaleToEnclosingRect( - tile->content_rect(), 1.f / tile->contents_scale()); + tile->content_rect(), 1.f / tile->contents_scale_key()); // Tiles are occluded on the active tree iff they lie beneath the // occluding layer. EXPECT_EQ(prioritized_tiles[tile].is_occluded(), @@ -4030,7 +4054,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) { active_layer()->GetPendingOrActiveTwinTiling(tiling)->TileAt( iter.i(), iter.j()); gfx::Rect scaled_content_rect = ScaleToEnclosingRect( - tile->content_rect(), 1.f / tile->contents_scale()); + tile->content_rect(), 1.f / tile->contents_scale_key()); if (scaled_content_rect.Intersects(invalidation_rect)) { // Tiles inside the invalidation rect exist on both trees. @@ -4138,7 +4162,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, } EXPECT_EQ(expected_occluded_tile_count_on_pending[i], occluded_tile_count_on_pending) - << tiling->contents_scale(); + << tiling->contents_scale_key(); } // Verify number of occluded tiles on the active layer for each tiling. @@ -4249,7 +4273,8 @@ void GetClientDataAndUpdateInvalidation(RecordingSource* recording_source, painter_reported_memory_usage); } -void PictureLayerImplTest::TestQuadsForSolidColor(bool test_for_solid) { +void PictureLayerImplTest::TestQuadsForSolidColor(bool test_for_solid, + bool partial_opaque) { host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); gfx::Size tile_size(100, 100); @@ -4268,6 +4293,10 @@ void PictureLayerImplTest::TestQuadsForSolidColor(bool test_for_solid) { RecordingSource* recording_source = layer->GetRecordingSourceForTesting(); client.set_fill_with_nonsolid_color(!test_for_solid); + PaintFlags flags; + flags.setColor(SK_ColorRED); + if (test_for_solid) + client.add_draw_rect(layer_rect, flags); Region invalidation(layer_rect); @@ -4291,12 +4320,28 @@ void PictureLayerImplTest::TestQuadsForSolidColor(bool test_for_solid) { host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(tiles); } + if (partial_opaque) { + std::vector<Tile*> high_res_tiles = + active_layer()->HighResTiling()->AllTilesForTesting(); + size_t i = 0; + for (std::vector<Tile*>::iterator tile_it = high_res_tiles.begin(); + tile_it != high_res_tiles.end() && i < 5; ++tile_it, ++i) { + Tile* tile = *tile_it; + TileDrawInfo& draw_info = tile->draw_info(); + draw_info.SetSolidColorForTesting(0); + } + } + std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); AppendQuadsData data; active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr); active_layer()->AppendQuads(render_pass.get(), &data); active_layer()->DidDraw(nullptr); + // Transparent quads should be eliminated. + if (partial_opaque) + EXPECT_EQ(4u, render_pass->quad_list.size()); + DrawQuad::Material expected = test_for_solid ? DrawQuad::Material::SOLID_COLOR : DrawQuad::Material::TILED_CONTENT; @@ -4304,11 +4349,15 @@ void PictureLayerImplTest::TestQuadsForSolidColor(bool test_for_solid) { } TEST_F(PictureLayerImplTest, DrawSolidQuads) { - TestQuadsForSolidColor(true); + TestQuadsForSolidColor(true, false); } TEST_F(PictureLayerImplTest, DrawNonSolidQuads) { - TestQuadsForSolidColor(false); + TestQuadsForSolidColor(false, false); +} + +TEST_F(PictureLayerImplTest, DrawTransparentQuads) { + TestQuadsForSolidColor(false, true); } TEST_F(PictureLayerImplTest, NonSolidToSolidNoTilings) { @@ -4728,7 +4777,7 @@ TEST_F(NoLowResPictureLayerImplTest, LowResWasHighResCollision) { 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); + EXPECT_BOTH_EQ(tilings()->tiling_at(0)->contents_scale_key(), page_scale); host_impl()->PinchGestureBegin(); @@ -4737,7 +4786,8 @@ TEST_F(NoLowResPictureLayerImplTest, LowResWasHighResCollision) { 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()); + EXPECT_EQ(zoomed, + pending_layer()->tilings()->tiling_at(0)->contents_scale_key()); } TEST_F(PictureLayerImplTest, HighResWasLowResCollision) { @@ -4755,8 +4805,9 @@ TEST_F(PictureLayerImplTest, HighResWasLowResCollision) { page_scale, 1.0f, 0.f, false); EXPECT_EQ(2u, active_layer()->tilings()->num_tilings()); EXPECT_EQ(page_scale, - active_layer()->tilings()->tiling_at(0)->contents_scale()); - EXPECT_EQ(low_res, active_layer()->tilings()->tiling_at(1)->contents_scale()); + active_layer()->tilings()->tiling_at(0)->contents_scale_key()); + EXPECT_EQ(low_res, + active_layer()->tilings()->tiling_at(1)->contents_scale_key()); // Grab a current low res tile. PictureLayerTiling* old_low_res_tiling = @@ -4781,9 +4832,9 @@ TEST_F(PictureLayerImplTest, HighResWasLowResCollision) { EXPECT_EQ(3u, active_layer()->num_tilings()); PictureLayerTilingSet* tilings = active_layer()->tilings(); - EXPECT_EQ(page_scale, tilings->tiling_at(0)->contents_scale()); - EXPECT_EQ(low_res, tilings->tiling_at(1)->contents_scale()); - EXPECT_EQ(extra_low_res, tilings->tiling_at(2)->contents_scale()); + EXPECT_EQ(page_scale, tilings->tiling_at(0)->contents_scale_key()); + EXPECT_EQ(low_res, tilings->tiling_at(1)->contents_scale_key()); + EXPECT_EQ(extra_low_res, tilings->tiling_at(2)->contents_scale_key()); EXPECT_EQ(NON_IDEAL_RESOLUTION, tilings->tiling_at(0)->resolution()); EXPECT_EQ(HIGH_RESOLUTION, tilings->tiling_at(1)->resolution()); @@ -4854,7 +4905,8 @@ TEST_F(PictureLayerImplTest, CompositedImageIgnoreIdealContentsScale) { pending_layer_ptr, suggested_ideal_contents_scale, device_scale_factor, page_scale_factor, animation_contents_scale, animation_contents_scale, animating_transform_to_screen); - EXPECT_EQ(1.f, pending_layer_ptr->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(1.f, + pending_layer_ptr->tilings()->tiling_at(0)->contents_scale_key()); // Push to active layer. host_impl()->ActivateSyncTree(); @@ -4865,7 +4917,7 @@ TEST_F(PictureLayerImplTest, CompositedImageIgnoreIdealContentsScale) { active_layer, suggested_ideal_contents_scale, device_scale_factor, page_scale_factor, animation_contents_scale, animation_contents_scale, animating_transform_to_screen); - EXPECT_EQ(1.f, active_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(1.f, active_layer->tilings()->tiling_at(0)->contents_scale_key()); active_layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); // Create resources for the tiles. @@ -4921,7 +4973,7 @@ TEST_F(PictureLayerImplTest, CompositedImageRasterScaleChanges) { EXPECT_FLOAT_EQ(expected_contents_scale, pending_layer_ptr->picture_layer_tiling_set() ->FindTilingWithResolution(HIGH_RESOLUTION) - ->contents_scale()) + ->contents_scale_key()) << "ideal_contents_scale: " << ideal_contents_scale; } @@ -4943,7 +4995,7 @@ TEST_F(PictureLayerImplTest, CompositedImageRasterScaleChanges) { EXPECT_FLOAT_EQ(expected_contents_scale, pending_layer_ptr->picture_layer_tiling_set() ->FindTilingWithResolution(HIGH_RESOLUTION) - ->contents_scale()) + ->contents_scale_key()) << "ideal_contents_scale: " << ideal_contents_scale; } } diff --git a/chromium/cc/layers/picture_layer_unittest.cc b/chromium/cc/layers/picture_layer_unittest.cc index c151267bde9..1ba4387702c 100644 --- a/chromium/cc/layers/picture_layer_unittest.cc +++ b/chromium/cc/layers/picture_layer_unittest.cc @@ -11,16 +11,15 @@ #include "cc/animation/animation_host.h" #include "cc/layers/append_quads_data.h" #include "cc/layers/content_layer_client.h" -#include "cc/layers/empty_content_layer_client.h" #include "cc/layers/picture_layer_impl.h" #include "cc/paint/paint_flags.h" #include "cc/test/fake_compositor_frame_sink.h" +#include "cc/test/fake_content_layer_client.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/fake_recording_source.h" -#include "cc/test/layer_tree_settings_for_testing.h" #include "cc/test/skia_common.h" #include "cc/test/stub_layer_tree_host_single_thread_client.h" #include "cc/test/test_task_graph_runner.h" @@ -34,8 +33,9 @@ namespace cc { namespace { TEST(PictureLayerTest, NoTilesIfEmptyBounds) { - ContentLayerClient* client = EmptyContentLayerClient::GetInstance(); - scoped_refptr<PictureLayer> layer = PictureLayer::Create(client); + FakeContentLayerClient client; + client.set_bounds(gfx::Size()); + scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client); layer->SetBounds(gfx::Size(10, 10)); FakeLayerTreeHostClient host_client; @@ -101,7 +101,7 @@ TEST(PictureLayerTest, InvalidateRasterAfterUpdate) { FakeImplTaskRunnerProvider impl_task_runner_provider; std::unique_ptr<CompositorFrameSink> compositor_frame_sink( FakeCompositorFrameSink::Create3d()); - LayerTreeSettings layer_tree_settings = LayerTreeSettingsForTesting(); + LayerTreeSettings layer_tree_settings = LayerTreeSettings(); layer_tree_settings.image_decode_tasks_enabled = true; FakeLayerTreeHostImpl host_impl( layer_tree_settings, &impl_task_runner_provider, &task_graph_runner); @@ -144,7 +144,7 @@ TEST(PictureLayerTest, InvalidateRasterWithoutUpdate) { FakeImplTaskRunnerProvider impl_task_runner_provider; std::unique_ptr<CompositorFrameSink> compositor_frame_sink( FakeCompositorFrameSink::Create3d()); - LayerTreeSettings layer_tree_settings = LayerTreeSettingsForTesting(); + LayerTreeSettings layer_tree_settings = LayerTreeSettings(); layer_tree_settings.image_decode_tasks_enabled = true; FakeLayerTreeHostImpl host_impl( layer_tree_settings, &impl_task_runner_provider, &task_graph_runner); @@ -191,7 +191,7 @@ TEST(PictureLayerTest, ClearVisibleRectWhenNoTiling) { std::unique_ptr<CompositorFrameSink> compositor_frame_sink( FakeCompositorFrameSink::Create3d()); - LayerTreeSettings layer_tree_settings = LayerTreeSettingsForTesting(); + LayerTreeSettings layer_tree_settings = LayerTreeSettings(); layer_tree_settings.image_decode_tasks_enabled = true; FakeLayerTreeHostImpl host_impl( layer_tree_settings, &impl_task_runner_provider, &task_graph_runner); @@ -247,10 +247,11 @@ TEST(PictureLayerTest, SuitableForGpuRasterization) { new FakeRecordingSource); FakeRecordingSource* recording_source = recording_source_owned.get(); - ContentLayerClient* client = EmptyContentLayerClient::GetInstance(); + FakeContentLayerClient client; + client.set_bounds(gfx::Size()); scoped_refptr<FakePictureLayer> layer = FakePictureLayer::CreateWithRecordingSource( - client, std::move(recording_source_owned)); + &client, std::move(recording_source_owned)); FakeLayerTreeHostClient host_client; TestTaskGraphRunner task_graph_runner; @@ -264,12 +265,12 @@ TEST(PictureLayerTest, SuitableForGpuRasterization) { gfx::Rect layer_rect(layer_bounds); Region invalidation(layer_rect); - gfx::Rect new_recorded_viewport = client->PaintableRegion(); + gfx::Rect new_recorded_viewport = client.PaintableRegion(); scoped_refptr<DisplayItemList> display_list = - client->PaintContentsToDisplayList( + client.PaintContentsToDisplayList( ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); size_t painter_reported_memory_usage = - client->GetApproximateUnsharedMemoryUsage(); + client.GetApproximateUnsharedMemoryUsage(); recording_source->UpdateAndExpandInvalidation(&invalidation, layer_bounds, new_recorded_viewport); recording_source->UpdateDisplayItemList(display_list, @@ -288,7 +289,7 @@ TEST(PictureLayerTest, SuitableForGpuRasterization) { // non-monotonically. This executes that code path under this scenario allowing // for the code to verify correctness with DCHECKs. TEST(PictureLayerTest, NonMonotonicSourceFrameNumber) { - LayerTreeSettings settings = LayerTreeSettingsForTesting(); + LayerTreeSettings settings = LayerTreeSettings(); settings.single_thread_proxy_scheduler = false; settings.use_zero_copy = true; @@ -297,8 +298,9 @@ TEST(PictureLayerTest, NonMonotonicSourceFrameNumber) { FakeLayerTreeHostClient host_client2; TestTaskGraphRunner task_graph_runner; - ContentLayerClient* client = EmptyContentLayerClient::GetInstance(); - scoped_refptr<FakePictureLayer> layer = FakePictureLayer::Create(client); + FakeContentLayerClient client; + client.set_bounds(gfx::Size()); + scoped_refptr<FakePictureLayer> layer = FakePictureLayer::Create(&client); auto animation_host = AnimationHost::CreateForTesting(ThreadInstance::MAIN); diff --git a/chromium/cc/playback/recording_source.cc b/chromium/cc/layers/recording_source.cc index abb7b0af3f6..9b1efbd7137 100644 --- a/chromium/cc/playback/recording_source.cc +++ b/chromium/cc/layers/recording_source.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/recording_source.h" +#include "cc/layers/recording_source.h" #include <stdint.h> @@ -11,8 +11,8 @@ #include "base/numerics/safe_math.h" #include "cc/base/region.h" #include "cc/layers/content_layer_client.h" -#include "cc/playback/display_item_list.h" -#include "cc/playback/raster_source.h" +#include "cc/paint/display_item_list.h" +#include "cc/raster/raster_source.h" #include "skia/ext/analysis_canvas.h" namespace { diff --git a/chromium/cc/playback/recording_source.h b/chromium/cc/layers/recording_source.h index 802aaf65bd0..dadb0e77548 100644 --- a/chromium/cc/playback/recording_source.h +++ b/chromium/cc/layers/recording_source.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_PLAYBACK_RECORDING_SOURCE_H_ -#define CC_PLAYBACK_RECORDING_SOURCE_H_ +#ifndef CC_LAYERS_RECORDING_SOURCE_H_ +#define CC_LAYERS_RECORDING_SOURCE_H_ #include <stddef.h> @@ -11,8 +11,8 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" #include "cc/base/invalidation_region.h" +#include "cc/cc_export.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -90,4 +90,4 @@ class CC_EXPORT RecordingSource { } // namespace cc -#endif // CC_PLAYBACK_RECORDING_SOURCE_H_ +#endif // CC_LAYERS_RECORDING_SOURCE_H_ diff --git a/chromium/cc/playback/recording_source_unittest.cc b/chromium/cc/layers/recording_source_unittest.cc index 2cbe3c8e138..2a034a77125 100644 --- a/chromium/cc/playback/recording_source_unittest.cc +++ b/chromium/cc/layers/recording_source_unittest.cc @@ -6,7 +6,7 @@ #include "base/memory/ptr_util.h" #include "cc/base/region.h" -#include "cc/playback/raster_source.h" +#include "cc/raster/raster_source.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_recording_source.h" #include "cc/test/skia_common.h" @@ -17,6 +17,10 @@ namespace cc { namespace { +gfx::ColorSpace DefaultColorSpace() { + return gfx::ColorSpace::CreateSRGB(); +} + std::unique_ptr<FakeRecordingSource> CreateRecordingSource( const gfx::Rect& viewport) { gfx::Rect layer_rect(viewport.right(), viewport.bottom()); @@ -76,7 +80,7 @@ TEST(RecordingSourceTest, DiscardableImagesWithTransform) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 128, 128), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_EQ(2u, images.size()); EXPECT_TRUE(images[0].image() == discardable_image[0][0]); EXPECT_TRUE(images[1].image() == discardable_image[1][1]); @@ -85,8 +89,8 @@ TEST(RecordingSourceTest, DiscardableImagesWithTransform) { // Shifted tile sized iterators. These should find only one pixel ref. { std::vector<DrawImage> images; - raster_source->GetDiscardableImagesInRect(gfx::Rect(130, 140, 128, 128), - 1.f, &images); + raster_source->GetDiscardableImagesInRect( + gfx::Rect(130, 140, 128, 128), 1.f, DefaultColorSpace(), &images); EXPECT_EQ(1u, images.size()); EXPECT_TRUE(images[0].image() == discardable_image[1][1]); } @@ -95,7 +99,7 @@ TEST(RecordingSourceTest, DiscardableImagesWithTransform) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(130, 0, 128, 128), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_EQ(1u, images.size()); EXPECT_TRUE(images[0].image() == discardable_image[1][1]); } @@ -104,7 +108,7 @@ TEST(RecordingSourceTest, DiscardableImagesWithTransform) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_EQ(3u, images.size()); // Top left tile with bitmap[0][0] and bitmap[1][1]. EXPECT_TRUE(images[0].image() == discardable_image[0][0]); @@ -115,8 +119,8 @@ TEST(RecordingSourceTest, DiscardableImagesWithTransform) { // Verify different raster scales for (float scale = 1.f; scale <= 5.f; scale += 0.5f) { std::vector<DrawImage> images; - raster_source->GetDiscardableImagesInRect(gfx::Rect(130, 0, 128, 128), - scale, &images); + raster_source->GetDiscardableImagesInRect( + gfx::Rect(130, 0, 128, 128), scale, DefaultColorSpace(), &images); EXPECT_EQ(1u, images.size()); EXPECT_FLOAT_EQ(scale, images[0].scale().width()); EXPECT_FLOAT_EQ(scale, images[0].scale().height()); @@ -138,7 +142,8 @@ TEST(RecordingSourceTest, NoGatherImageEmptyImages) { // get images. { std::vector<DrawImage> images; - raster_source->GetDiscardableImagesInRect(recorded_viewport, 1.f, &images); + raster_source->GetDiscardableImagesInRect(recorded_viewport, 1.f, + DefaultColorSpace(), &images); EXPECT_TRUE(images.empty()); } } @@ -158,21 +163,21 @@ TEST(RecordingSourceTest, EmptyImages) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 128, 128), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_TRUE(images.empty()); } // Shifted tile sized iterators. { std::vector<DrawImage> images; - raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 140, 128, 128), - 1.f, &images); + raster_source->GetDiscardableImagesInRect( + gfx::Rect(140, 140, 128, 128), 1.f, DefaultColorSpace(), &images); EXPECT_TRUE(images.empty()); } // Layer sized iterators. { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_TRUE(images.empty()); } } @@ -213,21 +218,21 @@ TEST(RecordingSourceTest, NoDiscardableImages) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 128, 128), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_TRUE(images.empty()); } // Shifted tile sized iterators. { std::vector<DrawImage> images; - raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 140, 128, 128), - 1.f, &images); + raster_source->GetDiscardableImagesInRect( + gfx::Rect(140, 140, 128, 128), 1.f, DefaultColorSpace(), &images); EXPECT_TRUE(images.empty()); } // Layer sized iterators. { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_TRUE(images.empty()); } } @@ -263,7 +268,7 @@ TEST(RecordingSourceTest, DiscardableImages) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 128, 128), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_EQ(1u, images.size()); EXPECT_TRUE(images[0].image() == discardable_image[0][0]); } @@ -271,8 +276,8 @@ TEST(RecordingSourceTest, DiscardableImages) { // Shifted tile sized iterators. These should find only one image. { std::vector<DrawImage> images; - raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 140, 128, 128), - 1.f, &images); + raster_source->GetDiscardableImagesInRect( + gfx::Rect(140, 140, 128, 128), 1.f, DefaultColorSpace(), &images); EXPECT_EQ(1u, images.size()); EXPECT_TRUE(images[0].image() == discardable_image[1][1]); } @@ -281,7 +286,7 @@ TEST(RecordingSourceTest, DiscardableImages) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 0, 128, 128), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_TRUE(images.empty()); } @@ -289,7 +294,7 @@ TEST(RecordingSourceTest, DiscardableImages) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_EQ(3u, images.size()); EXPECT_TRUE(images[0].image() == discardable_image[0][0]); EXPECT_TRUE(images[1].image() == discardable_image[1][0]); @@ -336,15 +341,15 @@ TEST(RecordingSourceTest, DiscardableImagesBaseNonDiscardable) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_EQ(1u, images.size()); EXPECT_TRUE(images[0].image() == discardable_image[0][0]); } // Shifted tile sized iterators. These should find only one image. { std::vector<DrawImage> images; - raster_source->GetDiscardableImagesInRect(gfx::Rect(260, 260, 256, 256), - 1.f, &images); + raster_source->GetDiscardableImagesInRect( + gfx::Rect(260, 260, 256, 256), 1.f, DefaultColorSpace(), &images); EXPECT_EQ(1u, images.size()); EXPECT_TRUE(images[0].image() == discardable_image[1][1]); } @@ -352,14 +357,14 @@ TEST(RecordingSourceTest, DiscardableImagesBaseNonDiscardable) { { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 256, 256, 256), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_TRUE(images.empty()); } // Layer sized iterators. These should find three images. { std::vector<DrawImage> images; raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 512, 512), 1.f, - &images); + DefaultColorSpace(), &images); EXPECT_EQ(3u, images.size()); EXPECT_TRUE(images[0].image() == discardable_image[0][0]); EXPECT_TRUE(images[1].image() == discardable_image[0][1]); diff --git a/chromium/cc/layers/render_pass_sink.h b/chromium/cc/layers/render_pass_sink.h deleted file mode 100644 index aa5bfbcfc85..00000000000 --- a/chromium/cc/layers/render_pass_sink.h +++ /dev/null @@ -1,25 +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_RENDER_PASS_SINK_H_ -#define CC_LAYERS_RENDER_PASS_SINK_H_ - -#include <memory> - -#include "cc/base/cc_export.h" - -namespace cc { -class RenderPass; - -class CC_EXPORT RenderPassSink { - public: - virtual void AppendRenderPass(std::unique_ptr<RenderPass> render_pass) = 0; - - protected: - virtual ~RenderPassSink() {} -}; - -} // namespace cc - -#endif // CC_LAYERS_RENDER_PASS_SINK_H_ diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc index 4b6355631c1..a03fb006fec 100644 --- a/chromium/cc/layers/render_surface_impl.cc +++ b/chromium/cc/layers/render_surface_impl.cc @@ -10,15 +10,17 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" +#include "cc/base/filter_operations.h" #include "cc/base/math_util.h" #include "cc/debug/debug_colors.h" +#include "cc/layers/append_quads_data.h" #include "cc/layers/layer_impl.h" -#include "cc/layers/render_pass_sink.h" -#include "cc/output/filter_operations.h" +#include "cc/quads/content_draw_quad_base.h" #include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/render_pass.h" #include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/shared_quad_state.h" +#include "cc/quads/solid_color_draw_quad.h" #include "cc/trees/damage_tracker.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/effect_node.h" @@ -36,12 +38,11 @@ RenderSurfaceImpl::RenderSurfaceImpl(LayerTreeImpl* layer_tree_impl, : layer_tree_impl_(layer_tree_impl), stable_effect_id_(stable_effect_id), effect_tree_index_(EffectTree::kInvalidNodeId), + has_contributing_layer_that_escapes_clip_(false), surface_property_changed_(false), ancestor_property_changed_(false), contributes_to_drawn_surface_(false), - nearest_occlusion_immune_ancestor_(nullptr), - target_render_surface_layer_index_history_(0), - current_layer_index_history_(0) { + nearest_occlusion_immune_ancestor_(nullptr) { damage_tracker_ = DamageTracker::Create(); } @@ -81,7 +82,7 @@ gfx::RectF RenderSurfaceImpl::DrawableContentRect() const { const FilterOperations& filters = Filters(); if (!filters.IsEmpty()) { surface_content_rect = - filters.MapRect(surface_content_rect, FiltersTransform().matrix()); + filters.MapRect(surface_content_rect, SurfaceScale().matrix()); } gfx::RectF drawable_content_rect = MathUtil::MapClippedRect( draw_transform(), gfx::RectF(surface_content_rect)); @@ -114,7 +115,8 @@ SkColor RenderSurfaceImpl::GetDebugBorderColor() const { } float RenderSurfaceImpl::GetDebugBorderWidth() const { - return DebugColors::SurfaceBorderWidth(layer_tree_impl_); + return DebugColors::SurfaceBorderWidth( + layer_tree_impl_ ? layer_tree_impl_->device_scale_factor() : 1); } LayerImpl* RenderSurfaceImpl::MaskLayer() { @@ -134,11 +136,11 @@ gfx::PointF RenderSurfaceImpl::FiltersOrigin() const { return OwningEffectNode()->filters_origin; } -gfx::Transform RenderSurfaceImpl::FiltersTransform() const { - gfx::Transform filters_transform; - filters_transform.Scale(OwningEffectNode()->surface_contents_scale.x(), - OwningEffectNode()->surface_contents_scale.y()); - return filters_transform; +gfx::Transform RenderSurfaceImpl::SurfaceScale() const { + gfx::Transform surface_scale; + surface_scale.Scale(OwningEffectNode()->surface_contents_scale.x(), + OwningEffectNode()->surface_contents_scale.y()); + return surface_scale; } const FilterOperations& RenderSurfaceImpl::BackgroundFilters() const { @@ -158,9 +160,10 @@ int RenderSurfaceImpl::ClipTreeIndex() const { } int RenderSurfaceImpl::EffectTreeIndex() const { - DCHECK_EQ(effect_tree_index_, - layer_tree_impl_->property_trees() - ->layer_id_to_effect_node_index[stable_effect_id_]); + DCHECK_EQ( + effect_tree_index_, + layer_tree_impl_->property_trees() + ->effect_tree.FindNodeIndexFromOwningLayerId(stable_effect_id_)); return effect_tree_index_; } @@ -193,8 +196,8 @@ gfx::Rect RenderSurfaceImpl::CalculateExpandedClipForFilters( const gfx::Transform& target_to_surface) { gfx::Rect clip_in_surface_space = MathUtil::ProjectEnclosingClippedRect(target_to_surface, clip_rect()); - gfx::Rect expanded_clip_in_surface_space = Filters().MapRectReverse( - clip_in_surface_space, FiltersTransform().matrix()); + gfx::Rect expanded_clip_in_surface_space = + Filters().MapRectReverse(clip_in_surface_space, SurfaceScale().matrix()); gfx::Rect expanded_clip_in_target_space = MathUtil::MapEnclosingClippedRect( draw_transform(), expanded_clip_in_surface_space); return expanded_clip_in_target_space; @@ -357,7 +360,7 @@ int RenderSurfaceImpl::GetRenderPassId() { return id(); } -void RenderSurfaceImpl::AppendRenderPasses(RenderPassSink* pass_sink) { +std::unique_ptr<RenderPass> RenderSurfaceImpl::CreateRenderPass() { std::unique_ptr<RenderPass> pass = RenderPass::Create(layer_list_.size()); gfx::Rect damage_rect = GetDamageRect(); damage_rect.Intersect(content_rect()); @@ -365,7 +368,7 @@ void RenderSurfaceImpl::AppendRenderPasses(RenderPassSink* pass_sink) { draw_properties_.screen_space_transform); pass->filters = Filters(); pass->background_filters = BackgroundFilters(); - pass_sink->AppendRenderPass(std::move(pass)); + return pass; } void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass, @@ -386,7 +389,8 @@ void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass, draw_properties_.clip_rect, draw_properties_.is_clipped, draw_properties_.draw_opacity, BlendMode(), sorting_context_id); - if (layer_tree_impl_->debug_state().show_debug_borders) { + if (layer_tree_impl_->debug_state().show_debug_borders.test( + DebugBorderType::RENDERPASS)) { DebugBorderDrawQuad* debug_border_quad = render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>(); debug_border_quad->SetNew(shared_quad_state, content_rect(), @@ -396,10 +400,10 @@ void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass, ResourceId mask_resource_id = 0; gfx::Size mask_texture_size; - gfx::Vector2dF mask_uv_scale; + gfx::RectF mask_uv_rect; gfx::Vector2dF surface_contents_scale = OwningEffectNode()->surface_contents_scale; - LayerImpl* mask_layer = MaskLayer(); + PictureLayerImpl* mask_layer = static_cast<PictureLayerImpl*>(MaskLayer()); if (mask_layer && mask_layer->DrawsContent() && !mask_layer->bounds().IsEmpty()) { // The software renderer applies mask layer and blending in the wrong @@ -408,21 +412,139 @@ void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass, // mask layers. DCHECK(BlendMode() != SkBlendMode::kDstIn) << "kDstIn blend mode with mask layer is unsupported."; + if (mask_layer->mask_type() == Layer::LayerMaskType::MULTI_TEXTURE_MASK) { + TileMaskLayer(render_pass, shared_quad_state, visible_layer_rect); + return; + } mask_layer->GetContentsResourceId(&mask_resource_id, &mask_texture_size); gfx::SizeF unclipped_mask_target_size = gfx::ScaleSize( gfx::SizeF(OwningEffectNode()->unscaled_mask_target_size), surface_contents_scale.x(), surface_contents_scale.y()); - mask_uv_scale = gfx::Vector2dF(1.0f / unclipped_mask_target_size.width(), - 1.0f / unclipped_mask_target_size.height()); + // Convert content_rect from target space to normalized space. + // Where unclipped_mask_target_size maps to gfx::Size(1, 1). + mask_uv_rect = gfx::ScaleRect(gfx::RectF(content_rect()), + 1.0f / unclipped_mask_target_size.width(), + 1.0f / unclipped_mask_target_size.height()); } + gfx::RectF tex_coord_rect(gfx::Rect(content_rect().size())); RenderPassDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); - quad->SetNew( - shared_quad_state, content_rect(), visible_layer_rect, GetRenderPassId(), - mask_resource_id, gfx::ScaleRect(gfx::RectF(content_rect()), - mask_uv_scale.x(), mask_uv_scale.y()), - mask_texture_size, surface_contents_scale, FiltersOrigin(), gfx::RectF()); + quad->SetNew(shared_quad_state, content_rect(), visible_layer_rect, + GetRenderPassId(), mask_resource_id, mask_uv_rect, + mask_texture_size, surface_contents_scale, FiltersOrigin(), + tex_coord_rect); +} + +void RenderSurfaceImpl::TileMaskLayer(RenderPass* render_pass, + SharedQuadState* shared_quad_state, + const gfx::Rect& visible_layer_rect) { + DCHECK(MaskLayer()); + DCHECK(Filters().IsEmpty()); + + LayerImpl* mask_layer = MaskLayer(); + gfx::Vector2dF owning_layer_to_surface_contents_scale = + OwningEffectNode()->surface_contents_scale; + std::unique_ptr<RenderPass> temp_render_pass = RenderPass::Create(); + AppendQuadsData temp_append_quads_data; + mask_layer->AppendQuads(temp_render_pass.get(), &temp_append_quads_data); + + auto* temp_quad = temp_render_pass->quad_list.front(); + if (!temp_quad) + return; + gfx::Transform mask_quad_to_surface_contents = + temp_quad->shared_quad_state->quad_to_target_transform; + // Draw transform of a mask layer should be a 2d scale. + DCHECK(mask_quad_to_surface_contents.IsScale2d()); + gfx::Vector2dF mask_quad_to_surface_contents_scale = + mask_quad_to_surface_contents.Scale2d(); + shared_quad_state->quad_to_target_transform.matrix().preScale( + mask_quad_to_surface_contents_scale.x(), + mask_quad_to_surface_contents_scale.y(), 1.f); + shared_quad_state->quad_layer_bounds = + gfx::ScaleToCeiledSize(shared_quad_state->quad_layer_bounds, + 1.f / mask_quad_to_surface_contents_scale.x(), + 1.f / mask_quad_to_surface_contents_scale.y()); + shared_quad_state->visible_quad_layer_rect = + gfx::ScaleToEnclosedRect(shared_quad_state->visible_quad_layer_rect, + mask_quad_to_surface_contents_scale.x(), + mask_quad_to_surface_contents_scale.y()); + gfx::Rect content_rect_in_coverage_space = gfx::ScaleToEnclosedRect( + content_rect(), 1.f / mask_quad_to_surface_contents_scale.x(), + 1.f / mask_quad_to_surface_contents_scale.y()); + gfx::Rect visible_layer_rect_in_coverage_space = gfx::ScaleToEnclosedRect( + visible_layer_rect, 1.f / mask_quad_to_surface_contents_scale.x(), + 1.f / mask_quad_to_surface_contents_scale.y()); + + for (auto* temp_quad : temp_render_pass->quad_list) { + gfx::Rect quad_rect = temp_quad->rect; + gfx::Rect render_quad_rect = quad_rect; + if (!quad_rect.Intersects(content_rect_in_coverage_space)) + continue; + render_quad_rect = + gfx::IntersectRects(quad_rect, content_rect_in_coverage_space); + gfx::RectF quad_rect_in_surface_contents_space = gfx::ScaleRect( + gfx::RectF(render_quad_rect), mask_quad_to_surface_contents_scale.x(), + mask_quad_to_surface_contents_scale.y()); + gfx::RectF quad_rect_in_non_normalized_texture_space = + quad_rect_in_surface_contents_space; + quad_rect_in_non_normalized_texture_space.Offset( + -content_rect().OffsetFromOrigin()); + + switch (temp_quad->material) { + case DrawQuad::TILED_CONTENT: { + DCHECK_EQ(1U, temp_quad->resources.count); + RenderPassDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); + + gfx::Size mask_texture_size = + static_cast<ContentDrawQuadBase*>(temp_quad)->texture_size; + gfx::RectF temp_tex_coord_rect = + static_cast<ContentDrawQuadBase*>(temp_quad)->tex_coord_rect; + gfx::Transform coverage_to_non_normalized_mask = + gfx::Transform(SkMatrix44(SkMatrix::MakeRectToRect( + RectToSkRect(quad_rect), RectFToSkRect(temp_tex_coord_rect), + SkMatrix::kFill_ScaleToFit))); + gfx::Transform coverage_to_normalized_mask = + coverage_to_non_normalized_mask; + coverage_to_normalized_mask.matrix().postScale( + 1.f / mask_texture_size.width(), 1.f / mask_texture_size.height(), + 1.f); + gfx::RectF mask_uv_rect = gfx::RectF(render_quad_rect); + coverage_to_normalized_mask.TransformRect(&mask_uv_rect); + + quad->SetNew(shared_quad_state, render_quad_rect, + gfx::IntersectRects(temp_quad->visible_rect, + visible_layer_rect_in_coverage_space), + GetRenderPassId(), temp_quad->resources.ids[0], + mask_uv_rect, mask_texture_size, + owning_layer_to_surface_contents_scale, FiltersOrigin(), + quad_rect_in_non_normalized_texture_space); + } break; + case DrawQuad::SOLID_COLOR: { + if (!static_cast<SolidColorDrawQuad*>(temp_quad)->color) + continue; + SkAlpha solid = SK_AlphaOPAQUE; + DCHECK_EQ( + SkColorGetA(static_cast<SolidColorDrawQuad*>(temp_quad)->color), + solid); + RenderPassDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); + quad->SetNew(shared_quad_state, render_quad_rect, + gfx::IntersectRects(temp_quad->visible_rect, + visible_layer_rect_in_coverage_space), + GetRenderPassId(), 0, gfx::RectF(), gfx::Size(), + owning_layer_to_surface_contents_scale, FiltersOrigin(), + quad_rect_in_non_normalized_texture_space); + } break; + case DrawQuad::DEBUG_BORDER: + NOTIMPLEMENTED(); + break; + default: + NOTREACHED(); + break; + } + } } } // namespace cc diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h index 1b2f0cd2b23..5cf15e86af2 100644 --- a/chromium/cc/layers/render_surface_impl.h +++ b/chromium/cc/layers/render_surface_impl.h @@ -12,7 +12,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_collections.h" #include "cc/quads/render_pass.h" #include "cc/quads/shared_quad_state.h" @@ -24,16 +24,13 @@ namespace cc { +class AppendQuadsData; class DamageTracker; class FilterOperations; class Occlusion; -class RenderPassSink; class LayerImpl; -class LayerIterator; class LayerTreeImpl; -struct AppendQuadsData; - class CC_EXPORT RenderSurfaceImpl { public: RenderSurfaceImpl(LayerTreeImpl* layer_tree_impl, int stable_effect_id); @@ -99,6 +96,14 @@ class CC_EXPORT RenderSurfaceImpl { contributes_to_drawn_surface_ = contributes_to_drawn_surface; } + void set_has_contributing_layer_that_escapes_clip( + bool contributing_layer_escapes_clip) { + has_contributing_layer_that_escapes_clip_ = contributing_layer_escapes_clip; + } + bool has_contributing_layer_that_escapes_clip() const { + return has_contributing_layer_that_escapes_clip_; + } + void CalculateContentRectFromAccumulatedContentRect(int max_texture_size); void SetContentRectToViewport(); void SetContentRectForTesting(const gfx::Rect& rect); @@ -132,7 +137,7 @@ class CC_EXPORT RenderSurfaceImpl { const FilterOperations& Filters() const; const FilterOperations& BackgroundFilters() const; gfx::PointF FiltersOrigin() const; - gfx::Transform FiltersTransform() const; + gfx::Transform SurfaceScale() const; bool HasCopyRequest() const; @@ -147,7 +152,7 @@ class CC_EXPORT RenderSurfaceImpl { int GetRenderPassId(); - void AppendRenderPasses(RenderPassSink* pass_sink); + std::unique_ptr<RenderPass> CreateRenderPass(); void AppendQuads(RenderPass* render_pass, AppendQuadsData* append_quads_data); int TransformTreeIndex() const; @@ -156,13 +161,16 @@ class CC_EXPORT RenderSurfaceImpl { void set_effect_tree_index(int index) { effect_tree_index_ = index; } int EffectTreeIndex() const; + const EffectNode* OwningEffectNode() const; + private: void SetContentRect(const gfx::Rect& content_rect); gfx::Rect CalculateClippedAccumulatedContentRect(); gfx::Rect CalculateExpandedClipForFilters( const gfx::Transform& target_to_surface); - - const EffectNode* OwningEffectNode() const; + void TileMaskLayer(RenderPass* render_pass, + SharedQuadState* shared_quad_state, + const gfx::Rect& visible_layer_rect); LayerTreeImpl* layer_tree_impl_; int stable_effect_id_; @@ -196,6 +204,8 @@ class CC_EXPORT RenderSurfaceImpl { // Is used to calculate the content rect from property trees. gfx::Rect accumulated_content_rect_; + // Is used to decide if the surface is clipped. + bool has_contributing_layer_that_escapes_clip_ : 1; bool surface_property_changed_ : 1; bool ancestor_property_changed_ : 1; @@ -210,12 +220,6 @@ class CC_EXPORT RenderSurfaceImpl { std::unique_ptr<DamageTracker> damage_tracker_; - // For LayerIteratorActions - int target_render_surface_layer_index_history_; - size_t current_layer_index_history_; - - 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 2095c941eff..49f2f7d6eb9 100644 --- a/chromium/cc/layers/render_surface_impl_unittest.cc +++ b/chromium/cc/layers/render_surface_impl_unittest.cc @@ -9,6 +9,7 @@ #include "cc/layers/append_quads_data.h" #include "cc/quads/render_pass_draw_quad.h" #include "cc/test/fake_mask_layer_impl.h" +#include "cc/test/fake_raster_source.h" #include "cc/test/layer_test_common.h" #include "testing/gtest/include/gtest/gtest.h" @@ -68,8 +69,12 @@ TEST(RenderSurfaceLayerImplTest, Occlusion) { TEST(RenderSurfaceLayerImplTest, AppendQuadsWithScaledMask) { gfx::Size layer_size(1000, 1000); gfx::Size viewport_size(1000, 1000); + scoped_refptr<FakeRasterSource> raster_source = + FakeRasterSource::CreateFilledSolidColor(layer_size); - LayerTestCommon::LayerImplTest impl; + LayerTreeSettings settings; + settings.layer_transforms_should_scale_layer_contents = true; + LayerTestCommon::LayerImplTest impl(settings); std::unique_ptr<LayerImpl> root = LayerImpl::Create(impl.host_impl()->active_tree(), 2); std::unique_ptr<LayerImpl> surface = @@ -81,8 +86,9 @@ TEST(RenderSurfaceLayerImplTest, AppendQuadsWithScaledMask) { scale.Scale(2, 2); surface->test_properties()->transform = scale; - surface->test_properties()->SetMaskLayer( - FakeMaskLayerImpl::Create(impl.host_impl()->active_tree(), 4)); + surface->test_properties()->SetMaskLayer(FakeMaskLayerImpl::Create( + impl.host_impl()->active_tree(), 4, raster_source, + Layer::LayerMaskType::SINGLE_TEXTURE_MASK)); surface->test_properties()->mask_layer->SetDrawsContent(true); surface->test_properties()->mask_layer->SetBounds(layer_size); @@ -109,9 +115,10 @@ TEST(RenderSurfaceLayerImplTest, AppendQuadsWithScaledMask) { AppendQuadsData append_quads_data; render_surface_impl->AppendQuads(render_pass.get(), &append_quads_data); + DCHECK(render_pass->quad_list.front()); const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(render_pass->quad_list.front()); - EXPECT_EQ(gfx::RectF(0, 0, 1.f, 1.f), quad->mask_uv_rect); + EXPECT_EQ(gfx::RectF(0, 0, 1, 1), quad->mask_uv_rect); EXPECT_EQ(gfx::Vector2dF(2.f, 2.f), quad->filters_scale); } diff --git a/chromium/cc/layers/render_surface_unittest.cc b/chromium/cc/layers/render_surface_unittest.cc index 85ed8c4294a..a8662d8aab0 100644 --- a/chromium/cc/layers/render_surface_unittest.cc +++ b/chromium/cc/layers/render_surface_unittest.cc @@ -4,7 +4,6 @@ #include "cc/layers/append_quads_data.h" #include "cc/layers/layer_impl.h" -#include "cc/layers/render_pass_sink.h" #include "cc/layers/render_surface_impl.h" #include "cc/quads/shared_quad_state.h" #include "cc/test/fake_compositor_frame_sink.h" @@ -63,10 +62,8 @@ TEST(RenderSurfaceTest, VerifySurfaceChangesAreTrackedProperly) { EXECUTE_AND_VERIFY_SURFACE_CHANGED( render_surface->SetContentRectForTesting(test_rect)); - host_impl.active_tree()->property_trees()->effect_tree.OnOpacityAnimated( - 0.5f, - host_impl.active_tree()->root_layer_for_testing()->effect_tree_index(), - host_impl.active_tree()); + host_impl.active_tree()->SetOpacityMutated( + host_impl.active_tree()->root_layer_for_testing()->element_id(), 0.5f); EXPECT_TRUE(render_surface->SurfacePropertyChanged()); host_impl.active_tree()->ResetAllChangeTracking(); @@ -152,19 +149,6 @@ TEST(RenderSurfaceTest, SanityCheckSurfaceCreatesCorrectSharedQuadState) { EXPECT_EQ(blend_mode, shared_quad_state->blend_mode); } -class TestRenderPassSink : public RenderPassSink { - public: - void AppendRenderPass(std::unique_ptr<RenderPass> render_pass) override { - render_passes_.push_back(std::move(render_pass)); - } - - const RenderPassList& RenderPasses() const { - return render_passes_; - } - - private: - RenderPassList render_passes_; -}; TEST(RenderSurfaceTest, SanityCheckSurfaceCreatesCorrectRenderPass) { FakeImplTaskRunnerProvider task_runner_provider; @@ -199,12 +183,7 @@ TEST(RenderSurfaceTest, SanityCheckSurfaceCreatesCorrectRenderPass) { render_surface->SetScreenSpaceTransform(origin); render_surface->SetContentRectForTesting(content_rect); - TestRenderPassSink pass_sink; - - render_surface->AppendRenderPasses(&pass_sink); - - ASSERT_EQ(1u, pass_sink.RenderPasses().size()); - RenderPass* pass = pass_sink.RenderPasses()[0].get(); + auto pass = render_surface->CreateRenderPass(); EXPECT_EQ(2, pass->id); EXPECT_EQ(content_rect, pass->output_rect); diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.cc b/chromium/cc/layers/scrollbar_layer_impl_base.cc index 61924f3d129..da53036fea0 100644 --- a/chromium/cc/layers/scrollbar_layer_impl_base.cc +++ b/chromium/cc/layers/scrollbar_layer_impl_base.cc @@ -5,6 +5,7 @@ #include "cc/layers/scrollbar_layer_impl_base.h" #include <algorithm> +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_impl.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -200,4 +201,35 @@ gfx::Rect ScrollbarLayerImplBase::ComputeThumbQuadRect() const { return gfx::ToEnclosingRect(thumb_rect); } +void ScrollbarLayerImplBase::SetOverlayScrollbarLayerOpacityAnimated( + float opacity) { + DCHECK(is_overlay_scrollbar()); + if (!layer_tree_impl()) + return; + + PropertyTrees* property_trees = layer_tree_impl()->property_trees(); + int effect_node_index = + property_trees->effect_tree.FindNodeIndexFromOwningLayerId(id()); + // If this method is called during LayerImpl::PushPropertiesTo, we may not yet + // have valid owning_layer_id_to_node_index entries in effect tree as property + // trees are pushed after layers during activation. We can skip updating + // opacity in that case as we are only registering a scrollbar and because + // opacity will be overwritten anyway when property trees are pushed. + if (effect_node_index == EffectTree::kInvalidNodeId || + effect_node_index != effect_tree_index()) + return; + + EffectNode* node = property_trees->effect_tree.Node(effect_tree_index()); + if (node->opacity == opacity) + return; + + layer_tree_impl()->AddToOpacityAnimationsMap(id(), opacity); + + node->opacity = opacity; + node->effect_changed = true; + property_trees->changed = true; + property_trees->effect_tree.set_needs_update(true); + layer_tree_impl()->set_needs_update_draw_properties(); +} + } // namespace cc diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.h b/chromium/cc/layers/scrollbar_layer_impl_base.h index 7ec930a24d4..0b9b403950b 100644 --- a/chromium/cc/layers/scrollbar_layer_impl_base.h +++ b/chromium/cc/layers/scrollbar_layer_impl_base.h @@ -6,7 +6,7 @@ #define CC_LAYERS_SCROLLBAR_LAYER_IMPL_BASE_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" @@ -56,6 +56,10 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl { virtual int ThumbThickness() const = 0; + // TODO(crbug.com/702832): No need for this function once there is element id + // on overlay scrollbar layers. + void SetOverlayScrollbarLayerOpacityAnimated(float opacity); + protected: ScrollbarLayerImplBase(LayerTreeImpl* tree_impl, int id, diff --git a/chromium/cc/layers/scrollbar_layer_interface.h b/chromium/cc/layers/scrollbar_layer_interface.h index acb73924409..30c335ba011 100644 --- a/chromium/cc/layers/scrollbar_layer_interface.h +++ b/chromium/cc/layers/scrollbar_layer_interface.h @@ -6,7 +6,7 @@ #define CC_LAYERS_SCROLLBAR_LAYER_INTERFACE_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/scrollbar.h" namespace cc { diff --git a/chromium/cc/layers/scrollbar_layer_unittest.cc b/chromium/cc/layers/scrollbar_layer_unittest.cc index 5abdca78a25..3e6e56ec142 100644 --- a/chromium/cc/layers/scrollbar_layer_unittest.cc +++ b/chromium/cc/layers/scrollbar_layer_unittest.cc @@ -11,6 +11,7 @@ #include "cc/animation/animation_host.h" #include "cc/input/scrollbar_animation_controller.h" #include "cc/layers/append_quads_data.h" +#include "cc/layers/painted_overlay_scrollbar_layer.h" #include "cc/layers/painted_scrollbar_layer.h" #include "cc/layers/painted_scrollbar_layer_impl.h" #include "cc/layers/scrollbar_layer_interface.h" @@ -105,13 +106,10 @@ class ScrollbarLayerTest : public testing::Test { layer_tree_settings_.use_zero_copy = true; layer_tree_settings_.scrollbar_animator = LayerTreeSettings::ANDROID_OVERLAY; - layer_tree_settings_.scrollbar_show_delay = + layer_tree_settings_.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(20); - layer_tree_settings_.scrollbar_fade_out_delay = + layer_tree_settings_.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(20); - layer_tree_settings_.scrollbar_fade_out_duration = - base::TimeDelta::FromMilliseconds(20); - layer_tree_settings_.verify_clip_tree_calculations = true; scrollbar_layer_id_ = -1; @@ -176,6 +174,75 @@ class ScrollbarLayerTest : public testing::Test { int scrollbar_layer_id_; }; +class FakePaintedOverlayScrollbar : public FakeScrollbar { + public: + FakePaintedOverlayScrollbar() : FakeScrollbar(true, true, true) {} + bool UsesNinePatchThumbResource() const override { return true; } + gfx::Size NinePatchThumbCanvasSize() const override { + return gfx::Size(3, 3); + } + gfx::Rect NinePatchThumbAperture() const override { + return gfx::Rect(1, 1, 1, 1); + } +}; + +// Test that a painted overlay scrollbar will repaint and recrate its resource +// after its been disposed, even if Blink doesn't think it requires a repaint. +// crbug.com/704656. +TEST_F(ScrollbarLayerTest, RepaintOverlayWhenResourceDisposed) { + scoped_refptr<Layer> layer_tree_root = Layer::Create(); + scoped_refptr<Layer> content_layer = Layer::Create(); + std::unique_ptr<FakePaintedOverlayScrollbar> scrollbar( + new FakePaintedOverlayScrollbar); + FakePaintedOverlayScrollbar* fake_scrollbar = scrollbar.get(); + scoped_refptr<PaintedOverlayScrollbarLayer> scrollbar_layer = + PaintedOverlayScrollbarLayer::Create(std::move(scrollbar), + layer_tree_root->id()); + + // Setup. + { + layer_tree_root->AddChild(content_layer); + layer_tree_root->AddChild(scrollbar_layer); + layer_tree_host_->SetRootLayer(layer_tree_root); + scrollbar_layer->SetIsDrawable(true); + scrollbar_layer->SetBounds(gfx::Size(100, 100)); + layer_tree_root->SetBounds(gfx::Size(100, 200)); + content_layer->SetBounds(gfx::Size(100, 200)); + scrollbar_layer->set_visible_layer_rect(gfx::Rect(0, 0, 100, 200)); + scrollbar_layer->SavePaintProperties(); + } + + // First call to update should create a resource. The scrollbar itself thinks + // it needs a repaint. + { + fake_scrollbar->set_needs_paint_thumb(true); + EXPECT_EQ(0u, fake_ui_resource_manager_->UIResourceCount()); + EXPECT_TRUE(scrollbar_layer->Update()); + EXPECT_EQ(1u, fake_ui_resource_manager_->UIResourceCount()); + } + + // Now the scrollbar has been painted and nothing else has changed, calling + // Update() shouldn't have an effect. + { + fake_scrollbar->set_needs_paint_thumb(false); + EXPECT_FALSE(scrollbar_layer->Update()); + EXPECT_EQ(1u, fake_ui_resource_manager_->UIResourceCount()); + } + + // Detach and reattach the LayerTreeHost (this can happen during tree + // reconstruction). This should cause the UIResource for the scrollbar to be + // disposed but the scrollbar itself hasn't changed so it reports that no + // repaint is needed. An Update should cause us to recreate the resource + // though. + { + scrollbar_layer->SetLayerTreeHost(nullptr); + scrollbar_layer->SetLayerTreeHost(layer_tree_host_.get()); + EXPECT_EQ(0u, fake_ui_resource_manager_->UIResourceCount()); + EXPECT_TRUE(scrollbar_layer->Update()); + EXPECT_EQ(1u, fake_ui_resource_manager_->UIResourceCount()); + } +} + TEST_F(ScrollbarLayerTest, ShouldScrollNonOverlayOnMainThread) { // Create and attach a non-overlay scrollbar. std::unique_ptr<Scrollbar> scrollbar(new FakeScrollbar); @@ -224,8 +291,8 @@ TEST_F(ScrollbarLayerTest, ScrollOffsetSynchronization) { 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( - std::move(scrollbar), layer_tree_root->id()); + scoped_refptr<Layer> scrollbar_layer = + PaintedScrollbarLayer::Create(std::move(scrollbar), scroll_layer->id()); // Choose bounds to give max_scroll_offset = (30, 50). layer_tree_root->SetBounds(gfx::Size(70, 150)); @@ -238,7 +305,6 @@ TEST_F(ScrollbarLayerTest, ScrollOffsetSynchronization) { layer_tree_root->AddChild(scroll_layer); scroll_layer->AddChild(content_layer); layer_tree_root->AddChild(scrollbar_layer); - scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(scroll_layer->id()); layer_tree_root->SavePaintProperties(); content_layer->SavePaintProperties(); @@ -531,8 +597,7 @@ TEST_F(ScrollbarLayerTest, LayerDrivenSolidColorDrawQuads) { const bool kIsLeftSideVerticalScrollbar = false; child2 = SolidColorScrollbarLayer::Create( scrollbar->Orientation(), kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar, child1->id()); - child2->ToScrollbarLayer()->SetScrollLayer(scroll_layer->id()); + kIsLeftSideVerticalScrollbar, scroll_layer->id()); scroll_layer->AddChild(child1); scroll_layer->InsertChild(child2, 1); layer_tree_root->AddChild(scroll_layer); @@ -584,8 +649,7 @@ TEST_F(ScrollbarLayerTest, ScrollbarLayerOpacity) { const bool kIsLeftSideVerticalScrollbar = false; scrollbar_layer = SolidColorScrollbarLayer::Create( scrollbar->Orientation(), kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar, child1->id()); - scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(scroll_layer->id()); + kIsLeftSideVerticalScrollbar, scroll_layer->id()); scroll_layer->AddChild(child1); scroll_layer->InsertChild(scrollbar_layer, 1); layer_tree_root->AddChild(scroll_layer); @@ -631,10 +695,10 @@ TEST_F(ScrollbarLayerTest, ScrollbarLayerOpacity) { EXPECT_EQ(node->opacity, 0.f); // This tests that activation does not change the opacity of scrollbar layer. - LayerImpl* scrollbar_layer_impl = - layer_tree_impl->LayerById(scrollbar_layer->id()); - layer_tree_impl->property_trees()->effect_tree.OnOpacityAnimated( - 0.25f, scrollbar_layer_impl->effect_tree_index(), layer_tree_impl); + ScrollbarLayerImplBase* scrollbar_layer_impl = + static_cast<ScrollbarLayerImplBase*>( + layer_tree_impl->LayerById(scrollbar_layer->id())); + scrollbar_layer_impl->SetOverlayScrollbarLayerOpacityAnimated(0.25f); host_impl->CreatePendingTree(); layer_impl_tree_root = layer_tree_host_->CommitAndCreatePendingTree(); layer_tree_impl = layer_impl_tree_root->layer_tree_impl(); @@ -666,9 +730,8 @@ TEST_F(ScrollbarLayerTest, ScrollbarLayerPushProperties) { const bool kIsLeftSideVerticalScrollbar = false; scrollbar_layer = SolidColorScrollbarLayer::Create( scrollbar->Orientation(), kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar, child1->id()); + kIsLeftSideVerticalScrollbar, scroll_layer->id()); scroll_layer->SetScrollClipLayerId(layer_tree_root->id()); - scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(scroll_layer->id()); scroll_layer->AddChild(child1); scroll_layer->InsertChild(scrollbar_layer, 1); layer_tree_root->AddChild(scroll_layer); @@ -697,7 +760,6 @@ class ScrollbarLayerSolidColorThumbTest : public testing::Test { public: ScrollbarLayerSolidColorThumbTest() { LayerTreeSettings layer_tree_settings; - layer_tree_settings.verify_clip_tree_calculations = true; host_impl_.reset(new FakeLayerTreeHostImpl( layer_tree_settings, &task_runner_provider_, &task_graph_runner_)); diff --git a/chromium/cc/layers/scrollbar_theme_painter.h b/chromium/cc/layers/scrollbar_theme_painter.h index 8f3e68d8dcb..2733f44d42d 100644 --- a/chromium/cc/layers/scrollbar_theme_painter.h +++ b/chromium/cc/layers/scrollbar_theme_painter.h @@ -5,7 +5,7 @@ #ifndef CC_LAYERS_SCROLLBAR_THEME_PAINTER_H_ #define CC_LAYERS_SCROLLBAR_THEME_PAINTER_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" class SkCanvas; diff --git a/chromium/cc/layers/solid_color_layer.h b/chromium/cc/layers/solid_color_layer.h index 66a6ad8ec0e..653dd8a8717 100644 --- a/chromium/cc/layers/solid_color_layer.h +++ b/chromium/cc/layers/solid_color_layer.h @@ -7,7 +7,7 @@ #define CC_LAYERS_SOLID_COLOR_LAYER_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" namespace cc { diff --git a/chromium/cc/layers/solid_color_layer_impl.cc b/chromium/cc/layers/solid_color_layer_impl.cc index 322d9c8c19f..c5b7574ccee 100644 --- a/chromium/cc/layers/solid_color_layer_impl.cc +++ b/chromium/cc/layers/solid_color_layer_impl.cc @@ -34,6 +34,11 @@ void SolidColorLayerImpl::AppendSolidQuads( const gfx::Rect& visible_layer_rect, SkColor color, AppendQuadsData* append_quads_data) { + float alpha = + (SkColorGetA(color) * (1.0f / 255.0f)) * shared_quad_state->opacity; + DCHECK_EQ(SkBlendMode::kSrcOver, shared_quad_state->blend_mode); + if (alpha < std::numeric_limits<float>::epsilon()) + return; // 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_layer_rect.right(); diff --git a/chromium/cc/layers/solid_color_layer_impl.h b/chromium/cc/layers/solid_color_layer_impl.h index 1f6aaf5a267..ed0b2de065f 100644 --- a/chromium/cc/layers/solid_color_layer_impl.h +++ b/chromium/cc/layers/solid_color_layer_impl.h @@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_impl.h" namespace cc { diff --git a/chromium/cc/layers/solid_color_layer_impl_unittest.cc b/chromium/cc/layers/solid_color_layer_impl_unittest.cc index b5c8dd14d39..51f435552ae 100644 --- a/chromium/cc/layers/solid_color_layer_impl_unittest.cc +++ b/chromium/cc/layers/solid_color_layer_impl_unittest.cc @@ -36,7 +36,9 @@ TEST(SolidColorLayerImplTest, VerifyTilingCompleteAndNoOverlap) { std::unique_ptr<SolidColorLayerImpl> layer = SolidColorLayerImpl::Create(host_impl.active_tree(), 1); layer->draw_properties().visible_layer_rect = visible_layer_rect; + layer->draw_properties().opacity = 1.f; layer->SetBounds(layer_size); + layer->SetBackgroundColor(SK_ColorRED); layer->test_properties()->force_render_surface = true; host_impl.active_tree()->SetRootLayerForTesting(std::move(layer)); host_impl.active_tree()->BuildPropertyTreesForTesting(); @@ -62,6 +64,7 @@ TEST(SolidColorLayerImplTest, VerifyCorrectBackgroundColorInQuad) { std::unique_ptr<SolidColorLayerImpl> layer = SolidColorLayerImpl::Create(host_impl.active_tree(), 1); layer->draw_properties().visible_layer_rect = visible_layer_rect; + layer->draw_properties().opacity = 1.f; layer->SetBounds(layer_size); layer->SetBackgroundColor(test_color); layer->test_properties()->force_render_surface = true; @@ -94,6 +97,7 @@ TEST(SolidColorLayerImplTest, VerifyCorrectOpacityInQuad) { layer->SetBounds(layer_size); layer->draw_properties().opacity = opacity; layer->test_properties()->force_render_surface = true; + layer->SetBackgroundColor(SK_ColorRED); host_impl.active_tree()->SetRootLayerForTesting(std::move(layer)); host_impl.active_tree()->BuildPropertyTreesForTesting(); AppendQuadsData data; @@ -106,6 +110,60 @@ TEST(SolidColorLayerImplTest, VerifyCorrectOpacityInQuad) { ->shared_quad_state->opacity); } +TEST(SolidColorLayerImplTest, VerifyEliminateTransparentAlpha) { + SkColor test_color = 0; + + std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); + + gfx::Size layer_size = gfx::Size(100, 100); + gfx::Rect visible_layer_rect = gfx::Rect(layer_size); + + FakeImplTaskRunnerProvider task_runner_provider; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner); + std::unique_ptr<SolidColorLayerImpl> layer = + SolidColorLayerImpl::Create(host_impl.active_tree(), 1); + layer->draw_properties().visible_layer_rect = visible_layer_rect; + layer->draw_properties().opacity = 1.f; + layer->SetBounds(layer_size); + layer->SetBackgroundColor(test_color); + layer->test_properties()->force_render_surface = true; + host_impl.active_tree()->SetRootLayerForTesting(std::move(layer)); + host_impl.active_tree()->BuildPropertyTreesForTesting(); + AppendQuadsData data; + host_impl.active_tree()->root_layer_for_testing()->AppendQuads( + render_pass.get(), &data); + + EXPECT_EQ(render_pass->quad_list.size(), 0U); +} + +TEST(SolidColorLayerImplTest, VerifyEliminateTransparentOpacity) { + SkColor test_color = 0xFFA55AFF; + + std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); + + gfx::Size layer_size = gfx::Size(100, 100); + gfx::Rect visible_layer_rect = gfx::Rect(layer_size); + + FakeImplTaskRunnerProvider task_runner_provider; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner); + std::unique_ptr<SolidColorLayerImpl> layer = + SolidColorLayerImpl::Create(host_impl.active_tree(), 1); + layer->draw_properties().visible_layer_rect = visible_layer_rect; + layer->draw_properties().opacity = 0.f; + layer->SetBounds(layer_size); + layer->SetBackgroundColor(test_color); + layer->test_properties()->force_render_surface = true; + host_impl.active_tree()->SetRootLayerForTesting(std::move(layer)); + host_impl.active_tree()->BuildPropertyTreesForTesting(); + AppendQuadsData data; + host_impl.active_tree()->root_layer_for_testing()->AppendQuads( + render_pass.get(), &data); + + EXPECT_EQ(render_pass->quad_list.size(), 0U); +} + TEST(SolidColorLayerImplTest, VerifyOpaqueRect) { gfx::Size layer_size = gfx::Size(100, 100); gfx::Rect visible_layer_rect = gfx::Rect(layer_size); diff --git a/chromium/cc/layers/solid_color_scrollbar_layer.cc b/chromium/cc/layers/solid_color_scrollbar_layer.cc index 2670fd32165..2eb5484c855 100644 --- a/chromium/cc/layers/solid_color_scrollbar_layer.cc +++ b/chromium/cc/layers/solid_color_scrollbar_layer.cc @@ -39,7 +39,7 @@ SolidColorScrollbarLayer::SolidColorScrollbarLayerInputs:: int track_start, bool is_left_side_vertical_scrollbar, int scroll_layer_id) - : scroll_layer_id(Layer::INVALID_ID), + : scroll_layer_id(scroll_layer_id), orientation(orientation), thumb_thickness(thumb_thickness), track_start(track_start), diff --git a/chromium/cc/layers/solid_color_scrollbar_layer.h b/chromium/cc/layers/solid_color_scrollbar_layer.h index f29117a9059..319674c22ad 100644 --- a/chromium/cc/layers/solid_color_scrollbar_layer.h +++ b/chromium/cc/layers/solid_color_scrollbar_layer.h @@ -6,7 +6,7 @@ #define CC_LAYERS_SOLID_COLOR_SCROLLBAR_LAYER_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/layers/scrollbar_layer_interface.h" diff --git a/chromium/cc/layers/solid_color_scrollbar_layer_impl.h b/chromium/cc/layers/solid_color_scrollbar_layer_impl.h index a7b776ef0ae..1306391baa6 100644 --- a/chromium/cc/layers/solid_color_scrollbar_layer_impl.h +++ b/chromium/cc/layers/solid_color_scrollbar_layer_impl.h @@ -5,7 +5,7 @@ #ifndef CC_LAYERS_SOLID_COLOR_SCROLLBAR_LAYER_IMPL_H_ #define CC_LAYERS_SOLID_COLOR_SCROLLBAR_LAYER_IMPL_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/scrollbar_layer_impl_base.h" namespace cc { diff --git a/chromium/cc/layers/surface_layer.cc b/chromium/cc/layers/surface_layer.cc index c208d4778f8..000832fe116 100644 --- a/chromium/cc/layers/surface_layer.cc +++ b/chromium/cc/layers/surface_layer.cc @@ -70,7 +70,7 @@ void SurfaceLayer::SetPrimarySurfaceInfo(const SurfaceInfo& surface_info) { layer_tree_host(), primary_surface_info_.id()); } UpdateDrawsContent(HasDrawableContent()); - SetNeedsCommitNoRebuild(); + SetNeedsCommit(); } void SurfaceLayer::SetFallbackSurfaceInfo(const SurfaceInfo& surface_info) { @@ -80,7 +80,7 @@ void SurfaceLayer::SetFallbackSurfaceInfo(const SurfaceInfo& surface_info) { fallback_reference_returner_ = ref_factory_->CreateReference( layer_tree_host(), fallback_surface_info_.id()); } - SetNeedsCommitNoRebuild(); + SetNeedsCommit(); } void SurfaceLayer::SetStretchContentToFillBounds( diff --git a/chromium/cc/layers/surface_layer.h b/chromium/cc/layers/surface_layer.h index ed8289b739f..56f8d61f879 100644 --- a/chromium/cc/layers/surface_layer.h +++ b/chromium/cc/layers/surface_layer.h @@ -6,7 +6,7 @@ #define CC_LAYERS_SURFACE_LAYER_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/surfaces/surface_info.h" #include "cc/surfaces/surface_reference_factory.h" diff --git a/chromium/cc/layers/surface_layer_impl.cc b/chromium/cc/layers/surface_layer_impl.cc index 1e072569e06..7a1bfbd9795 100644 --- a/chromium/cc/layers/surface_layer_impl.cc +++ b/chromium/cc/layers/surface_layer_impl.cc @@ -8,6 +8,7 @@ #include "base/trace_event/trace_event_argument.h" #include "cc/debug/debug_colors.h" +#include "cc/layers/append_quads_data.h" #include "cc/quads/solid_color_draw_quad.h" #include "cc/quads/surface_draw_quad.h" #include "cc/trees/layer_tree_impl.h" @@ -65,19 +66,22 @@ void SurfaceLayerImpl::AppendQuads(RenderPass* render_pass, AppendQuadsData* append_quads_data) { AppendRainbowDebugBorder(render_pass); auto* primary = CreateSurfaceDrawQuad( - render_pass, SurfaceDrawQuadType::PRIMARY, primary_surface_info_); + render_pass, SurfaceDrawQuadType::PRIMARY, primary_surface_info_, + &append_quads_data->embedded_surfaces); // Emitting a fallback SurfaceDrawQuad is unnecessary if the primary and // fallback surface Ids match. if (primary && fallback_surface_info_.id() != primary_surface_info_.id()) { primary->fallback_quad = CreateSurfaceDrawQuad( - render_pass, SurfaceDrawQuadType::FALLBACK, fallback_surface_info_); + render_pass, SurfaceDrawQuadType::FALLBACK, fallback_surface_info_, + nullptr /* embedded_surfaces */); } } SurfaceDrawQuad* SurfaceLayerImpl::CreateSurfaceDrawQuad( RenderPass* render_pass, SurfaceDrawQuadType surface_draw_quad_type, - const SurfaceInfo& surface_info) { + const SurfaceInfo& surface_info, + std::vector<SurfaceId>* embedded_surfaces) { if (!surface_info.is_valid()) return nullptr; @@ -117,17 +121,21 @@ SurfaceDrawQuad* SurfaceLayerImpl::CreateSurfaceDrawQuad( render_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); surface_draw_quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, surface_info.id(), surface_draw_quad_type, nullptr); + if (embedded_surfaces) + embedded_surfaces->push_back(surface_info.id()); + return surface_draw_quad; } void SurfaceLayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const { *color = DebugColors::SurfaceLayerBorderColor(); - *width = DebugColors::SurfaceLayerBorderWidth(layer_tree_impl()); + *width = DebugColors::SurfaceLayerBorderWidth( + layer_tree_impl() ? layer_tree_impl()->device_scale_factor() : 1); } void SurfaceLayerImpl::AppendRainbowDebugBorder(RenderPass* render_pass) { - if (!ShowDebugBorders()) + if (!ShowDebugBorders(DebugBorderType::SURFACE)) return; SharedQuadState* shared_quad_state = diff --git a/chromium/cc/layers/surface_layer_impl.h b/chromium/cc/layers/surface_layer_impl.h index a8523cdcec5..9b853df5253 100644 --- a/chromium/cc/layers/surface_layer_impl.h +++ b/chromium/cc/layers/surface_layer_impl.h @@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_impl.h" #include "cc/quads/surface_draw_quad.h" #include "cc/surfaces/surface_id.h" @@ -50,7 +50,8 @@ class CC_EXPORT SurfaceLayerImpl : public LayerImpl { SurfaceDrawQuad* CreateSurfaceDrawQuad( RenderPass* render_pass, SurfaceDrawQuadType surface_draw_quad_type, - const SurfaceInfo& surface_info); + const SurfaceInfo& surface_info, + std::vector<SurfaceId>* embedded_surfaces); void GetDebugBorderProperties(SkColor* color, float* width) const override; void AppendRainbowDebugBorder(RenderPass* render_pass); diff --git a/chromium/cc/layers/surface_layer_impl_unittest.cc b/chromium/cc/layers/surface_layer_impl_unittest.cc index 1b41a538677..5c6f942a66f 100644 --- a/chromium/cc/layers/surface_layer_impl_unittest.cc +++ b/chromium/cc/layers/surface_layer_impl_unittest.cc @@ -9,8 +9,11 @@ #include "cc/layers/append_quads_data.h" #include "cc/test/layer_test_common.h" #include "cc/trees/layer_tree_host_common.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::UnorderedElementsAre; + namespace cc { namespace { @@ -168,6 +171,7 @@ TEST(SurfaceLayerImplTest, SurfaceStretchedToLayerBounds) { std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); AppendQuadsData data; surface_layer_impl->AppendQuads(render_pass.get(), &data); + EXPECT_THAT(data.embedded_surfaces, UnorderedElementsAre(surface_id)); const QuadList& quads = render_pass->quad_list; ASSERT_EQ(1u, quads.size()); @@ -236,6 +240,8 @@ TEST(SurfaceLayerImplTest, SurfaceLayerImplEmitsTwoDrawQuadsIfUniqueFallback) { std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); AppendQuadsData data; surface_layer_impl->AppendQuads(render_pass.get(), &data); + // The the primary SurfaceInfo will be added to embedded_surfaces. + EXPECT_THAT(data.embedded_surfaces, UnorderedElementsAre(surface_id1)); ASSERT_EQ(2u, render_pass->quad_list.size()); const SurfaceDrawQuad* surface_draw_quad1 = @@ -286,6 +292,7 @@ TEST(SurfaceLayerImplTest, std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); AppendQuadsData data; surface_layer_impl->AppendQuads(render_pass.get(), &data); + EXPECT_THAT(data.embedded_surfaces, UnorderedElementsAre(surface_id1)); ASSERT_EQ(1u, render_pass->quad_list.size()); const SurfaceDrawQuad* surface_draw_quad1 = diff --git a/chromium/cc/layers/surface_layer_unittest.cc b/chromium/cc/layers/surface_layer_unittest.cc index ff787087015..0ee4e836500 100644 --- a/chromium/cc/layers/surface_layer_unittest.cc +++ b/chromium/cc/layers/surface_layer_unittest.cc @@ -241,8 +241,8 @@ class SurfaceLayerSwapPromise : public LayerTreeTest { void DidCommitAndDrawFrame() override { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&SurfaceLayerSwapPromise::ChangeTree, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&SurfaceLayerSwapPromise::ChangeTree, + base::Unretained(this))); } protected: diff --git a/chromium/cc/layers/texture_layer.h b/chromium/cc/layers/texture_layer.h index 1b42e976ef0..05f7367ff87 100644 --- a/chromium/cc/layers/texture_layer.h +++ b/chromium/cc/layers/texture_layer.h @@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/resources/texture_mailbox.h" diff --git a/chromium/cc/layers/texture_layer_impl.h b/chromium/cc/layers/texture_layer_impl.h index 2fc7cd30bb1..035463bc1b8 100644 --- a/chromium/cc/layers/texture_layer_impl.h +++ b/chromium/cc/layers/texture_layer_impl.h @@ -10,7 +10,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_impl.h" namespace cc { diff --git a/chromium/cc/layers/texture_layer_unittest.cc b/chromium/cc/layers/texture_layer_unittest.cc index 998c6291e3b..dc9c60d3795 100644 --- a/chromium/cc/layers/texture_layer_unittest.cc +++ b/chromium/cc/layers/texture_layer_unittest.cc @@ -76,7 +76,6 @@ class MockLayerTreeHost : public LayerTreeHost { params.task_graph_runner = task_graph_runner; params.mutator_host = mutator_host; LayerTreeSettings settings; - settings.verify_clip_tree_calculations = true; params.settings = &settings; return base::WrapUnique(new MockLayerTreeHost(¶ms)); } @@ -344,8 +343,9 @@ class TextureLayerMailboxHolderTest : public TextureLayerTest { : main_thread_("MAIN") { main_thread_.Start(); main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&TextureLayerMailboxHolderTest::InitializeOnMain, + base::Unretained(this))); Wait(main_thread_); } @@ -354,7 +354,7 @@ class TextureLayerMailboxHolderTest : public TextureLayerTest { base::WaitableEvent::InitialState::NOT_SIGNALED); thread.task_runner()->PostTask( FROM_HERE, - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event))); + base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event))); event.Wait(); } @@ -397,8 +397,8 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { ASSERT_TRUE(test_layer.get()); main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateMainRef, + base::Unretained(this))); Wait(main_thread_); @@ -406,15 +406,15 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { // impl tree. std::unique_ptr<SingleReleaseCallbackImpl> compositor1; main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, - base::Unretained(this), &compositor1)); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateImplRef, + base::Unretained(this), &compositor1)); // Then the texture layer is removed and attached to compositor2, and passes a // reference to its impl tree. std::unique_ptr<SingleReleaseCallbackImpl> compositor2; main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, - base::Unretained(this), &compositor2)); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateImplRef, + base::Unretained(this), &compositor2)); Wait(main_thread_); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -438,8 +438,8 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { .Times(1); main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::ReleaseMainRef, + base::Unretained(this))); Wait(main_thread_); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); } @@ -450,8 +450,8 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { ASSERT_TRUE(test_layer.get()); main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateMainRef, + base::Unretained(this))); Wait(main_thread_); @@ -459,15 +459,15 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { // impl tree. std::unique_ptr<SingleReleaseCallbackImpl> compositor1; main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, - base::Unretained(this), &compositor1)); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateImplRef, + base::Unretained(this), &compositor1)); // Then the texture layer is removed and attached to compositor2, and passes a // reference to its impl tree. std::unique_ptr<SingleReleaseCallbackImpl> compositor2; main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, - base::Unretained(this), &compositor2)); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateImplRef, + base::Unretained(this), &compositor2)); Wait(main_thread_); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -478,8 +478,8 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { // Then the main thread reference is destroyed. main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::ReleaseMainRef, + base::Unretained(this))); Wait(main_thread_); @@ -504,8 +504,8 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { ASSERT_TRUE(test_layer.get()); main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateMainRef, + base::Unretained(this))); Wait(main_thread_); @@ -513,23 +513,23 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { // impl tree. std::unique_ptr<SingleReleaseCallbackImpl> compositor1; main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, - base::Unretained(this), &compositor1)); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateImplRef, + base::Unretained(this), &compositor1)); // Then the texture layer is removed and attached to compositor2, and passes a // reference to its impl tree. std::unique_ptr<SingleReleaseCallbackImpl> compositor2; main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, - base::Unretained(this), &compositor2)); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateImplRef, + base::Unretained(this), &compositor2)); Wait(main_thread_); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); // The main thread reference is destroyed first. main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::ReleaseMainRef, + base::Unretained(this))); // One compositor destroys their impl tree. compositor2->Run(SyncTokenFromUInt(200), false, @@ -558,8 +558,8 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { ASSERT_TRUE(test_layer.get()); main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateMainRef, + base::Unretained(this))); Wait(main_thread_); @@ -567,23 +567,23 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { // impl tree. std::unique_ptr<SingleReleaseCallbackImpl> compositor1; main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, - base::Unretained(this), &compositor1)); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateImplRef, + base::Unretained(this), &compositor1)); // Then the texture layer is removed and attached to compositor2, and passes a // reference to its impl tree. std::unique_ptr<SingleReleaseCallbackImpl> compositor2; main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, - base::Unretained(this), &compositor2)); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::CreateImplRef, + base::Unretained(this), &compositor2)); Wait(main_thread_); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); // The main thread reference is destroyed first. main_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&TextureLayerMailboxHolderTest::ReleaseMainRef, + base::Unretained(this))); EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, SyncTokenFromUInt(200), true)) @@ -603,9 +603,9 @@ TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { // the main thread until we signal the |stop_capture| event. main_thread_.task_runner()->PostTask( FROM_HERE, - base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait, - base::Unretained(this), &begin_capture, &wait_for_capture, - &stop_capture)); + base::BindOnce(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait, + base::Unretained(this), &begin_capture, &wait_for_capture, + &stop_capture)); // Before the main thread capturing starts, one compositor destroys their // impl reference. Since capturing did not start, this gets post-tasked to @@ -787,11 +787,21 @@ SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerImplWithMailboxThreadedCallback); class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest { protected: - TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {} - - static void ReleaseCallback(const gpu::SyncToken& original_sync_token, - const gpu::SyncToken& release_sync_token, - bool lost_resource) {} + void ReleaseCallback(const gpu::SyncToken& original_sync_token, + const gpu::SyncToken& release_sync_token, + bool lost_resource) { + released_count_++; + switch (released_count_) { + case 1: + break; + case 2: + EXPECT_EQ(3, layer_tree_host()->SourceFrameNumber()); + EndTest(); + break; + default: + NOTREACHED(); + } + } void SetMailbox(char mailbox_char) { const gpu::SyncToken sync_token = @@ -799,7 +809,7 @@ class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest { std::unique_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(base::Bind( &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback, - sync_token)); + base::Unretained(this), sync_token)); layer_->SetTextureMailbox(TextureMailbox(MailboxFromChar(mailbox_char), sync_token, GL_TEXTURE_2D), std::move(callback)); @@ -849,8 +859,12 @@ class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest { layer_->RemoveFromParent(); break; case 3: - EndTest(); + // This ensures all texture mailboxes are released before the end of the + // test. + layer_->ClearClient(); break; + default: + NOTREACHED(); } } @@ -863,15 +877,13 @@ class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest { void AfterTest() override {} base::Lock activate_count_lock_; - int activate_count_; + int activate_count_ = 0; scoped_refptr<Layer> root_; scoped_refptr<TextureLayer> layer_; + int released_count_ = 0; }; -// Flaky on windows and linux. https://crbug.com/641613 -#if !defined(OS_WIN) && !defined(OS_LINUX) SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerMailboxIsActivatedDuringCommit); -#endif class TextureLayerImplWithMailboxTest : public TextureLayerTest { protected: @@ -1176,6 +1188,16 @@ class TextureLayerChangeInvisibleMailboxTest void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) { EXPECT_TRUE(sync_token.HasData()); ++mailbox_returned_; + switch (mailbox_returned_) { + case 1: + break; + case 2: + EXPECT_EQ(commit_count_, 5); + EndTest(); + break; + default: + NOTREACHED(); + } } void SetupTree() override { @@ -1240,8 +1262,6 @@ class TextureLayerChangeInvisibleMailboxTest texture_layer_->ClearClient(); break; case 5: - EXPECT_EQ(2, mailbox_returned_); - EndTest(); break; default: NOTREACHED(); @@ -1264,7 +1284,8 @@ class TextureLayerChangeInvisibleMailboxTest int commit_count_; }; -SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest); +// Flaky when multi-threaded. crbug.com/702868 +SINGLE_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest); // Test that TextureLayerImpl::ReleaseResources can be called which releases // the mailbox back to TextureLayerClient. diff --git a/chromium/cc/layers/ui_resource_layer.h b/chromium/cc/layers/ui_resource_layer.h index 0dbe6d019e4..57d2f031516 100644 --- a/chromium/cc/layers/ui_resource_layer.h +++ b/chromium/cc/layers/ui_resource_layer.h @@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/resources/ui_resource_client.h" #include "ui/gfx/geometry/rect.h" diff --git a/chromium/cc/layers/ui_resource_layer_impl.cc b/chromium/cc/layers/ui_resource_layer_impl.cc index 50d0321fefa..dd2441bf37b 100644 --- a/chromium/cc/layers/ui_resource_layer_impl.cc +++ b/chromium/cc/layers/ui_resource_layer_impl.cc @@ -143,17 +143,17 @@ const char* UIResourceLayerImpl::LayerTypeAsString() const { std::unique_ptr<base::DictionaryValue> UIResourceLayerImpl::LayerTreeAsJson() { std::unique_ptr<base::DictionaryValue> result = LayerImpl::LayerTreeAsJson(); - result->Set("ImageBounds", MathUtil::AsValue(image_bounds_).release()); + result->Set("ImageBounds", MathUtil::AsValue(image_bounds_)); - base::ListValue* list = new base::ListValue; + auto list = base::MakeUnique<base::ListValue>(); list->AppendDouble(vertex_opacity_[0]); list->AppendDouble(vertex_opacity_[1]); list->AppendDouble(vertex_opacity_[2]); list->AppendDouble(vertex_opacity_[3]); - result->Set("VertexOpacity", list); + result->Set("VertexOpacity", std::move(list)); - result->Set("UVTopLeft", MathUtil::AsValue(uv_top_left_).release()); - result->Set("UVBottomRight", MathUtil::AsValue(uv_bottom_right_).release()); + result->Set("UVTopLeft", MathUtil::AsValue(uv_top_left_)); + result->Set("UVBottomRight", MathUtil::AsValue(uv_bottom_right_)); return result; } diff --git a/chromium/cc/layers/ui_resource_layer_impl.h b/chromium/cc/layers/ui_resource_layer_impl.h index 36bcdd55dbc..e7d8b6f91f5 100644 --- a/chromium/cc/layers/ui_resource_layer_impl.h +++ b/chromium/cc/layers/ui_resource_layer_impl.h @@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_impl.h" #include "cc/resources/resource_provider.h" #include "cc/resources/ui_resource_client.h" diff --git a/chromium/cc/layers/video_frame_provider.h b/chromium/cc/layers/video_frame_provider.h index a6789c11166..e610d4df91b 100644 --- a/chromium/cc/layers/video_frame_provider.h +++ b/chromium/cc/layers/video_frame_provider.h @@ -7,7 +7,7 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace media { class VideoFrame; diff --git a/chromium/cc/layers/video_frame_provider_client_impl.h b/chromium/cc/layers/video_frame_provider_client_impl.h index f7892ee1bf8..f7c91c944a9 100644 --- a/chromium/cc/layers/video_frame_provider_client_impl.h +++ b/chromium/cc/layers/video_frame_provider_client_impl.h @@ -9,7 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/video_frame_provider.h" #include "cc/scheduler/video_frame_controller.h" #include "ui/gfx/transform.h" diff --git a/chromium/cc/layers/video_layer.h b/chromium/cc/layers/video_layer.h index 9bd75655cb8..02919b15273 100644 --- a/chromium/cc/layers/video_layer.h +++ b/chromium/cc/layers/video_layer.h @@ -7,7 +7,7 @@ #include "base/callback.h" #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "media/base/video_rotation.h" diff --git a/chromium/cc/layers/video_layer_impl.cc b/chromium/cc/layers/video_layer_impl.cc index d63ab87c7ae..53b90ee4fa5 100644 --- a/chromium/cc/layers/video_layer_impl.cc +++ b/chromium/cc/layers/video_layer_impl.cc @@ -170,7 +170,7 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass, render_pass->CreateAndAppendSharedQuadState(); shared_quad_state->SetAll(transform, rotated_size, visible_layer_rect(), clip_rect(), is_clipped(), draw_opacity(), - draw_blend_mode(), GetSortingContextId()); + SkBlendMode::kSrcOver, GetSortingContextId()); AppendDebugBorderQuad( render_pass, rotated_size, shared_quad_state, append_quads_data); diff --git a/chromium/cc/layers/video_layer_impl.h b/chromium/cc/layers/video_layer_impl.h index 9169359fcaf..c895813ff65 100644 --- a/chromium/cc/layers/video_layer_impl.h +++ b/chromium/cc/layers/video_layer_impl.h @@ -8,7 +8,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_impl.h" #include "cc/resources/release_callback_impl.h" #include "cc/resources/video_resource_updater.h" diff --git a/chromium/cc/output/begin_frame_args.cc b/chromium/cc/output/begin_frame_args.cc index f6d66520b51..ae595450857 100644 --- a/chromium/cc/output/begin_frame_args.cc +++ b/chromium/cc/output/begin_frame_args.cc @@ -111,20 +111,24 @@ BeginFrameAck::BeginFrameAck() : sequence_number(BeginFrameArgs::kInvalidFrameNumber), latest_confirmed_sequence_number(BeginFrameArgs::kInvalidFrameNumber), source_id(0), - remaining_frames(0), has_damage(false) {} BeginFrameAck::BeginFrameAck(uint32_t source_id, uint64_t sequence_number, uint64_t latest_confirmed_sequence_number, - uint32_t remaining_frames, bool has_damage) : sequence_number(sequence_number), latest_confirmed_sequence_number(latest_confirmed_sequence_number), source_id(source_id), - remaining_frames(remaining_frames), has_damage(has_damage) { DCHECK_LT(BeginFrameArgs::kInvalidFrameNumber, sequence_number); } +// static +BeginFrameAck BeginFrameAck::CreateManualAckWithDamage() { + return BeginFrameAck(BeginFrameArgs::kManualSourceId, + BeginFrameArgs::kStartingFrameNumber, + BeginFrameArgs::kInvalidFrameNumber, true); +} + } // namespace cc diff --git a/chromium/cc/output/begin_frame_args.h b/chromium/cc/output/begin_frame_args.h index 7fe704c572b..d4ced74a32c 100644 --- a/chromium/cc/output/begin_frame_args.h +++ b/chromium/cc/output/begin_frame_args.h @@ -12,7 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "base/values.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { namespace trace_event { @@ -50,6 +50,12 @@ struct CC_EXPORT BeginFrameArgs { }; static const char* TypeToString(BeginFrameArgsType type); + static constexpr uint32_t kStartingSourceId = 0; + // |source_id| for BeginFrameArgs not created by a BeginFrameSource. Used to + // avoid sequence number conflicts of BeginFrameArgs manually fed to an + // observer with those fed to the observer by the its BeginFrameSource. + static constexpr uint32_t kManualSourceId = UINT32_MAX; + static constexpr uint64_t kInvalidFrameNumber = 0; static constexpr uint64_t kStartingFrameNumber = 1; @@ -116,9 +122,12 @@ struct CC_EXPORT BeginFrameAck { BeginFrameAck(uint32_t source_id, uint64_t sequence_number, uint64_t latest_confirmed_sequence_number, - uint32_t remaining_frames, bool has_damage); + // Creates a BeginFrameAck for a manual BeginFrame. Used when clients produce + // a CompositorFrame without prior BeginFrame, e.g. for synchronous drawing. + static BeginFrameAck CreateManualAckWithDamage(); + // Sequence number of the BeginFrame that is acknowledged. uint64_t sequence_number; @@ -158,10 +167,6 @@ struct CC_EXPORT BeginFrameAck { // BeginFrame from the old source is still in flight. uint32_t source_id; // |source_id| after above fields for packing. - // Number of BeginFrames queued at the observer at time of acknowledgment. - // TODO(eseckler): Remove this field and replace with ack-tracking if needed. - uint32_t remaining_frames; - // |true| if the observer has produced damage (e.g. sent a CompositorFrame or // damaged a surface) as part of responding to the BeginFrame. bool has_damage; diff --git a/chromium/cc/output/bsp_tree_perftest.cc b/chromium/cc/output/bsp_tree_perftest.cc index a6f2ab677c2..3b954d1d41e 100644 --- a/chromium/cc/output/bsp_tree_perftest.cc +++ b/chromium/cc/output/bsp_tree_perftest.cc @@ -14,7 +14,7 @@ #include "base/strings/string_piece.h" #include "base/threading/thread.h" #include "base/time/time.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/layers/layer.h" #include "cc/output/bsp_tree.h" #include "cc/quads/draw_polygon.h" @@ -120,8 +120,7 @@ class BspTreePerfTest : public LayerTreeTest { active_tree->OverscrollElasticityLayer(), max_texture_size, can_render_to_separate_surface, host_impl->settings().layer_transforms_should_scale_layer_contents, - false, // do not verify_clip_tree_calculation for perf tests - false, // do not verify_visible_rect_calculation for perf tests + false, // don't use layer lists for perf tests &update_list, active_tree->property_trees()); LayerTreeHostCommon::CalculateDrawProperties(&inputs); } diff --git a/chromium/cc/output/buffer_to_texture_target_map.h b/chromium/cc/output/buffer_to_texture_target_map.h index 62ea52fd853..95193fe77ef 100644 --- a/chromium/cc/output/buffer_to_texture_target_map.h +++ b/chromium/cc/output/buffer_to_texture_target_map.h @@ -8,7 +8,7 @@ #include <map> #include <string> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "ui/gfx/buffer_types.h" namespace cc { diff --git a/chromium/cc/output/color_lut_cache.cc b/chromium/cc/output/color_lut_cache.cc index 4cc72203631..f54c1934adf 100644 --- a/chromium/cc/output/color_lut_cache.cc +++ b/chromium/cc/output/color_lut_cache.cc @@ -81,7 +81,10 @@ unsigned int ColorLUTCache::MakeLUT(const gfx::ColorTransform* transform, } } - unsigned int lut_texture; + GLuint previously_bound_texture = 0; + GLuint lut_texture = 0; + gl_->GetIntegerv(GL_TEXTURE_BINDING_2D, + reinterpret_cast<GLint*>(&previously_bound_texture)); gl_->GenTextures(1, &lut_texture); gl_->BindTexture(GL_TEXTURE_2D, lut_texture); gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -92,6 +95,7 @@ unsigned int ColorLUTCache::MakeLUT(const gfx::ColorTransform* transform, lut_samples * lut_samples, 0, GL_RGBA, sizeof(T) == 1 ? GL_UNSIGNED_BYTE : GL_HALF_FLOAT_OES, lut.data()); + gl_->BindTexture(GL_TEXTURE_2D, previously_bound_texture); return lut_texture; } @@ -103,11 +107,11 @@ ColorLUTCache::LUT ColorLUTCache::GetLUT(const gfx::ColorTransform* transform) { } LUT lut; - // If input is HDR, and the output is scRGB, we're going to need + // If input is HDR, and the output is full range, we're going to need // to produce values outside of 0-1, so we'll need to make a half-float // LUT. Also, we'll need to build a larger lut to maintain accuracy. - // All LUT sizes should be odd a some transforms hav a knee at 0.5. - if (transform->GetDstColorSpace() == gfx::ColorSpace::CreateSCRGBLinear() && + // All LUT sizes should be odd as some transforms have a knee at 0.5. + if (transform->GetDstColorSpace().FullRangeEncodedValues() && transform->GetSrcColorSpace().IsHDR() && texture_half_float_linear_) { lut.size = 37; lut.texture = MakeLUT<uint16_t>(transform, lut.size); diff --git a/chromium/cc/output/compositor_frame.h b/chromium/cc/output/compositor_frame.h index 57e26b50ee6..1ee3fb72b4f 100644 --- a/chromium/cc/output/compositor_frame.h +++ b/chromium/cc/output/compositor_frame.h @@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/compositor_frame_metadata.h" #include "cc/quads/render_pass.h" #include "cc/resources/transferable_resource.h" diff --git a/chromium/cc/output/compositor_frame_metadata.h b/chromium/cc/output/compositor_frame_metadata.h index 8bd04f00d18..a3ebfc26483 100644 --- a/chromium/cc/output/compositor_frame_metadata.h +++ b/chromium/cc/output/compositor_frame_metadata.h @@ -9,14 +9,15 @@ #include <vector> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/selection.h" +#include "cc/output/begin_frame_args.h" #include "cc/surfaces/surface_id.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/events/latency_info.h" #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/geometry/vector2d_f.h" #include "ui/gfx/selection_bound.h" +#include "ui/latency/latency_info.h" namespace cc { @@ -76,8 +77,17 @@ class CC_EXPORT CompositorFrameMetadata { std::vector<ui::LatencyInfo> latency_info; // This is the set of Surfaces that are referenced by this frame. + // Note: this includes occluded and clipped surfaces and surfaces that may + // be accessed by this CompositorFrame in the future. + // TODO(fsamuel): In the future, a generalized frame eviction system will + // determine which surfaces to retain and which to evict. It will likely + // be unnecessary for the embedder to explicitly specify which surfaces to + // retain. Thus, this field will likely go away. std::vector<SurfaceId> referenced_surfaces; + // This is the set of SurfaceIds embedded in DrawQuads. + std::vector<SurfaceId> embedded_surfaces; + // This indicates whether this CompositorFrame can be activated before // dependencies have been resolved. bool can_activate_before_dependencies = true; @@ -88,6 +98,14 @@ class CC_EXPORT CompositorFrameMetadata { // become available in all renderer processes. See https://crbug.com/695579. uint32_t content_source_id = 0; + // BeginFrameAck for the BeginFrame that this CompositorFrame answers. + BeginFrameAck begin_frame_ack; + + // Once the display compositor processes a frame containing a non-zero frame + // token, the token is sent to embedder of the frame. This is helpful when + // the embedder wants to do something after a particular frame is processed. + uint32_t frame_token = 0; + private: CompositorFrameMetadata(const CompositorFrameMetadata& other); CompositorFrameMetadata operator=(const CompositorFrameMetadata&) = delete; diff --git a/chromium/cc/output/compositor_frame_sink.h b/chromium/cc/output/compositor_frame_sink.h index 92496ed8b0e..650f7191c2e 100644 --- a/chromium/cc/output/compositor_frame_sink.h +++ b/chromium/cc/output/compositor_frame_sink.h @@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/threading/thread_checker.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/context_provider.h" #include "cc/output/overlay_candidate_validator.h" #include "cc/output/vulkan_context_provider.h" @@ -27,6 +27,7 @@ namespace cc { class CompositorFrame; class CompositorFrameSinkClient; +class LocalSurfaceId; class SharedBitmapManager; // An interface for submitting CompositorFrames to a display compositor @@ -105,6 +106,10 @@ class CC_EXPORT CompositorFrameSink { // currently in use. virtual void ForceReclaimResources() {} + // If supported, this sets the LocalSurfaceId the CompositorFrameSink will use + // to submit a CompositorFrame. + virtual void SetLocalSurfaceId(const LocalSurfaceId& local_surface_id) {} + // Support for a pull-model where draws are requested by the output surface. // // CompositorFrameSink::Invalidate is called by the compositor to notify that diff --git a/chromium/cc/output/compositor_frame_sink_client.h b/chromium/cc/output/compositor_frame_sink_client.h index b67c6fc302c..afc9b3ad93e 100644 --- a/chromium/cc/output/compositor_frame_sink_client.h +++ b/chromium/cc/output/compositor_frame_sink_client.h @@ -8,7 +8,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/context_provider.h" #include "cc/resources/returned_resource.h" #include "gpu/command_buffer/common/texture_in_use_response.h" diff --git a/chromium/cc/output/context_cache_controller.cc b/chromium/cc/output/context_cache_controller.cc index 79e85b3e033..de178771aee 100644 --- a/chromium/cc/output/context_cache_controller.cc +++ b/chromium/cc/output/context_cache_controller.cc @@ -128,8 +128,9 @@ void ContextCacheController::ClientBecameNotBusy( void ContextCacheController::PostIdleCallback( uint32_t current_idle_generation) const { task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(&ContextCacheController::OnIdle, weak_ptr_, - current_idle_generation), + FROM_HERE, + base::BindOnce(&ContextCacheController::OnIdle, weak_ptr_, + current_idle_generation), base::TimeDelta::FromSeconds(kIdleCleanupDelaySeconds)); } diff --git a/chromium/cc/output/context_cache_controller.h b/chromium/cc/output/context_cache_controller.h index 67b215e6305..614ec0d66c2 100644 --- a/chromium/cc/output/context_cache_controller.h +++ b/chromium/cc/output/context_cache_controller.h @@ -12,7 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" class GrContext; diff --git a/chromium/cc/output/context_provider.h b/chromium/cc/output/context_provider.h index bc8f8c35ed8..44c69412d3b 100644 --- a/chromium/cc/output/context_provider.h +++ b/chromium/cc/output/context_provider.h @@ -11,7 +11,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/context_cache_controller.h" #include "gpu/command_buffer/common/capabilities.h" diff --git a/chromium/cc/output/copy_output_request.h b/chromium/cc/output/copy_output_request.h index 112daa40dce..437ebdf1b27 100644 --- a/chromium/cc/output/copy_output_request.h +++ b/chromium/cc/output/copy_output_request.h @@ -11,7 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/optional.h" #include "base/unguessable_token.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "mojo/public/cpp/bindings/struct_traits.h" diff --git a/chromium/cc/output/copy_output_result.h b/chromium/cc/output/copy_output_result.h index 23334645edc..c4d2fee98e1 100644 --- a/chromium/cc/output/copy_output_result.h +++ b/chromium/cc/output/copy_output_result.h @@ -8,7 +8,7 @@ #include <memory> #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "mojo/public/cpp/bindings/struct_traits.h" diff --git a/chromium/cc/output/dc_layer_overlay.cc b/chromium/cc/output/dc_layer_overlay.cc new file mode 100644 index 00000000000..eda508e6e13 --- /dev/null +++ b/chromium/cc/output/dc_layer_overlay.cc @@ -0,0 +1,207 @@ +// Copyright 2017 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/output/dc_layer_overlay.h" + +#include "cc/base/math_util.h" +#include "cc/quads/solid_color_draw_quad.h" +#include "cc/quads/yuv_video_draw_quad.h" +#include "cc/resources/resource_provider.h" +#include "gpu/GLES2/gl2extchromium.h" +#include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gl/gl_switches.h" + +namespace cc { + +namespace { + +DCLayerOverlayProcessor::DCLayerResult FromYUVQuad( + ResourceProvider* resource_provider, + const YUVVideoDrawQuad* quad, + DCLayerOverlay* ca_layer_overlay) { + for (const auto& resource : quad->resources) { + if (!resource_provider->IsOverlayCandidate(resource)) + return DCLayerOverlayProcessor::DC_LAYER_FAILED_TEXTURE_NOT_CANDIDATE; + } + ca_layer_overlay->resources = quad->resources; + ca_layer_overlay->contents_rect = quad->ya_tex_coord_rect; + ca_layer_overlay->filter = GL_LINEAR; + return DCLayerOverlayProcessor::DC_LAYER_SUCCESS; +} + +// This returns the smallest rectangle in target space that contains the quad. +gfx::RectF ClippedQuadRectangle(const DrawQuad* quad) { + gfx::RectF quad_rect = MathUtil::MapClippedRect( + quad->shared_quad_state->quad_to_target_transform, + gfx::RectF(quad->rect)); + if (quad->shared_quad_state->is_clipped) + quad_rect.Intersect(gfx::RectF(quad->shared_quad_state->clip_rect)); + return quad_rect; +} + +// Find a rectangle containing all the quads in a list that occlude the area +// in target_quad. +gfx::RectF GetOcclusionBounds(const gfx::RectF& target_quad, + QuadList::ConstIterator quad_list_begin, + QuadList::ConstIterator quad_list_end) { + gfx::RectF occlusion_bounding_box; + for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end; + ++overlap_iter) { + float opacity = overlap_iter->shared_quad_state->opacity; + if (opacity < std::numeric_limits<float>::epsilon()) + continue; + const DrawQuad* quad = *overlap_iter; + gfx::RectF overlap_rect = ClippedQuadRectangle(quad); + if (quad->material == DrawQuad::SOLID_COLOR) { + SkColor color = SolidColorDrawQuad::MaterialCast(quad)->color; + float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; + if (quad->ShouldDrawWithBlending() && + alpha < std::numeric_limits<float>::epsilon()) + continue; + } + overlap_rect.Intersect(target_quad); + if (!overlap_rect.IsEmpty()) { + occlusion_bounding_box.Union(overlap_rect); + } + } + return occlusion_bounding_box; +} + +} // namespace + +DCLayerOverlay::DCLayerOverlay() : filter(GL_LINEAR) {} + +DCLayerOverlay::DCLayerOverlay(const DCLayerOverlay& other) = default; + +DCLayerOverlay::~DCLayerOverlay() {} + +DCLayerOverlayProcessor::DCLayerResult DCLayerOverlayProcessor::FromDrawQuad( + ResourceProvider* resource_provider, + const gfx::RectF& display_rect, + QuadList::ConstIterator quad_list_begin, + QuadList::ConstIterator quad, + DCLayerOverlay* ca_layer_overlay) { + if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver) + return DC_LAYER_FAILED_QUAD_BLEND_MODE; + + DCLayerResult result = DC_LAYER_FAILED_UNKNOWN; + switch (quad->material) { + case DrawQuad::YUV_VIDEO_CONTENT: + result = + FromYUVQuad(resource_provider, YUVVideoDrawQuad::MaterialCast(*quad), + ca_layer_overlay); + break; + default: + return DC_LAYER_FAILED_UNKNOWN; + } + if (result != DC_LAYER_SUCCESS) + return result; + + scoped_refptr<DCLayerOverlaySharedState> overlay_shared_state( + new DCLayerOverlaySharedState); + overlay_shared_state->z_order = 1; + + overlay_shared_state->is_clipped = quad->shared_quad_state->is_clipped; + overlay_shared_state->clip_rect = + gfx::RectF(quad->shared_quad_state->clip_rect); + + overlay_shared_state->opacity = quad->shared_quad_state->opacity; + overlay_shared_state->transform = + quad->shared_quad_state->quad_to_target_transform.matrix(); + + ca_layer_overlay->shared_state = overlay_shared_state; + ca_layer_overlay->bounds_rect = gfx::RectF(quad->rect); + + return result; +} + +void DCLayerOverlayProcessor::Process(ResourceProvider* resource_provider, + const gfx::RectF& display_rect, + QuadList* quad_list, + gfx::Rect* overlay_damage_rect, + gfx::Rect* damage_rect, + DCLayerOverlayList* ca_layer_overlays) { + gfx::Rect this_frame_underlay_rect; + bool display_rect_changed = (display_rect != previous_display_rect_); + for (auto it = quad_list->begin(); it != quad_list->end(); ++it) { + DCLayerOverlay ca_layer; + DCLayerResult result = FromDrawQuad(resource_provider, display_rect, + quad_list->begin(), it, &ca_layer); + if (result != DC_LAYER_SUCCESS) + continue; + + if (!it->shared_quad_state->quad_to_target_transform + .Preserves2dAxisAlignment() && + !base::FeatureList::IsEnabled( + features::kDirectCompositionComplexOverlays)) { + continue; + } + + gfx::Rect quad_rectangle = gfx::ToEnclosingRect(ClippedQuadRectangle(*it)); + gfx::RectF occlusion_bounding_box = + GetOcclusionBounds(gfx::RectF(quad_rectangle), quad_list->begin(), it); + if (occlusion_bounding_box.IsEmpty()) { + // The quad is on top, so promote it to an overlay and remove all damage + // underneath it. + if (it->shared_quad_state->quad_to_target_transform + .Preserves2dAxisAlignment() && + !display_rect_changed && !it->ShouldDrawWithBlending()) { + damage_rect->Subtract(quad_rectangle); + } + quad_list->EraseAndInvalidateAllPointers(it); + } else if (!base::FeatureList::IsEnabled( + features::kDirectCompositionUnderlays)) { + continue; + } else { + // The quad is occluded, so replace it with a black solid color quad and + // place the overlay itself under the quad. + if (it->shared_quad_state->quad_to_target_transform + .IsIdentityOrIntegerTranslation()) { + this_frame_underlay_rect = quad_rectangle; + } + ca_layer.shared_state->z_order = -1; + const SharedQuadState* shared_quad_state = it->shared_quad_state; + gfx::Rect rect = it->visible_rect; + SolidColorDrawQuad* replacement = + quad_list->ReplaceExistingElement<SolidColorDrawQuad>(it); + replacement->SetAll(shared_quad_state, rect, rect, rect, false, + SK_ColorTRANSPARENT, true); + + if (this_frame_underlay_rect == previous_frame_underlay_rect_) { + // If this underlay rect is the same as for last frame, subtract its + // area from the damage of the main surface, as the cleared area was + // already cleared last frame. Add back the damage from the occluded + // area for this and last frame, as that may have changed. + if (it->shared_quad_state->quad_to_target_transform + .Preserves2dAxisAlignment() && + !display_rect_changed) { + gfx::Rect occluding_damage_rect = *damage_rect; + occluding_damage_rect.Intersect(quad_rectangle); + damage_rect->Subtract(quad_rectangle); + gfx::Rect new_occlusion_bounding_box = + gfx::ToEnclosingRect(occlusion_bounding_box); + new_occlusion_bounding_box.Union(previous_occlusion_bounding_box_); + occluding_damage_rect.Intersect(new_occlusion_bounding_box); + + damage_rect->Union(occluding_damage_rect); + } + } else { + // Entire replacement quad must be redrawn. + damage_rect->Union(quad_rectangle); + } + previous_occlusion_bounding_box_ = + gfx::ToEnclosingRect(occlusion_bounding_box); + } + overlay_damage_rect->Union(quad_rectangle); + + ca_layer_overlays->push_back(ca_layer); + // Only allow one overlay for now. + break; + } + damage_rect->Intersect(gfx::ToEnclosingRect(display_rect)); + previous_frame_underlay_rect_ = this_frame_underlay_rect; + previous_display_rect_ = display_rect; +} + +} // namespace cc diff --git a/chromium/cc/output/dc_layer_overlay.h b/chromium/cc/output/dc_layer_overlay.h new file mode 100644 index 00000000000..5ae861a22d8 --- /dev/null +++ b/chromium/cc/output/dc_layer_overlay.h @@ -0,0 +1,102 @@ +// Copyright 2017 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_DC_LAYER_OVERLAY_H_ +#define CC_OUTPUT_DC_LAYER_OVERLAY_H_ + +#include "base/memory/ref_counted.h" +#include "cc/quads/render_pass.h" +#include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkMatrix44.h" +#include "ui/gfx/geometry/rect_f.h" +#include "ui/gl/dc_renderer_layer_params.h" + +namespace cc { +class DrawQuad; +class ResourceProvider; + +class CC_EXPORT DCLayerOverlaySharedState + : public base::RefCounted<DCLayerOverlaySharedState> { + public: + DCLayerOverlaySharedState() {} + int z_order = 0; + // If |is_clipped| is true, then clip to |clip_rect| in the target space. + bool is_clipped = false; + gfx::RectF clip_rect; + // The opacity property for the CAayer. + float opacity = 1; + // The transform to apply to the DCLayer. + SkMatrix44 transform = SkMatrix44(SkMatrix44::kIdentity_Constructor); + + private: + friend class base::RefCounted<DCLayerOverlaySharedState>; + ~DCLayerOverlaySharedState() {} +}; + +// Holds all information necessary to construct a DCLayer from a DrawQuad. +class CC_EXPORT DCLayerOverlay { + public: + DCLayerOverlay(); + DCLayerOverlay(const DCLayerOverlay& other); + ~DCLayerOverlay(); + + // State that is frequently shared between consecutive DCLayerOverlays. + scoped_refptr<DCLayerOverlaySharedState> shared_state; + + // Resource ids that correspond to the DXGI textures to set as the contents + // of the DCLayer. + DrawQuad::Resources resources; + // The contents rect property for the DCLayer. + gfx::RectF contents_rect; + // The bounds for the DCLayer in pixels. + gfx::RectF bounds_rect; + // The background color property for the DCLayer. + SkColor background_color = SK_ColorTRANSPARENT; + // The edge anti-aliasing mask property for the DCLayer. + unsigned edge_aa_mask = 0; + // The minification and magnification filters for the DCLayer. + unsigned filter; + // If |rpdq| is present, then the renderer must draw the filter effects and + // copy the result into an IOSurface. + const RenderPassDrawQuad* rpdq = nullptr; +}; + +typedef std::vector<DCLayerOverlay> DCLayerOverlayList; + +class DCLayerOverlayProcessor { + public: + enum DCLayerResult { + DC_LAYER_SUCCESS, + DC_LAYER_FAILED_QUAD_BLEND_MODE, + DC_LAYER_FAILED_TEXTURE_NOT_CANDIDATE, + DC_LAYER_FAILED_OCCLUDED, + DC_LAYER_FAILED_UNKNOWN + }; + + void Process(ResourceProvider* resource_provider, + const gfx::RectF& display_rect, + QuadList* quad_list, + gfx::Rect* overlay_damage_rect, + gfx::Rect* damage_rect, + DCLayerOverlayList* ca_layer_overlays); + void ClearOverlayState() { + previous_frame_underlay_rect_ = gfx::Rect(); + previous_occlusion_bounding_box_ = gfx::Rect(); + } + + private: + DCLayerResult FromDrawQuad(ResourceProvider* resource_provider, + const gfx::RectF& display_rect, + QuadList::ConstIterator quad_list_begin, + QuadList::ConstIterator quad, + DCLayerOverlay* ca_layer_overlay); + + gfx::Rect previous_frame_underlay_rect_; + gfx::Rect previous_occlusion_bounding_box_; + gfx::RectF previous_display_rect_; +}; + +} // namespace cc + +#endif // CC_OUTPUT_DC_LAYER_OVERLAY_H_ diff --git a/chromium/cc/output/direct_renderer.cc b/chromium/cc/output/direct_renderer.cc index e4fcf68ca0a..024f5653f36 100644 --- a/chromium/cc/output/direct_renderer.cc +++ b/chromium/cc/output/direct_renderer.cc @@ -25,6 +25,8 @@ #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/transform.h" +namespace { + static gfx::Transform OrthoProjectionMatrix(float left, float right, float bottom, @@ -62,6 +64,13 @@ static gfx::Transform window_matrix(int x, int y, int width, int height) { return canvas; } +// Switching between enabling DC layers and not is expensive, so only +// switch away after a large number of frames not needing DC layers have +// been produced. +constexpr int kNumberOfFramesBeforeDisablingDCLayers = 60; + +} // namespace + namespace cc { DirectRenderer::DrawingFrame::DrawingFrame() = default; @@ -87,8 +96,8 @@ void DirectRenderer::Initialize() { if (context_provider) { if (context_provider->ContextCapabilities().commit_overlay_planes) allow_empty_swap_ = true; - if (context_provider->ContextCapabilities().set_draw_rectangle) - use_set_draw_rectangle_ = true; + if (context_provider->ContextCapabilities().dc_layers) + supports_dc_layers_ = true; if (context_provider->ContextCapabilities() .disable_non_empty_post_sub_buffers) { use_partial_swap_ = false; @@ -259,6 +268,7 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, bool frame_has_alpha = current_frame()->root_render_pass->has_transparent_background; bool use_stencil = overdraw_feedback_; + bool did_reshape = false; if (device_viewport_size != reshape_surface_size_ || device_scale_factor != reshape_device_scale_factor_ || root_render_pass->color_space != reshape_device_color_space_ || @@ -273,6 +283,7 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, output_surface_->Reshape( reshape_surface_size_, reshape_device_scale_factor_, reshape_device_color_space_, reshape_has_alpha_, reshape_use_stencil_); + did_reshape = true; } BeginDrawingFrame(); @@ -315,8 +326,26 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, resource_provider_, root_render_pass, render_pass_filters_, render_pass_background_filters_, ¤t_frame()->overlay_list, ¤t_frame()->ca_layer_overlay_list, + ¤t_frame()->dc_layer_overlay_list, ¤t_frame()->root_damage_rect, ¤t_frame()->root_content_bounds); + bool was_using_dc_layers = using_dc_layers_; + if (!current_frame()->dc_layer_overlay_list.empty()) { + DCHECK(supports_dc_layers_); + using_dc_layers_ = true; + frames_since_using_dc_layers_ = 0; + } else if (++frames_since_using_dc_layers_ >= + kNumberOfFramesBeforeDisablingDCLayers) { + using_dc_layers_ = false; + } + if (supports_dc_layers_ && + (did_reshape || (was_using_dc_layers != using_dc_layers_))) { + // The entire surface has to be redrawn if it was reshaped or if switching + // from or to DirectComposition layers, because the previous contents are + // discarded and some contents would otherwise be undefined. + current_frame()->root_damage_rect = + current_frame()->root_render_pass->output_rect; + } // We can skip all drawing if the damage rect is now empty. bool skip_drawing_root_render_pass = @@ -378,13 +407,13 @@ bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad, if (render_pass_scissor.IsEmpty()) return true; - if (quad.shared_quad_state->is_clipped) { - gfx::Rect r = quad.shared_quad_state->clip_rect; - r.Intersect(render_pass_scissor); - return r.IsEmpty(); - } + gfx::Rect target_rect = MathUtil::MapEnclosingClippedRect( + quad.shared_quad_state->quad_to_target_transform, quad.visible_rect); + if (quad.shared_quad_state->is_clipped) + target_rect.Intersect(quad.shared_quad_state->clip_rect); - return false; + target_rect.Intersect(render_pass_scissor); + return target_rect.IsEmpty(); } void DirectRenderer::SetScissorStateForQuad( @@ -510,13 +539,15 @@ void DirectRenderer::DrawRenderPass(const RenderPass* render_pass) { bool is_root_render_pass = current_frame()->current_render_pass == current_frame()->root_render_pass; + bool render_pass_is_clipped = + !render_pass_scissor_in_draw_space.Contains(surface_rect_in_draw_space); + // The SetDrawRectangleCHROMIUM spec requires that the scissor bit is always // set on the root framebuffer or else the rendering may modify something // outside the damage rectangle, even if the damage rectangle is the size of // the full backbuffer. - bool render_pass_is_clipped = - (use_set_draw_rectangle_ && is_root_render_pass) || - !render_pass_scissor_in_draw_space.Contains(surface_rect_in_draw_space); + bool render_pass_requires_scissor = + (supports_dc_layers_ && is_root_render_pass) || render_pass_is_clipped; bool has_external_stencil_test = is_root_render_pass && output_surface_->HasExternalStencilTest(); bool should_clear_surface = @@ -529,7 +560,7 @@ void DirectRenderer::DrawRenderPass(const RenderPass* render_pass) { !current_frame()->current_render_pass->has_transparent_background); SurfaceInitializationMode mode; - if (should_clear_surface && render_pass_is_clipped) { + if (should_clear_surface && render_pass_requires_scissor) { mode = SURFACE_INITIALIZATION_MODE_SCISSORED_CLEAR; } else if (should_clear_surface) { mode = SURFACE_INITIALIZATION_MODE_FULL_SURFACE_CLEAR; @@ -557,7 +588,7 @@ void DirectRenderer::DrawRenderPass(const RenderPass* render_pass) { if (last_sorting_context_id != quad.shared_quad_state->sorting_context_id) { last_sorting_context_id = quad.shared_quad_state->sorting_context_id; FlushPolygons(&poly_list, render_pass_scissor_in_draw_space, - render_pass_is_clipped); + render_pass_requires_scissor); } // This layer is in a 3D sorting context so we add it to the list of @@ -574,12 +605,12 @@ void DirectRenderer::DrawRenderPass(const RenderPass* render_pass) { // We are not in a 3d sorting context, so we should draw the quad normally. SetScissorStateForQuad(quad, render_pass_scissor_in_draw_space, - render_pass_is_clipped); + render_pass_requires_scissor); DoDrawQuad(&quad, nullptr); } FlushPolygons(&poly_list, render_pass_scissor_in_draw_space, - render_pass_is_clipped); + render_pass_requires_scissor); FinishDrawingQuadList(); } @@ -589,8 +620,10 @@ bool DirectRenderer::UseRenderPass(const RenderPass* render_pass) { if (render_pass == current_frame()->root_render_pass) { BindFramebufferToOutputSurface(); - if (use_set_draw_rectangle_) + if (supports_dc_layers_) { + SetEnableDCLayers(using_dc_layers_); output_surface_->SetDrawRectangle(current_frame()->root_damage_rect); + } InitializeViewport(current_frame(), render_pass->output_rect, gfx::Rect(current_frame()->device_viewport_size), current_frame()->device_viewport_size); diff --git a/chromium/cc/output/direct_renderer.h b/chromium/cc/output/direct_renderer.h index 8153e8eef7d..864c1863b29 100644 --- a/chromium/cc/output/direct_renderer.h +++ b/chromium/cc/output/direct_renderer.h @@ -11,16 +11,17 @@ #include "base/callback.h" #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/base/filter_operations.h" +#include "cc/cc_export.h" #include "cc/output/ca_layer_overlay.h" -#include "cc/output/filter_operations.h" +#include "cc/output/dc_layer_overlay.h" #include "cc/output/overlay_processor.h" #include "cc/quads/tile_draw_quad.h" #include "cc/resources/resource_provider.h" #include "gpu/command_buffer/common/texture_in_use_response.h" -#include "ui/events/latency_info.h" #include "ui/gfx/geometry/quad_f.h" #include "ui/gfx/geometry/rect.h" +#include "ui/latency/latency_info.h" namespace gfx { class ColorSpace; @@ -89,8 +90,13 @@ class CC_EXPORT DirectRenderer { OverlayCandidateList overlay_list; CALayerOverlayList ca_layer_overlay_list; + DCLayerOverlayList dc_layer_overlay_list; }; + void DisableColorChecksForTesting() { + disable_color_checks_for_testing_ = true; + } + protected: friend class BspWalkActionDrawPolygon; @@ -164,6 +170,7 @@ class CC_EXPORT DirectRenderer { virtual void DidChangeVisibility() = 0; virtual void CopyCurrentRenderPassToBitmap( std::unique_ptr<CopyOutputRequest> request) = 0; + virtual void SetEnableDCLayers(bool enable) = 0; gfx::Size surface_size_for_swap_buffers() const { return reshape_surface_size_; @@ -182,8 +189,14 @@ class CC_EXPORT DirectRenderer { bool use_partial_swap_ = false; // Whether overdraw feedback is enabled and can be used. bool overdraw_feedback_ = false; - // Whether the SetDrawRectangle command is in use. - bool use_set_draw_rectangle_ = false; + // Whether the SetDrawRectangle and EnableDCLayers commands are in + // use. + bool supports_dc_layers_ = false; + // Whether the output surface is actually using DirectComposition. + bool using_dc_layers_ = false; + // This counts the number of draws since the last time + // DirectComposition layers needed to be used. + int frames_since_using_dc_layers_ = 0; // TODO(danakj): Just use a vector of pairs here? Hash map is way overkill. std::unordered_map<int, std::unique_ptr<ScopedResource>> @@ -194,6 +207,7 @@ class CC_EXPORT DirectRenderer { RenderPassFilterList render_pass_background_filters_; bool visible_ = false; + bool disable_color_checks_for_testing_ = false; // For use in coordinate conversion, this stores the output rect, viewport // rect (= unflipped version of glViewport rect), the size of target diff --git a/chromium/cc/output/gl_renderer.cc b/chromium/cc/output/gl_renderer.cc index cdbde1a9c74..3446cc7d721 100644 --- a/chromium/cc/output/gl_renderer.cc +++ b/chromium/cc/output/gl_renderer.cc @@ -27,6 +27,7 @@ #include "build/build_config.h" #include "cc/base/container_util.h" #include "cc/base/math_util.h" +#include "cc/base/render_surface_filters.h" #include "cc/debug/debug_colors.h" #include "cc/output/compositor_frame.h" #include "cc/output/compositor_frame_metadata.h" @@ -36,7 +37,6 @@ #include "cc/output/layer_quad.h" #include "cc/output/output_surface.h" #include "cc/output/output_surface_frame.h" -#include "cc/output/render_surface_filters.h" #include "cc/output/renderer_settings.h" #include "cc/output/static_geometry_binding.h" #include "cc/output/texture_mailbox_deleter.h" @@ -224,6 +224,8 @@ struct DrawRenderPassDrawQuadParams { gfx::QuadF surface_quad; gfx::Transform contents_device_transform; + + gfx::RectF tex_coord_rect; }; static GLint GetActiveTextureUnit(GLES2Interface* gl) { @@ -425,8 +427,10 @@ bool GLRenderer::CanPartialSwap() { } ResourceFormat GLRenderer::BackbufferFormat() const { - // TODO(ccameron): If we are targeting high bit depth or HDR, we should use - // RGBA_F16 here. + if (current_frame()->current_render_pass->color_space.IsHDR() && + resource_provider_->IsRenderBufferFormatSupported(RGBA_F16)) { + return RGBA_F16; + } return resource_provider_->best_texture_format(); } @@ -1038,6 +1042,7 @@ void GLRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad, params.clip_region = clip_region; params.window_matrix = current_frame()->window_matrix; params.projection_matrix = current_frame()->projection_matrix; + params.tex_coord_rect = quad->tex_coord_rect; if (bypass != render_pass_bypass_quads_.end()) { TileDrawQuad* tile_quad = &bypass->second; // RGBA_8888 here is arbitrary and unused. @@ -1245,6 +1250,9 @@ bool GLRenderer::UpdateRPDQWithSkiaFilters( gfx::RectF(src_rect.x() + offset.fX, src_rect.y() + offset.fY, subset.width(), subset.height()); params->src_offset.SetPoint(subset.x(), subset.y()); + gfx::RectF tex_rect = gfx::RectF(gfx::PointF(params->src_offset), + params->dst_rect.size()); + params->tex_coord_rect = tex_rect; } } } @@ -1318,12 +1326,14 @@ void GLRenderer::ChooseRPDQProgram(DrawRenderPassDrawQuadParams* params) { tex_coord_precision, sampler_type, shader_blend_mode, params->use_aa ? USE_AA : NO_AA, mask_mode, mask_for_background, params->use_color_matrix), - current_frame()->current_render_pass->color_space); + params->contents_resource_lock + ? params->contents_resource_lock->color_space() + : gfx::ColorSpace()); } void GLRenderer::UpdateRPDQUniforms(DrawRenderPassDrawQuadParams* params) { - gfx::RectF tex_rect(params->src_offset.x(), params->src_offset.y(), - params->dst_rect.width(), params->dst_rect.height()); + gfx::RectF tex_rect = params->tex_coord_rect; + gfx::Size texture_size; if (params->filter_image) { texture_size.set_width(params->filter_image->width()); @@ -1363,25 +1373,23 @@ void GLRenderer::UpdateRPDQUniforms(DrawRenderPassDrawQuadParams* params) { mask_uv_rect.Scale(params->quad->mask_texture_size.width(), params->quad->mask_texture_size.height()); } + + SkMatrix tex_to_mask = SkMatrix::MakeRectToRect(RectFToSkRect(tex_rect), + RectFToSkRect(mask_uv_rect), + SkMatrix::kFill_ScaleToFit); + if (params->source_needs_flip) { // Mask textures are oriented vertically flipped relative to the // framebuffer and the RenderPass contents texture, so we flip the tex // coords from the RenderPass texture to find the mask texture coords. - gl_->Uniform2f( - current_program_->mask_tex_coord_offset_location(), mask_uv_rect.x(), - mask_uv_rect.height() / tex_rect.height() + mask_uv_rect.y()); - gl_->Uniform2f(current_program_->mask_tex_coord_scale_location(), - mask_uv_rect.width() / tex_rect.width(), - -mask_uv_rect.height() / tex_rect.height()); - } else { - // Tile textures are oriented the same way as mask textures. - gl_->Uniform2f(current_program_->mask_tex_coord_offset_location(), - mask_uv_rect.x(), mask_uv_rect.y()); - gl_->Uniform2f(current_program_->mask_tex_coord_scale_location(), - mask_uv_rect.width() / tex_rect.width(), - mask_uv_rect.height() / tex_rect.height()); + tex_to_mask.preTranslate(0, 1); + tex_to_mask.preScale(1, -1); } + gl_->Uniform2f(current_program_->mask_tex_coord_offset_location(), + tex_to_mask.getTranslateX(), tex_to_mask.getTranslateY()); + gl_->Uniform2f(current_program_->mask_tex_coord_scale_location(), + tex_to_mask.getScaleX(), tex_to_mask.getScaleY()); last_texture_unit = 1; } @@ -1534,7 +1542,7 @@ static gfx::QuadF GetDeviceQuadWithAntialiasingOnExteriorEdges( // Only apply anti-aliasing to edges not clipped by culling or scissoring. // If an edge is degenerate we do not want to replace it with a "proper" edge - // as that will cause the quad to possibly expand is strange ways. + // as that will cause the quad to possibly expand in strange ways. if (!top_edge.degenerate() && is_top(clip_region, quad) && tile_rect.y() == quad->rect.y()) { top_edge = device_layer_edges.top(); @@ -2059,9 +2067,9 @@ void GLRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad, gfx::ColorSpace src_color_space = quad->video_color_space; gfx::ColorSpace dst_color_space = current_frame()->current_render_pass->color_space; - if (!base::FeatureList::IsEnabled(media::kVideoColorManagement)) { - if (!settings_->enable_color_correct_rendering) - dst_color_space = gfx::ColorSpace(); + if (!base::FeatureList::IsEnabled(media::kVideoColorManagement) && + !settings_->enable_color_correct_rendering) { + dst_color_space = gfx::ColorSpace(); switch (quad->color_space) { case YUVVideoDrawQuad::REC_601: src_color_space = gfx::ColorSpace::CreateREC601(); @@ -2078,11 +2086,17 @@ void GLRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad, if (!src_color_space.IsValid()) src_color_space = gfx::ColorSpace::CreateREC709(); + // The source color space should never be RGB. + DCHECK_NE(src_color_space, src_color_space.GetAsFullRangeRGB()); + ResourceProvider::ScopedSamplerGL y_plane_lock( resource_provider_, quad->y_plane_resource_id(), GL_TEXTURE1, GL_LINEAR); + if (base::FeatureList::IsEnabled(media::kVideoColorManagement)) + DCHECK_EQ(src_color_space, y_plane_lock.color_space()); ResourceProvider::ScopedSamplerGL u_plane_lock( resource_provider_, quad->u_plane_resource_id(), GL_TEXTURE2, GL_LINEAR); DCHECK_EQ(y_plane_lock.target(), u_plane_lock.target()); + DCHECK_EQ(y_plane_lock.color_space(), u_plane_lock.color_space()); // TODO(jbauman): Use base::Optional when available. std::unique_ptr<ResourceProvider::ScopedSamplerGL> v_plane_lock; @@ -2091,6 +2105,7 @@ void GLRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad, resource_provider_, quad->v_plane_resource_id(), GL_TEXTURE3, GL_LINEAR)); DCHECK_EQ(y_plane_lock.target(), v_plane_lock->target()); + DCHECK_EQ(y_plane_lock.color_space(), v_plane_lock->color_space()); } std::unique_ptr<ResourceProvider::ScopedSamplerGL> a_plane_lock; if (alpha_texture_mode == YUV_HAS_ALPHA_TEXTURE) { @@ -2441,12 +2456,16 @@ void GLRenderer::FinishDrawingFrame() { if (overdraw_feedback_) FlushOverdrawFeedback(swap_buffer_rect_); + if (use_swap_with_bounds_) + swap_content_bounds_ = current_frame()->root_content_bounds; + current_framebuffer_lock_ = nullptr; gl_->Disable(GL_BLEND); blend_shadow_ = false; ScheduleCALayers(); + ScheduleDCLayers(); ScheduleOverlays(); } @@ -2454,6 +2473,10 @@ void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(SHARED_BINDING); } +void GLRenderer::SetEnableDCLayers(bool enable) { + gl_->SetEnableDCLayersCHROMIUM(enable); +} + bool GLRenderer::FlippedFramebuffer() const { if (force_drawing_frame_framebuffer_unflipped_) return false; @@ -2600,7 +2623,7 @@ void GLRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) { output_frame.latency_info = std::move(latency_info); output_frame.size = surface_size; if (use_swap_with_bounds_) { - output_frame.content_bounds = current_frame()->root_content_bounds; + output_frame.content_bounds = std::move(swap_content_bounds_); } else if (use_partial_swap_) { // If supported, we can save significant bandwidth by only swapping the // damaged/scissored region (clamped to the viewport). @@ -2650,6 +2673,8 @@ void GLRenderer::SwapBuffersComplete() { gl_->ScheduleCALayerInUseQueryCHROMIUM(textures.size(), textures.data()); } } else if (swapping_overlay_resources_.size() > 1) { + ResourceProvider::ScopedBatchReturnResources returner(resource_provider_); + // If a query is not needed to release the overlay buffers, we can assume // that once a swap buffer has completed we can remove the oldest buffers // from the queue. @@ -2660,6 +2685,7 @@ void GLRenderer::SwapBuffersComplete() { void GLRenderer::DidReceiveTextureInUseResponses( const gpu::TextureInUseResponses& responses) { DCHECK(settings_->release_overlay_resources_after_gpu_query); + ResourceProvider::ScopedBatchReturnResources returner(resource_provider_); for (const gpu::TextureInUseResponse& response : responses) { if (!response.in_use) { swapped_and_acked_overlay_resources_.erase(response.texture); @@ -2982,12 +3008,15 @@ void GLRenderer::PrepareGeometry(BoundGeometry binding) { void GLRenderer::SetUseProgram(const ProgramKey& program_key, const gfx::ColorSpace& src_color_space) { + // The source color space for non-YUV draw quads should always be full-range + // RGB. + if (!disable_color_checks_for_testing_) + DCHECK_EQ(src_color_space, src_color_space.GetAsFullRangeRGB()); + // Ensure that we do not apply any color conversion unless the color correct // rendering flag has been specified. This is because media mailboxes will // provide YUV color spaces despite YUV to RGB conversion already having been // performed. - // TODO(ccameron): Ensure that media mailboxes be accurate. - // https://crbug.com/699243 if (settings_->enable_color_correct_rendering) { SetUseProgram(program_key, src_color_space, current_frame()->current_render_pass->color_space); @@ -3190,6 +3219,66 @@ void GLRenderer::ScheduleCALayers() { } } +void GLRenderer::ScheduleDCLayers() { + if (overlay_resource_pool_) { + overlay_resource_pool_->CheckBusyResources(); + } + + scoped_refptr<DCLayerOverlaySharedState> shared_state; + size_t copied_render_pass_count = 0; + for (const DCLayerOverlay& dc_layer_overlay : + current_frame()->dc_layer_overlay_list) { + DCHECK(!dc_layer_overlay.rpdq); + + unsigned texture_id = 0; + for (const auto& contents_resource_id : dc_layer_overlay.resources) { + if (contents_resource_id) { + pending_overlay_resources_.push_back( + base::MakeUnique<ResourceProvider::ScopedReadLockGL>( + resource_provider_, contents_resource_id)); + if (!texture_id) + texture_id = pending_overlay_resources_.back()->texture_id(); + } + } + GLfloat contents_rect[4] = { + dc_layer_overlay.contents_rect.x(), dc_layer_overlay.contents_rect.y(), + dc_layer_overlay.contents_rect.width(), + dc_layer_overlay.contents_rect.height(), + }; + GLfloat bounds_rect[4] = { + dc_layer_overlay.bounds_rect.x(), dc_layer_overlay.bounds_rect.y(), + dc_layer_overlay.bounds_rect.width(), + dc_layer_overlay.bounds_rect.height(), + }; + GLboolean is_clipped = dc_layer_overlay.shared_state->is_clipped; + GLfloat clip_rect[4] = {dc_layer_overlay.shared_state->clip_rect.x(), + dc_layer_overlay.shared_state->clip_rect.y(), + dc_layer_overlay.shared_state->clip_rect.width(), + dc_layer_overlay.shared_state->clip_rect.height()}; + GLint z_order = dc_layer_overlay.shared_state->z_order; + GLfloat transform[16]; + dc_layer_overlay.shared_state->transform.asColMajorf(transform); + unsigned filter = dc_layer_overlay.filter; + + if (dc_layer_overlay.shared_state != shared_state) { + shared_state = dc_layer_overlay.shared_state; + gl_->ScheduleDCLayerSharedStateCHROMIUM( + dc_layer_overlay.shared_state->opacity, is_clipped, clip_rect, + z_order, transform); + } + gl_->ScheduleDCLayerCHROMIUM( + texture_id, contents_rect, dc_layer_overlay.background_color, + dc_layer_overlay.edge_aa_mask, bounds_rect, filter); + } + + // Take the number of copied render passes in this frame, and use 3 times that + // amount as the cache limit. + if (overlay_resource_pool_) { + overlay_resource_pool_->SetResourceUsageLimits( + std::numeric_limits<std::size_t>::max(), copied_render_pass_count * 5); + } +} + void GLRenderer::ScheduleOverlays() { if (current_frame()->overlay_list.empty()) return; @@ -3247,6 +3336,7 @@ void GLRenderer::CopyRenderPassDrawQuadToOverlayResource( params.contents_texture = contents_texture; params.quad_to_target_transform = params.quad->shared_quad_state->quad_to_target_transform; + params.tex_coord_rect = params.quad->tex_coord_rect; // Calculate projection and window matrices using InitializeViewport(). This // requires creating a dummy DrawingFrame. diff --git a/chromium/cc/output/gl_renderer.h b/chromium/cc/output/gl_renderer.h index 36130768a54..3562271d64c 100644 --- a/chromium/cc/output/gl_renderer.h +++ b/chromium/cc/output/gl_renderer.h @@ -10,7 +10,7 @@ #include "base/cancelable_callback.h" #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/color_lut_cache.h" #include "cc/output/context_cache_controller.h" #include "cc/output/direct_renderer.h" @@ -21,8 +21,8 @@ #include "cc/quads/solid_color_draw_quad.h" #include "cc/quads/tile_draw_quad.h" #include "cc/quads/yuv_video_draw_quad.h" -#include "ui/events/latency_info.h" #include "ui/gfx/geometry/quad_f.h" +#include "ui/latency/latency_info.h" namespace gpu { namespace gles2 { @@ -55,6 +55,8 @@ class CC_EXPORT GLRenderer : public DirectRenderer { int highp_threshold_min); ~GLRenderer() override; + bool use_swap_with_bounds() const { return use_swap_with_bounds_; } + void SwapBuffers(std::vector<ui::LatencyInfo> latency_info) override; void SwapBuffersComplete() override; @@ -100,6 +102,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer { void EnsureScissorTestDisabled() override; void CopyCurrentRenderPassToBitmap( std::unique_ptr<CopyOutputRequest> request) override; + void SetEnableDCLayers(bool enable) override; void FinishDrawingQuadList() override; // Returns true if quad requires antialiasing and false otherwise. @@ -244,6 +247,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer { void RestoreGLState(); void ScheduleCALayers(); + void ScheduleDCLayers(); void ScheduleOverlays(); // Copies the contents of the render pass draw quad, including filter effects, @@ -311,6 +315,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer { TextureMailboxDeleter* texture_mailbox_deleter_; gfx::Rect swap_buffer_rect_; + std::vector<gfx::Rect> swap_content_bounds_; gfx::Rect scissor_rect_; bool is_scissor_enabled_ = false; bool stencil_shadow_ = false; diff --git a/chromium/cc/output/gl_renderer_unittest.cc b/chromium/cc/output/gl_renderer_unittest.cc index 59d711d165e..ff42c7e6d07 100644 --- a/chromium/cc/output/gl_renderer_unittest.cc +++ b/chromium/cc/output/gl_renderer_unittest.cc @@ -11,6 +11,7 @@ #include "base/location.h" #include "base/memory/ptr_util.h" +#include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/base/math_util.h" #include "cc/output/copy_output_request.h" @@ -38,8 +39,8 @@ #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/effects/SkColorFilterImageFilter.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" -#include "ui/events/latency_info.h" #include "ui/gfx/transform.h" +#include "ui/latency/latency_info.h" using testing::_; using testing::AnyNumber; @@ -138,7 +139,7 @@ class GLRendererShaderPixelTest : public GLRendererPixelTest { const size_t kNumSrcColorSpaces = 4; gfx::ColorSpace src_color_spaces[kNumSrcColorSpaces] = { gfx::ColorSpace(), gfx::ColorSpace::CreateSRGB(), - gfx::ColorSpace::CreateREC709(), + gfx::ColorSpace::CreateREC709(), gfx::ColorSpace::CreateExtendedSRGB(), }; const size_t kNumDstColorSpaces = 3; gfx::ColorSpace dst_color_spaces[kNumDstColorSpaces] = { @@ -1178,12 +1179,104 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) { } } -class FlippedScissorAndViewportGLES2Interface : public TestGLES2Interface { +class DrawElementsGLES2Interface : public TestGLES2Interface { public: - MOCK_METHOD4(Viewport, void(GLint x, GLint y, GLsizei width, GLsizei height)); - MOCK_METHOD4(Scissor, void(GLint x, GLint y, GLsizei width, GLsizei height)); + void InitializeTestContext(TestWebGraphicsContext3D* context) override { + context->set_have_post_sub_buffer(true); + } + + MOCK_METHOD4( + DrawElements, + void(GLenum mode, GLsizei count, GLenum type, const void* indices)); }; +class GLRendererSkipTest : public GLRendererTest { + protected: + GLRendererSkipTest() { + auto gl_owned = base::MakeUnique<StrictMock<DrawElementsGLES2Interface>>(); + gl_ = gl_owned.get(); + + auto provider = TestContextProvider::Create(std::move(gl_owned)); + provider->BindToCurrentThread(); + + output_surface_ = FakeOutputSurface::Create3d(std::move(provider)); + output_surface_->BindToClient(&output_surface_client_); + + shared_bitmap_manager_.reset(new TestSharedBitmapManager()); + resource_provider_ = FakeResourceProvider::Create( + output_surface_->context_provider(), shared_bitmap_manager_.get()); + settings_.partial_swap_enabled = true; + renderer_ = base::MakeUnique<FakeRendererGL>( + &settings_, output_surface_.get(), resource_provider_.get()); + renderer_->Initialize(); + renderer_->SetVisible(true); + } + + StrictMock<DrawElementsGLES2Interface>* gl_; + RendererSettings settings_; + FakeOutputSurfaceClient output_surface_client_; + std::unique_ptr<FakeOutputSurface> output_surface_; + std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_; + std::unique_ptr<ResourceProvider> resource_provider_; + std::unique_ptr<FakeRendererGL> renderer_; +}; + +TEST_F(GLRendererSkipTest, DrawQuad) { + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1); + + gfx::Size viewport_size(100, 100); + gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20); + + int root_pass_id = 1; + RenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, + root_pass_id, gfx::Rect(viewport_size), + gfx::Transform(), FilterOperations()); + root_pass->damage_rect = gfx::Rect(0, 0, 25, 25); + AddQuad(root_pass, quad_rect, SK_ColorGREEN); + + renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); + DrawFrame(renderer_.get(), viewport_size); +} + +TEST_F(GLRendererSkipTest, SkipVisibleRect) { + gfx::Size viewport_size(100, 100); + gfx::Rect quad_rect = gfx::Rect(0, 0, 40, 40); + + int root_pass_id = 1; + RenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, + root_pass_id, gfx::Rect(viewport_size), + gfx::Transform(), FilterOperations()); + root_pass->damage_rect = gfx::Rect(0, 0, 10, 10); + AddQuad(root_pass, quad_rect, SK_ColorGREEN); + root_pass->shared_quad_state_list.front()->is_clipped = true; + root_pass->shared_quad_state_list.front()->clip_rect = + gfx::Rect(0, 0, 40, 40); + root_pass->quad_list.front()->visible_rect = gfx::Rect(20, 20, 20, 20); + + renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); + DrawFrame(renderer_.get(), viewport_size); + // DrawElements should not be called because the visible rect is outside the + // scissor, even though the clip rect and quad rect intersect the scissor. +} + +TEST_F(GLRendererSkipTest, SkipClippedQuads) { + gfx::Size viewport_size(100, 100); + gfx::Rect quad_rect = gfx::Rect(25, 25, 90, 90); + + int root_pass_id = 1; + RenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, + root_pass_id, gfx::Rect(viewport_size), + gfx::Transform(), FilterOperations()); + root_pass->damage_rect = gfx::Rect(0, 0, 25, 25); + AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN); + root_pass->quad_list.front()->rect = gfx::Rect(20, 20, 20, 20); + + renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); + DrawFrame(renderer_.get(), viewport_size); + // DrawElements should not be called because the clip rect is outside the + // scissor. +} + TEST_F(GLRendererTest, DrawFramePreservesFramebuffer) { // When using render-to-FBO to display the surface, all rendering is done // to a non-zero FBO. Make sure that the framebuffer is always restored to @@ -1480,7 +1573,8 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) { } TEST_F(GLRendererShaderTest, DrawSolidColorShader) { - gfx::Size viewport_size(1, 1); + gfx::Size viewport_size(30, 30); // Don't translate out of the viewport. + gfx::Size quad_size(3, 3); int root_pass_id = 1; RenderPass* root_pass; @@ -1491,7 +1585,7 @@ TEST_F(GLRendererShaderTest, DrawSolidColorShader) { root_pass = AddRenderPass(&render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size), gfx::Transform(), FilterOperations()); - AddTransformedQuad(root_pass, gfx::Rect(viewport_size), SK_ColorYELLOW, + AddTransformedQuad(root_pass, gfx::Rect(quad_size), SK_ColorYELLOW, pixel_aligned_transform_causing_aa); renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); @@ -1640,6 +1734,7 @@ class TestOverlayProcessor : public OverlayProcessor { // Returns true if draw quads can be represented as CALayers (Mac only). MOCK_METHOD0(AllowCALayerOverlays, bool()); + MOCK_METHOD0(AllowDCLayerOverlays, bool()); // A list of possible overlay candidates is presented to this function. // The expected result is that those candidates that can be in a separate @@ -1730,6 +1825,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) { // list because the render pass is cleaned up by DrawFrame. EXPECT_CALL(*processor->strategy_, Attempt(_, _, _, _)).Times(0); EXPECT_CALL(*validator, AllowCALayerOverlays()).Times(0); + EXPECT_CALL(*validator, AllowDCLayerOverlays()).Times(0); DrawFrame(&renderer, viewport_size); Mock::VerifyAndClearExpectations(processor->strategy_); Mock::VerifyAndClearExpectations(validator.get()); @@ -1749,6 +1845,9 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) { EXPECT_CALL(*validator, AllowCALayerOverlays()) .Times(1) .WillOnce(::testing::Return(false)); + EXPECT_CALL(*validator, AllowDCLayerOverlays()) + .Times(1) + .WillOnce(::testing::Return(false)); EXPECT_CALL(*processor->strategy_, Attempt(_, _, _, _)).Times(1); DrawFrame(&renderer, viewport_size); @@ -1782,6 +1881,7 @@ class SingleOverlayOnTopProcessor : public OverlayProcessor { } bool AllowCALayerOverlays() override { return false; } + bool AllowDCLayerOverlays() override { return false; } void CheckOverlaySupport(OverlayCandidateList* surfaces) override { ASSERT_EQ(1U, surfaces->size()); @@ -1900,20 +2000,21 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) { class PartialSwapMockGLES2Interface : public TestGLES2Interface { public: - explicit PartialSwapMockGLES2Interface(bool support_set_draw_rectangle) - : support_set_draw_rectangle_(support_set_draw_rectangle) {} + explicit PartialSwapMockGLES2Interface(bool support_dc_layers) + : support_dc_layers_(support_dc_layers) {} void InitializeTestContext(TestWebGraphicsContext3D* context) override { context->set_have_post_sub_buffer(true); - context->set_support_set_draw_rectangle(support_set_draw_rectangle_); + context->set_enable_dc_layers(support_dc_layers_); } MOCK_METHOD1(Enable, void(GLenum cap)); MOCK_METHOD1(Disable, void(GLenum cap)); MOCK_METHOD4(Scissor, void(GLint x, GLint y, GLsizei width, GLsizei height)); + MOCK_METHOD1(SetEnableDCLayersCHROMIUM, void(GLboolean enable)); private: - bool support_set_draw_rectangle_; + bool support_dc_layers_; }; class GLRendererPartialSwapTest : public GLRendererTest { @@ -1945,7 +2046,7 @@ class GLRendererPartialSwapTest : public GLRendererTest { gfx::Size viewport_size(100, 100); - { + for (int i = 0; i < 2; ++i) { int root_pass_id = 1; RenderPass* root_pass = AddRenderPass( &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size), @@ -1964,8 +2065,13 @@ class GLRendererPartialSwapTest : public GLRendererTest { // Partial frame, we should use a scissor to swap only that part when // partial swap is enabled. root_pass->damage_rect = gfx::Rect(2, 2, 3, 3); - gfx::Rect output_rectangle = - partial_swap ? root_pass->damage_rect : gfx::Rect(viewport_size); + // With SetDrawRectangle the first frame will have its damage expanded + // to cover the entire output rect. + bool frame_has_partial_damage = + partial_swap && (!set_draw_rectangle || (i > 0)); + gfx::Rect output_rectangle = frame_has_partial_damage + ? root_pass->damage_rect + : gfx::Rect(viewport_size); if (partial_swap || set_draw_rectangle) { EXPECT_CALL(*gl, Enable(GL_SCISSOR_TEST)).InSequence(seq); @@ -1992,6 +2098,7 @@ class GLRendererPartialSwapTest : public GLRendererTest { if (set_draw_rectangle) { EXPECT_EQ(output_rectangle, output_surface->last_set_draw_rectangle()); } + Mock::VerifyAndClearExpectations(gl); } } }; @@ -2012,6 +2119,105 @@ TEST_F(GLRendererPartialSwapTest, SetDrawRectangle_NoPartialSwap) { RunTest(false, true); } +class DCLayerValidator : public OverlayCandidateValidator { + public: + void GetStrategies(OverlayProcessor::StrategyList* strategies) override {} + bool AllowCALayerOverlays() override { return false; } + bool AllowDCLayerOverlays() override { return true; } + void CheckOverlaySupport(OverlayCandidateList* surfaces) override {} +}; + +// Test that SetEnableDCLayersCHROMIUM is properly called when enabling +// and disabling DC layers. +TEST_F(GLRendererTest, DCLayerOverlaySwitch) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kDirectCompositionUnderlays); + auto gl_owned = base::MakeUnique<PartialSwapMockGLES2Interface>(true); + auto* gl = gl_owned.get(); + + auto provider = TestContextProvider::Create(std::move(gl_owned)); + provider->BindToCurrentThread(); + + FakeOutputSurfaceClient output_surface_client; + std::unique_ptr<FakeOutputSurface> output_surface( + FakeOutputSurface::Create3d(std::move(provider))); + output_surface->BindToClient(&output_surface_client); + + std::unique_ptr<ResourceProvider> resource_provider = + FakeResourceProvider::Create(output_surface->context_provider(), nullptr); + + RendererSettings settings; + settings.partial_swap_enabled = true; + FakeRendererGL renderer(&settings, output_surface.get(), + resource_provider.get()); + renderer.Initialize(); + renderer.SetVisible(true); + TestOverlayProcessor* processor = + new TestOverlayProcessor(output_surface.get()); + processor->Initialize(); + renderer.SetOverlayProcessor(processor); + std::unique_ptr<DCLayerValidator> validator(new DCLayerValidator); + output_surface->SetOverlayCandidateValidator(validator.get()); + + gfx::Size viewport_size(100, 100); + + TextureMailbox mailbox = + TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), GL_TEXTURE_2D, + gfx::Size(256, 256), true, false); + std::unique_ptr<SingleReleaseCallbackImpl> release_callback = + SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); + ResourceId resource_id = resource_provider->CreateResourceFromTextureMailbox( + mailbox, std::move(release_callback)); + + for (int i = 0; i < 65; i++) { + int root_pass_id = 1; + RenderPass* root_pass = AddRenderPass( + &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size), + gfx::Transform(), FilterOperations()); + if (i == 0) { + gfx::Rect rect(0, 0, 100, 100); + gfx::RectF tex_coord_rect(0, 0, 1, 1); + SharedQuadState* shared_state = + root_pass->CreateAndAppendSharedQuadState(); + shared_state->SetAll(gfx::Transform(), rect.size(), rect, rect, false, 1, + SkBlendMode::kSrcOver, 0); + YUVVideoDrawQuad* quad = + root_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>(); + quad->SetNew(shared_state, rect, rect, rect, tex_coord_rect, + tex_coord_rect, rect.size(), rect.size(), resource_id, + resource_id, resource_id, resource_id, + YUVVideoDrawQuad::REC_601, gfx::ColorSpace(), 0, 1.0, 8); + } + + // A bunch of initialization that happens. + EXPECT_CALL(*gl, Disable(_)).Times(AnyNumber()); + EXPECT_CALL(*gl, Enable(_)).Times(AnyNumber()); + EXPECT_CALL(*gl, Scissor(_, _, _, _)).Times(AnyNumber()); + + // Partial frame, we should use a scissor to swap only that part when + // partial swap is enabled. + root_pass->damage_rect = gfx::Rect(2, 2, 3, 3); + // Frame 0 should be completely damaged because it's the first. + // Frame 1 should be because it changed. Frame 60 should be + // because it's disabling DC layers. + gfx::Rect output_rectangle = (i == 0 || i == 1 || i == 60) + ? root_pass->output_rect + : root_pass->damage_rect; + + // Frame 0 should have DC Layers enabled because of the overlay. + // After 60 frames of no overlays DC layers should be disabled again. + if (i < 60) + EXPECT_CALL(*gl, SetEnableDCLayersCHROMIUM(GL_TRUE)); + else + EXPECT_CALL(*gl, SetEnableDCLayersCHROMIUM(GL_FALSE)); + + renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); + DrawFrame(&renderer, viewport_size); + EXPECT_EQ(output_rectangle, output_surface->last_set_draw_rectangle()); + testing::Mock::VerifyAndClearExpectations(gl); + } +} + class GLRendererWithMockContextTest : public ::testing::Test { protected: class MockContextSupport : public TestContextSupport { @@ -2056,5 +2262,105 @@ TEST_F(GLRendererWithMockContextTest, Mock::VerifyAndClearExpectations(context_support_ptr_); } +class SwapWithBoundsMockGLES2Interface : public TestGLES2Interface { + public: + void InitializeTestContext(TestWebGraphicsContext3D* context) override { + context->set_have_swap_buffers_with_bounds(true); + } +}; + +class ContentBoundsOverlayProcessor : public OverlayProcessor { + public: + class Strategy : public OverlayProcessor::Strategy { + public: + explicit Strategy(const std::vector<gfx::Rect>& content_bounds) + : content_bounds_(content_bounds) {} + ~Strategy() override {} + bool Attempt(ResourceProvider* resource_provider, + RenderPass* render_pass, + OverlayCandidateList* candidates, + std::vector<gfx::Rect>* content_bounds) override { + content_bounds->insert(content_bounds->end(), content_bounds_.begin(), + content_bounds_.end()); + return true; + } + + const std::vector<gfx::Rect> content_bounds_; + }; + + ContentBoundsOverlayProcessor(OutputSurface* surface, + const std::vector<gfx::Rect>& content_bounds) + : OverlayProcessor(surface), content_bounds_(content_bounds) {} + + void Initialize() override { + strategy_ = new Strategy(content_bounds_); + strategies_.push_back(base::WrapUnique(strategy_)); + } + + Strategy* strategy_; + const std::vector<gfx::Rect> content_bounds_; +}; + +class GLRendererSwapWithBoundsTest : public GLRendererTest { + protected: + void RunTest(const std::vector<gfx::Rect>& content_bounds) { + auto gl_owned = base::MakeUnique<SwapWithBoundsMockGLES2Interface>(); + + auto provider = TestContextProvider::Create(std::move(gl_owned)); + provider->BindToCurrentThread(); + + FakeOutputSurfaceClient output_surface_client; + std::unique_ptr<FakeOutputSurface> output_surface( + FakeOutputSurface::Create3d(std::move(provider))); + output_surface->BindToClient(&output_surface_client); + + std::unique_ptr<ResourceProvider> resource_provider = + FakeResourceProvider::Create(output_surface->context_provider(), + nullptr); + + RendererSettings settings; + FakeRendererGL renderer(&settings, output_surface.get(), + resource_provider.get()); + renderer.Initialize(); + EXPECT_EQ(true, renderer.use_swap_with_bounds()); + renderer.SetVisible(true); + + OverlayProcessor* processor = + new ContentBoundsOverlayProcessor(output_surface.get(), content_bounds); + processor->Initialize(); + renderer.SetOverlayProcessor(processor); + + gfx::Size viewport_size(100, 100); + + { + int root_pass_id = 1; + AddRenderPass(&render_passes_in_draw_order_, root_pass_id, + gfx::Rect(viewport_size), gfx::Transform(), + FilterOperations()); + + renderer.DecideRenderPassAllocationsForFrame( + render_passes_in_draw_order_); + DrawFrame(&renderer, viewport_size); + renderer.SwapBuffers(std::vector<ui::LatencyInfo>()); + + std::vector<gfx::Rect> expected_content_bounds; + EXPECT_EQ(content_bounds, + output_surface->last_sent_frame()->content_bounds); + } + } +}; + +TEST_F(GLRendererSwapWithBoundsTest, EmptyContent) { + std::vector<gfx::Rect> content_bounds; + RunTest(content_bounds); +} + +TEST_F(GLRendererSwapWithBoundsTest, NonEmpty) { + std::vector<gfx::Rect> content_bounds; + content_bounds.push_back(gfx::Rect(0, 0, 10, 10)); + content_bounds.push_back(gfx::Rect(20, 20, 30, 30)); + RunTest(content_bounds); +} + } // namespace } // namespace cc diff --git a/chromium/cc/output/in_process_context_provider.cc b/chromium/cc/output/in_process_context_provider.cc index 9fd6d182417..79e7adf9fe2 100644 --- a/chromium/cc/output/in_process_context_provider.cc +++ b/chromium/cc/output/in_process_context_provider.cc @@ -103,7 +103,8 @@ class GrContext* InProcessContextProvider::GrContext() { if (gr_context_) return gr_context_->get(); - gr_context_.reset(new skia_bindings::GrContextForGLES2Interface(ContextGL())); + gr_context_.reset(new skia_bindings::GrContextForGLES2Interface( + ContextGL(), ContextCapabilities())); return gr_context_->get(); } diff --git a/chromium/cc/output/in_process_context_provider.h b/chromium/cc/output/in_process_context_provider.h index d85f194655a..0a355d28de1 100644 --- a/chromium/cc/output/in_process_context_provider.h +++ b/chromium/cc/output/in_process_context_provider.h @@ -11,7 +11,7 @@ #include "base/compiler_specific.h" #include "base/synchronization/lock.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/context_cache_controller.h" #include "cc/output/context_provider.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" diff --git a/chromium/cc/output/latency_info_swap_promise.h b/chromium/cc/output/latency_info_swap_promise.h index 1db4d9ac1b0..91abe7d687d 100644 --- a/chromium/cc/output/latency_info_swap_promise.h +++ b/chromium/cc/output/latency_info_swap_promise.h @@ -9,7 +9,7 @@ #include "base/compiler_specific.h" #include "cc/output/swap_promise.h" -#include "ui/events/latency_info.h" +#include "ui/latency/latency_info.h" namespace cc { diff --git a/chromium/cc/output/layer_quad.h b/chromium/cc/output/layer_quad.h index 22b9357f482..8b109883d32 100644 --- a/chromium/cc/output/layer_quad.h +++ b/chromium/cc/output/layer_quad.h @@ -7,7 +7,7 @@ #define CC_OUTPUT_LAYER_QUAD_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/point_f.h" namespace gfx { diff --git a/chromium/cc/output/managed_memory_policy.h b/chromium/cc/output/managed_memory_policy.h index 953e6ec1da8..886bebdfac2 100644 --- a/chromium/cc/output/managed_memory_policy.h +++ b/chromium/cc/output/managed_memory_policy.h @@ -7,7 +7,7 @@ #include <stddef.h> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/tiles/tile_priority.h" #include "gpu/command_buffer/common/gpu_memory_allocation.h" diff --git a/chromium/cc/output/output_surface.h b/chromium/cc/output/output_surface.h index 32179f23188..d1715cbcdff 100644 --- a/chromium/cc/output/output_surface.h +++ b/chromium/cc/output/output_surface.h @@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/threading/thread_checker.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/context_provider.h" #include "cc/output/overlay_candidate_validator.h" #include "cc/output/software_output_device.h" @@ -84,8 +84,8 @@ class CC_EXPORT OutputSurface { virtual void BindFramebuffer() = 0; // Marks that the given rectangle will be drawn to on the default, bound - // framebuffer. Only valid for surfaces with set_draw_rectangle in the - // context capabilities. + // framebuffer. Only valid for surfaces with dc_layers in the context + // capabilities. virtual void SetDrawRectangle(const gfx::Rect& rect) = 0; // Get the class capable of informing cc of hardware overlay capability. diff --git a/chromium/cc/output/output_surface_client.h b/chromium/cc/output/output_surface_client.h index 7f8cadef43b..c3f3df4497a 100644 --- a/chromium/cc/output/output_surface_client.h +++ b/chromium/cc/output/output_surface_client.h @@ -8,7 +8,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/context_provider.h" #include "cc/resources/returned_resource.h" #include "gpu/command_buffer/common/texture_in_use_response.h" diff --git a/chromium/cc/output/output_surface_frame.h b/chromium/cc/output/output_surface_frame.h index 3133e8e260d..fd01648a114 100644 --- a/chromium/cc/output/output_surface_frame.h +++ b/chromium/cc/output/output_surface_frame.h @@ -9,10 +9,10 @@ #include "base/macros.h" #include "base/optional.h" -#include "cc/base/cc_export.h" -#include "ui/events/latency_info.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" +#include "ui/latency/latency_info.h" namespace cc { diff --git a/chromium/cc/output/overlay_candidate.cc b/chromium/cc/output/overlay_candidate.cc index 64ee2a57668..9b7babec12c 100644 --- a/chromium/cc/output/overlay_candidate.cc +++ b/chromium/cc/output/overlay_candidate.cc @@ -22,6 +22,11 @@ namespace { // Tolerance for considering axis vector elements to be zero. const SkMScalar kEpsilon = std::numeric_limits<float>::epsilon(); +const gfx::BufferFormat kOverlayFormats[] = { + gfx::BufferFormat::RGBX_8888, gfx::BufferFormat::RGBA_8888, + gfx::BufferFormat::BGRX_8888, gfx::BufferFormat::BGRA_8888, + gfx::BufferFormat::BGR_565, gfx::BufferFormat::YUV_420_BIPLANAR}; + enum Axis { NONE, AXIS_POS_X, AXIS_NEG_X, AXIS_POS_Y, AXIS_NEG_Y }; Axis VectorToAxis(const gfx::Vector3dF& vec) { @@ -168,9 +173,10 @@ gfx::OverlayTransform ComposeTransforms(gfx::OverlayTransform delta, OverlayCandidate::OverlayCandidate() : transform(gfx::OVERLAY_TRANSFORM_NONE), - format(RGBA_8888), + format(gfx::BufferFormat::RGBA_8888), uv_rect(0.f, 0.f, 1.f, 1.f), is_clipped(false), + is_opaque(false), use_output_surface_for_resource(false), resource_id(0), #if defined(OS_ANDROID) @@ -190,9 +196,12 @@ OverlayCandidate::~OverlayCandidate() {} bool OverlayCandidate::FromDrawQuad(ResourceProvider* resource_provider, const DrawQuad* quad, OverlayCandidate* candidate) { - if (quad->ShouldDrawWithBlending() || - quad->shared_quad_state->opacity != 1.f || - quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver) + // We don't support an opacity value different than one for an overlay plane. + if (quad->shared_quad_state->opacity != 1.f) + return false; + // We support only kSrc (no blending) and kSrcOver (blending with premul). + if (!(quad->shared_quad_state->blend_mode == SkBlendMode::kSrc || + quad->shared_quad_state->blend_mode == SkBlendMode::kSrcOver)) return false; auto& transform = quad->shared_quad_state->quad_to_target_transform; @@ -201,9 +210,9 @@ bool OverlayCandidate::FromDrawQuad(ResourceProvider* resource_provider, candidate->quad_rect_in_target_space = MathUtil::MapEnclosingClippedRect(transform, quad->rect); - candidate->format = RGBA_8888; candidate->clip_rect = quad->shared_quad_state->clip_rect; candidate->is_clipped = quad->shared_quad_state->is_clipped; + candidate->is_opaque = !quad->ShouldDrawWithBlending(); switch (quad->material) { case DrawQuad::TEXTURE_CONTENT: @@ -257,6 +266,10 @@ bool OverlayCandidate::FromTextureQuad(ResourceProvider* resource_provider, OverlayCandidate* candidate) { if (!resource_provider->IsOverlayCandidate(quad->resource_id())) return false; + candidate->format = resource_provider->GetBufferFormat(quad->resource_id()); + if (std::find(std::begin(kOverlayFormats), std::end(kOverlayFormats), + candidate->format) == std::end(kOverlayFormats)) + return false; gfx::OverlayTransform overlay_transform = GetOverlayTransform( quad->shared_quad_state->quad_to_target_transform, quad->y_flipped); if (quad->background_color != SK_ColorTRANSPARENT || diff --git a/chromium/cc/output/overlay_candidate.h b/chromium/cc/output/overlay_candidate.h index e35299ded49..8c5d6e26b79 100644 --- a/chromium/cc/output/overlay_candidate.h +++ b/chromium/cc/output/overlay_candidate.h @@ -8,10 +8,10 @@ #include <map> #include <vector> -#include "cc/base/cc_export.h" #include "cc/base/resource_id.h" +#include "cc/cc_export.h" #include "cc/quads/render_pass.h" -#include "cc/resources/resource_format.h" +#include "ui/gfx/buffer_types.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size.h" @@ -52,8 +52,8 @@ class CC_EXPORT OverlayCandidate { // Transformation to apply to layer during composition. gfx::OverlayTransform transform; - // Format of the buffer to composite. - ResourceFormat format; + // Format of the buffer to scanout. + gfx::BufferFormat 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 @@ -67,6 +67,8 @@ class CC_EXPORT OverlayCandidate { gfx::Rect clip_rect; // If the quad is clipped after composition. bool is_clipped; + // If the quad doesn't require blending. + bool is_opaque; // True if the texture for this overlay should be the same one used by the // output surface's main overlay. bool use_output_surface_for_resource; diff --git a/chromium/cc/output/overlay_candidate_validator.h b/chromium/cc/output/overlay_candidate_validator.h index 09d380b82a9..9c01486d284 100644 --- a/chromium/cc/output/overlay_candidate_validator.h +++ b/chromium/cc/output/overlay_candidate_validator.h @@ -7,7 +7,7 @@ #include <vector> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/overlay_candidate.h" #include "cc/output/overlay_processor.h" @@ -23,6 +23,10 @@ class CC_EXPORT OverlayCandidateValidator { // Returns true if draw quads can be represented as CALayers (Mac only). virtual bool AllowCALayerOverlays() = 0; + // Returns true if draw quads can be represented as Direct Composition + // Visuals (Windows only). + virtual bool AllowDCLayerOverlays() = 0; + // A list of possible overlay candidates is presented to this function. // The expected result is that those candidates that can be in a separate // plane are marked with |overlay_handled| set to true, otherwise they are diff --git a/chromium/cc/output/overlay_processor.cc b/chromium/cc/output/overlay_processor.cc index 47358e3b81e..594111bd786 100644 --- a/chromium/cc/output/overlay_processor.cc +++ b/chromium/cc/output/overlay_processor.cc @@ -4,6 +4,7 @@ #include "cc/output/overlay_processor.h" +#include "cc/output/dc_layer_overlay.h" #include "cc/output/output_surface.h" #include "cc/output/overlay_strategy_single_on_top.h" #include "cc/output/overlay_strategy_underlay.h" @@ -86,6 +87,27 @@ bool OverlayProcessor::ProcessForCALayers( return true; } +bool OverlayProcessor::ProcessForDCLayers( + ResourceProvider* resource_provider, + RenderPass* render_pass, + const RenderPassFilterList& render_pass_filters, + const RenderPassFilterList& render_pass_background_filters, + OverlayCandidateList* overlay_candidates, + DCLayerOverlayList* dc_layer_overlays, + gfx::Rect* damage_rect) { + OverlayCandidateValidator* overlay_validator = + surface_->GetOverlayCandidateValidator(); + if (!overlay_validator || !overlay_validator->AllowDCLayerOverlays()) + return false; + + dc_processor_.Process(resource_provider, gfx::RectF(render_pass->output_rect), + &render_pass->quad_list, &overlay_damage_rect_, + damage_rect, dc_layer_overlays); + + DCHECK(overlay_candidates->empty()); + return true; +} + void OverlayProcessor::ProcessForOverlays( ResourceProvider* resource_provider, RenderPass* render_pass, @@ -93,6 +115,7 @@ void OverlayProcessor::ProcessForOverlays( const RenderPassFilterList& render_pass_background_filters, OverlayCandidateList* candidates, CALayerOverlayList* ca_layer_overlays, + DCLayerOverlayList* dc_layer_overlays, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) { #if defined(OS_ANDROID) @@ -106,6 +129,7 @@ void OverlayProcessor::ProcessForOverlays( // CALayers because the framebuffer would be missing the removed quads' // contents. if (!render_pass->copy_requests.empty()) { + dc_processor_.ClearOverlayState(); // If overlay processing was skipped for a frame there's no way to be sure // of the state of the previous frame, so reset. previous_frame_underlay_rect_ = gfx::Rect(); @@ -119,6 +143,12 @@ void OverlayProcessor::ProcessForOverlays( return; } + if (ProcessForDCLayers(resource_provider, render_pass, render_pass_filters, + render_pass_background_filters, candidates, + dc_layer_overlays, damage_rect)) { + return; + } + // Only if that fails, attempt hardware overlay strategies. for (const auto& strategy : strategies_) { if (!strategy->Attempt(resource_provider, render_pass, candidates, @@ -130,7 +160,7 @@ void OverlayProcessor::ProcessForOverlays( } } -// Subtract on-top overlays from the damage rect, unless the overlays use +// Subtract on-top opaque overlays from the damage rect, unless the overlays use // the backbuffer as their content (in which case, add their combined rect // back to the damage at the end). // Also subtract unoccluded underlays from the damage rect if we know that the @@ -143,7 +173,7 @@ void OverlayProcessor::UpdateDamageRect(OverlayCandidateList* candidates, gfx::Rect output_surface_overlay_damage_rect; gfx::Rect this_frame_underlay_rect; for (const OverlayCandidate& overlay : *candidates) { - if (overlay.plane_z_order > 0) { + if (overlay.plane_z_order > 0 && overlay.is_opaque) { const gfx::Rect overlay_display_rect = ToEnclosedRect(overlay.display_rect); overlay_damage_rect_.Union(overlay_display_rect); diff --git a/chromium/cc/output/overlay_processor.h b/chromium/cc/output/overlay_processor.h index 99190da20ef..a00574e45c1 100644 --- a/chromium/cc/output/overlay_processor.h +++ b/chromium/cc/output/overlay_processor.h @@ -8,8 +8,9 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/ca_layer_overlay.h" +#include "cc/output/dc_layer_overlay.h" #include "cc/output/overlay_candidate.h" #include "cc/quads/render_pass.h" @@ -49,6 +50,7 @@ class CC_EXPORT OverlayProcessor { const RenderPassFilterList& render_pass_background_filters, OverlayCandidateList* overlay_candidates, CALayerOverlayList* ca_layer_overlays, + DCLayerOverlayList* dc_layer_overlays, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds); @@ -67,10 +69,20 @@ class CC_EXPORT OverlayProcessor { OverlayCandidateList* overlay_candidates, CALayerOverlayList* ca_layer_overlays, gfx::Rect* damage_rect); + bool ProcessForDCLayers( + ResourceProvider* resource_provider, + RenderPass* render_pass, + const RenderPassFilterList& render_pass_filters, + const RenderPassFilterList& render_pass_background_filters, + OverlayCandidateList* overlay_candidates, + DCLayerOverlayList* dc_layer_overlays, + gfx::Rect* damage_rect); // Update |damage_rect| by removing damage casued by |candidates|. void UpdateDamageRect(OverlayCandidateList* candidates, gfx::Rect* damage_rect); + DCLayerOverlayProcessor dc_processor_; + DISALLOW_COPY_AND_ASSIGN(OverlayProcessor); }; diff --git a/chromium/cc/output/overlay_strategy_fullscreen.cc b/chromium/cc/output/overlay_strategy_fullscreen.cc index 681611fa5f2..2dd3e474268 100644 --- a/chromium/cc/output/overlay_strategy_fullscreen.cc +++ b/chromium/cc/output/overlay_strategy_fullscreen.cc @@ -38,8 +38,12 @@ bool OverlayStrategyFullscreen::Attempt( if (front == quad_list->end()) return false; + const DrawQuad* quad = *front; + if (quad->ShouldDrawWithBlending()) + return false; + OverlayCandidate candidate; - if (!OverlayCandidate::FromDrawQuad(resource_provider, *front, &candidate)) { + if (!OverlayCandidate::FromDrawQuad(resource_provider, quad, &candidate)) { return false; } diff --git a/chromium/cc/output/overlay_strategy_single_on_top.cc b/chromium/cc/output/overlay_strategy_single_on_top.cc index 8ce4c6a38ab..0cc5d998564 100644 --- a/chromium/cc/output/overlay_strategy_single_on_top.cc +++ b/chromium/cc/output/overlay_strategy_single_on_top.cc @@ -7,9 +7,15 @@ #include "cc/base/math_util.h" #include "cc/output/overlay_candidate_validator.h" #include "cc/quads/draw_quad.h" +#include "ui/gfx/buffer_types.h" #include "ui/gfx/geometry/rect_conversions.h" namespace cc { +namespace { + +const gfx::BufferFormat kOverlayFormatsWithAlpha[] = { + gfx::BufferFormat::RGBA_8888, gfx::BufferFormat::BGRA_8888}; +} OverlayStrategySingleOnTop::OverlayStrategySingleOnTop( OverlayCandidateValidator* capability_checker) @@ -25,13 +31,38 @@ bool OverlayStrategySingleOnTop::Attempt( OverlayCandidateList* candidate_list, std::vector<gfx::Rect>* content_bounds) { QuadList* quad_list = &render_pass->quad_list; + // Build a list of candidates with the associated quad. + OverlayCandidate best_candidate; + QuadList::Iterator best_quad_it = quad_list->end(); for (auto it = quad_list->begin(); it != quad_list->end(); ++it) { OverlayCandidate candidate; if (OverlayCandidate::FromDrawQuad(resource_provider, *it, &candidate) && - TryOverlay(quad_list, candidate_list, candidate, it)) { - return true; + // TODO(dcastagna): Remove this once drm platform supports transforms. + candidate.transform == gfx::OVERLAY_TRANSFORM_NONE && + !OverlayCandidate::IsOccluded(candidate, quad_list->cbegin(), it)) { + // We currently reject quads with alpha that do not request alpha blending + // since the alpha channel might not be set to 1 and we're not disabling + // blending when scanning out. + // TODO(dcastagna): We should support alpha formats without blending using + // the opaque FB at scanout. + if (std::find(std::begin(kOverlayFormatsWithAlpha), + std::end(kOverlayFormatsWithAlpha), + candidate.format) != std::end(kOverlayFormatsWithAlpha) && + it->shared_quad_state->blend_mode == SkBlendMode::kSrc) + continue; + + if (candidate.display_rect.size().GetArea() > + best_candidate.display_rect.size().GetArea()) { + best_candidate = candidate; + best_quad_it = it; + } } } + if (best_quad_it == quad_list->end()) + return false; + + if (TryOverlay(quad_list, candidate_list, best_candidate, best_quad_it)) + return true; return false; } @@ -41,15 +72,6 @@ bool OverlayStrategySingleOnTop::TryOverlay( OverlayCandidateList* candidate_list, const OverlayCandidate& candidate, QuadList::Iterator candidate_iterator) { - // Reject transformed overlays. - // TODO(dcastagna): Remove this once drm platform supports transforms. - if (candidate.transform != gfx::OVERLAY_TRANSFORM_NONE) - return false; - // Check that no prior quads overlap it. - if (OverlayCandidate::IsOccluded(candidate, quad_list->cbegin(), - candidate_iterator)) - return false; - // Add the overlay. OverlayCandidateList new_candidate_list = *candidate_list; new_candidate_list.push_back(candidate); diff --git a/chromium/cc/output/overlay_unittest.cc b/chromium/cc/output/overlay_unittest.cc index aa4102d0ceb..9c077e90564 100644 --- a/chromium/cc/output/overlay_unittest.cc +++ b/chromium/cc/output/overlay_unittest.cc @@ -8,9 +8,10 @@ #include <vector> #include "base/memory/ptr_util.h" +#include "base/test/scoped_feature_list.h" +#include "cc/base/filter_operation.h" #include "cc/base/region.h" #include "cc/output/ca_layer_overlay.h" -#include "cc/output/filter_operation.h" #include "cc/output/gl_renderer.h" #include "cc/output/output_surface.h" #include "cc/output/output_surface_client.h" @@ -36,8 +37,9 @@ #include "cc/test/test_web_graphics_context_3d.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/latency_info.h" #include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gl/gl_switches.h" +#include "ui/latency/latency_info.h" using testing::_; using testing::Mock; @@ -73,18 +75,21 @@ class FullscreenOverlayValidator : public OverlayCandidateValidator { strategies->push_back(base::MakeUnique<OverlayStrategyFullscreen>(this)); } bool AllowCALayerOverlays() override { return false; } + bool AllowDCLayerOverlays() override { return false; } void CheckOverlaySupport(OverlayCandidateList* surfaces) override {} }; class SingleOverlayValidator : public OverlayCandidateValidator { public: - SingleOverlayValidator() : expected_rect_(kOverlayRect) {} + SingleOverlayValidator() : expected_rects_(1, gfx::RectF(kOverlayRect)) {} void GetStrategies(OverlayProcessor::StrategyList* strategies) override { strategies->push_back(base::MakeUnique<OverlayStrategySingleOnTop>(this)); strategies->push_back(base::MakeUnique<OverlayStrategyUnderlay>(this)); } + bool AllowCALayerOverlays() override { return false; } + bool AllowDCLayerOverlays() override { return false; } void CheckOverlaySupport(OverlayCandidateList* surfaces) override { // We may have 1 or 2 surfaces depending on whether this ran through the // full renderer and picked up the output surface, or not. @@ -93,31 +98,49 @@ class SingleOverlayValidator : public OverlayCandidateValidator { OverlayCandidate& candidate = surfaces->back(); EXPECT_TRUE(!candidate.use_output_surface_for_resource); - EXPECT_NEAR(expected_rect_.x(), candidate.display_rect.x(), 0.01f); - EXPECT_NEAR(expected_rect_.y(), candidate.display_rect.y(), 0.01f); - EXPECT_NEAR(expected_rect_.width(), candidate.display_rect.width(), 0.01f); - EXPECT_NEAR(expected_rect_.height(), candidate.display_rect.height(), - 0.01f); - - EXPECT_FLOAT_RECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight), - candidate.uv_rect); - if (!candidate.clip_rect.IsEmpty()) { - EXPECT_EQ(true, candidate.is_clipped); - EXPECT_EQ(kOverlayClipRect, candidate.clip_rect); + for (const auto& r : expected_rects_) { + const float kAbsoluteError = 0.01f; + if (std::abs(r.x() - candidate.display_rect.x()) <= kAbsoluteError && + std::abs(r.y() - candidate.display_rect.y()) <= kAbsoluteError && + std::abs(r.width() - candidate.display_rect.width()) <= + kAbsoluteError && + std::abs(r.height() - candidate.display_rect.height()) <= + kAbsoluteError) { + EXPECT_FLOAT_RECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight), + candidate.uv_rect); + if (!candidate.clip_rect.IsEmpty()) { + EXPECT_EQ(true, candidate.is_clipped); + EXPECT_EQ(kOverlayClipRect, candidate.clip_rect); + } + candidate.overlay_handled = true; + return; + } } - candidate.overlay_handled = true; + // We should find one rect in expected_rects_that matches candidate. + EXPECT_TRUE(false); } - void SetExpectedRect(const gfx::RectF& rect) { expected_rect_ = rect; } + void AddExpectedRect(const gfx::RectF& rect) { + expected_rects_.push_back(rect); + } private: - gfx::RectF expected_rect_; + std::vector<gfx::RectF> expected_rects_; }; class CALayerValidator : public OverlayCandidateValidator { public: void GetStrategies(OverlayProcessor::StrategyList* strategies) override {} bool AllowCALayerOverlays() override { return true; } + bool AllowDCLayerOverlays() override { return false; } + void CheckOverlaySupport(OverlayCandidateList* surfaces) override {} +}; + +class DCLayerValidator : public OverlayCandidateValidator { + public: + void GetStrategies(OverlayProcessor::StrategyList* strategies) override {} + bool AllowCALayerOverlays() override { return false; } + bool AllowDCLayerOverlays() override { return true; } void CheckOverlaySupport(OverlayCandidateList* surfaces) override {} }; @@ -321,6 +344,28 @@ StreamVideoDrawQuad* CreateFullscreenCandidateVideoQuad( transform); } +YUVVideoDrawQuad* CreateFullscreenCandidateYUVVideoQuad( + ResourceProvider* resource_provider, + const SharedQuadState* shared_quad_state, + RenderPass* render_pass) { + gfx::RectF tex_coord_rect(0, 0, 1, 1); + gfx::Rect rect = render_pass->output_rect; + gfx::Size resource_size_in_pixels = rect.size(); + bool is_overlay_candidate = true; + ResourceId resource_id = CreateResource( + resource_provider, resource_size_in_pixels, is_overlay_candidate); + + YUVVideoDrawQuad* overlay_quad = + render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>(); + overlay_quad->SetNew(shared_quad_state, rect, rect, rect, tex_coord_rect, + tex_coord_rect, resource_size_in_pixels, + resource_size_in_pixels, resource_id, resource_id, + resource_id, resource_id, YUVVideoDrawQuad::REC_601, + gfx::ColorSpace(), 0, 1.0, 8); + + return overlay_quad; +} + void CreateOpaqueQuadAt(ResourceProvider* resource_provider, const SharedQuadState* shared_quad_state, RenderPass* render_pass, @@ -414,6 +459,7 @@ using SingleOverlayOnTopTest = OverlayTest<SingleOnTopOverlayValidator>; using UnderlayTest = OverlayTest<UnderlayOverlayValidator>; using UnderlayCastTest = OverlayTest<UnderlayCastOverlayValidator>; using CALayerOverlayTest = OverlayTest<CALayerValidator>; +using DCLayerOverlayTest = OverlayTest<DCLayerValidator>; TEST(OverlayTest, NoOverlaysByDefault) { scoped_refptr<TestContextProvider> provider = TestContextProvider::Create(); @@ -460,8 +506,8 @@ TEST_F(FullscreenOverlayTest, SuccessfulOverlay) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); RenderPass* main_pass = pass.get(); @@ -473,6 +519,29 @@ TEST_F(FullscreenOverlayTest, SuccessfulOverlay) { EXPECT_EQ(original_resource_id, candidate_list.front().resource_id); } +TEST_F(FullscreenOverlayTest, AlphaFail) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad( + resource_provider_.get(), pass->shared_quad_state_list.back(), + pass.get()); + original_quad->opaque_rect = gfx::Rect(0, 0, 0, 0); + + // Check for potential candidates. + OverlayCandidateList candidate_list; + RenderPassFilterList render_pass_filters; + RenderPassFilterList render_pass_background_filters; + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), pass.get(), render_pass_filters, + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); + + RenderPass* main_pass = pass.get(); + // Check that all the quads are gone. + EXPECT_EQ(1U, main_pass->quad_list.size()); + // Check that we have only one overlay. + EXPECT_EQ(0U, candidate_list.size()); +} + TEST_F(FullscreenOverlayTest, ResourceSizeInPixelsFail) { std::unique_ptr<RenderPass> pass = CreateRenderPass(); TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad( @@ -486,8 +555,8 @@ TEST_F(FullscreenOverlayTest, ResourceSizeInPixelsFail) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(0U, candidate_list.size()); RenderPass* main_pass = pass.get(); @@ -513,8 +582,8 @@ TEST_F(FullscreenOverlayTest, OnTopFail) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(0U, candidate_list.size()); RenderPass* main_pass = pass.get(); @@ -536,8 +605,8 @@ TEST_F(FullscreenOverlayTest, NotCoveringFullscreenFail) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(0U, candidate_list.size()); RenderPass* main_pass = pass.get(); @@ -566,8 +635,8 @@ TEST_F(FullscreenOverlayTest, RemoveFullscreenQuadFromQuadList) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); // Check that the fullscreen quad is gone. @@ -596,8 +665,8 @@ TEST_F(SingleOverlayOnTopTest, SuccessfulOverlay) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); RenderPass* main_pass = pass.get(); @@ -614,6 +683,49 @@ TEST_F(SingleOverlayOnTopTest, SuccessfulOverlay) { EXPECT_EQ(original_resource_id, candidate_list.back().resource_id); } +TEST_F(SingleOverlayOnTopTest, PrioritizeBiggerOne) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + // Add a small quad. + const auto kSmallCandidateRect = gfx::Rect(0, 0, 16, 16); + CreateCandidateQuadAt(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get(), + kSmallCandidateRect); + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( + gfx::RectF(kSmallCandidateRect)); + + // Add a bigger quad below the previous one, but not occluded. + const auto kBigCandidateRect = gfx::Rect(20, 20, 32, 32); + TextureDrawQuad* quad_big = CreateCandidateQuadAt( + resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), + kBigCandidateRect); + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( + gfx::RectF(kBigCandidateRect)); + + unsigned resource_big = quad_big->resource_id(); + + // Add something behind it. + CreateFullscreenOpaqueQuad(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get()); + + // Check for potential candidates. + OverlayCandidateList candidate_list; + RenderPassFilterList render_pass_filters; + RenderPassFilterList render_pass_background_filters; + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), pass.get(), render_pass_filters, + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); + ASSERT_EQ(1U, candidate_list.size()); + + RenderPass* main_pass = pass.get(); + // Check that one quad is gone. + EXPECT_EQ(2U, main_pass->quad_list.size()); + // Check that we have only one overlay. + EXPECT_EQ(1U, candidate_list.size()); + // Check that the right resource id (bigger quad) got extracted. + EXPECT_EQ(resource_big, candidate_list.front().resource_id); +} + TEST_F(SingleOverlayOnTopTest, DamageRect) { std::unique_ptr<RenderPass> pass = CreateRenderPass(); CreateFullscreenCandidateQuad(resource_provider_.get(), @@ -642,9 +754,9 @@ TEST_F(SingleOverlayOnTopTest, DamageRect) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); - DCHECK(damage_rect_.IsEmpty()); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); + EXPECT_TRUE(damage_rect_.IsEmpty()); } TEST_F(SingleOverlayOnTopTest, NoCandidates) { @@ -665,8 +777,8 @@ TEST_F(SingleOverlayOnTopTest, NoCandidates) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass_list.back().get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); // There should be nothing new here. CompareRenderPassLists(pass_list, original_pass_list); @@ -694,8 +806,8 @@ TEST_F(SingleOverlayOnTopTest, OccludedCandidates) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass_list.back().get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); // There should be nothing new here. CompareRenderPassLists(pass_list, original_pass_list); @@ -720,27 +832,30 @@ TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } -TEST_F(SingleOverlayOnTopTest, RejectBlending) { +TEST_F(SingleOverlayOnTopTest, AcceptBlending) { std::unique_ptr<RenderPass> pass = CreateRenderPass(); TextureDrawQuad* quad = CreateFullscreenCandidateQuad(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); quad->needs_blending = true; + quad->opaque_rect = gfx::Rect(0, 0, 0, 0); OverlayCandidateList candidate_list; RenderPassFilterList render_pass_filters; RenderPassFilterList render_pass_background_filters; + damage_rect_ = quad->rect; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); - EXPECT_EQ(0U, candidate_list.size()); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); + EXPECT_EQ(1U, candidate_list.size()); + EXPECT_FALSE(damage_rect_.IsEmpty()); } TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) { @@ -756,8 +871,8 @@ TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); } @@ -773,8 +888,8 @@ TEST_F(SingleOverlayOnTopTest, RejectBlendMode) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); } @@ -790,8 +905,8 @@ TEST_F(SingleOverlayOnTopTest, RejectOpacity) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); } @@ -808,8 +923,8 @@ TEST_F(SingleOverlayOnTopTest, RejectNonAxisAlignedTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); } @@ -826,8 +941,8 @@ TEST_F(SingleOverlayOnTopTest, AllowClipped) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } @@ -845,8 +960,8 @@ TEST_F(UnderlayTest, AllowVerticalFlip) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL, candidate_list.back().transform); @@ -867,8 +982,8 @@ TEST_F(UnderlayTest, AllowHorizontalFlip) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL, candidate_list.back().transform); @@ -887,8 +1002,8 @@ TEST_F(SingleOverlayOnTopTest, AllowPositiveScaleTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } @@ -906,8 +1021,8 @@ TEST_F(SingleOverlayOnTopTest, RejectTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(0U, candidate_list.size()); } @@ -925,8 +1040,8 @@ TEST_F(UnderlayTest, Allow90DegreeRotation) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_90, candidate_list.back().transform); } @@ -945,8 +1060,8 @@ TEST_F(UnderlayTest, Allow180DegreeRotation) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_180, candidate_list.back().transform); } @@ -965,14 +1080,14 @@ TEST_F(UnderlayTest, Allow270DegreeRotation) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_270, candidate_list.back().transform); } TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) { - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(kOverlayBottomRightRect)); std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -989,13 +1104,13 @@ TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } TEST_F(SingleOverlayOnTopTest, AllowTransparentOnTop) { - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(kOverlayBottomRightRect)); std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -1013,13 +1128,13 @@ TEST_F(SingleOverlayOnTopTest, AllowTransparentOnTop) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } TEST_F(SingleOverlayOnTopTest, AllowTransparentColorOnTop) { - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(kOverlayBottomRightRect)); std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -1035,8 +1150,8 @@ TEST_F(SingleOverlayOnTopTest, AllowTransparentColorOnTop) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } @@ -1056,8 +1171,8 @@ TEST_F(SingleOverlayOnTopTest, RejectOpaqueColorOnTop) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); } @@ -1075,8 +1190,8 @@ TEST_F(SingleOverlayOnTopTest, RejectTransparentColorOnTopWithoutBlending) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); } @@ -1091,8 +1206,8 @@ TEST_F(SingleOverlayOnTopTest, RejectVideoSwapTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); } @@ -1107,8 +1222,8 @@ TEST_F(UnderlayTest, AllowVideoXMirrorTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } @@ -1123,8 +1238,8 @@ TEST_F(UnderlayTest, AllowVideoBothMirrorTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } @@ -1139,8 +1254,8 @@ TEST_F(UnderlayTest, AllowVideoNormalTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } @@ -1155,13 +1270,13 @@ TEST_F(SingleOverlayOnTopTest, AllowVideoYMirrorTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, candidate_list.size()); } TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) { - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(kOverlayBottomRightRect)); std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -1176,8 +1291,8 @@ TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(-1, candidate_list[0].plane_z_order); EXPECT_EQ(2U, pass->quad_list.size()); @@ -1199,8 +1314,8 @@ TEST_F(UnderlayTest, AllowOnTop) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(-1, candidate_list[0].plane_z_order); // The overlay quad should have changed to a SOLID_COLOR quad. @@ -1221,8 +1336,8 @@ TEST_F(UnderlayTest, InitialUnderlayDamageNotSubtracted) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(kOverlayRect, damage_rect_); } @@ -1247,8 +1362,8 @@ TEST_F(UnderlayTest, DamageSubtractedForConsecutiveIdenticalUnderlays) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); } // The second time the same overlay rect is scheduled it will be subtracted @@ -1261,7 +1376,7 @@ TEST_F(UnderlayTest, DamageSubtractedForConsecutiveIdenticalUnderlays) { TEST_F(UnderlayTest, DamageNotSubtractedForNonIdenticalConsecutiveUnderlays) { gfx::Rect overlay_rects[] = {kOverlayBottomRightRect, kOverlayRect}; for (int i = 0; i < 2; ++i) { - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(overlay_rects[i])); std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -1277,8 +1392,8 @@ TEST_F(UnderlayTest, DamageNotSubtractedForNonIdenticalConsecutiveUnderlays) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(overlay_rects[i], damage_rect_); } @@ -1301,15 +1416,15 @@ TEST_F(UnderlayTest, DamageNotSubtractedWhenQuadsAboveOverlap) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); } EXPECT_EQ(kOverlayRect, damage_rect_); } TEST_F(UnderlayTest, DamageSubtractedWhenQuadsAboveDontOverlap) { - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(kOverlayBottomRightRect)); for (int i = 0; i < 2; ++i) { @@ -1329,8 +1444,8 @@ TEST_F(UnderlayTest, DamageSubtractedWhenQuadsAboveDontOverlap) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); } EXPECT_TRUE(damage_rect_.IsEmpty()); @@ -1348,8 +1463,8 @@ TEST_F(UnderlayCastTest, NoOverlayContentBounds) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, content_bounds_.size()); } @@ -1364,15 +1479,15 @@ TEST_F(UnderlayCastTest, FullScreenOverlayContentBounds) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_TRUE(content_bounds_[0].IsEmpty()); } TEST_F(UnderlayCastTest, BlackOutsideOverlayContentBounds) { - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(kOverlayBottomRightRect)); const gfx::Rect kLeftSide(0, 0, 128, 256); @@ -1394,8 +1509,8 @@ TEST_F(UnderlayCastTest, BlackOutsideOverlayContentBounds) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_TRUE(content_bounds_[0].IsEmpty()); @@ -1415,8 +1530,8 @@ TEST_F(UnderlayCastTest, OverlayOccludedContentBounds) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_EQ(kOverlayTopLeftRect, content_bounds_[0]); @@ -1439,8 +1554,8 @@ TEST_F(UnderlayCastTest, OverlayOccludedUnionContentBounds) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_EQ(kOverlayRect, content_bounds_[0]); @@ -1450,7 +1565,7 @@ TEST_F(UnderlayCastTest, RoundOverlayContentBounds) { // Check rounding behaviour on overlay quads. Be conservative (content // potentially visible on boundary). const gfx::Rect overlay_rect(1, 1, 8, 8); - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(1.5f, 1.5f, 8, 8)); gfx::Transform transform; @@ -1469,8 +1584,8 @@ TEST_F(UnderlayCastTest, RoundOverlayContentBounds) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_EQ(gfx::Rect(0, 0, 11, 11), content_bounds_[0]); @@ -1481,7 +1596,7 @@ TEST_F(UnderlayCastTest, RoundContentBounds) { // rect). gfx::Rect overlay_rect = kOverlayRect; overlay_rect.Inset(0, 0, 1, 1); - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(0.5f, 0.5f, 255, 255)); gfx::Transform transform; @@ -1500,8 +1615,8 @@ TEST_F(UnderlayCastTest, RoundContentBounds) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &candidate_list, nullptr, &damage_rect_, - &content_bounds_); + render_pass_background_filters, &candidate_list, nullptr, nullptr, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_EQ(kOverlayRect, content_bounds_[0]); @@ -1534,7 +1649,7 @@ TEST_F(CALayerOverlayTest, AllowNonAxisAlignedTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &overlay_list, &ca_layer_list, + render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr, &damage_rect_, &content_bounds_); EXPECT_EQ(gfx::Rect(), damage_rect); EXPECT_EQ(0U, overlay_list.size()); @@ -1557,7 +1672,7 @@ TEST_F(CALayerOverlayTest, ThreeDTransform) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &overlay_list, &ca_layer_list, + render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr, &damage_rect_, &content_bounds_); EXPECT_EQ(0U, overlay_list.size()); EXPECT_EQ(1U, ca_layer_list.size()); @@ -1583,7 +1698,7 @@ TEST_F(CALayerOverlayTest, AllowContainingClip) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &overlay_list, &ca_layer_list, + render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr, &damage_rect_, &content_bounds_); EXPECT_EQ(gfx::Rect(), damage_rect); EXPECT_EQ(0U, overlay_list.size()); @@ -1606,7 +1721,7 @@ TEST_F(CALayerOverlayTest, NontrivialClip) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &overlay_list, &ca_layer_list, + render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr, &damage_rect_, &content_bounds_); EXPECT_EQ(gfx::Rect(), damage_rect); EXPECT_EQ(0U, overlay_list.size()); @@ -1631,7 +1746,7 @@ TEST_F(CALayerOverlayTest, SkipTransparent) { RenderPassFilterList render_pass_background_filters; overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass.get(), render_pass_filters, - render_pass_background_filters, &overlay_list, &ca_layer_list, + render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr, &damage_rect_, &content_bounds_); EXPECT_EQ(gfx::Rect(), damage_rect); EXPECT_EQ(0U, overlay_list.size()); @@ -1639,6 +1754,201 @@ TEST_F(CALayerOverlayTest, SkipTransparent) { EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); } +TEST_F(DCLayerOverlayTest, AllowNonAxisAlignedTransform) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + features::kDirectCompositionComplexOverlays); + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + CreateFullscreenCandidateYUVVideoQuad(resource_provider_.get(), + pass->shared_quad_state_list.back(), + pass.get()); + pass->shared_quad_state_list.back() + ->quad_to_target_transform.RotateAboutZAxis(45.f); + + gfx::Rect damage_rect; + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + RenderPassFilterList render_pass_filters; + RenderPassFilterList render_pass_background_filters; + damage_rect_ = gfx::Rect(1, 1, 10, 10); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), pass.get(), render_pass_filters, + render_pass_background_filters, &overlay_list, nullptr, &dc_layer_list, + &damage_rect_, &content_bounds_); + EXPECT_EQ(gfx::Rect(), damage_rect); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(1, dc_layer_list.back().shared_state->z_order); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); + EXPECT_EQ(gfx::Rect(1, 1, 10, 10), damage_rect_); +} + +TEST_F(DCLayerOverlayTest, Occluded) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kDirectCompositionUnderlays); + { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + CreateOpaqueQuadAt(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get(), + gfx::Rect(0, 2, 100, 100), SK_ColorWHITE); + CreateFullscreenCandidateYUVVideoQuad(resource_provider_.get(), + pass->shared_quad_state_list.back(), + pass.get()); + + gfx::Rect damage_rect; + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + RenderPassFilterList render_pass_filters; + RenderPassFilterList render_pass_background_filters; + damage_rect_ = gfx::Rect(1, 1, 10, 10); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), pass.get(), render_pass_filters, + render_pass_background_filters, &overlay_list, nullptr, &dc_layer_list, + &damage_rect_, &content_bounds_); + EXPECT_EQ(gfx::Rect(), damage_rect); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); + EXPECT_EQ(-1, dc_layer_list.back().shared_state->z_order); + // Entire underlay rect must be redrawn. + EXPECT_EQ(gfx::Rect(0, 0, 256, 256), damage_rect_); + } + { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + CreateOpaqueQuadAt(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get(), + gfx::Rect(2, 2, 100, 100), SK_ColorWHITE); + CreateFullscreenCandidateYUVVideoQuad(resource_provider_.get(), + pass->shared_quad_state_list.back(), + pass.get()); + + gfx::Rect damage_rect; + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + RenderPassFilterList render_pass_filters; + RenderPassFilterList render_pass_background_filters; + damage_rect_ = gfx::Rect(1, 1, 10, 10); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), pass.get(), render_pass_filters, + render_pass_background_filters, &overlay_list, nullptr, &dc_layer_list, + &damage_rect_, &content_bounds_); + EXPECT_EQ(gfx::Rect(), damage_rect); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); + EXPECT_EQ(-1, dc_layer_list.back().shared_state->z_order); + // The underlay rectangle is the same, so the damage is contained within + // the combined occluding rects for this and the last frame. + EXPECT_EQ(gfx::Rect(1, 2, 10, 9), damage_rect_); + } +} + +TEST_F(DCLayerOverlayTest, DamageRect) { + for (int i = 0; i < 2; i++) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + CreateFullscreenCandidateYUVVideoQuad(resource_provider_.get(), + pass->shared_quad_state_list.back(), + pass.get()); + + gfx::Rect damage_rect; + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + RenderPassFilterList render_pass_filters; + RenderPassFilterList render_pass_background_filters; + damage_rect_ = gfx::Rect(1, 1, 10, 10); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), pass.get(), render_pass_filters, + render_pass_background_filters, &overlay_list, nullptr, &dc_layer_list, + &damage_rect_, &content_bounds_); + EXPECT_EQ(gfx::Rect(), damage_rect); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); + EXPECT_EQ(1, dc_layer_list.back().shared_state->z_order); + // Damage rect should be unchanged on initial frame because of resize, but + // should be empty on the second frame because everything was put in a + // layer. + if (i == 1) + EXPECT_TRUE(damage_rect_.IsEmpty()); + else + EXPECT_EQ(gfx::Rect(1, 1, 10, 10), damage_rect_); + } +} + +TEST_F(DCLayerOverlayTest, ClipRect) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kDirectCompositionUnderlays); + + // Process twice. The second time through the overlay list shouldn't change, + // which will allow the damage rect to reflect just the changes in that + // frame. + for (size_t i = 0; i < 2; ++i) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + CreateOpaqueQuadAt(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get(), + gfx::Rect(0, 2, 100, 100), SK_ColorWHITE); + pass->shared_quad_state_list.back()->is_clipped = true; + pass->shared_quad_state_list.back()->clip_rect = gfx::Rect(0, 3, 100, 100); + SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState(); + shared_state->opacity = 1.f; + CreateFullscreenCandidateYUVVideoQuad(resource_provider_.get(), + shared_state, pass.get()); + shared_state->is_clipped = true; + // Clipped rect shouldn't be overlapped by clipped opaque quad rect. + shared_state->clip_rect = gfx::Rect(0, 0, 100, 3); + + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + RenderPassFilterList render_pass_filters; + RenderPassFilterList render_pass_background_filters; + damage_rect_ = gfx::Rect(1, 1, 10, 10); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), pass.get(), render_pass_filters, + render_pass_background_filters, &overlay_list, nullptr, &dc_layer_list, + &damage_rect_, &content_bounds_); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + // Because of clip rects the overlay isn't occluded and shouldn't be an + // underlay. + EXPECT_EQ(1, dc_layer_list.back().shared_state->z_order); + if (i == 1) { + // The damage rect should only contain contents that aren't in the + // clipped overlay rect. + EXPECT_EQ(gfx::Rect(1, 3, 10, 8), damage_rect_); + } + } +} + +TEST_F(DCLayerOverlayTest, TransparentOnTop) { + base::test::ScopedFeatureList feature_list; + + // Process twice. The second time through the overlay list shouldn't change, + // which will allow the damage rect to reflect just the changes in that + // frame. + for (size_t i = 0; i < 2; ++i) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + CreateFullscreenCandidateYUVVideoQuad(resource_provider_.get(), + pass->shared_quad_state_list.back(), + pass.get()); + pass->shared_quad_state_list.back()->opacity = 0.5f; + + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + RenderPassFilterList render_pass_filters; + RenderPassFilterList render_pass_background_filters; + damage_rect_ = gfx::Rect(1, 1, 10, 10); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), pass.get(), render_pass_filters, + render_pass_background_filters, &overlay_list, nullptr, &dc_layer_list, + &damage_rect_, &content_bounds_); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(1, dc_layer_list.back().shared_state->z_order); + // Quad isn't opaque, so underlying damage must remain the same. + EXPECT_EQ(gfx::Rect(1, 1, 10, 10), damage_rect_); + } +} + class OverlayInfoRendererGL : public GLRenderer { public: OverlayInfoRendererGL(const RendererSettings* settings, @@ -1747,7 +2057,7 @@ TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) { bool use_validator = true; Init(use_validator); renderer_->set_expect_overlays(true); - output_surface_->GetOverlayCandidateValidator()->SetExpectedRect( + output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(kOverlayBottomRightRect)); gfx::Size viewport_size(16, 16); @@ -2177,7 +2487,7 @@ class CALayerOverlayRPDQTest : public CALayerOverlayTest { overlay_processor_->ProcessForOverlays( resource_provider_.get(), pass_.get(), render_pass_filters_, render_pass_background_filters_, &overlay_list_, &ca_layer_list_, - &damage_rect_, &content_bounds_); + nullptr, &damage_rect_, &content_bounds_); } std::unique_ptr<RenderPass> pass_; RenderPassDrawQuad* quad_; diff --git a/chromium/cc/output/program_binding.cc b/chromium/cc/output/program_binding.cc index 8402e824492..a8f4b6a9f6c 100644 --- a/chromium/cc/output/program_binding.cc +++ b/chromium/cc/output/program_binding.cc @@ -177,24 +177,21 @@ bool ProgramBindingBase::Init(GLES2Interface* context, return !!program_; } -bool ProgramBindingBase::Link(GLES2Interface* context, - const std::string& vertex_source, - const std::string& fragment_source) { +bool ProgramBindingBase::Link(GLES2Interface* context) { context->LinkProgram(program_); CleanupShaders(context); if (!program_) return false; +#ifndef NDEBUG int linked = 0; context->GetProgramiv(program_, GL_LINK_STATUS, &linked); if (!linked) { char buffer[1024] = ""; context->GetProgramInfoLog(program_, sizeof(buffer), nullptr, buffer); - LOG(ERROR) << "Error linking shader: " << buffer << "\n" - << "Vertex shader:\n" - << vertex_source << "Fragment shader:\n" - << fragment_source; + DLOG(ERROR) << "Error compiling shader: " << buffer; return false; } +#endif return true; } @@ -224,16 +221,17 @@ unsigned ProgramBindingBase::LoadShader(GLES2Interface* context, shader_source_str, shader_length); context->CompileShader(shader); +#if DCHECK_IS_ON() int compiled = 0; context->GetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { char buffer[1024] = ""; context->GetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer); - LOG(ERROR) << "Error compiling shader: " << buffer << "\n" - << "Shader program:\n" - << shader_source; + DLOG(ERROR) << "Error compiling shader: " << buffer + << "\n shader program: " << shader_source; return 0u; } +#endif return shader; } diff --git a/chromium/cc/output/program_binding.h b/chromium/cc/output/program_binding.h index ce45f2692ad..6f1bc914875 100644 --- a/chromium/cc/output/program_binding.h +++ b/chromium/cc/output/program_binding.h @@ -32,9 +32,7 @@ class ProgramBindingBase { bool Init(gpu::gles2::GLES2Interface* context, const std::string& vertex_shader, const std::string& fragment_shader); - bool Link(gpu::gles2::GLES2Interface* context, - const std::string& vertex_source, - const std::string& fragment_source); + bool Link(gpu::gles2::GLES2Interface* context); void Cleanup(gpu::gles2::GLES2Interface* context); unsigned program() const { return program_; } @@ -405,10 +403,9 @@ class Program : public ProgramBindingBase { if (IsContextLost(context_provider->ContextGL())) return; - std::string vertex_source = vertex_shader_.GetShaderString(); - std::string fragment_source = fragment_shader_.GetShaderString(); - if (!ProgramBindingBase::Init(context_provider->ContextGL(), vertex_source, - fragment_source)) { + if (!ProgramBindingBase::Init(context_provider->ContextGL(), + vertex_shader_.GetShaderString(), + fragment_shader_.GetShaderString())) { DCHECK(IsContextLost(context_provider->ContextGL())); return; } @@ -420,7 +417,7 @@ class Program : public ProgramBindingBase { program_, &base_uniform_index); // Link after binding uniforms - if (!Link(context_provider->ContextGL(), vertex_source, fragment_source)) { + if (!Link(context_provider->ContextGL())) { DCHECK(IsContextLost(context_provider->ContextGL())); return; } diff --git a/chromium/cc/output/renderer_pixeltest.cc b/chromium/cc/output/renderer_pixeltest.cc index 93aa2d84caf..6fc2ac45522 100644 --- a/chromium/cc/output/renderer_pixeltest.cc +++ b/chromium/cc/output/renderer_pixeltest.cc @@ -9,8 +9,8 @@ #include "base/message_loop/message_loop.h" #include "cc/base/math_util.h" #include "cc/output/gl_renderer.h" -#include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" +#include "cc/paint/skia_paint_canvas.h" #include "cc/quads/draw_quad.h" #include "cc/quads/picture_draw_quad.h" #include "cc/quads/texture_draw_quad.h" @@ -27,7 +27,9 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/effects/SkColorFilterImageFilter.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" +#include "ui/gfx/color_transform.h" #include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gfx/test/icc_profiles.h" using gpu::gles2::GLES2Interface; @@ -99,12 +101,12 @@ void CreateTestRenderPassDrawQuad(const SharedQuadState* shared_state, RenderPassDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); quad->SetNew(shared_state, rect, rect, pass_id, - 0, // mask_resource_id - gfx::RectF(), // mask_uv_rect - gfx::Size(), // mask_texture_size - gfx::Vector2dF(), // filters scale - gfx::PointF(), // filter origin - gfx::RectF()); // tex_coord_rect + 0, // mask_resource_id + gfx::RectF(), // mask_uv_rect + gfx::Size(), // mask_texture_size + gfx::Vector2dF(), // filters scale + gfx::PointF(), // filter origin + gfx::RectF(rect)); // tex_coord_rect } void CreateTestTwoColoredTextureDrawQuad(const gfx::Rect& rect, @@ -1586,9 +1588,9 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) { RenderPassDrawQuad* render_pass_quad = root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); - render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect, - child_pass_id, 0, gfx::RectF(), gfx::Size(), - gfx::Vector2dF(), gfx::PointF(), gfx::RectF()); + render_pass_quad->SetNew( + pass_shared_state, pass_rect, pass_rect, child_pass_id, 0, gfx::RectF(), + gfx::Size(), gfx::Vector2dF(), gfx::PointF(), gfx::RectF(pass_rect)); RenderPassList pass_list; pass_list.push_back(std::move(child_pass)); @@ -1652,9 +1654,9 @@ TYPED_TEST(RendererPixelTest, FastPassSaturateFilter) { RenderPassDrawQuad* render_pass_quad = root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); - render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect, - child_pass_id, 0, gfx::RectF(), gfx::Size(), - gfx::Vector2dF(), gfx::PointF(), gfx::RectF()); + render_pass_quad->SetNew( + pass_shared_state, pass_rect, pass_rect, child_pass_id, 0, gfx::RectF(), + gfx::Size(), gfx::Vector2dF(), gfx::PointF(), gfx::RectF(pass_rect)); RenderPassList pass_list; pass_list.push_back(std::move(child_pass)); @@ -1718,9 +1720,9 @@ TYPED_TEST(RendererPixelTest, FastPassFilterChain) { RenderPassDrawQuad* render_pass_quad = root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); - render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect, - child_pass_id, 0, gfx::RectF(), gfx::Size(), - gfx::Vector2dF(), gfx::PointF(), gfx::RectF()); + render_pass_quad->SetNew( + pass_shared_state, pass_rect, pass_rect, child_pass_id, 0, gfx::RectF(), + gfx::Size(), gfx::Vector2dF(), gfx::PointF(), gfx::RectF(pass_rect)); RenderPassList pass_list; pass_list.push_back(std::move(child_pass)); @@ -1805,9 +1807,9 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) { RenderPassDrawQuad* render_pass_quad = root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); - render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect, - child_pass_id, 0, gfx::RectF(), gfx::Size(), - gfx::Vector2dF(), gfx::PointF(), gfx::RectF()); + render_pass_quad->SetNew( + pass_shared_state, pass_rect, pass_rect, child_pass_id, 0, gfx::RectF(), + gfx::Size(), gfx::Vector2dF(), gfx::PointF(), gfx::RectF(pass_rect)); RenderPassList pass_list; @@ -1963,7 +1965,7 @@ TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad) { SkBitmap bitmap; bitmap.allocPixels( SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height())); - PaintCanvas canvas(bitmap); + SkiaPaintCanvas canvas(bitmap); PaintFlags flags; flags.setStyle(PaintFlags::kStroke_Style); flags.setStrokeWidth(SkIntToScalar(4)); @@ -2007,7 +2009,7 @@ TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad) { gfx::Size(mask_rect.size()), // mask_texture_size gfx::Vector2dF(), // filters scale gfx::PointF(), // filter origin - gfx::RectF()); // tex_coord_rect + gfx::RectF(sub_rect)); // tex_coord_rect // White background behind the masked render pass. SolidColorDrawQuad* white = @@ -2058,7 +2060,7 @@ TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad2) { SkBitmap bitmap; bitmap.allocPixels( SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height())); - PaintCanvas canvas(bitmap); + SkiaPaintCanvas canvas(bitmap); PaintFlags flags; flags.setStyle(PaintFlags::kStroke_Style); flags.setStrokeWidth(SkIntToScalar(4)); @@ -2102,7 +2104,7 @@ TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad2) { gfx::Size(mask_rect.size()), // mask_texture_size gfx::Vector2dF(), // filters scale gfx::PointF(), // filter origin - gfx::RectF()); // tex_coord_rect + gfx::RectF(sub_rect)); // tex_coord_rect // White background behind the masked render pass. SolidColorDrawQuad* white = @@ -3383,6 +3385,195 @@ TEST_F(GLRendererPixelTestWithOverdrawFeedback, TranslucentRectangles) { ExactPixelComparator(true))); } +typedef std::tr1::tuple<gfx::ColorSpace, gfx::ColorSpace> ColorSpacePair; + +class ColorTransformPixelTest + : public GLRendererPixelTest, + public testing::WithParamInterface<ColorSpacePair> { + public: + ColorTransformPixelTest() { + settings_.renderer_settings.enable_color_correct_rendering = true; + // Note that this size of 17 is not random -- it is chosen to match the + // size of LUTs that are created. If we did not match the LUT size exactly, + // then the error for LUT based transforms is much larger. + device_viewport_size_ = gfx::Size(17, 4); + src_color_space_ = std::tr1::get<0>(GetParam()); + dst_color_space_ = std::tr1::get<1>(GetParam()); + if (!src_color_space_.IsValid()) { + src_color_space_ = + gfx::ICCProfileForTestingNoAnalyticTrFn().GetColorSpace(); + } + if (!dst_color_space_.IsValid()) { + dst_color_space_ = + gfx::ICCProfileForTestingNoAnalyticTrFn().GetColorSpace(); + } + } + gfx::ColorSpace src_color_space_; + gfx::ColorSpace dst_color_space_; +}; + +TEST_P(ColorTransformPixelTest, Basic) { + gfx::Rect rect(this->device_viewport_size_); + std::vector<uint8_t> input_colors(4 * rect.width() * rect.height(), 0); + std::vector<SkColor> expected_output_colors(rect.width() * rect.height()); + + renderer_->DisableColorChecksForTesting(); + + // Set the input data to be: + // Row 0: Gradient of red from 0 to 255 + // Row 1: Gradient of green from 0 to 255 + // Row 2: Gradient of blue from 0 to 255 + // Row 3: Gradient of grey from 0 to 255 + for (int x = 0; x < rect.width(); ++x) { + int v = (x * 255) / (rect.width() - 1); + for (int y = 0; y < rect.height(); ++y) { + for (int c = 0; c < 3; ++c) { + if (y == c || y == rect.height() - 1) { + input_colors[c + 4 * (x + rect.width() * y)] = v; + } + } + input_colors[3 + 4 * (x + rect.width() * y)] = 255; + } + } + + std::unique_ptr<gfx::ColorTransform> transform = + gfx::ColorTransform::NewColorTransform( + src_color_space_, dst_color_space_, + gfx::ColorTransform::Intent::INTENT_PERCEPTUAL); + + for (size_t i = 0; i < expected_output_colors.size(); ++i) { + gfx::ColorTransform::TriStim color; + color.set_x(input_colors[4 * i + 0] / 255.f); + color.set_y(input_colors[4 * i + 1] / 255.f); + color.set_z(input_colors[4 * i + 2] / 255.f); + transform->Transform(&color, 1); + color.set_x(std::min(std::max(0.f, color.x()), 1.f)); + color.set_y(std::min(std::max(0.f, color.y()), 1.f)); + color.set_z(std::min(std::max(0.f, color.z()), 1.f)); + expected_output_colors[i] = + SkColorSetARGBInline(255, static_cast<size_t>(255.f * color.x() + 0.5f), + static_cast<size_t>(255.f * color.y() + 0.5f), + static_cast<size_t>(255.f * color.z() + 0.5f)); + } + + int id = 1; + std::unique_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); + pass->color_space = dst_color_space_; + + { + SharedQuadState* shared_state = + CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); + + ResourceId resource = resource_provider_->CreateResource( + rect.size(), ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888, + src_color_space_); + resource_provider_->CopyToResource(resource, input_colors.data(), + rect.size()); + + const gfx::PointF uv_top_left(0.0f, 0.0f); + const gfx::PointF uv_bottom_right(1.0f, 1.0f); + const bool flipped = false; + const bool nearest_neighbor = false; + const bool premultiplied_alpha = false; + TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); + + float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + quad->SetNew(shared_state, rect, gfx::Rect(), rect, resource, + premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorBLACK, vertex_opacity, flipped, nearest_neighbor, + false); + + SolidColorDrawQuad* color_quad = + pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false); + } + + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + + // Allow a difference of 2 bytes in comparison for shader-based transforms, + // and 4 bytes for LUT-based transforms (determined empirically). + FuzzyPixelComparator comparator(false, 100.f, 0.f, 2.f, 2, 0); + if (!transform->CanGetShaderSource()) + comparator = FuzzyPixelComparator(false, 100.f, 0.f, 6.f, 6, 0); + EXPECT_TRUE(RunPixelTest(&pass_list, &expected_output_colors, comparator)); +} + +typedef gfx::ColorSpace::PrimaryID PrimaryID; +typedef gfx::ColorSpace::TransferID TransferID; +typedef gfx::ColorSpace::MatrixID MatrixID; +typedef gfx::ColorSpace::RangeID RangeID; + +gfx::ColorSpace src_color_spaces[] = { + // This will be replaced by an ICC-based space (which can't be initialized + // here). + gfx::ColorSpace(), + gfx::ColorSpace(PrimaryID::BT709, TransferID::BT709), + gfx::ColorSpace(PrimaryID::BT709, TransferID::GAMMA22), + gfx::ColorSpace(PrimaryID::BT709, TransferID::GAMMA24), + gfx::ColorSpace(PrimaryID::BT709, TransferID::GAMMA28), + gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTE170M), + gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTE240M), + gfx::ColorSpace(PrimaryID::BT709, TransferID::LINEAR), + gfx::ColorSpace(PrimaryID::BT709, TransferID::LOG), + gfx::ColorSpace(PrimaryID::BT709, TransferID::LOG_SQRT), + gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_4), + gfx::ColorSpace(PrimaryID::BT709, TransferID::BT1361_ECG), + gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1), + gfx::ColorSpace(PrimaryID::BT709, TransferID::BT2020_10), + gfx::ColorSpace(PrimaryID::BT709, TransferID::BT2020_12), + gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTEST2084), + gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTEST428_1), + gfx::ColorSpace(PrimaryID::BT709, TransferID::ARIB_STD_B67), + gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1_HDR), + gfx::ColorSpace(PrimaryID::BT709, TransferID::LINEAR_HDR), + gfx::ColorSpace(PrimaryID::BT709, + TransferID::BT2020_10, + MatrixID::BT2020_CL, + RangeID::FULL), +}; + +gfx::ColorSpace dst_color_spaces[] = { + // This will be replaced by an ICC-based space (which can't be initialized + // here). + gfx::ColorSpace(), + gfx::ColorSpace(PrimaryID::BT709, TransferID::BT709), + gfx::ColorSpace(PrimaryID::BT709, TransferID::GAMMA22), + gfx::ColorSpace(PrimaryID::BT709, TransferID::GAMMA24), + gfx::ColorSpace(PrimaryID::BT709, TransferID::GAMMA28), + gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTE170M), + gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTE240M), + gfx::ColorSpace(PrimaryID::BT709, TransferID::LINEAR), + gfx::ColorSpace(PrimaryID::BT709, TransferID::LOG), + gfx::ColorSpace(PrimaryID::BT709, TransferID::LOG_SQRT), + gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_4), + gfx::ColorSpace(PrimaryID::BT709, TransferID::BT1361_ECG), + gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1), + gfx::ColorSpace(PrimaryID::BT709, TransferID::BT2020_10), + gfx::ColorSpace(PrimaryID::BT709, TransferID::BT2020_12), + gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTEST2084), + gfx::ColorSpace(PrimaryID::BT709, TransferID::ARIB_STD_B67), + gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1_HDR), + gfx::ColorSpace(PrimaryID::BT709, TransferID::LINEAR_HDR), +}; + +gfx::ColorSpace intermediate_color_spaces[] = { + gfx::ColorSpace(PrimaryID::XYZ_D50, TransferID::LINEAR), + gfx::ColorSpace(PrimaryID::XYZ_D50, TransferID::IEC61966_2_1_HDR), +}; + +INSTANTIATE_TEST_CASE_P( + FromColorSpace, + ColorTransformPixelTest, + testing::Combine(testing::ValuesIn(src_color_spaces), + testing::ValuesIn(intermediate_color_spaces))); + +INSTANTIATE_TEST_CASE_P( + ToColorSpace, + ColorTransformPixelTest, + testing::Combine(testing::ValuesIn(intermediate_color_spaces), + testing::ValuesIn(dst_color_spaces))); + #endif // !defined(OS_ANDROID) } // namespace diff --git a/chromium/cc/output/renderer_settings.cc b/chromium/cc/output/renderer_settings.cc index 85b032ce906..acfc6938594 100644 --- a/chromium/cc/output/renderer_settings.cc +++ b/chromium/cc/output/renderer_settings.cc @@ -19,29 +19,4 @@ RendererSettings::RendererSettings(const RendererSettings& other) = default; RendererSettings::~RendererSettings() { } -bool RendererSettings::operator==(const RendererSettings& other) const { - return allow_antialiasing == other.allow_antialiasing && - force_antialiasing == other.force_antialiasing && - force_blending_with_shaders == other.force_blending_with_shaders && - partial_swap_enabled == other.partial_swap_enabled && - finish_rendering_on_resize == other.finish_rendering_on_resize && - should_clear_root_render_pass == other.should_clear_root_render_pass && - disable_display_vsync == other.disable_display_vsync && - release_overlay_resources_after_gpu_query == - other.release_overlay_resources_after_gpu_query && - gl_composited_texture_quad_border == - other.gl_composited_texture_quad_border && - show_overdraw_feedback == other.show_overdraw_feedback && - enable_color_correct_rendering == - other.enable_color_correct_rendering && - refresh_rate == other.refresh_rate && - highp_threshold_min == other.highp_threshold_min && - texture_id_allocation_chunk_size == - other.texture_id_allocation_chunk_size && - use_gpu_memory_buffer_resources == - other.use_gpu_memory_buffer_resources && - preferred_tile_format == other.preferred_tile_format && - buffer_to_texture_target_map == other.buffer_to_texture_target_map; -} - } // namespace cc diff --git a/chromium/cc/output/renderer_settings.h b/chromium/cc/output/renderer_settings.h index ced1ec0cc02..f6afb55467a 100644 --- a/chromium/cc/output/renderer_settings.h +++ b/chromium/cc/output/renderer_settings.h @@ -7,7 +7,7 @@ #include <stddef.h> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/buffer_to_texture_target_map.h" #include "cc/resources/resource_format.h" @@ -37,8 +37,6 @@ class CC_EXPORT RendererSettings { bool use_gpu_memory_buffer_resources = false; ResourceFormat preferred_tile_format; BufferToTextureTargetMap buffer_to_texture_target_map; - - bool operator==(const RendererSettings& other) const; }; } // namespace cc diff --git a/chromium/cc/output/shader.h b/chromium/cc/output/shader.h index 0f65a59538c..cf1496627d4 100644 --- a/chromium/cc/output/shader.h +++ b/chromium/cc/output/shader.h @@ -9,7 +9,7 @@ #include "base/logging.h" #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace gfx { class ColorTransform; diff --git a/chromium/cc/output/software_output_device.h b/chromium/cc/output/software_output_device.h index f4c766c532f..322e17cab76 100644 --- a/chromium/cc/output/software_output_device.h +++ b/chromium/cc/output/software_output_device.h @@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "third_party/skia/include/core/SkSurface.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" diff --git a/chromium/cc/output/software_renderer.cc b/chromium/cc/output/software_renderer.cc index 97137ca0f0e..75dbff4a6e8 100644 --- a/chromium/cc/output/software_renderer.cc +++ b/chromium/cc/output/software_renderer.cc @@ -7,10 +7,10 @@ #include "base/memory/ptr_util.h" #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" +#include "cc/base/render_surface_filters.h" #include "cc/output/copy_output_request.h" #include "cc/output/output_surface.h" #include "cc/output/output_surface_frame.h" -#include "cc/output/render_surface_filters.h" #include "cc/output/renderer_settings.h" #include "cc/output/software_output_device.h" #include "cc/quads/debug_border_draw_quad.h" @@ -29,6 +29,7 @@ #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/effects/SkLayerRasterizer.h" +#include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/skia_util.h" #include "ui/gfx/transform.h" @@ -150,7 +151,7 @@ void SoftwareRenderer::SetClipRect(const gfx::Rect& rect) { current_canvas_->resetMatrix(); // TODO(fmalita) stop using kReplace (see crbug.com/673851) current_canvas_->clipRect(gfx::RectToSkRect(rect), - SkClipOp::kReplace_private_internal_do_not_use); + SkClipOp::kReplace_deprecated); current_canvas_->setMatrix(current_matrix); } @@ -336,6 +337,11 @@ void SoftwareRenderer::DrawPictureQuad(const PictureDrawQuad* quad) { TRACE_EVENT0("cc", "SoftwareRenderer::DrawPictureQuad"); + // TODO(ccameron): Determine a color space strategy for software rendering. + gfx::ColorSpace canvas_color_space; + if (settings_->enable_color_correct_rendering) + canvas_color_space = gfx::ColorSpace::CreateSRGB(); + RasterSource::PlaybackSettings playback_settings; playback_settings.playback_to_shared_canvas = true; // Indicates whether content rasterization should happen through an @@ -356,12 +362,16 @@ void SoftwareRenderer::DrawPictureQuad(const PictureDrawQuad* quad) { quad->shared_quad_state->opacity, disable_image_filtering); quad->raster_source->PlaybackToCanvas( - &filtered_canvas, quad->content_rect, quad->content_rect, - quad->contents_scale, playback_settings); + &filtered_canvas, canvas_color_space, quad->content_rect, + quad->content_rect, + gfx::AxisTransform2d(quad->contents_scale, gfx::Vector2dF()), + playback_settings); } else { quad->raster_source->PlaybackToCanvas( - current_canvas_, quad->content_rect, quad->content_rect, - quad->contents_scale, playback_settings); + current_canvas_, canvas_color_space, quad->content_rect, + quad->content_rect, + gfx::AxisTransform2d(quad->contents_scale, gfx::Vector2dF()), + playback_settings); } } @@ -460,7 +470,7 @@ void SoftwareRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) { SkRect dest_visible_rect = gfx::RectFToSkRect( MathUtil::ScaleRectProportional(QuadVertexRect(), gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect))); - SkRect content_rect = SkRect::MakeWH(quad->rect.width(), quad->rect.height()); + SkRect content_rect = RectFToSkRect(quad->tex_coord_rect); const SkBitmap* content = lock.sk_bitmap(); @@ -574,6 +584,10 @@ void SoftwareRenderer::CopyCurrentRenderPassToBitmap( request->SendBitmapResult(std::move(bitmap)); } +void SoftwareRenderer::SetEnableDCLayers(bool enable) { + NOTIMPLEMENTED(); +} + void SoftwareRenderer::DidChangeVisibility() { if (visible_) output_surface_->EnsureBackbuffer(); diff --git a/chromium/cc/output/software_renderer.h b/chromium/cc/output/software_renderer.h index 9798e1fe3ff..07e9102737e 100644 --- a/chromium/cc/output/software_renderer.h +++ b/chromium/cc/output/software_renderer.h @@ -6,9 +6,9 @@ #define CC_OUTPUT_SOFTWARE_RENDERER_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/direct_renderer.h" -#include "ui/events/latency_info.h" +#include "ui/latency/latency_info.h" namespace cc { class DebugBorderDrawQuad; @@ -51,6 +51,7 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer { void EnsureScissorTestDisabled() override; void CopyCurrentRenderPassToBitmap( std::unique_ptr<CopyOutputRequest> request) override; + void SetEnableDCLayers(bool enable) override; void DidChangeVisibility() override; private: diff --git a/chromium/cc/output/texture_mailbox_deleter.cc b/chromium/cc/output/texture_mailbox_deleter.cc index ff3480d5f30..1e306a7c90f 100644 --- a/chromium/cc/output/texture_mailbox_deleter.cc +++ b/chromium/cc/output/texture_mailbox_deleter.cc @@ -36,7 +36,7 @@ static void PostTaskFromMainToImplThread( bool is_lost) { // This posts the task to RunDeleteTextureOnImplThread(). impl_task_runner->PostTask( - FROM_HERE, base::Bind(run_impl_callback, sync_token, is_lost)); + FROM_HERE, base::BindOnce(run_impl_callback, sync_token, is_lost)); } TextureMailboxDeleter::TextureMailboxDeleter( diff --git a/chromium/cc/output/texture_mailbox_deleter.h b/chromium/cc/output/texture_mailbox_deleter.h index c4fbf0b5136..800358366c0 100644 --- a/chromium/cc/output/texture_mailbox_deleter.h +++ b/chromium/cc/output/texture_mailbox_deleter.h @@ -9,7 +9,7 @@ #include <vector> #include "base/memory/weak_ptr.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { class SingleThreadTaskRunner; diff --git a/chromium/cc/output/vulkan_context_provider.h b/chromium/cc/output/vulkan_context_provider.h index f3d6be0b986..40ba02260df 100644 --- a/chromium/cc/output/vulkan_context_provider.h +++ b/chromium/cc/output/vulkan_context_provider.h @@ -6,7 +6,7 @@ #define CC_OUTPUT_VULKAN_CONTEXT_PROVIDER_H_ #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace gpu { class VulkanDeviceQueue; diff --git a/chromium/cc/output/vulkan_in_process_context_provider.cc b/chromium/cc/output/vulkan_in_process_context_provider.cc index 9d602c42450..f8a3b21025a 100644 --- a/chromium/cc/output/vulkan_in_process_context_provider.cc +++ b/chromium/cc/output/vulkan_in_process_context_provider.cc @@ -3,17 +3,18 @@ // found in the LICENSE file. #include "cc/output/vulkan_in_process_context_provider.h" +#include "gpu/vulkan/features.h" -#if defined(ENABLE_VULKAN) +#if BUILDFLAG(ENABLE_VULKAN) #include "gpu/vulkan/vulkan_device_queue.h" #include "gpu/vulkan/vulkan_implementation.h" -#endif // defined(ENABLE_VULKAN) +#endif // BUILDFLAG(ENABLE_VULKAN) namespace cc { scoped_refptr<VulkanInProcessContextProvider> VulkanInProcessContextProvider::Create() { -#if defined(ENABLE_VULKAN) +#if BUILDFLAG(ENABLE_VULKAN) if (!gpu::VulkanSupported()) return nullptr; @@ -28,7 +29,7 @@ VulkanInProcessContextProvider::Create() { } bool VulkanInProcessContextProvider::Initialize() { -#if defined(ENABLE_VULKAN) +#if BUILDFLAG(ENABLE_VULKAN) DCHECK(!device_queue_); std::unique_ptr<gpu::VulkanDeviceQueue> device_queue( new gpu::VulkanDeviceQueue); @@ -47,7 +48,7 @@ bool VulkanInProcessContextProvider::Initialize() { } void VulkanInProcessContextProvider::Destroy() { -#if defined(ENABLE_VULKAN) +#if BUILDFLAG(ENABLE_VULKAN) if (device_queue_) { device_queue_->Destroy(); device_queue_.reset(); @@ -56,7 +57,7 @@ void VulkanInProcessContextProvider::Destroy() { } gpu::VulkanDeviceQueue* VulkanInProcessContextProvider::GetDeviceQueue() { -#if defined(ENABLE_VULKAN) +#if BUILDFLAG(ENABLE_VULKAN) return device_queue_.get(); #else return nullptr; diff --git a/chromium/cc/output/vulkan_in_process_context_provider.h b/chromium/cc/output/vulkan_in_process_context_provider.h index c477f2f3eee..661752b657c 100644 --- a/chromium/cc/output/vulkan_in_process_context_provider.h +++ b/chromium/cc/output/vulkan_in_process_context_provider.h @@ -7,8 +7,9 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/vulkan_context_provider.h" +#include "gpu/vulkan/features.h" namespace gpu { class VulkanDeviceQueue; @@ -31,7 +32,7 @@ class CC_EXPORT VulkanInProcessContextProvider : public VulkanContextProvider { ~VulkanInProcessContextProvider() override; private: -#if defined(ENABLE_VULKAN) +#if BUILDFLAG(ENABLE_VULKAN) std::unique_ptr<gpu::VulkanDeviceQueue> device_queue_; #endif diff --git a/chromium/cc/output/vulkan_renderer.h b/chromium/cc/output/vulkan_renderer.h index 45b34a847be..32bed8a3626 100644 --- a/chromium/cc/output/vulkan_renderer.h +++ b/chromium/cc/output/vulkan_renderer.h @@ -7,7 +7,7 @@ #include "cc/base/cc_export.h" #include "cc/output/direct_renderer.h" -#include "ui/events/latency_info.h" +#include "ui/latency/latency_info.h" namespace cc { diff --git a/chromium/cc/paint/BUILD.gn b/chromium/cc/paint/BUILD.gn index a37d4a6dae5..c442f045829 100644 --- a/chromium/cc/paint/BUILD.gn +++ b/chromium/cc/paint/BUILD.gn @@ -7,21 +7,57 @@ import("//cc/cc.gni") cc_component("paint") { output_name = "cc_paint" sources = [ + "clip_display_item.cc", + "clip_display_item.h", + "clip_path_display_item.cc", + "clip_path_display_item.h", + "compositing_display_item.cc", + "compositing_display_item.h", + "discardable_image_map.cc", + "discardable_image_map.h", + "display_item.h", + "display_item_list.cc", + "display_item_list.h", + "draw_image.cc", + "draw_image.h", + "drawing_display_item.cc", + "drawing_display_item.h", + "filter_display_item.cc", + "filter_display_item.h", + "float_clip_display_item.cc", + "float_clip_display_item.h", + "image_id.h", + "largest_display_item.cc", + "largest_display_item.h", "paint_canvas.cc", "paint_canvas.h", "paint_export.h", "paint_flags.h", "paint_record.h", + "paint_recorder.cc", "paint_recorder.h", "paint_shader.h", - "paint_surface.h", + "skia_paint_canvas.cc", + "skia_paint_canvas.h", + "transform_display_item.cc", + "transform_display_item.h", ] defines = [ "CC_PAINT_IMPLEMENTATION=1" ] # cc/paint is intended to be a separate component from cc that can be - # included in Blink. This component should never include //base. + # included in Blink. This component should never publicly include + # anything that Blink core wouldn't include (e.g. base). public_deps = [ + "//cc/base", + "//cc/debug", "//skia", + "//ui/gfx:color_space", + "//ui/gfx:geometry_skia", + "//ui/gfx/geometry", + ] + + deps = [ + "//base", ] } diff --git a/chromium/cc/paint/clip_display_item.cc b/chromium/cc/paint/clip_display_item.cc new file mode 100644 index 00000000000..e2095c00b73 --- /dev/null +++ b/chromium/cc/paint/clip_display_item.cc @@ -0,0 +1,23 @@ +// 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/paint/clip_display_item.h" + +namespace cc { + +ClipDisplayItem::ClipDisplayItem(const gfx::Rect& clip_rect, + std::vector<SkRRect> rounded_clip_rects, + bool antialias) + : DisplayItem(CLIP), + clip_rect(clip_rect), + rounded_clip_rects(std::move(rounded_clip_rects)), + antialias(antialias) {} + +ClipDisplayItem::~ClipDisplayItem() = default; + +EndClipDisplayItem::EndClipDisplayItem() : DisplayItem(END_CLIP) {} + +EndClipDisplayItem::~EndClipDisplayItem() = default; + +} // namespace cc diff --git a/chromium/cc/paint/clip_display_item.h b/chromium/cc/paint/clip_display_item.h new file mode 100644 index 00000000000..a969d48dd5b --- /dev/null +++ b/chromium/cc/paint/clip_display_item.h @@ -0,0 +1,46 @@ +// 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_PAINT_CLIP_DISPLAY_ITEM_H_ +#define CC_PAINT_CLIP_DISPLAY_ITEM_H_ + +#include <stddef.h> + +#include <vector> + +#include "cc/paint/display_item.h" +#include "cc/paint/paint_export.h" +#include "third_party/skia/include/core/SkRRect.h" +#include "ui/gfx/geometry/rect.h" + +namespace cc { + +class CC_PAINT_EXPORT ClipDisplayItem : public DisplayItem { + public: + ClipDisplayItem(const gfx::Rect& clip_rect, + std::vector<SkRRect> rounded_clip_rects, + bool antialias); + ~ClipDisplayItem() override; + + size_t ExternalMemoryUsage() const { + return rounded_clip_rects.capacity() * sizeof(rounded_clip_rects[0]); + } + int ApproximateOpCount() const { return 1; } + + const gfx::Rect clip_rect; + const std::vector<SkRRect> rounded_clip_rects; + const bool antialias; +}; + +class CC_PAINT_EXPORT EndClipDisplayItem : public DisplayItem { + public: + EndClipDisplayItem(); + ~EndClipDisplayItem() override; + + int ApproximateOpCount() const { return 0; } +}; + +} // namespace cc + +#endif // CC_PAINT_CLIP_DISPLAY_ITEM_H_ diff --git a/chromium/cc/paint/clip_path_display_item.cc b/chromium/cc/paint/clip_path_display_item.cc new file mode 100644 index 00000000000..5882e5db928 --- /dev/null +++ b/chromium/cc/paint/clip_path_display_item.cc @@ -0,0 +1,19 @@ +// 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/paint/clip_path_display_item.h" + +namespace cc { + +ClipPathDisplayItem::ClipPathDisplayItem(const SkPath& clip_path, + bool antialias) + : DisplayItem(CLIP_PATH), clip_path(clip_path), antialias(antialias) {} + +ClipPathDisplayItem::~ClipPathDisplayItem() = default; + +EndClipPathDisplayItem::EndClipPathDisplayItem() : DisplayItem(END_CLIP_PATH) {} + +EndClipPathDisplayItem::~EndClipPathDisplayItem() = default; + +} // namespace cc diff --git a/chromium/cc/paint/clip_path_display_item.h b/chromium/cc/paint/clip_path_display_item.h new file mode 100644 index 00000000000..54de9992233 --- /dev/null +++ b/chromium/cc/paint/clip_path_display_item.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_PAINT_CLIP_PATH_DISPLAY_ITEM_H_ +#define CC_PAINT_CLIP_PATH_DISPLAY_ITEM_H_ + +#include <stddef.h> + +#include "cc/paint/display_item.h" +#include "cc/paint/paint_export.h" +#include "third_party/skia/include/core/SkPath.h" + +namespace cc { + +class CC_PAINT_EXPORT ClipPathDisplayItem : public DisplayItem { + public: + ClipPathDisplayItem(const SkPath& path, bool antialias); + ~ClipPathDisplayItem() override; + + size_t ExternalMemoryUsage() const { + // The size of SkPath's external storage is not currently accounted for (and + // may well be shared anyway). + return 0; + } + int ApproximateOpCount() const { return 1; } + + const SkPath clip_path; + const bool antialias; +}; + +class CC_PAINT_EXPORT EndClipPathDisplayItem : public DisplayItem { + public: + EndClipPathDisplayItem(); + ~EndClipPathDisplayItem() override; + + int ApproximateOpCount() const { return 0; } +}; + +} // namespace cc + +#endif // CC_PAINT_CLIP_PATH_DISPLAY_ITEM_H_ diff --git a/chromium/cc/paint/compositing_display_item.cc b/chromium/cc/paint/compositing_display_item.cc new file mode 100644 index 00000000000..9cda4580bdb --- /dev/null +++ b/chromium/cc/paint/compositing_display_item.cc @@ -0,0 +1,32 @@ +// 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/paint/compositing_display_item.h" + +#include "third_party/skia/include/core/SkColorFilter.h" + +namespace cc { + +CompositingDisplayItem::CompositingDisplayItem( + uint8_t alpha, + SkBlendMode xfermode, + SkRect* bounds, + sk_sp<SkColorFilter> color_filter, + bool lcd_text_requires_opaque_layer) + : DisplayItem(COMPOSITING), + alpha(alpha), + xfermode(xfermode), + has_bounds(!!bounds), + bounds(bounds ? SkRect(*bounds) : SkRect()), + color_filter(std::move(color_filter)), + lcd_text_requires_opaque_layer(lcd_text_requires_opaque_layer) {} + +CompositingDisplayItem::~CompositingDisplayItem() = default; + +EndCompositingDisplayItem::EndCompositingDisplayItem() + : DisplayItem(END_COMPOSITING) {} + +EndCompositingDisplayItem::~EndCompositingDisplayItem() = default; + +} // namespace cc diff --git a/chromium/cc/paint/compositing_display_item.h b/chromium/cc/paint/compositing_display_item.h new file mode 100644 index 00000000000..266ab4d2ea8 --- /dev/null +++ b/chromium/cc/paint/compositing_display_item.h @@ -0,0 +1,52 @@ +// 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_PAINT_COMPOSITING_DISPLAY_ITEM_H_ +#define CC_PAINT_COMPOSITING_DISPLAY_ITEM_H_ + +#include <stddef.h> + +#include "cc/paint/display_item.h" +#include "cc/paint/paint_export.h" +#include "third_party/skia/include/core/SkBlendMode.h" +#include "third_party/skia/include/core/SkColorFilter.h" +#include "third_party/skia/include/core/SkRect.h" +#include "third_party/skia/include/core/SkRefCnt.h" + +namespace cc { + +class CC_PAINT_EXPORT CompositingDisplayItem : public DisplayItem { + public: + CompositingDisplayItem(uint8_t alpha, + SkBlendMode xfermode, + SkRect* bounds, + sk_sp<SkColorFilter> color_filter, + bool lcd_text_requires_opaque_layer); + ~CompositingDisplayItem() override; + + size_t ExternalMemoryUsage() const { + // TODO(pdr): Include color_filter's memory here. + return 0; + } + int ApproximateOpCount() const { return 1; } + + const uint8_t alpha; + const SkBlendMode xfermode; + const bool has_bounds; + const SkRect bounds; + const sk_sp<SkColorFilter> color_filter; + const bool lcd_text_requires_opaque_layer; +}; + +class CC_PAINT_EXPORT EndCompositingDisplayItem : public DisplayItem { + public: + EndCompositingDisplayItem(); + ~EndCompositingDisplayItem() override; + + int ApproximateOpCount() const { return 0; } +}; + +} // namespace cc + +#endif // CC_PAINT_COMPOSITING_DISPLAY_ITEM_H_ diff --git a/chromium/cc/playback/discardable_image_map.cc b/chromium/cc/paint/discardable_image_map.cc index 7e1abd6640b..c1a3b57ccb5 100644 --- a/chromium/cc/playback/discardable_image_map.cc +++ b/chromium/cc/paint/discardable_image_map.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/discardable_image_map.h" +#include "cc/paint/discardable_image_map.h" #include <stddef.h> @@ -12,7 +12,7 @@ #include "base/containers/adapters.h" #include "base/memory/ptr_util.h" #include "cc/base/math_util.h" -#include "cc/playback/display_item_list.h" +#include "cc/paint/display_item_list.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/utils/SkNWayCanvas.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -140,7 +140,7 @@ class DiscardableImagesMetadataCanvas : public SkNWayCanvas { } SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override { - saved_paints_.push_back(*rec.fPaint); + saved_paints_.push_back(rec.fPaint ? *rec.fPaint : SkPaint()); return SkNWayCanvas::getSaveLayerStrategy(rec); } @@ -172,6 +172,7 @@ class DiscardableImagesMetadataCanvas : public SkNWayCanvas { return false; *paint_bounds = paint.computeFastBounds(*paint_bounds, paint_bounds); } + return true; } @@ -202,10 +203,27 @@ class DiscardableImagesMetadataCanvas : public SkNWayCanvas { src_rect.roundOut(&src_irect); gfx::Rect image_rect = SafeClampPaintRectToSize(paint_rect, canvas_size_); + // During raster, we use the device clip bounds on the canvas, which outsets + // the actual clip by 1 due to the possibility of antialiasing. Account for + // this here by outsetting the image rect by 1. Note that this only affects + // queries into the rtree, which will now return images that only touch the + // bounds of the query rect. + // + // Note that it's not sufficient for us to inset the device clip bounds at + // raster time, since we might be sending a larger-than-one-item display + // item to skia, which means that skia will internally determine whether to + // raster the picture (using device clip bounds that are outset). + image_rect.Inset(-1, -1); + + // The true target color space will be assigned when it is known, in + // GetDiscardableImagesInRect. + gfx::ColorSpace target_color_space; + (*image_id_to_rect_)[image->uniqueID()].Union(image_rect); - image_set_->push_back(std::make_pair( - DrawImage(std::move(image), src_irect, filter_quality, matrix), - image_rect)); + image_set_->push_back( + std::make_pair(DrawImage(std::move(image), src_irect, filter_quality, + matrix, target_color_space), + image_rect)); } // Currently this function only handles extracting images from SkImageShaders @@ -258,11 +276,15 @@ void DiscardableImageMap::EndGeneratingMetadata() { void DiscardableImageMap::GetDiscardableImagesInRect( const gfx::Rect& rect, float contents_scale, + const gfx::ColorSpace& target_color_space, std::vector<DrawImage>* images) const { std::vector<size_t> indices; images_rtree_.Search(rect, &indices); - for (size_t index : indices) - images->push_back(all_images_[index].first.ApplyScale(contents_scale)); + for (size_t index : indices) { + images->push_back(all_images_[index] + .first.ApplyScale(contents_scale) + .ApplyTargetColorSpace(target_color_space)); + } } gfx::Rect DiscardableImageMap::GetRectForImage(ImageId image_id) const { diff --git a/chromium/cc/playback/discardable_image_map.h b/chromium/cc/paint/discardable_image_map.h index abbf08bc0e7..0e006838834 100644 --- a/chromium/cc/playback/discardable_image_map.h +++ b/chromium/cc/paint/discardable_image_map.h @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_PLAYBACK_DISCARDABLE_IMAGE_MAP_H_ -#define CC_PLAYBACK_DISCARDABLE_IMAGE_MAP_H_ +#ifndef CC_PAINT_DISCARDABLE_IMAGE_MAP_H_ +#define CC_PAINT_DISCARDABLE_IMAGE_MAP_H_ #include <unordered_map> #include <utility> #include <vector> -#include "cc/base/cc_export.h" #include "cc/base/rtree.h" -#include "cc/playback/draw_image.h" -#include "cc/playback/image_id.h" +#include "cc/paint/draw_image.h" +#include "cc/paint/image_id.h" +#include "cc/paint/paint_export.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "ui/gfx/geometry/rect.h" @@ -26,9 +26,9 @@ SkRect MapRect(const SkMatrix& matrix, const SkRect& src); // This class is used for generating discardable images data (see DrawImage // for the type of data it stores). It allows the client to query a particular // rect and get back a list of DrawImages in that rect. -class CC_EXPORT DiscardableImageMap { +class CC_PAINT_EXPORT DiscardableImageMap { public: - class CC_EXPORT ScopedMetadataGenerator { + class CC_PAINT_EXPORT ScopedMetadataGenerator { public: ScopedMetadataGenerator(DiscardableImageMap* image_map, const gfx::Size& bounds); @@ -47,6 +47,7 @@ class CC_EXPORT DiscardableImageMap { bool empty() const { return all_images_.empty(); } void GetDiscardableImagesInRect(const gfx::Rect& rect, float contents_scale, + const gfx::ColorSpace& target_color_space, std::vector<DrawImage>* images) const; gfx::Rect GetRectForImage(ImageId image_id) const; @@ -65,4 +66,4 @@ class CC_EXPORT DiscardableImageMap { } // namespace cc -#endif // CC_PLAYBACK_DISCARDABLE_IMAGE_MAP_H_ +#endif // CC_PAINT_DISCARDABLE_IMAGE_MAP_H_ diff --git a/chromium/cc/playback/discardable_image_map_unittest.cc b/chromium/cc/paint/discardable_image_map_unittest.cc index b0e71fcffb7..eb687ad27df 100644 --- a/chromium/cc/playback/discardable_image_map_unittest.cc +++ b/chromium/cc/paint/discardable_image_map_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/discardable_image_map.h" +#include "cc/paint/discardable_image_map.h" #include <stddef.h> @@ -43,7 +43,11 @@ class DiscardableImageMapTest : public testing::Test { const DiscardableImageMap& image_map, const gfx::Rect& rect) { std::vector<DrawImage> draw_images; - image_map.GetDiscardableImagesInRect(rect, 1.f, &draw_images); + // Choose a not-SRGB-and-not-invalid target color space to verify that it + // is passed correctly to the resulting DrawImages. + gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateXYZD50(); + image_map.GetDiscardableImagesInRect(rect, 1.f, target_color_space, + &draw_images); std::vector<size_t> indices; image_map.images_rtree_.Search(rect, &indices); @@ -56,10 +60,24 @@ class DiscardableImageMapTest : public testing::Test { } EXPECT_EQ(draw_images.size(), position_draw_images.size()); - for (size_t i = 0; i < draw_images.size(); ++i) + for (size_t i = 0; i < draw_images.size(); ++i) { EXPECT_TRUE(draw_images[i].image() == position_draw_images[i].image); + EXPECT_EQ(draw_images[i].target_color_space(), target_color_space); + } return position_draw_images; } + + // Note that the image rtree outsets the images by 1, see the comment in + // DiscardableImagesMetadataCanvas::AddImage. + std::vector<gfx::Rect> InsetImageRects( + const std::vector<PositionScaleDrawImage>& images) { + std::vector<gfx::Rect> result; + for (auto& image : images) { + result.push_back(image.image_rect); + result.back().Inset(1, 1, 1, 1); + } + return result; + } }; TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectTest) { @@ -105,12 +123,13 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectTest) { for (int x = 0; x < 4; ++x) { std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect( image_map, gfx::Rect(x * 512, y * 512, 500, 500)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); if ((x + y) & 1) { EXPECT_EQ(1u, images.size()) << x << " " << y; - EXPECT_TRUE(images[0].image == discardable_image[y][x]) << x << " " - << y; + EXPECT_TRUE(images[0].image == discardable_image[y][x]) + << x << " " << y; EXPECT_EQ(gfx::Rect(x * 512 + 6, y * 512 + 6, 500, 500), - images[0].image_rect); + inset_rects[0]); EXPECT_EQ(images[0].image_rect, image_map.GetRectForImage(images[0].image->uniqueID())); } else { @@ -122,27 +141,26 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectTest) { // Capture 4 pixel refs. std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(image_map, gfx::Rect(512, 512, 2048, 2048)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); EXPECT_EQ(4u, images.size()); EXPECT_TRUE(images[0].image == discardable_image[1][2]); - EXPECT_EQ(gfx::Rect(2 * 512 + 6, 512 + 6, 500, 500), images[0].image_rect); + EXPECT_EQ(gfx::Rect(2 * 512 + 6, 512 + 6, 500, 500), inset_rects[0]); EXPECT_EQ(images[0].image_rect, image_map.GetRectForImage(images[0].image->uniqueID())); EXPECT_TRUE(images[1].image == discardable_image[2][1]); - EXPECT_EQ(gfx::Rect(512 + 6, 2 * 512 + 6, 500, 500), images[1].image_rect); + EXPECT_EQ(gfx::Rect(512 + 6, 2 * 512 + 6, 500, 500), inset_rects[1]); EXPECT_EQ(images[1].image_rect, image_map.GetRectForImage(images[1].image->uniqueID())); EXPECT_TRUE(images[2].image == discardable_image[2][3]); - EXPECT_EQ(gfx::Rect(3 * 512 + 6, 2 * 512 + 6, 500, 500), - images[2].image_rect); + EXPECT_EQ(gfx::Rect(3 * 512 + 6, 2 * 512 + 6, 500, 500), inset_rects[2]); EXPECT_EQ(images[2].image_rect, image_map.GetRectForImage(images[2].image->uniqueID())); EXPECT_TRUE(images[3].image == discardable_image[3][2]); - EXPECT_EQ(gfx::Rect(2 * 512 + 6, 3 * 512 + 6, 500, 500), - images[3].image_rect); + EXPECT_EQ(gfx::Rect(2 * 512 + 6, 3 * 512 + 6, 500, 500), inset_rects[3]); EXPECT_EQ(images[3].image_rect, image_map.GetRectForImage(images[3].image->uniqueID())); } @@ -192,12 +210,13 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectNonZeroLayer) { for (int x = 0; x < 4; ++x) { std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect( image_map, gfx::Rect(1024 + x * 512, y * 512, 500, 500)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); if ((x + y) & 1) { EXPECT_EQ(1u, images.size()) << x << " " << y; - EXPECT_TRUE(images[0].image == discardable_image[y][x]) << x << " " - << y; + EXPECT_TRUE(images[0].image == discardable_image[y][x]) + << x << " " << y; EXPECT_EQ(gfx::Rect(1024 + x * 512 + 6, y * 512 + 6, 500, 500), - images[0].image_rect); + inset_rects[0]); EXPECT_EQ(images[0].image_rect, image_map.GetRectForImage(images[0].image->uniqueID())); } else { @@ -209,29 +228,28 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectNonZeroLayer) { { std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect( image_map, gfx::Rect(1024 + 512, 512, 2048, 2048)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); EXPECT_EQ(4u, images.size()); EXPECT_TRUE(images[0].image == discardable_image[1][2]); - EXPECT_EQ(gfx::Rect(1024 + 2 * 512 + 6, 512 + 6, 500, 500), - images[0].image_rect); + EXPECT_EQ(gfx::Rect(1024 + 2 * 512 + 6, 512 + 6, 500, 500), inset_rects[0]); EXPECT_EQ(images[0].image_rect, image_map.GetRectForImage(images[0].image->uniqueID())); EXPECT_TRUE(images[1].image == discardable_image[2][1]); - EXPECT_EQ(gfx::Rect(1024 + 512 + 6, 2 * 512 + 6, 500, 500), - images[1].image_rect); + EXPECT_EQ(gfx::Rect(1024 + 512 + 6, 2 * 512 + 6, 500, 500), inset_rects[1]); EXPECT_EQ(images[1].image_rect, image_map.GetRectForImage(images[1].image->uniqueID())); EXPECT_TRUE(images[2].image == discardable_image[2][3]); EXPECT_EQ(gfx::Rect(1024 + 3 * 512 + 6, 2 * 512 + 6, 500, 500), - images[2].image_rect); + inset_rects[2]); EXPECT_EQ(images[2].image_rect, image_map.GetRectForImage(images[2].image->uniqueID())); EXPECT_TRUE(images[3].image == discardable_image[3][2]); EXPECT_EQ(gfx::Rect(1024 + 2 * 512 + 6, 3 * 512 + 6, 500, 500), - images[3].image_rect); + inset_rects[3]); EXPECT_EQ(images[3].image_rect, image_map.GetRectForImage(images[3].image->uniqueID())); } @@ -308,12 +326,13 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectOnePixelQuery) { for (int x = 0; x < 4; ++x) { std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect( image_map, gfx::Rect(x * 512 + 256, y * 512 + 256, 1, 1)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); if ((x + y) & 1) { EXPECT_EQ(1u, images.size()) << x << " " << y; - EXPECT_TRUE(images[0].image == discardable_image[y][x]) << x << " " - << y; + EXPECT_TRUE(images[0].image == discardable_image[y][x]) + << x << " " << y; EXPECT_EQ(gfx::Rect(x * 512 + 6, y * 512 + 6, 500, 500), - images[0].image_rect); + inset_rects[0]); EXPECT_EQ(images[0].image_rect, image_map.GetRectForImage(images[0].image->uniqueID())); } else { @@ -346,9 +365,10 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectMassiveImage) { } std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(image_map, gfx::Rect(0, 0, 1, 1)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); EXPECT_EQ(1u, images.size()); EXPECT_TRUE(images[0].image == discardable_image); - EXPECT_EQ(gfx::Rect(0, 0, 2048, 2048), images[0].image_rect); + EXPECT_EQ(gfx::Rect(0, 0, 2048, 2048), inset_rects[0]); EXPECT_EQ(images[0].image_rect, image_map.GetRectForImage(images[0].image->uniqueID())); } @@ -379,6 +399,29 @@ TEST_F(DiscardableImageMapTest, PaintDestroyedWhileImageIsDrawn) { EXPECT_TRUE(images[0].image == discardable_image); } +TEST_F(DiscardableImageMapTest, NullPaintOnSaveLayer) { + gfx::Rect visible_rect(2048, 2048); + FakeContentLayerClient content_layer_client; + content_layer_client.set_bounds(visible_rect.size()); + + sk_sp<SkImage> discardable_image = CreateDiscardableImage(gfx::Size(10, 10)); + + DiscardableImageMap image_map; + { + DiscardableImageMap::ScopedMetadataGenerator generator(&image_map, + visible_rect.size()); + SkPaint* null_paint = nullptr; + generator.canvas()->saveLayer(gfx::RectToSkRect(visible_rect), null_paint); + generator.canvas()->drawImage(discardable_image, 0, 0, nullptr); + generator.canvas()->restore(); + } + + std::vector<PositionScaleDrawImage> images = + GetDiscardableImagesInRect(image_map, gfx::Rect(0, 0, 1, 1)); + EXPECT_EQ(1u, images.size()); + EXPECT_TRUE(images[0].image == discardable_image); +} + TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectMaxImage) { gfx::Rect visible_rect(2048, 2048); FakeContentLayerClient content_layer_client; @@ -403,9 +446,10 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectMaxImage) { } std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(image_map, gfx::Rect(42, 42, 1, 1)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); EXPECT_EQ(1u, images.size()); EXPECT_TRUE(images[0].image == discardable_image); - EXPECT_EQ(gfx::Rect(42, 42, 2006, 2006), images[0].image_rect); + EXPECT_EQ(gfx::Rect(42, 42, 2006, 2006), inset_rects[0]); EXPECT_EQ(images[0].image_rect, image_map.GetRectForImage(images[0].image->uniqueID())); } @@ -444,14 +488,15 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectMaxImageMaxLayer) { } std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(image_map, gfx::Rect(0, 0, 1, 1)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); EXPECT_EQ(1u, images.size()); - EXPECT_EQ(gfx::Rect(0, 0, dimension, dimension), images[0].image_rect); + EXPECT_EQ(gfx::Rect(0, 0, dimension, dimension), inset_rects[0]); images = GetDiscardableImagesInRect(image_map, gfx::Rect(10000, 0, 1, 1)); + inset_rects = InsetImageRects(images); EXPECT_EQ(2u, images.size()); - EXPECT_EQ(gfx::Rect(10000, 0, dimension - 10000, dimension), - images[1].image_rect); - EXPECT_EQ(gfx::Rect(0, 0, dimension, dimension), images[0].image_rect); + EXPECT_EQ(gfx::Rect(10000, 0, dimension - 10000, dimension), inset_rects[1]); + EXPECT_EQ(gfx::Rect(0, 0, dimension, dimension), inset_rects[0]); // Since we adjust negative offsets before using ToEnclosingRect, the expected // width will be converted to float, which means that we lose some precision. @@ -459,12 +504,12 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectMaxImageMaxLayer) { // back to int. int expected10k = static_cast<int>(static_cast<float>(dimension - 10000)); images = GetDiscardableImagesInRect(image_map, gfx::Rect(0, 500, 1, 1)); + inset_rects = InsetImageRects(images); EXPECT_EQ(2u, images.size()); - EXPECT_EQ(gfx::Rect(0, 500, expected10k, dimension - 500), - images[1].image_rect); - EXPECT_EQ(gfx::Rect(0, 0, dimension, dimension), images[0].image_rect); + EXPECT_EQ(gfx::Rect(0, 500, expected10k, dimension - 500), inset_rects[1]); + EXPECT_EQ(gfx::Rect(0, 0, dimension, dimension), inset_rects[0]); - EXPECT_EQ(gfx::Rect(0, 0, dimension, dimension), + EXPECT_EQ(images[0].image_rect, image_map.GetRectForImage(discardable_image->uniqueID())); } @@ -498,24 +543,28 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesRectInBounds) { } std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(image_map, gfx::Rect(0, 0, 1, 1)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); EXPECT_EQ(1u, images.size()); - EXPECT_EQ(gfx::Rect(0, 0, 90, 89), images[0].image_rect); + EXPECT_EQ(gfx::Rect(0, 0, 90, 89), inset_rects[0]); images = GetDiscardableImagesInRect(image_map, gfx::Rect(999, 999, 1, 1)); + inset_rects = InsetImageRects(images); EXPECT_EQ(1u, images.size()); - EXPECT_EQ(gfx::Rect(950, 951, 50, 49), images[0].image_rect); + EXPECT_EQ(gfx::Rect(950, 951, 50, 49), inset_rects[0]); images = GetDiscardableImagesInRect(image_map, gfx::Rect(0, 500, 1, 1)); + inset_rects = InsetImageRects(images); EXPECT_EQ(1u, images.size()); - EXPECT_EQ(gfx::Rect(0, 500, 1000, 100), images[0].image_rect); + EXPECT_EQ(gfx::Rect(0, 500, 1000, 100), inset_rects[0]); gfx::Rect discardable_image_rect; discardable_image_rect.Union(gfx::Rect(0, 0, 90, 89)); discardable_image_rect.Union(gfx::Rect(950, 951, 50, 49)); + discardable_image_rect.Inset(-1, -1, -1, -1); EXPECT_EQ(discardable_image_rect, image_map.GetRectForImage(discardable_image->uniqueID())); - EXPECT_EQ(gfx::Rect(0, 500, 1000, 100), + EXPECT_EQ(gfx::Rect(-1, 499, 1002, 102), image_map.GetRectForImage(long_discardable_image->uniqueID())); } @@ -570,12 +619,13 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInShader) { for (int x = 0; x < 4; ++x) { std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect( image_map, gfx::Rect(x * 512, y * 512, 500, 500)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); if ((x + y) & 1) { EXPECT_EQ(1u, images.size()) << x << " " << y; - EXPECT_TRUE(images[0].image == discardable_image[y][x]) << x << " " - << y; + EXPECT_TRUE(images[0].image == discardable_image[y][x]) + << x << " " << y; EXPECT_EQ(gfx::Rect(x * 512 + 6, y * 512 + 6, 500, 500), - images[0].image_rect); + inset_rects[0]); EXPECT_EQ(std::max(x * 0.5f, kMinScale), images[0].scale.fWidth); EXPECT_EQ(std::max(y * 0.5f, kMinScale), images[0].scale.fHeight); } else { @@ -587,17 +637,16 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInShader) { // Capture 4 pixel refs. std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(image_map, gfx::Rect(512, 512, 2048, 2048)); + std::vector<gfx::Rect> inset_rects = InsetImageRects(images); EXPECT_EQ(4u, images.size()); EXPECT_TRUE(images[0].image == discardable_image[1][2]); - EXPECT_EQ(gfx::Rect(2 * 512 + 6, 512 + 6, 500, 500), images[0].image_rect); + EXPECT_EQ(gfx::Rect(2 * 512 + 6, 512 + 6, 500, 500), inset_rects[0]); EXPECT_TRUE(images[1].image == discardable_image[2][1]); - EXPECT_EQ(gfx::Rect(512 + 6, 2 * 512 + 6, 500, 500), images[1].image_rect); + EXPECT_EQ(gfx::Rect(512 + 6, 2 * 512 + 6, 500, 500), inset_rects[1]); EXPECT_TRUE(images[2].image == discardable_image[2][3]); - EXPECT_EQ(gfx::Rect(3 * 512 + 6, 2 * 512 + 6, 500, 500), - images[2].image_rect); + EXPECT_EQ(gfx::Rect(3 * 512 + 6, 2 * 512 + 6, 500, 500), inset_rects[2]); EXPECT_TRUE(images[3].image == discardable_image[3][2]); - EXPECT_EQ(gfx::Rect(2 * 512 + 6, 3 * 512 + 6, 500, 500), - images[3].image_rect); + EXPECT_EQ(gfx::Rect(2 * 512 + 6, 3 * 512 + 6, 500, 500), inset_rects[3]); } } // namespace cc diff --git a/chromium/cc/playback/display_item.h b/chromium/cc/paint/display_item.h index 5065a4ee803..74a3c5965de 100644 --- a/chromium/cc/playback/display_item.h +++ b/chromium/cc/paint/display_item.h @@ -2,24 +2,25 @@ // 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_H_ -#define CC_PLAYBACK_DISPLAY_ITEM_H_ +#ifndef CC_PAINT_DISPLAY_ITEM_H_ +#define CC_PAINT_DISPLAY_ITEM_H_ #include <stddef.h> #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/debug/traced_value.h" +#include "cc/paint/paint_export.h" #include "third_party/skia/include/core/SkPicture.h" #include "ui/gfx/geometry/rect.h" -class SkCanvas; - namespace cc { -class CC_EXPORT DisplayItem { +class CC_PAINT_EXPORT DisplayItem { public: + virtual ~DisplayItem() = default; + enum Type { CLIP, END_CLIP, @@ -35,22 +36,12 @@ class CC_EXPORT DisplayItem { TRANSFORM, END_TRANSFORM, }; - - virtual ~DisplayItem() {} - - virtual void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const = 0; - virtual void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const = 0; - - Type type() const { return type_; } + const Type type; protected: - explicit DisplayItem(Type type) : type_(type) {} - - const Type type_; + explicit DisplayItem(Type type) : type(type) {} }; } // namespace cc -#endif // CC_PLAYBACK_DISPLAY_ITEM_H_ +#endif // CC_PAINT_DISPLAY_ITEM_H_ diff --git a/chromium/cc/paint/display_item_list.cc b/chromium/cc/paint/display_item_list.cc new file mode 100644 index 00000000000..83599482f53 --- /dev/null +++ b/chromium/cc/paint/display_item_list.cc @@ -0,0 +1,501 @@ +// 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/paint/display_item_list.h" + +#include <stddef.h> + +#include <string> + +#include "base/memory/ptr_util.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" +#include "cc/base/math_util.h" +#include "cc/base/render_surface_filters.h" +#include "cc/debug/picture_debug_util.h" +#include "cc/paint/clip_display_item.h" +#include "cc/paint/clip_path_display_item.h" +#include "cc/paint/compositing_display_item.h" +#include "cc/paint/drawing_display_item.h" +#include "cc/paint/filter_display_item.h" +#include "cc/paint/float_clip_display_item.h" +#include "cc/paint/largest_display_item.h" +#include "cc/paint/transform_display_item.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkImageFilter.h" +#include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gfx/skia_util.h" + +namespace cc { + +namespace { + +// We don't perform per-layer solid color analysis when there are too many skia +// operations. +const int kOpCountThatIsOkToAnalyze = 10; + +bool GetCanvasClipBounds(SkCanvas* canvas, gfx::Rect* clip_bounds) { + SkRect canvas_clip_bounds; + if (!canvas->getLocalClipBounds(&canvas_clip_bounds)) + return false; + *clip_bounds = ToEnclosingRect(gfx::SkRectToRectF(canvas_clip_bounds)); + return true; +} + +const int kDefaultNumDisplayItemsToReserve = 100; + +NOINLINE DISABLE_CFI_PERF void RasterItem(const DisplayItem& base_item, + SkCanvas* canvas, + SkPicture::AbortCallback* callback) { + switch (base_item.type) { + case DisplayItem::CLIP: { + const auto& item = static_cast<const ClipDisplayItem&>(base_item); + canvas->save(); + canvas->clipRect(gfx::RectToSkRect(item.clip_rect), item.antialias); + for (const auto& rrect : item.rounded_clip_rects) { + if (rrect.isRect()) { + canvas->clipRect(rrect.rect(), item.antialias); + } else { + canvas->clipRRect(rrect, item.antialias); + } + } + break; + } + case DisplayItem::END_CLIP: + canvas->restore(); + break; + case DisplayItem::CLIP_PATH: { + const auto& item = static_cast<const ClipPathDisplayItem&>(base_item); + canvas->save(); + canvas->clipPath(item.clip_path, item.antialias); + break; + } + case DisplayItem::END_CLIP_PATH: + canvas->restore(); + break; + case DisplayItem::COMPOSITING: { + const auto& item = static_cast<const CompositingDisplayItem&>(base_item); + SkPaint paint; + paint.setBlendMode(item.xfermode); + paint.setAlpha(item.alpha); + paint.setColorFilter(item.color_filter); + const SkRect* bounds = item.has_bounds ? &item.bounds : nullptr; + if (item.lcd_text_requires_opaque_layer) + canvas->saveLayer(bounds, &paint); + else + canvas->saveLayerPreserveLCDTextRequests(bounds, &paint); + break; + } + case DisplayItem::END_COMPOSITING: + canvas->restore(); + break; + case DisplayItem::DRAWING: { + const auto& item = static_cast<const DrawingDisplayItem&>(base_item); + if (canvas->quickReject(item.picture->cullRect())) + break; + + // SkPicture always does a wrapping save/restore on the canvas, so it is + // not necessary here. + item.picture->playback(canvas, callback); + break; + } + case DisplayItem::FLOAT_CLIP: { + const auto& item = static_cast<const FloatClipDisplayItem&>(base_item); + canvas->save(); + canvas->clipRect(gfx::RectFToSkRect(item.clip_rect)); + break; + } + case DisplayItem::END_FLOAT_CLIP: + canvas->restore(); + break; + case DisplayItem::FILTER: { + const auto& item = static_cast<const FilterDisplayItem&>(base_item); + canvas->save(); + canvas->translate(item.origin.x(), item.origin.y()); + + sk_sp<SkImageFilter> image_filter = + RenderSurfaceFilters::BuildImageFilter(item.filters, + item.bounds.size()); + SkRect boundaries = RectFToSkRect(item.bounds); + boundaries.offset(-item.origin.x(), -item.origin.y()); + + SkPaint paint; + paint.setBlendMode(SkBlendMode::kSrcOver); + paint.setImageFilter(std::move(image_filter)); + canvas->saveLayer(&boundaries, &paint); + + canvas->translate(-item.origin.x(), -item.origin.y()); + break; + } + case DisplayItem::END_FILTER: + canvas->restore(); + canvas->restore(); + break; + case DisplayItem::TRANSFORM: { + const auto& item = static_cast<const TransformDisplayItem&>(base_item); + canvas->save(); + if (!item.transform.IsIdentity()) + canvas->concat(item.transform.matrix()); + break; + } + case DisplayItem::END_TRANSFORM: + canvas->restore(); + break; + } +} + +} // namespace + +DisplayItemList::DisplayItemList() + : items_(LargestDisplayItemSize(), + LargestDisplayItemSize() * kDefaultNumDisplayItemsToReserve) {} + +DisplayItemList::~DisplayItemList() = default; + +void DisplayItemList::Raster(SkCanvas* canvas, + SkPicture::AbortCallback* callback, + const gfx::Rect& canvas_target_playback_rect, + float contents_scale) const { + canvas->save(); + if (!canvas_target_playback_rect.IsEmpty()) { + // canvas_target_playback_rect is specified in device space. We can't + // use clipRect because canvas CTM will be applied on it. Use clipRegion + // instead because it ignores canvas CTM. + SkRegion device_clip; + device_clip.setRect(gfx::RectToSkIRect(canvas_target_playback_rect)); + canvas->clipRegion(device_clip); + } + canvas->scale(contents_scale, contents_scale); + Raster(canvas, callback); + canvas->restore(); +} + +void DisplayItemList::Raster(SkCanvas* canvas, + SkPicture::AbortCallback* callback) const { + gfx::Rect canvas_playback_rect; + if (!GetCanvasClipBounds(canvas, &canvas_playback_rect)) + return; + + std::vector<size_t> indices; + rtree_.Search(canvas_playback_rect, &indices); + for (size_t index : indices) { + RasterItem(items_[index], canvas, callback); + + // We use a callback during solid color analysis on the compositor thread to + // break out early. Since we're handling a sequence of pictures via rtree + // query results ourselves, we have to respect the callback and early out. + if (callback && callback->abort()) + break; + } +} + +void DisplayItemList::GrowCurrentBeginItemVisualRect( + const gfx::Rect& visual_rect) { + if (!begin_item_indices_.empty()) + visual_rects_[begin_item_indices_.back()].Union(visual_rect); +} + +void DisplayItemList::Finalize() { + TRACE_EVENT0("cc", "DisplayItemList::Finalize"); + DCHECK(items_.size() == visual_rects_.size()) + << "items.size() " << items_.size() << " visual_rects.size() " + << visual_rects_.size(); + rtree_.Build(visual_rects_); + + if (!retain_visual_rects_) + // This clears both the vector and the vector's capacity, since + // visual_rects won't be used anymore. + std::vector<gfx::Rect>().swap(visual_rects_); +} + +bool DisplayItemList::IsSuitableForGpuRasterization() const { + // TODO(wkorman): 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. See crbug.com/513016. + return all_items_are_suitable_for_gpu_rasterization_; +} + +int DisplayItemList::ApproximateOpCount() const { + return approximate_op_count_; +} + +size_t DisplayItemList::ApproximateMemoryUsage() const { + size_t memory_usage = sizeof(*this); + + size_t external_memory_usage = 0; + for (const auto& item : items_) { + size_t bytes = 0; + switch (item.type) { + case DisplayItem::CLIP: + bytes = static_cast<const ClipDisplayItem&>(item).ExternalMemoryUsage(); + break; + case DisplayItem::CLIP_PATH: + bytes = + static_cast<const ClipPathDisplayItem&>(item).ExternalMemoryUsage(); + break; + case DisplayItem::COMPOSITING: + bytes = static_cast<const CompositingDisplayItem&>(item) + .ExternalMemoryUsage(); + break; + case DisplayItem::DRAWING: + bytes = + static_cast<const DrawingDisplayItem&>(item).ExternalMemoryUsage(); + break; + case DisplayItem::FLOAT_CLIP: + bytes = static_cast<const FloatClipDisplayItem&>(item) + .ExternalMemoryUsage(); + break; + case DisplayItem::FILTER: + bytes = + static_cast<const FilterDisplayItem&>(item).ExternalMemoryUsage(); + break; + case DisplayItem::TRANSFORM: + bytes = static_cast<const TransformDisplayItem&>(item) + .ExternalMemoryUsage(); + break; + case DisplayItem::END_CLIP: + case DisplayItem::END_CLIP_PATH: + case DisplayItem::END_COMPOSITING: + case DisplayItem::END_FLOAT_CLIP: + case DisplayItem::END_FILTER: + case DisplayItem::END_TRANSFORM: + break; + } + external_memory_usage += bytes; + } + + // Memory outside this class due to |items_|. + memory_usage += items_.GetCapacityInBytes() + external_memory_usage; + + // TODO(jbroman): Does anything else owned by this class substantially + // contribute to memory usage? + // TODO(vmpstr): Probably DiscardableImageMap is worth counting here. + + return memory_usage; +} + +bool DisplayItemList::ShouldBeAnalyzedForSolidColor() const { + return ApproximateOpCount() <= kOpCountThatIsOkToAnalyze; +} + +void DisplayItemList::EmitTraceSnapshot() const { + bool include_items; + TRACE_EVENT_CATEGORY_GROUP_ENABLED( + TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items"), &include_items); + 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, CreateTracedValue(include_items)); +} + +std::unique_ptr<base::trace_event::TracedValue> +DisplayItemList::CreateTracedValue(bool include_items) const { + auto state = base::MakeUnique<base::trace_event::TracedValue>(); + state->BeginDictionary("params"); + + if (include_items) { + state->BeginArray("items"); + + auto visual_rects_it = visual_rects_.begin(); + for (const DisplayItem& base_item : items_) { + gfx::Rect visual_rect; + if (visual_rects_it != visual_rects_.end()) { + visual_rect = *visual_rects_it; + ++visual_rects_it; + } + + switch (base_item.type) { + case DisplayItem::CLIP: { + const auto& item = static_cast<const ClipDisplayItem&>(base_item); + std::string output = + base::StringPrintf("ClipDisplayItem rect: [%s] visualRect: [%s]", + item.clip_rect.ToString().c_str(), + visual_rect.ToString().c_str()); + for (const SkRRect& rounded_rect : item.rounded_clip_rects) { + base::StringAppendF( + &output, " rounded_rect: [rect: [%s]", + gfx::SkRectToRectF(rounded_rect.rect()).ToString().c_str()); + base::StringAppendF(&output, " radii: ["); + SkVector upper_left_radius = + rounded_rect.radii(SkRRect::kUpperLeft_Corner); + base::StringAppendF(&output, "[%f,%f],", upper_left_radius.x(), + upper_left_radius.y()); + SkVector upper_right_radius = + rounded_rect.radii(SkRRect::kUpperRight_Corner); + base::StringAppendF(&output, " [%f,%f],", upper_right_radius.x(), + upper_right_radius.y()); + SkVector lower_right_radius = + rounded_rect.radii(SkRRect::kLowerRight_Corner); + base::StringAppendF(&output, " [%f,%f],", lower_right_radius.x(), + lower_right_radius.y()); + SkVector lower_left_radius = + rounded_rect.radii(SkRRect::kLowerLeft_Corner); + base::StringAppendF(&output, " [%f,%f]]", lower_left_radius.x(), + lower_left_radius.y()); + } + state->AppendString(output); + break; + } + case DisplayItem::END_CLIP: + state->AppendString( + base::StringPrintf("EndClipDisplayItem visualRect: [%s]", + visual_rect.ToString().c_str())); + break; + case DisplayItem::CLIP_PATH: { + const auto& item = static_cast<const ClipPathDisplayItem&>(base_item); + state->AppendString(base::StringPrintf( + "ClipPathDisplayItem length: %d visualRect: [%s]", + item.clip_path.countPoints(), visual_rect.ToString().c_str())); + break; + } + case DisplayItem::END_CLIP_PATH: + state->AppendString( + base::StringPrintf("EndClipPathDisplayItem visualRect: [%s]", + visual_rect.ToString().c_str())); + break; + case DisplayItem::COMPOSITING: { + const auto& item = + static_cast<const CompositingDisplayItem&>(base_item); + std::string output = base::StringPrintf( + "CompositingDisplayItem alpha: %d, xfermode: %d, visualRect: " + "[%s]", + item.alpha, static_cast<int>(item.xfermode), + visual_rect.ToString().c_str()); + if (item.has_bounds) { + base::StringAppendF( + &output, ", bounds: [%s]", + gfx::SkRectToRectF(item.bounds).ToString().c_str()); + } + state->AppendString(output); + break; + } + case DisplayItem::END_COMPOSITING: + state->AppendString( + base::StringPrintf("EndCompositingDisplayItem visualRect: [%s]", + visual_rect.ToString().c_str())); + break; + case DisplayItem::DRAWING: { + const auto& item = static_cast<const DrawingDisplayItem&>(base_item); + state->BeginDictionary(); + state->SetString("name", "DrawingDisplayItem"); + + state->BeginArray("visualRect"); + state->AppendInteger(visual_rect.x()); + state->AppendInteger(visual_rect.y()); + state->AppendInteger(visual_rect.width()); + state->AppendInteger(visual_rect.height()); + state->EndArray(); + + state->BeginArray("cullRect"); + state->AppendInteger(item.picture->cullRect().x()); + state->AppendInteger(item.picture->cullRect().y()); + state->AppendInteger(item.picture->cullRect().width()); + state->AppendInteger(item.picture->cullRect().height()); + state->EndArray(); + + std::string b64_picture; + PictureDebugUtil::SerializeAsBase64(ToSkPicture(item.picture).get(), + &b64_picture); + state->SetString("skp64", b64_picture); + state->EndDictionary(); + break; + } + case DisplayItem::FILTER: { + const auto& item = static_cast<const FilterDisplayItem&>(base_item); + state->AppendString(base::StringPrintf( + "FilterDisplayItem bounds: [%s] visualRect: [%s]", + item.bounds.ToString().c_str(), visual_rect.ToString().c_str())); + break; + } + case DisplayItem::END_FILTER: + state->AppendString( + base::StringPrintf("EndFilterDisplayItem visualRect: [%s]", + visual_rect.ToString().c_str())); + break; + case DisplayItem::FLOAT_CLIP: { + const auto& item = + static_cast<const FloatClipDisplayItem&>(base_item); + state->AppendString(base::StringPrintf( + "FloatClipDisplayItem rect: [%s] visualRect: [%s]", + item.clip_rect.ToString().c_str(), + visual_rect.ToString().c_str())); + break; + } + case DisplayItem::END_FLOAT_CLIP: + state->AppendString( + base::StringPrintf("EndFloatClipDisplayItem visualRect: [%s]", + visual_rect.ToString().c_str())); + break; + case DisplayItem::TRANSFORM: { + const auto& item = + static_cast<const TransformDisplayItem&>(base_item); + state->AppendString(base::StringPrintf( + "TransformDisplayItem transform: [%s] visualRect: [%s]", + item.transform.ToString().c_str(), + visual_rect.ToString().c_str())); + break; + } + case DisplayItem::END_TRANSFORM: + state->AppendString( + base::StringPrintf("EndTransformDisplayItem visualRect: [%s]", + visual_rect.ToString().c_str())); + break; + } + } + state->EndArray(); // "items". + } + + MathUtil::AddToTracedValue("layer_rect", rtree_.GetBounds(), state.get()); + state->EndDictionary(); // "params". + + { + SkPictureRecorder recorder; + gfx::Rect bounds = rtree_.GetBounds(); + SkCanvas* canvas = recorder.beginRecording(bounds.width(), bounds.height()); + canvas->translate(-bounds.x(), -bounds.y()); + canvas->clipRect(gfx::RectToSkRect(bounds)); + Raster(canvas, nullptr, gfx::Rect(), 1.f); + sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); + + std::string b64_picture; + PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture); + state->SetString("skp64", b64_picture); + } + + return state; +} + +void DisplayItemList::GenerateDiscardableImagesMetadata() { + // This should be only called once. + DCHECK(image_map_.empty()); + + gfx::Rect bounds = rtree_.GetBounds(); + DiscardableImageMap::ScopedMetadataGenerator generator( + &image_map_, gfx::Size(bounds.right(), bounds.bottom())); + auto* canvas = generator.canvas(); + for (const auto& item : items_) + RasterItem(item, canvas, nullptr); +} + +void DisplayItemList::GetDiscardableImagesInRect( + const gfx::Rect& rect, + float contents_scale, + const gfx::ColorSpace& target_color_space, + std::vector<DrawImage>* images) { + image_map_.GetDiscardableImagesInRect(rect, contents_scale, + target_color_space, images); +} + +gfx::Rect DisplayItemList::GetRectForImage(ImageId image_id) const { + return image_map_.GetRectForImage(image_id); +} + +} // namespace cc diff --git a/chromium/cc/playback/display_item_list.h b/chromium/cc/paint/display_item_list.h index 5e1ea3d6a1a..b65707dc6e0 100644 --- a/chromium/cc/playback/display_item_list.h +++ b/chromium/cc/paint/display_item_list.h @@ -2,8 +2,8 @@ // 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_H_ -#define CC_PLAYBACK_DISPLAY_ITEM_LIST_H_ +#ifndef CC_PAINT_DISPLAY_ITEM_LIST_H_ +#define CC_PAINT_DISPLAY_ITEM_LIST_H_ #include <stddef.h> @@ -14,12 +14,12 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/trace_event/trace_event.h" -#include "cc/base/cc_export.h" #include "cc/base/contiguous_container.h" #include "cc/base/rtree.h" -#include "cc/playback/discardable_image_map.h" -#include "cc/playback/display_item.h" -#include "cc/playback/image_id.h" +#include "cc/paint/discardable_image_map.h" +#include "cc/paint/display_item.h" +#include "cc/paint/image_id.h" +#include "cc/paint/paint_export.h" #include "third_party/skia/include/core/SkPicture.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/rect.h" @@ -27,10 +27,16 @@ class SkCanvas; +namespace base { +namespace trace_event { +class TracedValue; +} +} + namespace cc { class DisplayItem; -class CC_EXPORT DisplayItemList +class CC_PAINT_EXPORT DisplayItemList : public base::RefCountedThreadSafe<DisplayItemList> { public: DisplayItemList(); @@ -43,7 +49,6 @@ class CC_EXPORT DisplayItemList void Raster(SkCanvas* canvas, SkPicture::AbortCallback* callback) const; - // Because processing happens in these CreateAndAppend functions, all the set // up for the item should be done via the args, which is why the return type // needs to be const, to prevent set-after-processing mistakes. @@ -63,18 +68,18 @@ class CC_EXPORT DisplayItemList const DisplayItemType& CreateAndAppendPairedBeginItemWithVisualRect( const gfx::Rect& visual_rect, Args&&... args) { - size_t item_index = inputs_.visual_rects.size(); - inputs_.visual_rects.push_back(visual_rect); - inputs_.begin_item_indices.push_back(item_index); + size_t item_index = visual_rects_.size(); + visual_rects_.push_back(visual_rect); + begin_item_indices_.push_back(item_index); return AllocateAndConstruct<DisplayItemType>(std::forward<Args>(args)...); } template <typename DisplayItemType, typename... Args> const DisplayItemType& CreateAndAppendPairedEndItem(Args&&... args) { - DCHECK(!inputs_.begin_item_indices.empty()); - size_t last_begin_index = inputs_.begin_item_indices.back(); - inputs_.begin_item_indices.pop_back(); + DCHECK(!begin_item_indices_.empty()); + size_t last_begin_index = begin_item_indices_.back(); + begin_item_indices_.pop_back(); // Note that we are doing two separate things below: // @@ -98,11 +103,11 @@ class CC_EXPORT DisplayItemList // overhead. // Ending bounds match the starting bounds. - inputs_.visual_rects.push_back(inputs_.visual_rects[last_begin_index]); + visual_rects_.push_back(visual_rects_[last_begin_index]); // The block that ended needs to be included in the bounds of the enclosing // block. - GrowCurrentBeginItemVisualRect(inputs_.visual_rects[last_begin_index]); + GrowCurrentBeginItemVisualRect(visual_rects_[last_begin_index]); return AllocateAndConstruct<DisplayItemType>(std::forward<Args>(args)...); } @@ -111,7 +116,7 @@ class CC_EXPORT DisplayItemList const DisplayItemType& CreateAndAppendDrawingItem( const gfx::Rect& visual_rect, Args&&... args) { - inputs_.visual_rects.push_back(visual_rect); + visual_rects_.push_back(visual_rect); GrowCurrentBeginItemVisualRect(visual_rect); return AllocateAndConstruct<DisplayItemType>(std::forward<Args>(args)...); @@ -122,7 +127,7 @@ class CC_EXPORT DisplayItemList void Finalize(); void SetIsSuitableForGpuRasterization(bool is_suitable) { - inputs_.all_items_are_suitable_for_gpu_rasterization = is_suitable; + all_items_are_suitable_for_gpu_rasterization_ = is_suitable; } bool IsSuitableForGpuRasterization() const; @@ -130,14 +135,12 @@ class CC_EXPORT DisplayItemList size_t ApproximateMemoryUsage() const; bool ShouldBeAnalyzedForSolidColor() const; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue( - bool include_items) const; - void EmitTraceSnapshot() const; void GenerateDiscardableImagesMetadata(); void GetDiscardableImagesInRect(const gfx::Rect& rect, float contents_scale, + const gfx::ColorSpace& target_color_space, std::vector<DrawImage>* images); gfx::Rect GetRectForImage(ImageId image_id) const; @@ -145,27 +148,26 @@ class CC_EXPORT DisplayItemList retain_visual_rects_ = retain; } - size_t size() const { return inputs_.items.size(); } + size_t size() const { return items_.size(); } - gfx::Rect VisualRectForTesting(int index) { - return inputs_.visual_rects[index]; - } + gfx::Rect VisualRectForTesting(int index) { return visual_rects_[index]; } ContiguousContainer<DisplayItem>::const_iterator begin() const { - return inputs_.items.begin(); + return items_.begin(); } ContiguousContainer<DisplayItem>::const_iterator end() const { - return inputs_.items.end(); + return items_.end(); } private: + FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithNoItems); + FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithItems); + ~DisplayItemList(); - RTree rtree_; - // For testing purposes only. Whether to keep visual rects across calls to - // Finalize(). - bool retain_visual_rects_ = false; + std::unique_ptr<base::trace_event::TracedValue> CreateTracedValue( + bool include_items) const; // If we're currently within a paired display item block, unions the // given visual rect with the begin display item's visual rect. @@ -173,32 +175,29 @@ class CC_EXPORT DisplayItemList template <typename DisplayItemType, typename... Args> const DisplayItemType& AllocateAndConstruct(Args&&... args) { - auto* item = &inputs_.items.AllocateAndConstruct<DisplayItemType>( + auto* item = &items_.AllocateAndConstruct<DisplayItemType>( std::forward<Args>(args)...); approximate_op_count_ += item->ApproximateOpCount(); return *item; } - int approximate_op_count_ = 0; - + RTree rtree_; DiscardableImageMap image_map_; + ContiguousContainer<DisplayItem> items_; - struct Inputs { - Inputs(); - ~Inputs(); - - ContiguousContainer<DisplayItem> items; - // The visual rects associated with each of the display items in the - // display item list. There is one rect per display item, and the - // position in |visual_rects| matches the position of the item in - // |items| . These rects are intentionally kept separate - // because they are not needed while walking the |items| for raster. - std::vector<gfx::Rect> visual_rects; - std::vector<size_t> begin_item_indices; - bool all_items_are_suitable_for_gpu_rasterization = true; - }; + // The visual rects associated with each of the display items in the + // display item list. There is one rect per display item, and the + // position in |visual_rects| matches the position of the item in + // |items| . These rects are intentionally kept separate + // because they are not needed while walking the |items| for raster. + std::vector<gfx::Rect> visual_rects_; + std::vector<size_t> begin_item_indices_; - Inputs inputs_; + int approximate_op_count_ = 0; + bool all_items_are_suitable_for_gpu_rasterization_ = true; + // For testing purposes only. Whether to keep visual rects across calls to + // Finalize(). + bool retain_visual_rects_ = false; friend class base::RefCountedThreadSafe<DisplayItemList>; FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, ApproximateMemoryUsage); @@ -207,4 +206,4 @@ class CC_EXPORT DisplayItemList } // namespace cc -#endif // CC_PLAYBACK_DISPLAY_ITEM_LIST_H_ +#endif // CC_PAINT_DISPLAY_ITEM_LIST_H_ diff --git a/chromium/cc/playback/display_item_list_unittest.cc b/chromium/cc/paint/display_item_list_unittest.cc index 426371e6bd8..f1b9e759f9b 100644 --- a/chromium/cc/playback/display_item_list_unittest.cc +++ b/chromium/cc/paint/display_item_list_unittest.cc @@ -2,33 +2,36 @@ // 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.h" +#include "cc/paint/display_item_list.h" #include <stddef.h> #include <vector> #include "base/memory/ptr_util.h" -#include "cc/output/filter_operation.h" -#include "cc/output/filter_operations.h" +#include "base/trace_event/trace_event_argument.h" +#include "cc/base/filter_operation.h" +#include "cc/base/filter_operations.h" +#include "cc/paint/clip_display_item.h" +#include "cc/paint/clip_path_display_item.h" +#include "cc/paint/compositing_display_item.h" +#include "cc/paint/drawing_display_item.h" +#include "cc/paint/filter_display_item.h" + +#include "cc/paint/float_clip_display_item.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" #include "cc/paint/paint_record.h" #include "cc/paint/paint_recorder.h" -#include "cc/paint/paint_surface.h" -#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/drawing_display_item.h" -#include "cc/playback/filter_display_item.h" -#include "cc/playback/float_clip_display_item.h" -#include "cc/playback/transform_display_item.h" +#include "cc/paint/transform_display_item.h" #include "cc/test/geometry_test_utils.h" +#include "cc/test/pixel_test_utils.h" #include "cc/test/skia_common.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" #include "third_party/skia/include/effects/SkImageSource.h" #include "ui/gfx/geometry/rect.h" @@ -39,6 +42,32 @@ namespace cc { namespace { +bool CompareN32Pixels(void* actual_pixels, + void* expected_pixels, + int width, + int height) { + if (memcmp(actual_pixels, expected_pixels, 4 * width * height) == 0) + return true; + + SkImageInfo actual_info = SkImageInfo::MakeN32Premul(width, height); + SkBitmap actual_bitmap; + actual_bitmap.installPixels(actual_info, actual_pixels, + actual_info.minRowBytes()); + + SkImageInfo expected_info = SkImageInfo::MakeN32Premul(width, height); + SkBitmap expected_bitmap; + expected_bitmap.installPixels(expected_info, expected_pixels, + expected_info.minRowBytes()); + + std::string gen_bmp_data_url = GetPNGDataUrl(actual_bitmap); + std::string ref_bmp_data_url = GetPNGDataUrl(expected_bitmap); + + LOG(ERROR) << "Pixels do not match!"; + LOG(ERROR) << "Actual: " << gen_bmp_data_url; + LOG(ERROR) << "Expected: " << ref_bmp_data_url; + return false; +} + const gfx::Rect kVisualRect(0, 0, 42, 42); sk_sp<const PaintRecord> CreateRectPicture(const gfx::Rect& bounds) { @@ -96,7 +125,7 @@ TEST(DisplayItemListTest, SingleDrawingItem) { SkImageInfo info = SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes()); - PaintCanvas expected_canvas(expected_bitmap); + SkiaPaintCanvas expected_canvas(expected_bitmap); expected_canvas.clipRect(gfx::RectToSkRect(layer_rect)); expected_canvas.drawRect( SkRect::MakeLTRB(0.f + offset.x(), 0.f + offset.y(), 60.f + offset.x(), @@ -107,7 +136,7 @@ TEST(DisplayItemListTest, SingleDrawingItem) { 75.f + offset.y()), blue_flags); - EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); + EXPECT_TRUE(CompareN32Pixels(pixels, expected_pixels, 100, 100)); } TEST(DisplayItemListTest, ClipItem) { @@ -152,7 +181,7 @@ TEST(DisplayItemListTest, ClipItem) { SkImageInfo info = SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes()); - PaintCanvas expected_canvas(expected_bitmap); + SkiaPaintCanvas expected_canvas(expected_bitmap); expected_canvas.clipRect(gfx::RectToSkRect(layer_rect)); expected_canvas.drawRect( SkRect::MakeLTRB(0.f + first_offset.x(), 0.f + first_offset.y(), @@ -164,7 +193,7 @@ TEST(DisplayItemListTest, ClipItem) { 75.f + second_offset.x(), 75.f + second_offset.y()), blue_flags); - EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); + EXPECT_TRUE(CompareN32Pixels(pixels, expected_pixels, 100, 100)); } TEST(DisplayItemListTest, TransformItem) { @@ -209,7 +238,7 @@ TEST(DisplayItemListTest, TransformItem) { SkImageInfo info = SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes()); - PaintCanvas expected_canvas(expected_bitmap); + SkiaPaintCanvas expected_canvas(expected_bitmap); expected_canvas.clipRect(gfx::RectToSkRect(layer_rect)); expected_canvas.drawRect( SkRect::MakeLTRB(0.f + first_offset.x(), 0.f + first_offset.y(), @@ -221,7 +250,7 @@ TEST(DisplayItemListTest, TransformItem) { 75.f + second_offset.x(), 75.f + second_offset.y()), blue_flags); - EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); + EXPECT_TRUE(CompareN32Pixels(pixels, expected_pixels, 100, 100)); } TEST(DisplayItemListTest, FilterItem) { @@ -282,10 +311,10 @@ TEST(DisplayItemListTest, FilterItem) { SkImageInfo info = SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes()); - PaintCanvas expected_canvas(expected_bitmap); + SkiaPaintCanvas expected_canvas(expected_bitmap); expected_canvas.drawRect(RectFToSkRect(filter_bounds), paint); - EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); + EXPECT_TRUE(CompareN32Pixels(pixels, expected_pixels, 100, 100)); } TEST(DisplayItemListTest, ApproximateMemoryUsage) { @@ -317,13 +346,13 @@ TEST(DisplayItemListTest, AsValueWithNoItems) { list->SetRetainVisualRectsForTesting(true); list->Finalize(); - std::string value = list->AsValue(true)->ToString(); + std::string value = list->CreateTracedValue(true)->ToString(); EXPECT_EQ(value.find("\"layer_rect\": [0,0,0,0]"), std::string::npos); EXPECT_NE(value.find("\"items\":[]"), std::string::npos); EXPECT_EQ(value.find("visualRect: [0,0 42x42]"), std::string::npos); EXPECT_NE(value.find("\"skp64\":"), std::string::npos); - value = list->AsValue(false)->ToString(); + value = list->CreateTracedValue(false)->ToString(); EXPECT_EQ(value.find("\"layer_rect\": [0,0,0,0]"), std::string::npos); EXPECT_EQ(value.find("\"items\":"), std::string::npos); EXPECT_EQ(value.find("visualRect: [0,0 42x42]"), std::string::npos); @@ -341,14 +370,14 @@ TEST(DisplayItemListTest, AsValueWithItems) { list->CreateAndAppendPairedEndItem<EndTransformDisplayItem>(); list->Finalize(); - std::string value = list->AsValue(true)->ToString(); + std::string value = list->CreateTracedValue(true)->ToString(); EXPECT_EQ(value.find("\"layer_rect\": [0,0,42,42]"), std::string::npos); EXPECT_NE(value.find("{\"items\":[\"TransformDisplayItem"), std::string::npos); EXPECT_NE(value.find("visualRect: [0,0 42x42]"), std::string::npos); EXPECT_NE(value.find("\"skp64\":"), std::string::npos); - value = list->AsValue(false)->ToString(); + value = list->CreateTracedValue(false)->ToString(); EXPECT_EQ(value.find("\"layer_rect\": [0,0,42,42]"), std::string::npos); EXPECT_EQ(value.find("{\"items\":[\"TransformDisplayItem"), std::string::npos); diff --git a/chromium/cc/playback/draw_image.cc b/chromium/cc/paint/draw_image.cc index 2b1779f9568..6c0bb644864 100644 --- a/chromium/cc/playback/draw_image.cc +++ b/chromium/cc/paint/draw_image.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/draw_image.h" +#include "cc/paint/draw_image.h" namespace cc { namespace { @@ -33,11 +33,13 @@ DrawImage::DrawImage() DrawImage::DrawImage(sk_sp<const SkImage> image, const SkIRect& src_rect, SkFilterQuality filter_quality, - const SkMatrix& matrix) + const SkMatrix& matrix, + const gfx::ColorSpace& target_color_space) : image_(std::move(image)), src_rect_(src_rect), filter_quality_(filter_quality), - matrix_(matrix) { + matrix_(matrix), + target_color_space_(target_color_space) { matrix_is_decomposable_ = ExtractScale(matrix_, &scale_); } diff --git a/chromium/cc/playback/draw_image.h b/chromium/cc/paint/draw_image.h index d3633e01141..78513b90d1e 100644 --- a/chromium/cc/playback/draw_image.h +++ b/chromium/cc/paint/draw_image.h @@ -2,28 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_PLAYBACK_DRAW_IMAGE_H_ -#define CC_PLAYBACK_DRAW_IMAGE_H_ +#ifndef CC_PAINT_DRAW_IMAGE_H_ +#define CC_PAINT_DRAW_IMAGE_H_ -#include "cc/base/cc_export.h" +#include "cc/paint/paint_export.h" #include "third_party/skia/include/core/SkFilterQuality.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkRefCnt.h" +#include "ui/gfx/color_space.h" #include "ui/gfx/geometry/size_f.h" namespace cc { // TODO(vmpstr): This should probably be DISALLOW_COPY_AND_ASSIGN and transport // it around using a pointer, since it became kind of large. Profile. -class CC_EXPORT DrawImage { +class CC_PAINT_EXPORT DrawImage { public: DrawImage(); DrawImage(sk_sp<const SkImage> image, const SkIRect& src_rect, SkFilterQuality filter_quality, - const SkMatrix& matrix); + const SkMatrix& matrix, + const gfx::ColorSpace& target_color_space); DrawImage(const DrawImage& other); ~DrawImage(); @@ -33,11 +35,19 @@ class CC_EXPORT DrawImage { SkFilterQuality filter_quality() const { return filter_quality_; } bool matrix_is_decomposable() const { return matrix_is_decomposable_; } const SkMatrix& matrix() const { return matrix_; } + const gfx::ColorSpace& target_color_space() const { + return target_color_space_; + } DrawImage ApplyScale(float scale) const { SkMatrix scaled_matrix = matrix_; scaled_matrix.preScale(scale, scale); - return DrawImage(image_, src_rect_, filter_quality_, scaled_matrix); + return DrawImage(image_, src_rect_, filter_quality_, scaled_matrix, + target_color_space_); + } + DrawImage ApplyTargetColorSpace(const gfx::ColorSpace& target_color_space) { + return DrawImage(image_, src_rect_, filter_quality_, matrix_, + target_color_space); } private: @@ -47,8 +57,9 @@ class CC_EXPORT DrawImage { SkMatrix matrix_; SkSize scale_; bool matrix_is_decomposable_; + gfx::ColorSpace target_color_space_; }; } // namespace cc -#endif // CC_PLAYBACK_DRAW_IMAGE_H_ +#endif // CC_PAINT_DRAW_IMAGE_H_ diff --git a/chromium/cc/paint/drawing_display_item.cc b/chromium/cc/paint/drawing_display_item.cc new file mode 100644 index 00000000000..60b09ee0e27 --- /dev/null +++ b/chromium/cc/paint/drawing_display_item.cc @@ -0,0 +1,30 @@ +// 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/paint/drawing_display_item.h" + +#include "third_party/skia/include/core/SkPicture.h" + +namespace cc { + +DrawingDisplayItem::DrawingDisplayItem() : DisplayItem(DRAWING) {} + +DrawingDisplayItem::DrawingDisplayItem(sk_sp<const PaintRecord> record) + : DisplayItem(DRAWING), picture(std::move(record)) {} + +DrawingDisplayItem::DrawingDisplayItem(const DrawingDisplayItem& item) + : DisplayItem(DRAWING), picture(item.picture) {} + +DrawingDisplayItem::~DrawingDisplayItem() = default; + +size_t DrawingDisplayItem::ExternalMemoryUsage() const { + return picture->approximateBytesUsed(); +} + +DISABLE_CFI_PERF +int DrawingDisplayItem::ApproximateOpCount() const { + return picture->approximateOpCount(); +} + +} // namespace cc diff --git a/chromium/cc/paint/drawing_display_item.h b/chromium/cc/paint/drawing_display_item.h new file mode 100644 index 00000000000..56c7b17aef2 --- /dev/null +++ b/chromium/cc/paint/drawing_display_item.h @@ -0,0 +1,32 @@ +// 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_PAINT_DRAWING_DISPLAY_ITEM_H_ +#define CC_PAINT_DRAWING_DISPLAY_ITEM_H_ + +#include <stddef.h> + +#include "cc/paint/display_item.h" +#include "cc/paint/paint_export.h" +#include "cc/paint/paint_record.h" +#include "third_party/skia/include/core/SkRefCnt.h" + +namespace cc { + +class CC_PAINT_EXPORT DrawingDisplayItem : public DisplayItem { + public: + DrawingDisplayItem(); + explicit DrawingDisplayItem(sk_sp<const PaintRecord> record); + explicit DrawingDisplayItem(const DrawingDisplayItem& item); + ~DrawingDisplayItem() override; + + size_t ExternalMemoryUsage() const; + int ApproximateOpCount() const; + + const sk_sp<const PaintRecord> picture; +}; + +} // namespace cc + +#endif // CC_PAINT_DRAWING_DISPLAY_ITEM_H_ diff --git a/chromium/cc/paint/filter_display_item.cc b/chromium/cc/paint/filter_display_item.cc new file mode 100644 index 00000000000..de8f0d3d31e --- /dev/null +++ b/chromium/cc/paint/filter_display_item.cc @@ -0,0 +1,20 @@ +// 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/paint/filter_display_item.h" + +namespace cc { + +FilterDisplayItem::FilterDisplayItem(const FilterOperations& filters, + const gfx::RectF& bounds, + const gfx::PointF& origin) + : DisplayItem(FILTER), filters(filters), bounds(bounds), origin(origin) {} + +FilterDisplayItem::~FilterDisplayItem() = default; + +EndFilterDisplayItem::EndFilterDisplayItem() : DisplayItem(END_FILTER) {} + +EndFilterDisplayItem::~EndFilterDisplayItem() = default; + +} // namespace cc diff --git a/chromium/cc/paint/filter_display_item.h b/chromium/cc/paint/filter_display_item.h new file mode 100644 index 00000000000..c4f18dcbc85 --- /dev/null +++ b/chromium/cc/paint/filter_display_item.h @@ -0,0 +1,45 @@ +// 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_PAINT_FILTER_DISPLAY_ITEM_H_ +#define CC_PAINT_FILTER_DISPLAY_ITEM_H_ + +#include "cc/base/filter_operations.h" +#include "cc/paint/display_item.h" +#include "cc/paint/paint_export.h" +#include "ui/gfx/geometry/point_f.h" +#include "ui/gfx/geometry/rect_f.h" + +namespace cc { + +class CC_PAINT_EXPORT FilterDisplayItem : public DisplayItem { + public: + FilterDisplayItem(const FilterOperations& filters, + const gfx::RectF& bounds, + const gfx::PointF& origin); + ~FilterDisplayItem() override; + + size_t ExternalMemoryUsage() const { + // FilterOperations doesn't expose its capacity, but size is probably good + // enough. + return filters.size() * sizeof(filters.at(0)); + } + int ApproximateOpCount() const { return 1; } + + const FilterOperations filters; + const gfx::RectF bounds; + const gfx::PointF origin; +}; + +class CC_PAINT_EXPORT EndFilterDisplayItem : public DisplayItem { + public: + EndFilterDisplayItem(); + ~EndFilterDisplayItem() override; + + int ApproximateOpCount() const { return 0; } +}; + +} // namespace cc + +#endif // CC_PAINT_FILTER_DISPLAY_ITEM_H_ diff --git a/chromium/cc/paint/float_clip_display_item.cc b/chromium/cc/paint/float_clip_display_item.cc new file mode 100644 index 00000000000..85cd5adff90 --- /dev/null +++ b/chromium/cc/paint/float_clip_display_item.cc @@ -0,0 +1,19 @@ +// 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/paint/float_clip_display_item.h" + +namespace cc { + +FloatClipDisplayItem::FloatClipDisplayItem(const gfx::RectF& clip_rect) + : DisplayItem(FLOAT_CLIP), clip_rect(clip_rect) {} + +FloatClipDisplayItem::~FloatClipDisplayItem() = default; + +EndFloatClipDisplayItem::EndFloatClipDisplayItem() + : DisplayItem(END_FLOAT_CLIP) {} + +EndFloatClipDisplayItem::~EndFloatClipDisplayItem() = default; + +} // namespace cc diff --git a/chromium/cc/paint/float_clip_display_item.h b/chromium/cc/paint/float_clip_display_item.h new file mode 100644 index 00000000000..43d751b36ce --- /dev/null +++ b/chromium/cc/paint/float_clip_display_item.h @@ -0,0 +1,37 @@ +// 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_PAINT_FLOAT_CLIP_DISPLAY_ITEM_H_ +#define CC_PAINT_FLOAT_CLIP_DISPLAY_ITEM_H_ + +#include <stddef.h> + +#include "cc/paint/display_item.h" +#include "cc/paint/paint_export.h" +#include "ui/gfx/geometry/rect_f.h" + +namespace cc { + +class CC_PAINT_EXPORT FloatClipDisplayItem : public DisplayItem { + public: + explicit FloatClipDisplayItem(const gfx::RectF& clip_rect); + ~FloatClipDisplayItem() override; + + size_t ExternalMemoryUsage() const { return 0; } + int ApproximateOpCount() const { return 1; } + + const gfx::RectF clip_rect; +}; + +class CC_PAINT_EXPORT EndFloatClipDisplayItem : public DisplayItem { + public: + EndFloatClipDisplayItem(); + ~EndFloatClipDisplayItem() override; + + int ApproximateOpCount() const { return 0; } +}; + +} // namespace cc + +#endif // CC_PAINT_FLOAT_CLIP_DISPLAY_ITEM_H_ diff --git a/chromium/cc/playback/image_id.h b/chromium/cc/paint/image_id.h index 5103857f790..0ffaafd782f 100644 --- a/chromium/cc/playback/image_id.h +++ b/chromium/cc/paint/image_id.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_PLAYBACK_IMAGE_ID_H_ -#define CC_PLAYBACK_IMAGE_ID_H_ +#ifndef CC_PAINT_IMAGE_ID_H_ +#define CC_PAINT_IMAGE_ID_H_ #include <stdint.h> #include <unordered_set> @@ -17,4 +17,4 @@ using ImageIdFlatSet = base::flat_set<ImageId>; } // namespace cc -#endif // CC_PLAYBACK_IMAGE_ID_H_ +#endif // CC_PAINT_IMAGE_ID_H_ diff --git a/chromium/cc/playback/largest_display_item.cc b/chromium/cc/paint/largest_display_item.cc index daf40363507..448c2b85670 100644 --- a/chromium/cc/playback/largest_display_item.cc +++ b/chromium/cc/paint/largest_display_item.cc @@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/largest_display_item.h" +#include "cc/paint/largest_display_item.h" #include <stddef.h> #include <algorithm> -#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/drawing_display_item.h" -#include "cc/playback/filter_display_item.h" -#include "cc/playback/float_clip_display_item.h" -#include "cc/playback/transform_display_item.h" +#include "cc/paint/clip_display_item.h" +#include "cc/paint/clip_path_display_item.h" +#include "cc/paint/compositing_display_item.h" +#include "cc/paint/drawing_display_item.h" +#include "cc/paint/filter_display_item.h" +#include "cc/paint/float_clip_display_item.h" +#include "cc/paint/transform_display_item.h" #include "third_party/skia/include/core/SkPicture.h" diff --git a/chromium/cc/playback/largest_display_item.h b/chromium/cc/paint/largest_display_item.h index 8350c61f1a0..e885ced9bf0 100644 --- a/chromium/cc/playback/largest_display_item.h +++ b/chromium/cc/paint/largest_display_item.h @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_PLAYBACK_LARGEST_DISPLAY_ITEM_H_ -#define CC_PLAYBACK_LARGEST_DISPLAY_ITEM_H_ +#ifndef CC_PAINT_LARGEST_DISPLAY_ITEM_H_ +#define CC_PAINT_LARGEST_DISPLAY_ITEM_H_ #include <stddef.h> -#include "cc/base/cc_export.h" +#include "cc/paint/paint_export.h" namespace cc { -CC_EXPORT size_t LargestDisplayItemSize(); +CC_PAINT_EXPORT size_t LargestDisplayItemSize(); } // namespace cc -#endif // CC_PLAYBACK_LARGEST_DISPLAY_ITEM_H_ +#endif // CC_PAINT_LARGEST_DISPLAY_ITEM_H_ diff --git a/chromium/cc/paint/paint_canvas.cc b/chromium/cc/paint/paint_canvas.cc index 53dab8fb45b..4aab0652b19 100644 --- a/chromium/cc/paint/paint_canvas.cc +++ b/chromium/cc/paint/paint_canvas.cc @@ -4,6 +4,10 @@ #include "cc/paint/paint_canvas.h" +#include "base/memory/ptr_util.h" +#include "cc/paint/paint_record.h" +#include "cc/paint/paint_recorder.h" +#include "third_party/skia/include/core/SkAnnotation.h" #include "third_party/skia/include/core/SkMetaData.h" #if defined(OS_MACOSX) @@ -14,32 +18,8 @@ const char kIsPreviewMetafileKey[] = "CrIsPreviewMetafile"; namespace cc { -PaintCanvasPassThrough::PaintCanvasPassThrough(SkCanvas* canvas) - : SkNWayCanvas(canvas->getBaseLayerSize().width(), - canvas->getBaseLayerSize().height()) { - SkIRect raster_bounds; - canvas->getDeviceClipBounds(&raster_bounds); - clipRect(SkRect::MakeFromIRect(raster_bounds)); - setMatrix(canvas->getTotalMatrix()); - addCanvas(canvas); -} - -PaintCanvasPassThrough::PaintCanvasPassThrough(int width, int height) - : SkNWayCanvas(width, height) {} - -PaintCanvasPassThrough::~PaintCanvasPassThrough() = default; - bool ToPixmap(PaintCanvas* canvas, SkPixmap* output) { - SkImageInfo info; - size_t row_bytes; - void* pixels = canvas->accessTopLayerPixels(&info, &row_bytes); - if (!pixels) { - output->reset(); - return false; - } - - output->reset(info, pixels, row_bytes); - return true; + return canvas->ToPixmap(output); } #if defined(OS_MACOSX) diff --git a/chromium/cc/paint/paint_canvas.h b/chromium/cc/paint/paint_canvas.h index 649096cf8ea..daacc301788 100644 --- a/chromium/cc/paint/paint_canvas.h +++ b/chromium/cc/paint/paint_canvas.h @@ -5,26 +5,228 @@ #ifndef CC_PAINT_PAINT_CANVAS_H_ #define CC_PAINT_PAINT_CANVAS_H_ +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" #include "build/build_config.h" #include "cc/paint/paint_export.h" +#include "cc/paint/paint_record.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/utils/SkNWayCanvas.h" -#include "third_party/skia/include/utils/SkNoDrawCanvas.h" namespace cc { -using PaintCanvas = SkCanvas; -using PaintCanvasNoDraw = SkNoDrawCanvas; -using PaintCanvasAutoRestore = SkAutoCanvasRestore; +class DisplayItemList; +class PaintFlags; -class CC_PAINT_EXPORT PaintCanvasPassThrough : public SkNWayCanvas { +class CC_PAINT_EXPORT PaintCanvas { public: - explicit PaintCanvasPassThrough(SkCanvas* canvas); - PaintCanvasPassThrough(int width, int height); - ~PaintCanvasPassThrough() override; + virtual ~PaintCanvas() {} + + virtual SkMetaData& getMetaData() = 0; + virtual SkImageInfo imageInfo() const = 0; + + // TODO(enne): It would be nice to get rid of flush() entirely, as it + // doesn't really make sense for recording. However, this gets used by + // SkCanvasVideoRenderer which takes a PaintCanvas to paint both + // software and hardware video. This is super entangled with ImageBuffer + // and canvas/video painting in Blink where the same paths are used for + // both recording and gpu work. + virtual void flush() = 0; + + virtual SkISize getBaseLayerSize() const = 0; + virtual bool writePixels(const SkImageInfo& info, + const void* pixels, + size_t row_bytes, + int x, + int y) = 0; + virtual int save() = 0; + virtual int saveLayer(const SkRect* bounds, const PaintFlags* flags) = 0; + virtual int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) = 0; + + virtual void restore() = 0; + virtual int getSaveCount() const = 0; + virtual void restoreToCount(int save_count) = 0; + virtual void translate(SkScalar dx, SkScalar dy) = 0; + virtual void scale(SkScalar sx, SkScalar sy) = 0; + virtual void rotate(SkScalar degrees) = 0; + virtual void concat(const SkMatrix& matrix) = 0; + virtual void setMatrix(const SkMatrix& matrix) = 0; + + virtual void clipRect(const SkRect& rect, + SkClipOp op, + bool do_anti_alias) = 0; + void clipRect(const SkRect& rect, SkClipOp op) { clipRect(rect, op, false); } + void clipRect(const SkRect& rect, bool do_anti_alias) { + clipRect(rect, SkClipOp::kIntersect, do_anti_alias); + } + void clipRect(const SkRect& rect) { + clipRect(rect, SkClipOp::kIntersect, false); + } + + virtual void clipRRect(const SkRRect& rrect, + SkClipOp op, + bool do_anti_alias) = 0; + void clipRRect(const SkRRect& rrect, bool do_anti_alias) { + clipRRect(rrect, SkClipOp::kIntersect, do_anti_alias); + } + void clipRRect(const SkRRect& rrect, SkClipOp op) { + clipRRect(rrect, op, false); + } + void clipRRect(const SkRRect& rrect) { + clipRRect(rrect, SkClipOp::kIntersect, false); + } + + virtual void clipPath(const SkPath& path, + SkClipOp op, + bool do_anti_alias) = 0; + void clipPath(const SkPath& path, SkClipOp op) { clipPath(path, op, false); } + void clipPath(const SkPath& path, bool do_anti_alias) { + clipPath(path, SkClipOp::kIntersect, do_anti_alias); + } + + virtual bool quickReject(const SkRect& rect) const = 0; + virtual bool quickReject(const SkPath& path) const = 0; + virtual SkRect getLocalClipBounds() const = 0; + virtual bool getLocalClipBounds(SkRect* bounds) const = 0; + virtual SkIRect getDeviceClipBounds() const = 0; + virtual bool getDeviceClipBounds(SkIRect* bounds) const = 0; + virtual void drawColor(SkColor color, SkBlendMode mode) = 0; + void drawColor(SkColor color) { drawColor(color, SkBlendMode::kSrcOver); } + virtual void clear(SkColor color) = 0; + + virtual void drawLine(SkScalar x0, + SkScalar y0, + SkScalar x1, + SkScalar y1, + const PaintFlags& flags) = 0; + virtual void drawRect(const SkRect& rect, const PaintFlags& flags) = 0; + virtual void drawIRect(const SkIRect& rect, const PaintFlags& flags) = 0; + virtual void drawOval(const SkRect& oval, const PaintFlags& flags) = 0; + virtual void drawRRect(const SkRRect& rrect, const PaintFlags& flags) = 0; + virtual void drawDRRect(const SkRRect& outer, + const SkRRect& inner, + const PaintFlags& flags) = 0; + virtual void drawCircle(SkScalar cx, + SkScalar cy, + SkScalar radius, + const PaintFlags& flags) = 0; + virtual void drawArc(const SkRect& oval, + SkScalar start_angle, + SkScalar sweep_angle, + bool use_center, + const PaintFlags& flags) = 0; + virtual void drawRoundRect(const SkRect& rect, + SkScalar rx, + SkScalar ry, + const PaintFlags& flags) = 0; + virtual void drawPath(const SkPath& path, const PaintFlags& flags) = 0; + virtual void drawImage(sk_sp<const SkImage> image, + SkScalar left, + SkScalar top, + const PaintFlags* flags) = 0; + void drawImage(sk_sp<const SkImage> image, SkScalar left, SkScalar top) { + drawImage(image, left, top, nullptr); + } + + enum SrcRectConstraint { + kStrict_SrcRectConstraint = SkCanvas::kStrict_SrcRectConstraint, + kFast_SrcRectConstraint = SkCanvas::kFast_SrcRectConstraint, + }; + + virtual void drawImageRect(sk_sp<const SkImage> image, + const SkRect& src, + const SkRect& dst, + const PaintFlags* flags, + SrcRectConstraint constraint) = 0; + virtual void drawBitmap(const SkBitmap& bitmap, + SkScalar left, + SkScalar top, + const PaintFlags* flags) = 0; + void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top) { + drawBitmap(bitmap, left, top, nullptr); + } + + virtual void drawText(const void* text, + size_t byte_length, + SkScalar x, + SkScalar y, + const PaintFlags& flags) = 0; + virtual void drawPosText(const void* text, + size_t byte_length, + const SkPoint pos[], + const PaintFlags& flags) = 0; + virtual void drawTextBlob(sk_sp<SkTextBlob> blob, + SkScalar x, + SkScalar y, + const PaintFlags& flags) = 0; + + virtual void drawDisplayItemList( + scoped_refptr<DisplayItemList> display_item_list) = 0; + + virtual void drawPicture(sk_sp<const PaintRecord> record) = 0; + + virtual bool isClipEmpty() const = 0; + virtual bool isClipRect() const = 0; + virtual const SkMatrix& getTotalMatrix() const = 0; + + // For GraphicsContextCanvas only. Maybe this could be rewritten? + virtual void temporary_internal_describeTopLayer(SkMatrix* matrix, + SkIRect* clip_bounds) = 0; + + virtual bool ToPixmap(SkPixmap* output) = 0; + + enum class AnnotationType { + URL, + NAMED_DESTINATION, + LINK_TO_DESTINATION, + }; + virtual void Annotate(AnnotationType type, + const SkRect& rect, + sk_sp<SkData> data) = 0; + + // TODO(enne): maybe this should live on PaintRecord, but that's not + // possible when PaintRecord is a typedef. + virtual void PlaybackPaintRecord(sk_sp<const PaintRecord> record) = 0; + + protected: + friend class PaintSurface; + friend class PaintRecorder; + friend CC_PAINT_EXPORT bool ToPixmap(PaintCanvas* canvas, SkPixmap* output); +}; + +class CC_PAINT_EXPORT PaintCanvasAutoRestore { + public: + PaintCanvasAutoRestore(PaintCanvas* canvas, bool save) : canvas_(canvas) { + if (canvas_) { + save_count_ = canvas_->getSaveCount(); + if (save) { + canvas_->save(); + } + } + } + + ~PaintCanvasAutoRestore() { + if (canvas_) { + canvas_->restoreToCount(save_count_); + } + } + + void restore() { + if (canvas_) { + canvas_->restoreToCount(save_count_); + canvas_ = nullptr; + } + } + + private: + PaintCanvas* canvas_ = nullptr; + int save_count_ = 0; }; -// TODO(enne): Move all these functions into PaintCanvas. +// TODO(enne): Move all these functions into PaintCanvas. These are only +// separate now to make the transition to concrete types easier by keeping +// the base PaintCanvas type equivalent to the SkCanvas interface and +// all these helper functions potentially operating on both. // PaintCanvas equivalent of skia::GetWritablePixels. CC_PAINT_EXPORT bool ToPixmap(PaintCanvas* canvas, SkPixmap* output); diff --git a/chromium/cc/paint/paint_flags.h b/chromium/cc/paint/paint_flags.h index aa112452121..b7e96c68e2e 100644 --- a/chromium/cc/paint/paint_flags.h +++ b/chromium/cc/paint/paint_flags.h @@ -5,14 +5,212 @@ #ifndef CC_PAINT_PAINT_FLAGS_H_ #define CC_PAINT_PAINT_FLAGS_H_ +#include "base/compiler_specific.h" +#include "cc/paint/paint_export.h" +#include "cc/paint/paint_shader.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkColorFilter.h" +#include "third_party/skia/include/core/SkDrawLooper.h" +#include "third_party/skia/include/core/SkImageFilter.h" +#include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/core/SkPathEffect.h" +#include "third_party/skia/include/core/SkTypeface.h" namespace cc { -using PaintFlags = SkPaint; +class CC_PAINT_EXPORT PaintFlags { + public: + enum Style { + kFill_Style = SkPaint::kFill_Style, + kStroke_Style = SkPaint::kStroke_Style, + kStrokeAndFill_Style = SkPaint::kStrokeAndFill_Style, + }; + ALWAYS_INLINE Style getStyle() const { + return static_cast<Style>(paint_.getStyle()); + } + ALWAYS_INLINE void setStyle(Style style) { + paint_.setStyle(static_cast<SkPaint::Style>(style)); + } + ALWAYS_INLINE SkColor getColor() const { return paint_.getColor(); } + ALWAYS_INLINE void setColor(SkColor color) { paint_.setColor(color); } + ALWAYS_INLINE void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { + paint_.setARGB(a, r, g, b); + } + ALWAYS_INLINE uint8_t getAlpha() const { return paint_.getAlpha(); } + ALWAYS_INLINE void setAlpha(U8CPU a) { paint_.setAlpha(a); } + ALWAYS_INLINE void setBlendMode(SkBlendMode mode) { + paint_.setBlendMode(mode); + } + ALWAYS_INLINE SkBlendMode getBlendMode() const { + return paint_.getBlendMode(); + } + ALWAYS_INLINE bool isSrcOver() const { return paint_.isSrcOver(); } + ALWAYS_INLINE bool isAntiAlias() const { return paint_.isAntiAlias(); } + ALWAYS_INLINE void setAntiAlias(bool aa) { paint_.setAntiAlias(aa); } + ALWAYS_INLINE bool isVerticalText() const { return paint_.isVerticalText(); } + ALWAYS_INLINE void setVerticalText(bool vertical) { + paint_.setVerticalText(vertical); + } + ALWAYS_INLINE bool isSubpixelText() const { return paint_.isSubpixelText(); } + ALWAYS_INLINE void setSubpixelText(bool subpixel_text) { + paint_.setSubpixelText(subpixel_text); + } + ALWAYS_INLINE bool isLCDRenderText() const { + return paint_.isLCDRenderText(); + } + ALWAYS_INLINE void setLCDRenderText(bool lcd_text) { + paint_.setLCDRenderText(lcd_text); + } + enum Hinting { + kNo_Hinting = SkPaint::kNo_Hinting, + kSlight_Hinting = SkPaint::kSlight_Hinting, + kNormal_Hinting = SkPaint::kNormal_Hinting, //!< this is the default + kFull_Hinting = SkPaint::kFull_Hinting + }; + ALWAYS_INLINE Hinting getHinting() const { + return static_cast<Hinting>(paint_.getHinting()); + } + ALWAYS_INLINE void setHinting(Hinting hinting_level) { + paint_.setHinting(static_cast<SkPaint::Hinting>(hinting_level)); + } + ALWAYS_INLINE bool isAutohinted() const { return paint_.isAutohinted(); } + ALWAYS_INLINE void setAutohinted(bool use_auto_hinter) { + paint_.setAutohinted(use_auto_hinter); + } + ALWAYS_INLINE bool isDither() const { return paint_.isDither(); } + ALWAYS_INLINE void setDither(bool dither) { paint_.setDither(dither); } + enum TextEncoding { + kUTF8_TextEncoding = SkPaint::kUTF8_TextEncoding, + kUTF16_TextEncoding = SkPaint::kUTF16_TextEncoding, + kUTF32_TextEncoding = SkPaint::kUTF32_TextEncoding, + kGlyphID_TextEncoding = SkPaint::kGlyphID_TextEncoding + }; + ALWAYS_INLINE TextEncoding getTextEncoding() const { + return static_cast<TextEncoding>(paint_.getTextEncoding()); + } + ALWAYS_INLINE void setTextEncoding(TextEncoding encoding) { + paint_.setTextEncoding(static_cast<SkPaint::TextEncoding>(encoding)); + } + ALWAYS_INLINE SkScalar getTextSize() const { return paint_.getTextSize(); } + ALWAYS_INLINE void setTextSize(SkScalar textSize) { + paint_.setTextSize(textSize); + } + ALWAYS_INLINE void setFilterQuality(SkFilterQuality quality) { + paint_.setFilterQuality(quality); + } + ALWAYS_INLINE SkFilterQuality getFilterQuality() const { + return paint_.getFilterQuality(); + } + ALWAYS_INLINE SkScalar getStrokeWidth() const { + return paint_.getStrokeWidth(); + } + ALWAYS_INLINE void setStrokeWidth(SkScalar width) { + paint_.setStrokeWidth(width); + } + ALWAYS_INLINE SkScalar getStrokeMiter() const { + return paint_.getStrokeMiter(); + } + ALWAYS_INLINE void setStrokeMiter(SkScalar miter) { + paint_.setStrokeMiter(miter); + } + enum Cap { + kButt_Cap = SkPaint::kButt_Cap, //!< begin/end contours with no extension + kRound_Cap = SkPaint::kRound_Cap, //!< begin/end contours with a + //! semi-circle extension + kSquare_Cap = SkPaint::kSquare_Cap, //!< begin/end contours with a half + //! square extension + kLast_Cap = kSquare_Cap, + kDefault_Cap = kButt_Cap + }; + ALWAYS_INLINE Cap getStrokeCap() const { + return static_cast<Cap>(paint_.getStrokeCap()); + } + ALWAYS_INLINE void setStrokeCap(Cap cap) { + paint_.setStrokeCap(static_cast<SkPaint::Cap>(cap)); + } + enum Join { + kMiter_Join = SkPaint::kMiter_Join, + kRound_Join = SkPaint::kRound_Join, + kBevel_Join = SkPaint::kBevel_Join, + kLast_Join = kBevel_Join, + kDefault_Join = kMiter_Join + }; + ALWAYS_INLINE Join getStrokeJoin() const { + return static_cast<Join>(paint_.getStrokeJoin()); + } + ALWAYS_INLINE void setStrokeJoin(Join join) { + paint_.setStrokeJoin(static_cast<SkPaint::Join>(join)); + } + ALWAYS_INLINE SkTypeface* getTypeface() const { return paint_.getTypeface(); } + ALWAYS_INLINE void setTypeface(sk_sp<SkTypeface> typeface) { + paint_.setTypeface(std::move(typeface)); + } + ALWAYS_INLINE SkColorFilter* getColorFilter() const { + return paint_.getColorFilter(); + } + ALWAYS_INLINE void setColorFilter(sk_sp<SkColorFilter> filter) { + paint_.setColorFilter(std::move(filter)); + } + ALWAYS_INLINE SkMaskFilter* getMaskFilter() const { + return paint_.getMaskFilter(); + } + ALWAYS_INLINE void setMaskFilter(sk_sp<SkMaskFilter> mask) { + paint_.setMaskFilter(std::move(mask)); + } + ALWAYS_INLINE PaintShader* getShader() const { return paint_.getShader(); } + ALWAYS_INLINE void setShader(sk_sp<PaintShader> shader) { + paint_.setShader(std::move(shader)); + } + ALWAYS_INLINE SkPathEffect* getPathEffect() const { + return paint_.getPathEffect(); + } + ALWAYS_INLINE void setPathEffect(sk_sp<SkPathEffect> effect) { + paint_.setPathEffect(std::move(effect)); + } + ALWAYS_INLINE bool getFillPath(const SkPath& src, + SkPath* dst, + const SkRect* cullRect = nullptr, + SkScalar resScale = 1) const { + return paint_.getFillPath(src, dst, cullRect, resScale); + } + ALWAYS_INLINE sk_sp<SkImageFilter> refImageFilter() const { + return paint_.refImageFilter(); + } + ALWAYS_INLINE SkImageFilter* getImageFilter() const { + return paint_.getImageFilter(); + } + void setImageFilter(sk_sp<SkImageFilter> filter) { + paint_.setImageFilter(std::move(filter)); + } + ALWAYS_INLINE SkDrawLooper* getDrawLooper() const { + return paint_.getDrawLooper(); + } + ALWAYS_INLINE SkDrawLooper* getLooper() const { return paint_.getLooper(); } + ALWAYS_INLINE void setLooper(sk_sp<SkDrawLooper> looper) { + paint_.setLooper(std::move(looper)); + } + ALWAYS_INLINE bool canComputeFastBounds() const { + return paint_.canComputeFastBounds(); + } + ALWAYS_INLINE const SkRect& computeFastBounds(const SkRect& orig, + SkRect* storage) const { + return paint_.computeFastBounds(orig, storage); + } -inline const SkPaint& ToSkPaint(const PaintFlags& flags) { - return flags; + private: + friend const SkPaint& ToSkPaint(const PaintFlags& flags); + friend const SkPaint* ToSkPaint(const PaintFlags* flags); + + SkPaint paint_; +}; + +ALWAYS_INLINE const SkPaint& ToSkPaint(const PaintFlags& flags) { + return flags.paint_; +} + +ALWAYS_INLINE const SkPaint* ToSkPaint(const PaintFlags* flags) { + return &flags->paint_; } } // namespace cc diff --git a/chromium/cc/paint/paint_record.h b/chromium/cc/paint/paint_record.h index a376394cc84..8506606b59f 100644 --- a/chromium/cc/paint/paint_record.h +++ b/chromium/cc/paint/paint_record.h @@ -6,20 +6,11 @@ #define CC_PAINT_PAINT_RECORD_H_ #include "third_party/skia/include/core/SkPicture.h" -#include "third_party/skia/include/utils/SkPictureUtils.h" namespace cc { using PaintRecord = SkPicture; -inline const SkPicture* ToSkPicture(const PaintRecord* record) { - return record; -} - -inline SkPicture* ToSkPicture(PaintRecord* record) { - return record; -} - inline sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record) { return record; } diff --git a/chromium/cc/paint/paint_recorder.cc b/chromium/cc/paint/paint_recorder.cc new file mode 100644 index 00000000000..672f0712725 --- /dev/null +++ b/chromium/cc/paint/paint_recorder.cc @@ -0,0 +1,12 @@ +// Copyright 2017 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/paint/paint_recorder.h" + +namespace cc { + +PaintRecorder::PaintRecorder() = default; +PaintRecorder::~PaintRecorder() = default; + +} // namespace cc diff --git a/chromium/cc/paint/paint_recorder.h b/chromium/cc/paint/paint_recorder.h index be866fddf1d..2bbea83b981 100644 --- a/chromium/cc/paint/paint_recorder.h +++ b/chromium/cc/paint/paint_recorder.h @@ -5,10 +5,55 @@ #ifndef CC_PAINT_PAINT_RECORDER_H_ #define CC_PAINT_PAINT_RECORDER_H_ +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/optional.h" +#include "cc/paint/paint_canvas.h" +#include "cc/paint/paint_record.h" +#include "cc/paint/skia_paint_canvas.h" #include "third_party/skia/include/core/SkPictureRecorder.h" namespace cc { -using PaintRecorder = SkPictureRecorder; -} + +class CC_PAINT_EXPORT PaintRecorder { + public: + PaintRecorder(); + ~PaintRecorder(); + + ALWAYS_INLINE PaintCanvas* beginRecording(const SkRect& bounds) { + uint32_t record_flags = 0; + canvas_.emplace(recorder_.beginRecording(bounds, nullptr, record_flags)); + return getRecordingCanvas(); + } + + ALWAYS_INLINE PaintCanvas* beginRecording(SkScalar width, SkScalar height) { + uint32_t record_flags = 0; + canvas_.emplace( + recorder_.beginRecording(width, height, nullptr, record_flags)); + return getRecordingCanvas(); + } + + // Only valid between between and finish recording. + ALWAYS_INLINE PaintCanvas* getRecordingCanvas() { + return canvas_.has_value() ? &canvas_.value() : nullptr; + } + + ALWAYS_INLINE sk_sp<PaintRecord> finishRecordingAsPicture() { + sk_sp<SkPicture> picture = recorder_.finishRecordingAsPicture(); + // Some users (e.g. printing) use the existence of the recording canvas + // to know if recording is finished, so reset it here. + canvas_.reset(); + return sk_ref_sp(static_cast<PaintRecord*>(picture.get())); + } + + private: + SkPictureRecorder recorder_; + base::Optional<SkiaPaintCanvas> canvas_; + + DISALLOW_COPY_AND_ASSIGN(PaintRecorder); +}; + +} // namespace cc #endif // CC_PAINT_PAINT_RECORDER_H_ diff --git a/chromium/cc/paint/paint_shader.h b/chromium/cc/paint/paint_shader.h index f519703eb88..6afdaa650de 100644 --- a/chromium/cc/paint/paint_shader.h +++ b/chromium/cc/paint/paint_shader.h @@ -16,14 +16,7 @@ inline sk_sp<PaintShader> WrapSkShader(sk_sp<SkShader> shader) { return shader; } -inline sk_sp<PaintShader> MakePaintShaderImage(const SkImage* image, - SkShader::TileMode tx, - SkShader::TileMode ty, - const SkMatrix* local_matrix) { - return image->makeShader(tx, ty, local_matrix); -} - -inline sk_sp<PaintShader> MakePaintShaderImage(const sk_sp<SkImage> image, +inline sk_sp<PaintShader> MakePaintShaderImage(sk_sp<const SkImage> image, SkShader::TileMode tx, SkShader::TileMode ty, const SkMatrix* local_matrix) { @@ -35,7 +28,8 @@ inline sk_sp<PaintShader> MakePaintShaderRecord(sk_sp<PaintRecord> record, SkShader::TileMode ty, const SkMatrix* local_matrix, const SkRect* tile) { - return SkShader::MakePictureShader(record, tx, ty, local_matrix, tile); + return SkShader::MakePictureShader(ToSkPicture(record), tx, ty, local_matrix, + tile); } } // namespace cc diff --git a/chromium/cc/paint/paint_surface.h b/chromium/cc/paint/paint_surface.h deleted file mode 100644 index 34165bf16ed..00000000000 --- a/chromium/cc/paint/paint_surface.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2017 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_PAINT_PAINT_SURFACE_H_ -#define CC_PAINT_PAINT_SURFACE_H_ - -#include "third_party/skia/include/core/SkSurface.h" - -namespace cc { -using PaintSurface = SkSurface; -} - -#endif // CC_PAINT_PAINT_SURFACE_H_ diff --git a/chromium/cc/paint/skia_paint_canvas.cc b/chromium/cc/paint/skia_paint_canvas.cc new file mode 100644 index 00000000000..94b0cfb7a30 --- /dev/null +++ b/chromium/cc/paint/skia_paint_canvas.cc @@ -0,0 +1,311 @@ +// Copyright 2017 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/paint/paint_canvas.h" + +#include "base/memory/ptr_util.h" +#include "cc/paint/display_item_list.h" +#include "cc/paint/paint_record.h" +#include "cc/paint/paint_recorder.h" +#include "third_party/skia/include/core/SkAnnotation.h" +#include "third_party/skia/include/core/SkMetaData.h" +#include "third_party/skia/include/utils/SkNWayCanvas.h" + +namespace cc { + +SkiaPaintCanvas::SkiaPaintCanvas(SkCanvas* canvas) : canvas_(canvas) {} + +SkiaPaintCanvas::SkiaPaintCanvas(const SkBitmap& bitmap) + : canvas_(new SkCanvas(bitmap)), owned_(canvas_) {} + +SkiaPaintCanvas::SkiaPaintCanvas(const SkBitmap& bitmap, + const SkSurfaceProps& props) + : canvas_(new SkCanvas(bitmap, props)), owned_(canvas_) {} + +SkiaPaintCanvas::SkiaPaintCanvas(SkiaPaintCanvas&& other) = default; +SkiaPaintCanvas::~SkiaPaintCanvas() = default; + +SkMetaData& SkiaPaintCanvas::getMetaData() { + return canvas_->getMetaData(); +} + +SkImageInfo SkiaPaintCanvas::imageInfo() const { + return canvas_->imageInfo(); +} + +void SkiaPaintCanvas::flush() { + canvas_->flush(); +} + +SkISize SkiaPaintCanvas::getBaseLayerSize() const { + return canvas_->getBaseLayerSize(); +} + +bool SkiaPaintCanvas::writePixels(const SkImageInfo& info, + const void* pixels, + size_t row_bytes, + int x, + int y) { + return canvas_->writePixels(info, pixels, row_bytes, x, y); +} + +int SkiaPaintCanvas::save() { + return canvas_->save(); +} + +int SkiaPaintCanvas::saveLayer(const SkRect* bounds, const PaintFlags* flags) { + return canvas_->saveLayer(bounds, ToSkPaint(flags)); +} + +int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { + return canvas_->saveLayerAlpha(bounds, alpha); +} + +void SkiaPaintCanvas::restore() { + canvas_->restore(); +} + +int SkiaPaintCanvas::getSaveCount() const { + return canvas_->getSaveCount(); +} + +void SkiaPaintCanvas::restoreToCount(int save_count) { + canvas_->restoreToCount(save_count); +} + +void SkiaPaintCanvas::translate(SkScalar dx, SkScalar dy) { + canvas_->translate(dx, dy); +} + +void SkiaPaintCanvas::scale(SkScalar sx, SkScalar sy) { + canvas_->scale(sx, sy); +} + +void SkiaPaintCanvas::rotate(SkScalar degrees) { + canvas_->rotate(degrees); +} + +void SkiaPaintCanvas::concat(const SkMatrix& matrix) { + canvas_->concat(matrix); +} + +void SkiaPaintCanvas::setMatrix(const SkMatrix& matrix) { + canvas_->setMatrix(matrix); +} + +void SkiaPaintCanvas::clipRect(const SkRect& rect, + SkClipOp op, + bool do_anti_alias) { + canvas_->clipRect(rect, op, do_anti_alias); +} + +void SkiaPaintCanvas::clipRRect(const SkRRect& rrect, + SkClipOp op, + bool do_anti_alias) { + canvas_->clipRRect(rrect, op, do_anti_alias); +} + +void SkiaPaintCanvas::clipPath(const SkPath& path, + SkClipOp op, + bool do_anti_alias) { + canvas_->clipPath(path, op, do_anti_alias); +} + +bool SkiaPaintCanvas::quickReject(const SkRect& rect) const { + return canvas_->quickReject(rect); +} + +bool SkiaPaintCanvas::quickReject(const SkPath& path) const { + return canvas_->quickReject(path); +} + +SkRect SkiaPaintCanvas::getLocalClipBounds() const { + return canvas_->getLocalClipBounds(); +} + +bool SkiaPaintCanvas::getLocalClipBounds(SkRect* bounds) const { + return canvas_->getLocalClipBounds(bounds); +} + +SkIRect SkiaPaintCanvas::getDeviceClipBounds() const { + return canvas_->getDeviceClipBounds(); +} + +bool SkiaPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const { + return canvas_->getDeviceClipBounds(bounds); +} + +void SkiaPaintCanvas::drawColor(SkColor color, SkBlendMode mode) { + canvas_->drawColor(color, mode); +} + +void SkiaPaintCanvas::clear(SkColor color) { + canvas_->clear(color); +} + +void SkiaPaintCanvas::drawLine(SkScalar x0, + SkScalar y0, + SkScalar x1, + SkScalar y1, + const PaintFlags& flags) { + SkiaPaintCanvas::canvas_->drawLine(x0, y0, x1, y1, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { + canvas_->drawRect(rect, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) { + canvas_->drawIRect(rect, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) { + canvas_->drawOval(oval, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawRRect(const SkRRect& rrect, const PaintFlags& flags) { + canvas_->drawRRect(rrect, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawDRRect(const SkRRect& outer, + const SkRRect& inner, + const PaintFlags& flags) { + canvas_->drawDRRect(outer, inner, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawCircle(SkScalar cx, + SkScalar cy, + SkScalar radius, + const PaintFlags& flags) { + canvas_->drawCircle(cx, cy, radius, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawArc(const SkRect& oval, + SkScalar start_angle, + SkScalar sweep_angle, + bool use_center, + const PaintFlags& flags) { + canvas_->drawArc(oval, start_angle, sweep_angle, use_center, + ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawRoundRect(const SkRect& rect, + SkScalar rx, + SkScalar ry, + const PaintFlags& flags) { + canvas_->drawRoundRect(rect, rx, ry, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) { + canvas_->drawPath(path, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawImage(sk_sp<const SkImage> image, + SkScalar left, + SkScalar top, + const PaintFlags* flags) { + canvas_->drawImage(image.get(), left, top, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawImageRect(sk_sp<const SkImage> image, + const SkRect& src, + const SkRect& dst, + const PaintFlags* flags, + SrcRectConstraint constraint) { + canvas_->drawImageRect(image.get(), src, dst, ToSkPaint(flags), + static_cast<SkCanvas::SrcRectConstraint>(constraint)); +} + +void SkiaPaintCanvas::drawBitmap(const SkBitmap& bitmap, + SkScalar left, + SkScalar top, + const PaintFlags* flags) { + canvas_->drawBitmap(bitmap, left, top, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawText(const void* text, + size_t byte_length, + SkScalar x, + SkScalar y, + const PaintFlags& flags) { + canvas_->drawText(text, byte_length, x, y, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawPosText(const void* text, + size_t byte_length, + const SkPoint pos[], + const PaintFlags& flags) { + canvas_->drawPosText(text, byte_length, pos, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob, + SkScalar x, + SkScalar y, + const PaintFlags& flags) { + canvas_->drawTextBlob(blob.get(), x, y, ToSkPaint(flags)); +} + +void SkiaPaintCanvas::drawDisplayItemList( + scoped_refptr<DisplayItemList> display_item_list) { + display_item_list->Raster(canvas_, nullptr); +} + +void SkiaPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) { + record->playback(canvas_); +} + +bool SkiaPaintCanvas::isClipEmpty() const { + return canvas_->isClipEmpty(); +} + +bool SkiaPaintCanvas::isClipRect() const { + return canvas_->isClipRect(); +} + +const SkMatrix& SkiaPaintCanvas::getTotalMatrix() const { + return canvas_->getTotalMatrix(); +} + +void SkiaPaintCanvas::temporary_internal_describeTopLayer( + SkMatrix* matrix, + SkIRect* clip_bounds) { + return canvas_->temporary_internal_describeTopLayer(matrix, clip_bounds); +} + +void SkiaPaintCanvas::PlaybackPaintRecord(sk_sp<const PaintRecord> record) { + record->playback(canvas_); +} + +bool SkiaPaintCanvas::ToPixmap(SkPixmap* output) { + SkImageInfo info; + size_t row_bytes; + void* pixels = canvas_->accessTopLayerPixels(&info, &row_bytes); + if (!pixels) { + output->reset(); + return false; + } + + output->reset(info, pixels, row_bytes); + return true; +} + +void SkiaPaintCanvas::Annotate(AnnotationType type, + const SkRect& rect, + sk_sp<SkData> data) { + switch (type) { + case AnnotationType::URL: + SkAnnotateRectWithURL(canvas_, rect, data.get()); + break; + case AnnotationType::LINK_TO_DESTINATION: + SkAnnotateLinkToDestination(canvas_, rect, data.get()); + break; + case AnnotationType::NAMED_DESTINATION: { + SkPoint point = SkPoint::Make(rect.x(), rect.y()); + SkAnnotateNamedDestination(canvas_, point, data.get()); + break; + } + } +} + +} // namespace cc diff --git a/chromium/cc/paint/skia_paint_canvas.h b/chromium/cc/paint/skia_paint_canvas.h new file mode 100644 index 00000000000..669ca9b3e0b --- /dev/null +++ b/chromium/cc/paint/skia_paint_canvas.h @@ -0,0 +1,165 @@ +// Copyright 2017 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_PAINT_SKIA_PAINT_CANVAS_H_ +#define CC_PAINT_SKIA_PAINT_CANVAS_H_ + +#include <memory> + +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "base/macros.h" +#include "build/build_config.h" +#include "cc/paint/paint_canvas.h" +#include "cc/paint/paint_flags.h" +#include "cc/paint/paint_record.h" +#include "third_party/skia/include/core/SkCanvas.h" + +namespace cc { + +class PaintFlags; + +// A PaintCanvas derived class that passes PaintCanvas APIs through to +// an SkCanvas. This is more efficient than recording to a PaintRecord +// and then playing back to an SkCanvas. +class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas { + public: + explicit SkiaPaintCanvas(SkCanvas* canvas); + explicit SkiaPaintCanvas(const SkBitmap& bitmap); + explicit SkiaPaintCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props); + explicit SkiaPaintCanvas(SkiaPaintCanvas&& other); + ~SkiaPaintCanvas() override; + + SkiaPaintCanvas& operator=(SkiaPaintCanvas&& other) = default; + + SkMetaData& getMetaData() override; + SkImageInfo imageInfo() const override; + + void flush() override; + + SkISize getBaseLayerSize() const override; + bool writePixels(const SkImageInfo& info, + const void* pixels, + size_t row_bytes, + int x, + int y) override; + int save() override; + int saveLayer(const SkRect* bounds, const PaintFlags* flags) override; + int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) override; + + void restore() override; + int getSaveCount() const override; + void restoreToCount(int save_count) override; + void translate(SkScalar dx, SkScalar dy) override; + void scale(SkScalar sx, SkScalar sy) override; + void rotate(SkScalar degrees) override; + void concat(const SkMatrix& matrix) override; + void setMatrix(const SkMatrix& matrix) override; + + void clipRect(const SkRect& rect, SkClipOp op, bool do_anti_alias) override; + void clipRRect(const SkRRect& rrect, + SkClipOp op, + bool do_anti_alias) override; + void clipPath(const SkPath& path, SkClipOp op, bool do_anti_alias) override; + bool quickReject(const SkRect& rect) const override; + bool quickReject(const SkPath& path) const override; + SkRect getLocalClipBounds() const override; + bool getLocalClipBounds(SkRect* bounds) const override; + SkIRect getDeviceClipBounds() const override; + bool getDeviceClipBounds(SkIRect* bounds) const override; + void drawColor(SkColor color, SkBlendMode mode) override; + void clear(SkColor color) override; + + void drawLine(SkScalar x0, + SkScalar y0, + SkScalar x1, + SkScalar y1, + const PaintFlags& flags) override; + void drawRect(const SkRect& rect, const PaintFlags& flags) override; + void drawIRect(const SkIRect& rect, const PaintFlags& flags) override; + void drawOval(const SkRect& oval, const PaintFlags& flags) override; + void drawRRect(const SkRRect& rrect, const PaintFlags& flags) override; + void drawDRRect(const SkRRect& outer, + const SkRRect& inner, + const PaintFlags& flags) override; + void drawCircle(SkScalar cx, + SkScalar cy, + SkScalar radius, + const PaintFlags& flags) override; + void drawArc(const SkRect& oval, + SkScalar start_angle, + SkScalar sweep_angle, + bool use_center, + const PaintFlags& flags) override; + void drawRoundRect(const SkRect& rect, + SkScalar rx, + SkScalar ry, + const PaintFlags& flags) override; + void drawPath(const SkPath& path, const PaintFlags& flags) override; + void drawImage(sk_sp<const SkImage> image, + SkScalar left, + SkScalar top, + const PaintFlags* flags) override; + void drawImageRect(sk_sp<const SkImage> image, + const SkRect& src, + const SkRect& dst, + const PaintFlags* flags, + SrcRectConstraint constraint) override; + void drawBitmap(const SkBitmap& bitmap, + SkScalar left, + SkScalar top, + const PaintFlags* flags) override; + + void drawText(const void* text, + size_t byte_length, + SkScalar x, + SkScalar y, + const PaintFlags& flags) override; + void drawPosText(const void* text, + size_t byte_length, + const SkPoint pos[], + const PaintFlags& flags) override; + void drawTextBlob(sk_sp<SkTextBlob> blob, + SkScalar x, + SkScalar y, + const PaintFlags& flags) override; + + void drawDisplayItemList( + scoped_refptr<DisplayItemList> display_item_list) override; + + void drawPicture(sk_sp<const PaintRecord> record) override; + + bool isClipEmpty() const override; + bool isClipRect() const override; + const SkMatrix& getTotalMatrix() const override; + + void temporary_internal_describeTopLayer(SkMatrix* matrix, + SkIRect* clip_bounds) override; + + bool ToPixmap(SkPixmap* output) override; + void Annotate(AnnotationType type, + const SkRect& rect, + sk_sp<SkData> data) override; + + void PlaybackPaintRecord(sk_sp<const PaintRecord> record) override; + + // Don't shadow non-virtual helper functions. + using PaintCanvas::clipRect; + using PaintCanvas::clipRRect; + using PaintCanvas::clipPath; + using PaintCanvas::drawBitmap; + using PaintCanvas::drawColor; + using PaintCanvas::drawImage; + using PaintCanvas::drawPicture; + + private: + SkCanvas* canvas_; + std::unique_ptr<SkCanvas> owned_; + + DISALLOW_COPY_AND_ASSIGN(SkiaPaintCanvas); +}; + +} // namespace cc + +#endif // CC_PAINT_SKIA_PAINT_CANVAS_H_ diff --git a/chromium/cc/paint/transform_display_item.cc b/chromium/cc/paint/transform_display_item.cc new file mode 100644 index 00000000000..6cc3e7f2d1e --- /dev/null +++ b/chromium/cc/paint/transform_display_item.cc @@ -0,0 +1,20 @@ +// 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/paint/transform_display_item.h" + +namespace cc { + +TransformDisplayItem::TransformDisplayItem(const gfx::Transform& transform) + + : DisplayItem(TRANSFORM), transform(transform) {} + +TransformDisplayItem::~TransformDisplayItem() = default; + +EndTransformDisplayItem::EndTransformDisplayItem() + : DisplayItem(END_TRANSFORM) {} + +EndTransformDisplayItem::~EndTransformDisplayItem() = default; + +} // namespace cc diff --git a/chromium/cc/paint/transform_display_item.h b/chromium/cc/paint/transform_display_item.h new file mode 100644 index 00000000000..a75db2a4d87 --- /dev/null +++ b/chromium/cc/paint/transform_display_item.h @@ -0,0 +1,37 @@ +// 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_PAINT_TRANSFORM_DISPLAY_ITEM_H_ +#define CC_PAINT_TRANSFORM_DISPLAY_ITEM_H_ + +#include <stddef.h> + +#include "cc/paint/display_item.h" +#include "cc/paint/paint_export.h" +#include "ui/gfx/transform.h" + +namespace cc { + +class CC_PAINT_EXPORT TransformDisplayItem : public DisplayItem { + public: + explicit TransformDisplayItem(const gfx::Transform& transform); + ~TransformDisplayItem() override; + + size_t ExternalMemoryUsage() const { return 0; } + int ApproximateOpCount() const { return 1; } + + const gfx::Transform transform; +}; + +class CC_PAINT_EXPORT EndTransformDisplayItem : public DisplayItem { + public: + EndTransformDisplayItem(); + ~EndTransformDisplayItem() override; + + int ApproximateOpCount() const { return 0; } +}; + +} // namespace cc + +#endif // CC_PAINT_TRANSFORM_DISPLAY_ITEM_H_ diff --git a/chromium/cc/playback/OWNERS b/chromium/cc/playback/OWNERS deleted file mode 100644 index bdd83bf7316..00000000000 --- a/chromium/cc/playback/OWNERS +++ /dev/null @@ -1 +0,0 @@ -# COMPONENT: Internals>Compositing>Rasterization diff --git a/chromium/cc/playback/clip_display_item.cc b/chromium/cc/playback/clip_display_item.cc deleted file mode 100644 index 4b4f0df4a23..00000000000 --- a/chromium/cc/playback/clip_display_item.cc +++ /dev/null @@ -1,95 +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/playback/clip_display_item.h" - -#include <stddef.h> - -#include <string> - -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event_argument.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "ui/gfx/skia_util.h" - -namespace cc { -class ImageSerializationProcessor; - -ClipDisplayItem::ClipDisplayItem(const gfx::Rect& clip_rect, - const std::vector<SkRRect>& rounded_clip_rects, - bool antialias) - : DisplayItem(CLIP) { - SetNew(clip_rect, rounded_clip_rects, antialias); -} - -void ClipDisplayItem::SetNew(const gfx::Rect& clip_rect, - const std::vector<SkRRect>& rounded_clip_rects, - bool antialias) { - clip_rect_ = clip_rect; - rounded_clip_rects_ = rounded_clip_rects; - antialias_ = antialias; -} - -ClipDisplayItem::~ClipDisplayItem() {} - -void ClipDisplayItem::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->save(); - canvas->clipRect(gfx::RectToSkRect(clip_rect_), antialias_); - for (size_t i = 0; i < rounded_clip_rects_.size(); ++i) { - if (rounded_clip_rects_[i].isRect()) { - canvas->clipRect(rounded_clip_rects_[i].rect(), antialias_); - } else { - canvas->clipRRect(rounded_clip_rects_[i], antialias_); - } - } -} - -void ClipDisplayItem::AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - std::string value = base::StringPrintf( - "ClipDisplayItem rect: [%s] visualRect: [%s]", - clip_rect_.ToString().c_str(), visual_rect.ToString().c_str()); - for (const SkRRect& rounded_rect : rounded_clip_rects_) { - base::StringAppendF( - &value, " rounded_rect: [rect: [%s]", - gfx::SkRectToRectF(rounded_rect.rect()).ToString().c_str()); - base::StringAppendF(&value, " radii: ["); - SkVector upper_left_radius = rounded_rect.radii(SkRRect::kUpperLeft_Corner); - base::StringAppendF(&value, "[%f,%f],", upper_left_radius.x(), - upper_left_radius.y()); - SkVector upper_right_radius = - rounded_rect.radii(SkRRect::kUpperRight_Corner); - base::StringAppendF(&value, " [%f,%f],", upper_right_radius.x(), - upper_right_radius.y()); - SkVector lower_right_radius = - rounded_rect.radii(SkRRect::kLowerRight_Corner); - base::StringAppendF(&value, " [%f,%f],", lower_right_radius.x(), - lower_right_radius.y()); - SkVector lower_left_radius = rounded_rect.radii(SkRRect::kLowerLeft_Corner); - base::StringAppendF(&value, " [%f,%f]]", lower_left_radius.x(), - lower_left_radius.y()); - } - array->AppendString(value); -} - -EndClipDisplayItem::EndClipDisplayItem() : DisplayItem(END_CLIP) {} - -EndClipDisplayItem::~EndClipDisplayItem() { -} - -void EndClipDisplayItem::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->restore(); -} - -void EndClipDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString(base::StringPrintf("EndClipDisplayItem visualRect: [%s]", - visual_rect.ToString().c_str())); -} - -} // namespace cc diff --git a/chromium/cc/playback/clip_display_item.h b/chromium/cc/playback/clip_display_item.h deleted file mode 100644 index 8ab86aeeaeb..00000000000 --- a/chromium/cc/playback/clip_display_item.h +++ /dev/null @@ -1,64 +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_PLAYBACK_CLIP_DISPLAY_ITEM_H_ -#define CC_PLAYBACK_CLIP_DISPLAY_ITEM_H_ - -#include <stddef.h> - -#include <memory> -#include <vector> - -#include "cc/base/cc_export.h" -#include "cc/playback/display_item.h" -#include "third_party/skia/include/core/SkRRect.h" -#include "ui/gfx/geometry/rect.h" - -class SkCanvas; - -namespace cc { - -class CC_EXPORT ClipDisplayItem : public DisplayItem { - public: - ClipDisplayItem(const gfx::Rect& clip_rect, - const std::vector<SkRRect>& rounded_clip_rects, - bool antialias); - ~ClipDisplayItem() override; - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - size_t ExternalMemoryUsage() const { - return rounded_clip_rects_.capacity() * sizeof(rounded_clip_rects_[0]); - } - int ApproximateOpCount() const { return 1; } - - private: - void SetNew(const gfx::Rect& clip_rect, - const std::vector<SkRRect>& rounded_clip_rects, - bool antialias); - - gfx::Rect clip_rect_; - std::vector<SkRRect> rounded_clip_rects_; - bool antialias_; -}; - -class CC_EXPORT EndClipDisplayItem : public DisplayItem { - public: - EndClipDisplayItem(); - ~EndClipDisplayItem() override; - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - int ApproximateOpCount() const { return 0; } -}; - -} // namespace cc - -#endif // CC_PLAYBACK_CLIP_DISPLAY_ITEM_H_ diff --git a/chromium/cc/playback/clip_path_display_item.cc b/chromium/cc/playback/clip_path_display_item.cc deleted file mode 100644 index c7bbcce7d28..00000000000 --- a/chromium/cc/playback/clip_path_display_item.cc +++ /dev/null @@ -1,64 +0,0 @@ -// 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/clip_path_display_item.h" - -#include <stddef.h> -#include <stdint.h> - -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event_argument.h" -#include "third_party/skia/include/core/SkCanvas.h" - -namespace cc { - -ClipPathDisplayItem::ClipPathDisplayItem(const SkPath& clip_path, - bool antialias) - : DisplayItem(CLIP_PATH) { - SetNew(clip_path, antialias); -} - -ClipPathDisplayItem::~ClipPathDisplayItem() { -} - -void ClipPathDisplayItem::SetNew(const SkPath& clip_path, - bool antialias) { - clip_path_ = clip_path; - antialias_ = antialias; -} - -void ClipPathDisplayItem::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->save(); - canvas->clipPath(clip_path_, antialias_); -} - -void ClipPathDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString(base::StringPrintf( - "ClipPathDisplayItem length: %d visualRect: [%s]", - clip_path_.countPoints(), visual_rect.ToString().c_str())); -} - -EndClipPathDisplayItem::EndClipPathDisplayItem() : DisplayItem(END_CLIP_PATH) {} - -EndClipPathDisplayItem::~EndClipPathDisplayItem() { -} - -void EndClipPathDisplayItem::Raster( - SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->restore(); -} - -void EndClipPathDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString( - base::StringPrintf("EndClipPathDisplayItem visualRect: [%s]", - visual_rect.ToString().c_str())); -} - -} // namespace cc diff --git a/chromium/cc/playback/clip_path_display_item.h b/chromium/cc/playback/clip_path_display_item.h deleted file mode 100644 index f736b023148..00000000000 --- a/chromium/cc/playback/clip_path_display_item.h +++ /dev/null @@ -1,64 +0,0 @@ -// 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_CLIP_PATH_DISPLAY_ITEM_H_ -#define CC_PLAYBACK_CLIP_PATH_DISPLAY_ITEM_H_ - -#include <stddef.h> - -#include <memory> - -#include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" -#include "cc/playback/display_item.h" -#include "third_party/skia/include/core/SkPath.h" - -class SkCanvas; - -namespace cc { - -class CC_EXPORT ClipPathDisplayItem : public DisplayItem { - public: - ClipPathDisplayItem(const SkPath& path, bool antialias); - ~ClipPathDisplayItem() override; - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - size_t ExternalMemoryUsage() const { - // The size of SkPath's external storage is not currently accounted for (and - // may well be shared anyway). - return 0; - } - int ApproximateOpCount() const { return 1; } - - private: - void SetNew(const SkPath& path, bool antialias); - - SkPath clip_path_; - bool antialias_; -}; - -class CC_EXPORT EndClipPathDisplayItem : public DisplayItem { - public: - EndClipPathDisplayItem(); - ~EndClipPathDisplayItem() override; - - static std::unique_ptr<EndClipPathDisplayItem> Create() { - return base::MakeUnique<EndClipPathDisplayItem>(); - } - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - int ApproximateOpCount() const { return 0; } -}; - -} // namespace cc - -#endif // CC_PLAYBACK_CLIP_PATH_DISPLAY_ITEM_H_ diff --git a/chromium/cc/playback/compositing_display_item.cc b/chromium/cc/playback/compositing_display_item.cc deleted file mode 100644 index 628ab5617aa..00000000000 --- a/chromium/cc/playback/compositing_display_item.cc +++ /dev/null @@ -1,99 +0,0 @@ -// 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/compositing_display_item.h" - -#include <stddef.h> -#include <stdint.h> - -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event_argument.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkData.h" -#include "third_party/skia/include/core/SkFlattenable.h" -#include "third_party/skia/include/core/SkFlattenableSerialization.h" -#include "third_party/skia/include/core/SkPaint.h" - -#include "ui/gfx/skia_util.h" - -namespace cc { - -CompositingDisplayItem::CompositingDisplayItem( - uint8_t alpha, - SkBlendMode xfermode, - SkRect* bounds, - sk_sp<SkColorFilter> cf, - bool lcd_text_requires_opaque_layer) - : DisplayItem(COMPOSITING) { - SetNew(alpha, xfermode, bounds, std::move(cf), - lcd_text_requires_opaque_layer); -} - -CompositingDisplayItem::~CompositingDisplayItem() { -} - -void CompositingDisplayItem::SetNew(uint8_t alpha, - SkBlendMode xfermode, - SkRect* bounds, - sk_sp<SkColorFilter> cf, - bool lcd_text_requires_opaque_layer) { - alpha_ = alpha; - xfermode_ = xfermode; - has_bounds_ = !!bounds; - if (bounds) - bounds_ = SkRect(*bounds); - color_filter_ = std::move(cf); - lcd_text_requires_opaque_layer_ = lcd_text_requires_opaque_layer; -} - -void CompositingDisplayItem::Raster( - SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - SkPaint paint; - paint.setBlendMode(xfermode_); - paint.setAlpha(alpha_); - paint.setColorFilter(color_filter_); - const SkRect* bounds = has_bounds_ ? &bounds_ : nullptr; - if (lcd_text_requires_opaque_layer_) - canvas->saveLayer(bounds, &paint); - else - canvas->saveLayerPreserveLCDTextRequests(bounds, &paint); -} - -void CompositingDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - std::string info = base::StringPrintf( - "CompositingDisplayItem alpha: %d, xfermode: %d, visualRect: [%s]", - alpha_, static_cast<int>(xfermode_), visual_rect.ToString().c_str()); - if (has_bounds_) { - base::StringAppendF( - &info, ", bounds: [%f, %f, %f, %f]", static_cast<float>(bounds_.x()), - static_cast<float>(bounds_.y()), static_cast<float>(bounds_.width()), - static_cast<float>(bounds_.height())); - } - array->AppendString(info); -} - -EndCompositingDisplayItem::EndCompositingDisplayItem() - : DisplayItem(END_COMPOSITING) {} - -EndCompositingDisplayItem::~EndCompositingDisplayItem() { -} - -void EndCompositingDisplayItem::Raster( - SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->restore(); -} - -void EndCompositingDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString( - base::StringPrintf("EndCompositingDisplayItem visualRect: [%s]", - visual_rect.ToString().c_str())); -} - -} // namespace cc diff --git a/chromium/cc/playback/compositing_display_item.h b/chromium/cc/playback/compositing_display_item.h deleted file mode 100644 index d562e5ed288..00000000000 --- a/chromium/cc/playback/compositing_display_item.h +++ /dev/null @@ -1,79 +0,0 @@ -// 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_COMPOSITING_DISPLAY_ITEM_H_ -#define CC_PLAYBACK_COMPOSITING_DISPLAY_ITEM_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <memory> - -#include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" -#include "cc/playback/display_item.h" -#include "third_party/skia/include/core/SkColorFilter.h" -#include "third_party/skia/include/core/SkRect.h" -#include "third_party/skia/include/core/SkRefCnt.h" -#include "ui/gfx/geometry/rect_f.h" - -class SkCanvas; - -namespace cc { - -class CC_EXPORT CompositingDisplayItem : public DisplayItem { - public: - CompositingDisplayItem(uint8_t alpha, - SkBlendMode xfermode, - SkRect* bounds, - sk_sp<SkColorFilter> color_filter, - bool lcd_text_requires_opaque_layer); - ~CompositingDisplayItem() override; - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - size_t ExternalMemoryUsage() const { - // TODO(pdr): Include color_filter's memory here. - return 0; - } - int ApproximateOpCount() const { return 1; } - - private: - void SetNew(uint8_t alpha, - SkBlendMode xfermode, - SkRect* bounds, - sk_sp<SkColorFilter> color_filter, - bool lcd_text_requires_opaque_layer); - - uint8_t alpha_; - SkBlendMode xfermode_; - bool has_bounds_; - SkRect bounds_; - sk_sp<SkColorFilter> color_filter_; - bool lcd_text_requires_opaque_layer_; -}; - -class CC_EXPORT EndCompositingDisplayItem : public DisplayItem { - public: - EndCompositingDisplayItem(); - ~EndCompositingDisplayItem() override; - - static std::unique_ptr<EndCompositingDisplayItem> Create() { - return base::MakeUnique<EndCompositingDisplayItem>(); - } - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - int ApproximateOpCount() const { return 0; } -}; - -} // namespace cc - -#endif // CC_PLAYBACK_COMPOSITING_DISPLAY_ITEM_H_ diff --git a/chromium/cc/playback/display_item_list.cc b/chromium/cc/playback/display_item_list.cc deleted file mode 100644 index dc40961fc7c..00000000000 --- a/chromium/cc/playback/display_item_list.cc +++ /dev/null @@ -1,265 +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/playback/display_item_list.h" - -#include <stddef.h> - -#include <string> - -#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" -#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_value.h" -#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/drawing_display_item.h" -#include "cc/playback/filter_display_item.h" -#include "cc/playback/float_clip_display_item.h" -#include "cc/playback/largest_display_item.h" -#include "cc/playback/transform_display_item.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkPictureRecorder.h" -#include "third_party/skia/include/utils/SkPictureUtils.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/skia_util.h" - -namespace cc { - -namespace { - -// We don't perform per-layer solid color analysis when there are too many skia -// operations. -const int kOpCountThatIsOkToAnalyze = 10; - -bool DisplayItemsTracingEnabled() { - bool tracing_enabled; - TRACE_EVENT_CATEGORY_GROUP_ENABLED( - TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items"), &tracing_enabled); - return tracing_enabled; -} - -bool GetCanvasClipBounds(SkCanvas* canvas, gfx::Rect* clip_bounds) { - SkRect canvas_clip_bounds; - if (!canvas->getLocalClipBounds(&canvas_clip_bounds)) - return false; - *clip_bounds = ToEnclosingRect(gfx::SkRectToRectF(canvas_clip_bounds)); - return true; -} - -const int kDefaultNumDisplayItemsToReserve = 100; - -} // namespace - -DisplayItemList::Inputs::Inputs() - : items(LargestDisplayItemSize(), - LargestDisplayItemSize() * kDefaultNumDisplayItemsToReserve) {} - -DisplayItemList::Inputs::~Inputs() = default; - -DisplayItemList::DisplayItemList() = default; - -DisplayItemList::~DisplayItemList() = default; - -void DisplayItemList::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback, - const gfx::Rect& canvas_target_playback_rect, - float contents_scale) const { - canvas->save(); - if (!canvas_target_playback_rect.IsEmpty()) { - // canvas_target_playback_rect is specified in device space. We can't - // use clipRect because canvas CTM will be applied on it. Use clipRegion - // instead because it ignores canvas CTM. - SkRegion device_clip; - device_clip.setRect(gfx::RectToSkIRect(canvas_target_playback_rect)); - canvas->clipRegion(device_clip); - } - canvas->scale(contents_scale, contents_scale); - Raster(canvas, callback); - canvas->restore(); -} - -DISABLE_CFI_PERF -void DisplayItemList::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - gfx::Rect canvas_playback_rect; - if (!GetCanvasClipBounds(canvas, &canvas_playback_rect)) - return; - - std::vector<size_t> indices; - rtree_.Search(canvas_playback_rect, &indices); - for (size_t index : indices) { - inputs_.items[index].Raster(canvas, callback); - // We use a callback during solid color analysis on the compositor thread to - // break out early. Since we're handling a sequence of pictures via rtree - // query results ourselves, we have to respect the callback and early out. - if (callback && callback->abort()) - break; - } -} - -void DisplayItemList::GrowCurrentBeginItemVisualRect( - const gfx::Rect& visual_rect) { - if (!inputs_.begin_item_indices.empty()) - inputs_.visual_rects[inputs_.begin_item_indices.back()].Union(visual_rect); -} - -void DisplayItemList::Finalize() { - TRACE_EVENT0("cc", "DisplayItemList::Finalize"); - DCHECK(inputs_.items.size() == inputs_.visual_rects.size()) - << "items.size() " << inputs_.items.size() << " visual_rects.size() " - << inputs_.visual_rects.size(); - rtree_.Build(inputs_.visual_rects); - - if (!retain_visual_rects_) - // This clears both the vector and the vector's capacity, since - // visual_rects won't be used anymore. - std::vector<gfx::Rect>().swap(inputs_.visual_rects); -} - -bool DisplayItemList::IsSuitableForGpuRasterization() const { - // TODO(wkorman): 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. See crbug.com/513016. - return inputs_.all_items_are_suitable_for_gpu_rasterization; -} - -int DisplayItemList::ApproximateOpCount() const { - return approximate_op_count_; -} - -size_t DisplayItemList::ApproximateMemoryUsage() const { - size_t memory_usage = sizeof(*this); - - size_t external_memory_usage = 0; - for (const auto& item : inputs_.items) { - size_t bytes = 0; - switch (item.type()) { - case DisplayItem::CLIP: - bytes = static_cast<const ClipDisplayItem&>(item).ExternalMemoryUsage(); - break; - case DisplayItem::CLIP_PATH: - bytes = - static_cast<const ClipPathDisplayItem&>(item).ExternalMemoryUsage(); - break; - case DisplayItem::COMPOSITING: - bytes = static_cast<const CompositingDisplayItem&>(item) - .ExternalMemoryUsage(); - break; - case DisplayItem::DRAWING: - bytes = - static_cast<const DrawingDisplayItem&>(item).ExternalMemoryUsage(); - break; - case DisplayItem::FLOAT_CLIP: - bytes = static_cast<const FloatClipDisplayItem&>(item) - .ExternalMemoryUsage(); - break; - case DisplayItem::FILTER: - bytes = - static_cast<const FilterDisplayItem&>(item).ExternalMemoryUsage(); - break; - case DisplayItem::TRANSFORM: - bytes = static_cast<const TransformDisplayItem&>(item) - .ExternalMemoryUsage(); - break; - case DisplayItem::END_CLIP: - case DisplayItem::END_CLIP_PATH: - case DisplayItem::END_COMPOSITING: - case DisplayItem::END_FLOAT_CLIP: - case DisplayItem::END_FILTER: - case DisplayItem::END_TRANSFORM: - break; - } - external_memory_usage += bytes; - } - - // Memory outside this class due to |items_|. - memory_usage += inputs_.items.GetCapacityInBytes() + external_memory_usage; - - // TODO(jbroman): Does anything else owned by this class substantially - // contribute to memory usage? - // TODO(vmpstr): Probably DiscardableImageMap is worth counting here. - - return memory_usage; -} - -bool DisplayItemList::ShouldBeAnalyzedForSolidColor() const { - return ApproximateOpCount() <= kOpCountThatIsOkToAnalyze; -} - -std::unique_ptr<base::trace_event::ConvertableToTraceFormat> -DisplayItemList::AsValue(bool include_items) const { - std::unique_ptr<base::trace_event::TracedValue> state( - new base::trace_event::TracedValue()); - - state->BeginDictionary("params"); - if (include_items) { - state->BeginArray("items"); - size_t item_index = 0; - for (const DisplayItem& item : inputs_.items) { - item.AsValueInto(item_index < inputs_.visual_rects.size() - ? inputs_.visual_rects[item_index] - : gfx::Rect(), - state.get()); - item_index++; - } - state->EndArray(); // "items". - } - MathUtil::AddToTracedValue("layer_rect", rtree_.GetBounds(), state.get()); - state->EndDictionary(); // "params". - - SkPictureRecorder recorder; - gfx::Rect bounds = rtree_.GetBounds(); - SkCanvas* canvas = recorder.beginRecording(bounds.width(), bounds.height()); - canvas->translate(-bounds.x(), -bounds.y()); - canvas->clipRect(gfx::RectToSkRect(bounds)); - Raster(canvas, nullptr, gfx::Rect(), 1.f); - sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); - - std::string b64_picture; - PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture); - state->SetString("skp64", b64_picture); - - return std::move(state); -} - -void DisplayItemList::EmitTraceSnapshot() const { - 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, - TracedDisplayItemList::AsTraceableDisplayItemList(this, - DisplayItemsTracingEnabled())); -} - -void DisplayItemList::GenerateDiscardableImagesMetadata() { - // This should be only called once. - DCHECK(image_map_.empty()); - - gfx::Rect bounds = rtree_.GetBounds(); - DiscardableImageMap::ScopedMetadataGenerator generator( - &image_map_, gfx::Size(bounds.right(), bounds.bottom())); - Raster(generator.canvas(), nullptr, gfx::Rect(), 1.f); -} - -void DisplayItemList::GetDiscardableImagesInRect( - const gfx::Rect& rect, - float contents_scale, - std::vector<DrawImage>* images) { - image_map_.GetDiscardableImagesInRect(rect, contents_scale, images); -} - -gfx::Rect DisplayItemList::GetRectForImage(ImageId image_id) const { - return image_map_.GetRectForImage(image_id); -} - -} // namespace cc diff --git a/chromium/cc/playback/drawing_display_item.cc b/chromium/cc/playback/drawing_display_item.cc deleted file mode 100644 index 90f1030dec1..00000000000 --- a/chromium/cc/playback/drawing_display_item.cc +++ /dev/null @@ -1,97 +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/playback/drawing_display_item.h" - -#include <stddef.h> - -#include <string> - -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_argument.h" -#include "base/values.h" -#include "cc/debug/picture_debug_util.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/utils/SkPictureUtils.h" -#include "ui/gfx/skia_util.h" - -namespace cc { - -DrawingDisplayItem::DrawingDisplayItem() : DisplayItem(DRAWING) {} - -DrawingDisplayItem::DrawingDisplayItem(sk_sp<const PaintRecord> record) - : DisplayItem(DRAWING) { - SetNew(std::move(record)); -} - -DrawingDisplayItem::DrawingDisplayItem(const DrawingDisplayItem& item) - : DisplayItem(DRAWING) { - item.CloneTo(this); -} - -DrawingDisplayItem::~DrawingDisplayItem() { -} - -void DrawingDisplayItem::SetNew(sk_sp<const PaintRecord> record) { - picture_ = std::move(record); -} - -DISABLE_CFI_PERF -void DrawingDisplayItem::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - if (canvas->quickReject(picture_->cullRect())) - return; - - // SkPicture always does a wrapping save/restore on the canvas, so it is not - // necessary here. - if (callback) { - picture_->playback(canvas, callback); - } else { - // TODO(enne): switch this to playback once PaintRecord is real. - canvas->drawPicture(ToSkPicture(picture_.get())); - } -} - -void DrawingDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->BeginDictionary(); - array->SetString("name", "DrawingDisplayItem"); - - array->BeginArray("visualRect"); - array->AppendInteger(visual_rect.x()); - array->AppendInteger(visual_rect.y()); - array->AppendInteger(visual_rect.width()); - array->AppendInteger(visual_rect.height()); - array->EndArray(); - - array->BeginArray("cullRect"); - array->AppendInteger(picture_->cullRect().x()); - array->AppendInteger(picture_->cullRect().y()); - array->AppendInteger(picture_->cullRect().width()); - array->AppendInteger(picture_->cullRect().height()); - array->EndArray(); - - std::string b64_picture; - PictureDebugUtil::SerializeAsBase64(ToSkPicture(picture_.get()), - &b64_picture); - array->SetString("skp64", b64_picture); - array->EndDictionary(); -} - -void DrawingDisplayItem::CloneTo(DrawingDisplayItem* item) const { - item->SetNew(picture_); -} - -size_t DrawingDisplayItem::ExternalMemoryUsage() const { - return picture_->approximateBytesUsed(); -} - -DISABLE_CFI_PERF -int DrawingDisplayItem::ApproximateOpCount() const { - return picture_->approximateOpCount(); -} - -} // namespace cc diff --git a/chromium/cc/playback/drawing_display_item.h b/chromium/cc/playback/drawing_display_item.h deleted file mode 100644 index ef5f4d57d65..00000000000 --- a/chromium/cc/playback/drawing_display_item.h +++ /dev/null @@ -1,48 +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_PLAYBACK_DRAWING_DISPLAY_ITEM_H_ -#define CC_PLAYBACK_DRAWING_DISPLAY_ITEM_H_ - -#include <stddef.h> - -#include <memory> -#include <vector> - -#include "cc/base/cc_export.h" -#include "cc/paint/paint_record.h" -#include "cc/playback/display_item.h" -#include "third_party/skia/include/core/SkRefCnt.h" -#include "ui/gfx/geometry/point_f.h" - -class SkCanvas; - -namespace cc { - -class CC_EXPORT DrawingDisplayItem : public DisplayItem { - public: - DrawingDisplayItem(); - explicit DrawingDisplayItem(sk_sp<const PaintRecord> record); - explicit DrawingDisplayItem(const DrawingDisplayItem& item); - ~DrawingDisplayItem() override; - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - size_t ExternalMemoryUsage() const; - int ApproximateOpCount() const; - - void CloneTo(DrawingDisplayItem* item) const; - - private: - void SetNew(sk_sp<const PaintRecord> record); - - sk_sp<const PaintRecord> picture_; -}; - -} // namespace cc - -#endif // CC_PLAYBACK_DRAWING_DISPLAY_ITEM_H_ diff --git a/chromium/cc/playback/filter_display_item.cc b/chromium/cc/playback/filter_display_item.cc deleted file mode 100644 index 3e9d9f161bc..00000000000 --- a/chromium/cc/playback/filter_display_item.cc +++ /dev/null @@ -1,81 +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/playback/filter_display_item.h" - -#include <stddef.h> - -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event_argument.h" -#include "cc/output/render_surface_filters.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkImageFilter.h" -#include "third_party/skia/include/core/SkPaint.h" -#include "third_party/skia/include/core/SkRefCnt.h" -#include "ui/gfx/skia_util.h" - -namespace cc { - -FilterDisplayItem::FilterDisplayItem(const FilterOperations& filters, - const gfx::RectF& bounds, - const gfx::PointF& origin) - : DisplayItem(FILTER) { - SetNew(filters, bounds, origin); -} - -FilterDisplayItem::~FilterDisplayItem() {} - -void FilterDisplayItem::SetNew(const FilterOperations& filters, - const gfx::RectF& bounds, - const gfx::PointF& origin) { - filters_ = filters; - bounds_ = bounds; - origin_ = origin; -} - -void FilterDisplayItem::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->save(); - canvas->translate(origin_.x(), origin_.y()); - - sk_sp<SkImageFilter> image_filter = RenderSurfaceFilters::BuildImageFilter( - filters_, gfx::SizeF(bounds_.width(), bounds_.height())); - SkRect boundaries = RectFToSkRect(bounds_); - boundaries.offset(-origin_.x(), -origin_.y()); - - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrcOver); - paint.setImageFilter(std::move(image_filter)); - canvas->saveLayer(&boundaries, &paint); - - canvas->translate(-origin_.x(), -origin_.y()); -} - -void FilterDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString(base::StringPrintf( - "FilterDisplayItem bounds: [%s] visualRect: [%s]", - bounds_.ToString().c_str(), visual_rect.ToString().c_str())); -} - -EndFilterDisplayItem::EndFilterDisplayItem() : DisplayItem(END_FILTER) {} - -EndFilterDisplayItem::~EndFilterDisplayItem() {} - -void EndFilterDisplayItem::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->restore(); - canvas->restore(); -} - -void EndFilterDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString( - base::StringPrintf("EndFilterDisplayItem visualRect: [%s]", - visual_rect.ToString().c_str())); -} - -} // namespace cc diff --git a/chromium/cc/playback/filter_display_item.h b/chromium/cc/playback/filter_display_item.h deleted file mode 100644 index 6cc77a0dcca..00000000000 --- a/chromium/cc/playback/filter_display_item.h +++ /dev/null @@ -1,70 +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_PLAYBACK_FILTER_DISPLAY_ITEM_H_ -#define CC_PLAYBACK_FILTER_DISPLAY_ITEM_H_ - -#include <stddef.h> - -#include <memory> - -#include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" -#include "cc/output/filter_operations.h" -#include "cc/playback/display_item.h" -#include "ui/gfx/geometry/rect_f.h" - -class SkCanvas; - -namespace cc { - -class CC_EXPORT FilterDisplayItem : public DisplayItem { - public: - FilterDisplayItem(const FilterOperations& filters, - const gfx::RectF& bounds, - const gfx::PointF& origin); - ~FilterDisplayItem() override; - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - size_t ExternalMemoryUsage() const { - // FilterOperations doesn't expose its capacity, but size is probably good - // enough. - return filters_.size() * sizeof(filters_.at(0)); - } - int ApproximateOpCount() const { return 1; } - - private: - void SetNew(const FilterOperations& filters, - const gfx::RectF& bounds, - const gfx::PointF& origin); - - FilterOperations filters_; - gfx::RectF bounds_; - gfx::PointF origin_; -}; - -class CC_EXPORT EndFilterDisplayItem : public DisplayItem { - public: - EndFilterDisplayItem(); - ~EndFilterDisplayItem() override; - - static std::unique_ptr<EndFilterDisplayItem> Create() { - return base::MakeUnique<EndFilterDisplayItem>(); - } - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - int ApproximateOpCount() const { return 0; } -}; - -} // namespace cc - -#endif // CC_PLAYBACK_FILTER_DISPLAY_ITEM_H_ diff --git a/chromium/cc/playback/float_clip_display_item.cc b/chromium/cc/playback/float_clip_display_item.cc deleted file mode 100644 index 648bb0a315f..00000000000 --- a/chromium/cc/playback/float_clip_display_item.cc +++ /dev/null @@ -1,62 +0,0 @@ -// 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/float_clip_display_item.h" - -#include <stddef.h> - -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event_argument.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "ui/gfx/skia_util.h" - -namespace cc { - -FloatClipDisplayItem::FloatClipDisplayItem(const gfx::RectF& clip_rect) - : DisplayItem(FLOAT_CLIP) { - SetNew(clip_rect); -} - -FloatClipDisplayItem::~FloatClipDisplayItem() { -} - -void FloatClipDisplayItem::SetNew(const gfx::RectF& clip_rect) { - clip_rect_ = clip_rect; -} - -void FloatClipDisplayItem::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->save(); - canvas->clipRect(gfx::RectFToSkRect(clip_rect_)); -} - -void FloatClipDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString(base::StringPrintf( - "FloatClipDisplayItem rect: [%s] visualRect: [%s]", - clip_rect_.ToString().c_str(), visual_rect.ToString().c_str())); -} - -EndFloatClipDisplayItem::EndFloatClipDisplayItem() - : DisplayItem(END_FLOAT_CLIP) {} - -EndFloatClipDisplayItem::~EndFloatClipDisplayItem() { -} - -void EndFloatClipDisplayItem::Raster( - SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->restore(); -} - -void EndFloatClipDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString( - base::StringPrintf("EndFloatClipDisplayItem visualRect: [%s]", - visual_rect.ToString().c_str())); -} - -} // namespace cc diff --git a/chromium/cc/playback/float_clip_display_item.h b/chromium/cc/playback/float_clip_display_item.h deleted file mode 100644 index 6233d3cebce..00000000000 --- a/chromium/cc/playback/float_clip_display_item.h +++ /dev/null @@ -1,60 +0,0 @@ -// 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_FLOAT_CLIP_DISPLAY_ITEM_H_ -#define CC_PLAYBACK_FLOAT_CLIP_DISPLAY_ITEM_H_ - -#include <stddef.h> - -#include <memory> -#include <vector> - -#include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" -#include "cc/playback/display_item.h" -#include "ui/gfx/geometry/rect_f.h" - -class SkCanvas; - -namespace cc { - -class CC_EXPORT FloatClipDisplayItem : public DisplayItem { - public: - explicit FloatClipDisplayItem(const gfx::RectF& clip_rect); - ~FloatClipDisplayItem() override; - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - size_t ExternalMemoryUsage() const { return 0; } - int ApproximateOpCount() const { return 1; } - - private: - void SetNew(const gfx::RectF& clip_rect); - - gfx::RectF clip_rect_; -}; - -class CC_EXPORT EndFloatClipDisplayItem : public DisplayItem { - public: - EndFloatClipDisplayItem(); - ~EndFloatClipDisplayItem() override; - - static std::unique_ptr<EndFloatClipDisplayItem> Create() { - return base::MakeUnique<EndFloatClipDisplayItem>(); - } - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - int ApproximateOpCount() const { return 0; } -}; - -} // namespace cc - -#endif // CC_PLAYBACK_FLOAT_CLIP_DISPLAY_ITEM_H_ diff --git a/chromium/cc/playback/transform_display_item.cc b/chromium/cc/playback/transform_display_item.cc deleted file mode 100644 index 173170f731a..00000000000 --- a/chromium/cc/playback/transform_display_item.cc +++ /dev/null @@ -1,62 +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/playback/transform_display_item.h" - -#include <stddef.h> - -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event_argument.h" -#include "third_party/skia/include/core/SkCanvas.h" - -namespace cc { - -TransformDisplayItem::TransformDisplayItem(const gfx::Transform& transform) - : DisplayItem(TRANSFORM), transform_(gfx::Transform::kSkipInitialization) { - SetNew(transform); -} - -TransformDisplayItem::~TransformDisplayItem() { -} - -void TransformDisplayItem::SetNew(const gfx::Transform& transform) { - transform_ = transform; -} - -void TransformDisplayItem::Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->save(); - if (!transform_.IsIdentity()) - canvas->concat(transform_.matrix()); -} - -void TransformDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString(base::StringPrintf( - "TransformDisplayItem transform: [%s] visualRect: [%s]", - transform_.ToString().c_str(), visual_rect.ToString().c_str())); -} - -EndTransformDisplayItem::EndTransformDisplayItem() - : DisplayItem(END_TRANSFORM) {} - -EndTransformDisplayItem::~EndTransformDisplayItem() { -} - -void EndTransformDisplayItem::Raster( - SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - canvas->restore(); -} - -void EndTransformDisplayItem::AsValueInto( - const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const { - array->AppendString( - base::StringPrintf("EndTransformDisplayItem visualRect: [%s]", - visual_rect.ToString().c_str())); -} - -} // namespace cc diff --git a/chromium/cc/playback/transform_display_item.h b/chromium/cc/playback/transform_display_item.h deleted file mode 100644 index 75ef6da852a..00000000000 --- a/chromium/cc/playback/transform_display_item.h +++ /dev/null @@ -1,59 +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_PLAYBACK_TRANSFORM_DISPLAY_ITEM_H_ -#define CC_PLAYBACK_TRANSFORM_DISPLAY_ITEM_H_ - -#include <stddef.h> - -#include <memory> - -#include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" -#include "cc/playback/display_item.h" -#include "ui/gfx/transform.h" - -class SkCanvas; - -namespace cc { - -class CC_EXPORT TransformDisplayItem : public DisplayItem { - public: - explicit TransformDisplayItem(const gfx::Transform& transform); - ~TransformDisplayItem() override; - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - size_t ExternalMemoryUsage() const { return 0; } - int ApproximateOpCount() const { return 1; } - - private: - void SetNew(const gfx::Transform& transform); - - gfx::Transform transform_; -}; - -class CC_EXPORT EndTransformDisplayItem : public DisplayItem { - public: - EndTransformDisplayItem(); - ~EndTransformDisplayItem() override; - - static std::unique_ptr<EndTransformDisplayItem> Create() { - return base::MakeUnique<EndTransformDisplayItem>(); - } - - void Raster(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const override; - void AsValueInto(const gfx::Rect& visual_rect, - base::trace_event::TracedValue* array) const override; - - int ApproximateOpCount() const { return 0; } -}; - -} // namespace cc - -#endif // CC_PLAYBACK_TRANSFORM_DISPLAY_ITEM_H_ diff --git a/chromium/cc/quads/content_draw_quad_base.h b/chromium/cc/quads/content_draw_quad_base.h index 52b1850f264..cc130755a01 100644 --- a/chromium/cc/quads/content_draw_quad_base.h +++ b/chromium/cc/quads/content_draw_quad_base.h @@ -7,7 +7,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/quads/draw_quad.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size.h" diff --git a/chromium/cc/quads/debug_border_draw_quad.h b/chromium/cc/quads/debug_border_draw_quad.h index 1a205b3304e..0ef432c3d1e 100644 --- a/chromium/cc/quads/debug_border_draw_quad.h +++ b/chromium/cc/quads/debug_border_draw_quad.h @@ -7,7 +7,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/quads/draw_quad.h" #include "third_party/skia/include/core/SkColor.h" diff --git a/chromium/cc/quads/draw_polygon.cc b/chromium/cc/quads/draw_polygon.cc index 6574196ae09..43642fa5ea2 100644 --- a/chromium/cc/quads/draw_polygon.cc +++ b/chromium/cc/quads/draw_polygon.cc @@ -39,16 +39,17 @@ DrawPolygon::DrawPolygon(const DrawQuad* original, const std::vector<gfx::Point3F>& in_points, const gfx::Vector3dF& normal, int draw_order_index) - : order_index_(draw_order_index), original_ref_(original), is_split_(true) { + : normal_(normal), + order_index_(draw_order_index), + original_ref_(original), + is_split_(true) { for (size_t i = 0; i < in_points.size(); i++) { points_.push_back(in_points[i]); } -#if DCHECK_IS_ON() - normal_ = normal; - ConstructNormal(); - DCHECK_LE((normal_ - normal).Length(), normalized_threshold); -#endif - normal_ = normal; + // If life was fair, we could recalculate the normal from the given points + // and assert it was roughly the same. This causes unhelpful breaks on + // trivial slices of split polygons. Similarly, when splitting, it is + // better to keep the normal that was constructed from the original. } // This takes the original DrawQuad that this polygon should be based on, diff --git a/chromium/cc/quads/draw_polygon.h b/chromium/cc/quads/draw_polygon.h index 8c89e599334..351d3cbc344 100644 --- a/chromium/cc/quads/draw_polygon.h +++ b/chromium/cc/quads/draw_polygon.h @@ -8,6 +8,7 @@ #include <vector> #include "cc/base/math_util.h" +#include "cc/cc_export.h" #include "cc/output/bsp_compare_result.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/quad_f.h" diff --git a/chromium/cc/quads/draw_quad.h b/chromium/cc/quads/draw_quad.h index 4a72e994106..5e46ea4d2f6 100644 --- a/chromium/cc/quads/draw_quad.h +++ b/chromium/cc/quads/draw_quad.h @@ -8,8 +8,8 @@ #include <stddef.h> #include "base/callback.h" -#include "cc/base/cc_export.h" #include "cc/base/resource_id.h" +#include "cc/cc_export.h" #include "cc/quads/shared_quad_state.h" namespace base { @@ -122,8 +122,8 @@ class CC_EXPORT DrawQuad { return ids + count; } - const ResourceId* const_begin() const { return ids; } - const ResourceId* const_end() const { + const ResourceId* begin() const { return ids; } + const ResourceId* end() const { DCHECK_LE(count, kMaxResourceIdCount); return ids + count; } diff --git a/chromium/cc/quads/draw_quad_perftest.cc b/chromium/cc/quads/draw_quad_perftest.cc index 4d648b9c6f2..5d6c4c2ab33 100644 --- a/chromium/cc/quads/draw_quad_perftest.cc +++ b/chromium/cc/quads/draw_quad_perftest.cc @@ -6,7 +6,7 @@ #include "base/bind.h" #include "base/time/time.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/quads/draw_quad.h" #include "cc/quads/render_pass.h" #include "cc/quads/texture_draw_quad.h" diff --git a/chromium/cc/quads/draw_quad_unittest.cc b/chromium/cc/quads/draw_quad_unittest.cc index 9d1602ea3e0..fce24b153d7 100644 --- a/chromium/cc/quads/draw_quad_unittest.cc +++ b/chromium/cc/quads/draw_quad_unittest.cc @@ -10,8 +10,8 @@ #include "base/bind.h" #include "base/compiler_specific.h" +#include "cc/base/filter_operations.h" #include "cc/base/math_util.h" -#include "cc/output/filter_operations.h" #include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/largest_draw_quad.h" #include "cc/quads/picture_draw_quad.h" diff --git a/chromium/cc/quads/largest_draw_quad.h b/chromium/cc/quads/largest_draw_quad.h index 62593e5cfe8..aefbd5ecee4 100644 --- a/chromium/cc/quads/largest_draw_quad.h +++ b/chromium/cc/quads/largest_draw_quad.h @@ -7,7 +7,7 @@ #include <stddef.h> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/quads/nine_patch_generator.cc b/chromium/cc/quads/nine_patch_generator.cc index ea722ad47e2..4edde067abd 100644 --- a/chromium/cc/quads/nine_patch_generator.cc +++ b/chromium/cc/quads/nine_patch_generator.cc @@ -369,28 +369,28 @@ void NinePatchGenerator::AppendQuads(LayerImpl* layer_impl, } void NinePatchGenerator::AsJson(base::DictionaryValue* dictionary) const { - base::ListValue* list = new base::ListValue; + auto list = base::MakeUnique<base::ListValue>(); list->AppendInteger(image_aperture_.origin().x()); list->AppendInteger(image_aperture_.origin().y()); list->AppendInteger(image_aperture_.size().width()); list->AppendInteger(image_aperture_.size().height()); - dictionary->Set("ImageAperture", list); + dictionary->Set("ImageAperture", std::move(list)); - list = new base::ListValue; + list = base::MakeUnique<base::ListValue>(); list->AppendInteger(image_bounds_.width()); list->AppendInteger(image_bounds_.height()); - dictionary->Set("ImageBounds", list); + dictionary->Set("ImageBounds", std::move(list)); - dictionary->Set("Border", MathUtil::AsValue(border_).release()); + dictionary->Set("Border", MathUtil::AsValue(border_)); dictionary->SetBoolean("FillCenter", fill_center_); - list = new base::ListValue; + list = base::MakeUnique<base::ListValue>(); list->AppendInteger(output_occlusion_.x()); list->AppendInteger(output_occlusion_.y()); list->AppendInteger(output_occlusion_.width()); list->AppendInteger(output_occlusion_.height()); - dictionary->Set("OutputOcclusion", list); + dictionary->Set("OutputOcclusion", std::move(list)); } } // namespace cc diff --git a/chromium/cc/quads/nine_patch_generator.h b/chromium/cc/quads/nine_patch_generator.h index 140d361914e..8bdd6cdc69b 100644 --- a/chromium/cc/quads/nine_patch_generator.h +++ b/chromium/cc/quads/nine_patch_generator.h @@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/ui_resource_client.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" diff --git a/chromium/cc/quads/picture_draw_quad.h b/chromium/cc/quads/picture_draw_quad.h index b9286b73729..cb9f5a794fe 100644 --- a/chromium/cc/quads/picture_draw_quad.h +++ b/chromium/cc/quads/picture_draw_quad.h @@ -8,9 +8,9 @@ #include <memory> #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" -#include "cc/playback/raster_source.h" +#include "cc/cc_export.h" #include "cc/quads/content_draw_quad_base.h" +#include "cc/raster/raster_source.h" #include "cc/resources/resource_provider.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" diff --git a/chromium/cc/quads/render_pass.h b/chromium/cc/quads/render_pass.h index 274c27ec426..fbb43237b5a 100644 --- a/chromium/cc/quads/render_pass.h +++ b/chromium/cc/quads/render_pass.h @@ -14,9 +14,9 @@ #include "base/callback.h" #include "base/hash.h" #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/base/filter_operations.h" #include "cc/base/list_container.h" -#include "cc/output/filter_operations.h" +#include "cc/cc_export.h" #include "cc/quads/draw_quad.h" #include "cc/quads/largest_draw_quad.h" #include "ui/gfx/color_space.h" diff --git a/chromium/cc/quads/render_pass_draw_quad.h b/chromium/cc/quads/render_pass_draw_quad.h index 085446e68b8..4764560f24c 100644 --- a/chromium/cc/quads/render_pass_draw_quad.h +++ b/chromium/cc/quads/render_pass_draw_quad.h @@ -9,8 +9,8 @@ #include <memory> -#include "cc/base/cc_export.h" -#include "cc/output/filter_operations.h" +#include "cc/base/filter_operations.h" +#include "cc/cc_export.h" #include "cc/quads/draw_quad.h" #include "ui/gfx/geometry/point_f.h" diff --git a/chromium/cc/quads/shared_quad_state.h b/chromium/cc/quads/shared_quad_state.h index 11119eae045..f3758fb0d96 100644 --- a/chromium/cc/quads/shared_quad_state.h +++ b/chromium/cc/quads/shared_quad_state.h @@ -7,7 +7,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "third_party/skia/include/core/SkBlendMode.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/transform.h" diff --git a/chromium/cc/quads/solid_color_draw_quad.h b/chromium/cc/quads/solid_color_draw_quad.h index 97ab1e23881..2e99408be93 100644 --- a/chromium/cc/quads/solid_color_draw_quad.h +++ b/chromium/cc/quads/solid_color_draw_quad.h @@ -7,7 +7,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/quads/draw_quad.h" #include "third_party/skia/include/core/SkColor.h" diff --git a/chromium/cc/quads/stream_video_draw_quad.h b/chromium/cc/quads/stream_video_draw_quad.h index 68f3bffd87c..320194dd800 100644 --- a/chromium/cc/quads/stream_video_draw_quad.h +++ b/chromium/cc/quads/stream_video_draw_quad.h @@ -9,7 +9,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/quads/draw_quad.h" #include "ui/gfx/transform.h" diff --git a/chromium/cc/quads/surface_draw_quad.h b/chromium/cc/quads/surface_draw_quad.h index f4c131b3c25..1c1f19d26c7 100644 --- a/chromium/cc/quads/surface_draw_quad.h +++ b/chromium/cc/quads/surface_draw_quad.h @@ -7,7 +7,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/quads/draw_quad.h" #include "cc/surfaces/surface_id.h" diff --git a/chromium/cc/quads/texture_draw_quad.h b/chromium/cc/quads/texture_draw_quad.h index 191a3436874..3c8cce8ea22 100644 --- a/chromium/cc/quads/texture_draw_quad.h +++ b/chromium/cc/quads/texture_draw_quad.h @@ -9,7 +9,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/quads/draw_quad.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/rect_f.h" diff --git a/chromium/cc/quads/yuv_video_draw_quad.h b/chromium/cc/quads/yuv_video_draw_quad.h index ef07848efdc..513938467cc 100644 --- a/chromium/cc/quads/yuv_video_draw_quad.h +++ b/chromium/cc/quads/yuv_video_draw_quad.h @@ -9,7 +9,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/quads/draw_quad.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/rect_f.h" diff --git a/chromium/cc/raster/bitmap_raster_buffer_provider.cc b/chromium/cc/raster/bitmap_raster_buffer_provider.cc index 5f708c38298..470e6e03354 100644 --- a/chromium/cc/raster/bitmap_raster_buffer_provider.cc +++ b/chromium/cc/raster/bitmap_raster_buffer_provider.cc @@ -15,7 +15,7 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/debug/traced_value.h" -#include "cc/playback/raster_source.h" +#include "cc/raster/raster_source.h" #include "cc/resources/platform_color.h" #include "cc/resources/resource.h" @@ -40,7 +40,7 @@ class RasterBufferImpl : public RasterBuffer { const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings) override { TRACE_EVENT0("cc", "BitmapRasterBuffer::Playback"); gfx::Rect playback_rect = raster_full_rect; @@ -53,8 +53,8 @@ class RasterBufferImpl : public RasterBuffer { size_t stride = 0u; RasterBufferProvider::PlaybackToMemory( lock_.sk_bitmap().getPixels(), resource_->format(), resource_->size(), - stride, raster_source, raster_full_rect, playback_rect, scale, - lock_.sk_color_space(), playback_settings); + stride, raster_source, raster_full_rect, playback_rect, transform, + lock_.color_space_for_raster(), playback_settings); } private: diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.cc b/chromium/cc/raster/gpu_raster_buffer_provider.cc index 2e253dc0613..de489ff8fde 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.cc +++ b/chromium/cc/raster/gpu_raster_buffer_provider.cc @@ -14,8 +14,8 @@ #include "base/trace_event/trace_event.h" #include "cc/base/histograms.h" #include "cc/paint/paint_canvas.h" -#include "cc/playback/image_hijack_canvas.h" -#include "cc/playback/raster_source.h" +#include "cc/raster/image_hijack_canvas.h" +#include "cc/raster/raster_source.h" #include "cc/raster/scoped_gpu_raster.h" #include "cc/resources/resource.h" #include "gpu/command_buffer/client/context_support.h" @@ -34,7 +34,7 @@ static void RasterizeSource( const gfx::Size& resource_size, const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings, ContextProvider* context_provider, ResourceProvider::ScopedWriteLockGL* resource_lock, @@ -77,8 +77,9 @@ static void RasterizeSource( 100.0f * fraction_saved); } - raster_source->PlaybackToCanvas(sk_surface->getCanvas(), raster_full_rect, - playback_rect, scale, playback_settings); + raster_source->PlaybackToCanvas( + sk_surface->getCanvas(), resource_lock->color_space_for_raster(), + raster_full_rect, playback_rect, transform, playback_settings); } } // namespace @@ -104,13 +105,13 @@ void GpuRasterBufferProvider::RasterBufferImpl::Playback( const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings) { TRACE_EVENT0("cc", "GpuRasterBuffer::Playback"); client_->PlaybackOnWorkerThread(&lock_, sync_token_, resource_has_previous_content_, raster_source, raster_full_rect, raster_dirty_rect, - new_content_id, scale, playback_settings); + new_content_id, transform, playback_settings); } GpuRasterBufferProvider::GpuRasterBufferProvider( @@ -119,12 +120,14 @@ GpuRasterBufferProvider::GpuRasterBufferProvider( ResourceProvider* resource_provider, bool use_distance_field_text, int gpu_rasterization_msaa_sample_count, + ResourceFormat preferred_tile_format, bool async_worker_context_enabled) : compositor_context_provider_(compositor_context_provider), worker_context_provider_(worker_context_provider), resource_provider_(resource_provider), use_distance_field_text_(use_distance_field_text), msaa_sample_count_(gpu_rasterization_msaa_sample_count), + preferred_tile_format_(preferred_tile_format), async_worker_context_enabled_(async_worker_context_enabled) { DCHECK(compositor_context_provider); DCHECK(worker_context_provider); @@ -174,6 +177,13 @@ void GpuRasterBufferProvider::OrderingBarrier() { ResourceFormat GpuRasterBufferProvider::GetResourceFormat( bool must_support_alpha) const { + if (resource_provider_->IsRenderBufferFormatSupported( + preferred_tile_format_) && + (DoesResourceFormatSupportAlpha(preferred_tile_format_) || + !must_support_alpha)) { + return preferred_tile_format_; + } + return resource_provider_->best_render_buffer_format(); } @@ -200,8 +210,8 @@ bool GpuRasterBufferProvider::IsResourceReadyToDraw( if (!sync_token.HasData()) return true; - // IsSyncTokenSignalled is threadsafe, no need for worker context lock. - return worker_context_provider_->ContextSupport()->IsSyncTokenSignalled( + // IsSyncTokenSignaled is thread-safe, no need for worker context lock. + return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled( sync_token); } @@ -242,7 +252,7 @@ void GpuRasterBufferProvider::PlaybackOnWorkerThread( const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings) { ContextProvider::ScopedContextLock scoped_context(worker_context_provider_); gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); @@ -259,7 +269,7 @@ void GpuRasterBufferProvider::PlaybackOnWorkerThread( RasterizeSource(raster_source, resource_has_previous_content, resource_lock->size(), raster_full_rect, raster_dirty_rect, - scale, playback_settings, worker_context_provider_, + transform, playback_settings, worker_context_provider_, resource_lock, async_worker_context_enabled_, use_distance_field_text_, msaa_sample_count_); diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.h b/chromium/cc/raster/gpu_raster_buffer_provider.h index 195eef84033..0777db294c3 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.h +++ b/chromium/cc/raster/gpu_raster_buffer_provider.h @@ -22,6 +22,7 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { ResourceProvider* resource_provider, bool use_distance_field_text, int gpu_rasterization_msaa_sample_count, + ResourceFormat preferred_tile_format, bool async_worker_context_enabled); ~GpuRasterBufferProvider() override; @@ -50,7 +51,7 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings); private: @@ -69,7 +70,7 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings) override; void set_sync_token(const gpu::SyncToken& sync_token) { @@ -91,6 +92,7 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { ResourceProvider* const resource_provider_; const bool use_distance_field_text_; const int msaa_sample_count_; + const ResourceFormat preferred_tile_format_; const bool async_worker_context_enabled_; std::set<RasterBufferImpl*> pending_raster_buffers_; diff --git a/chromium/cc/playback/image_hijack_canvas.cc b/chromium/cc/raster/image_hijack_canvas.cc index bd26d3237c3..150be23fa5d 100644 --- a/chromium/cc/playback/image_hijack_canvas.cc +++ b/chromium/cc/raster/image_hijack_canvas.cc @@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/image_hijack_canvas.h" +#include "cc/raster/image_hijack_canvas.h" #include "base/optional.h" -#include "cc/playback/discardable_image_map.h" +#include "base/trace_event/trace_event.h" +#include "cc/paint/discardable_image_map.h" #include "cc/tiles/image_decode_cache.h" #include "third_party/skia/include/core/SkPath.h" @@ -24,12 +25,14 @@ class ScopedDecodedImageLock { sk_sp<const SkImage> image, const SkRect& src_rect, const SkMatrix& matrix, - const SkPaint* paint) + const SkPaint* paint, + const gfx::ColorSpace& target_color_space) : image_decode_cache_(image_decode_cache), draw_image_(std::move(image), RoundOutRect(src_rect), paint ? paint->getFilterQuality() : kNone_SkFilterQuality, - matrix), + matrix, + target_color_space), decoded_draw_image_( image_decode_cache_->GetDecodedImageForDraw(draw_image_)) { DCHECK(draw_image_.image()->isLazyGenerated()); @@ -75,7 +78,8 @@ class ScopedImagePaint { static base::Optional<ScopedImagePaint> TryCreate( ImageDecodeCache* image_decode_cache, const SkMatrix& ctm, - const SkPaint& paint) { + const SkPaint& paint, + const gfx::ColorSpace& target_color_space) { SkShader* shader = paint.getShader(); if (!shader) return base::Optional<ScopedImagePaint>(); @@ -92,7 +96,7 @@ class ScopedImagePaint { ScopedDecodedImageLock scoped_lock( image_decode_cache, sk_ref_sp(image), SkRect::MakeIWH(image->width(), image->height()), total_image_matrix, - &paint); + &paint, target_color_space); const DecodedDrawImage& decoded_image = scoped_lock.decoded_image(); if (!decoded_image.image()) return base::Optional<ScopedImagePaint>(); @@ -129,14 +133,18 @@ const SkImage* GetImageInPaint(const SkPaint& paint) { ImageHijackCanvas::ImageHijackCanvas(int width, int height, ImageDecodeCache* image_decode_cache, - const ImageIdFlatSet* images_to_skip) + const ImageIdFlatSet* images_to_skip, + const gfx::ColorSpace& target_color_space) : SkNWayCanvas(width, height), image_decode_cache_(image_decode_cache), - images_to_skip_(images_to_skip) {} + images_to_skip_(images_to_skip), + target_color_space_(target_color_space) {} void ImageHijackCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "ImageHijackCanvas::onDrawPicture"); // Ensure that pictures are unpacked by this canvas, instead of being // forwarded to the raster canvas. SkCanvas::onDrawPicture(picture, matrix, paint); @@ -146,6 +154,8 @@ void ImageHijackCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "ImageHijackCanvas::onDrawImage"); if (!image->isLazyGenerated()) { DCHECK(!ShouldSkipImage(image)); SkNWayCanvas::onDrawImage(image, x, y, paint); @@ -159,7 +169,8 @@ void ImageHijackCanvas::onDrawImage(const SkImage* image, ScopedDecodedImageLock scoped_lock( image_decode_cache_, sk_ref_sp(image), - SkRect::MakeIWH(image->width(), image->height()), ctm, paint); + SkRect::MakeIWH(image->width(), image->height()), ctm, paint, + target_color_space_); const DecodedDrawImage& decoded_image = scoped_lock.decoded_image(); if (!decoded_image.image()) return; @@ -184,6 +195,8 @@ void ImageHijackCanvas::onDrawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "ImageHijackCanvas::onDrawImageRect"); if (!image->isLazyGenerated()) { DCHECK(!ShouldSkipImage(image)); SkNWayCanvas::onDrawImageRect(image, src, dst, paint, constraint); @@ -203,7 +216,7 @@ void ImageHijackCanvas::onDrawImageRect(const SkImage* image, matrix.postConcat(getTotalMatrix()); ScopedDecodedImageLock scoped_lock(image_decode_cache_, sk_ref_sp(image), - *src, matrix, paint); + *src, matrix, paint, target_color_space_); const DecodedDrawImage& decoded_image = scoped_lock.decoded_image(); if (!decoded_image.image()) return; @@ -225,11 +238,13 @@ void ImageHijackCanvas::onDrawImageRect(const SkImage* image, } void ImageHijackCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "ImageHijackCanvas::onDrawRect"); if (ShouldSkipImageInPaint(paint)) return; - base::Optional<ScopedImagePaint> image_paint = - ScopedImagePaint::TryCreate(image_decode_cache_, getTotalMatrix(), paint); + base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate( + image_decode_cache_, getTotalMatrix(), paint, target_color_space_); if (!image_paint.has_value()) { SkNWayCanvas::onDrawRect(r, paint); return; @@ -238,11 +253,13 @@ void ImageHijackCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { } void ImageHijackCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "ImageHijackCanvas::onDrawPath"); if (ShouldSkipImageInPaint(paint)) return; - base::Optional<ScopedImagePaint> image_paint = - ScopedImagePaint::TryCreate(image_decode_cache_, getTotalMatrix(), paint); + base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate( + image_decode_cache_, getTotalMatrix(), paint, target_color_space_); if (!image_paint.has_value()) { SkNWayCanvas::onDrawPath(path, paint); return; @@ -251,11 +268,13 @@ void ImageHijackCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { } void ImageHijackCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "ImageHijackCanvas::onDrawOval"); if (ShouldSkipImageInPaint(paint)) return; - base::Optional<ScopedImagePaint> image_paint = - ScopedImagePaint::TryCreate(image_decode_cache_, getTotalMatrix(), paint); + base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate( + image_decode_cache_, getTotalMatrix(), paint, target_color_space_); if (!image_paint.has_value()) { SkNWayCanvas::onDrawOval(r, paint); return; @@ -268,11 +287,13 @@ void ImageHijackCanvas::onDrawArc(const SkRect& r, SkScalar sweep_angle, bool use_center, const SkPaint& paint) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "ImageHijackCanvas::onDrawArc"); if (ShouldSkipImageInPaint(paint)) return; - base::Optional<ScopedImagePaint> image_paint = - ScopedImagePaint::TryCreate(image_decode_cache_, getTotalMatrix(), paint); + base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate( + image_decode_cache_, getTotalMatrix(), paint, target_color_space_); if (!image_paint.has_value()) { SkNWayCanvas::onDrawArc(r, start_angle, sweep_angle, use_center, paint); return; @@ -282,11 +303,13 @@ void ImageHijackCanvas::onDrawArc(const SkRect& r, } void ImageHijackCanvas::onDrawRRect(const SkRRect& rr, const SkPaint& paint) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "ImageHijackCanvas::onDrawRRect"); if (ShouldSkipImageInPaint(paint)) return; - base::Optional<ScopedImagePaint> image_paint = - ScopedImagePaint::TryCreate(image_decode_cache_, getTotalMatrix(), paint); + base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate( + image_decode_cache_, getTotalMatrix(), paint, target_color_space_); if (!image_paint.has_value()) { SkNWayCanvas::onDrawRRect(rr, paint); return; @@ -303,7 +326,12 @@ void ImageHijackCanvas::onDrawImageNine(const SkImage* image, } bool ImageHijackCanvas::ShouldSkipImage(const SkImage* image) const { - return images_to_skip_->find(image->uniqueID()) != images_to_skip_->end(); + bool skip = + images_to_skip_->find(image->uniqueID()) != images_to_skip_->end(); + TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "ImageHijackCanvas::ShouldSkipImage", "imageId", + image->uniqueID(), "skip", skip); + return skip; } bool ImageHijackCanvas::ShouldSkipImageInPaint(const SkPaint& paint) const { diff --git a/chromium/cc/playback/image_hijack_canvas.h b/chromium/cc/raster/image_hijack_canvas.h index 2a43d524938..4693e8d8622 100644 --- a/chromium/cc/playback/image_hijack_canvas.h +++ b/chromium/cc/raster/image_hijack_canvas.h @@ -2,15 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_PLAYBACK_IMAGE_HIJACK_CANVAS_H_ -#define CC_PLAYBACK_IMAGE_HIJACK_CANVAS_H_ +#ifndef CC_RASTER_IMAGE_HIJACK_CANVAS_H_ +#define CC_RASTER_IMAGE_HIJACK_CANVAS_H_ #include <unordered_set> #include "base/macros.h" -#include "cc/base/cc_export.h" -#include "cc/playback/image_id.h" +#include "cc/cc_export.h" +#include "cc/paint/image_id.h" #include "third_party/skia/include/utils/SkNWayCanvas.h" +#include "ui/gfx/color_space.h" namespace cc { @@ -21,7 +22,8 @@ class CC_EXPORT ImageHijackCanvas : public SkNWayCanvas { ImageHijackCanvas(int width, int height, ImageDecodeCache* image_decode_cache, - const ImageIdFlatSet* images_to_skip); + const ImageIdFlatSet* images_to_skip, + const gfx::ColorSpace& target_color_space); private: // Ensure that pictures are unpacked by this canvas, instead of being @@ -57,10 +59,11 @@ class CC_EXPORT ImageHijackCanvas : public SkNWayCanvas { ImageDecodeCache* image_decode_cache_; const ImageIdFlatSet* images_to_skip_; + const gfx::ColorSpace target_color_space_; DISALLOW_COPY_AND_ASSIGN(ImageHijackCanvas); }; } // namespace cc -#endif // CC_PLAYBACK_IMAGE_HIJACK_CANVAS_H_ +#endif // CC_RASTER_IMAGE_HIJACK_CANVAS_H_ diff --git a/chromium/cc/playback/image_hijack_canvas_unittest.cc b/chromium/cc/raster/image_hijack_canvas_unittest.cc index 951efb7ac71..070070f2632 100644 --- a/chromium/cc/playback/image_hijack_canvas_unittest.cc +++ b/chromium/cc/raster/image_hijack_canvas_unittest.cc @@ -1,7 +1,7 @@ // Copyright 2016 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/image_hijack_canvas.h" +#include "cc/raster/image_hijack_canvas.h" #include "cc/test/skia_common.h" #include "cc/tiles/image_decode_cache.h" @@ -29,6 +29,7 @@ class MockImageDecodeCache : public ImageDecodeCache { MOCK_METHOD0(ReduceCacheUsage, void()); MOCK_METHOD1(SetShouldAggressivelyFreeResources, void(bool aggressively_free_resources)); + MOCK_METHOD0(ClearCache, void()); MOCK_METHOD2(GetOutOfRasterDecodeTaskForImageAndRef, bool(const DrawImage& image, scoped_refptr<TileTask>* task)); }; @@ -38,7 +39,9 @@ TEST(ImageHijackCanvasTest, NonLazyImagesSkipped) { // will hit an error. testing::StrictMock<MockImageDecodeCache> image_decode_cache; ImageIdFlatSet images_to_skip; - ImageHijackCanvas canvas(100, 100, &image_decode_cache, &images_to_skip); + gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB(); + ImageHijackCanvas canvas(100, 100, &image_decode_cache, &images_to_skip, + target_color_space); // Use an SkBitmap backed image to ensure that the image is not // lazy-generated. @@ -71,7 +74,9 @@ TEST(ImageHijackCanvasTest, ImagesToSkipAreSkipped) { ImageIdFlatSet images_to_skip; sk_sp<SkImage> image = CreateDiscardableImage(gfx::Size(10, 10)); images_to_skip.insert(image->uniqueID()); - ImageHijackCanvas canvas(100, 100, &image_decode_cache, &images_to_skip); + gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB(); + ImageHijackCanvas canvas(100, 100, &image_decode_cache, &images_to_skip, + target_color_space); SkPaint paint; canvas.drawImage(image, 0, 0, &paint); diff --git a/chromium/cc/raster/one_copy_raster_buffer_provider.cc b/chromium/cc/raster/one_copy_raster_buffer_provider.cc index 18dc44cdc94..abc63e46fc3 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.cc @@ -57,12 +57,12 @@ void OneCopyRasterBufferProvider::RasterBufferImpl::Playback( const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings) { TRACE_EVENT0("cc", "OneCopyRasterBuffer::Playback"); client_->PlaybackAndCopyOnWorkerThread( resource_, &lock_, sync_token_, raster_source, raster_full_rect, - raster_dirty_rect, scale, playback_settings, previous_content_id_, + raster_dirty_rect, transform, playback_settings, previous_content_id_, new_content_id); } @@ -142,7 +142,7 @@ void OneCopyRasterBufferProvider::OrderingBarrier() { ResourceFormat OneCopyRasterBufferProvider::GetResourceFormat( bool must_support_alpha) const { - if (resource_provider_->IsResourceFormatSupported(preferred_tile_format_) && + if (resource_provider_->IsTextureFormatSupported(preferred_tile_format_) && (DoesResourceFormatSupportAlpha(preferred_tile_format_) || !must_support_alpha)) { return preferred_tile_format_; @@ -173,8 +173,8 @@ bool OneCopyRasterBufferProvider::IsResourceReadyToDraw( if (!sync_token.HasData()) return true; - // IsSyncTokenSignalled is threadsafe, no need for worker context lock. - return worker_context_provider_->ContextSupport()->IsSyncTokenSignalled( + // IsSyncTokenSignaled is thread-safe, no need for worker context lock. + return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled( sync_token); } @@ -215,7 +215,7 @@ void OneCopyRasterBufferProvider::PlaybackAndCopyOnWorkerThread( const RasterSource* raster_source, const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings, uint64_t previous_content_id, uint64_t new_content_id) { @@ -234,10 +234,10 @@ void OneCopyRasterBufferProvider::PlaybackAndCopyOnWorkerThread( std::unique_ptr<StagingBuffer> staging_buffer = staging_pool_.AcquireStagingBuffer(resource, previous_content_id); - PlaybackToStagingBuffer(staging_buffer.get(), resource, raster_source, - raster_full_rect, raster_dirty_rect, scale, - resource_lock->sk_color_space(), playback_settings, - previous_content_id, new_content_id); + PlaybackToStagingBuffer( + staging_buffer.get(), resource, raster_source, raster_full_rect, + raster_dirty_rect, transform, resource_lock->color_space_for_raster(), + playback_settings, previous_content_id, new_content_id); CopyOnWorkerThread(staging_buffer.get(), resource_lock, sync_token, raster_source, previous_content_id, new_content_id); @@ -251,8 +251,8 @@ void OneCopyRasterBufferProvider::PlaybackToStagingBuffer( const RasterSource* raster_source, const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, - float scale, - sk_sp<SkColorSpace> dst_color_space, + const gfx::AxisTransform2d& transform, + const gfx::ColorSpace& dst_color_space, const RasterSource::PlaybackSettings& playback_settings, uint64_t previous_content_id, uint64_t new_content_id) { @@ -301,7 +301,7 @@ void OneCopyRasterBufferProvider::PlaybackToStagingBuffer( RasterBufferProvider::PlaybackToMemory( buffer->memory(0), resource->format(), staging_buffer->size, buffer->stride(0), raster_source, raster_full_rect, playback_rect, - scale, dst_color_space, playback_settings); + transform, dst_color_space, playback_settings); buffer->Unmap(); staging_buffer->content_id = new_content_id; } diff --git a/chromium/cc/raster/one_copy_raster_buffer_provider.h b/chromium/cc/raster/one_copy_raster_buffer_provider.h index 22e0dd58f39..5d82849cc6c 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.h +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.h @@ -56,7 +56,7 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { const RasterSource* raster_source, const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings, uint64_t previous_content_id, uint64_t new_content_id); @@ -77,7 +77,7 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings) override; void set_sync_token(const gpu::SyncToken& sync_token) { @@ -101,8 +101,8 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { const RasterSource* raster_source, const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, - float scale, - sk_sp<SkColorSpace> dst_color_space, + const gfx::AxisTransform2d& transform, + const gfx::ColorSpace& dst_color_space, const RasterSource::PlaybackSettings& playback_settings, uint64_t previous_content_id, uint64_t new_content_id); diff --git a/chromium/cc/raster/raster_buffer.h b/chromium/cc/raster/raster_buffer.h index 04972f9d73e..0de76b350c2 100644 --- a/chromium/cc/raster/raster_buffer.h +++ b/chromium/cc/raster/raster_buffer.h @@ -7,10 +7,14 @@ #include <stdint.h> -#include "cc/base/cc_export.h" -#include "cc/playback/raster_source.h" +#include "cc/cc_export.h" +#include "cc/raster/raster_source.h" #include "ui/gfx/geometry/rect.h" +namespace gfx { +class AxisTransform2d; +} // namespace gfx + namespace cc { class CC_EXPORT RasterBuffer { @@ -23,7 +27,7 @@ class CC_EXPORT RasterBuffer { const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings) = 0; }; diff --git a/chromium/cc/raster/raster_buffer_provider.cc b/chromium/cc/raster/raster_buffer_provider.cc index 98e366f04a0..7b3dfc6710f 100644 --- a/chromium/cc/raster/raster_buffer_provider.cc +++ b/chromium/cc/raster/raster_buffer_provider.cc @@ -7,12 +7,13 @@ #include <stddef.h> #include "base/trace_event/trace_event.h" -#include "cc/playback/raster_source.h" +#include "cc/raster/raster_source.h" #include "cc/raster/texture_compressor.h" #include "cc/resources/platform_color.h" #include "cc/resources/resource_format_utils.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkSurface.h" +#include "ui/gfx/geometry/axis_transform2d.h" namespace cc { @@ -27,7 +28,6 @@ bool IsSupportedPlaybackToMemoryFormat(ResourceFormat format) { case RGBA_4444: case RGBA_8888: case BGRA_8888: - case RGBA_F16: case ETC1: return true; case ALPHA_8: @@ -35,6 +35,7 @@ bool IsSupportedPlaybackToMemoryFormat(ResourceFormat format) { case RGB_565: case RED_8: case LUMINANCE_F16: + case RGBA_F16: return false; } NOTREACHED(); @@ -52,8 +53,8 @@ void RasterBufferProvider::PlaybackToMemory( const RasterSource* raster_source, const gfx::Rect& canvas_bitmap_rect, const gfx::Rect& canvas_playback_rect, - float scale, - sk_sp<SkColorSpace> dst_color_space, + const gfx::AxisTransform2d& transform, + const gfx::ColorSpace& target_color_space, const RasterSource::PlaybackSettings& playback_settings) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "RasterBufferProvider::PlaybackToMemory"); @@ -61,8 +62,8 @@ void RasterBufferProvider::PlaybackToMemory( DCHECK(IsSupportedPlaybackToMemoryFormat(format)) << format; // Uses kPremul_SkAlphaType since the result is not known to be opaque. - SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), - kPremul_SkAlphaType, dst_color_space); + SkImageInfo info = + SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType); // Use unknown pixel geometry to disable LCD text. SkSurfaceProps surface_props(0, kUnknown_SkPixelGeometry); @@ -81,9 +82,9 @@ void RasterBufferProvider::PlaybackToMemory( case RGBA_F16: { sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect(info, memory, stride, &surface_props); - raster_source->PlaybackToCanvas(surface->getCanvas(), canvas_bitmap_rect, - canvas_playback_rect, scale, - playback_settings); + raster_source->PlaybackToCanvas(surface->getCanvas(), target_color_space, + canvas_bitmap_rect, canvas_playback_rect, + transform, playback_settings); return; } case RGBA_4444: @@ -91,9 +92,9 @@ void RasterBufferProvider::PlaybackToMemory( sk_sp<SkSurface> surface = SkSurface::MakeRaster(info, &surface_props); // TODO(reveman): Improve partial raster support by reducing the size of // playback rect passed to PlaybackToCanvas. crbug.com/519070 - raster_source->PlaybackToCanvas(surface->getCanvas(), canvas_bitmap_rect, - canvas_bitmap_rect, scale, - playback_settings); + raster_source->PlaybackToCanvas(surface->getCanvas(), target_color_space, + canvas_bitmap_rect, canvas_bitmap_rect, + transform, playback_settings); if (format == ETC1) { TRACE_EVENT0("cc", diff --git a/chromium/cc/raster/raster_buffer_provider.h b/chromium/cc/raster/raster_buffer_provider.h index 48045842c67..40611dfb96b 100644 --- a/chromium/cc/raster/raster_buffer_provider.h +++ b/chromium/cc/raster/raster_buffer_provider.h @@ -7,8 +7,8 @@ #include <stddef.h> -#include "cc/playback/raster_source.h" #include "cc/raster/raster_buffer.h" +#include "cc/raster/raster_source.h" #include "cc/raster/task_graph_runner.h" #include "cc/raster/tile_task.h" #include "cc/resources/resource_format.h" @@ -38,8 +38,8 @@ class CC_EXPORT RasterBufferProvider { const RasterSource* raster_source, const gfx::Rect& canvas_bitmap_rect, const gfx::Rect& canvas_playback_rect, - float scale, - sk_sp<SkColorSpace> color_space, + const gfx::AxisTransform2d& transform, + const gfx::ColorSpace& target_color_space, const RasterSource::PlaybackSettings& playback_settings); // Acquire raster buffer. diff --git a/chromium/cc/raster/raster_buffer_provider_perftest.cc b/chromium/cc/raster/raster_buffer_provider_perftest.cc index d4dd4e4a6b4..4fdb265a2e4 100644 --- a/chromium/cc/raster/raster_buffer_provider_perftest.cc +++ b/chromium/cc/raster/raster_buffer_provider_perftest.cc @@ -9,7 +9,7 @@ #include "base/memory/ptr_util.h" #include "base/test/test_simple_task_runner.h" #include "base/time/time.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/output/context_cache_controller.h" #include "cc/output/context_provider.h" #include "cc/raster/bitmap_raster_buffer_provider.h" @@ -341,7 +341,8 @@ class RasterBufferProviderPerfTest Create3dResourceProvider(); raster_buffer_provider_ = base::MakeUnique<GpuRasterBufferProvider>( compositor_context_provider_.get(), worker_context_provider_.get(), - resource_provider_.get(), false, 0, false); + resource_provider_.get(), false, 0, + PlatformColor::BestTextureFormat(), false); break; case RASTER_BUFFER_PROVIDER_TYPE_BITMAP: CreateSoftwareResourceProvider(); diff --git a/chromium/cc/raster/raster_buffer_provider_unittest.cc b/chromium/cc/raster/raster_buffer_provider_unittest.cc index 50eb375be79..ea4cdff0c4a 100644 --- a/chromium/cc/raster/raster_buffer_provider_unittest.cc +++ b/chromium/cc/raster/raster_buffer_provider_unittest.cc @@ -38,6 +38,7 @@ #include "cc/tiles/tile_task_manager.h" #include "gpu/GLES2/gl2extchromium.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/axis_transform2d.h" namespace cc { namespace { @@ -83,7 +84,8 @@ class TestRasterTaskImpl : public TileTask { uint64_t new_content_id = 0; raster_buffer_->Playback(raster_source_.get(), gfx::Rect(1, 1), - gfx::Rect(1, 1), new_content_id, 1.f, settings); + gfx::Rect(1, 1), new_content_id, + gfx::AxisTransform2d(), settings); } // Overridden from TileTask: @@ -182,13 +184,15 @@ class RasterBufferProviderTest Create3dResourceProvider(); raster_buffer_provider_ = base::MakeUnique<GpuRasterBufferProvider>( context_provider_.get(), worker_context_provider_.get(), - resource_provider_.get(), false, 0, false); + resource_provider_.get(), false, 0, + PlatformColor::BestTextureFormat(), false); break; case RASTER_BUFFER_PROVIDER_TYPE_ASYNC_GPU: Create3dResourceProvider(); raster_buffer_provider_ = base::MakeUnique<GpuRasterBufferProvider>( context_provider_.get(), worker_context_provider_.get(), - resource_provider_.get(), false, 0, true); + resource_provider_.get(), false, 0, + PlatformColor::BestTextureFormat(), true); break; case RASTER_BUFFER_PROVIDER_TYPE_BITMAP: CreateSoftwareResourceProvider(); diff --git a/chromium/cc/playback/raster_source.cc b/chromium/cc/raster/raster_source.cc index e53daf10b36..b1443e61770 100644 --- a/chromium/cc/playback/raster_source.cc +++ b/chromium/cc/raster/raster_source.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/raster_source.h" +#include "cc/raster/raster_source.h" #include <stddef.h> @@ -10,12 +10,15 @@ #include "cc/base/math_util.h" #include "cc/base/region.h" #include "cc/debug/debug_colors.h" -#include "cc/playback/display_item_list.h" -#include "cc/playback/image_hijack_canvas.h" -#include "cc/playback/skip_image_canvas.h" +#include "cc/debug/traced_value.h" +#include "cc/paint/display_item_list.h" +#include "cc/raster/image_hijack_canvas.h" +#include "cc/raster/skip_image_canvas.h" #include "skia/ext/analysis_canvas.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkColorSpaceXformCanvas.h" #include "third_party/skia/include/core/SkPictureRecorder.h" +#include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect_conversions.h" namespace cc { @@ -56,14 +59,15 @@ RasterSource::RasterSource(const RasterSource* other, bool can_use_lcd_text) other->slow_down_raster_scale_factor_for_debug_), image_decode_cache_(other->image_decode_cache_) {} -RasterSource::~RasterSource() { -} +RasterSource::~RasterSource() {} -void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas, - const gfx::Rect& canvas_bitmap_rect, - const gfx::Rect& canvas_playback_rect, - float raster_scale, - const PlaybackSettings& settings) const { +void RasterSource::PlaybackToCanvas( + SkCanvas* raster_canvas, + const gfx::ColorSpace& target_color_space, + const gfx::Rect& canvas_bitmap_rect, + const gfx::Rect& canvas_playback_rect, + const gfx::AxisTransform2d& raster_transform, + const PlaybackSettings& settings) const { SkIRect raster_bounds = gfx::RectToSkIRect(canvas_bitmap_rect); if (!canvas_playback_rect.IsEmpty() && !raster_bounds.intersect(gfx::RectToSkIRect(canvas_playback_rect))) @@ -74,13 +78,24 @@ void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas, raster_canvas->save(); raster_canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y()); raster_canvas->clipRect(SkRect::MakeFromIRect(raster_bounds)); - raster_canvas->scale(raster_scale, raster_scale); - PlaybackToCanvas(raster_canvas, settings); + raster_canvas->translate(raster_transform.translation().x(), + raster_transform.translation().y()); + raster_canvas->scale(raster_transform.scale(), raster_transform.scale()); + PlaybackToCanvas(raster_canvas, target_color_space, settings); raster_canvas->restore(); } -void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas, +void RasterSource::PlaybackToCanvas(SkCanvas* input_canvas, + const gfx::ColorSpace& target_color_space, const PlaybackSettings& settings) const { + SkCanvas* raster_canvas = input_canvas; + std::unique_ptr<SkCanvas> color_transform_canvas; + if (target_color_space.IsValid()) { + color_transform_canvas = SkCreateColorSpaceXformCanvas( + input_canvas, target_color_space.ToSkColorSpace()); + raster_canvas = color_transform_canvas.get(); + } + if (!settings.playback_to_shared_canvas) PrepareForPlaybackToCanvas(raster_canvas); @@ -90,7 +105,7 @@ void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas, } else if (settings.use_image_hijack_canvas) { const SkImageInfo& info = raster_canvas->imageInfo(); ImageHijackCanvas canvas(info.width(), info.height(), image_decode_cache_, - &settings.images_to_skip); + &settings.images_to_skip, target_color_space); // Before adding the canvas, make sure that the ImageHijackCanvas is aware // of the current transform and clip, which may affect the clip bounds. // Since we query the clip bounds of the current canvas to get the list of @@ -195,12 +210,12 @@ void RasterSource::PrepareForPlaybackToCanvas(SkCanvas* canvas) const { canvas->restore(); } -void RasterSource::RasterCommon(SkCanvas* canvas, +void RasterSource::RasterCommon(SkCanvas* raster_canvas, SkPicture::AbortCallback* callback) const { DCHECK(display_list_.get()); int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); for (int i = 0; i < repeat_count; ++i) - display_list_->Raster(canvas, callback); + display_list_->Raster(raster_canvas, callback); } sk_sp<SkPicture> RasterSource::GetFlattenedPicture() { @@ -234,6 +249,8 @@ bool RasterSource::PerformSolidColorAnalysis(const gfx::Rect& content_rect, layer_rect.Intersect(gfx::Rect(size_)); skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height()); canvas.translate(-layer_rect.x(), -layer_rect.y()); + // Note that because no color conversion is applied to solid color analysis, + // the resulting solid color will be known to be sRGB. RasterCommon(&canvas, &canvas); return canvas.GetColorIfSolid(color); } @@ -241,9 +258,11 @@ bool RasterSource::PerformSolidColorAnalysis(const gfx::Rect& content_rect, void RasterSource::GetDiscardableImagesInRect( const gfx::Rect& layer_rect, float contents_scale, + const gfx::ColorSpace& target_color_space, std::vector<DrawImage>* images) const { DCHECK_EQ(0u, images->size()); - display_list_->GetDiscardableImagesInRect(layer_rect, contents_scale, images); + display_list_->GetDiscardableImagesInRect(layer_rect, contents_scale, + target_color_space, images); } gfx::Rect RasterSource::GetRectForImage(ImageId image_id) const { diff --git a/chromium/cc/playback/raster_source.h b/chromium/cc/raster/raster_source.h index 522557cbb8d..df899ab220c 100644 --- a/chromium/cc/playback/raster_source.h +++ b/chromium/cc/raster/raster_source.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_PLAYBACK_RASTER_SOURCE_H_ -#define CC_PLAYBACK_RASTER_SOURCE_H_ +#ifndef CC_RASTER_RASTER_SOURCE_H_ +#define CC_RASTER_RASTER_SOURCE_H_ #include <stddef.h> @@ -11,12 +11,17 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/debug/rendering_stats_instrumentation.h" -#include "cc/playback/image_id.h" -#include "cc/playback/recording_source.h" +#include "cc/layers/recording_source.h" +#include "cc/paint/image_id.h" #include "skia/ext/analysis_canvas.h" #include "third_party/skia/include/core/SkPicture.h" +#include "ui/gfx/color_space.h" + +namespace gfx { +class AxisTransform2d; +} // namespace gfx namespace cc { class DisplayItemList; @@ -53,11 +58,20 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { const RecordingSource* other, bool can_use_lcd_text); - // TODO(trchen): Deprecated. + // Helper function to apply a few common operations before passing the canvas + // to the shorter version. This is useful for rastering into tiles. + // canvas is expected to be backed by a tile, with a default state. + // raster_transform will be applied to the display list, rastering the list + // into the "content space". + // canvas_bitmap_rect defines the extent of the tile in the content space, + // i.e. contents in the rect will be cropped and translated onto the canvas. + // canvas_playback_rect can be used to replay only part of the recording in, + // the content space, so only a sub-rect of the tile gets rastered. void PlaybackToCanvas(SkCanvas* canvas, + const gfx::ColorSpace& target_color_space, const gfx::Rect& canvas_bitmap_rect, const gfx::Rect& canvas_playback_rect, - float contents_scale, + const gfx::AxisTransform2d& raster_transform, const PlaybackSettings& settings) const; // Raster this RasterSource into the given canvas. Canvas states such as @@ -70,6 +84,7 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { // Note that this should only be called after the image decode controller has // been set, which happens during commit. virtual void PlaybackToCanvas(SkCanvas* canvas, + const gfx::ColorSpace& target_color_space, const PlaybackSettings& settings) const; // Returns whether the given rect at given scale is of solid color in @@ -93,6 +108,7 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { // they were being using during raster at scale |raster_scale|. void GetDiscardableImagesInRect(const gfx::Rect& layer_rect, float contents_scale, + const gfx::ColorSpace& target_color_space, std::vector<DrawImage>* images) const; // Return true iff this raster source can raster the given rect in layer @@ -151,7 +167,8 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { ImageDecodeCache* image_decode_cache_; private: - void RasterCommon(SkCanvas* canvas, SkPicture::AbortCallback* callback) const; + void RasterCommon(SkCanvas* canvas, + SkPicture::AbortCallback* callback) const; void PrepareForPlaybackToCanvas(SkCanvas* canvas) const; @@ -160,4 +177,4 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { } // namespace cc -#endif // CC_PLAYBACK_RASTER_SOURCE_H_ +#endif // CC_RASTER_RASTER_SOURCE_H_ diff --git a/chromium/cc/playback/raster_source_unittest.cc b/chromium/cc/raster/raster_source_unittest.cc index a0e0ab8ef4e..344205714c4 100644 --- a/chromium/cc/playback/raster_source_unittest.cc +++ b/chromium/cc/raster/raster_source_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/raster_source.h" +#include "cc/raster/raster_source.h" #include <stddef.h> @@ -15,12 +15,17 @@ #include "third_party/skia/include/core/SkPixelRef.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkShader.h" +#include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size_conversions.h" namespace cc { namespace { +gfx::ColorSpace ColorSpaceForTesting() { + return gfx::ColorSpace(); +} + TEST(RasterSourceTest, AnalyzeIsSolidUnscaled) { gfx::Size layer_bounds(400, 400); @@ -210,34 +215,45 @@ TEST(RasterSourceTest, PixelRefIteratorDiscardableRefsOneTile) { // Tile sized iterators. These should find only one pixel ref. { + gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB(); std::vector<DrawImage> images; - raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), 1.f, &images); + raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), 1.f, + target_color_space, &images); EXPECT_EQ(1u, images.size()); EXPECT_EQ(discardable_image[0][0], images[0].image()); + EXPECT_EQ(target_color_space, images[0].target_color_space()); } // Shifted tile sized iterators. These should find only one pixel ref. { + gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateXYZD50(); std::vector<DrawImage> images; raster->GetDiscardableImagesInRect(gfx::Rect(260, 260, 256, 256), 1.f, - &images); + target_color_space, &images); EXPECT_EQ(1u, images.size()); EXPECT_EQ(discardable_image[1][1], images[0].image()); + EXPECT_EQ(target_color_space, images[0].target_color_space()); } // Ensure there's no discardable pixel refs in the empty cell { + gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB(); std::vector<DrawImage> images; raster->GetDiscardableImagesInRect(gfx::Rect(0, 256, 256, 256), 1.f, - &images); + target_color_space, &images); EXPECT_EQ(0u, images.size()); } // Layer sized iterators. These should find three pixel ref. { + gfx::ColorSpace target_color_space; std::vector<DrawImage> images; - raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 512, 512), 1.f, &images); + raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 512, 512), 1.f, + target_color_space, &images); EXPECT_EQ(3u, images.size()); EXPECT_EQ(discardable_image[0][0], images[0].image()); EXPECT_EQ(discardable_image[0][1], images[1].image()); EXPECT_EQ(discardable_image[1][1], images[2].image()); + EXPECT_EQ(target_color_space, images[0].target_color_space()); + EXPECT_EQ(target_color_space, images[1].target_color_space()); + EXPECT_EQ(target_color_space, images[2].target_color_space()); } } @@ -286,9 +302,10 @@ TEST(RasterSourceTest, RasterFullContents) { SkCanvas canvas(bitmap); canvas.clear(SK_ColorTRANSPARENT); - raster->PlaybackToCanvas(&canvas, canvas_rect, canvas_rect, - contents_scale, - RasterSource::PlaybackSettings()); + raster->PlaybackToCanvas( + &canvas, ColorSpaceForTesting(), canvas_rect, canvas_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + RasterSource::PlaybackSettings()); SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); int num_pixels = bitmap.width() * bitmap.height(); @@ -338,8 +355,10 @@ TEST(RasterSourceTest, RasterPartialContents) { // 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, RasterSource::PlaybackSettings()); + raster->PlaybackToCanvas( + &canvas, ColorSpaceForTesting(), raster_full_rect, playback_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + RasterSource::PlaybackSettings()); { SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); @@ -369,8 +388,10 @@ TEST(RasterSourceTest, RasterPartialContents) { // 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, RasterSource::PlaybackSettings()); + raster->PlaybackToCanvas( + &canvas, ColorSpaceForTesting(), raster_full_rect, playback_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + RasterSource::PlaybackSettings()); SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); int num_black = 0; @@ -433,8 +454,10 @@ TEST(RasterSourceTest, RasterPartialClear) { // 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, RasterSource::PlaybackSettings()); + raster->PlaybackToCanvas( + &canvas, ColorSpaceForTesting(), raster_full_rect, playback_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + RasterSource::PlaybackSettings()); { SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); @@ -472,8 +495,10 @@ TEST(RasterSourceTest, RasterPartialClear) { // darker white background rectangle. playback_rect = gfx::Rect(gfx::ScaleToCeiledSize(partial_bounds, contents_scale)); - raster->PlaybackToCanvas(&canvas, raster_full_rect, playback_rect, - contents_scale, RasterSource::PlaybackSettings()); + raster->PlaybackToCanvas( + &canvas, ColorSpaceForTesting(), raster_full_rect, playback_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + RasterSource::PlaybackSettings()); // Test that the whole playback_rect was cleared and repainted with new alpha. SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); @@ -512,8 +537,10 @@ TEST(RasterSourceTest, RasterContentsTransparent) { bitmap.allocN32Pixels(canvas_rect.width(), canvas_rect.height()); SkCanvas canvas(bitmap); - raster->PlaybackToCanvas(&canvas, canvas_rect, canvas_rect, contents_scale, - RasterSource::PlaybackSettings()); + raster->PlaybackToCanvas( + &canvas, ColorSpaceForTesting(), canvas_rect, canvas_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + RasterSource::PlaybackSettings()); SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); int num_pixels = bitmap.width() * bitmap.height(); @@ -574,7 +601,7 @@ TEST(RasterSourceTest, ImageHijackCanvasRespectsSharedCanvasTransform) { recording_source->CreateRasterSource(can_use_lcd); SoftwareImageDecodeCache controller( ResourceFormat::RGBA_8888, - LayerTreeSettings().software_decoded_image_budget_bytes); + LayerTreeSettings().decoded_image_working_set_budget_bytes); raster_source->set_image_decode_cache(&controller); SkBitmap bitmap; @@ -585,8 +612,9 @@ TEST(RasterSourceTest, ImageHijackCanvasRespectsSharedCanvasTransform) { RasterSource::PlaybackSettings settings; settings.playback_to_shared_canvas = true; settings.use_image_hijack_canvas = true; - raster_source->PlaybackToCanvas(&canvas, gfx::Rect(size), gfx::Rect(size), - 1.f, settings); + raster_source->PlaybackToCanvas(&canvas, ColorSpaceForTesting(), + gfx::Rect(size), gfx::Rect(size), + gfx::AxisTransform2d(), settings); EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(0, 0)); EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(49, 0)); diff --git a/chromium/cc/raster/scoped_gpu_raster.h b/chromium/cc/raster/scoped_gpu_raster.h index 3d9083bbf68..dea7f275539 100644 --- a/chromium/cc/raster/scoped_gpu_raster.h +++ b/chromium/cc/raster/scoped_gpu_raster.h @@ -9,7 +9,7 @@ #include "base/logging.h" #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/context_provider.h" namespace cc { diff --git a/chromium/cc/playback/skip_image_canvas.cc b/chromium/cc/raster/skip_image_canvas.cc index 27926be145b..3ec2e5f085f 100644 --- a/chromium/cc/playback/skip_image_canvas.cc +++ b/chromium/cc/raster/skip_image_canvas.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/skip_image_canvas.h" +#include "cc/raster/skip_image_canvas.h" #include "third_party/skia/include/core/SkShader.h" diff --git a/chromium/cc/playback/skip_image_canvas.h b/chromium/cc/raster/skip_image_canvas.h index 67206b7cb91..6932e996798 100644 --- a/chromium/cc/playback/skip_image_canvas.h +++ b/chromium/cc/raster/skip_image_canvas.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_PLAYBACK_SKIP_IMAGE_CANVAS_H_ -#define CC_PLAYBACK_SKIP_IMAGE_CANVAS_H_ +#ifndef CC_RASTER_SKIP_IMAGE_CANVAS_H_ +#define CC_RASTER_SKIP_IMAGE_CANVAS_H_ #include "third_party/skia/include/utils/SkPaintFilterCanvas.h" @@ -23,4 +23,4 @@ class SkipImageCanvas : public SkPaintFilterCanvas { } // namespace cc -#endif // CC_PLAYBACK_SKIP_IMAGE_CANVAS_H_ +#endif // CC_RASTER_SKIP_IMAGE_CANVAS_H_ diff --git a/chromium/cc/raster/staging_buffer_pool.cc b/chromium/cc/raster/staging_buffer_pool.cc index 6fa0fe03551..526e864ebdc 100644 --- a/chromium/cc/raster/staging_buffer_pool.cc +++ b/chromium/cc/raster/staging_buffer_pool.cc @@ -147,8 +147,9 @@ StagingBufferPool::StagingBufferPool(base::SequencedTaskRunner* task_runner, &StagingBufferPool::ReduceMemoryUsage, weak_ptr_factory_.GetWeakPtr()); task_runner_->PostTask( - FROM_HERE, base::Bind(&StagingBufferPool::RegisterMemoryCoordinatorClient, - weak_ptr_factory_.GetWeakPtr())); + FROM_HERE, + base::BindOnce(&StagingBufferPool::RegisterMemoryCoordinatorClient, + weak_ptr_factory_.GetWeakPtr())); } StagingBufferPool::~StagingBufferPool() { diff --git a/chromium/cc/raster/task.h b/chromium/cc/raster/task.h index 01c16a02f45..66ebc932680 100644 --- a/chromium/cc/raster/task.h +++ b/chromium/cc/raster/task.h @@ -11,7 +11,7 @@ #include <vector> #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { class Task; diff --git a/chromium/cc/raster/task_graph_runner.h b/chromium/cc/raster/task_graph_runner.h index d5e0d90f786..50c952bf60c 100644 --- a/chromium/cc/raster/task_graph_runner.h +++ b/chromium/cc/raster/task_graph_runner.h @@ -15,7 +15,7 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/raster/task.h" namespace cc { diff --git a/chromium/cc/raster/task_graph_runner_perftest.cc b/chromium/cc/raster/task_graph_runner_perftest.cc index a4b2af2a479..62b1d629e0b 100644 --- a/chromium/cc/raster/task_graph_runner_perftest.cc +++ b/chromium/cc/raster/task_graph_runner_perftest.cc @@ -12,7 +12,7 @@ #include "base/memory/ptr_util.h" #include "base/time/time.h" #include "cc/base/completion_event.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/raster/synchronous_task_graph_runner.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" diff --git a/chromium/cc/raster/task_graph_work_queue.h b/chromium/cc/raster/task_graph_work_queue.h index 4842a575270..b1bbce8636a 100644 --- a/chromium/cc/raster/task_graph_work_queue.h +++ b/chromium/cc/raster/task_graph_work_queue.h @@ -11,7 +11,7 @@ #include <map> #include <vector> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/raster/task_graph_runner.h" namespace cc { diff --git a/chromium/cc/raster/texture_compressor.h b/chromium/cc/raster/texture_compressor.h index 36a5a8d5abb..709fc264516 100644 --- a/chromium/cc/raster/texture_compressor.h +++ b/chromium/cc/raster/texture_compressor.h @@ -10,7 +10,7 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/raster/texture_compressor_perftest.cc b/chromium/cc/raster/texture_compressor_perftest.cc index 99ccb60302b..e444c30b33f 100644 --- a/chromium/cc/raster/texture_compressor_perftest.cc +++ b/chromium/cc/raster/texture_compressor_perftest.cc @@ -5,7 +5,7 @@ #include <stdint.h> #include "base/logging.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/raster/texture_compressor.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" diff --git a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc index ff99fcfb315..85db2c4684f 100644 --- a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc @@ -34,7 +34,7 @@ class RasterBufferImpl : public RasterBuffer { const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings) override { TRACE_EVENT0("cc", "ZeroCopyRasterBuffer::Playback"); gfx::GpuMemoryBuffer* buffer = lock_.GetGpuMemoryBuffer(); @@ -52,7 +52,7 @@ class RasterBufferImpl : public RasterBuffer { RasterBufferProvider::PlaybackToMemory( buffer->memory(0), resource_->format(), resource_->size(), buffer->stride(0), raster_source, raster_full_rect, raster_full_rect, - scale, lock_.sk_color_space(), playback_settings); + transform, lock_.color_space_for_raster(), playback_settings); buffer->Unmap(); } @@ -102,7 +102,7 @@ void ZeroCopyRasterBufferProvider::OrderingBarrier() { ResourceFormat ZeroCopyRasterBufferProvider::GetResourceFormat( bool must_support_alpha) const { - if (resource_provider_->IsResourceFormatSupported(preferred_tile_format_) && + if (resource_provider_->IsTextureFormatSupported(preferred_tile_format_) && (DoesResourceFormatSupportAlpha(preferred_tile_format_) || !must_support_alpha)) { return preferred_tile_format_; diff --git a/chromium/cc/resources/memory_history.h b/chromium/cc/resources/memory_history.h index 2a396485b36..21b27bb4bde 100644 --- a/chromium/cc/resources/memory_history.h +++ b/chromium/cc/resources/memory_history.h @@ -12,7 +12,7 @@ #include "base/macros.h" #include "base/time/time.h" -#include "cc/debug/ring_buffer.h" +#include "cc/base/ring_buffer.h" namespace cc { diff --git a/chromium/cc/resources/resource.h b/chromium/cc/resources/resource.h index 7fd361f503d..4dd483ed125 100644 --- a/chromium/cc/resources/resource.h +++ b/chromium/cc/resources/resource.h @@ -7,7 +7,7 @@ #include "base/logging.h" #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/resource_provider.h" #include "cc/resources/resource_util.h" #include "ui/gfx/geometry/size.h" diff --git a/chromium/cc/resources/resource_format.cc b/chromium/cc/resources/resource_format.cc index a7db8a78082..e159f15ec24 100644 --- a/chromium/cc/resources/resource_format.cc +++ b/chromium/cc/resources/resource_format.cc @@ -114,11 +114,12 @@ gfx::BufferFormat BufferFormat(ResourceFormat format) { return gfx::BufferFormat::RGBA_8888; case ETC1: return gfx::BufferFormat::ETC1; + case RGBA_F16: + return gfx::BufferFormat::RGBA_F16; case ALPHA_8: case LUMINANCE_8: case RGB_565: case LUMINANCE_F16: - case RGBA_F16: break; } NOTREACHED(); diff --git a/chromium/cc/resources/resource_format.h b/chromium/cc/resources/resource_format.h index 207dbf40e0f..125a4ebf9c1 100644 --- a/chromium/cc/resources/resource_format.h +++ b/chromium/cc/resources/resource_format.h @@ -6,7 +6,7 @@ #define CC_RESOURCES_RESOURCE_FORMAT_H_ #include "base/logging.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "ui/gfx/buffer_types.h" // TODO(prashant.n): Including third_party/khronos/GLES2/gl2.h causes diff --git a/chromium/cc/resources/resource_pool.cc b/chromium/cc/resources/resource_pool.cc index c2003758c4b..ee516d50ebf 100644 --- a/chromium/cc/resources/resource_pool.cc +++ b/chromium/cc/resources/resource_pool.cc @@ -397,10 +397,11 @@ void ResourcePool::ScheduleEvictExpiredResourcesIn( evict_expired_resources_pending_ = true; - task_runner_->PostDelayedTask(FROM_HERE, - base::Bind(&ResourcePool::EvictExpiredResources, - weak_ptr_factory_.GetWeakPtr()), - time_from_now); + task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&ResourcePool::EvictExpiredResources, + weak_ptr_factory_.GetWeakPtr()), + time_from_now); } void ResourcePool::EvictExpiredResources() { diff --git a/chromium/cc/resources/resource_pool.h b/chromium/cc/resources/resource_pool.h index 5f387ea461f..8932364ee4c 100644 --- a/chromium/cc/resources/resource_pool.h +++ b/chromium/cc/resources/resource_pool.h @@ -16,7 +16,7 @@ #include "base/memory/memory_coordinator_client.h" #include "base/memory/ptr_util.h" #include "base/trace_event/memory_dump_provider.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/resource.h" #include "cc/resources/resource_format.h" #include "cc/resources/scoped_resource.h" diff --git a/chromium/cc/resources/resource_provider.cc b/chromium/cc/resources/resource_provider.cc index f5b71710b87..5275af92daf 100644 --- a/chromium/cc/resources/resource_provider.cc +++ b/chromium/cc/resources/resource_provider.cc @@ -48,27 +48,41 @@ using gpu::gles2::GLES2Interface; namespace cc { -class IdAllocator { +class TextureIdAllocator { public: - virtual ~IdAllocator() {} - - virtual GLuint NextId() = 0; - - protected: - IdAllocator(GLES2Interface* gl, size_t id_allocation_chunk_size) + TextureIdAllocator(GLES2Interface* gl, + size_t texture_id_allocation_chunk_size) : gl_(gl), - id_allocation_chunk_size_(id_allocation_chunk_size), - ids_(new GLuint[id_allocation_chunk_size]), - next_id_index_(id_allocation_chunk_size) { + id_allocation_chunk_size_(texture_id_allocation_chunk_size), + ids_(new GLuint[texture_id_allocation_chunk_size]), + next_id_index_(texture_id_allocation_chunk_size) { DCHECK(id_allocation_chunk_size_); DCHECK_LE(id_allocation_chunk_size_, static_cast<size_t>(std::numeric_limits<int>::max())); } + ~TextureIdAllocator() { + gl_->DeleteTextures( + static_cast<int>(id_allocation_chunk_size_ - next_id_index_), + ids_.get() + next_id_index_); + } + + GLuint NextId() { + if (next_id_index_ == id_allocation_chunk_size_) { + gl_->GenTextures(static_cast<int>(id_allocation_chunk_size_), ids_.get()); + next_id_index_ = 0; + } + + return ids_[next_id_index_++]; + } + + private: GLES2Interface* gl_; const size_t id_allocation_chunk_size_; std::unique_ptr<GLuint[]> ids_; size_t next_id_index_; + + DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator); }; namespace { @@ -159,55 +173,6 @@ class ScopedSetActiveTexture { GLenum unit_; }; -class TextureIdAllocator : public IdAllocator { - public: - TextureIdAllocator(GLES2Interface* gl, - size_t texture_id_allocation_chunk_size) - : IdAllocator(gl, texture_id_allocation_chunk_size) {} - ~TextureIdAllocator() override { - 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(static_cast<int>(id_allocation_chunk_size_), ids_.get()); - next_id_index_ = 0; - } - - return ids_[next_id_index_++]; - } - - private: - DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator); -}; - -class BufferIdAllocator : public IdAllocator { - public: - BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size) - : IdAllocator(gl, buffer_id_allocation_chunk_size) {} - ~BufferIdAllocator() override { - 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(static_cast<int>(id_allocation_chunk_size_), ids_.get()); - next_id_index_ = 0; - } - - return ids_[next_id_index_++]; - } - - private: - DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator); -}; - // Generates process-unique IDs to use for tracing a ResourceProvider's // resources. base::StaticAtomicSequenceNumber g_next_resource_provider_tracing_id; @@ -256,6 +221,7 @@ ResourceProvider::Resource::Resource(GLuint texture_id, hint(hint), type(type), usage(gfx::BufferUsage::GPU_READ_CPU_READ_WRITE), + buffer_format(gfx::BufferFormat::RGBA_8888), format(format), shared_bitmap(nullptr) { } @@ -296,6 +262,7 @@ ResourceProvider::Resource::Resource(uint8_t* pixels, bound_image_id(0), hint(TEXTURE_HINT_IMMUTABLE), type(RESOURCE_TYPE_BITMAP), + buffer_format(gfx::BufferFormat::RGBA_8888), format(RGBA_8888), shared_bitmap(bitmap) { DCHECK(origin == DELEGATED || pixels); @@ -338,6 +305,7 @@ ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id, bound_image_id(0), hint(TEXTURE_HINT_IMMUTABLE), type(RESOURCE_TYPE_BITMAP), + buffer_format(gfx::BufferFormat::RGBA_8888), format(RGBA_8888), shared_bitmap_id(bitmap_id), shared_bitmap(nullptr) { @@ -407,11 +375,11 @@ ResourceProvider::Settings::Settings( ContextProvider* compositor_context_provider, bool delegated_sync_points_required, bool use_gpu_memory_buffer_resources, - bool enable_color_correct_rendering) + bool enable_color_correct_rasterization) : default_resource_type(use_gpu_memory_buffer_resources ? RESOURCE_TYPE_GPU_MEMORY_BUFFER : RESOURCE_TYPE_GL_TEXTURE), - enable_color_correct_rendering(enable_color_correct_rendering), + enable_color_correct_rasterization(enable_color_correct_rasterization), delegated_sync_points_required(delegated_sync_points_required) { if (!compositor_context_provider) { default_resource_type = RESOURCE_TYPE_BITMAP; @@ -454,12 +422,12 @@ ResourceProvider::ResourceProvider( size_t id_allocation_chunk_size, bool delegated_sync_points_required, bool use_gpu_memory_buffer_resources, - bool enable_color_correct_rendering, + bool enable_color_correct_rasterization, const BufferToTextureTargetMap& buffer_to_texture_target_map) : settings_(compositor_context_provider, delegated_sync_points_required, use_gpu_memory_buffer_resources, - enable_color_correct_rendering), + enable_color_correct_rasterization), compositor_context_provider_(compositor_context_provider), shared_bitmap_manager_(shared_bitmap_manager), gpu_memory_buffer_manager_(gpu_memory_buffer_manager), @@ -484,12 +452,9 @@ ResourceProvider::ResourceProvider( return; DCHECK(!texture_id_allocator_); - DCHECK(!buffer_id_allocator_); GLES2Interface* gl = ContextGL(); texture_id_allocator_.reset( new TextureIdAllocator(gl, id_allocation_chunk_size)); - buffer_id_allocator_.reset( - new BufferIdAllocator(gl, id_allocation_chunk_size)); } ResourceProvider::~ResourceProvider() { @@ -518,11 +483,10 @@ ResourceProvider::~ResourceProvider() { #endif // DCHECK_IS_ON() texture_id_allocator_ = nullptr; - buffer_id_allocator_ = nullptr; gl->Finish(); } -bool ResourceProvider::IsResourceFormatSupported(ResourceFormat format) const { +bool ResourceProvider::IsTextureFormatSupported(ResourceFormat format) const { gpu::Capabilities caps; if (compositor_context_provider_) caps = compositor_context_provider_->ContextCapabilities(); @@ -541,13 +505,41 @@ bool ResourceProvider::IsResourceFormatSupported(ResourceFormat format) const { case RED_8: return caps.texture_rg; case LUMINANCE_F16: + case RGBA_F16: return caps.texture_half_float_linear; + } + + NOTREACHED(); + return false; +} + +bool ResourceProvider::IsRenderBufferFormatSupported( + ResourceFormat format) const { + gpu::Capabilities caps; + if (compositor_context_provider_) + caps = compositor_context_provider_->ContextCapabilities(); + + switch (format) { + case RGBA_4444: + case RGBA_8888: + case RGB_565: + return true; + case BGRA_8888: + return caps.render_buffer_format_bgra8888; case RGBA_F16: // TODO(ccameron): This will always return false on pixel tests, which // makes it un-test-able until we upgrade Mesa. // https://crbug.com/687720 return caps.texture_half_float_linear && caps.color_buffer_half_float_rgba; + case LUMINANCE_8: + case ALPHA_8: + case RED_8: + case ETC1: + case LUMINANCE_F16: + // We don't currently render into these formats. If we need to render into + // these eventually, we should expand this logic. + return false; } NOTREACHED(); @@ -587,8 +579,8 @@ ResourceId ResourceProvider::CreateResource( DCHECK(!size.IsEmpty()); switch (settings_.default_resource_type) { case RESOURCE_TYPE_GPU_MEMORY_BUFFER: - // GPU memory buffers don't support LUMINANCE_F16 or RGBA_F16 yet. - if (format != LUMINANCE_F16 && format != RGBA_F16) { + // GPU memory buffers don't support LUMINANCE_F16 yet. + if (format != LUMINANCE_F16) { return CreateGLTexture( size, hint, RESOURCE_TYPE_GPU_MEMORY_BUFFER, format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, color_space); @@ -880,11 +872,11 @@ ResourceProvider::TextureHint ResourceProvider::GetTextureHint(ResourceId id) { return GetResource(id)->hint; } -sk_sp<SkColorSpace> ResourceProvider::GetResourceSkColorSpace( +gfx::ColorSpace ResourceProvider::GetResourceColorSpaceForRaster( const Resource* resource) const { - if (!settings_.enable_color_correct_rendering) - return nullptr; - return resource->color_space.ToSkColorSpace(); + if (!settings_.enable_color_correct_rasterization) + return gfx::ColorSpace(); + return resource->color_space; } void ResourceProvider::CopyToResource(ResourceId id, @@ -908,8 +900,7 @@ void ResourceProvider::CopyToResource(ResourceId id, DCHECK(resource->allocated); DCHECK_EQ(RGBA_8888, resource->format); SkImageInfo source_info = - SkImageInfo::MakeN32Premul(image_size.width(), image_size.height(), - GetResourceSkColorSpace(resource)); + SkImageInfo::MakeN32Premul(image_size.width(), image_size.height()); size_t image_stride = image_size.width() * 4; ScopedWriteLockSoftware lock(this, id); @@ -1070,10 +1061,14 @@ void ResourceProvider::UnlockForRead(ResourceId id) { // The resource belongs to this ResourceProvider, so it can be destroyed. DeleteResourceInternal(it, NORMAL); } else { - ChildMap::iterator child_it = children_.find(resource->child_id); - ResourceIdArray unused; - unused.push_back(id); - DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused); + if (batch_return_resources_) { + batched_returning_resources_[resource->child_id].push_back(id); + } else { + ChildMap::iterator child_it = children_.find(resource->child_id); + ResourceIdArray unused; + unused.push_back(id); + DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused); + } } } } @@ -1100,6 +1095,11 @@ bool ResourceProvider::IsOverlayCandidate(ResourceId id) { return resource->is_overlay_candidate; } +gfx::BufferFormat ResourceProvider::GetBufferFormat(ResourceId id) { + Resource* resource = GetResource(id); + return resource->buffer_format; +} + #if defined(OS_ANDROID) bool ResourceProvider::IsBackedBySurfaceTexture(ResourceId id) { Resource* resource = GetResource(id); @@ -1184,7 +1184,7 @@ ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL( format_ = resource->format; size_ = resource->size; mailbox_ = resource->mailbox(); - sk_color_space_ = resource_provider->GetResourceSkColorSpace(resource); + color_space_ = resource_provider->GetResourceColorSpaceForRaster(resource); } ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() { @@ -1252,8 +1252,7 @@ ResourceProvider::ScopedSkSurfaceProvider::ScopedSkSurfaceProvider( SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType); } sk_surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget( - context_provider->GrContext(), desc, resource_lock->sk_color_space(), - &surface_props); + context_provider->GrContext(), desc, nullptr, &surface_props); } ResourceProvider::ScopedSkSurfaceProvider::~ScopedSkSurfaceProvider() { @@ -1266,9 +1265,8 @@ ResourceProvider::ScopedSkSurfaceProvider::~ScopedSkSurfaceProvider() { void ResourceProvider::PopulateSkBitmapWithResource(SkBitmap* sk_bitmap, const Resource* resource) { DCHECK_EQ(RGBA_8888, resource->format); - SkImageInfo info = SkImageInfo::MakeN32Premul( - resource->size.width(), resource->size.height(), - GetResourceSkColorSpace(resource)); + SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(), + resource->size.height()); sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes()); } @@ -1301,8 +1299,7 @@ ResourceProvider::ScopedReadLockSkImage::ScopedReadLockSkImage( desc.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(texture_info); sk_image_ = SkImage::MakeFromTexture( resource_provider->compositor_context_provider_->GrContext(), desc, - kPremul_SkAlphaType, - resource_provider->GetResourceSkColorSpace(resource), nullptr, nullptr); + kPremul_SkAlphaType); } else if (resource->pixels) { SkBitmap sk_bitmap; resource_provider->PopulateSkBitmapWithResource(&sk_bitmap, resource); @@ -1329,7 +1326,7 @@ ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware( : resource_provider_(resource_provider), resource_id_(resource_id) { Resource* resource = resource_provider->LockForWrite(resource_id); resource_provider->PopulateSkBitmapWithResource(&sk_bitmap_, resource); - sk_color_space_ = resource_provider->GetResourceSkColorSpace(resource); + color_space_ = resource_provider->GetResourceColorSpaceForRaster(resource); DCHECK(valid()); } @@ -1352,6 +1349,7 @@ ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: usage_ = resource->usage; gpu_memory_buffer_ = std::move(resource->gpu_memory_buffer); resource->gpu_memory_buffer = nullptr; + color_space_ = resource_provider->GetResourceColorSpaceForRaster(resource); } ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: @@ -1360,7 +1358,8 @@ ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: Resource* resource = resource_provider_->GetResource(resource_id_); DCHECK(resource); if (gpu_memory_buffer_) { - if (resource_provider_->settings_.enable_color_correct_rendering) + // Note that this impacts overlay compositing, not rasterization. + if (resource_provider_->settings_.enable_color_correct_rasterization) gpu_memory_buffer_->SetColorSpaceForScanout(resource->color_space); DCHECK(!resource->gpu_memory_buffer); resource_provider_->LazyCreate(resource); @@ -1388,6 +1387,16 @@ ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() { return gpu_memory_buffer_.get(); } +ResourceProvider::ScopedBatchReturnResources::ScopedBatchReturnResources( + ResourceProvider* resource_provider) + : resource_provider_(resource_provider) { + resource_provider_->SetBatchReturnResources(true); +} + +ResourceProvider::ScopedBatchReturnResources::~ScopedBatchReturnResources() { + resource_provider_->SetBatchReturnResources(false); +} + ResourceProvider::SynchronousFence::SynchronousFence( gpu::gles2::GLES2Interface* gl) : gl_(gl), has_synchronized_(true) {} @@ -1596,6 +1605,7 @@ void ResourceProvider::ReceiveFromChild( it->mailbox_holder.texture_target, it->filter, TEXTURE_HINT_IMMUTABLE, RESOURCE_TYPE_GL_TEXTURE, it->format)); + resource->buffer_format = it->buffer_format; resource->set_mailbox(TextureMailbox(it->mailbox_holder.mailbox, it->mailbox_holder.sync_token, it->mailbox_holder.texture_target)); @@ -1695,6 +1705,19 @@ void ResourceProvider::ReceiveReturnsFromParent( } } +void ResourceProvider::SetBatchReturnResources(bool batch) { + DCHECK_NE(batch_return_resources_, batch); + batch_return_resources_ = batch; + if (!batch) { + for (const auto& resources : batched_returning_resources_) { + ChildMap::iterator child_it = children_.find(resources.first); + DCHECK(child_it != children_.end()); + DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, resources.second); + } + batched_returning_resources_.clear(); + } +} + #if defined(OS_ANDROID) void ResourceProvider::SendPromotionHints( const OverlayCandidateList::PromotionHintInfoMap& promotion_hints) { @@ -1761,6 +1784,7 @@ void ResourceProvider::TransferResource(Resource* source, DCHECK(source->allocated); resource->id = id; resource->format = source->format; + resource->buffer_format = source->buffer_format; resource->mailbox_holder.texture_target = source->target; resource->filter = source->filter; resource->size = source->size; @@ -1987,8 +2011,9 @@ void ResourceProvider::LazyAllocate(Resource* resource) { gpu_memory_buffer_manager_->CreateGpuMemoryBuffer( size, BufferFormat(format), resource->usage, gpu::kNullSurfaceHandle); + // Note that this impacts overlay compositing, not rasterization. if (resource->gpu_memory_buffer && - settings_.enable_color_correct_rendering) { + settings_.enable_color_correct_rasterization) { resource->gpu_memory_buffer->SetColorSpaceForScanout( resource->color_space); } diff --git a/chromium/cc/resources/resource_provider.h b/chromium/cc/resources/resource_provider.h index d12767136fe..c323d4282ed 100644 --- a/chromium/cc/resources/resource_provider.h +++ b/chromium/cc/resources/resource_provider.h @@ -18,13 +18,14 @@ #include <vector> #include "base/callback.h" +#include "base/containers/small_map.h" #include "base/macros.h" #include "base/memory/linked_ptr.h" #include "base/threading/thread_checker.h" #include "base/trace_event/memory_allocator_dump.h" #include "base/trace_event/memory_dump_provider.h" -#include "cc/base/cc_export.h" #include "cc/base/resource_id.h" +#include "cc/cc_export.h" #include "cc/output/context_provider.h" #include "cc/output/output_surface.h" #include "cc/output/renderer_settings.h" @@ -38,6 +39,7 @@ #include "third_party/khronos/GLES2/gl2.h" #include "third_party/khronos/GLES2/gl2ext.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/buffer_types.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/gpu_memory_buffer.h" @@ -51,9 +53,9 @@ class GLES2Interface; namespace cc { class BlockingTaskRunner; -class IdAllocator; class SharedBitmap; class SharedBitmapManager; +class TextureIdAllocator; // This class is not thread-safe and can only be called from the thread it was // created on (in practice, the impl thread). @@ -86,7 +88,7 @@ class CC_EXPORT ResourceProvider size_t id_allocation_chunk_size, bool delegated_sync_points_required, bool use_gpu_memory_buffer_resources, - bool enable_color_correct_rendering, + bool enable_color_correct_rasterization, const BufferToTextureTargetMap& buffer_to_texture_target_map); ~ResourceProvider() override; @@ -108,7 +110,11 @@ class CC_EXPORT ResourceProvider } size_t num_resources() const { return resources_.size(); } - bool IsResourceFormatSupported(ResourceFormat format) const; + bool IsTextureFormatSupported(ResourceFormat format) const; + + // Returns true if the provided |format| can be used as a render buffer. + // Note that render buffer support implies texture support. + bool IsRenderBufferFormatSupported(ResourceFormat format) const; // Checks whether a resource is in use by a consumer. bool InUseByConsumer(ResourceId id); @@ -287,7 +293,11 @@ class CC_EXPORT ResourceProvider GLenum target() const { return target_; } ResourceFormat format() const { return format_; } const gfx::Size& size() const { return size_; } - sk_sp<SkColorSpace> sk_color_space() const { return sk_color_space_; } + // Will return the invalid color space unless + // |enable_color_correct_rasterization| is true. + const gfx::ColorSpace& color_space_for_raster() const { + return color_space_; + } const TextureMailbox& mailbox() const { return mailbox_; } @@ -310,7 +320,7 @@ class CC_EXPORT ResourceProvider bool has_sync_token_; bool synchronized_; base::ThreadChecker thread_checker_; - sk_sp<SkColorSpace> sk_color_space_; + gfx::ColorSpace color_space_; DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL); }; @@ -398,13 +408,17 @@ class CC_EXPORT ResourceProvider SkBitmap& sk_bitmap() { return sk_bitmap_; } bool valid() const { return !!sk_bitmap_.getPixels(); } - sk_sp<SkColorSpace> sk_color_space() const { return sk_color_space_; } + // Will return the invalid color space unless + // |enable_color_correct_rasterization| is true. + const gfx::ColorSpace& color_space_for_raster() const { + return color_space_; + } private: ResourceProvider* resource_provider_; ResourceId resource_id_; SkBitmap sk_bitmap_; - sk_sp<SkColorSpace> sk_color_space_; + gfx::ColorSpace color_space_; base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockSoftware); @@ -416,7 +430,11 @@ class CC_EXPORT ResourceProvider ResourceId resource_id); ~ScopedWriteLockGpuMemoryBuffer(); gfx::GpuMemoryBuffer* GetGpuMemoryBuffer(); - sk_sp<SkColorSpace> sk_color_space() const { return sk_color_space_; } + // Will return the invalid color space unless + // |enable_color_correct_rasterization| is true. + const gfx::ColorSpace& color_space_for_raster() const { + return color_space_; + } private: ResourceProvider* resource_provider_; @@ -425,12 +443,25 @@ class CC_EXPORT ResourceProvider gfx::BufferUsage usage_; gfx::Size size_; std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; - sk_sp<SkColorSpace> sk_color_space_; + gfx::ColorSpace color_space_; base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpuMemoryBuffer); }; + // All resources that are returned to children while an instance of this + // class exists will be stored and returned when the instance is destroyed. + class CC_EXPORT ScopedBatchReturnResources { + public: + explicit ScopedBatchReturnResources(ResourceProvider* resource_provider); + ~ScopedBatchReturnResources(); + + private: + ResourceProvider* resource_provider_; + + DISALLOW_COPY_AND_ASSIGN(ScopedBatchReturnResources); + }; + class Fence : public base::RefCounted<Fence> { public: Fence() {} @@ -488,6 +519,9 @@ class CC_EXPORT ResourceProvider // Indicates if this resource may be used for a hardware overlay plane. bool IsOverlayCandidate(ResourceId id); + // Return the format of the underlying buffer that can be used for scanout. + gfx::BufferFormat GetBufferFormat(ResourceId id); + #if defined(OS_ANDROID) // Indicates if this resource is backed by an Android SurfaceTexture, and thus // can't really be promoted to an overlay. @@ -515,6 +549,8 @@ class CC_EXPORT ResourceProvider int tracing_id() const { return tracing_id_; } private: + friend class ScopedBatchReturnResources; + struct Resource { enum Origin { INTERNAL, EXTERNAL, DELEGATED }; enum SynchronizationState { @@ -632,6 +668,13 @@ class CC_EXPORT ResourceProvider // GpuMemoryBuffer resource allocation needs to know how the resource will // be used. gfx::BufferUsage usage; + // This is the the actual format of the underlaying GpuMemoryBuffer, if any, + // and might not correspond to ResourceFormat. This format is needed to + // scanout the buffer as HW overlay. + gfx::BufferFormat buffer_format; + // Resource format is the format as seen from the compositor and might not + // correspond to buffer_format (e.g: A resouce that was created from a YUV + // buffer could be seen as RGB from the compositor/GL.) ResourceFormat format; SharedBitmapId shared_bitmap_id; SharedBitmap* shared_bitmap; @@ -712,15 +755,19 @@ class CC_EXPORT ResourceProvider gpu::gles2::GLES2Interface* ContextGL() const; bool IsGLContextLost() const; - // Returns null if |settings_.enable_color_correct_rendering| is false. - sk_sp<SkColorSpace> GetResourceSkColorSpace(const Resource* resource) const; + // Will return the invalid color space unless + // |enable_color_correct_rasterization| is true. + gfx::ColorSpace GetResourceColorSpaceForRaster( + const Resource* resource) const; + + void SetBatchReturnResources(bool aggregate); // Holds const settings for the ResourceProvider. Never changed after init. struct Settings { Settings(ContextProvider* compositor_context_provider, bool delegated_sync_points_required, bool use_gpu_memory_buffer_resources, - bool enable_color_correct_rendering); + bool enable_color_correct_rasterization); int max_texture_size = 0; bool use_texture_storage_ext = false; @@ -732,7 +779,7 @@ class CC_EXPORT ResourceProvider ResourceFormat yuv_highbit_resource_format = LUMINANCE_8; ResourceFormat best_texture_format = RGBA_8888; ResourceFormat best_render_buffer_format = RGBA_8888; - bool enable_color_correct_rendering = false; + bool enable_color_correct_rasterization = false; bool delegated_sync_points_required = false; } const settings_; @@ -746,10 +793,15 @@ class CC_EXPORT ResourceProvider int next_child_; ChildMap children_; scoped_refptr<Fence> current_read_lock_fence_; - std::unique_ptr<IdAllocator> texture_id_allocator_; - std::unique_ptr<IdAllocator> buffer_id_allocator_; + std::unique_ptr<TextureIdAllocator> texture_id_allocator_; BufferToTextureTargetMap buffer_to_texture_target_map_; + // Keep track of whether deleted resources should be batched up or returned + // immediately. + bool batch_return_resources_ = false; + // Maps from a child id to the set of resources to be returned to it. + base::SmallMap<std::map<int, ResourceIdArray>> batched_returning_resources_; + base::ThreadChecker thread_checker_; // A process-unique ID used for disambiguating memory dumps from different diff --git a/chromium/cc/resources/resource_provider_unittest.cc b/chromium/cc/resources/resource_provider_unittest.cc index 934908b1285..b804afbb7ba 100644 --- a/chromium/cc/resources/resource_provider_unittest.cc +++ b/chromium/cc/resources/resource_provider_unittest.cc @@ -1094,6 +1094,68 @@ INSTANTIATE_TEST_CASE_P( ResourceProviderTestNoSyncToken, ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)); +// Test that SetBatchReturnResources batching works. +TEST_P(ResourceProviderTest, SetBatchPreventsReturn) { + if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) + return; + gfx::Size size(1, 1); + ResourceFormat format = RGBA_8888; + + uint8_t data1[4] = {1, 2, 3, 4}; + ReturnedResourceArray returned_to_child; + int child_id = + resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); + + // Transfer some resources to the parent. + ResourceProvider::ResourceIdArray resource_ids_to_transfer; + ResourceId ids[2]; + for (size_t i = 0; i < arraysize(ids); i++) { + ids[i] = child_resource_provider_->CreateResource( + size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format, + gfx::ColorSpace()); + child_resource_provider_->CopyToResource(ids[i], data1, size); + resource_ids_to_transfer.push_back(ids[i]); + } + + child_resource_provider_->GenerateSyncTokenForResources( + resource_ids_to_transfer); + + TransferableResourceArray list; + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); + ASSERT_EQ(2u, list.size()); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(ids[0])); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(ids[1])); + + resource_provider_->ReceiveFromChild(child_id, list); + + std::vector<std::unique_ptr<ResourceProvider::ScopedReadLockGL>> read_locks; + for (auto& parent_resource : list) { + resource_provider_->WaitSyncTokenIfNeeded(parent_resource.id); + read_locks.push_back(base::MakeUnique<ResourceProvider::ScopedReadLockGL>( + resource_provider_.get(), parent_resource.id)); + } + + resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet()); + std::unique_ptr<ResourceProvider::ScopedBatchReturnResources> returner = + base::MakeUnique<ResourceProvider::ScopedBatchReturnResources>( + resource_provider_.get()); + EXPECT_EQ(0u, returned_to_child.size()); + + read_locks.clear(); + EXPECT_EQ(0u, returned_to_child.size()); + + returner.reset(); + EXPECT_EQ(2u, returned_to_child.size()); + // All resources in a batch should share a sync token. + EXPECT_EQ(returned_to_child[0].sync_token, returned_to_child[1].sync_token); + + child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); + child_resource_provider_->DeleteResource(ids[0]); + child_resource_provider_->DeleteResource(ids[1]); + EXPECT_EQ(0u, child_resource_provider_->num_resources()); +} + TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) { if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) return; diff --git a/chromium/cc/resources/resource_util.h b/chromium/cc/resources/resource_util.h index 51cda02d499..99fd2dc0c7a 100644 --- a/chromium/cc/resources/resource_util.h +++ b/chromium/cc/resources/resource_util.h @@ -11,8 +11,8 @@ #include "base/macros.h" #include "base/numerics/safe_math.h" -#include "cc/base/cc_export.h" #include "cc/base/math_util.h" +#include "cc/cc_export.h" #include "cc/resources/resource_format.h" #include "ui/gfx/geometry/size.h" diff --git a/chromium/cc/resources/returned_resource.h b/chromium/cc/resources/returned_resource.h index 6fb4af7b5b6..d919df9a6d5 100644 --- a/chromium/cc/resources/returned_resource.h +++ b/chromium/cc/resources/returned_resource.h @@ -7,8 +7,8 @@ #include <vector> -#include "cc/base/cc_export.h" #include "cc/base/resource_id.h" +#include "cc/cc_export.h" #include "gpu/command_buffer/common/sync_token.h" namespace cc { diff --git a/chromium/cc/resources/scoped_resource.h b/chromium/cc/resources/scoped_resource.h index 989a0211053..5fda730ac3b 100644 --- a/chromium/cc/resources/scoped_resource.h +++ b/chromium/cc/resources/scoped_resource.h @@ -10,7 +10,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/resource.h" #if DCHECK_IS_ON() diff --git a/chromium/cc/resources/scoped_ui_resource.h b/chromium/cc/resources/scoped_ui_resource.h index a0fb5d6df29..8b11f7ee7f0 100644 --- a/chromium/cc/resources/scoped_ui_resource.h +++ b/chromium/cc/resources/scoped_ui_resource.h @@ -7,7 +7,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/ui_resource_bitmap.h" #include "cc/resources/ui_resource_client.h" diff --git a/chromium/cc/resources/shared_bitmap.h b/chromium/cc/resources/shared_bitmap.h index c711a8b5ea4..464ac5c6d4c 100644 --- a/chromium/cc/resources/shared_bitmap.h +++ b/chromium/cc/resources/shared_bitmap.h @@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/trace_event/memory_allocator_dump.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "gpu/command_buffer/common/mailbox.h" #include "ui/gfx/geometry/size.h" diff --git a/chromium/cc/resources/shared_bitmap_manager.h b/chromium/cc/resources/shared_bitmap_manager.h index 7ee8c9ce2fb..3257a00c4c5 100644 --- a/chromium/cc/resources/shared_bitmap_manager.h +++ b/chromium/cc/resources/shared_bitmap_manager.h @@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/shared_bitmap.h" #include "ui/gfx/geometry/size.h" diff --git a/chromium/cc/resources/single_release_callback.h b/chromium/cc/resources/single_release_callback.h index cfb2330a4c2..802ccb16c33 100644 --- a/chromium/cc/resources/single_release_callback.h +++ b/chromium/cc/resources/single_release_callback.h @@ -8,7 +8,7 @@ #include <memory> #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/release_callback.h" namespace cc { diff --git a/chromium/cc/resources/single_release_callback_impl.h b/chromium/cc/resources/single_release_callback_impl.h index eafcb1f85e0..f5a8af05645 100644 --- a/chromium/cc/resources/single_release_callback_impl.h +++ b/chromium/cc/resources/single_release_callback_impl.h @@ -8,7 +8,7 @@ #include <memory> #include "base/memory/ptr_util.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/release_callback_impl.h" namespace cc { diff --git a/chromium/cc/resources/texture_mailbox.h b/chromium/cc/resources/texture_mailbox.h index bcb40c575a5..ee864718dfd 100644 --- a/chromium/cc/resources/texture_mailbox.h +++ b/chromium/cc/resources/texture_mailbox.h @@ -11,7 +11,7 @@ #include <string> #include "base/memory/shared_memory.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "gpu/command_buffer/common/mailbox_holder.h" #include "mojo/public/cpp/bindings/struct_traits.h" #include "ui/gfx/color_space.h" diff --git a/chromium/cc/resources/transferable_resource.cc b/chromium/cc/resources/transferable_resource.cc index a0bd745b409..65ac1f6ecfc 100644 --- a/chromium/cc/resources/transferable_resource.cc +++ b/chromium/cc/resources/transferable_resource.cc @@ -10,6 +10,7 @@ namespace cc { TransferableResource::TransferableResource() : id(0), format(RGBA_8888), + buffer_format(gfx::BufferFormat::RGBA_8888), filter(0), read_lock_fences_enabled(false), is_software(false), diff --git a/chromium/cc/resources/transferable_resource.h b/chromium/cc/resources/transferable_resource.h index ca623ad3c37..baa40486f8c 100644 --- a/chromium/cc/resources/transferable_resource.h +++ b/chromium/cc/resources/transferable_resource.h @@ -9,10 +9,11 @@ #include <vector> -#include "cc/base/cc_export.h" #include "cc/base/resource_id.h" +#include "cc/cc_export.h" #include "cc/resources/resource_format.h" #include "gpu/command_buffer/common/mailbox_holder.h" +#include "ui/gfx/buffer_types.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/size.h" @@ -33,7 +34,9 @@ struct CC_EXPORT TransferableResource { ReturnedResourceArray* output); ResourceId id; + // Refer to ResourceProvider::Resource for the meaning of the following data. ResourceFormat format; + gfx::BufferFormat buffer_format; uint32_t filter; gfx::Size size; gpu::MailboxHolder mailbox_holder; diff --git a/chromium/cc/resources/ui_resource_bitmap.cc b/chromium/cc/resources/ui_resource_bitmap.cc index c730c0e5e89..4d8d2816175 100644 --- a/chromium/cc/resources/ui_resource_bitmap.cc +++ b/chromium/cc/resources/ui_resource_bitmap.cc @@ -53,7 +53,7 @@ void UIResourceBitmap::Create(sk_sp<SkPixelRef> pixel_ref, void UIResourceBitmap::DrawToCanvas(SkCanvas* canvas, SkPaint* paint) { SkBitmap bitmap; bitmap.setInfo(pixel_ref_.get()->info(), pixel_ref_.get()->rowBytes()); - bitmap.setPixelRef(pixel_ref_.get()); + bitmap.setPixelRef(pixel_ref_, 0, 0); canvas->drawBitmap(bitmap, 0, 0, paint); canvas->flush(); } @@ -75,7 +75,7 @@ UIResourceBitmap::UIResourceBitmap(const gfx::Size& size, bool is_opaque) { SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), alphaType); sk_sp<SkPixelRef> pixel_ref( - SkMallocPixelRef::NewAllocate(info, info.minRowBytes(), NULL)); + SkMallocPixelRef::MakeAllocate(info, info.minRowBytes(), NULL)); pixel_ref->setImmutable(); Create(std::move(pixel_ref), size, UIResourceBitmap::RGBA8); SetOpaque(is_opaque); diff --git a/chromium/cc/resources/ui_resource_bitmap.h b/chromium/cc/resources/ui_resource_bitmap.h index fab6bc8d4b4..66a8a38d1cf 100644 --- a/chromium/cc/resources/ui_resource_bitmap.h +++ b/chromium/cc/resources/ui_resource_bitmap.h @@ -10,7 +10,7 @@ #include <memory> #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPixelRef.h" diff --git a/chromium/cc/resources/ui_resource_client.h b/chromium/cc/resources/ui_resource_client.h index c935ded6fcb..9da52dba104 100644 --- a/chromium/cc/resources/ui_resource_client.h +++ b/chromium/cc/resources/ui_resource_client.h @@ -7,7 +7,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/resources/ui_resource_manager.h b/chromium/cc/resources/ui_resource_manager.h index 269929b1c61..7f29ba61f30 100644 --- a/chromium/cc/resources/ui_resource_manager.h +++ b/chromium/cc/resources/ui_resource_manager.h @@ -9,7 +9,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/ui_resource_request.h" namespace cc { diff --git a/chromium/cc/resources/ui_resource_request.h b/chromium/cc/resources/ui_resource_request.h index 8294724e548..6178fde9094 100644 --- a/chromium/cc/resources/ui_resource_request.h +++ b/chromium/cc/resources/ui_resource_request.h @@ -8,7 +8,7 @@ #include <memory> #include "base/logging.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/ui_resource_bitmap.h" #include "cc/resources/ui_resource_client.h" diff --git a/chromium/cc/resources/video_resource_updater.cc b/chromium/cc/resources/video_resource_updater.cc index 295e2811d37..1c53b32da57 100644 --- a/chromium/cc/resources/video_resource_updater.cc +++ b/chromium/cc/resources/video_resource_updater.cc @@ -14,12 +14,14 @@ #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" #include "cc/output/gl_renderer.h" +#include "cc/paint/skia_paint_canvas.h" #include "cc/resources/resource_provider.h" #include "cc/resources/resource_util.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "media/base/video_frame.h" #include "media/renderers/skcanvas_video_renderer.h" +#include "media/video/half_float_maker.h" #include "third_party/khronos/GLES2/gl2.h" #include "third_party/khronos/GLES2/gl2ext.h" #include "third_party/libyuv/include/libyuv.h" @@ -297,138 +299,12 @@ static gfx::Size SoftwarePlaneDimension(media::VideoFrame* input_frame, return gfx::Size(plane_width, plane_height); } -namespace { -// By OR-ing with 0x3800, 10-bit numbers become half-floats in the -// range [0.5..1) and 9-bit numbers get the range [0.5..0.75). -// -// Half-floats are evaluated as: -// float value = pow(2.0, exponent - 25) * (0x400 + fraction); -// -// In our case the exponent is 14 (since we or with 0x3800) and -// pow(2.0, 14-25) * 0x400 evaluates to 0.5 (our offset) and -// pow(2.0, 14-25) * fraction is [0..0.49951171875] for 10-bit and -// [0..0.24951171875] for 9-bit. -// -// https://en.wikipedia.org/wiki/Half-precision_floating-point_format -class HalfFloatMaker_xor : public VideoResourceUpdater::HalfFloatMaker { - public: - explicit HalfFloatMaker_xor(int bits_per_channel) - : bits_per_channel_(bits_per_channel) {} - float Offset() const override { return 0.5; } - float Multiplier() const override { - int max_input_value = (1 << bits_per_channel_) - 1; - // 2 << 11 = 2048 would be 1.0 with our exponent. - return 2048.0 / max_input_value; - } - void MakeHalfFloats(const uint16_t* src, size_t num, uint16_t* dst) override { - // Micro-benchmarking indicates that the compiler does - // a good enough job of optimizing this loop that trying - // to manually operate on one uint64 at a time is not - // actually helpful. - // Note to future optimizers: Benchmark your optimizations! - for (size_t i = 0; i < num; i++) - dst[i] = src[i] | 0x3800; - } - - private: - int bits_per_channel_; -}; - -class HalfFloatMaker_libyuv : public VideoResourceUpdater::HalfFloatMaker { - public: - explicit HalfFloatMaker_libyuv(int bits_per_channel) { - int max_value = (1 << bits_per_channel) - 1; - // For less than 15 bits, we can give libyuv a multiplier of - // 1.0, which is faster on some platforms. If bits is 16 or larger, - // a multiplier of 1.0 would cause overflows. However, a multiplier - // of 1/max_value would cause subnormal floats, which perform - // very poorly on some platforms. - if (bits_per_channel <= 15) { - libyuv_multiplier_ = 1.0f; - } else { - // This multiplier makes sure that we avoid subnormal values. - libyuv_multiplier_ = 1.0f / 4096.0f; - } - resource_multiplier_ = 1.0f / libyuv_multiplier_ / max_value; - } - float Offset() const override { return 0.0f; } - float Multiplier() const override { return resource_multiplier_; } - void MakeHalfFloats(const uint16_t* src, size_t num, uint16_t* dst) override { - // Source and dest stride can be zero since we're only copying - // one row at a time. - int stride = 0; - int rows = 1; - libyuv::HalfFloatPlane(src, stride, dst, stride, libyuv_multiplier_, num, - rows); - } - - private: - float libyuv_multiplier_; - float resource_multiplier_; -}; - -} // namespace - -std::unique_ptr<VideoResourceUpdater::HalfFloatMaker> -VideoResourceUpdater::NewHalfFloatMaker(int bits_per_channel) { - if (bits_per_channel < 11) { - return std::unique_ptr<VideoResourceUpdater::HalfFloatMaker>( - new HalfFloatMaker_xor(bits_per_channel)); - } else { - return std::unique_ptr<VideoResourceUpdater::HalfFloatMaker>( - new HalfFloatMaker_libyuv(bits_per_channel)); - } -} - VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( scoped_refptr<media::VideoFrame> video_frame) { TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); const media::VideoPixelFormat input_frame_format = video_frame->format(); - // TODO(hubbe): Make this a video frame method. - int bits_per_channel = 0; - switch (input_frame_format) { - case media::PIXEL_FORMAT_UNKNOWN: - NOTREACHED(); - // Fall through! - case media::PIXEL_FORMAT_I420: - case media::PIXEL_FORMAT_YV12: - case media::PIXEL_FORMAT_YV16: - case media::PIXEL_FORMAT_YV12A: - case media::PIXEL_FORMAT_YV24: - case media::PIXEL_FORMAT_NV12: - case media::PIXEL_FORMAT_NV21: - case media::PIXEL_FORMAT_UYVY: - case media::PIXEL_FORMAT_YUY2: - case media::PIXEL_FORMAT_ARGB: - case media::PIXEL_FORMAT_XRGB: - case media::PIXEL_FORMAT_RGB24: - case media::PIXEL_FORMAT_RGB32: - case media::PIXEL_FORMAT_MJPEG: - case media::PIXEL_FORMAT_MT21: - case media::PIXEL_FORMAT_Y8: - case media::PIXEL_FORMAT_I422: - bits_per_channel = 8; - break; - case media::PIXEL_FORMAT_YUV420P9: - case media::PIXEL_FORMAT_YUV422P9: - case media::PIXEL_FORMAT_YUV444P9: - bits_per_channel = 9; - break; - case media::PIXEL_FORMAT_YUV420P10: - case media::PIXEL_FORMAT_YUV422P10: - case media::PIXEL_FORMAT_YUV444P10: - bits_per_channel = 10; - break; - case media::PIXEL_FORMAT_YUV420P12: - case media::PIXEL_FORMAT_YUV422P12: - case media::PIXEL_FORMAT_YUV444P12: - bits_per_channel = 12; - break; - case media::PIXEL_FORMAT_Y16: - bits_per_channel = 16; - break; - } + int bits_per_channel = video_frame->BitsPerChannel(input_frame_format); // Only YUV and Y16 software video frames are supported. DCHECK(media::IsYuvPlanar(input_frame_format) || @@ -437,10 +313,12 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( const bool software_compositor = context_provider_ == NULL; ResourceFormat output_resource_format; + gfx::ColorSpace output_color_space = video_frame->ColorSpace(); if (input_frame_format == media::PIXEL_FORMAT_Y16) { // Unable to display directly as yuv planes so convert it to RGBA for // compositing. output_resource_format = RGBA_8888; + output_color_space = output_color_space.GetAsFullRangeRGB(); } else { // Can be composited directly from yuv planes. output_resource_format = @@ -491,9 +369,8 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( const bool is_immutable = true; ResourceList::iterator resource_it = RecycleOrAllocateResource( - output_plane_resource_size, output_resource_format, - video_frame->ColorSpace(), software_compositor, is_immutable, - video_frame->unique_id(), i); + output_plane_resource_size, output_resource_format, output_color_space, + software_compositor, is_immutable, video_frame->unique_id(), i); resource_it->add_ref(); plane_resources.push_back(resource_it); @@ -517,7 +394,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( ResourceProvider::ScopedWriteLockSoftware lock( resource_provider_, plane_resource.resource_id()); - PaintCanvas canvas(lock.sk_bitmap()); + SkiaPaintCanvas canvas(lock.sk_bitmap()); // This is software path, so canvas and video_frame are always backed // by software. video_renderer_->Copy(video_frame, &canvas, media::Context3D()); @@ -550,7 +427,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), resource_provider_->GetResourceTextureTarget( plane_resource.resource_id())); - mailbox.set_color_space(video_frame->ColorSpace()); + mailbox.set_color_space(output_color_space); external_resources.mailboxes.push_back(mailbox); external_resources.release_callbacks.push_back(base::Bind( &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); @@ -559,10 +436,11 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( return external_resources; } - std::unique_ptr<HalfFloatMaker> half_float_maker; + std::unique_ptr<media::HalfFloatMaker> half_float_maker; if (resource_provider_->YuvResourceFormat(bits_per_channel) == LUMINANCE_F16) { - half_float_maker = NewHalfFloatMaker(bits_per_channel); + half_float_maker = + media::HalfFloatMaker::NewHalfFloatMaker(bits_per_channel); external_resources.offset = half_float_maker->Offset(); external_resources.multiplier = half_float_maker->Multiplier(); } @@ -574,7 +452,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( resource_provider_->YuvResourceFormat(bits_per_channel)); if (!plane_resource.Matches(video_frame->unique_id(), i)) { - // TODO(hubbe): Move all conversion (and upload?) code to media/. + // TODO(hubbe): Move upload code to media/. // We need to transfer data from |video_frame| to the plane resource. // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. @@ -652,7 +530,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), resource_provider_->GetResourceTextureTarget( plane_resource.resource_id())); - mailbox.set_color_space(video_frame->ColorSpace()); + mailbox.set_color_space(output_color_space); external_resources.mailboxes.push_back(mailbox); external_resources.release_callbacks.push_back(base::Bind( &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); @@ -685,6 +563,7 @@ void VideoResourceUpdater::ReturnTexture( // texture. void VideoResourceUpdater::CopyPlaneTexture( media::VideoFrame* video_frame, + const gfx::ColorSpace& resource_color_space, const gpu::MailboxHolder& mailbox_holder, VideoFrameExternalResources* external_resources) { gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); @@ -700,7 +579,7 @@ void VideoResourceUpdater::CopyPlaneTexture( const int no_plane_index = -1; // Do not recycle referenced textures. VideoResourceUpdater::ResourceList::iterator resource = RecycleOrAllocateResource(output_plane_resource_size, copy_target_format, - video_frame->ColorSpace(), false, is_immutable, + resource_color_space, false, is_immutable, no_unique_id, no_plane_index); resource->add_ref(); @@ -726,7 +605,7 @@ void VideoResourceUpdater::CopyPlaneTexture( // sync token is not required. TextureMailbox mailbox(resource->mailbox(), gpu::SyncToken(), GL_TEXTURE_2D, video_frame->coded_size(), false, false); - mailbox.set_color_space(video_frame->ColorSpace()); + mailbox.set_color_space(resource_color_space); external_resources->mailboxes.push_back(mailbox); external_resources->release_callbacks.push_back( @@ -745,6 +624,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) { external_resources.read_lock_fences_enabled = true; } + gfx::ColorSpace resource_color_space = video_frame->ColorSpace(); external_resources.type = ResourceTypeForVideoFrame(video_frame.get()); if (external_resources.type == VideoFrameExternalResources::NONE) { @@ -752,6 +632,8 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( << media::VideoPixelFormatToString(video_frame->format()); return external_resources; } + if (external_resources.type == VideoFrameExternalResources::RGB_RESOURCE) + resource_color_space = resource_color_space.GetAsFullRangeRGB(); const size_t num_planes = media::VideoFrame::NumPlanes(video_frame->format()); for (size_t i = 0; i < num_planes; ++i) { @@ -761,7 +643,8 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( if (video_frame->metadata()->IsTrue( media::VideoFrameMetadata::COPY_REQUIRED)) { - CopyPlaneTexture(video_frame.get(), mailbox_holder, &external_resources); + CopyPlaneTexture(video_frame.get(), resource_color_space, mailbox_holder, + &external_resources); } else { TextureMailbox mailbox(mailbox_holder.mailbox, mailbox_holder.sync_token, mailbox_holder.texture_target, @@ -769,7 +652,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( video_frame->metadata()->IsTrue( media::VideoFrameMetadata::ALLOW_OVERLAY), false); - mailbox.set_color_space(video_frame->ColorSpace()); + mailbox.set_color_space(resource_color_space); #if defined(OS_ANDROID) mailbox.set_is_backed_by_surface_texture(video_frame->metadata()->IsTrue( media::VideoFrameMetadata::SURFACE_TEXTURE)); diff --git a/chromium/cc/resources/video_resource_updater.h b/chromium/cc/resources/video_resource_updater.h index b9b5b95c026..603b4a35d09 100644 --- a/chromium/cc/resources/video_resource_updater.h +++ b/chromium/cc/resources/video_resource_updater.h @@ -16,7 +16,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/release_callback_impl.h" #include "cc/resources/resource_format.h" #include "cc/resources/texture_mailbox.h" @@ -80,28 +80,6 @@ class CC_EXPORT VideoResourceUpdater VideoFrameExternalResources CreateExternalResourcesFromVideoFrame( scoped_refptr<media::VideoFrame> video_frame); - // Base class for converting short integers to half-floats. - // TODO(hubbe): Move this to media/. - class HalfFloatMaker { - public: - // Convert an array of short integers into an array of half-floats. - // |src| is an array of integers in range 0 .. 2^{bits_per_channel} - 1 - // |num| is number of entries in input and output array. - // The numbers stored in |dst| will be half floats in range 0.0..1.0 - virtual void MakeHalfFloats(const uint16_t* src, - size_t num, - uint16_t* dst) = 0; - // The half-floats made needs by this class will be in the range - // [Offset() .. Offset() + 1.0/Multiplier]. So if you want results - // in the 0-1 range, you need to do: - // (half_float - Offset()) * Multiplier() - // to each returned value. - virtual float Offset() const = 0; - virtual float Multiplier() const = 0; - }; - - static std::unique_ptr<HalfFloatMaker> NewHalfFloatMaker( - int bits_per_channel); private: class PlaneResource { @@ -177,6 +155,7 @@ class CC_EXPORT VideoResourceUpdater bool immutable_hint); void DeleteResource(ResourceList::iterator resource_it); void CopyPlaneTexture(media::VideoFrame* video_frame, + const gfx::ColorSpace& resource_color_space, const gpu::MailboxHolder& mailbox_holder, VideoFrameExternalResources* external_resources); VideoFrameExternalResources CreateForHardwarePlanes( diff --git a/chromium/cc/resources/video_resource_updater_unittest.cc b/chromium/cc/resources/video_resource_updater_unittest.cc index 4b54fbe759f..3c7874e498e 100644 --- a/chromium/cc/resources/video_resource_updater_unittest.cc +++ b/chromium/cc/resources/video_resource_updater_unittest.cc @@ -519,62 +519,5 @@ TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_StreamTexture) { EXPECT_FALSE(context3d_->WasImmutableTextureCreated()); } -namespace { - -// Convert an IEEE 754 half-float to a double value -// that we can do math on. -double FromHalfFloat(uint16_t half_float) { - if (!half_float) - return 0.0; - int sign = (half_float & 0x8000) ? -1 : 1; - int exponent = (half_float >> 10) & 0x1F; - int fraction = half_float & 0x3FF; - if (exponent == 0) { - return pow(2.0, -24.0) * fraction; - } else if (exponent == 0x1F) { - return sign * 1000000000000.0; - } else { - return pow(2.0, exponent - 25) * (0x400 + fraction); - } -} - -} // namespace - -TEST_F(VideoResourceUpdaterTest, MakeHalfFloatTest) { - unsigned short integers[1 << 16]; - unsigned short half_floats[1 << 16]; - for (int bits = 9; bits <= 16; bits++) { - std::unique_ptr<VideoResourceUpdater::HalfFloatMaker> half_float_maker; - half_float_maker = VideoResourceUpdater::NewHalfFloatMaker(bits); - int num_values = 1 << bits; - for (int i = 0; i < num_values; i++) - integers[i] = i; - - half_float_maker->MakeHalfFloats(integers, num_values, half_floats); - // Multiplier to converting integers to 0.0..1.0 range. - double multiplier = 1.0 / (num_values - 1); - - for (int i = 0; i < num_values; i++) { - // This value is in range 0..1 - float value = integers[i] * multiplier; - // Reverse the effect of offset and multiplier to get the expected - // output value from the half-float converter. - float expected_value = - value / half_float_maker->Multiplier() + half_float_maker->Offset(); - EXPECT_EQ(integers[i], i); - - // We expect the result to be within +/- one least-significant bit. - // Within the range we care about, half-floats values and - // their representation both sort in the same order, so we - // can just add one to get the next bigger half-float. - float expected_precision = - FromHalfFloat(half_floats[i] + 1) - FromHalfFloat(half_floats[i]); - EXPECT_NEAR(FromHalfFloat(half_floats[i]), expected_value, - expected_precision) - << "i = " << i << " bits = " << bits; - } - } -} - } // namespace } // namespace cc diff --git a/chromium/cc/scheduler/begin_frame_source.cc b/chromium/cc/scheduler/begin_frame_source.cc index 714f505037b..4db7202a02c 100644 --- a/chromium/cc/scheduler/begin_frame_source.cc +++ b/chromium/cc/scheduler/begin_frame_source.cc @@ -103,7 +103,7 @@ void BackToBackBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { void BackToBackBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, const BeginFrameAck& ack) { - if (ack.remaining_frames == 0 && observers_.find(obs) != observers_.end()) { + if (observers_.find(obs) != observers_.end()) { pending_begin_frame_observers_.insert(obs); time_source_->SetActive(true); } @@ -437,7 +437,7 @@ void ExternalBeginFrameSource::FinishFrame() { BeginFrameAck ack(missed_begin_frame_args_.source_id, missed_begin_frame_args_.sequence_number, - ack_tracker_.LatestConfirmedSequenceNumber(), 0, + ack_tracker_.LatestConfirmedSequenceNumber(), ack_tracker_.AnyObserversHadDamage()); client_->OnDidFinishFrame(ack); } diff --git a/chromium/cc/scheduler/begin_frame_source.h b/chromium/cc/scheduler/begin_frame_source.h index 3b4e5231d18..9d5ce242b27 100644 --- a/chromium/cc/scheduler/begin_frame_source.h +++ b/chromium/cc/scheduler/begin_frame_source.h @@ -119,6 +119,12 @@ class CC_EXPORT BeginFrameSource { // (rather than toggling SetNeedsBeginFrames every frame). For example, the // BackToBackFrameSource uses them to make sure only one frame is pending at a // time. + // + // Note that the BeginFrameSource should not assume that the |ack| references + // a valid BeginFrame sent by the source. The |ack| may reference a BeginFrame + // sent by a different BeginFrameSource, and a malicious client may reference + // any invalid frame. The source is responsible for checking for + // validity/relevance of the BeginFrame itself. // TODO(eseckler): Use BeginFrameAcks in DisplayScheduler as described above. virtual void DidFinishFrame(BeginFrameObserver* obs, const BeginFrameAck& ack) = 0; @@ -164,7 +170,7 @@ class CC_EXPORT SyntheticBeginFrameSource : public BeginFrameSource { }; // A frame source which calls BeginFrame (at the next possible time) as soon as -// remaining frames reaches zero. +// an observer acknowledges the prior BeginFrame. class CC_EXPORT BackToBackBeginFrameSource : public SyntheticBeginFrameSource, public DelayBasedTimeSourceClient { public: diff --git a/chromium/cc/scheduler/begin_frame_source_unittest.cc b/chromium/cc/scheduler/begin_frame_source_unittest.cc index bce3439e31c..a15c4be4ebb 100644 --- a/chromium/cc/scheduler/begin_frame_source_unittest.cc +++ b/chromium/cc/scheduler/begin_frame_source_unittest.cc @@ -74,7 +74,7 @@ TEST_F(BackToBackBeginFrameSourceTest, AddObserverSendsBeginFrame) { 1100 + kDeadline, kInterval); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); task_runner_->RunPendingTasks(); } @@ -88,7 +88,7 @@ TEST_F(BackToBackBeginFrameSourceTest, source_->RemoveObserver(obs_.get()); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); // Verify no BeginFrame is sent to |obs_|. There is a pending task in the // task_runner_ as a BeginFrame was posted, but it gets aborted since |obs_| @@ -107,7 +107,7 @@ TEST_F(BackToBackBeginFrameSourceTest, now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); source_->RemoveObserver(obs_.get()); EXPECT_TRUE(task_runner_->HasPendingTasks()); @@ -131,7 +131,7 @@ TEST_F(BackToBackBeginFrameSourceTest, now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); // The begin frame is posted at the time when the observer was added, @@ -152,7 +152,7 @@ TEST_F(BackToBackBeginFrameSourceTest, now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); source_->RemoveObserver(obs_.get()); @@ -175,42 +175,10 @@ TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameNoObserver) { source_->AddObserver(obs_.get()); source_->RemoveObserver(obs_.get()); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); EXPECT_FALSE(task_runner_->RunPendingTasks()); } -TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameRemainingFrames) { - EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); - source_->AddObserver(obs_.get()); - EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000, - 1000 + kDeadline, kInterval); - // Runs the pending begin frame. - task_runner_->RunPendingTasks(); - // While running the begin frame, the next frame was cancelled, this - // runs the next frame, sees it was cancelled, and goes to sleep. - task_runner_->RunPendingTasks(); - EXPECT_FALSE(task_runner_->HasPendingTasks()); - - now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); - - source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 3, true)); - EXPECT_FALSE(task_runner_->HasPendingTasks()); - source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 2, true)); - EXPECT_FALSE(task_runner_->HasPendingTasks()); - source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 1, true)); - EXPECT_FALSE(task_runner_->HasPendingTasks()); - - EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1100, - 1100 + kDeadline, kInterval); - source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); - EXPECT_EQ(base::TimeDelta(), task_runner_->DelayToNextTaskTime()); - task_runner_->RunPendingTasks(); -} - TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameMultipleCallsIdempotent) { EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); source_->AddObserver(obs_.get()); @@ -220,22 +188,22 @@ TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameMultipleCallsIdempotent) { now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1100, 1100 + kDeadline, kInterval); task_runner_->RunPendingTasks(); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 2, 2, 0, true)); + BeginFrameAck(source_->source_id(), 2, 2, true)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 2, 2, 0, true)); + BeginFrameAck(source_->source_id(), 2, 2, true)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 2, 2, 0, true)); + BeginFrameAck(source_->source_id(), 2, 2, true)); EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 1200, 1200 + kDeadline, kInterval); task_runner_->RunPendingTasks(); @@ -250,7 +218,7 @@ TEST_F(BackToBackBeginFrameSourceTest, DelayInPostedTaskProducesCorrectFrame) { now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(obs_.get(), - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); now_src_->Advance(base::TimeDelta::FromMicroseconds(50)); // Ticks at the time the last frame finished, so ignores the last change to // "now". @@ -277,9 +245,9 @@ TEST_F(BackToBackBeginFrameSourceTest, MultipleObserversSynchronized) { now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(&obs1, - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); source_->DidFinishFrame(&obs2, - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 2, 1100, 1100 + kDeadline, kInterval); EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 2, 1100, 1100 + kDeadline, @@ -288,9 +256,9 @@ TEST_F(BackToBackBeginFrameSourceTest, MultipleObserversSynchronized) { now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(&obs1, - BeginFrameAck(source_->source_id(), 2, 2, 0, true)); + BeginFrameAck(source_->source_id(), 2, 2, true)); source_->DidFinishFrame(&obs2, - BeginFrameAck(source_->source_id(), 2, 2, 0, true)); + BeginFrameAck(source_->source_id(), 2, 2, true)); EXPECT_TRUE(task_runner_->HasPendingTasks()); source_->RemoveObserver(&obs1); source_->RemoveObserver(&obs2); @@ -315,13 +283,13 @@ TEST_F(BackToBackBeginFrameSourceTest, MultipleObserversInterleaved) { now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(&obs1, - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 3, 1200, 1200 + kDeadline, kInterval); task_runner_->RunPendingTasks(); source_->DidFinishFrame(&obs1, - BeginFrameAck(source_->source_id(), 3, 3, 0, true)); + BeginFrameAck(source_->source_id(), 3, 3, true)); source_->RemoveObserver(&obs1); // Removing all finished observers should disable the time source. EXPECT_FALSE(delay_based_time_source_->Active()); @@ -331,13 +299,13 @@ TEST_F(BackToBackBeginFrameSourceTest, MultipleObserversInterleaved) { now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(&obs2, - BeginFrameAck(source_->source_id(), 2, 2, 0, true)); + BeginFrameAck(source_->source_id(), 2, 2, true)); EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 4, 1300, 1300 + kDeadline, kInterval); task_runner_->RunPendingTasks(); source_->DidFinishFrame(&obs2, - BeginFrameAck(source_->source_id(), 4, 4, 0, true)); + BeginFrameAck(source_->source_id(), 4, 4, true)); source_->RemoveObserver(&obs2); } @@ -357,12 +325,12 @@ TEST_F(BackToBackBeginFrameSourceTest, MultipleObserversAtOnce) { // |obs1| finishes first. now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(&obs1, - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); // |obs2| finishes also, before getting to the newly posted begin frame. now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(&obs2, - BeginFrameAck(source_->source_id(), 1, 1, 0, true)); + BeginFrameAck(source_->source_id(), 1, 1, true)); // Because the begin frame source already ticked when |obs1| finished, // we see it as the frame time for both observers. @@ -373,10 +341,10 @@ TEST_F(BackToBackBeginFrameSourceTest, MultipleObserversAtOnce) { task_runner_->RunPendingTasks(); source_->DidFinishFrame(&obs1, - BeginFrameAck(source_->source_id(), 2, 2, 0, true)); + BeginFrameAck(source_->source_id(), 2, 2, true)); source_->RemoveObserver(&obs1); source_->DidFinishFrame(&obs2, - BeginFrameAck(source_->source_id(), 2, 2, 0, true)); + BeginFrameAck(source_->source_id(), 2, 2, true)); source_->RemoveObserver(&obs2); } @@ -647,7 +615,7 @@ TEST_F(BeginFrameObserverAckTrackerTest, CorrectnessWith1Observer) { // When the observer finishes and confirms, the BeginFrame is finished // and confirmed. obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 1, 1, 0, false)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 1, 1, false)); EXPECT_ACK_TRACKER_STATE(true, false, 1u); // A new BeginFrame is initially not finished or confirmed. @@ -656,13 +624,13 @@ TEST_F(BeginFrameObserverAckTrackerTest, CorrectnessWith1Observer) { EXPECT_ACK_TRACKER_STATE(false, false, 1u); // Stray ACK for an old BeginFrame is ignored. - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 1, 1, 0, false)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 1, 1, false)); EXPECT_ACK_TRACKER_STATE(false, false, 1u); // When the observer finishes but doesn't confirm, the BeginFrame is finished // but not confirmed. obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 2, 1, 0, false)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 2, 1, false)); EXPECT_ACK_TRACKER_STATE(true, false, 1u); // Damage from ACK propagates. @@ -670,7 +638,7 @@ TEST_F(BeginFrameObserverAckTrackerTest, CorrectnessWith1Observer) { tracker_->OnBeginFrame(current_args_); EXPECT_ACK_TRACKER_STATE(false, false, 1u); obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 3, 3, 0, true)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 3, 3, true)); EXPECT_ACK_TRACKER_STATE(true, true, 3u); // Removing an out-of-date observer confirms the latest BeginFrame. @@ -678,7 +646,7 @@ TEST_F(BeginFrameObserverAckTrackerTest, CorrectnessWith1Observer) { tracker_->OnBeginFrame(current_args_); EXPECT_ACK_TRACKER_STATE(false, false, 3u); obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 4, 3, 0, false)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 4, 3, false)); EXPECT_ACK_TRACKER_STATE(true, false, 3u); tracker_->OnObserverRemoved(&obs1_); EXPECT_ACK_TRACKER_STATE(true, false, 4u); @@ -702,11 +670,11 @@ TEST_F(BeginFrameObserverAckTrackerTest, CorrectnessWith2Observers) { // When one observer finishes and confirms, nothing changes. obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 1, 1, 0, false)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 1, 1, false)); EXPECT_ACK_TRACKER_STATE(false, false, 0u); // When both finish and confirm, the BeginFrame is finished and confirmed. obs2_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 1, 1, 0, false)); + tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 1, 1, false)); EXPECT_ACK_TRACKER_STATE(true, false, 1u); // A new BeginFrame is not finished or confirmed. @@ -717,10 +685,10 @@ TEST_F(BeginFrameObserverAckTrackerTest, CorrectnessWith2Observers) { // When both observers finish but only one confirms, the BeginFrame is // finished but not confirmed. obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 2, 2, 0, false)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 2, 2, false)); EXPECT_ACK_TRACKER_STATE(false, false, 1u); obs2_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 2, 1, 0, false)); + tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 2, 1, false)); EXPECT_ACK_TRACKER_STATE(true, false, 1u); // With reversed confirmations in the next ACKs, the latest confirmed frame @@ -729,10 +697,10 @@ TEST_F(BeginFrameObserverAckTrackerTest, CorrectnessWith2Observers) { tracker_->OnBeginFrame(current_args_); EXPECT_ACK_TRACKER_STATE(false, false, 1u); obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 3, 2, 0, false)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 3, 2, false)); EXPECT_ACK_TRACKER_STATE(false, false, 1u); obs2_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 3, 3, 0, false)); + tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 3, 3, false)); EXPECT_ACK_TRACKER_STATE(true, false, 2u); // Only a single ACK with damage suffices. @@ -740,10 +708,10 @@ TEST_F(BeginFrameObserverAckTrackerTest, CorrectnessWith2Observers) { tracker_->OnBeginFrame(current_args_); EXPECT_ACK_TRACKER_STATE(false, false, 2u); obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 4, 4, 0, true)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 4, 4, true)); EXPECT_ACK_TRACKER_STATE(false, true, 3u); obs2_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 4, 4, 0, false)); + tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 4, 4, false)); EXPECT_ACK_TRACKER_STATE(true, true, 4u); // Removing the damaging observer makes no difference in this case. @@ -765,10 +733,10 @@ TEST_F(BeginFrameObserverAckTrackerTest, CorrectnessWith2Observers) { EXPECT_ACK_TRACKER_STATE(false, false, 4u); // Both observers need to finish for the BeginFrame to be finished. obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 5, 5, 0, false)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(0, 5, 5, false)); EXPECT_ACK_TRACKER_STATE(false, false, 4u); obs2_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 5, 5, 0, false)); + tracker_->OnObserverFinishedFrame(&obs2_, BeginFrameAck(0, 5, 5, false)); EXPECT_ACK_TRACKER_STATE(true, false, 5u); } @@ -785,7 +753,7 @@ TEST_F(BeginFrameObserverAckTrackerTest, ChangingSourceIdOnBeginFrame) { tracker_->OnObserverAdded(&obs1_); EXPECT_ACK_TRACKER_STATE(false, false, 9u); // up to date to previous frame. obs1_.OnBeginFrame(current_args_); - tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(1, 10, 10, 0, true)); + tracker_->OnObserverFinishedFrame(&obs1_, BeginFrameAck(1, 10, 10, true)); EXPECT_ACK_TRACKER_STATE(true, true, 10u); // Changing source id with an observer sets confirmed BeginFrame to invalid. @@ -821,7 +789,7 @@ class ExternalBeginFrameSourceTest : public ::testing::Test { }; TEST_F(ExternalBeginFrameSourceTest, CallsOnDidFinishFrameWithoutObservers) { - EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 2, 0, false))) + EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 2, false))) .Times(1); source_->OnBeginFrame(CreateBeginFrameArgsForTesting( BEGINFRAME_FROM_HERE, 0, 2, base::TimeTicks::FromInternalValue(10000))); @@ -838,18 +806,18 @@ TEST_F(ExternalBeginFrameSourceTest, EXPECT_BEGIN_FRAME_ARGS_USED(*obs_, args); source_->OnBeginFrame(args); - EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 2, 0, true))) + EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 2, true))) .Times(1); - source_->DidFinishFrame(obs_.get(), BeginFrameAck(0, 2, 2, 0, true)); + source_->DidFinishFrame(obs_.get(), BeginFrameAck(0, 2, 2, true)); args = CreateBeginFrameArgsForTesting( BEGINFRAME_FROM_HERE, 0, 3, base::TimeTicks::FromInternalValue(20000)); EXPECT_BEGIN_FRAME_ARGS_USED(*obs_, args); source_->OnBeginFrame(args); - EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 3, 2, 0, false))) + EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 3, 2, false))) .Times(1); - source_->DidFinishFrame(obs_.get(), BeginFrameAck(0, 3, 2, 0, false)); + source_->DidFinishFrame(obs_.get(), BeginFrameAck(0, 3, 2, false)); } TEST_F(ExternalBeginFrameSourceTest, @@ -862,9 +830,9 @@ TEST_F(ExternalBeginFrameSourceTest, BEGINFRAME_FROM_HERE, 0, 2, base::TimeTicks::FromInternalValue(10000)); EXPECT_BEGIN_FRAME_ARGS_DROP(*obs_, args); source_->OnBeginFrame(args); - EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 0, 0, false))) + EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 0, false))) .Times(1); - source_->DidFinishFrame(obs_.get(), BeginFrameAck(0, 2, 0, 0, false)); + source_->DidFinishFrame(obs_.get(), BeginFrameAck(0, 2, 0, false)); } TEST_F(ExternalBeginFrameSourceTest, CallsOnDidFinishFrameWhenObserverRemoved) { @@ -877,7 +845,7 @@ TEST_F(ExternalBeginFrameSourceTest, CallsOnDidFinishFrameWhenObserverRemoved) { EXPECT_BEGIN_FRAME_ARGS_USED(*obs_, args); source_->OnBeginFrame(args); - EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 2, 0, false))) + EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 2, false))) .Times(1); EXPECT_CALL((*client_), OnNeedsBeginFrames(false)).Times(1); source_->RemoveObserver(obs_.get()); @@ -895,7 +863,7 @@ TEST_F(ExternalBeginFrameSourceTest, OnBeginFrameChecksBeginFrameContinuity) { source_->OnBeginFrame(args); // Providing same args again to OnBeginFrame() should not notify observer. - EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 0, 0, false))) + EXPECT_CALL((*client_), OnDidFinishFrame(BeginFrameAck(0, 2, 0, false))) .Times(1); source_->OnBeginFrame(args); diff --git a/chromium/cc/scheduler/commit_earlyout_reason.h b/chromium/cc/scheduler/commit_earlyout_reason.h index ff1566d9697..cd79c5c2fab 100644 --- a/chromium/cc/scheduler/commit_earlyout_reason.h +++ b/chromium/cc/scheduler/commit_earlyout_reason.h @@ -6,7 +6,7 @@ #define CC_SCHEDULER_COMMIT_EARLYOUT_REASON_H_ #include "base/logging.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/scheduler/compositor_timing_history.cc b/chromium/cc/scheduler/compositor_timing_history.cc index eee7dd06b00..d53023a6ba7 100644 --- a/chromium/cc/scheduler/compositor_timing_history.cc +++ b/chromium/cc/scheduler/compositor_timing_history.cc @@ -26,6 +26,7 @@ class CompositorTimingHistory::UMAReporter { virtual void AddDrawInterval(base::TimeDelta interval) = 0; // Latency measurements + virtual void AddBeginImplFrameLatency(base::TimeDelta delta) = 0; virtual void AddBeginMainFrameQueueDurationCriticalDuration( base::TimeDelta duration) = 0; virtual void AddBeginMainFrameQueueDurationNotCriticalDuration( @@ -62,10 +63,6 @@ const double kDrawEstimationPercentile = 90.0; constexpr base::TimeDelta kSubmitAckWatchdogTimeout = base::TimeDelta::FromSeconds(8); -const int kUmaDurationMinMicros = 1; -const int64_t kUmaDurationMaxMicros = base::Time::kMicrosecondsPerSecond / 5; -const int kUmaDurationBucketCount = 100; - // This macro is deprecated since its bucket count uses too much bandwidth. // It also has sub-optimal range and bucket distribution. // TODO(brianderson): Delete this macro and associated UMAs once there is @@ -111,7 +108,6 @@ const int kUMADurationBuckets[] = { #define UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED(name, sample) \ do { \ - UMA_HISTOGRAM_CUSTOM_TIMES_MICROS(name, sample); \ UMA_HISTOGRAM_CUSTOM_ENUMERATION( \ name "2", sample.InMicroseconds(), \ std::vector<int>(kUMAVSyncBuckets, \ @@ -120,7 +116,6 @@ const int kUMADurationBuckets[] = { #define UMA_HISTOGRAM_CUSTOM_TIMES_DURATION(name, sample) \ do { \ - UMA_HISTOGRAM_CUSTOM_TIMES_MICROS(name, sample); \ UMA_HISTOGRAM_CUSTOM_ENUMERATION( \ name "2", sample.InMicroseconds(), \ std::vector<int>( \ @@ -152,6 +147,11 @@ class RendererUMAReporter : public CompositorTimingHistory::UMAReporter { interval); } + void AddBeginImplFrameLatency(base::TimeDelta delta) override { + UMA_HISTOGRAM_CUSTOM_TIMES_DURATION( + "Scheduling.Renderer.BeginImplFrameLatency", delta); + } + void AddBeginMainFrameQueueDurationCriticalDuration( base::TimeDelta duration) override { UMA_HISTOGRAM_CUSTOM_TIMES_DURATION( @@ -229,6 +229,11 @@ class BrowserUMAReporter : public CompositorTimingHistory::UMAReporter { interval); } + void AddBeginImplFrameLatency(base::TimeDelta delta) override { + UMA_HISTOGRAM_CUSTOM_TIMES_DURATION( + "Scheduling.Browser.BeginImplFrameLatency", delta); + } + void AddBeginMainFrameQueueDurationCriticalDuration( base::TimeDelta duration) override { UMA_HISTOGRAM_CUSTOM_TIMES_DURATION( @@ -290,6 +295,7 @@ class NullUMAReporter : public CompositorTimingHistory::UMAReporter { } void AddCommitInterval(base::TimeDelta interval) override {} void AddDrawInterval(base::TimeDelta interval) override {} + void AddBeginImplFrameLatency(base::TimeDelta delta) override {} void AddBeginMainFrameQueueDurationCriticalDuration( base::TimeDelta duration) override {} void AddBeginMainFrameQueueDurationNotCriticalDuration( @@ -461,7 +467,10 @@ void CompositorTimingHistory::DidCreateAndInitializeCompositorFrameSink() { } void CompositorTimingHistory::WillBeginImplFrame( - bool new_active_tree_is_likely) { + bool new_active_tree_is_likely, + base::TimeTicks frame_time, + BeginFrameArgs::BeginFrameArgsType frame_type, + base::TimeTicks now) { // The check for whether a BeginMainFrame was sent anytime between two // BeginImplFrames protects us from not detecting a fast main thread that // does all it's work and goes idle in between BeginImplFrames. @@ -474,7 +483,7 @@ void CompositorTimingHistory::WillBeginImplFrame( } if (submit_ack_watchdog_enabled_) { - base::TimeDelta submit_not_acked_time_ = Now() - submit_start_time_; + base::TimeDelta submit_not_acked_time_ = now - submit_start_time_; if (submit_not_acked_time_ >= kSubmitAckWatchdogTimeout) { uma_reporter_->AddSubmitAckWasFast(false); // Only record this UMA once per submitted CompositorFrame. @@ -482,6 +491,9 @@ void CompositorTimingHistory::WillBeginImplFrame( } } + if (frame_type == BeginFrameArgs::NORMAL) + uma_reporter_->AddBeginImplFrameLatency(now - frame_time); + did_send_begin_main_frame_ = false; } diff --git a/chromium/cc/scheduler/compositor_timing_history.h b/chromium/cc/scheduler/compositor_timing_history.h index fb2fd816744..58f5a20191a 100644 --- a/chromium/cc/scheduler/compositor_timing_history.h +++ b/chromium/cc/scheduler/compositor_timing_history.h @@ -9,6 +9,8 @@ #include "base/macros.h" #include "cc/base/rolling_time_delta_history.h" +#include "cc/cc_export.h" +#include "cc/output/begin_frame_args.h" namespace base { namespace trace_event { @@ -53,7 +55,10 @@ class CC_EXPORT CompositorTimingHistory { void DidCreateAndInitializeCompositorFrameSink(); // Events to be timed. - void WillBeginImplFrame(bool new_active_tree_is_likely); + void WillBeginImplFrame(bool new_active_tree_is_likely, + base::TimeTicks frame_time, + BeginFrameArgs::BeginFrameArgsType frame_type, + base::TimeTicks now); void WillFinishImplFrame(bool needs_redraw); void BeginImplFrameNotExpectedSoon(); void WillBeginMainFrame(bool on_critical_path, diff --git a/chromium/cc/scheduler/delay_based_time_source.h b/chromium/cc/scheduler/delay_based_time_source.h index 417ee26fd07..a4fb79118e8 100644 --- a/chromium/cc/scheduler/delay_based_time_source.h +++ b/chromium/cc/scheduler/delay_based_time_source.h @@ -13,7 +13,7 @@ #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" #include "base/values.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { namespace trace_event { diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc index 66de03d3139..7212416461f 100644 --- a/chromium/cc/scheduler/scheduler.cc +++ b/chromium/cc/scheduler/scheduler.cc @@ -13,7 +13,7 @@ #include "base/single_thread_task_runner.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/debug/traced_value.h" #include "cc/scheduler/compositor_timing_history.h" #include "cc/scheduler/delay_based_time_source.h" @@ -409,20 +409,19 @@ void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { return; } - BeginImplFrame(adjusted_args); + BeginImplFrame(adjusted_args, now); } void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", args.AsValue()); - // The main thread currently can't commit before we draw with the // synchronous compositor, so never consider the BeginMainFrame fast. state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false); begin_main_frame_args_ = args; begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); - BeginImplFrame(args); + BeginImplFrame(args, Now()); compositor_timing_history_->WillFinishImplFrame( state_machine_.needs_redraw()); FinishImplFrame(); @@ -456,14 +455,15 @@ void Scheduler::SendBeginFrameAck(const BeginFrameArgs& args, } BeginFrameAck ack(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, did_submit); + latest_confirmed_sequence_number, did_submit); begin_frame_source_->DidFinishFrame(this, ack); } // 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(const BeginFrameArgs& args) { +void Scheduler::BeginImplFrame(const BeginFrameArgs& args, + base::TimeTicks now) { DCHECK_EQ(state_machine_.begin_impl_frame_state(), SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); @@ -473,7 +473,7 @@ void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { state_machine_.OnBeginImplFrame(args.source_id, args.sequence_number); devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); compositor_timing_history_->WillBeginImplFrame( - state_machine_.NewActiveTreeLikely()); + state_machine_.NewActiveTreeLikely(), args.frame_time, args.type, now); client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); ProcessScheduledActions(); @@ -698,11 +698,12 @@ Scheduler::AsValue() const { state->SetString("inside_action", SchedulerStateMachine::ActionToString(inside_action_)); - state->BeginDictionary("begin_impl_frame_args"); + state->BeginDictionary("begin_impl_frame_tracker"); begin_impl_frame_tracker_.AsValueInto(now, state.get()); state->EndDictionary(); - state->SetString("begin_impl_frame_deadline_mode_", + + state->SetString("begin_impl_frame_deadline_mode", SchedulerStateMachine::BeginImplFrameDeadlineModeToString( begin_impl_frame_deadline_mode_)); state->EndDictionary(); @@ -798,4 +799,11 @@ bool Scheduler::IsBeginMainFrameSentOrStarted() const { SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); } +BeginFrameAck Scheduler::CurrentBeginFrameAckForActiveTree() const { + return BeginFrameAck( + begin_main_frame_args_.source_id, begin_main_frame_args_.sequence_number, + state_machine_.last_begin_frame_sequence_number_active_tree_was_fresh(), + true); +} + } // namespace cc diff --git a/chromium/cc/scheduler/scheduler.h b/chromium/cc/scheduler/scheduler.h index 81a0a345c41..9efd831d76a 100644 --- a/chromium/cc/scheduler/scheduler.h +++ b/chromium/cc/scheduler/scheduler.h @@ -12,7 +12,7 @@ #include "base/cancelable_callback.h" #include "base/macros.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/begin_frame_args.h" #include "cc/scheduler/begin_frame_source.h" #include "cc/scheduler/begin_frame_tracker.h" @@ -152,6 +152,8 @@ class CC_EXPORT Scheduler : public BeginFrameObserverBase { return begin_frame_source_; } + BeginFrameAck CurrentBeginFrameAckForActiveTree() const; + protected: // Virtual for testing. virtual base::TimeTicks Now() const; @@ -204,7 +206,7 @@ class CC_EXPORT Scheduler : public BeginFrameObserverBase { bool IsBeginMainFrameSentOrStarted() const; void BeginImplFrameWithDeadline(const BeginFrameArgs& args); void BeginImplFrameSynchronous(const BeginFrameArgs& args); - void BeginImplFrame(const BeginFrameArgs& args); + void BeginImplFrame(const BeginFrameArgs& args, base::TimeTicks now); void FinishImplFrame(); enum BeginFrameResult { kBeginFrameSkipped, kBeginFrameFinished }; void SendBeginFrameAck(const BeginFrameArgs& args, BeginFrameResult result); diff --git a/chromium/cc/scheduler/scheduler_settings.h b/chromium/cc/scheduler/scheduler_settings.h index c6cc220ae69..eaf3799c182 100644 --- a/chromium/cc/scheduler/scheduler_settings.h +++ b/chromium/cc/scheduler/scheduler_settings.h @@ -10,7 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "base/values.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { namespace trace_event { diff --git a/chromium/cc/scheduler/scheduler_state_machine.cc b/chromium/cc/scheduler/scheduler_state_machine.cc index 6dd7c39f465..e73508ce1ab 100644 --- a/chromium/cc/scheduler/scheduler_state_machine.cc +++ b/chromium/cc/scheduler/scheduler_state_machine.cc @@ -693,9 +693,11 @@ void SchedulerStateMachine::WillSendBeginMainFrame() { } void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) { - DCHECK(!has_pending_tree_ || - (settings_.main_frame_before_activation_enabled && - commit_has_no_updates)); + bool can_have_pending_tree = + commit_has_no_updates && + (settings_.main_frame_before_activation_enabled || + current_pending_tree_is_impl_side_); + DCHECK(!has_pending_tree_ || can_have_pending_tree); commit_count_++; last_commit_had_no_updates_ = commit_has_no_updates; begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE; @@ -703,7 +705,7 @@ void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) { if (commit_has_no_updates) { // Pending tree might still exist from prior commit. if (has_pending_tree_) { - DCHECK(settings_.main_frame_before_activation_enabled); + DCHECK(can_have_pending_tree); last_begin_frame_sequence_number_pending_tree_was_fresh_ = last_begin_frame_sequence_number_begin_main_frame_sent_; } else { diff --git a/chromium/cc/scheduler/scheduler_state_machine.h b/chromium/cc/scheduler/scheduler_state_machine.h index 2ad99993d68..cd4a7f2ee66 100644 --- a/chromium/cc/scheduler/scheduler_state_machine.h +++ b/chromium/cc/scheduler/scheduler_state_machine.h @@ -11,7 +11,7 @@ #include <string> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/scheduler/commit_earlyout_reason.h" #include "cc/scheduler/draw_result.h" #include "cc/scheduler/scheduler_settings.h" @@ -290,6 +290,9 @@ class CC_EXPORT SchedulerStateMachine { } uint32_t begin_frame_source_id() const { return begin_frame_source_id_; } + uint64_t last_begin_frame_sequence_number_active_tree_was_fresh() const { + return last_begin_frame_sequence_number_active_tree_was_fresh_; + } uint64_t last_begin_frame_sequence_number_compositor_frame_was_fresh() const { return last_begin_frame_sequence_number_compositor_frame_was_fresh_; } diff --git a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc index 71b1422b036..0a99a0969a0 100644 --- a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc @@ -181,9 +181,6 @@ class StateMachine : public SchedulerStateMachine { uint64_t last_begin_frame_sequence_number_pending_tree_was_fresh() const { return last_begin_frame_sequence_number_pending_tree_was_fresh_; } - uint64_t last_begin_frame_sequence_number_active_tree_was_fresh() const { - return last_begin_frame_sequence_number_active_tree_was_fresh_; - } using SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately; using SchedulerStateMachine::ProactiveBeginFrameWanted; diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc index dad49921d50..72e31f53735 100644 --- a/chromium/cc/scheduler/scheduler_unittest.cc +++ b/chromium/cc/scheduler/scheduler_unittest.cc @@ -2868,7 +2868,7 @@ TEST_F(SchedulerTest, SynchronousCompositorCommitAndVerifyBeginFrameAcks) { EXPECT_EQ( BeginFrameAck(fake_external_begin_frame_source_->source_id(), last_begin_frame_number, latest_confirmed_sequence_number, - 0, has_damage), + has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); scheduler_->SetNeedsBeginMainFrame(); @@ -2885,7 +2885,7 @@ TEST_F(SchedulerTest, SynchronousCompositorCommitAndVerifyBeginFrameAcks) { has_damage = false; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); @@ -2900,7 +2900,7 @@ TEST_F(SchedulerTest, SynchronousCompositorCommitAndVerifyBeginFrameAcks) { has_damage = false; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); scheduler_->NotifyReadyToCommit(); @@ -2925,7 +2925,7 @@ TEST_F(SchedulerTest, SynchronousCompositorCommitAndVerifyBeginFrameAcks) { has_damage = false; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); // Android onDraw. @@ -2948,7 +2948,7 @@ TEST_F(SchedulerTest, SynchronousCompositorCommitAndVerifyBeginFrameAcks) { has_damage = false; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); } @@ -3386,7 +3386,7 @@ TEST_F(SchedulerTest, BeginFrameAckForFinishedImplFrame) { EXPECT_EQ( BeginFrameAck(fake_external_begin_frame_source_->source_id(), last_begin_frame_number, latest_confirmed_sequence_number, - 0, has_damage), + has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); // Run a successful redraw and verify that a new ack is sent. @@ -3411,7 +3411,7 @@ TEST_F(SchedulerTest, BeginFrameAckForFinishedImplFrame) { has_damage = true; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); // Request another redraw, but fail it. Verify that a new ack is sent, but @@ -3439,7 +3439,7 @@ TEST_F(SchedulerTest, BeginFrameAckForFinishedImplFrame) { has_damage = false; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); } @@ -3472,7 +3472,7 @@ TEST_F(SchedulerTest, BeginFrameAckForSkippedImplFrame) { bool has_damage = true; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); // Request another redraw that will be skipped because the swap ack is still @@ -3491,7 +3491,7 @@ TEST_F(SchedulerTest, BeginFrameAckForSkippedImplFrame) { has_damage = false; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); } @@ -3528,7 +3528,7 @@ TEST_F(SchedulerTest, BeginFrameAckForBeginFrameBeforeLastDeadline) { bool has_damage = false; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); } @@ -3565,7 +3565,7 @@ TEST_F(SchedulerTest, BeginFrameAckForDroppedBeginFrame) { bool has_damage = false; EXPECT_EQ( BeginFrameAck(second_args.source_id, second_args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); task_runner().RunPendingTasks(); // Run deadline of prior BeginFrame. @@ -3578,7 +3578,7 @@ TEST_F(SchedulerTest, BeginFrameAckForDroppedBeginFrame) { has_damage = false; EXPECT_EQ( BeginFrameAck(first_args.source_id, first_args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); } @@ -3610,7 +3610,7 @@ TEST_F(SchedulerTest, BeginFrameAckForLateMissedBeginFrame) { bool has_damage = false; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); } @@ -3643,7 +3643,7 @@ TEST_F(SchedulerTest, BeginFrameAckForFinishedBeginFrameWithNewSourceId) { bool has_damage = true; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); } @@ -3676,7 +3676,7 @@ TEST_F(SchedulerTest, bool has_damage = false; EXPECT_EQ( BeginFrameAck(args.source_id, args.sequence_number, - latest_confirmed_sequence_number, 0, has_damage), + latest_confirmed_sequence_number, has_damage), fake_external_begin_frame_source_->LastAckForObserver(scheduler_.get())); } diff --git a/chromium/cc/scheduler/video_frame_controller.h b/chromium/cc/scheduler/video_frame_controller.h index 0307cd5e402..8a8c6e08ac0 100644 --- a/chromium/cc/scheduler/video_frame_controller.h +++ b/chromium/cc/scheduler/video_frame_controller.h @@ -5,7 +5,7 @@ #ifndef CC_SCHEDULER_VIDEO_FRAME_CONTROLLER_H_ #define CC_SCHEDULER_VIDEO_FRAME_CONTROLLER_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/begin_frame_args.h" namespace cc { diff --git a/chromium/cc/surfaces/BUILD.gn b/chromium/cc/surfaces/BUILD.gn index d3917457070..3ba5480608b 100644 --- a/chromium/cc/surfaces/BUILD.gn +++ b/chromium/cc/surfaces/BUILD.gn @@ -45,6 +45,8 @@ cc_component("surfaces") { "display_client.h", "display_scheduler.cc", "display_scheduler.h", + "framesink_manager.cc", + "framesink_manager.h", "local_surface_id_allocator.cc", "local_surface_id_allocator.h", "pending_frame_observer.h", @@ -83,9 +85,10 @@ cc_component("surfaces") { "//cc", "//gpu/command_buffer/client:gles2_interface", "//gpu/command_buffer/common", + "//gpu/vulkan:features", "//skia", - "//ui/events:events_base", "//ui/gfx", "//ui/gfx/geometry", + "//ui/latency", ] } diff --git a/chromium/cc/surfaces/compositor_frame_sink_support.cc b/chromium/cc/surfaces/compositor_frame_sink_support.cc index 0d2e90bd0a3..84b0a41d9cc 100644 --- a/chromium/cc/surfaces/compositor_frame_sink_support.cc +++ b/chromium/cc/surfaces/compositor_frame_sink_support.cc @@ -17,25 +17,19 @@ namespace cc { -CompositorFrameSinkSupport::CompositorFrameSinkSupport( +// static +std::unique_ptr<CompositorFrameSinkSupport> CompositorFrameSinkSupport::Create( CompositorFrameSinkSupportClient* client, SurfaceManager* surface_manager, const FrameSinkId& frame_sink_id, bool is_root, bool handles_frame_sink_id_invalidation, - bool needs_sync_points) - : client_(client), - surface_manager_(surface_manager), - frame_sink_id_(frame_sink_id), - surface_factory_(frame_sink_id_, surface_manager_, this), - reference_tracker_(frame_sink_id), - is_root_(is_root), - handles_frame_sink_id_invalidation_(handles_frame_sink_id_invalidation), - weak_factory_(this) { - surface_factory_.set_needs_sync_points(needs_sync_points); - if (handles_frame_sink_id_invalidation_) - surface_manager_->RegisterFrameSinkId(frame_sink_id_); - surface_manager_->RegisterSurfaceFactoryClient(frame_sink_id_, this); + bool needs_sync_points) { + std::unique_ptr<CompositorFrameSinkSupport> support = + base::WrapUnique(new CompositorFrameSinkSupport( + client, frame_sink_id, is_root, handles_frame_sink_id_invalidation)); + support->Init(surface_manager, needs_sync_points); + return support; } CompositorFrameSinkSupport::~CompositorFrameSinkSupport() { @@ -52,14 +46,63 @@ CompositorFrameSinkSupport::~CompositorFrameSinkSupport() { // SurfaceFactory's destructor will attempt to return resources which will // call back into here and access |client_| so we should destroy // |surface_factory_|'s resources early on. - surface_factory_.EvictSurface(); + surface_factory_->EvictSurface(); surface_manager_->UnregisterSurfaceFactoryClient(frame_sink_id_); if (handles_frame_sink_id_invalidation_) surface_manager_->InvalidateFrameSinkId(frame_sink_id_); } +void CompositorFrameSinkSupport::ReferencedSurfacesChanged( + const LocalSurfaceId& local_surface_id, + const std::vector<SurfaceId>* active_referenced_surfaces) { + if (!surface_manager_->using_surface_references()) + return; + + SurfaceId last_surface_id = reference_tracker_.current_surface_id(); + + // Populate list of surface references to add and remove based on reference + // surfaces in current frame compared with the last frame. The list of + // surface references includes references from both the pending and active + // frame if any. + reference_tracker_.UpdateReferences(local_surface_id, + active_referenced_surfaces); + + UpdateSurfaceReferences(last_surface_id, local_surface_id); +} + +void CompositorFrameSinkSupport::ReturnResources( + const ReturnedResourceArray& resources) { + if (resources.empty()) + return; + if (!ack_pending_count_ && client_) { + client_->ReclaimResources(resources); + return; + } + + std::copy(resources.begin(), resources.end(), + std::back_inserter(surface_returned_resources_)); +} + +void CompositorFrameSinkSupport::SetBeginFrameSource( + BeginFrameSource* begin_frame_source) { + if (begin_frame_source_ && added_frame_observer_) { + begin_frame_source_->RemoveObserver(this); + added_frame_observer_ = false; + } + begin_frame_source_ = begin_frame_source; + UpdateNeedsBeginFramesInternal(); +} + +void CompositorFrameSinkSupport::WillDrawSurface( + const LocalSurfaceId& local_surface_id, + const gfx::Rect& damage_rect) { + if (client_) + client_->WillDrawSurface(local_surface_id, damage_rect); +} + void CompositorFrameSinkSupport::EvictFrame() { - surface_factory_.EvictSurface(); + DCHECK(surface_factory_); + surface_factory_->EvictSurface(); } void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) { @@ -67,7 +110,18 @@ void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) { UpdateNeedsBeginFramesInternal(); } -void CompositorFrameSinkSupport::DidFinishFrame(const BeginFrameAck& ack) { +void CompositorFrameSinkSupport::BeginFrameDidNotSwap( + const BeginFrameAck& ack) { + // TODO(eseckler): While a pending CompositorFrame exists (see TODO below), we + // should not acknowledge immediately. Instead, we should update the ack that + // will be sent to DisplayScheduler when the pending frame is activated. + if (ack.sequence_number < BeginFrameArgs::kStartingFrameNumber) { + DLOG(ERROR) << "Received BeginFrameDidNotSwap with invalid BeginFrameAck."; + return; + } + + // |has_damage| is not transmitted, but false by default. + DCHECK(!ack.has_damage); if (begin_frame_source_) begin_frame_source_->DidFinishFrame(this, ack); } @@ -75,12 +129,32 @@ void CompositorFrameSinkSupport::DidFinishFrame(const BeginFrameAck& ack) { void CompositorFrameSinkSupport::SubmitCompositorFrame( const LocalSurfaceId& local_surface_id, CompositorFrame frame) { + DCHECK(surface_factory_); ++ack_pending_count_; - surface_factory_.SubmitCompositorFrame( + if (frame.metadata.begin_frame_ack.sequence_number < + BeginFrameArgs::kStartingFrameNumber) { + DLOG(ERROR) << "Received CompositorFrame with invalid BeginFrameAck."; + frame.metadata.begin_frame_ack.source_id = BeginFrameArgs::kManualSourceId; + frame.metadata.begin_frame_ack.sequence_number = + BeginFrameArgs::kStartingFrameNumber; + } + // |has_damage| is not transmitted. + frame.metadata.begin_frame_ack.has_damage = true; + + BeginFrameAck ack = frame.metadata.begin_frame_ack; + surface_factory_->SubmitCompositorFrame( local_surface_id, std::move(frame), base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck, weak_factory_.GetWeakPtr())); + + // TODO(eseckler): The CompositorFrame submitted below might not be activated + // right away b/c of surface synchronization. We should only send the + // BeginFrameAck to DisplayScheduler when it is activated. This also means + // that we need to stay an active BFO while a CompositorFrame is pending. + // See https://crbug.com/703079. + if (begin_frame_source_) + begin_frame_source_->DidFinishFrame(this, ack); } void CompositorFrameSinkSupport::UpdateSurfaceReferences( @@ -131,18 +205,15 @@ void CompositorFrameSinkSupport::RemoveTopLevelRootReference( void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() { DCHECK_GT(ack_pending_count_, 0); ack_pending_count_--; - if (!client_) return; - client_->DidReceiveCompositorFrameAck(); - if (!surface_returned_resources_.empty()) { - client_->ReclaimResources(surface_returned_resources_); - surface_returned_resources_.clear(); - } + client_->DidReceiveCompositorFrameAck(surface_returned_resources_); + surface_returned_resources_.clear(); } void CompositorFrameSinkSupport::ForceReclaimResources() { - surface_factory_.ClearSurface(); + DCHECK(surface_factory_); + surface_factory_->ClearSurface(); } void CompositorFrameSinkSupport::ClaimTemporaryReference( @@ -150,55 +221,27 @@ void CompositorFrameSinkSupport::ClaimTemporaryReference( surface_manager_->AssignTemporaryReference(surface_id, frame_sink_id_); } -void CompositorFrameSinkSupport::ReferencedSurfacesChanged( - const LocalSurfaceId& local_surface_id, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces) { - if (!surface_manager_->using_surface_references()) - return; - - SurfaceId last_surface_id = reference_tracker_.current_surface_id(); - - // Populate list of surface references to add and remove based on reference - // surfaces in current frame compared with the last frame. The list of - // surface references includes references from both the pending and active - // frame if any. - reference_tracker_.UpdateReferences(local_surface_id, - active_referenced_surfaces, - pending_referenced_surfaces); - - UpdateSurfaceReferences(last_surface_id, local_surface_id); -} - -void CompositorFrameSinkSupport::ReturnResources( - const ReturnedResourceArray& resources) { - if (resources.empty()) - return; - - if (!ack_pending_count_ && client_) { - client_->ReclaimResources(resources); - return; - } - - std::copy(resources.begin(), resources.end(), - std::back_inserter(surface_returned_resources_)); -} - -void CompositorFrameSinkSupport::SetBeginFrameSource( - BeginFrameSource* begin_frame_source) { - if (begin_frame_source_ && added_frame_observer_) { - begin_frame_source_->RemoveObserver(this); - added_frame_observer_ = false; - } - begin_frame_source_ = begin_frame_source; - UpdateNeedsBeginFramesInternal(); -} +CompositorFrameSinkSupport::CompositorFrameSinkSupport( + CompositorFrameSinkSupportClient* client, + const FrameSinkId& frame_sink_id, + bool is_root, + bool handles_frame_sink_id_invalidation) + : client_(client), + frame_sink_id_(frame_sink_id), + reference_tracker_(frame_sink_id), + is_root_(is_root), + handles_frame_sink_id_invalidation_(handles_frame_sink_id_invalidation), + weak_factory_(this) {} -void CompositorFrameSinkSupport::WillDrawSurface( - const LocalSurfaceId& local_surface_id, - const gfx::Rect& damage_rect) { - if (client_) - client_->WillDrawSurface(local_surface_id, damage_rect); +void CompositorFrameSinkSupport::Init(SurfaceManager* surface_manager, + bool needs_sync_points) { + surface_manager_ = surface_manager; + surface_factory_ = + base::MakeUnique<SurfaceFactory>(frame_sink_id_, surface_manager_, this); + if (handles_frame_sink_id_invalidation_) + surface_manager_->RegisterFrameSinkId(frame_sink_id_); + surface_manager_->RegisterSurfaceFactoryClient(frame_sink_id_, this); + surface_factory_->set_needs_sync_points(needs_sync_points); } void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) { @@ -231,7 +274,8 @@ void CompositorFrameSinkSupport::UpdateNeedsBeginFramesInternal() { void CompositorFrameSinkSupport::RequestCopyOfSurface( std::unique_ptr<CopyOutputRequest> request) { - surface_factory_.RequestCopyOfSurface(std::move(request)); + DCHECK(surface_factory_); + surface_factory_->RequestCopyOfSurface(std::move(request)); } } // namespace cc diff --git a/chromium/cc/surfaces/compositor_frame_sink_support.h b/chromium/cc/surfaces/compositor_frame_sink_support.h index a0018fd2b71..977acdf9788 100644 --- a/chromium/cc/surfaces/compositor_frame_sink_support.h +++ b/chromium/cc/surfaces/compositor_frame_sink_support.h @@ -28,34 +28,52 @@ class CC_SURFACES_EXPORT CompositorFrameSinkSupport : public SurfaceFactoryClient, public BeginFrameObserver { public: - CompositorFrameSinkSupport(CompositorFrameSinkSupportClient* client, - SurfaceManager* surface_manager, - const FrameSinkId& frame_sink_id, - bool is_root, - bool handles_frame_sink_id_invalidation, - bool needs_sync_points); + static std::unique_ptr<CompositorFrameSinkSupport> Create( + CompositorFrameSinkSupportClient* client, + SurfaceManager* surface_manager, + const FrameSinkId& frame_sink_id, + bool is_root, + bool handles_frame_sink_id_invalidation, + bool needs_sync_points); ~CompositorFrameSinkSupport() override; const FrameSinkId& frame_sink_id() const { return frame_sink_id_; } Surface* current_surface_for_testing() { - return surface_factory_.current_surface_for_testing(); + return surface_factory_->current_surface_for_testing(); } const ReferencedSurfaceTracker& ReferenceTrackerForTesting() const { return reference_tracker_; } + // SurfaceFactoryClient implementation. + void ReferencedSurfacesChanged( + const LocalSurfaceId& local_surface_id, + const std::vector<SurfaceId>* active_referenced_surfaces) override; + void ReturnResources(const ReturnedResourceArray& resources) override; + void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override; + void WillDrawSurface(const LocalSurfaceId& local_surface_id, + const gfx::Rect& damage_rect) override; + void EvictFrame(); void SetNeedsBeginFrame(bool needs_begin_frame); - void DidFinishFrame(const BeginFrameAck& ack); + void BeginFrameDidNotSwap(const BeginFrameAck& ack); void SubmitCompositorFrame(const LocalSurfaceId& local_surface_id, CompositorFrame frame); void RequestCopyOfSurface(std::unique_ptr<CopyOutputRequest> request); void ForceReclaimResources(); void ClaimTemporaryReference(const SurfaceId& surface_id); + protected: + CompositorFrameSinkSupport(CompositorFrameSinkSupportClient* client, + const FrameSinkId& frame_sink_id, + bool is_root, + bool handles_frame_sink_id_invalidation); + + void Init(SurfaceManager* surface_manager, bool needs_sync_points); + private: // Update surface references with SurfaceManager for current CompositorFrame // that has |local_surface_id|. UpdateReferences() must be called on @@ -69,16 +87,6 @@ class CC_SURFACES_EXPORT CompositorFrameSinkSupport void DidReceiveCompositorFrameAck(); - // SurfaceFactoryClient implementation. - void ReferencedSurfacesChanged( - const LocalSurfaceId& local_surface_id, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces) override; - void ReturnResources(const ReturnedResourceArray& resources) override; - void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override; - void WillDrawSurface(const LocalSurfaceId& local_surface_id, - const gfx::Rect& damage_rect) override; - // BeginFrameObserver implementation. void OnBeginFrame(const BeginFrameArgs& args) override; const BeginFrameArgs& LastUsedBeginFrameArgs() const override; @@ -88,11 +96,11 @@ class CC_SURFACES_EXPORT CompositorFrameSinkSupport CompositorFrameSinkSupportClient* const client_; - SurfaceManager* const surface_manager_; + SurfaceManager* surface_manager_ = nullptr; const FrameSinkId frame_sink_id_; - SurfaceFactory surface_factory_; + std::unique_ptr<SurfaceFactory> surface_factory_; // Counts the number of CompositorFrames that have been submitted and have not // yet received an ACK. int ack_pending_count_ = 0; diff --git a/chromium/cc/surfaces/compositor_frame_sink_support_client.h b/chromium/cc/surfaces/compositor_frame_sink_support_client.h index 905f6db8ec7..4fd378605b9 100644 --- a/chromium/cc/surfaces/compositor_frame_sink_support_client.h +++ b/chromium/cc/surfaces/compositor_frame_sink_support_client.h @@ -26,7 +26,8 @@ class CompositorFrameSinkSupportClient { // TODO(fsamuel): This method ought not be necessary with unified BeginFrame. // However, there's a fair amount of cleanup and refactoring necessary to get // rid of it. - virtual void DidReceiveCompositorFrameAck() = 0; + virtual void DidReceiveCompositorFrameAck( + const ReturnedResourceArray& resources) = 0; // Notification for the client to generate a CompositorFrame. virtual void OnBeginFrame(const BeginFrameArgs& args) = 0; diff --git a/chromium/cc/surfaces/compositor_frame_sink_support_unittest.cc b/chromium/cc/surfaces/compositor_frame_sink_support_unittest.cc index 83cf8edce9c..6a7a5089ae5 100644 --- a/chromium/cc/surfaces/compositor_frame_sink_support_unittest.cc +++ b/chromium/cc/surfaces/compositor_frame_sink_support_unittest.cc @@ -4,6 +4,7 @@ #include "cc/surfaces/compositor_frame_sink_support.h" +#include "base/debug/stack_trace.h" #include "base/macros.h" #include "cc/output/compositor_frame.h" #include "cc/surfaces/compositor_frame_sink_support_client.h" @@ -18,6 +19,9 @@ using testing::UnorderedElementsAre; using testing::IsEmpty; using testing::SizeIs; +using testing::Invoke; +using testing::_; +using testing::Eq; namespace cc { namespace test { @@ -29,6 +33,39 @@ constexpr FrameSinkId kChildFrameSink1(65563, 0); constexpr FrameSinkId kChildFrameSink2(65564, 0); constexpr FrameSinkId kArbitraryFrameSink(1337, 7331); +class MockCompositorFrameSinkSupportClient + : public CompositorFrameSinkSupportClient { + public: + MockCompositorFrameSinkSupportClient() { + ON_CALL(*this, ReclaimResources(_)) + .WillByDefault(Invoke( + this, + &MockCompositorFrameSinkSupportClient::ReclaimResourcesInternal)); + ON_CALL(*this, DidReceiveCompositorFrameAck(_)) + .WillByDefault(Invoke( + this, + &MockCompositorFrameSinkSupportClient::ReclaimResourcesInternal)); + } + + ReturnedResourceArray& last_returned_resources() { + return last_returned_resources_; + } + + // CompositorFrameSinkSupportClient implementation. + MOCK_METHOD1(DidReceiveCompositorFrameAck, + void(const ReturnedResourceArray&)); + MOCK_METHOD1(OnBeginFrame, void(const BeginFrameArgs&)); + MOCK_METHOD1(ReclaimResources, void(const ReturnedResourceArray&)); + MOCK_METHOD2(WillDrawSurface, void(const LocalSurfaceId&, const gfx::Rect&)); + + private: + void ReclaimResourcesInternal(const ReturnedResourceArray& resources) { + last_returned_resources_ = resources; + } + + ReturnedResourceArray last_returned_resources_; +}; + std::vector<SurfaceId> empty_surface_ids() { return std::vector<SurfaceId>(); } @@ -39,22 +76,41 @@ SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) { LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u))); } -CompositorFrame MakeCompositorFrame( - std::vector<SurfaceId> referenced_surfaces) { +CompositorFrame MakeCompositorFrame(std::vector<SurfaceId> embedded_surfaces, + std::vector<SurfaceId> referenced_surfaces, + TransferableResourceArray resource_list) { CompositorFrame compositor_frame; + compositor_frame.metadata.begin_frame_ack = BeginFrameAck(0, 1, 1, true); + compositor_frame.metadata.embedded_surfaces = std::move(embedded_surfaces); compositor_frame.metadata.referenced_surfaces = std::move(referenced_surfaces); + compositor_frame.resource_list = std::move(resource_list); return compositor_frame; } +CompositorFrame MakeCompositorFrame() { + return MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(), + TransferableResourceArray()); +} + +CompositorFrame MakeCompositorFrame(std::vector<SurfaceId> embedded_surfaces) { + return MakeCompositorFrame(embedded_surfaces, embedded_surfaces, + TransferableResourceArray()); +} + +CompositorFrame MakeCompositorFrame( + std::vector<SurfaceId> embedded_surfaces, + std::vector<SurfaceId> referenced_surfaces) { + return MakeCompositorFrame(std::move(embedded_surfaces), + std::move(referenced_surfaces), + TransferableResourceArray()); +} + CompositorFrame MakeCompositorFrameWithResources( - std::vector<SurfaceId> referenced_surfaces, + std::vector<SurfaceId> embedded_surfaces, TransferableResourceArray resource_list) { - CompositorFrame compositor_frame; - compositor_frame.metadata.referenced_surfaces = - std::move(referenced_surfaces); - compositor_frame.resource_list = std::move(resource_list); - return compositor_frame; + return MakeCompositorFrame(embedded_surfaces, embedded_surfaces, + std::move(resource_list)); } TransferableResource MakeResource(ResourceId id, @@ -71,14 +127,16 @@ TransferableResource MakeResource(ResourceId id, } // namespace -class CompositorFrameSinkSupportTest : public testing::Test, - public CompositorFrameSinkSupportClient { +class CompositorFrameSinkSupportTest : public testing::Test { public: CompositorFrameSinkSupportTest() : surface_manager_(SurfaceManager::LifetimeType::REFERENCES) {} ~CompositorFrameSinkSupportTest() override {} CompositorFrameSinkSupport& display_support() { return *supports_[0]; } + Surface* display_surface() { + return display_support().current_surface_for_testing(); + } CompositorFrameSinkSupport& parent_support() { return *supports_[1]; } Surface* parent_surface() { @@ -124,35 +182,30 @@ class CompositorFrameSinkSupportTest : public testing::Test, return begin_frame_source_.get(); } - ReturnedResourceArray& last_returned_resources() { - return last_returned_resources_; - } - // testing::Test: void SetUp() override { testing::Test::SetUp(); + constexpr bool is_root = true; + constexpr bool is_child_root = false; + constexpr bool handles_frame_sink_id_invalidation = true; + constexpr bool needs_sync_points = true; begin_frame_source_ = base::MakeUnique<FakeExternalBeginFrameSource>(0.f, false); - std::unique_ptr<SurfaceDependencyTracker> dependency_tracker( - new SurfaceDependencyTracker(&surface_manager_, - begin_frame_source_.get())); - surface_manager_.SetDependencyTracker(std::move(dependency_tracker)); - supports_.push_back(base::MakeUnique<CompositorFrameSinkSupport>( - this, &surface_manager_, kDisplayFrameSink, true /* is_root */, - true /* handles_frame_sink_id_invalidation */, - true /* needs_sync_points */)); - supports_.push_back(base::MakeUnique<CompositorFrameSinkSupport>( - this, &surface_manager_, kParentFrameSink, false /* is_root */, - true /* handles_frame_sink_id_invalidation */, - true /* needs_sync_points */)); - supports_.push_back(base::MakeUnique<CompositorFrameSinkSupport>( - this, &surface_manager_, kChildFrameSink1, false /* is_root */, - true /* handles_frame_sink_id_invalidation */, - true /* needs_sync_points */)); - supports_.push_back(base::MakeUnique<CompositorFrameSinkSupport>( - this, &surface_manager_, kChildFrameSink2, false /* is_root */, - true /* handles_frame_sink_id_invalidation */, - true /* needs_sync_points */)); + surface_manager_.SetDependencyTracker( + base::MakeUnique<SurfaceDependencyTracker>(&surface_manager_, + begin_frame_source_.get())); + supports_.push_back(CompositorFrameSinkSupport::Create( + &support_client_, &surface_manager_, kDisplayFrameSink, is_root, + handles_frame_sink_id_invalidation, needs_sync_points)); + supports_.push_back(CompositorFrameSinkSupport::Create( + &support_client_, &surface_manager_, kParentFrameSink, is_child_root, + handles_frame_sink_id_invalidation, needs_sync_points)); + supports_.push_back(CompositorFrameSinkSupport::Create( + &support_client_, &surface_manager_, kChildFrameSink1, is_child_root, + handles_frame_sink_id_invalidation, needs_sync_points)); + supports_.push_back(CompositorFrameSinkSupport::Create( + &support_client_, &surface_manager_, kChildFrameSink2, is_child_root, + handles_frame_sink_id_invalidation, needs_sync_points)); // Normally, the BeginFrameSource would be registered by the Display. We // register it here so that BeginFrames are received by the display support, @@ -173,20 +226,13 @@ class CompositorFrameSinkSupportTest : public testing::Test, supports_.clear(); } - // CompositorFrameSinkSupportClient implementation. - void DidReceiveCompositorFrameAck() override {} - void OnBeginFrame(const BeginFrameArgs& args) override {} - void ReclaimResources(const ReturnedResourceArray& resources) override { - last_returned_resources_ = resources; - } - void WillDrawSurface(const LocalSurfaceId& local_surface_id, - const gfx::Rect& damage_rect) override {} + protected: + testing::NiceMock<MockCompositorFrameSinkSupportClient> support_client_; private: SurfaceManager surface_manager_; std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source_; std::vector<std::unique_ptr<CompositorFrameSinkSupport>> supports_; - ReturnedResourceArray last_returned_resources_; DISALLOW_COPY_AND_ASSIGN(CompositorFrameSinkSupportTest); }; @@ -198,9 +244,8 @@ TEST_F(CompositorFrameSinkSupportTest, RootSurfaceReceivesReferences) { const SurfaceId display_id_second = MakeSurfaceId(kDisplayFrameSink, 2); // Submit a CompositorFrame for the first display root surface. - display_support().SubmitCompositorFrame( - display_id_first.local_surface_id(), - MakeCompositorFrame({MakeSurfaceId(kParentFrameSink, 1)})); + display_support().SubmitCompositorFrame(display_id_first.local_surface_id(), + MakeCompositorFrame()); // A surface reference from the top-level root is added and there shouldn't be // a temporary reference. @@ -209,9 +254,8 @@ TEST_F(CompositorFrameSinkSupportTest, RootSurfaceReceivesReferences) { UnorderedElementsAre(display_id_first)); // Submit a CompositorFrame for the second display root surface. - display_support().SubmitCompositorFrame( - display_id_second.local_surface_id(), - MakeCompositorFrame({MakeSurfaceId(kParentFrameSink, 2)})); + display_support().SubmitCompositorFrame(display_id_second.local_surface_id(), + MakeCompositorFrame()); // A surface reference from the top-level root to |display_id_second| should // be added and the reference to |display_root_first| removed. @@ -237,7 +281,7 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedOnTwo) { EXPECT_TRUE(dependency_tracker().has_deadline()); EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1, child_id2)); // Submit a CompositorFrame without any dependencies to |child_id1|. @@ -248,7 +292,7 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedOnTwo) { EXPECT_TRUE(dependency_tracker().has_deadline()); EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id2)); // Submit a CompositorFrame without any dependencies to |child_id2|. @@ -259,7 +303,7 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedOnTwo) { EXPECT_FALSE(dependency_tracker().has_deadline()); EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); } // The parent Surface is blocked on |child_id2| which is blocked on |child_id3|. @@ -275,7 +319,7 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedChain) { EXPECT_TRUE(dependency_tracker().has_deadline()); EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1)); child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), @@ -285,11 +329,11 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedChain) { EXPECT_TRUE(dependency_tracker().has_deadline()); EXPECT_FALSE(child_surface1()->HasActiveFrame()); EXPECT_TRUE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), + EXPECT_THAT(child_surface1()->blocking_surfaces(), UnorderedElementsAre(child_id2)); // The parent should still be blocked on |child_id1| because it's pending. - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1)); // Submit a CompositorFrame without any dependencies to |child_id2|. @@ -302,12 +346,12 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedChain) { // child_surface1 should now be active. EXPECT_TRUE(child_surface1()->HasActiveFrame()); EXPECT_FALSE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); // parent_surface should now be active. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); } // parent_surface and child_surface1 are blocked on |child_id2|. @@ -324,7 +368,7 @@ TEST_F(CompositorFrameSinkSupportTest, EXPECT_TRUE(dependency_tracker().has_deadline()); EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id2)); // child_support1 should now be blocked on |child_id2|. @@ -334,11 +378,11 @@ TEST_F(CompositorFrameSinkSupportTest, EXPECT_TRUE(dependency_tracker().has_deadline()); EXPECT_FALSE(child_surface1()->HasActiveFrame()); EXPECT_TRUE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), + EXPECT_THAT(child_surface1()->blocking_surfaces(), UnorderedElementsAre(child_id2)); // The parent should still be blocked on |child_id2|. - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id2)); // Submit a CompositorFrame without any dependencies to |child_id2|. @@ -351,12 +395,12 @@ TEST_F(CompositorFrameSinkSupportTest, // child_surface1 should now be active. EXPECT_TRUE(child_surface1()->HasActiveFrame()); EXPECT_FALSE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); // parent_surface should now be active. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); } // parent_surface is blocked on |child_id1|, and child_surface2 is blocked on @@ -373,7 +417,7 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingDeadlineHits) { EXPECT_TRUE(dependency_tracker().has_deadline()); EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1)); child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), @@ -383,11 +427,11 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingDeadlineHits) { EXPECT_TRUE(dependency_tracker().has_deadline()); EXPECT_FALSE(child_surface1()->HasActiveFrame()); EXPECT_TRUE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), + EXPECT_THAT(child_surface1()->blocking_surfaces(), UnorderedElementsAre(child_id2)); // The parent should still be blocked on |child_id1| because it's pending. - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1)); BeginFrameArgs args = @@ -401,13 +445,13 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingDeadlineHits) { // parent_support is still blocked on |child_id1|. EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1)); // child_support1 is still blocked on |child_id2|. EXPECT_FALSE(child_surface1()->HasActiveFrame()); EXPECT_TRUE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), + EXPECT_THAT(child_surface1()->blocking_surfaces(), UnorderedElementsAre(child_id2)); } @@ -419,12 +463,12 @@ TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingDeadlineHits) { // parent_surface has been activated. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); // child_surface1 has been activated. EXPECT_TRUE(child_surface1()->HasActiveFrame()); EXPECT_FALSE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); } // Verifies that the deadline does not reset if we submit CompositorFrames @@ -444,7 +488,7 @@ TEST_F(CompositorFrameSinkSupportTest, // support(i) should be blocked on arbitrary_id. EXPECT_FALSE(surface(i)->HasActiveFrame()); EXPECT_TRUE(surface(i)->HasPendingFrame()); - EXPECT_THAT(surface(i)->blocking_surfaces_for_testing(), + EXPECT_THAT(surface(i)->blocking_surfaces(), UnorderedElementsAre(arbitrary_id)); // Issue a BeginFrame to get closer to the deadline. @@ -456,7 +500,7 @@ TEST_F(CompositorFrameSinkSupportTest, for (int i = 0; i < 3; ++i) { EXPECT_TRUE(surface(i)->HasActiveFrame()); EXPECT_FALSE(surface(i)->HasPendingFrame()); - EXPECT_THAT(surface(i)->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(surface(i)->blocking_surfaces(), IsEmpty()); } } @@ -474,7 +518,7 @@ TEST_F(CompositorFrameSinkSupportTest, // Verify that the CompositorFrame is blocked on |arbitrary_id|. EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(arbitrary_id)); // Submit a CompositorFrame that has no dependencies. @@ -484,55 +528,63 @@ TEST_F(CompositorFrameSinkSupportTest, // Verify that the CompositorFrame has been activated. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); } -// This test verifies that the set of references from a Surface includes both -// the pending and active CompositorFrames. +// This test verifies that a pending CompositorFrame does not affect surface +// references. A new surface from a child will continue to exist as a temporary +// reference until the parent's frame activates. TEST_F(CompositorFrameSinkSupportTest, - DisplayCompositorLockingReferencesFromPendingAndActiveFrames) { + OnlyActiveFramesAffectSurfaceReferences) { const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); - const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1); - const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1); - const SurfaceReference parent_child_reference(parent_id, child_id); - const SurfaceReference parent_arbitrary_reference(parent_id, arbitrary_id); + const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); + const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1); // child_support1 submits a CompositorFrame without any dependencies. - child_support1().SubmitCompositorFrame( - child_id.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); + child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), + MakeCompositorFrame()); // Verify that the child surface is not blocked. EXPECT_TRUE(child_surface1()->HasActiveFrame()); EXPECT_FALSE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); + + // Verify that there's a temporary reference for |child_id1|. + EXPECT_TRUE(HasTemporaryReference(child_id1)); // parent_support submits a CompositorFrame that depends on |child_id1| - // which is already active. Thus, this CompositorFrame should activate - // immediately. - parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), - MakeCompositorFrame({child_id})); + // (which is already active) and |child_id2|. Thus, the parent should not + // activate immediately. + parent_support().SubmitCompositorFrame( + parent_id.local_surface_id(), + MakeCompositorFrame({child_id1, child_id2})); + EXPECT_FALSE(parent_surface()->HasActiveFrame()); + EXPECT_TRUE(parent_surface()->HasPendingFrame()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), + UnorderedElementsAre(child_id2)); + EXPECT_THAT(GetChildReferences(parent_id), IsEmpty()); + + // Verify that there's a temporary reference for |child_id1| that still + // exists. + EXPECT_TRUE(HasTemporaryReference(child_id1)); + + // child_support2 submits a CompositorFrame without any dependencies. + child_support2().SubmitCompositorFrame(child_id2.local_surface_id(), + MakeCompositorFrame()); + + // Verify that the child surface is not blocked. + EXPECT_TRUE(child_surface1()->HasActiveFrame()); + EXPECT_FALSE(child_surface1()->HasPendingFrame()); + EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); + + // Verify that the parent surface's CompositorFrame has activated and that the + // temporary reference has been replaced by a permanent one. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); - // Verify that the parent will add a reference to the |child_id|. - EXPECT_THAT(parent_reference_tracker().references_to_add(), - UnorderedElementsAre(parent_child_reference)); - EXPECT_THAT(parent_reference_tracker().references_to_remove(), IsEmpty()); - - // parent_support now submits another CompositorFrame to the same surface - // but depends on arbitrary_id. The parent surface should now have both - // a pending and active CompositorFrame. - parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), - MakeCompositorFrame({arbitrary_id})); - EXPECT_TRUE(parent_surface()->HasActiveFrame()); - EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), - UnorderedElementsAre(arbitrary_id)); - // Verify that the parent will add a reference to |arbitrary_id| and will not - // remove a reference to |child_id|. - EXPECT_THAT(parent_reference_tracker().references_to_add(), - UnorderedElementsAre(parent_arbitrary_reference)); - EXPECT_THAT(parent_reference_tracker().references_to_remove(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); + EXPECT_FALSE(HasTemporaryReference(child_id1)); + EXPECT_THAT(GetChildReferences(parent_id), + UnorderedElementsAre(child_id1, child_id2)); } // This test verifies that we do not double count returned resources when a @@ -557,7 +609,7 @@ TEST_F(CompositorFrameSinkSupportTest, // Verify that the CompositorFrame is blocked on |child_id|. EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id)); child_support1().SubmitCompositorFrame( @@ -566,12 +618,12 @@ TEST_F(CompositorFrameSinkSupportTest, // Verify that the child CompositorFrame activates immediately. EXPECT_TRUE(child_surface1()->HasActiveFrame()); EXPECT_FALSE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); // Verify that the parent has activated. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); // The parent submits a CompositorFrame without any dependencies. That frame // should activate immediately, replacing the earlier frame. The resource from @@ -580,49 +632,12 @@ TEST_F(CompositorFrameSinkSupportTest, parent_id.local_surface_id(), MakeCompositorFrame({empty_surface_ids()})); EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); ReturnedResource returned_resource = resource.ToReturnedResource(); - EXPECT_THAT(last_returned_resources(), + EXPECT_THAT(support_client_.last_returned_resources(), UnorderedElementsAre(returned_resource)); } -// This test verifies that a SurfaceReference from parent to child can be added -// prior to the child submitting a CompositorFrame. This test also verifies that -// when the child later submits a CompositorFrame, -TEST_F(CompositorFrameSinkSupportTest, - DisplayCompositorLockingReferenceAddedBeforeChildExists) { - const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); - const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1); - - // The parent submits a CompositorFrame that depends on |child_id| before the - // child submits a CompositorFrame. - parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), - MakeCompositorFrame({child_id})); - - // Verify that the CompositorFrame is blocked on |child_id|. - EXPECT_FALSE(parent_surface()->HasActiveFrame()); - EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), - UnorderedElementsAre(child_id)); - - // Verify that a SurfaceReference(parent_id, child_id) exists in the - // SurfaceManager. - EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id)); - - child_support1().SubmitCompositorFrame( - child_id.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); - - // Verify that the child CompositorFrame activates immediately. - EXPECT_TRUE(child_surface1()->HasActiveFrame()); - EXPECT_FALSE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), IsEmpty()); - - // Verify that there is no temporary reference for the child and that - // the reference from the parent to the child still exists. - EXPECT_FALSE(HasTemporaryReference(child_id)); - EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id)); -} - // The parent Surface is blocked on |child_id2| which is blocked on |child_id3|. // child_support1 evicts its blocked Surface. The parent surface should // activate. @@ -638,7 +653,7 @@ TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceWithPendingFrame) { // Verify that the CompositorFrame is blocked on |child_id1|. EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1)); // Submit a CompositorFrame that depends on |child_id2|. @@ -648,7 +663,7 @@ TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceWithPendingFrame) { // Verify that the CompositorFrame is blocked on |child_id2|. EXPECT_FALSE(child_surface1()->HasActiveFrame()); EXPECT_TRUE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), + EXPECT_THAT(child_surface1()->blocking_surfaces(), UnorderedElementsAre(child_id2)); // Evict child_support1's current Surface. @@ -658,7 +673,7 @@ TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceWithPendingFrame) { // The parent Surface should immediately activate. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); EXPECT_FALSE(dependency_tracker().has_deadline()); } @@ -680,12 +695,11 @@ TEST_F(CompositorFrameSinkSupportTest, DropStaleReferencesAfterActivation) { // Verify that the CompositorFrame is blocked on |child_id|. EXPECT_FALSE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1)); - // Verify that a SurfaceReference(parent_id, child_id1) exists in the - // SurfaceManager. - EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1)); + // Verify that no references are added while the CompositorFrame is pending. + EXPECT_THAT(GetChildReferences(parent_id), IsEmpty()); child_support1().SubmitCompositorFrame( child_id1.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); @@ -693,12 +707,12 @@ TEST_F(CompositorFrameSinkSupportTest, DropStaleReferencesAfterActivation) { // Verify that the child CompositorFrame activates immediately. EXPECT_TRUE(child_surface1()->HasActiveFrame()); EXPECT_FALSE(child_surface1()->HasPendingFrame()); - EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); // Verify that the parent Surface has activated. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); // Verify that there is no temporary reference for the child and that // the reference from the parent to the child still exists. @@ -711,13 +725,12 @@ TEST_F(CompositorFrameSinkSupportTest, DropStaleReferencesAfterActivation) { // The parent surface should now have both a pending and activate // CompositorFrame. Verify that the set of child references from - // |parent_id| include both the pending and active CompositorFrames. + // |parent_id| are only from the active CompositorFrame. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), + EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id2)); - EXPECT_THAT(GetChildReferences(parent_id), - UnorderedElementsAre(child_id1, child_id2)); + EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1)); child_support2().SubmitCompositorFrame( child_id2.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); @@ -727,7 +740,7 @@ TEST_F(CompositorFrameSinkSupportTest, DropStaleReferencesAfterActivation) { // reference of |parent_id|. EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty()); + EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id2)); } @@ -738,7 +751,7 @@ TEST_F(CompositorFrameSinkSupportTest, const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1); const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2); const ui::LatencyComponentType latency_type1 = - ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT; + ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT; const int64_t latency_id1 = 234; const int64_t latency_sequence_number1 = 5645432; const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT; @@ -749,7 +762,7 @@ TEST_F(CompositorFrameSinkSupportTest, ui::LatencyInfo info; info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1); - CompositorFrame frame; + CompositorFrame frame = MakeCompositorFrame(); frame.metadata.latency_info.push_back(info); parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), @@ -766,7 +779,7 @@ TEST_F(CompositorFrameSinkSupportTest, ui::LatencyInfo info2; info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2); - CompositorFrame frame2; + CompositorFrame frame2 = MakeCompositorFrame(); frame2.metadata.latency_info.push_back(info2); parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(), @@ -802,7 +815,7 @@ TEST_F(CompositorFrameSinkSupportTest, const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1); const ui::LatencyComponentType latency_type1 = - ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT; + ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT; const int64_t latency_id1 = 234; const int64_t latency_sequence_number1 = 5645432; const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT; @@ -813,7 +826,7 @@ TEST_F(CompositorFrameSinkSupportTest, ui::LatencyInfo info; info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1); - CompositorFrame frame; + CompositorFrame frame = MakeCompositorFrame(); frame.metadata.latency_info.push_back(info); parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), @@ -837,7 +850,7 @@ TEST_F(CompositorFrameSinkSupportTest, // Submit a frame with a new local surface id. parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(), - CompositorFrame()); + MakeCompositorFrame()); // Verify that the new surface has an active frame only. Surface* surface = surface_manager().GetSurfaceForId(parent_id2); @@ -870,7 +883,7 @@ TEST_F(CompositorFrameSinkSupportTest, const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1); const ui::LatencyComponentType latency_type1 = - ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT; + ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT; const int64_t latency_id1 = 234; const int64_t latency_sequence_number1 = 5645432; const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT; @@ -881,7 +894,7 @@ TEST_F(CompositorFrameSinkSupportTest, ui::LatencyInfo info; info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1); - CompositorFrame frame; + CompositorFrame frame = MakeCompositorFrame(); frame.metadata.latency_info.push_back(info); parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), @@ -912,7 +925,7 @@ TEST_F(CompositorFrameSinkSupportTest, // Resolve the dependencies. The frame in parent's surface must become active. child_support1().SubmitCompositorFrame(child_id.local_surface_id(), - CompositorFrame()); + MakeCompositorFrame()); EXPECT_FALSE(surface->HasPendingFrame()); EXPECT_TRUE(surface->HasActiveFrame()); @@ -933,6 +946,8 @@ TEST_F(CompositorFrameSinkSupportTest, } TEST_F(CompositorFrameSinkSupportTest, PassesOnBeginFrameAcks) { + const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1); + // Request BeginFrames. display_support().SetNeedsBeginFrame(true); @@ -941,10 +956,299 @@ TEST_F(CompositorFrameSinkSupportTest, PassesOnBeginFrameAcks) { CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); begin_frame_source()->TestOnBeginFrame(args); - // Check that the support forwards our ack to the BeginFrameSource. - BeginFrameAck ack(0, 1, 1, 0, false); - display_support().DidFinishFrame(ack); + // Check that the support forwards a BeginFrameDidNotSwap ack to the + // BeginFrameSource. + BeginFrameAck ack(0, 1, 1, false); + display_support().BeginFrameDidNotSwap(ack); EXPECT_EQ(ack, begin_frame_source()->LastAckForObserver(&display_support())); + + // Issue another BeginFrame. + args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2); + begin_frame_source()->TestOnBeginFrame(args); + + // Check that the support forwards the BeginFrameAck attached + // to a CompositorFrame to the BeginFrameSource. + BeginFrameAck ack2(0, 2, 2, true); + CompositorFrame frame = MakeCompositorFrame(); + frame.metadata.begin_frame_ack = ack2; + display_support().SubmitCompositorFrame(display_id.local_surface_id(), + std::move(frame)); + EXPECT_EQ(ack2, begin_frame_source()->LastAckForObserver(&display_support())); +} + +// Checks that resources and ack are sent together if possible. +TEST_F(CompositorFrameSinkSupportTest, ReturnResourcesWithAck) { + const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); + TransferableResource resource; + resource.id = 1234; + parent_support().SubmitCompositorFrame( + parent_id.local_surface_id(), + MakeCompositorFrameWithResources(empty_surface_ids(), {resource})); + ReturnedResourceArray returned_resources; + TransferableResource::ReturnResources({resource}, &returned_resources); + EXPECT_CALL(support_client_, ReclaimResources(_)).Times(0); + EXPECT_CALL(support_client_, + DidReceiveCompositorFrameAck(Eq(returned_resources))); + parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), + MakeCompositorFrame()); +} + +// Verifies that if a surface is marked destroyed and a new frame arrives for +// it, it will be recovered. +TEST_F(CompositorFrameSinkSupportTest, SurfaceResurrection) { + const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); + const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3); + + // Add a reference from the parent to the child. + parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), + MakeCompositorFrame({child_id})); + + // Create the child surface by submitting a frame to it. + EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id)); + child_support1().SubmitCompositorFrame(child_id.local_surface_id(), + MakeCompositorFrame()); + + // Verify that the child surface is created. + Surface* surface = surface_manager().GetSurfaceForId(child_id); + EXPECT_NE(nullptr, surface); + + // Attempt to destroy the child surface. The surface must still exist since + // the parent needs it but it will be marked as destroyed. + child_support1().EvictFrame(); + surface = surface_manager().GetSurfaceForId(child_id); + EXPECT_NE(nullptr, surface); + EXPECT_TRUE(surface->destroyed()); + + // Child submits another frame to the same local surface id that is marked + // destroyed. + child_support1().SubmitCompositorFrame(child_id.local_surface_id(), + MakeCompositorFrame()); + + // Verify that the surface that was marked destroyed is recovered and is being + // used again. + Surface* surface2 = surface_manager().GetSurfaceForId(child_id); + EXPECT_EQ(surface, surface2); + EXPECT_FALSE(surface2->destroyed()); +} + +// Verifies that if a LocalSurfaceId belonged to a surface that doesn't exist +// anymore, it can still be reused for new surfaces. +TEST_F(CompositorFrameSinkSupportTest, LocalSurfaceIdIsReusable) { + const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); + const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3); + + // Add a reference from parent. + parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), + MakeCompositorFrame({child_id})); + + // Submit the first frame. Creates the surface. + child_support1().SubmitCompositorFrame(child_id.local_surface_id(), + MakeCompositorFrame()); + EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id)); + + // Remove the reference from parant. This allows us to destroy the surface. + parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), + MakeCompositorFrame()); + + // Destroy the surface. + child_support1().EvictFrame(); + EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id)); + + // Submit another frame with the same local surface id. This should work fine + // and a new surface must be created. + child_support1().SubmitCompositorFrame(child_id.local_surface_id(), + MakeCompositorFrame()); + EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id)); +} + +// This test verifies that a crash does not occur if garbage collection is +// triggered during surface dependency resolution. This test triggers garbage +// collection during surface resolution, by causing an activation to remove +// a surface subtree from the root. Both the old subtree and the new +// activated subtree refer to the same dependency. The old subtree was activated +// by deadline, and the new subtree was activated by a dependency finally +// resolving. +TEST_F(CompositorFrameSinkSupportTest, DependencyTrackingGarbageCollection) { + const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1); + const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1); + const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2); + const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1); + + parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), + MakeCompositorFrame({child_id})); + display_support().SubmitCompositorFrame(display_id.local_surface_id(), + MakeCompositorFrame({parent_id1})); + + EXPECT_TRUE(dependency_tracker().has_deadline()); + + BeginFrameArgs args = + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); + + // Advance BeginFrames to trigger a deadline. + for (int i = 0; i < 3; ++i) { + begin_frame_source()->TestOnBeginFrame(args); + EXPECT_TRUE(dependency_tracker().has_deadline()); + } + begin_frame_source()->TestOnBeginFrame(args); + EXPECT_FALSE(dependency_tracker().has_deadline()); + + EXPECT_TRUE(display_surface()->HasActiveFrame()); + EXPECT_FALSE(display_surface()->HasPendingFrame()); + EXPECT_TRUE(parent_surface()->HasActiveFrame()); + EXPECT_FALSE(parent_surface()->HasPendingFrame()); + + parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(), + MakeCompositorFrame({child_id})); + display_support().SubmitCompositorFrame(display_id.local_surface_id(), + MakeCompositorFrame({parent_id2})); + + // The display surface now has two CompositorFrames. One that is pending, + // indirectly blocked on child_id and one that is active, also indirectly + // referring to child_id, but activated due to the deadline above. + EXPECT_TRUE(display_surface()->HasActiveFrame()); + EXPECT_TRUE(display_surface()->HasPendingFrame()); + + // Submitting a CompositorFrame will trigger garbage collection of the + // |parent_id1| subtree. This should not crash. + child_support1().SubmitCompositorFrame( + child_id.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); +} + +// This test verifies that a crash does not occur if garbage collection is +// triggered when a deadline forces frame activation. This test triggers garbage +// collection during deadline activation by causing the activation of a display +// frame to replace a previously activated display frame that was referring to +// a now-unreachable surface subtree. That subtree gets garbage collected during +// deadline activation. SurfaceDependencyTracker is also tracking a surface +// from that subtree due to an unresolved dependency. This test verifies that +// this dependency resolution does not crash. +TEST_F(CompositorFrameSinkSupportTest, GarbageCollectionOnDeadline) { + const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1); + const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1); + const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2); + const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1); + + display_support().SubmitCompositorFrame(display_id.local_surface_id(), + MakeCompositorFrame({parent_id1})); + + EXPECT_TRUE(display_surface()->HasPendingFrame()); + EXPECT_TRUE(dependency_tracker().has_deadline()); + EXPECT_FALSE(display_surface()->HasActiveFrame()); + + // Advance BeginFrames to trigger a deadline. This activates the + // CompositorFrame submitted above. + BeginFrameArgs args = + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); + for (int i = 0; i < 3; ++i) { + begin_frame_source()->TestOnBeginFrame(args); + EXPECT_TRUE(dependency_tracker().has_deadline()); + } + begin_frame_source()->TestOnBeginFrame(args); + EXPECT_FALSE(dependency_tracker().has_deadline()); + EXPECT_FALSE(display_surface()->HasPendingFrame()); + EXPECT_TRUE(display_surface()->HasActiveFrame()); + + // |parent_id1| is blocked on |child_id|, but |display_id|'s CompositorFrame + // has activated due to a deadline. |parent_id1| will be tracked by the + // SurfaceDependencyTracker. + parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), + MakeCompositorFrame({child_id})); + + // By submitting a display CompositorFrame, and replacing the parent's + // CompositorFrame with another surface ID, parent_id1 becomes unreachable and + // a candidate for garbage collection. + display_support().SubmitCompositorFrame(display_id.local_surface_id(), + MakeCompositorFrame({parent_id2})); + + // Now |parent_id1| is only kept alive by the active |display_id| frame. + parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(), + MakeCompositorFrame({child_id})); + + // SurfaceDependencyTracker should now be tracking |display_id|, |parent_id1| + // and |parent_id2|. By activating the pending |display_id| frame by deadline, + // |parent_id1| becomes unreachable and is garbage collected while + // SurfaceDependencyTracker is in the process of activating surfaces. This + // should not cause a crash or use-after-free. + for (int i = 0; i < 3; ++i) { + begin_frame_source()->TestOnBeginFrame(args); + EXPECT_TRUE(dependency_tracker().has_deadline()); + } + begin_frame_source()->TestOnBeginFrame(args); + EXPECT_FALSE(dependency_tracker().has_deadline()); +} + +// This test verifies that a CompositorFrame will only blocked on embedded +// surfaces but not on other retained surface IDs in the CompositorFrame. +TEST_F(CompositorFrameSinkSupportTest, OnlyBlockOnEmbeddedSurfaces) { + const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1); + const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1); + const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2); + + display_support().SubmitCompositorFrame( + display_id.local_surface_id(), + MakeCompositorFrame({parent_id1}, {parent_id1, parent_id2})); + + EXPECT_TRUE(display_surface()->HasPendingFrame()); + EXPECT_FALSE(display_surface()->HasActiveFrame()); + EXPECT_TRUE(dependency_tracker().has_deadline()); + + // Verify that the display CompositorFrame will only block on |parent_id1| but + // not |parent_id2|. + EXPECT_THAT(display_surface()->blocking_surfaces(), + UnorderedElementsAre(parent_id1)); + // Verify that the display surface holds no references while its + // CompositorFrame is pending. + EXPECT_THAT(GetChildReferences(display_id), IsEmpty()); + + // Submitting a CompositorFrame with |parent_id1| should unblock the display + // CompositorFrame. + parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), + MakeCompositorFrame()); + + EXPECT_FALSE(dependency_tracker().has_deadline()); + EXPECT_FALSE(display_surface()->HasPendingFrame()); + EXPECT_TRUE(display_surface()->HasActiveFrame()); + EXPECT_THAT(display_surface()->blocking_surfaces(), IsEmpty()); + + // Only a reference to |parent_id1| is added because |parent_id2| does not + // exist. + EXPECT_THAT(GetChildReferences(display_id), UnorderedElementsAre(parent_id1)); +} + +// This test verifies that a late arriving CompositorFrame activates immediately +// and does not trigger a new deadline. +TEST_F(CompositorFrameSinkSupportTest, LateArrivingDependency) { + const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1); + const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1); + const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); + + display_support().SubmitCompositorFrame(display_id.local_surface_id(), + MakeCompositorFrame({parent_id1})); + + EXPECT_TRUE(display_surface()->HasPendingFrame()); + EXPECT_FALSE(display_surface()->HasActiveFrame()); + EXPECT_TRUE(dependency_tracker().has_deadline()); + + // Advance BeginFrames to trigger a deadline. This activates the + // CompositorFrame submitted above. + BeginFrameArgs args = + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); + for (int i = 0; i < 3; ++i) { + begin_frame_source()->TestOnBeginFrame(args); + EXPECT_TRUE(dependency_tracker().has_deadline()); + } + begin_frame_source()->TestOnBeginFrame(args); + EXPECT_FALSE(dependency_tracker().has_deadline()); + EXPECT_FALSE(display_surface()->HasPendingFrame()); + EXPECT_TRUE(display_surface()->HasActiveFrame()); + + // A late arriving CompositorFrame should activate immediately without + // scheduling a deadline and without waiting for dependencies to resolve. + parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), + MakeCompositorFrame({child_id1})); + EXPECT_FALSE(dependency_tracker().has_deadline()); + EXPECT_FALSE(parent_surface()->HasPendingFrame()); + EXPECT_TRUE(parent_surface()->HasActiveFrame()); } } // namespace test diff --git a/chromium/cc/surfaces/direct_compositor_frame_sink.cc b/chromium/cc/surfaces/direct_compositor_frame_sink.cc index a915b941c1e..13b6c6299b0 100644 --- a/chromium/cc/surfaces/direct_compositor_frame_sink.cc +++ b/chromium/cc/surfaces/direct_compositor_frame_sink.cc @@ -69,7 +69,7 @@ bool DirectCompositorFrameSink::BindToClient( constexpr bool is_root = true; constexpr bool handles_frame_sink_id_invalidation = false; - support_ = base::MakeUnique<CompositorFrameSinkSupport>( + support_ = CompositorFrameSinkSupport::Create( this, surface_manager_, frame_sink_id_, is_root, handles_frame_sink_id_invalidation, capabilities_.delegated_sync_points_required); @@ -94,6 +94,10 @@ void DirectCompositorFrameSink::DetachFromClient() { } void DirectCompositorFrameSink::SubmitCompositorFrame(CompositorFrame frame) { + DCHECK(frame.metadata.begin_frame_ack.has_damage); + DCHECK_LE(BeginFrameArgs::kStartingFrameNumber, + frame.metadata.begin_frame_ack.sequence_number); + gfx::Size frame_size = frame.render_pass_list.back()->output_rect.size(); if (frame_size.IsEmpty() || frame_size != last_swap_frame_size_) { delegated_local_surface_id_ = local_surface_id_allocator_.GenerateId(); @@ -127,7 +131,9 @@ void DirectCompositorFrameSink::DisplayDidDrawAndSwap() { // be drawn. } -void DirectCompositorFrameSink::DidReceiveCompositorFrameAck() { +void DirectCompositorFrameSink::DidReceiveCompositorFrameAck( + const ReturnedResourceArray& resources) { + client_->ReclaimResources(resources); client_->DidReceiveCompositorFrameAck(); } @@ -151,7 +157,9 @@ void DirectCompositorFrameSink::OnNeedsBeginFrames(bool needs_begin_frame) { } void DirectCompositorFrameSink::OnDidFinishFrame(const BeginFrameAck& ack) { - support_->DidFinishFrame(ack); + // If there was damage, SubmitCompositorFrame includes the ack. + if (!ack.has_damage) + support_->BeginFrameDidNotSwap(ack); } } // namespace cc diff --git a/chromium/cc/surfaces/direct_compositor_frame_sink.h b/chromium/cc/surfaces/direct_compositor_frame_sink.h index 5f9f4bdefed..5aa021b448d 100644 --- a/chromium/cc/surfaces/direct_compositor_frame_sink.h +++ b/chromium/cc/surfaces/direct_compositor_frame_sink.h @@ -64,7 +64,8 @@ class CC_SURFACES_EXPORT DirectCompositorFrameSink private: // CompositorFrameSinkSupportClient implementation: - void DidReceiveCompositorFrameAck() override; + void DidReceiveCompositorFrameAck( + const ReturnedResourceArray& resources) override; void OnBeginFrame(const BeginFrameArgs& args) override; void ReclaimResources(const ReturnedResourceArray& resources) override; void WillDrawSurface(const LocalSurfaceId& local_surface_id, diff --git a/chromium/cc/surfaces/direct_compositor_frame_sink_unittest.cc b/chromium/cc/surfaces/direct_compositor_frame_sink_unittest.cc index 3bc52f1621a..5f1b8b885a0 100644 --- a/chromium/cc/surfaces/direct_compositor_frame_sink_unittest.cc +++ b/chromium/cc/surfaces/direct_compositor_frame_sink_unittest.cc @@ -109,6 +109,7 @@ class DirectCompositorFrameSinkTest : public testing::Test { render_pass->SetNew(1, display_rect_, damage_rect, gfx::Transform()); CompositorFrame frame; + frame.metadata.begin_frame_ack = BeginFrameAck(0, 1, 1, true); frame.render_pass_list.push_back(std::move(render_pass)); compositor_frame_sink_->SubmitCompositorFrame(std::move(frame)); @@ -185,30 +186,35 @@ TEST_F(DirectCompositorFrameSinkTest, class TestBeginFrameObserver : public BeginFrameObserverBase { public: - explicit TestBeginFrameObserver(BeginFrameSource* source) : source_(source) {} - - void FinishFrame() { source_->DidFinishFrame(this, ack()); } - const BeginFrameAck& ack() const { return ack_; } private: bool OnBeginFrameDerivedImpl(const BeginFrameArgs& args) override { ack_ = BeginFrameAck(args.source_id, args.sequence_number, - args.sequence_number, 0, true); + args.sequence_number, false); return true; } void OnBeginFrameSourcePausedChanged(bool paused) override{}; - BeginFrameSource* source_; BeginFrameAck ack_; }; -TEST_F(DirectCompositorFrameSinkTest, AcknowledgesBeginFrames) { +TEST_F(DirectCompositorFrameSinkTest, AcknowledgesBeginFramesWithDamage) { + // Verify that the frame sink acknowledged the BeginFrame attached to + // CompositorFrame submitted during SetUp(). + EXPECT_EQ(BeginFrameAck(0, 1, 1, true), begin_frame_source_->last_ack()); +} + +TEST_F(DirectCompositorFrameSinkTest, AcknowledgesBeginFramesWithoutDamage) { // Request a BeginFrame from the CompositorFrameSinkClient. - TestBeginFrameObserver observer(begin_frame_source_.get()); + TestBeginFrameObserver observer; compositor_frame_sink_client_.begin_frame_source()->AddObserver(&observer); - observer.FinishFrame(); + task_runner_->RunUntilIdle(); + EXPECT_LE(BeginFrameArgs::kStartingFrameNumber, + observer.ack().sequence_number); + compositor_frame_sink_client_.begin_frame_source()->DidFinishFrame( + &observer, observer.ack()); compositor_frame_sink_client_.begin_frame_source()->RemoveObserver(&observer); // Verify that the frame sink acknowledged the last BeginFrame. diff --git a/chromium/cc/surfaces/display.cc b/chromium/cc/surfaces/display.cc index f56de857d78..2b982d4694b 100644 --- a/chromium/cc/surfaces/display.cc +++ b/chromium/cc/surfaces/display.cc @@ -10,7 +10,7 @@ #include "base/metrics/histogram_macros.h" #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" -#include "cc/debug/benchmark_instrumentation.h" +#include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/output/compositor_frame.h" #include "cc/output/direct_renderer.h" #include "cc/output/gl_renderer.h" @@ -24,9 +24,10 @@ #include "cc/surfaces/surface_aggregator.h" #include "cc/surfaces/surface_manager.h" #include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/vulkan/features.h" #include "ui/gfx/buffer_types.h" -#if defined(ENABLE_VULKAN) +#if BUILDFLAG(ENABLE_VULKAN) #include "cc/output/vulkan_renderer.h" #endif @@ -159,10 +160,13 @@ void Display::Resize(const gfx::Size& size) { scheduler_->DisplayResized(); } -void Display::SetColorSpace(const gfx::ColorSpace& color_space) { - device_color_space_ = color_space; - if (aggregator_) - aggregator_->SetOutputColorSpace(device_color_space_); +void Display::SetColorSpace(const gfx::ColorSpace& blending_color_space, + const gfx::ColorSpace& device_color_space) { + blending_color_space_ = blending_color_space; + device_color_space_ = device_color_space; + if (aggregator_) { + aggregator_->SetOutputColorSpace(blending_color_space, device_color_space_); + } } void Display::SetOutputIsSecure(bool secure) { @@ -219,7 +223,7 @@ void Display::InitializeRenderer() { aggregator_.reset(new SurfaceAggregator( surface_manager_, resource_provider_.get(), output_partial_list)); aggregator_->set_output_is_secure(output_is_secure_); - aggregator_->SetOutputColorSpace(device_color_space_); + aggregator_->SetOutputColorSpace(blending_color_space_, device_color_space_); } void Display::UpdateRootSurfaceResourcesLocked() { diff --git a/chromium/cc/surfaces/display.h b/chromium/cc/surfaces/display.h index 35b504149b2..7718ffe32ea 100644 --- a/chromium/cc/surfaces/display.h +++ b/chromium/cc/surfaces/display.h @@ -19,8 +19,8 @@ #include "cc/surfaces/surface_manager.h" #include "cc/surfaces/surfaces_export.h" #include "gpu/command_buffer/common/texture_in_use_response.h" -#include "ui/events/latency_info.h" #include "ui/gfx/color_space.h" +#include "ui/latency/latency_info.h" namespace gpu { class GpuMemoryBufferManager; @@ -70,7 +70,8 @@ class CC_SURFACES_EXPORT Display : public DisplaySchedulerClient, void SetLocalSurfaceId(const LocalSurfaceId& id, float device_scale_factor); void SetVisible(bool visible); void Resize(const gfx::Size& new_size); - void SetColorSpace(const gfx::ColorSpace& color_space); + void SetColorSpace(const gfx::ColorSpace& blending_color_space, + const gfx::ColorSpace& device_color_space); void SetOutputIsSecure(bool secure); const SurfaceId& CurrentSurfaceId(); @@ -108,6 +109,7 @@ class CC_SURFACES_EXPORT Display : public DisplaySchedulerClient, SurfaceId current_surface_id_; gfx::Size current_surface_size_; float device_scale_factor_ = 1.f; + gfx::ColorSpace blending_color_space_; gfx::ColorSpace device_color_space_; bool visible_ = false; bool swapped_since_resize_ = false; diff --git a/chromium/cc/surfaces/display_scheduler.cc b/chromium/cc/surfaces/display_scheduler.cc index 1e91f5fd430..40e80bf97bd 100644 --- a/chromium/cc/surfaces/display_scheduler.cc +++ b/chromium/cc/surfaces/display_scheduler.cc @@ -26,6 +26,7 @@ DisplayScheduler::DisplayScheduler(base::SingleThreadTaskRunner* task_runner, needs_draw_(false), expecting_root_surface_damage_because_of_resize_(false), all_active_child_surfaces_ready_to_draw_(false), + next_swap_id_(1), pending_swaps_(0), max_pending_swaps_(max_pending_swaps), observing_begin_frame_source_(false), @@ -366,20 +367,20 @@ void DisplayScheduler::DidFinishFrame(bool did_draw) { // TODO(eseckler): Determine and set correct |ack.latest_confirmed_frame|. BeginFrameAck ack(current_begin_frame_args_.source_id, current_begin_frame_args_.sequence_number, - current_begin_frame_args_.sequence_number, 0, did_draw); + current_begin_frame_args_.sequence_number, did_draw); begin_frame_source_->DidFinishFrame(this, ack); } void DisplayScheduler::DidSwapBuffers() { pending_swaps_++; - TRACE_EVENT_ASYNC_BEGIN1("cc", "DisplayScheduler:pending_swaps", this, - "pending_frames", pending_swaps_); + uint32_t swap_id = next_swap_id_++; + TRACE_EVENT_ASYNC_BEGIN0("cc", "DisplayScheduler:pending_swaps", swap_id); } void DisplayScheduler::DidReceiveSwapBuffersAck() { + uint32_t swap_id = next_swap_id_ - pending_swaps_; pending_swaps_--; - TRACE_EVENT_ASYNC_END1("cc", "DisplayScheduler:pending_swaps", this, - "pending_frames", pending_swaps_); + TRACE_EVENT_ASYNC_END0("cc", "DisplayScheduler:pending_swaps", swap_id); ScheduleBeginFrameDeadline(); } diff --git a/chromium/cc/surfaces/display_scheduler.h b/chromium/cc/surfaces/display_scheduler.h index 83d13000393..76d21b8b260 100644 --- a/chromium/cc/surfaces/display_scheduler.h +++ b/chromium/cc/surfaces/display_scheduler.h @@ -84,6 +84,7 @@ class CC_SURFACES_EXPORT DisplayScheduler : public BeginFrameObserverBase { bool expecting_root_surface_damage_because_of_resize_; bool all_active_child_surfaces_ready_to_draw_; + int next_swap_id_; int pending_swaps_; int max_pending_swaps_; diff --git a/chromium/cc/surfaces/display_unittest.cc b/chromium/cc/surfaces/display_unittest.cc index 159c7ab7035..603d0682001 100644 --- a/chromium/cc/surfaces/display_unittest.cc +++ b/chromium/cc/surfaces/display_unittest.cc @@ -14,13 +14,12 @@ #include "cc/quads/render_pass.h" #include "cc/resources/shared_bitmap_manager.h" #include "cc/scheduler/begin_frame_source.h" +#include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/display_client.h" #include "cc/surfaces/display_scheduler.h" #include "cc/surfaces/frame_sink_id.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" -#include "cc/surfaces/surface_factory.h" -#include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_manager.h" #include "cc/test/fake_output_surface.h" #include "cc/test/scheduler_test_common.h" @@ -36,22 +35,6 @@ namespace { static constexpr FrameSinkId kArbitraryFrameSinkId(3, 3); -class FakeSurfaceFactoryClient : public SurfaceFactoryClient { - public: - FakeSurfaceFactoryClient() : begin_frame_source_(nullptr) {} - - void ReturnResources(const ReturnedResourceArray& resources) override {} - - void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override { - begin_frame_source_ = begin_frame_source; - } - - BeginFrameSource* begin_frame_source() { return begin_frame_source_; } - - private: - BeginFrameSource* begin_frame_source_; -}; - class TestSoftwareOutputDevice : public SoftwareOutputDevice { public: TestSoftwareOutputDevice() {} @@ -99,15 +82,16 @@ class TestDisplayScheduler : public DisplayScheduler { class DisplayTest : public testing::Test { public: DisplayTest() - : factory_(kArbitraryFrameSinkId, &manager_, &surface_factory_client_), - task_runner_(new base::NullTaskRunner) { - manager_.RegisterFrameSinkId(kArbitraryFrameSinkId); - } + : support_(CompositorFrameSinkSupport::Create( + nullptr, + &manager_, + kArbitraryFrameSinkId, + true /* is_root */, + true /* handles_frame_sink_id_invalidation */, + true /* needs_sync_points */)), + task_runner_(new base::NullTaskRunner) {} - ~DisplayTest() override { - manager_.InvalidateFrameSinkId(kArbitraryFrameSinkId); - factory_.EvictSurface(); - } + ~DisplayTest() override { support_->EvictFrame(); } void SetUpDisplay(const RendererSettings& settings, std::unique_ptr<TestWebGraphicsContext3D> context) { @@ -144,13 +128,11 @@ class DisplayTest : public testing::Test { CompositorFrame frame; pass_list->swap(frame.render_pass_list); - factory_.SubmitCompositorFrame(local_surface_id, std::move(frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(local_surface_id, std::move(frame)); } SurfaceManager manager_; - FakeSurfaceFactoryClient surface_factory_client_; - SurfaceFactory factory_; + std::unique_ptr<CompositorFrameSinkSupport> support_; LocalSurfaceIdAllocator id_allocator_; scoped_refptr<base::NullTaskRunner> task_runner_; TestSharedBitmapManager shared_bitmap_manager_; @@ -184,7 +166,7 @@ TEST_F(DisplayTest, DisplayDamaged) { StubDisplayClient client; display_->Initialize(&client, &manager_); - display_->SetColorSpace(color_space_1); + display_->SetColorSpace(color_space_1, color_space_1); LocalSurfaceId local_surface_id(id_allocator_.GenerateId()); EXPECT_FALSE(scheduler_->damaged); @@ -241,7 +223,7 @@ TEST_F(DisplayTest, DisplayDamaged) { scheduler_->swapped = false; EXPECT_EQ(color_space_1, output_surface_->last_reshape_color_space()); - display_->SetColorSpace(color_space_2); + display_->SetColorSpace(color_space_2, color_space_2); display_->DrawAndSwap(); EXPECT_EQ(color_space_2, output_surface_->last_reshape_color_space()); EXPECT_TRUE(scheduler_->swapped); @@ -352,8 +334,7 @@ TEST_F(DisplayTest, DisplayDamaged) { pass_list.swap(frame.render_pass_list); frame.metadata.latency_info.push_back(ui::LatencyInfo()); - factory_.SubmitCompositorFrame(local_surface_id, std::move(frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(local_surface_id, std::move(frame)); EXPECT_TRUE(scheduler_->damaged); EXPECT_FALSE(scheduler_->display_resized_); EXPECT_FALSE(scheduler_->has_new_root_surface); @@ -382,8 +363,7 @@ TEST_F(DisplayTest, DisplayDamaged) { CompositorFrame frame; pass_list.swap(frame.render_pass_list); - factory_.SubmitCompositorFrame(local_surface_id, std::move(frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(local_surface_id, std::move(frame)); EXPECT_TRUE(scheduler_->damaged); EXPECT_FALSE(scheduler_->display_resized_); EXPECT_FALSE(scheduler_->has_new_root_surface); diff --git a/chromium/cc/surfaces/framesink_manager.cc b/chromium/cc/surfaces/framesink_manager.cc new file mode 100644 index 00000000000..d8fad7e3bbe --- /dev/null +++ b/chromium/cc/surfaces/framesink_manager.cc @@ -0,0 +1,231 @@ +// 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/surfaces/framesink_manager.h" + +#include <stddef.h> +#include <stdint.h> + +#include "base/logging.h" +#include "cc/surfaces/surface_factory_client.h" + +#if DCHECK_IS_ON() +#include <sstream> +#endif + +namespace cc { + +FrameSinkManager::FrameSinkSourceMapping::FrameSinkSourceMapping() + : source(nullptr) {} + +FrameSinkManager::FrameSinkSourceMapping::FrameSinkSourceMapping( + const FrameSinkSourceMapping& other) = default; + +FrameSinkManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() { +} + +FrameSinkManager::FrameSinkManager() {} + +FrameSinkManager::~FrameSinkManager() { + // All surface factory clients should be unregistered prior to SurfaceManager + // destruction. + DCHECK_EQ(clients_.size(), 0u); + DCHECK_EQ(registered_sources_.size(), 0u); +} + +void FrameSinkManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) { + bool inserted = valid_frame_sink_ids_.insert(frame_sink_id).second; + DCHECK(inserted); +} + +void FrameSinkManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { + valid_frame_sink_ids_.erase(frame_sink_id); +} + +void FrameSinkManager::RegisterSurfaceFactoryClient( + const FrameSinkId& frame_sink_id, + SurfaceFactoryClient* client) { + DCHECK(client); + DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); + + clients_[frame_sink_id] = client; + + auto it = frame_sink_source_map_.find(frame_sink_id); + if (it != frame_sink_source_map_.end()) { + if (it->second.source) + client->SetBeginFrameSource(it->second.source); + } +} + +void FrameSinkManager::UnregisterSurfaceFactoryClient( + const FrameSinkId& frame_sink_id) { + DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); + auto client_iter = clients_.find(frame_sink_id); + DCHECK(client_iter != clients_.end()); + + auto source_iter = frame_sink_source_map_.find(frame_sink_id); + if (source_iter != frame_sink_source_map_.end()) { + if (source_iter->second.source) + client_iter->second->SetBeginFrameSource(nullptr); + if (!source_iter->second.has_children()) + frame_sink_source_map_.erase(source_iter); + } + clients_.erase(client_iter); +} + +void FrameSinkManager::RegisterBeginFrameSource( + BeginFrameSource* source, + const FrameSinkId& frame_sink_id) { + DCHECK(source); + DCHECK_EQ(registered_sources_.count(source), 0u); + DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); + + registered_sources_[source] = frame_sink_id; + RecursivelyAttachBeginFrameSource(frame_sink_id, source); +} + +void FrameSinkManager::UnregisterBeginFrameSource(BeginFrameSource* source) { + DCHECK(source); + DCHECK_EQ(registered_sources_.count(source), 1u); + + FrameSinkId frame_sink_id = registered_sources_[source]; + registered_sources_.erase(source); + + if (frame_sink_source_map_.count(frame_sink_id) == 0u) + return; + + // TODO(enne): these walks could be done in one step. + // Remove this begin frame source from its subtree. + RecursivelyDetachBeginFrameSource(frame_sink_id, source); + // Then flush every remaining registered source to fix any sources that + // became null because of the previous step but that have an alternative. + for (auto source_iter : registered_sources_) + RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); +} + +void FrameSinkManager::RecursivelyAttachBeginFrameSource( + const FrameSinkId& frame_sink_id, + BeginFrameSource* source) { + FrameSinkSourceMapping& mapping = frame_sink_source_map_[frame_sink_id]; + if (!mapping.source) { + mapping.source = source; + auto client_iter = clients_.find(frame_sink_id); + if (client_iter != clients_.end()) + client_iter->second->SetBeginFrameSource(source); + } + for (size_t i = 0; i < mapping.children.size(); ++i) + RecursivelyAttachBeginFrameSource(mapping.children[i], source); +} + +void FrameSinkManager::RecursivelyDetachBeginFrameSource( + const FrameSinkId& frame_sink_id, + BeginFrameSource* source) { + auto iter = frame_sink_source_map_.find(frame_sink_id); + if (iter == frame_sink_source_map_.end()) + return; + if (iter->second.source == source) { + iter->second.source = nullptr; + auto client_iter = clients_.find(frame_sink_id); + if (client_iter != clients_.end()) + client_iter->second->SetBeginFrameSource(nullptr); + } + + if (!iter->second.has_children() && !clients_.count(frame_sink_id)) { + frame_sink_source_map_.erase(iter); + return; + } + + std::vector<FrameSinkId>& children = iter->second.children; + for (size_t i = 0; i < children.size(); ++i) { + RecursivelyDetachBeginFrameSource(children[i], source); + } +} + +bool FrameSinkManager::ChildContains( + const FrameSinkId& child_frame_sink_id, + const FrameSinkId& search_frame_sink_id) const { + auto iter = frame_sink_source_map_.find(child_frame_sink_id); + if (iter == frame_sink_source_map_.end()) + return false; + + const std::vector<FrameSinkId>& children = iter->second.children; + for (size_t i = 0; i < children.size(); ++i) { + if (children[i] == search_frame_sink_id) + return true; + if (ChildContains(children[i], search_frame_sink_id)) + return true; + } + return false; +} + +void FrameSinkManager::RegisterFrameSinkHierarchy( + const FrameSinkId& parent_frame_sink_id, + const FrameSinkId& child_frame_sink_id) { + // If it's possible to reach the parent through the child's descendant chain, + // then this will create an infinite loop. Might as well just crash here. + CHECK(!ChildContains(child_frame_sink_id, parent_frame_sink_id)); + + std::vector<FrameSinkId>& children = + frame_sink_source_map_[parent_frame_sink_id].children; + for (size_t i = 0; i < children.size(); ++i) + DCHECK(children[i] != child_frame_sink_id); + children.push_back(child_frame_sink_id); + + // If the parent has no source, then attaching it to this child will + // not change any downstream sources. + BeginFrameSource* parent_source = + frame_sink_source_map_[parent_frame_sink_id].source; + if (!parent_source) + return; + + DCHECK_EQ(registered_sources_.count(parent_source), 1u); + RecursivelyAttachBeginFrameSource(child_frame_sink_id, parent_source); +} + +void FrameSinkManager::UnregisterFrameSinkHierarchy( + const FrameSinkId& parent_frame_sink_id, + const FrameSinkId& child_frame_sink_id) { + // Deliberately do not check validity of either parent or child FrameSinkId + // here. They were valid during the registration, so were valid at some + // point in time. This makes it possible to invalidate parent and child + // FrameSinkIds independently of each other and not have an ordering + // dependency of unregistering the hierarchy first before either of them. + DCHECK_EQ(frame_sink_source_map_.count(parent_frame_sink_id), 1u); + + auto iter = frame_sink_source_map_.find(parent_frame_sink_id); + + std::vector<FrameSinkId>& children = iter->second.children; + bool found_child = false; + for (size_t i = 0; i < children.size(); ++i) { + if (children[i] == child_frame_sink_id) { + found_child = true; + children[i] = children.back(); + children.resize(children.size() - 1); + break; + } + } + DCHECK(found_child); + + // The SurfaceFactoryClient and hierarchy can be registered/unregistered + // in either order, so empty frame_sink_source_map entries need to be + // checked when removing either clients or relationships. + if (!iter->second.has_children() && !clients_.count(parent_frame_sink_id) && + !iter->second.source) { + frame_sink_source_map_.erase(iter); + return; + } + + // If the parent does not have a begin frame source, then disconnecting it + // will not change any of its children. + BeginFrameSource* parent_source = iter->second.source; + if (!parent_source) + return; + + // TODO(enne): these walks could be done in one step. + RecursivelyDetachBeginFrameSource(child_frame_sink_id, parent_source); + for (auto source_iter : registered_sources_) + RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); +} + +} // namespace cc diff --git a/chromium/cc/surfaces/framesink_manager.h b/chromium/cc/surfaces/framesink_manager.h new file mode 100644 index 00000000000..087126c1fb2 --- /dev/null +++ b/chromium/cc/surfaces/framesink_manager.h @@ -0,0 +1,122 @@ +// 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_SURFACES_FRAMESINK_MANAGER_H_ +#define CC_SURFACES_FRAMESINK_MANAGER_H_ + +#include <stdint.h> + +#include <unordered_map> +#include <unordered_set> +#include <vector> + +#include "base/logging.h" +#include "base/macros.h" +#include "cc/surfaces/frame_sink_id.h" +#include "cc/surfaces/surfaces_export.h" + +namespace cc { +class BeginFrameSource; +class SurfaceFactoryClient; + +namespace test { +class CompositorFrameSinkSupportTest; +} + +class CC_SURFACES_EXPORT FrameSinkManager { + public: + FrameSinkManager(); + ~FrameSinkManager(); + + void RegisterFrameSinkId(const FrameSinkId& frame_sink_id); + + // Invalidate a frame_sink_id that might still have associated sequences, + // possibly because a renderer process has crashed. + void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id); + + // SurfaceFactoryClient, hierarchy, and BeginFrameSource can be registered + // and unregistered in any order with respect to each other. + // + // This happens in practice, e.g. the relationship to between ui::Compositor / + // DelegatedFrameHost is known before ui::Compositor has a surface/client). + // However, DelegatedFrameHost can register itself as a client before its + // relationship with the ui::Compositor is known. + + // Associates a SurfaceFactoryClient with the frame_sink_id it uses. + // SurfaceFactoryClient and framesink allocators have a 1:1 mapping. + // Caller guarantees the client is alive between register/unregister. + void RegisterSurfaceFactoryClient(const FrameSinkId& frame_sink_id, + SurfaceFactoryClient* client); + void UnregisterSurfaceFactoryClient(const FrameSinkId& frame_sink_id); + + // Associates a |source| with a particular framesink. That framesink and + // any children of that framesink with valid clients can potentially use + // that |source|. + void RegisterBeginFrameSource(BeginFrameSource* source, + const FrameSinkId& frame_sink_id); + void UnregisterBeginFrameSource(BeginFrameSource* source); + + // Register a relationship between two framesinks. This relationship means + // that surfaces from the child framesik will be displayed in the parent. + // Children are allowed to use any begin frame source that their parent can + // use. + void RegisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id, + const FrameSinkId& child_frame_sink_id); + void UnregisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id, + const FrameSinkId& child_frame_sink_id); + + // Export list of valid frame_sink_ids for SatisfyDestructionDeps in surface + // may be removed later when References replace Sequences + std::unordered_set<FrameSinkId, FrameSinkIdHash>* GetValidFrameSinkIds(){ + return &valid_frame_sink_ids_; + } + + private: + friend class test::CompositorFrameSinkSupportTest; + + void RecursivelyAttachBeginFrameSource(const FrameSinkId& frame_sink_id, + BeginFrameSource* source); + void RecursivelyDetachBeginFrameSource(const FrameSinkId& frame_sink_id, + BeginFrameSource* source); + + // Returns true if |child framesink| is or has |search_frame_sink_id| as a + // child. + bool ChildContains(const FrameSinkId& child_frame_sink_id, + const FrameSinkId& search_frame_sink_id) const; + + // Set of valid framesink Ids. When a framesink Id is removed from + // this set, any remaining (surface) sequences with that framesink are + // considered satisfied. + std::unordered_set<FrameSinkId, FrameSinkIdHash> valid_frame_sink_ids_; + + // Begin frame source routing. Both BeginFrameSource and SurfaceFactoryClient + // pointers guaranteed alive by callers until unregistered. + struct FrameSinkSourceMapping { + FrameSinkSourceMapping(); + FrameSinkSourceMapping(const FrameSinkSourceMapping& other); + ~FrameSinkSourceMapping(); + bool has_children() const { return !children.empty(); } + // The currently assigned begin frame source for this client. + BeginFrameSource* source; + // This represents a dag of parent -> children mapping. + std::vector<FrameSinkId> children; + }; + + std::unordered_map<FrameSinkId, SurfaceFactoryClient*, FrameSinkIdHash> + clients_; + + std::unordered_map<FrameSinkId, FrameSinkSourceMapping, FrameSinkIdHash> + frame_sink_source_map_; + + // Set of which sources are registered to which frmesinks. Any child + // that is implicitly using this framesink must be reachable by the + // parent in the dag. + std::unordered_map<BeginFrameSource*, FrameSinkId> registered_sources_; + + DISALLOW_COPY_AND_ASSIGN(FrameSinkManager); +}; + +} // namespace cc + +#endif // CC_SURFACES_FRAMESINK_MANAGER_H_ diff --git a/chromium/cc/surfaces/pending_frame_observer.h b/chromium/cc/surfaces/pending_frame_observer.h index 3efd678360a..ec7acab2e2a 100644 --- a/chromium/cc/surfaces/pending_frame_observer.h +++ b/chromium/cc/surfaces/pending_frame_observer.h @@ -19,12 +19,6 @@ class Surface; // changes should implement this class. class CC_SURFACES_EXPORT PendingFrameObserver { public: - // Called when one or both of the sets of referenced surfaces have changed. - virtual void OnReferencedSurfacesChanged( - Surface* surface, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces) = 0; - // Called when a CompositorFrame within |surface| has activated. virtual void OnSurfaceActivated(Surface* surface) = 0; diff --git a/chromium/cc/surfaces/referenced_surface_tracker.cc b/chromium/cc/surfaces/referenced_surface_tracker.cc index ce1bf61c3fb..5e440d88286 100644 --- a/chromium/cc/surfaces/referenced_surface_tracker.cc +++ b/chromium/cc/surfaces/referenced_surface_tracker.cc @@ -20,8 +20,7 @@ ReferencedSurfaceTracker::~ReferencedSurfaceTracker() {} void ReferencedSurfaceTracker::UpdateReferences( const LocalSurfaceId& local_surface_id, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces) { + const std::vector<SurfaceId>* active_referenced_surfaces) { DCHECK(local_surface_id.is_valid()); // Clear references to add/remove from the last frame. @@ -43,11 +42,6 @@ void ReferencedSurfaceTracker::UpdateReferences( active_referenced_surfaces->end()); } - if (pending_referenced_surfaces) { - referenced_surface_set.insert(pending_referenced_surfaces->begin(), - pending_referenced_surfaces->end()); - } - ProcessNewReferences(referenced_surface_set); } diff --git a/chromium/cc/surfaces/referenced_surface_tracker.h b/chromium/cc/surfaces/referenced_surface_tracker.h index 8153b644f1d..bfb3f3c7f99 100644 --- a/chromium/cc/surfaces/referenced_surface_tracker.h +++ b/chromium/cc/surfaces/referenced_surface_tracker.h @@ -41,8 +41,7 @@ class CC_SURFACES_EXPORT ReferencedSurfaceTracker { // CompositorFrame. void UpdateReferences( const LocalSurfaceId& local_surface_id, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces); + const std::vector<SurfaceId>* active_referenced_surfaces); private: // Updates |referenced_surfaces_| based on a |new_referenced_surfaces| from a diff --git a/chromium/cc/surfaces/referenced_surface_tracker_unittest.cc b/chromium/cc/surfaces/referenced_surface_tracker_unittest.cc index 70a33b11790..05e795320e2 100644 --- a/chromium/cc/surfaces/referenced_surface_tracker_unittest.cc +++ b/chromium/cc/surfaces/referenced_surface_tracker_unittest.cc @@ -63,7 +63,7 @@ TEST_F(ReferencedSurfaceTrackerTest, SetCurrentSurfaceId) { EXPECT_FALSE(tracker().current_surface_id().is_valid()); // After setting current SurfaceId then current_surface_id() should be valid. - tracker().UpdateReferences(parent_id.local_surface_id(), nullptr, nullptr); + tracker().UpdateReferences(parent_id.local_surface_id(), nullptr); EXPECT_EQ(parent_id, tracker().current_surface_id()); } @@ -75,8 +75,7 @@ TEST_F(ReferencedSurfaceTrackerTest, RefSurface) { // First frame has a reference to |child_id1|, check that reference is added. std::vector<SurfaceId> active_referenced_surfaces = {child_id1}; tracker().UpdateReferences(parent_id.local_surface_id(), - &active_referenced_surfaces, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces); EXPECT_THAT(tracker().references_to_add(), UnorderedElementsAre(reference)); EXPECT_THAT(tracker().references_to_remove(), IsEmpty()); } @@ -89,16 +88,14 @@ TEST_F(ReferencedSurfaceTrackerTest, NoChangeToReferences) { // First frame has a reference to |child_id1|, check that reference is added. std::vector<SurfaceId> active_referenced_surfaces = {child_id1}; tracker().UpdateReferences(parent_id.local_surface_id(), - &active_referenced_surfaces, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces); EXPECT_THAT(tracker().references_to_remove(), IsEmpty()); EXPECT_THAT(tracker().references_to_add(), UnorderedElementsAre(reference)); // Second frame has same reference, check that no references are added or // removed. tracker().UpdateReferences(parent_id.local_surface_id(), - &active_referenced_surfaces, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces); EXPECT_THAT(tracker().references_to_remove(), IsEmpty()); EXPECT_THAT(tracker().references_to_add(), IsEmpty()); } @@ -110,14 +107,12 @@ TEST_F(ReferencedSurfaceTrackerTest, UnrefSurface) { std::vector<SurfaceId> active_referenced_surfaces = {child_id1}; tracker().UpdateReferences(parent_id.local_surface_id(), - &active_referenced_surfaces, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces); // Second frame no longer references |child_id1|, check that reference to is // removed. tracker().UpdateReferences(parent_id.local_surface_id(), - nullptr /* active_referenced_surfaces */, - nullptr /* pending_referenced_surfaces */); + nullptr /* active_referenced_surfaces */); EXPECT_THAT(tracker().references_to_add(), IsEmpty()); EXPECT_THAT(tracker().references_to_remove(), UnorderedElementsAre(reference)); @@ -133,8 +128,7 @@ TEST_F(ReferencedSurfaceTrackerTest, RefNewSurfaceForFrameSink) { // First frame has reference to |child_id1_first|. std::vector<SurfaceId> active_referenced_surfaces1 = {child_id1_first}; tracker().UpdateReferences(parent_id.local_surface_id(), - &active_referenced_surfaces1, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces1); EXPECT_THAT(tracker().references_to_add(), UnorderedElementsAre(reference_first)); @@ -143,8 +137,7 @@ TEST_F(ReferencedSurfaceTrackerTest, RefNewSurfaceForFrameSink) { // removed and second reference is added. std::vector<SurfaceId> active_referenced_surfaces2 = {child_id1_second}; tracker().UpdateReferences(parent_id.local_surface_id(), - &active_referenced_surfaces2, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces2); EXPECT_THAT(tracker().references_to_remove(), UnorderedElementsAre(reference_first)); EXPECT_THAT(tracker().references_to_add(), @@ -160,16 +153,14 @@ TEST_F(ReferencedSurfaceTrackerTest, UpdateParentSurfaceId) { // First frame references |child_id1|. std::vector<SurfaceId> active_referenced_surfaces = {child_id1}; tracker().UpdateReferences(parent_id_first.local_surface_id(), - &active_referenced_surfaces, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces); EXPECT_THAT(tracker().references_to_add(), SizeIs(1)); // Second frame still reference |child_id1| but the parent SurfaceId has // changed. The new parent SurfaceId should have a reference added to // |child_id1|. tracker().UpdateReferences(parent_id_second.local_surface_id(), - &active_referenced_surfaces, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces); EXPECT_THAT(tracker().references_to_add(), UnorderedElementsAre(reference)); EXPECT_THAT(tracker().references_to_remove(), IsEmpty()); } @@ -184,8 +175,7 @@ TEST_F(ReferencedSurfaceTrackerTest, RefTwoThenUnrefOneSurface) { // First frame references both surfaces. std::vector<SurfaceId> active_referenced_surfaces1 = {child_id1, child_id2}; tracker().UpdateReferences(parent_id.local_surface_id(), - &active_referenced_surfaces1, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces1); EXPECT_THAT(tracker().references_to_add(), UnorderedElementsAre(reference1, reference2)); @@ -193,8 +183,7 @@ TEST_F(ReferencedSurfaceTrackerTest, RefTwoThenUnrefOneSurface) { // |child_id1| is removed. std::vector<SurfaceId> active_referenced_surfaces2 = {child_id2}; tracker().UpdateReferences(parent_id.local_surface_id(), - &active_referenced_surfaces2, - nullptr /* pending_referenced_surfaces */); + &active_referenced_surfaces2); EXPECT_THAT(tracker().references_to_remove(), UnorderedElementsAre(reference1)); EXPECT_THAT(tracker().references_to_add(), IsEmpty()); diff --git a/chromium/cc/surfaces/surface.cc b/chromium/cc/surfaces/surface.cc index 4aa7a436e49..a161eee5a0c 100644 --- a/chromium/cc/surfaces/surface.cc +++ b/chromium/cc/surfaces/surface.cc @@ -9,7 +9,7 @@ #include <algorithm> -#include "cc/base/container_util.h" +#include "base/stl_util.h" #include "cc/output/compositor_frame.h" #include "cc/output/copy_output_request.h" #include "cc/surfaces/local_surface_id_allocator.h" @@ -73,13 +73,6 @@ void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) { // Ask the surface manager to inform |this| when its dependencies are // resolved. factory_->manager()->RequestSurfaceResolution(this); - - // We do not have to notify observers that referenced surfaces have changed - // in the else case because ActivateFrame will notify observers. - for (auto& observer : observers_) { - observer.OnReferencedSurfacesChanged(this, active_referenced_surfaces(), - pending_referenced_surfaces()); - } } else { // If there are no blockers, then immediately activate the frame. ActivateFrame(std::move(frame)); @@ -113,12 +106,10 @@ void Surface::RequestCopyOfOutput( const base::UnguessableToken& source = copy_request->source(); // Remove existing CopyOutputRequests made on the Surface by the same // source. - auto to_remove = - std::remove_if(copy_requests.begin(), copy_requests.end(), - [&source](const std::unique_ptr<CopyOutputRequest>& x) { - return x->has_source() && x->source() == source; - }); - copy_requests.erase(to_remove, copy_requests.end()); + base::EraseIf(copy_requests, + [&source](const std::unique_ptr<CopyOutputRequest>& x) { + return x->has_source() && x->source() == source; + }); } copy_requests.push_back(std::move(copy_request)); } @@ -199,11 +190,6 @@ void Surface::ActivateFrame(CompositorFrame frame) { for (auto& observer : observers_) observer.OnSurfaceActivated(this); - - for (auto& observer : observers_) { - observer.OnReferencedSurfacesChanged(this, active_referenced_surfaces(), - pending_referenced_surfaces()); - } } void Surface::UpdateBlockingSurfaces( @@ -218,8 +204,7 @@ void Surface::UpdateBlockingSurfaces( base::flat_set<SurfaceId> new_blocking_surfaces; - for (const SurfaceId& surface_id : - current_frame.metadata.referenced_surfaces) { + for (const SurfaceId& surface_id : current_frame.metadata.embedded_surfaces) { Surface* surface = factory_->manager()->GetSurfaceForId(surface_id); // If a referenced surface does not have a corresponding active frame in the // display compositor, then it blocks this frame. @@ -301,14 +286,11 @@ void Surface::AddDestructionDependency(SurfaceSequence sequence) { void Surface::SatisfyDestructionDependencies( std::unordered_set<SurfaceSequence, SurfaceSequenceHash>* sequences, std::unordered_set<FrameSinkId, FrameSinkIdHash>* valid_frame_sink_ids) { - destruction_dependencies_.erase( - std::remove_if(destruction_dependencies_.begin(), - destruction_dependencies_.end(), - [sequences, valid_frame_sink_ids](SurfaceSequence seq) { - return (!!sequences->erase(seq) || - !valid_frame_sink_ids->count(seq.frame_sink_id)); - }), - destruction_dependencies_.end()); + base::EraseIf(destruction_dependencies_, + [sequences, valid_frame_sink_ids](SurfaceSequence seq) { + return (!!sequences->erase(seq) || + !valid_frame_sink_ids->count(seq.frame_sink_id)); + }); } void Surface::UnrefFrameResources(const CompositorFrame& frame) { diff --git a/chromium/cc/surfaces/surface.h b/chromium/cc/surfaces/surface.h index f35740ab3f0..6cd9bbf70db 100644 --- a/chromium/cc/surfaces/surface.h +++ b/chromium/cc/surfaces/surface.h @@ -106,12 +106,7 @@ class CC_SURFACES_EXPORT Surface { : nullptr; } - const std::vector<SurfaceId>* pending_referenced_surfaces() const { - return pending_frame_ ? &pending_frame_->metadata.referenced_surfaces - : nullptr; - } - - const SurfaceDependencies& blocking_surfaces_for_testing() const { + const SurfaceDependencies& blocking_surfaces() const { return blocking_surfaces_; } @@ -160,8 +155,6 @@ class CC_SURFACES_EXPORT Surface { DISALLOW_COPY_AND_ASSIGN(Surface); }; -using PendingSurfaceSet = base::flat_set<Surface*>; - } // namespace cc #endif // CC_SURFACES_SURFACE_H_ diff --git a/chromium/cc/surfaces/surface_aggregator.cc b/chromium/cc/surfaces/surface_aggregator.cc index 70ce4e59142..db1366da53c 100644 --- a/chromium/cc/surfaces/surface_aggregator.cc +++ b/chromium/cc/surfaces/surface_aggregator.cc @@ -13,6 +13,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" @@ -32,6 +33,16 @@ namespace cc { namespace { +// Maximum bucket size for the UMA stats. +constexpr int kUmaStatMaxSurfaces = 30; + +const char kUmaValidSurface[] = + "Compositing.SurfaceAggregator.SurfaceDrawQuad.ValidSurface"; +const char kUmaMissingSurface[] = + "Compositing.SurfaceAggregator.SurfaceDrawQuad.MissingSurface"; +const char kUmaNoActiveFrame[] = + "Compositing.SurfaceAggregator.SurfaceDrawQuad.NoActiveFrame"; + void MoveMatchingRequests( int render_pass_id, std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests, @@ -193,9 +204,14 @@ void SurfaceAggregator::HandleSurfaceQuad( clip_rect, dest_pass, ignore_undamaged, damage_rect_in_quad_space, damage_rect_in_quad_space_valid); + } else if (!surface) { + ++uma_stats_.missing_surface; + } else { + ++uma_stats_.no_active_frame; } return; } + ++uma_stats_.valid_surface; if (ignore_undamaged) { gfx::Transform quad_to_target_transform( @@ -248,7 +264,7 @@ void SurfaceAggregator::HandleSurfaceQuad( copy_pass->SetAll(remapped_pass_id, source.output_rect, source.output_rect, source.transform_to_root_target, source.filters, - source.background_filters, output_color_space_, + source.background_filters, blending_color_space_, source.has_transparent_background); MoveMatchingRequests(source.id, ©_requests, ©_pass->copy_requests); @@ -317,12 +333,47 @@ void SurfaceAggregator::HandleSurfaceQuad( dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); quad->SetNew(shared_quad_state, surface_quad->rect, surface_quad->visible_rect, remapped_pass_id, 0, gfx::RectF(), - gfx::Size(), gfx::Vector2dF(), gfx::PointF(), gfx::RectF()); + gfx::Size(), gfx::Vector2dF(), gfx::PointF(), + gfx::RectF(surface_quad->rect)); } referenced_surfaces_.erase(it); } +void SurfaceAggregator::AddColorConversionPass() { + if (dest_pass_list_->empty()) + return; + + RenderPass* root_render_pass = dest_pass_list_->back().get(); + if (root_render_pass->color_space == output_color_space_) + return; + + gfx::Rect output_rect = root_render_pass->output_rect; + CHECK(root_render_pass->transform_to_root_target == gfx::Transform()); + + if (!color_conversion_render_pass_id_) + color_conversion_render_pass_id_ = next_render_pass_id_++; + + std::unique_ptr<RenderPass> color_conversion_pass(RenderPass::Create(1, 1)); + color_conversion_pass->SetNew(color_conversion_render_pass_id_, output_rect, + root_render_pass->damage_rect, + root_render_pass->transform_to_root_target); + color_conversion_pass->color_space = output_color_space_; + + SharedQuadState* shared_quad_state = + color_conversion_pass->CreateAndAppendSharedQuadState(); + shared_quad_state->quad_layer_bounds = output_rect.size(); + shared_quad_state->visible_quad_layer_rect = output_rect; + shared_quad_state->opacity = 1.f; + + RenderPassDrawQuad* quad = + color_conversion_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); + quad->SetNew(shared_quad_state, output_rect, output_rect, + root_render_pass->id, 0, gfx::RectF(), gfx::Size(), + gfx::Vector2dF(), gfx::PointF(), gfx::RectF(output_rect)); + dest_pass_list_->push_back(std::move(color_conversion_pass)); +} + SharedQuadState* SurfaceAggregator::CopySharedQuadState( const SharedQuadState* source_sqs, const gfx::Transform& target_transform, @@ -492,7 +543,7 @@ void SurfaceAggregator::CopyPasses(const CompositorFrame& frame, copy_pass->SetAll(remapped_pass_id, source.output_rect, source.output_rect, source.transform_to_root_target, source.filters, - source.background_filters, output_color_space_, + source.background_filters, blending_color_space_, source.has_transparent_background); CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, @@ -782,6 +833,8 @@ void SurfaceAggregator::PropagateCopyRequestPasses() { } CompositorFrame SurfaceAggregator::Aggregate(const SurfaceId& surface_id) { + uma_stats_.Reset(); + Surface* surface = manager_->GetSurfaceForId(surface_id); DCHECK(surface); contained_surfaces_[surface_id] = surface->frame_index(); @@ -808,6 +861,7 @@ CompositorFrame SurfaceAggregator::Aggregate(const SurfaceId& surface_id) { SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; CopyPasses(root_surface_frame, surface); referenced_surfaces_.erase(it); + AddColorConversionPass(); moved_pixel_passes_.clear(); copy_request_passes_.clear(); @@ -845,6 +899,15 @@ CompositorFrame SurfaceAggregator::Aggregate(const SurfaceId& surface_id) { // TODO(jamesr): Aggregate all resource references into the returned frame's // resource list. + // Log UMA stats for SurfaceDrawQuads on the number of surfaces that were + // aggregated together and any failures. + UMA_HISTOGRAM_EXACT_LINEAR(kUmaValidSurface, uma_stats_.valid_surface, + kUmaStatMaxSurfaces); + UMA_HISTOGRAM_EXACT_LINEAR(kUmaMissingSurface, uma_stats_.missing_surface, + kUmaStatMaxSurfaces); + UMA_HISTOGRAM_EXACT_LINEAR(kUmaNoActiveFrame, uma_stats_.no_active_frame, + kUmaStatMaxSurfaces); + return frame; } @@ -866,7 +929,9 @@ void SurfaceAggregator::SetFullDamageForSurface(const SurfaceId& surface_id) { } void SurfaceAggregator::SetOutputColorSpace( + const gfx::ColorSpace& blending_color_space, const gfx::ColorSpace& output_color_space) { + blending_color_space_ = blending_color_space; output_color_space_ = output_color_space; } diff --git a/chromium/cc/surfaces/surface_aggregator.h b/chromium/cc/surfaces/surface_aggregator.h index 8e9c2906ae4..ec69f5d3319 100644 --- a/chromium/cc/surfaces/surface_aggregator.h +++ b/chromium/cc/surfaces/surface_aggregator.h @@ -47,7 +47,8 @@ class CC_SURFACES_EXPORT SurfaceAggregator { // Set the color spaces for the created RenderPasses, which is propagated // to the output surface. - void SetOutputColorSpace(const gfx::ColorSpace& output_color_space); + void SetOutputColorSpace(const gfx::ColorSpace& blending_color_space, + const gfx::ColorSpace& output_color_space); private: struct ClipData { @@ -75,6 +76,21 @@ class CC_SURFACES_EXPORT SurfaceAggregator { bool in_use = true; }; + struct SurfaceDrawQuadUmaStats { + void Reset() { + valid_surface = 0; + missing_surface = 0; + no_active_frame = 0; + } + + // The surface exists and has an active frame. + int valid_surface; + // The surface doesn't exist. + int missing_surface; + // The surface exists but doesn't have an active frame. + int no_active_frame; + }; + ClipData CalculateClipRect(const ClipData& surface_clip, const ClipData& quad_clip, const gfx::Transform& target_transform); @@ -107,6 +123,7 @@ class CC_SURFACES_EXPORT SurfaceAggregator { PrewalkResult* result); void CopyUndrawnSurfaces(PrewalkResult* prewalk); void CopyPasses(const CompositorFrame& frame, Surface* surface); + void AddColorConversionPass(); // Remove Surfaces that were referenced before but aren't currently // referenced from the ResourceProvider. @@ -134,7 +151,16 @@ class CC_SURFACES_EXPORT SurfaceAggregator { int next_render_pass_id_; const bool aggregate_only_damaged_; bool output_is_secure_; + + // The color space for the root render pass. If this is different from + // |blending_color_space_|, then a final render pass to convert between + // the two will be added. gfx::ColorSpace output_color_space_; + // The color space in which blending is done, used for all non-root render + // passes. + gfx::ColorSpace blending_color_space_; + // The id for the final color conversion render pass. + int color_conversion_render_pass_id_ = 0; using SurfaceToResourceChildIdMap = std::unordered_map<SurfaceId, int, SurfaceIdHash>; @@ -182,6 +208,9 @@ class CC_SURFACES_EXPORT SurfaceAggregator { // Resource list for the aggregated frame. TransferableResourceArray* dest_resource_list_; + // Tracks UMA stats for SurfaceDrawQuads during a call to Aggregate(). + SurfaceDrawQuadUmaStats uma_stats_; + base::WeakPtrFactory<SurfaceAggregator> weak_factory_; DISALLOW_COPY_AND_ASSIGN(SurfaceAggregator); diff --git a/chromium/cc/surfaces/surface_aggregator_perftest.cc b/chromium/cc/surfaces/surface_aggregator_perftest.cc index d86da68768c..691acfd9908 100644 --- a/chromium/cc/surfaces/surface_aggregator_perftest.cc +++ b/chromium/cc/surfaces/surface_aggregator_perftest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/memory/ptr_util.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/output/compositor_frame.h" #include "cc/quads/surface_draw_quad.h" #include "cc/quads/texture_draw_quad.h" diff --git a/chromium/cc/surfaces/surface_aggregator_unittest.cc b/chromium/cc/surfaces/surface_aggregator_unittest.cc index 5173b9d61b6..04cca7989e7 100644 --- a/chromium/cc/surfaces/surface_aggregator_unittest.cc +++ b/chromium/cc/surfaces/surface_aggregator_unittest.cc @@ -18,11 +18,11 @@ #include "cc/quads/surface_draw_quad.h" #include "cc/quads/texture_draw_quad.h" #include "cc/resources/shared_bitmap_manager.h" +#include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" -#include "cc/surfaces/surface_factory.h" -#include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_manager.h" +#include "cc/test/fake_compositor_frame_sink_support_client.h" #include "cc/test/fake_resource_provider.h" #include "cc/test/render_pass_test_utils.h" #include "cc/test/surface_aggregator_test_helpers.h" @@ -35,10 +35,16 @@ namespace cc { namespace { constexpr FrameSinkId kArbitraryRootFrameSinkId(1, 1); -constexpr FrameSinkId kArbitraryChildFrameSinkId1(2, 2); -constexpr FrameSinkId kArbitraryChildFrameSinkId2(3, 3); +constexpr FrameSinkId kArbitraryFrameSinkId1(2, 2); +constexpr FrameSinkId kArbitraryFrameSinkId2(3, 3); constexpr FrameSinkId kArbitraryMiddleFrameSinkId(4, 4); +constexpr FrameSinkId kArbitraryReservedFrameSinkId(5, 5); +constexpr FrameSinkId kArbitraryFrameSinkId3(6, 6); const base::UnguessableToken kArbitraryToken = base::UnguessableToken::Create(); +constexpr bool kRootIsRoot = true; +constexpr bool kChildIsRoot = false; +constexpr bool kHandlesFrameSinkIdInvalidation = true; +constexpr bool kNeedsSyncPoints = false; SurfaceId InvalidSurfaceId() { static SurfaceId invalid(FrameSinkId(), @@ -51,47 +57,36 @@ gfx::Size SurfaceSize() { return size; } -class EmptySurfaceFactoryClient : public SurfaceFactoryClient { - public: - void ReturnResources(const ReturnedResourceArray& resources) override {} - - void WillDrawSurface(const LocalSurfaceId& id, - const gfx::Rect& damage_rect) override { - last_local_surface_id_ = id; - last_damage_rect_ = damage_rect; - } - - void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override {} - - gfx::Rect last_damage_rect_; - LocalSurfaceId last_local_surface_id_; -}; - class SurfaceAggregatorTest : public testing::Test { public: explicit SurfaceAggregatorTest(bool use_damage_rect) - : factory_(kArbitraryRootFrameSinkId, &manager_, &empty_client_), + : support_( + CompositorFrameSinkSupport::Create(&fake_client_, + &manager_, + kArbitraryRootFrameSinkId, + kRootIsRoot, + kHandlesFrameSinkIdInvalidation, + kNeedsSyncPoints)), aggregator_(&manager_, NULL, use_damage_rect) {} SurfaceAggregatorTest() : SurfaceAggregatorTest(false) {} void TearDown() override { - factory_.EvictSurface(); + support_->EvictFrame(); testing::Test::TearDown(); } protected: SurfaceManager manager_; - EmptySurfaceFactoryClient empty_client_; - SurfaceFactory factory_; + FakeCompositorFrameSinkSupportClient fake_client_; + std::unique_ptr<CompositorFrameSinkSupport> support_; SurfaceAggregator aggregator_; }; TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) { LocalSurfaceId local_surface_id(7, base::UnguessableToken::Create()); SurfaceId one_id(kArbitraryRootFrameSinkId, local_surface_id); - factory_.SubmitCompositorFrame(local_surface_id, CompositorFrame(), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(local_surface_id, CompositorFrame()); CompositorFrame frame = aggregator_.Aggregate(one_id); EXPECT_TRUE(frame.render_pass_list.empty()); @@ -101,9 +96,13 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest { public: explicit SurfaceAggregatorValidSurfaceTest(bool use_damage_rect) : SurfaceAggregatorTest(use_damage_rect), - child_factory_(kArbitraryChildFrameSinkId1, - &manager_, - &empty_child_client_) {} + child_support_( + CompositorFrameSinkSupport::Create(nullptr, + &manager_, + kArbitraryReservedFrameSinkId, + kChildIsRoot, + kHandlesFrameSinkIdInvalidation, + kNeedsSyncPoints)) {} SurfaceAggregatorValidSurfaceTest() : SurfaceAggregatorValidSurfaceTest(false) {} @@ -111,11 +110,11 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest { SurfaceAggregatorTest::SetUp(); root_local_surface_id_ = allocator_.GenerateId(); root_surface_ = manager_.GetSurfaceForId( - SurfaceId(factory_.frame_sink_id(), root_local_surface_id_)); + SurfaceId(support_->frame_sink_id(), root_local_surface_id_)); } void TearDown() override { - child_factory_.EvictSurface(); + child_support_->EvictFrame(); SurfaceAggregatorTest::TearDown(); } @@ -124,7 +123,7 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest { SurfaceId* surface_ids, size_t expected_surface_count) { CompositorFrame aggregated_frame = aggregator_.Aggregate( - SurfaceId(factory_.frame_sink_id(), root_local_surface_id_)); + SurfaceId(support_->frame_sink_id(), root_local_surface_id_)); TestPassesMatchExpectations(expected_passes, expected_pass_count, &aggregated_frame.render_pass_list); @@ -144,41 +143,38 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest { } } - void SubmitPassListAsFrame(SurfaceFactory* factory, + void SubmitPassListAsFrame(CompositorFrameSinkSupport* support, const LocalSurfaceId& local_surface_id, RenderPassList* pass_list) { CompositorFrame frame; pass_list->swap(frame.render_pass_list); - factory->SubmitCompositorFrame(local_surface_id, std::move(frame), - SurfaceFactory::DrawCallback()); + support->SubmitCompositorFrame(local_surface_id, std::move(frame)); } - void SubmitCompositorFrame(SurfaceFactory* factory, + void SubmitCompositorFrame(CompositorFrameSinkSupport* support, test::Pass* passes, size_t pass_count, const LocalSurfaceId& local_surface_id) { RenderPassList pass_list; AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count); - SubmitPassListAsFrame(factory, local_surface_id, &pass_list); + SubmitPassListAsFrame(support, local_surface_id, &pass_list); } void QueuePassAsFrame(std::unique_ptr<RenderPass> pass, const LocalSurfaceId& local_surface_id, - SurfaceFactory* factory) { + CompositorFrameSinkSupport* support) { CompositorFrame child_frame; child_frame.render_pass_list.push_back(std::move(pass)); - factory->SubmitCompositorFrame(local_surface_id, std::move(child_frame), - SurfaceFactory::DrawCallback()); + support->SubmitCompositorFrame(local_surface_id, std::move(child_frame)); } protected: LocalSurfaceId root_local_surface_id_; Surface* root_surface_; LocalSurfaceIdAllocator allocator_; - EmptySurfaceFactoryClient empty_child_client_; - SurfaceFactory child_factory_; + std::unique_ptr<CompositorFrameSinkSupport> child_support_; LocalSurfaceIdAllocator child_allocator_; }; @@ -189,24 +185,26 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) { test::Quad::SolidColorQuad(SK_ColorBLUE)}; test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; - SubmitCompositorFrame(&factory_, passes, arraysize(passes), + SubmitCompositorFrame(support_.get(), passes, arraysize(passes), root_local_surface_id_); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); SurfaceId ids[] = {root_surface_id}; AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids)); // Check that WillDrawSurface was called. - EXPECT_EQ(gfx::Rect(SurfaceSize()), empty_client_.last_damage_rect_); - EXPECT_EQ(root_local_surface_id_, empty_client_.last_local_surface_id_); + EXPECT_EQ(gfx::Rect(SurfaceSize()), fake_client_.last_damage_rect()); + EXPECT_EQ(root_local_surface_id_, fake_client_.last_local_surface_id()); } TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) { - SurfaceFactory embedded_factory(kArbitraryChildFrameSinkId1, &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> embedded_support( + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId1, kRootIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints)); LocalSurfaceId embedded_local_surface_id = allocator_.GenerateId(); - SurfaceId embedded_surface_id(embedded_factory.frame_sink_id(), + SurfaceId embedded_surface_id(embedded_support->frame_sink_id(), embedded_local_surface_id); test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), @@ -214,17 +212,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) { test::Pass embedded_passes[] = { test::Pass(embedded_quads, arraysize(embedded_quads))}; - SubmitCompositorFrame(&embedded_factory, embedded_passes, + SubmitCompositorFrame(embedded_support.get(), embedded_passes, arraysize(embedded_passes), embedded_local_surface_id); test::Quad quads[] = { test::Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(), .5f)}; test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; - SubmitCompositorFrame(&factory_, passes, arraysize(passes), + SubmitCompositorFrame(support_.get(), passes, arraysize(passes), root_local_surface_id_); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); RenderPassList& render_pass_list(aggregated_frame.render_pass_list); @@ -240,7 +238,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) { ASSERT_EQ(1u, shared_quad_state_list2.size()); EXPECT_EQ(.5f, shared_quad_state_list2.ElementAt(0)->opacity); - embedded_factory.EvictSurface(); + embedded_support->EvictFrame(); } TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) { @@ -251,10 +249,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) { test::Pass passes[] = {test::Pass(quads[0], arraysize(quads[0]), 1), test::Pass(quads[1], arraysize(quads[1]), 2)}; - SubmitCompositorFrame(&factory_, passes, arraysize(passes), + SubmitCompositorFrame(support_.get(), passes, arraysize(passes), root_local_surface_id_); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); SurfaceId ids[] = {root_surface_id}; AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids)); @@ -269,10 +267,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassDeallocation) { test::Pass passes[] = {test::Pass(quads[0], arraysize(quads[0]), 2), test::Pass(quads[1], arraysize(quads[1]), 1)}; - SubmitCompositorFrame(&factory_, passes, arraysize(passes), + SubmitCompositorFrame(support_.get(), passes, arraysize(passes), root_local_surface_id_); - SurfaceId surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame; aggregated_frame = aggregator_.Aggregate(surface_id); @@ -288,7 +286,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassDeallocation) { test::Pass passes2[] = {test::Pass(quads[0], arraysize(quads[0]), 3), test::Pass(quads[1], arraysize(quads[1]), 1)}; - SubmitCompositorFrame(&factory_, passes2, arraysize(passes2), + SubmitCompositorFrame(support_.get(), passes2, arraysize(passes2), root_local_surface_id_); // The RenderPass that still exists should keep the same ID. @@ -298,7 +296,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassDeallocation) { EXPECT_NE(id2, id0); EXPECT_EQ(id1, aggregated_frame.render_pass_list[1]->id); - SubmitCompositorFrame(&factory_, passes, arraysize(passes), + SubmitCompositorFrame(support_.get(), passes, arraysize(passes), root_local_surface_id_); // |id1| didn't exist in the previous frame, so it should be @@ -316,17 +314,19 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassDeallocation) { // embedded_surface has a frame containing only a solid color quad. The solid // color quad should be aggregated into the final frame. TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) { - SurfaceFactory embedded_factory(kArbitraryChildFrameSinkId1, &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> embedded_support( + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId1, kRootIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints)); LocalSurfaceId embedded_local_surface_id = allocator_.GenerateId(); - SurfaceId embedded_surface_id(embedded_factory.frame_sink_id(), + SurfaceId embedded_surface_id(embedded_support->frame_sink_id(), embedded_local_surface_id); test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; test::Pass embedded_passes[] = { test::Pass(embedded_quads, arraysize(embedded_quads))}; - SubmitCompositorFrame(&embedded_factory, embedded_passes, + SubmitCompositorFrame(embedded_support.get(), embedded_passes, arraysize(embedded_passes), embedded_local_surface_id); test::Quad root_quads[] = { @@ -335,7 +335,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) { test::Quad::SolidColorQuad(SK_ColorBLACK)}; test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))}; - SubmitCompositorFrame(&factory_, root_passes, arraysize(root_passes), + SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), root_local_surface_id_); test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), @@ -343,28 +343,32 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) { test::Quad::SolidColorQuad(SK_ColorBLACK)}; test::Pass expected_passes[] = { test::Pass(expected_quads, arraysize(expected_quads))}; - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); SurfaceId ids[] = {root_surface_id, embedded_surface_id}; AggregateAndVerify( expected_passes, arraysize(expected_passes), ids, arraysize(ids)); - embedded_factory.EvictSurface(); + embedded_support->EvictFrame(); } // This test verifies that in the absence of a primary Surface, // SurfaceAggregator will embed a fallback Surface, if available. If the primary // Surface is available, though, the fallback will not be used. TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReference) { - SurfaceFactory primary_child_factory(kArbitraryChildFrameSinkId1, &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> primary_child_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId primary_child_local_surface_id = allocator_.GenerateId(); - SurfaceId primary_child_surface_id(primary_child_factory.frame_sink_id(), + SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(), primary_child_local_surface_id); - SurfaceFactory fallback_child_factory(kArbitraryChildFrameSinkId2, &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> fallback_child_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId2, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId fallback_child_local_surface_id = allocator_.GenerateId(); - SurfaceId fallback_child_surface_id(fallback_child_factory.frame_sink_id(), + SurfaceId fallback_child_surface_id(fallback_child_support->frame_sink_id(), fallback_child_local_surface_id); test::Quad fallback_child_quads[] = {test::Quad::SolidColorQuad(SK_ColorRED)}; @@ -373,7 +377,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReference) { // Submit a CompositorFrame to the fallback Surface containing a red // SolidColorDrawQuad. - SubmitCompositorFrame(&fallback_child_factory, fallback_child_passes, + SubmitCompositorFrame(fallback_child_support.get(), fallback_child_passes, arraysize(fallback_child_passes), fallback_child_local_surface_id); @@ -383,7 +387,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReference) { primary_child_surface_id, fallback_child_surface_id, 1.f)}; test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))}; - SubmitCompositorFrame(&factory_, root_passes, arraysize(root_passes), + SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), root_local_surface_id_); // There is no CompositorFrame submitted to |primary_child_surface_id| and so @@ -393,7 +397,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReference) { test::Pass expected_passes1[] = { test::Pass(expected_quads1, arraysize(expected_quads1))}; - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); SurfaceId ids[] = {root_surface_id, primary_child_surface_id, fallback_child_surface_id}; AggregateAndVerify(expected_passes1, arraysize(expected_passes1), ids, @@ -406,7 +410,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReference) { // Submit a CompositorFrame to the primary Surface containing a green // SolidColorDrawQuad. - SubmitCompositorFrame(&primary_child_factory, primary_child_passes, + SubmitCompositorFrame(primary_child_support.get(), primary_child_passes, arraysize(primary_child_passes), primary_child_local_surface_id); @@ -419,27 +423,94 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReference) { AggregateAndVerify(expected_passes2, arraysize(expected_passes2), ids, arraysize(ids)); - primary_child_factory.EvictSurface(); - fallback_child_factory.EvictSurface(); + primary_child_support->EvictFrame(); + fallback_child_support->EvictFrame(); +} + +// This test verifies that in the presence of both primary Surface and fallback +// Surface, the fallback will not be used. +TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) { + std::unique_ptr<CompositorFrameSinkSupport> primary_child_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + LocalSurfaceId primary_child_local_surface_id = allocator_.GenerateId(); + SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(), + primary_child_local_surface_id); + test::Quad primary_child_quads[] = { + test::Quad::SolidColorQuad(SK_ColorGREEN)}; + test::Pass primary_child_passes[] = { + test::Pass(primary_child_quads, arraysize(primary_child_quads))}; + + // Submit a CompositorFrame to the primary Surface containing a green + // SolidColorDrawQuad. + SubmitCompositorFrame(primary_child_support.get(), primary_child_passes, + arraysize(primary_child_passes), + primary_child_local_surface_id); + + std::unique_ptr<CompositorFrameSinkSupport> fallback_child_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId2, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + LocalSurfaceId fallback_child_local_surface_id = allocator_.GenerateId(); + SurfaceId fallback_child_surface_id(fallback_child_support->frame_sink_id(), + fallback_child_local_surface_id); + + test::Quad fallback_child_quads[] = {test::Quad::SolidColorQuad(SK_ColorRED)}; + test::Pass fallback_child_passes[] = { + test::Pass(fallback_child_quads, arraysize(fallback_child_quads))}; + + // Submit a CompositorFrame to the fallback Surface containing a red + // SolidColorDrawQuad. + SubmitCompositorFrame(fallback_child_support.get(), fallback_child_passes, + arraysize(fallback_child_passes), + fallback_child_local_surface_id); + + // Try to embed |primary_child_surface_id| and if unavailabe, embed + // |fallback_child_surface_id|. + test::Quad root_quads[] = {test::Quad::SurfaceQuad( + primary_child_surface_id, fallback_child_surface_id, 1.f)}; + test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))}; + + SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), + root_local_surface_id_); + + // The CompositorFrame is submitted to |primary_child_surface_id|, so + // |fallback_child_surface_id| will not be used and we should see a green + // SolidColorDrawQuad. + test::Quad expected_quads1[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; + test::Pass expected_passes1[] = { + test::Pass(expected_quads1, arraysize(expected_quads1))}; + + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); + SurfaceId ids[] = {root_surface_id, primary_child_surface_id, + fallback_child_surface_id}; + AggregateAndVerify(expected_passes1, arraysize(expected_passes1), ids, + arraysize(ids)); + + primary_child_support->EvictFrame(); + fallback_child_support->EvictFrame(); } TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) { - SurfaceFactory embedded_factory(kArbitraryChildFrameSinkId1, &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> embedded_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId embedded_local_surface_id = allocator_.GenerateId(); - SurfaceId embedded_surface_id(embedded_factory.frame_sink_id(), + SurfaceId embedded_surface_id(embedded_support->frame_sink_id(), embedded_local_surface_id); test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; test::Pass embedded_passes[] = { test::Pass(embedded_quads, arraysize(embedded_quads))}; - SubmitCompositorFrame(&embedded_factory, embedded_passes, + SubmitCompositorFrame(embedded_support.get(), embedded_passes, arraysize(embedded_passes), embedded_local_surface_id); std::unique_ptr<CopyOutputRequest> copy_request( CopyOutputRequest::CreateEmptyRequest()); CopyOutputRequest* copy_request_ptr = copy_request.get(); - embedded_factory.RequestCopyOfSurface(std::move(copy_request)); + embedded_support->RequestCopyOfSurface(std::move(copy_request)); test::Quad root_quads[] = { test::Quad::SolidColorQuad(SK_ColorWHITE), @@ -447,10 +518,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) { test::Quad::SolidColorQuad(SK_ColorBLACK)}; test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))}; - SubmitCompositorFrame(&factory_, root_passes, arraysize(root_passes), + SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), root_local_surface_id_); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); test::Quad expected_quads[] = { @@ -476,22 +547,24 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) { aggregator_.previous_contained_surfaces().end()); } - embedded_factory.EvictSurface(); + embedded_support->EvictFrame(); } // Root surface may contain copy requests. TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) { - SurfaceFactory embedded_factory(kArbitraryChildFrameSinkId1, &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> embedded_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId2, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId embedded_local_surface_id = allocator_.GenerateId(); - SurfaceId embedded_surface_id(embedded_factory.frame_sink_id(), + SurfaceId embedded_surface_id(embedded_support->frame_sink_id(), embedded_local_surface_id); test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; test::Pass embedded_passes[] = { test::Pass(embedded_quads, arraysize(embedded_quads))}; - SubmitCompositorFrame(&embedded_factory, embedded_passes, + SubmitCompositorFrame(embedded_support.get(), embedded_passes, arraysize(embedded_passes), embedded_local_surface_id); std::unique_ptr<CopyOutputRequest> copy_request( CopyOutputRequest::CreateEmptyRequest()); @@ -516,11 +589,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) { frame.render_pass_list[1]->copy_requests.push_back( std::move(copy_request2)); - factory_.SubmitCompositorFrame(root_local_surface_id_, std::move(frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame)); } - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), @@ -556,39 +628,43 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) { DCHECK(original_pass_list[0]->copy_requests.empty()); DCHECK(original_pass_list[1]->copy_requests.empty()); - embedded_factory.EvictSurface(); + embedded_support->EvictFrame(); } TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) { - SurfaceFactory embedded_factory(kArbitraryChildFrameSinkId1, &manager_, - &empty_client_); - SurfaceFactory parent_factory(kArbitraryRootFrameSinkId, &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> embedded_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + std::unique_ptr<CompositorFrameSinkSupport> parent_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId2, kRootIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId embedded_local_surface_id = allocator_.GenerateId(); - SurfaceId embedded_surface_id(embedded_factory.frame_sink_id(), + SurfaceId embedded_surface_id(embedded_support->frame_sink_id(), embedded_local_surface_id); - SurfaceId nonexistent_surface_id(factory_.frame_sink_id(), + SurfaceId nonexistent_surface_id(support_->frame_sink_id(), allocator_.GenerateId()); test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; test::Pass embedded_passes[] = { test::Pass(embedded_quads, arraysize(embedded_quads))}; - SubmitCompositorFrame(&embedded_factory, embedded_passes, + SubmitCompositorFrame(embedded_support.get(), embedded_passes, arraysize(embedded_passes), embedded_local_surface_id); std::unique_ptr<CopyOutputRequest> copy_request( CopyOutputRequest::CreateEmptyRequest()); CopyOutputRequest* copy_request_ptr = copy_request.get(); - embedded_factory.RequestCopyOfSurface(std::move(copy_request)); + embedded_support->RequestCopyOfSurface(std::move(copy_request)); LocalSurfaceId parent_local_surface_id = allocator_.GenerateId(); - SurfaceId parent_surface_id(parent_factory.frame_sink_id(), + SurfaceId parent_surface_id(parent_support->frame_sink_id(), parent_local_surface_id); test::Quad parent_quads[] = { - test::Quad::SolidColorQuad(SK_ColorWHITE), + test::Quad::SolidColorQuad(SK_ColorGRAY), test::Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(), 1.f), - test::Quad::SolidColorQuad(SK_ColorBLACK)}; + test::Quad::SolidColorQuad(SK_ColorLTGRAY)}; test::Pass parent_passes[] = { test::Pass(parent_quads, arraysize(parent_quads))}; @@ -600,9 +676,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) { frame.metadata.referenced_surfaces.push_back(embedded_surface_id); - parent_factory.SubmitCompositorFrame(parent_local_surface_id, - std::move(frame), - SurfaceFactory::DrawCallback()); + parent_support->SubmitCompositorFrame(parent_local_surface_id, + std::move(frame)); } test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), @@ -619,11 +694,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) { // included in previous_contained_surfaces, but otherwise ignored. frame.metadata.referenced_surfaces.push_back(nonexistent_surface_id); - factory_.SubmitCompositorFrame(root_local_surface_id_, std::move(frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame)); } - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); // First pass should come from surface that had a copy request but was not @@ -641,7 +715,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) { aggregated_frame.render_pass_list[0]->copy_requests[0].get()); SurfaceId surface_ids[] = { - SurfaceId(factory_.frame_sink_id(), root_local_surface_id_), + SurfaceId(support_->frame_sink_id(), root_local_surface_id_), parent_surface_id, embedded_surface_id, nonexistent_surface_id}; EXPECT_EQ(arraysize(surface_ids), aggregator_.previous_contained_surfaces().size()); @@ -651,14 +725,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) { aggregator_.previous_contained_surfaces().end()); } - embedded_factory.EvictSurface(); - parent_factory.EvictSurface(); + embedded_support->EvictFrame(); + parent_support->EvictFrame(); } // This tests referencing a surface that has multiple render passes. TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) { LocalSurfaceId embedded_local_surface_id = child_allocator_.GenerateId(); - SurfaceId embedded_surface_id(child_factory_.frame_sink_id(), + SurfaceId embedded_surface_id(child_support_->frame_sink_id(), embedded_local_surface_id); int pass_ids[] = {1, 2, 3}; @@ -672,7 +746,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) { test::Pass(embedded_quads[1], arraysize(embedded_quads[1]), pass_ids[1]), test::Pass(embedded_quads[2], arraysize(embedded_quads[2]), pass_ids[2])}; - SubmitCompositorFrame(&child_factory_, embedded_passes, + SubmitCompositorFrame(child_support_.get(), embedded_passes, arraysize(embedded_passes), embedded_local_surface_id); test::Quad root_quads[][2] = { @@ -685,10 +759,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) { test::Pass(root_quads[1], arraysize(root_quads[1]), pass_ids[1]), test::Pass(root_quads[2], arraysize(root_quads[2]), pass_ids[2])}; - SubmitCompositorFrame(&factory_, root_passes, arraysize(root_passes), + SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), root_local_surface_id_); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -800,14 +874,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) { test::Quad::SolidColorQuad(SK_ColorBLUE)}; test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; - SubmitCompositorFrame(&factory_, passes, arraysize(passes), + SubmitCompositorFrame(support_.get(), passes, arraysize(passes), root_local_surface_id_); test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), test::Quad::SolidColorQuad(SK_ColorBLUE)}; test::Pass expected_passes[] = { test::Pass(expected_quads, arraysize(expected_quads))}; - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); SurfaceId ids[] = {root_surface_id, InvalidSurfaceId()}; AggregateAndVerify( @@ -818,7 +892,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) { // should also just be dropped. TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) { LocalSurfaceId empty_local_surface_id = allocator_.GenerateId(); - SurfaceId surface_with_no_frame_id(factory_.frame_sink_id(), + SurfaceId surface_with_no_frame_id(support_->frame_sink_id(), empty_local_surface_id); test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), @@ -827,14 +901,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) { test::Quad::SolidColorQuad(SK_ColorBLUE)}; test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; - SubmitCompositorFrame(&factory_, passes, arraysize(passes), + SubmitCompositorFrame(support_.get(), passes, arraysize(passes), root_local_surface_id_); test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), test::Quad::SolidColorQuad(SK_ColorBLUE)}; test::Pass expected_passes[] = { test::Pass(expected_quads, arraysize(expected_quads))}; - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); SurfaceId ids[] = {root_surface_id, surface_with_no_frame_id}; AggregateAndVerify( expected_passes, arraysize(expected_passes), ids, arraysize(ids)); @@ -843,13 +917,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) { // Tests a surface quad referencing itself, generating a trivial cycle. // The quad creating the cycle should be dropped from the final frame. TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) { - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); test::Quad quads[] = { test::Quad::SurfaceQuad(root_surface_id, InvalidSurfaceId(), 1.f), test::Quad::SolidColorQuad(SK_ColorYELLOW)}; test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; - SubmitCompositorFrame(&factory_, passes, arraysize(passes), + SubmitCompositorFrame(support_.get(), passes, arraysize(passes), root_local_surface_id_); test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW)}; @@ -863,7 +937,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) { // Tests a more complex cycle with one intermediate surface. TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) { LocalSurfaceId child_local_surface_id = allocator_.GenerateId(); - SurfaceId child_surface_id(child_factory_.frame_sink_id(), + SurfaceId child_surface_id(child_support_->frame_sink_id(), child_local_surface_id); test::Quad parent_quads[] = { @@ -873,18 +947,18 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) { test::Pass parent_passes[] = { test::Pass(parent_quads, arraysize(parent_quads))}; - SubmitCompositorFrame(&factory_, parent_passes, arraysize(parent_passes), + SubmitCompositorFrame(support_.get(), parent_passes, arraysize(parent_passes), root_local_surface_id_); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); test::Quad child_quads[] = { test::Quad::SolidColorQuad(SK_ColorGREEN), test::Quad::SurfaceQuad(root_surface_id, InvalidSurfaceId(), 1.f), test::Quad::SolidColorQuad(SK_ColorMAGENTA)}; test::Pass child_passes[] = {test::Pass(child_quads, arraysize(child_quads))}; - SubmitCompositorFrame(&child_factory_, child_passes, arraysize(child_passes), - child_local_surface_id); + SubmitCompositorFrame(child_support_.get(), child_passes, + arraysize(child_passes), child_local_surface_id); // The child surface's reference to the root_surface_ will be dropped, so // we'll end up with: @@ -907,7 +981,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) { // namespace and update RenderPassDrawQuad's id references to match. TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) { LocalSurfaceId child_local_surface_id = allocator_.GenerateId(); - SurfaceId child_surface_id(child_factory_.frame_sink_id(), + SurfaceId child_surface_id(child_support_->frame_sink_id(), child_local_surface_id); int child_pass_id[] = {1, 2}; @@ -917,7 +991,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) { test::Pass(child_quad[0], arraysize(child_quad[0]), child_pass_id[0]), test::Pass(child_quad[1], arraysize(child_quad[1]), child_pass_id[1])}; - SubmitCompositorFrame(&child_factory_, surface_passes, + SubmitCompositorFrame(child_support_.get(), surface_passes, arraysize(surface_passes), child_local_surface_id); // Pass IDs from the parent surface may collide with ones from the child. @@ -929,10 +1003,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) { test::Pass(parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]), test::Pass(parent_quad[1], arraysize(parent_quad[1]), parent_pass_id[1])}; - SubmitCompositorFrame(&factory_, parent_passes, arraysize(parent_passes), + SubmitCompositorFrame(support_.get(), parent_passes, arraysize(parent_passes), root_local_surface_id_); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -1024,20 +1098,24 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { SkBlendMode::kSrcIn, // 5 SkBlendMode::kDstIn, // 6 }; - - SurfaceFactory grandchild_factory(FrameSinkId(2, 2), &manager_, - &empty_client_); - SurfaceFactory child_one_factory(FrameSinkId(3, 3), &manager_, - &empty_client_); - SurfaceFactory child_two_factory(FrameSinkId(4, 4), &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> grandchild_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + std::unique_ptr<CompositorFrameSinkSupport> child_one_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId2, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + std::unique_ptr<CompositorFrameSinkSupport> child_two_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId3, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); int pass_id = 1; LocalSurfaceId grandchild_local_surface_id = allocator_.GenerateId(); - SurfaceId grandchild_surface_id(grandchild_factory.frame_sink_id(), + SurfaceId grandchild_surface_id(grandchild_support->frame_sink_id(), grandchild_local_surface_id); - grandchild_factory.SubmitCompositorFrame(grandchild_local_surface_id, - CompositorFrame(), - SurfaceFactory::DrawCallback()); + grandchild_support->SubmitCompositorFrame(grandchild_local_surface_id, + CompositorFrame()); std::unique_ptr<RenderPass> grandchild_pass = RenderPass::Create(); gfx::Rect output_rect(SurfaceSize()); gfx::Rect damage_rect(SurfaceSize()); @@ -1047,14 +1125,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { AddSolidColorQuadWithBlendMode( SurfaceSize(), grandchild_pass.get(), blend_modes[2]); QueuePassAsFrame(std::move(grandchild_pass), grandchild_local_surface_id, - &grandchild_factory); + grandchild_support.get()); LocalSurfaceId child_one_local_surface_id = allocator_.GenerateId(); - SurfaceId child_one_surface_id(child_one_factory.frame_sink_id(), + SurfaceId child_one_surface_id(child_one_support->frame_sink_id(), child_one_local_surface_id); - child_one_factory.SubmitCompositorFrame(child_one_local_surface_id, - CompositorFrame(), - SurfaceFactory::DrawCallback()); + child_one_support->SubmitCompositorFrame(child_one_local_surface_id, + CompositorFrame()); std::unique_ptr<RenderPass> child_one_pass = RenderPass::Create(); child_one_pass->SetNew(pass_id, output_rect, damage_rect, @@ -1070,14 +1147,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { AddSolidColorQuadWithBlendMode( SurfaceSize(), child_one_pass.get(), blend_modes[3]); QueuePassAsFrame(std::move(child_one_pass), child_one_local_surface_id, - &child_one_factory); + child_one_support.get()); LocalSurfaceId child_two_local_surface_id = allocator_.GenerateId(); - SurfaceId child_two_surface_id(child_two_factory.frame_sink_id(), + SurfaceId child_two_surface_id(child_two_support->frame_sink_id(), child_two_local_surface_id); - child_two_factory.SubmitCompositorFrame(child_two_local_surface_id, - CompositorFrame(), - SurfaceFactory::DrawCallback()); + child_two_support->SubmitCompositorFrame(child_two_local_surface_id, + CompositorFrame()); std::unique_ptr<RenderPass> child_two_pass = RenderPass::Create(); child_two_pass->SetNew(pass_id, output_rect, damage_rect, @@ -1085,7 +1161,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { AddSolidColorQuadWithBlendMode( SurfaceSize(), child_two_pass.get(), blend_modes[5]); QueuePassAsFrame(std::move(child_two_pass), child_two_local_surface_id, - &child_two_factory); + child_two_support.get()); std::unique_ptr<RenderPass> root_pass = RenderPass::Create(); root_pass->SetNew(pass_id, output_rect, damage_rect, @@ -1110,9 +1186,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { AddSolidColorQuadWithBlendMode( SurfaceSize(), root_pass.get(), blend_modes[6]); - QueuePassAsFrame(std::move(root_pass), root_local_surface_id_, &factory_); + QueuePassAsFrame(std::move(root_pass), root_local_surface_id_, + support_.get()); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -1131,9 +1208,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { << iter.index(); } - grandchild_factory.EvictSurface(); - child_one_factory.EvictSurface(); - child_two_factory.EvictSurface(); + grandchild_support->EvictFrame(); + child_one_support->EvictFrame(); + child_two_support->EvictFrame(); } // This tests that when aggregating a frame with multiple render passes that we @@ -1155,11 +1232,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { // contributing render pass' transform in the aggregate frame should not be // affected. TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { - SurfaceFactory middle_factory(kArbitraryMiddleFrameSinkId, &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> middle_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Innermost child surface. LocalSurfaceId child_local_surface_id = allocator_.GenerateId(); - SurfaceId child_surface_id(child_factory_.frame_sink_id(), + SurfaceId child_surface_id(child_support_->frame_sink_id(), child_local_surface_id); { int child_pass_id[] = {1, 2}; @@ -1189,14 +1268,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { child_root_pass_sqs->is_clipped = true; child_root_pass_sqs->clip_rect = gfx::Rect(0, 0, 5, 5); - child_factory_.SubmitCompositorFrame(child_local_surface_id, - std::move(child_frame), - SurfaceFactory::DrawCallback()); + child_support_->SubmitCompositorFrame(child_local_surface_id, + std::move(child_frame)); } // Middle child surface. LocalSurfaceId middle_local_surface_id = allocator_.GenerateId(); - SurfaceId middle_surface_id(middle_factory.frame_sink_id(), + SurfaceId middle_surface_id(middle_support->frame_sink_id(), middle_local_surface_id); { test::Quad middle_quads[] = { @@ -1216,9 +1294,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { middle_root_pass->shared_quad_state_list.front(); middle_root_pass_sqs->quad_to_target_transform.Scale(2, 3); - middle_factory.SubmitCompositorFrame(middle_local_surface_id, - std::move(middle_frame), - SurfaceFactory::DrawCallback()); + middle_support->SubmitCompositorFrame(middle_local_surface_id, + std::move(middle_frame)); } // Root surface. @@ -1245,10 +1322,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { root_frame.render_pass_list[0]->transform_to_root_target.Translate(10, 5); - factory_.SubmitCompositorFrame(root_local_surface_id_, std::move(root_frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(root_local_surface_id_, + std::move(root_frame)); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -1321,13 +1398,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { ->shared_quad_state_list.ElementAt(1) ->clip_rect.ToString()); - middle_factory.EvictSurface(); + middle_support->EvictFrame(); } // Tests that damage rects are aggregated correctly when surfaces change. TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { - SurfaceFactory parent_factory(kArbitraryMiddleFrameSinkId, &manager_, - &empty_client_); + std::unique_ptr<CompositorFrameSinkSupport> parent_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); test::Quad child_quads[] = {test::Quad::RenderPassQuad(1)}; test::Pass child_passes[] = { test::Pass(child_quads, arraysize(child_quads), 1)}; @@ -1342,11 +1421,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { child_root_pass_sqs->quad_to_target_transform.Translate(8, 0); LocalSurfaceId child_local_surface_id = allocator_.GenerateId(); - SurfaceId child_surface_id(child_factory_.frame_sink_id(), + SurfaceId child_surface_id(child_support_->frame_sink_id(), child_local_surface_id); - child_factory_.SubmitCompositorFrame(child_local_surface_id, - std::move(child_frame), - SurfaceFactory::DrawCallback()); + child_support_->SubmitCompositorFrame(child_local_surface_id, + std::move(child_frame)); test::Quad parent_surface_quads[] = { test::Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), 1.f)}; @@ -1360,11 +1438,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { parent_surface_passes, arraysize(parent_surface_passes)); LocalSurfaceId parent_local_surface_id = allocator_.GenerateId(); - SurfaceId parent_surface_id(parent_factory.frame_sink_id(), + SurfaceId parent_surface_id(parent_support->frame_sink_id(), parent_local_surface_id); - parent_factory.SubmitCompositorFrame(parent_local_surface_id, - std::move(parent_surface_frame), - SurfaceFactory::DrawCallback()); + parent_support->SubmitCompositorFrame(parent_local_surface_id, + std::move(parent_surface_frame)); test::Quad root_surface_quads[] = { test::Quad::SurfaceQuad(parent_surface_id, InvalidSurfaceId(), 1.f)}; @@ -1384,10 +1461,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { root_frame.render_pass_list[0]->damage_rect = gfx::Rect(5, 5, 10, 10); root_frame.render_pass_list[1]->damage_rect = gfx::Rect(5, 5, 100, 100); - factory_.SubmitCompositorFrame(root_local_surface_id_, std::move(root_frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(root_local_surface_id_, + std::move(root_frame)); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -1410,11 +1487,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { child_root_pass_sqs->quad_to_target_transform.Translate(8, 0); child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10); - child_factory_.SubmitCompositorFrame(child_local_surface_id, - std::move(child_frame), - SurfaceFactory::DrawCallback()); + child_support_->SubmitCompositorFrame(child_local_surface_id, + std::move(child_frame)); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), + root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -1438,9 +1515,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { ->quad_to_target_transform.Translate(0, 10); root_frame.render_pass_list[0]->damage_rect = gfx::Rect(0, 0, 1, 1); - factory_.SubmitCompositorFrame(root_local_surface_id_, - std::move(root_frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(root_local_surface_id_, + std::move(root_frame)); } { @@ -1453,11 +1529,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { ->quad_to_target_transform.Translate(0, 10); root_frame.render_pass_list[0]->damage_rect = gfx::Rect(1, 1, 1, 1); - factory_.SubmitCompositorFrame(root_local_surface_id_, - std::move(root_frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(root_local_surface_id_, + std::move(root_frame)); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), + root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -1473,7 +1549,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { // No Surface changed, so no damage should be given. { - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), + root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -1499,7 +1576,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { gfx::Rect(SurfaceSize()))); } - parent_factory.EvictSurface(); + parent_support->EvictFrame(); } // Check that damage is correctly calculated for surfaces. @@ -1515,11 +1592,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SwitchSurfaceDamage) { root_frame.render_pass_list[0]->damage_rect = gfx::Rect(5, 5, 100, 100); - factory_.SubmitCompositorFrame(root_local_surface_id_, std::move(root_frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(root_local_surface_id_, + std::move(root_frame)); { - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), + root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -1533,7 +1611,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SwitchSurfaceDamage) { } LocalSurfaceId second_root_local_surface_id = allocator_.GenerateId(); - SurfaceId second_root_surface_id(factory_.frame_sink_id(), + SurfaceId second_root_surface_id(support_->frame_sink_id(), second_root_local_surface_id); { test::Quad root_render_pass_quads[] = {test::Quad::SolidColorQuad(1)}; @@ -1547,9 +1625,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SwitchSurfaceDamage) { root_frame.render_pass_list[0]->damage_rect = gfx::Rect(1, 2, 3, 4); - factory_.SubmitCompositorFrame(second_root_local_surface_id, - std::move(root_frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(second_root_local_surface_id, + std::move(root_frame)); } { CompositorFrame aggregated_frame = @@ -1586,7 +1663,7 @@ class SurfaceAggregatorPartialSwapTest // Tests that quads outside the damage rect are ignored. TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { LocalSurfaceId child_local_surface_id = allocator_.GenerateId(); - SurfaceId child_surface_id(child_factory_.frame_sink_id(), + SurfaceId child_surface_id(child_support_->frame_sink_id(), child_local_surface_id); // The child surface has three quads, one with a visible rect of 13,13 4x4 and // the other other with a visible rect of 10,10 2x2 (relative to root target @@ -1624,7 +1701,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { child_pass_list[2]->quad_list.ElementAt(0)->visible_rect = gfx::Rect(0, 0, 2, 2); - SubmitPassListAsFrame(&child_factory_, child_local_surface_id, + SubmitPassListAsFrame(child_support_.get(), child_local_surface_id, &child_pass_list); } @@ -1643,10 +1720,11 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { ->quad_to_target_transform.Translate(10, 10); root_pass->damage_rect = gfx::Rect(0, 0, 1, 1); - SubmitPassListAsFrame(&factory_, root_local_surface_id_, &root_pass_list); + SubmitPassListAsFrame(support_.get(), root_local_surface_id_, + &root_pass_list); } - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); const RenderPassList& aggregated_pass_list = @@ -1675,7 +1753,8 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { root_pass->shared_quad_state_list.front() ->quad_to_target_transform.Translate(10, 10); root_pass->damage_rect = gfx::Rect(10, 10, 2, 2); - SubmitPassListAsFrame(&factory_, root_local_surface_id_, &root_pass_list); + SubmitPassListAsFrame(support_.get(), root_local_surface_id_, + &root_pass_list); } { @@ -1725,7 +1804,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { child_root_pass->copy_requests.push_back( CopyOutputRequest::CreateEmptyRequest()); child_root_pass->damage_rect = gfx::Rect(); - SubmitPassListAsFrame(&child_factory_, child_local_surface_id, + SubmitPassListAsFrame(child_support_.get(), child_local_surface_id, &child_pass_list); } @@ -1785,7 +1864,8 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { RenderPass* root_pass = root_pass_list[2].get(); filter_pass->filters.Append(FilterOperation::CreateBlurFilter(2)); root_pass->damage_rect = gfx::Rect(10, 10, 2, 2); - SubmitPassListAsFrame(&factory_, root_local_surface_id_, &root_pass_list); + SubmitPassListAsFrame(support_.get(), root_local_surface_id_, + &root_pass_list); } { @@ -1833,7 +1913,8 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { ->quad_to_target_transform.Translate(10, 10); pass->background_filters.Append(FilterOperation::CreateBlurFilter(2)); root_pass->damage_rect = gfx::Rect(10, 10, 2, 2); - SubmitPassListAsFrame(&factory_, root_local_surface_id_, &root_pass_list); + SubmitPassListAsFrame(support_.get(), root_local_surface_id_, + &root_pass_list); } { @@ -1877,32 +1958,11 @@ class SurfaceAggregatorWithResourcesTest : public testing::Test { std::unique_ptr<SurfaceAggregator> aggregator_; }; -class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient { - public: - ResourceTrackingSurfaceFactoryClient() {} - ~ResourceTrackingSurfaceFactoryClient() override {} - - void ReturnResources(const ReturnedResourceArray& resources) override { - returned_resources_ = resources; - } - - ReturnedResourceArray returned_resources() const { - return returned_resources_; - } - - void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override {} - - private: - ReturnedResourceArray returned_resources_; - - DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient); -}; - void SubmitCompositorFrameWithResources(ResourceId* resource_ids, size_t num_resource_ids, bool valid, SurfaceId child_id, - SurfaceFactory* factory, + CompositorFrameSinkSupport* support, SurfaceId surface_id) { CompositorFrame frame; std::unique_ptr<RenderPass> pass = RenderPass::Create(); @@ -1941,27 +2001,29 @@ void SubmitCompositorFrameWithResources(ResourceId* resource_ids, nearest_neighbor, secure_output_only); } frame.render_pass_list.push_back(std::move(pass)); - factory->SubmitCompositorFrame(surface_id.local_surface_id(), - std::move(frame), - SurfaceFactory::DrawCallback()); + support->SubmitCompositorFrame(surface_id.local_surface_id(), + std::move(frame)); } TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) { - ResourceTrackingSurfaceFactoryClient client; - SurfaceFactory factory(kArbitraryRootFrameSinkId, &manager_, &client); + FakeCompositorFrameSinkSupportClient client; + std::unique_ptr<CompositorFrameSinkSupport> support = + CompositorFrameSinkSupport::Create( + &client, &manager_, kArbitraryRootFrameSinkId, kRootIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId local_surface_id(7u, base::UnguessableToken::Create()); - SurfaceId surface_id(factory.frame_sink_id(), local_surface_id); + SurfaceId surface_id(support->frame_sink_id(), local_surface_id); ResourceId ids[] = {11, 12, 13}; SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), - &factory, surface_id); + support.get(), surface_id); CompositorFrame frame = aggregator_->Aggregate(surface_id); // Nothing should be available to be returned yet. EXPECT_TRUE(client.returned_resources().empty()); - SubmitCompositorFrameWithResources(NULL, 0u, true, SurfaceId(), &factory, + SubmitCompositorFrameWithResources(NULL, 0u, true, SurfaceId(), support.get(), surface_id); frame = aggregator_->Aggregate(surface_id); @@ -1974,14 +2036,17 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) { EXPECT_THAT(returned_ids, testing::WhenSorted(testing::ElementsAreArray(ids))); - factory.EvictSurface(); + support->EvictFrame(); } TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) { - ResourceTrackingSurfaceFactoryClient client; - SurfaceFactory factory(kArbitraryRootFrameSinkId, &manager_, &client); + FakeCompositorFrameSinkSupportClient client; + std::unique_ptr<CompositorFrameSinkSupport> support = + CompositorFrameSinkSupport::Create( + &client, &manager_, kArbitraryRootFrameSinkId, kRootIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId local_surface_id(7u, base::UnguessableToken::Create()); - SurfaceId surface_id(factory.frame_sink_id(), local_surface_id); + SurfaceId surface_id(support->frame_sink_id(), local_surface_id); CompositorFrame frame; std::unique_ptr<RenderPass> pass = RenderPass::Create(); @@ -1993,42 +2058,47 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) { resource.is_software = false; frame.resource_list.push_back(resource); frame.render_pass_list.push_back(std::move(pass)); - factory.SubmitCompositorFrame(local_surface_id, std::move(frame), - SurfaceFactory::DrawCallback()); + support->SubmitCompositorFrame(local_surface_id, std::move(frame)); CompositorFrame returned_frame = aggregator_->Aggregate(surface_id); // Nothing should be available to be returned yet. EXPECT_TRUE(client.returned_resources().empty()); - SubmitCompositorFrameWithResources(NULL, 0, true, SurfaceId(), &factory, + SubmitCompositorFrameWithResources(NULL, 0, true, SurfaceId(), support.get(), surface_id); ASSERT_EQ(1u, client.returned_resources().size()); EXPECT_EQ(11u, client.returned_resources()[0].id); - factory.EvictSurface(); + support->EvictFrame(); } TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) { - ResourceTrackingSurfaceFactoryClient client; - SurfaceFactory factory1(FrameSinkId(1, 1), &manager_, &client); - SurfaceFactory factory2(FrameSinkId(2, 2), &manager_, &client); + FakeCompositorFrameSinkSupportClient client; + std::unique_ptr<CompositorFrameSinkSupport> support1 = + CompositorFrameSinkSupport::Create( + &client, &manager_, FrameSinkId(1, 1), kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + std::unique_ptr<CompositorFrameSinkSupport> support2 = + CompositorFrameSinkSupport::Create( + &client, &manager_, FrameSinkId(2, 2), kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId local_frame1_id(7u, base::UnguessableToken::Create()); - SurfaceId surface1_id(factory1.frame_sink_id(), local_frame1_id); + SurfaceId surface1_id(support1->frame_sink_id(), local_frame1_id); LocalSurfaceId local_frame2_id(8u, base::UnguessableToken::Create()); - SurfaceId surface2_id(factory2.frame_sink_id(), local_frame2_id); + SurfaceId surface2_id(support2->frame_sink_id(), local_frame2_id); ResourceId ids[] = {11, 12, 13}; SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), - &factory1, surface1_id); + support1.get(), surface1_id); ResourceId ids2[] = {14, 15, 16}; SubmitCompositorFrameWithResources(ids2, arraysize(ids2), true, SurfaceId(), - &factory2, surface2_id); + support2.get(), surface2_id); CompositorFrame frame = aggregator_->Aggregate(surface1_id); - SubmitCompositorFrameWithResources(NULL, 0, true, SurfaceId(), &factory1, + SubmitCompositorFrameWithResources(NULL, 0, true, SurfaceId(), support1.get(), surface1_id); // Nothing should be available to be returned yet. @@ -2046,40 +2116,47 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) { testing::WhenSorted(testing::ElementsAreArray(ids))); EXPECT_EQ(3u, resource_provider_->num_resources()); - factory1.EvictSurface(); - factory2.EvictSurface(); + support1->EvictFrame(); + support2->EvictFrame(); } // Ensure that aggregator completely ignores Surfaces that reference invalid // resources. TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) { - ResourceTrackingSurfaceFactoryClient client; - SurfaceFactory root_factory(kArbitraryRootFrameSinkId, &manager_, &client); - SurfaceFactory middle_factory(kArbitraryMiddleFrameSinkId, &manager_, - &client); - SurfaceFactory child_factory(kArbitraryChildFrameSinkId1, &manager_, &client); + std::unique_ptr<CompositorFrameSinkSupport> root_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryRootFrameSinkId, kRootIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + std::unique_ptr<CompositorFrameSinkSupport> middle_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + std::unique_ptr<CompositorFrameSinkSupport> child_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId root_local_surface_id(7u, kArbitraryToken); - SurfaceId root_surface_id(root_factory.frame_sink_id(), + SurfaceId root_surface_id(root_support->frame_sink_id(), root_local_surface_id); LocalSurfaceId middle_local_surface_id(8u, kArbitraryToken); - SurfaceId middle_surface_id(middle_factory.frame_sink_id(), + SurfaceId middle_surface_id(middle_support->frame_sink_id(), middle_local_surface_id); LocalSurfaceId child_local_surface_id(9u, kArbitraryToken); - SurfaceId child_surface_id(child_factory.frame_sink_id(), + SurfaceId child_surface_id(child_support->frame_sink_id(), child_local_surface_id); ResourceId ids[] = {14, 15, 16}; SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), - &child_factory, child_surface_id); + child_support.get(), child_surface_id); ResourceId ids2[] = {17, 18, 19}; SubmitCompositorFrameWithResources(ids2, arraysize(ids2), false, - child_surface_id, &middle_factory, + child_surface_id, middle_support.get(), middle_surface_id); ResourceId ids3[] = {20, 21, 22}; SubmitCompositorFrameWithResources(ids3, arraysize(ids3), true, - middle_surface_id, &root_factory, + middle_surface_id, root_support.get(), root_surface_id); CompositorFrame frame; @@ -2090,7 +2167,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) { EXPECT_EQ(1u, pass_list->back()->shared_quad_state_list.size()); EXPECT_EQ(3u, pass_list->back()->quad_list.size()); SubmitCompositorFrameWithResources(ids2, arraysize(ids), true, - child_surface_id, &middle_factory, + child_surface_id, middle_support.get(), middle_surface_id); frame = aggregator_->Aggregate(root_surface_id); @@ -2100,24 +2177,29 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) { EXPECT_EQ(3u, pass_list->back()->shared_quad_state_list.size()); EXPECT_EQ(9u, pass_list->back()->quad_list.size()); - root_factory.EvictSurface(); - middle_factory.EvictSurface(); - child_factory.EvictSurface(); + root_support->EvictFrame(); + middle_support->EvictFrame(); + child_support->EvictFrame(); } TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) { - ResourceTrackingSurfaceFactoryClient client; - SurfaceFactory factory1(FrameSinkId(1, 1), &manager_, &client); - SurfaceFactory factory2(FrameSinkId(2, 2), &manager_, &client); + std::unique_ptr<CompositorFrameSinkSupport> support1 = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, FrameSinkId(1, 1), kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + std::unique_ptr<CompositorFrameSinkSupport> support2 = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, FrameSinkId(2, 2), kChildIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId local_frame1_id(7u, base::UnguessableToken::Create()); - SurfaceId surface1_id(factory1.frame_sink_id(), local_frame1_id); + SurfaceId surface1_id(support1->frame_sink_id(), local_frame1_id); LocalSurfaceId local_frame2_id(8u, base::UnguessableToken::Create()); - SurfaceId surface2_id(factory2.frame_sink_id(), local_frame2_id); + SurfaceId surface2_id(support2->frame_sink_id(), local_frame2_id); ResourceId ids[] = {11, 12, 13}; SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), - &factory1, surface1_id); + support1.get(), surface1_id); CompositorFrame frame = aggregator_->Aggregate(surface1_id); @@ -2140,8 +2222,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) { CompositorFrame frame; frame.render_pass_list.push_back(std::move(pass)); - factory2.SubmitCompositorFrame(local_frame2_id, std::move(frame), - SurfaceFactory::DrawCallback()); + support2->SubmitCompositorFrame(local_frame2_id, std::move(frame)); } frame = aggregator_->Aggregate(surface2_id); @@ -2167,8 +2248,8 @@ TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) { // Output is insecure, so texture should be drawn. EXPECT_EQ(DrawQuad::SOLID_COLOR, render_pass->quad_list.back()->material); - factory1.EvictSurface(); - factory2.EvictSurface(); + support1->EvictFrame(); + support2->EvictFrame(); } // Ensure that the render passes have correct color spaces. @@ -2181,24 +2262,32 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ColorSpaceTest) { test::Pass(quads[1], arraysize(quads[1]), 1)}; gfx::ColorSpace color_space1 = gfx::ColorSpace::CreateXYZD50(); gfx::ColorSpace color_space2 = gfx::ColorSpace::CreateSRGB(); + gfx::ColorSpace color_space3 = gfx::ColorSpace::CreateSCRGBLinear(); - SubmitCompositorFrame(&factory_, passes, arraysize(passes), + SubmitCompositorFrame(support_.get(), passes, arraysize(passes), root_local_surface_id_); - SurfaceId surface_id(factory_.frame_sink_id(), root_local_surface_id_); + SurfaceId surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame; - aggregator_.SetOutputColorSpace(color_space1); + aggregator_.SetOutputColorSpace(color_space1, color_space1); aggregated_frame = aggregator_.Aggregate(surface_id); EXPECT_EQ(2u, aggregated_frame.render_pass_list.size()); EXPECT_EQ(color_space1, aggregated_frame.render_pass_list[0]->color_space); EXPECT_EQ(color_space1, aggregated_frame.render_pass_list[1]->color_space); - aggregator_.SetOutputColorSpace(color_space2); + aggregator_.SetOutputColorSpace(color_space2, color_space2); aggregated_frame = aggregator_.Aggregate(surface_id); EXPECT_EQ(2u, aggregated_frame.render_pass_list.size()); EXPECT_EQ(color_space2, aggregated_frame.render_pass_list[0]->color_space); EXPECT_EQ(color_space2, aggregated_frame.render_pass_list[1]->color_space); + + aggregator_.SetOutputColorSpace(color_space1, color_space3); + aggregated_frame = aggregator_.Aggregate(surface_id); + EXPECT_EQ(3u, aggregated_frame.render_pass_list.size()); + EXPECT_EQ(color_space1, aggregated_frame.render_pass_list[0]->color_space); + EXPECT_EQ(color_space1, aggregated_frame.render_pass_list[1]->color_space); + EXPECT_EQ(color_space3, aggregated_frame.render_pass_list[2]->color_space); } } // namespace diff --git a/chromium/cc/surfaces/surface_dependency_tracker.cc b/chromium/cc/surfaces/surface_dependency_tracker.cc index 6cfeae8ec2b..89eaf14fe0e 100644 --- a/chromium/cc/surfaces/surface_dependency_tracker.cc +++ b/chromium/cc/surfaces/surface_dependency_tracker.cc @@ -26,33 +26,42 @@ SurfaceDependencyTracker::SurfaceDependencyTracker( SurfaceDependencyTracker::~SurfaceDependencyTracker() { surface_manager_->RemoveObserver(this); begin_frame_source_->RemoveObserver(this); - for (Surface* pending_surface : pending_surfaces_) - pending_surface->RemoveObserver(this); - pending_surfaces_.clear(); + for (const SurfaceId& surface_id : observed_surfaces_by_id_) { + Surface* observed_surface = surface_manager_->GetSurfaceForId(surface_id); + DCHECK(observed_surface); + observed_surface->RemoveObserver(this); + } + observed_surfaces_by_id_.clear(); } void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) { DCHECK(surface->HasPendingFrame()); const CompositorFrame& pending_frame = surface->GetPendingFrame(); - bool needs_begin_frame = - pending_frame.metadata.can_activate_before_dependencies; + bool needs_deadline = pending_frame.metadata.can_activate_before_dependencies; + + auto late_it = late_surfaces_by_id_.find(surface->surface_id()); + if (needs_deadline && late_it != late_surfaces_by_id_.end()) { + late_surfaces_by_id_.erase(late_it); + surface->ActivatePendingFrameForDeadline(); + return; + } // Referenced surface IDs that aren't currently known to the surface manager // or do not have an active CompsotiorFrame block this frame. - for (const SurfaceId& surface_id : - pending_frame.metadata.referenced_surfaces) { + for (const SurfaceId& surface_id : pending_frame.metadata.embedded_surfaces) { Surface* surface_dependency = surface_manager_->GetSurfaceForId(surface_id); if (!surface_dependency || !surface_dependency->HasActiveFrame()) - blocked_surfaces_[surface_id].insert(surface); + blocked_surfaces_from_dependency_[surface_id].insert( + surface->surface_id()); } - if (!pending_surfaces_.count(surface)) { + if (!observed_surfaces_by_id_.count(surface->surface_id())) { surface->AddObserver(this); - pending_surfaces_.insert(surface); + observed_surfaces_by_id_.insert(surface->surface_id()); } - if (needs_begin_frame && !frames_since_deadline_set_) + if (needs_deadline && !frames_since_deadline_set_) frames_since_deadline_set_ = 0; } @@ -70,10 +79,32 @@ void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) { if (++(*frames_since_deadline_set_) != kMaxBeginFrameCount) return; + late_surfaces_by_id_.clear(); + // Activate all surfaces that respect the deadline. - PendingSurfaceSet pending_surfaces(pending_surfaces_); - for (Surface* pending_surface : pending_surfaces) - pending_surface->ActivatePendingFrameForDeadline(); + // Copy the set of blocked surfaces here because that set can mutate as we + // activate CompositorFrames: an activation can trigger further activations + // which will remove elements from |observed_surfaces_by_id_|. This + // invalidates the iterator. + base::flat_set<SurfaceId> blocked_surfaces_by_id(observed_surfaces_by_id_); + for (const SurfaceId& surface_id : blocked_surfaces_by_id) { + Surface* blocked_surface = surface_manager_->GetSurfaceForId(surface_id); + if (!blocked_surface) { + // A blocked surface may have been garbage collected during dependency + // resolution. + DCHECK(!observed_surfaces_by_id_.count(surface_id)); + continue; + } + // Clear all tracked blockers for |blocked_surface|. + for (const SurfaceId& blocking_surface_id : + blocked_surface->blocking_surfaces()) { + // If we are not activating this blocker now, then it's late. + if (!blocked_surfaces_by_id.count(blocking_surface_id)) + late_surfaces_by_id_.insert(blocking_surface_id); + blocked_surfaces_from_dependency_[blocking_surface_id].erase(surface_id); + } + blocked_surface->ActivatePendingFrameForDeadline(); + } frames_since_deadline_set_.reset(); } @@ -84,11 +115,6 @@ const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const { void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {} -void SurfaceDependencyTracker::OnReferencedSurfacesChanged( - Surface* surface, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces) {} - void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { // If the surface being destroyed doesn't have a pending frame then we have // nothing to do here. @@ -97,27 +123,27 @@ void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { const CompositorFrame& pending_frame = surface->GetPendingFrame(); - DCHECK(!pending_frame.metadata.referenced_surfaces.empty()); + DCHECK(!pending_frame.metadata.embedded_surfaces.empty()); - for (const SurfaceId& surface_id : - pending_frame.metadata.referenced_surfaces) { - auto it = blocked_surfaces_.find(surface_id); - if (it == blocked_surfaces_.end()) + for (const SurfaceId& surface_id : pending_frame.metadata.embedded_surfaces) { + auto it = blocked_surfaces_from_dependency_.find(surface_id); + if (it == blocked_surfaces_from_dependency_.end()) continue; - auto& pending_surface_set = it->second; - auto pending_surface_it = pending_surface_set.find(surface); - if (pending_surface_it != pending_surface_set.end()) { - pending_surface_set.erase(surface); - if (pending_surface_set.empty()) - blocked_surfaces_.erase(surface_id); + auto& blocked_surface_ids = it->second; + auto blocked_surface_ids_it = + blocked_surface_ids.find(surface->surface_id()); + if (blocked_surface_ids_it != blocked_surface_ids.end()) { + blocked_surface_ids.erase(surface->surface_id()); + if (blocked_surface_ids.empty()) + blocked_surfaces_from_dependency_.erase(surface_id); } } - if (blocked_surfaces_.empty()) + if (blocked_surfaces_from_dependency_.empty()) frames_since_deadline_set_.reset(); - pending_surfaces_.erase(surface); + observed_surfaces_by_id_.erase(surface->surface_id()); surface->RemoveObserver(this); // Pretend that the discarded surface's SurfaceId is now available to unblock @@ -127,7 +153,7 @@ void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { surface->RemoveObserver(this); - pending_surfaces_.erase(surface); + observed_surfaces_by_id_.erase(surface->surface_id()); NotifySurfaceIdAvailable(surface->surface_id()); } @@ -135,20 +161,21 @@ void SurfaceDependencyTracker::OnSurfaceDependenciesChanged( Surface* surface, const SurfaceDependencies& added_dependencies, const SurfaceDependencies& removed_dependencies) { - // Update the |blocked_surfaces_| map with the changes in dependencies. + // Update the |blocked_surfaces_from_dependency_| map with the changes in + // dependencies. for (const SurfaceId& surface_id : added_dependencies) - blocked_surfaces_[surface_id].insert(surface); + blocked_surfaces_from_dependency_[surface_id].insert(surface->surface_id()); for (const SurfaceId& surface_id : removed_dependencies) { - auto it = blocked_surfaces_.find(surface_id); - it->second.erase(surface); + auto it = blocked_surfaces_from_dependency_.find(surface_id); + it->second.erase(surface->surface_id()); if (it->second.empty()) - blocked_surfaces_.erase(it); + blocked_surfaces_from_dependency_.erase(it); } // If there are no more dependencies to resolve then we don't need to have a // deadline. - if (blocked_surfaces_.empty()) + if (blocked_surfaces_from_dependency_.empty()) frames_since_deadline_set_.reset(); } @@ -167,21 +194,30 @@ void SurfaceDependencyTracker::OnSurfaceDamaged(const SurfaceId& surface_id, void SurfaceDependencyTracker::NotifySurfaceIdAvailable( const SurfaceId& surface_id) { - auto it = blocked_surfaces_.find(surface_id); - if (it == blocked_surfaces_.end()) + auto it = blocked_surfaces_from_dependency_.find(surface_id); + if (it == blocked_surfaces_from_dependency_.end()) return; // Unblock surfaces that depend on this |surface_id|. - PendingSurfaceSet blocked_pending_surface_set(it->second); - blocked_surfaces_.erase(it); + base::flat_set<SurfaceId> blocked_surfaces_by_id(it->second); + blocked_surfaces_from_dependency_.erase(it); // If there are no more blockers in the system, then we no longer need to // have a deadline. - if (blocked_surfaces_.empty()) + if (blocked_surfaces_from_dependency_.empty()) frames_since_deadline_set_.reset(); // Tell each surface about the availability of its blocker. - for (Surface* blocked_pending_surface : blocked_pending_surface_set) - blocked_pending_surface->NotifySurfaceIdAvailable(surface_id); + for (const SurfaceId& blocked_surface_by_id : blocked_surfaces_by_id) { + Surface* blocked_surface = + surface_manager_->GetSurfaceForId(blocked_surface_by_id); + if (!blocked_surface) { + // A blocked surface may have been garbage collected during dependency + // resolution. + DCHECK(!observed_surfaces_by_id_.count(blocked_surface_by_id)); + continue; + } + blocked_surface->NotifySurfaceIdAvailable(surface_id); + } } } // namespace cc diff --git a/chromium/cc/surfaces/surface_dependency_tracker.h b/chromium/cc/surfaces/surface_dependency_tracker.h index 193eb31a22f..bdb8717fd06 100644 --- a/chromium/cc/surfaces/surface_dependency_tracker.h +++ b/chromium/cc/surfaces/surface_dependency_tracker.h @@ -50,10 +50,6 @@ class CC_SURFACES_EXPORT SurfaceDependencyTracker : public BeginFrameObserver, void OnBeginFrameSourcePausedChanged(bool paused) override; // PendingFrameObserver implementation: - void OnReferencedSurfacesChanged( - Surface* surface, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces) override; void OnSurfaceActivated(Surface* surface) override; void OnSurfaceDependenciesChanged( Surface* surface, @@ -84,10 +80,16 @@ class CC_SURFACES_EXPORT SurfaceDependencyTracker : public BeginFrameObserver, base::Optional<uint32_t> frames_since_deadline_set_; // A map from a SurfaceId to the set of Surfaces blocked on that SurfaceId. - std::unordered_map<SurfaceId, PendingSurfaceSet, SurfaceIdHash> - blocked_surfaces_; + std::unordered_map<SurfaceId, base::flat_set<SurfaceId>, SurfaceIdHash> + blocked_surfaces_from_dependency_; + + // The set of SurfaceIds corresponding to observed Surfaces that have + // blockers. + base::flat_set<SurfaceId> observed_surfaces_by_id_; - PendingSurfaceSet pending_surfaces_; + // The set of SurfaceIds to which corresponding CompositorFrames have not + // arrived by the time their deadline fired. + base::flat_set<SurfaceId> late_surfaces_by_id_; DISALLOW_COPY_AND_ASSIGN(SurfaceDependencyTracker); }; diff --git a/chromium/cc/surfaces/surface_factory.cc b/chromium/cc/surfaces/surface_factory.cc index f641274fd60..f6a6e0ec0f2 100644 --- a/chromium/cc/surfaces/surface_factory.cc +++ b/chromium/cc/surfaces/surface_factory.cc @@ -41,14 +41,6 @@ void SurfaceFactory::EvictSurface() { Destroy(std::move(current_surface_)); } -void SurfaceFactory::Reset() { - EvictSurface(); - // Disown Surfaces that are still alive so that they don't try to unref - // resources that we're not tracking any more. - weak_factory_.InvalidateWeakPtrs(); - holder_.Reset(); -} - void SurfaceFactory::SubmitCompositorFrame( const LocalSurfaceId& local_surface_id, CompositorFrame frame, @@ -113,32 +105,26 @@ void SurfaceFactory::UnrefResources(const ReturnedResourceArray& resources) { holder_.UnrefResources(resources); } -void SurfaceFactory::OnReferencedSurfacesChanged( - Surface* surface, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces) { - client_->ReferencedSurfacesChanged(surface->surface_id().local_surface_id(), - active_referenced_surfaces, - pending_referenced_surfaces); -} - void SurfaceFactory::OnSurfaceActivated(Surface* surface) { DCHECK(surface->HasActiveFrame()); - if (seen_first_frame_activation_) - return; - - seen_first_frame_activation_ = true; - - const CompositorFrame& frame = surface->GetActiveFrame(); - // CompositorFrames might not be populated with a RenderPass in unit tests. - gfx::Size frame_size; - if (!frame.render_pass_list.empty()) - frame_size = frame.render_pass_list.back()->output_rect.size(); - - // SurfaceCreated only applies for the first Surface activation. Thus, - // SurfaceFactory stops observing new activations after the first one. - manager_->SurfaceCreated(SurfaceInfo( - surface->surface_id(), frame.metadata.device_scale_factor, frame_size)); + if (!seen_first_frame_activation_) { + seen_first_frame_activation_ = true; + + const CompositorFrame& frame = surface->GetActiveFrame(); + // CompositorFrames might not be populated with a RenderPass in unit tests. + gfx::Size frame_size; + if (!frame.render_pass_list.empty()) + frame_size = frame.render_pass_list.back()->output_rect.size(); + + // SurfaceCreated only applies for the first Surface activation. Thus, + // SurfaceFactory stops observing new activations after the first one. + manager_->SurfaceCreated(SurfaceInfo( + surface->surface_id(), frame.metadata.device_scale_factor, frame_size)); + } + // Fire SurfaceCreated first so that a temporary reference is added before it + // is potentially transformed into a real reference by the client. + client_->ReferencedSurfacesChanged(surface->surface_id().local_surface_id(), + surface->active_referenced_surfaces()); } void SurfaceFactory::OnSurfaceDependenciesChanged( @@ -150,17 +136,16 @@ void SurfaceFactory::OnSurfaceDiscarded(Surface* surface) {} std::unique_ptr<Surface> SurfaceFactory::Create( const LocalSurfaceId& local_surface_id) { - auto surface = base::MakeUnique<Surface>( - SurfaceId(frame_sink_id_, local_surface_id), weak_factory_.GetWeakPtr()); seen_first_frame_activation_ = false; - manager_->RegisterSurface(surface.get()); + std::unique_ptr<Surface> surface = + manager_->CreateSurface(weak_factory_.GetWeakPtr(), local_surface_id); surface->AddObserver(this); return surface; } void SurfaceFactory::Destroy(std::unique_ptr<Surface> surface) { surface->RemoveObserver(this); - manager_->Destroy(std::move(surface)); + manager_->DestroySurface(std::move(surface)); } } // namespace cc diff --git a/chromium/cc/surfaces/surface_factory.h b/chromium/cc/surfaces/surface_factory.h index 911c044f33c..29b3e488ab4 100644 --- a/chromium/cc/surfaces/surface_factory.h +++ b/chromium/cc/surfaces/surface_factory.h @@ -50,10 +50,6 @@ class CC_SURFACES_EXPORT SurfaceFactory : public PendingFrameObserver { // the old surface will be dealt with). void EvictSurface(); - // Destroys and disowns the current surface, and resets all resource - // references. This is useful when resources are invalid (e.g. lost context). - void Reset(); - // Submits the frame to the current surface being managed by the factory if // the local frame ids match, or creates a new surface with the given local // frame id, destroys the old one, and submits the frame to this new surface. @@ -89,10 +85,6 @@ class CC_SURFACES_EXPORT SurfaceFactory : public PendingFrameObserver { private: // PendingFrameObserver implementation. - void OnReferencedSurfacesChanged( - Surface* surface, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces) override; void OnSurfaceActivated(Surface* surface) override; void OnSurfaceDependenciesChanged( Surface* surface, diff --git a/chromium/cc/surfaces/surface_factory_client.h b/chromium/cc/surfaces/surface_factory_client.h index ea32344afcd..57ecfed1104 100644 --- a/chromium/cc/surfaces/surface_factory_client.h +++ b/chromium/cc/surfaces/surface_factory_client.h @@ -21,8 +21,7 @@ class CC_SURFACES_EXPORT SurfaceFactoryClient { virtual void ReferencedSurfacesChanged( const LocalSurfaceId& local_surface_id, - const std::vector<SurfaceId>* active_referenced_surfaces, - const std::vector<SurfaceId>* pending_referenced_surfaces) {} + const std::vector<SurfaceId>* active_referenced_surfaces) {} virtual void ReturnResources(const ReturnedResourceArray& resources) = 0; diff --git a/chromium/cc/surfaces/surface_factory_unittest.cc b/chromium/cc/surfaces/surface_factory_unittest.cc index 96398d1dc19..0e445dd8caf 100644 --- a/chromium/cc/surfaces/surface_factory_unittest.cc +++ b/chromium/cc/surfaces/surface_factory_unittest.cc @@ -184,8 +184,8 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) { EXPECT_EQ(0u, client_.returned_resources().size()); client_.clear_returned_resources(); - // The second frame references no resources and thus should make all resources - // available to be returned. + // The second frame references no resources of first frame and thus should + // make all resources of first frame available to be returned. SubmitCompositorFrameWithResources(NULL, 0); ResourceId expected_returned_ids[] = {1, 2, 3}; @@ -194,6 +194,29 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) { CheckReturnedResourcesMatchExpected( expected_returned_ids, expected_returned_counts, arraysize(expected_returned_counts), gpu::SyncToken()); + + ResourceId third_frame_ids[] = {4, 5, 6}; + SubmitCompositorFrameWithResources(third_frame_ids, + arraysize(third_frame_ids)); + + // All of the resources submitted in the third frame are still in use at this + // time by virtue of being in the pending frame, so none can be returned to + // the client yet. + EXPECT_EQ(0u, client_.returned_resources().size()); + client_.clear_returned_resources(); + + // The forth frame references no resources of third frame and thus should + // make all resources of third frame available to be returned. + ResourceId forth_frame_ids[] = {7, 8, 9}; + SubmitCompositorFrameWithResources(forth_frame_ids, + arraysize(forth_frame_ids)); + + ResourceId forth_expected_returned_ids[] = {4, 5, 6}; + int forth_expected_returned_counts[] = {1, 1, 1}; + // Resources were never consumed so no sync token should be set. + CheckReturnedResourcesMatchExpected( + forth_expected_returned_ids, forth_expected_returned_counts, + arraysize(forth_expected_returned_counts), gpu::SyncToken()); } // Tests submitting a frame with resources followed by one with no resources @@ -561,86 +584,6 @@ TEST_F(SurfaceFactoryTest, EvictSurfaceDependencyRegistered) { EXPECT_FALSE(client_.returned_resources().empty()); } -// Tests that SurfaceFactory returns resources after Reset(). -TEST_F(SurfaceFactoryTest, Reset) { - LocalSurfaceId id(7, kArbitraryToken); - - TransferableResource resource; - resource.id = 1; - resource.mailbox_holder.texture_target = GL_TEXTURE_2D; - CompositorFrame frame; - frame.resource_list.push_back(resource); - factory_->SubmitCompositorFrame(id, std::move(frame), - SurfaceFactory::DrawCallback()); - EXPECT_EQ(last_created_surface_id().local_surface_id(), id); - - SurfaceId surface_id(kArbitraryFrameSinkId, id); - EXPECT_TRUE(manager_.GetSurfaceForId(surface_id)); - EXPECT_TRUE(client_.returned_resources().empty()); - factory_->Reset(); - EXPECT_FALSE(manager_.GetSurfaceForId(surface_id)); - EXPECT_FALSE(client_.returned_resources().empty()); - local_surface_id_ = LocalSurfaceId(); -} - -// Tests that SurfaceFactory returns resources after Reset() if dependency -// unregistered. -TEST_F(SurfaceFactoryTest, ResetDependenceUnRegistered) { - LocalSurfaceId id(7, kArbitraryToken); - - TransferableResource resource; - resource.id = 1; - resource.mailbox_holder.texture_target = GL_TEXTURE_2D; - CompositorFrame frame; - frame.resource_list.push_back(resource); - factory_->SubmitCompositorFrame(id, std::move(frame), - SurfaceFactory::DrawCallback()); - EXPECT_EQ(last_created_surface_id().local_surface_id(), id); - - SurfaceId surface_id(kArbitraryFrameSinkId, id); - Surface* surface = manager_.GetSurfaceForId(surface_id); - surface->AddDestructionDependency( - SurfaceSequence(kAnotherArbitraryFrameSinkId, 4)); - EXPECT_TRUE(manager_.GetSurfaceForId(surface_id)); - EXPECT_TRUE(client_.returned_resources().empty()); - factory_->Reset(); - EXPECT_FALSE(manager_.GetSurfaceForId(surface_id)); - EXPECT_FALSE(client_.returned_resources().empty()); - local_surface_id_ = LocalSurfaceId(); -} - -// Tests that SurfaceFactory doesn't return resources after Reset() if -// dependency registered. -TEST_F(SurfaceFactoryTest, ResetDependencyRegistered) { - LocalSurfaceId id(7, kArbitraryToken); - - TransferableResource resource; - resource.id = 1; - resource.mailbox_holder.texture_target = GL_TEXTURE_2D; - CompositorFrame frame; - frame.resource_list.push_back(resource); - factory_->SubmitCompositorFrame(id, std::move(frame), - SurfaceFactory::DrawCallback()); - EXPECT_EQ(last_created_surface_id().local_surface_id(), id); - - manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId); - - SurfaceId surface_id(kArbitraryFrameSinkId, id); - Surface* surface = manager_.GetSurfaceForId(surface_id); - surface->AddDestructionDependency( - SurfaceSequence(kAnotherArbitraryFrameSinkId, 4)); - EXPECT_TRUE(manager_.GetSurfaceForId(surface_id)); - EXPECT_TRUE(client_.returned_resources().empty()); - factory_->Reset(); - EXPECT_TRUE(manager_.GetSurfaceForId(surface_id)); - EXPECT_TRUE(client_.returned_resources().empty()); - - manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4)); - EXPECT_FALSE(manager_.GetSurfaceForId(surface_id)); - EXPECT_TRUE(client_.returned_resources().empty()); - local_surface_id_ = LocalSurfaceId(); -} - TEST_F(SurfaceFactoryTest, DestroySequence) { LocalSurfaceId local_surface_id2(5, kArbitraryToken); std::unique_ptr<SurfaceFactory> factory2( diff --git a/chromium/cc/surfaces/surface_hittest_unittest.cc b/chromium/cc/surfaces/surface_hittest_unittest.cc index fc27635c231..312a7ae9b50 100644 --- a/chromium/cc/surfaces/surface_hittest_unittest.cc +++ b/chromium/cc/surfaces/surface_hittest_unittest.cc @@ -5,10 +5,9 @@ #include <stddef.h> #include "cc/output/compositor_frame.h" +#include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" -#include "cc/surfaces/surface_factory.h" -#include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_hittest.h" #include "cc/surfaces/surface_manager.h" #include "cc/test/surface_hittest_test_helpers.h" @@ -20,7 +19,11 @@ namespace cc { namespace { -static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1); +constexpr FrameSinkId kArbitraryFrameSinkId(1, 1); +constexpr bool kIsRoot = true; +constexpr bool kIsChildRoot = false; +constexpr bool kHandlesFrameSinkIdInvalidation = true; +constexpr bool kNeedsSyncPoints = true; struct TestCase { SurfaceId input_surface_id; @@ -62,9 +65,11 @@ using namespace test; // not crash. TEST(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) { SurfaceManager manager; - EmptySurfaceFactoryClient client; FrameSinkId root_frame_sink_id(kArbitraryFrameSinkId); - SurfaceFactory root_factory(root_frame_sink_id, &manager, &client); + std::unique_ptr<CompositorFrameSinkSupport> root_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, kArbitraryFrameSinkId, kIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Creates a root surface. gfx::Rect root_rect(300, 300); @@ -86,9 +91,8 @@ TEST(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) { LocalSurfaceIdAllocator root_allocator; LocalSurfaceId root_local_surface_id = root_allocator.GenerateId(); SurfaceId root_surface_id(root_frame_sink_id, root_local_surface_id); - root_factory.SubmitCompositorFrame(root_local_surface_id, - std::move(root_frame), - SurfaceFactory::DrawCallback()); + root_support->SubmitCompositorFrame(root_local_surface_id, + std::move(root_frame)); { SurfaceHittest hittest(nullptr, &manager); @@ -99,16 +103,18 @@ TEST(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) { root_surface_id, gfx::Point(100, 100), &transform)); } - root_factory.EvictSurface(); + root_support->EvictFrame(); } TEST(SurfaceHittestTest, Hittest_SingleSurface) { SurfaceManager manager; // Set up root FrameSink. - EmptySurfaceFactoryClient root_client; FrameSinkId root_frame_sink_id(1, 1); - SurfaceFactory root_factory(root_frame_sink_id, &manager, &root_client); + std::unique_ptr<CompositorFrameSinkSupport> root_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, root_frame_sink_id, kIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Creates a root surface. gfx::Rect root_rect(300, 300); @@ -119,9 +125,8 @@ TEST(SurfaceHittestTest, Hittest_SingleSurface) { LocalSurfaceIdAllocator root_allocator; LocalSurfaceId root_local_surface_id = root_allocator.GenerateId(); SurfaceId root_surface_id(root_frame_sink_id, root_local_surface_id); - root_factory.SubmitCompositorFrame(root_local_surface_id, - std::move(root_frame), - SurfaceFactory::DrawCallback()); + root_support->SubmitCompositorFrame(root_local_surface_id, + std::move(root_frame)); TestCase tests[] = { { root_surface_id, @@ -133,21 +138,25 @@ TEST(SurfaceHittestTest, Hittest_SingleSurface) { RunTests(nullptr, &manager, tests, arraysize(tests)); - root_factory.EvictSurface(); + root_support->EvictFrame(); } TEST(SurfaceHittestTest, Hittest_ChildSurface) { SurfaceManager manager; // Set up root FrameSink. - EmptySurfaceFactoryClient root_client; FrameSinkId root_frame_sink_id(1, 1); - SurfaceFactory root_factory(root_frame_sink_id, &manager, &root_client); + std::unique_ptr<CompositorFrameSinkSupport> root_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, root_frame_sink_id, kIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Set up child FrameSink. - EmptySurfaceFactoryClient child_client; FrameSinkId child_frame_sink_id(2, 2); - SurfaceFactory child_factory(child_frame_sink_id, &manager, &child_client); + std::unique_ptr<CompositorFrameSinkSupport> child_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, child_frame_sink_id, kIsChildRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Creates a root surface. gfx::Rect root_rect(300, 300); @@ -172,9 +181,8 @@ TEST(SurfaceHittestTest, Hittest_ChildSurface) { LocalSurfaceIdAllocator root_allocator; LocalSurfaceId root_local_surface_id = root_allocator.GenerateId(); SurfaceId root_surface_id(root_frame_sink_id, root_local_surface_id); - root_factory.SubmitCompositorFrame(root_local_surface_id, - std::move(root_frame), - SurfaceFactory::DrawCallback()); + root_support->SubmitCompositorFrame(root_local_surface_id, + std::move(root_frame)); // Creates a child surface. RenderPass* child_pass = nullptr; @@ -191,9 +199,8 @@ TEST(SurfaceHittestTest, Hittest_ChildSurface) { root_rect, child_solid_quad_rect); // Submit the frame. - child_factory.SubmitCompositorFrame(child_local_surface_id, - std::move(child_frame), - SurfaceFactory::DrawCallback()); + child_support->SubmitCompositorFrame(child_local_surface_id, + std::move(child_frame)); TestCase tests[] = { { @@ -246,9 +253,8 @@ TEST(SurfaceHittestTest, Hittest_ChildSurface) { root_rect, child_rect, child_surface_id); - root_factory.SubmitCompositorFrame(root_local_surface_id, - std::move(root_frame), - SurfaceFactory::DrawCallback()); + root_support->SubmitCompositorFrame(root_local_surface_id, + std::move(root_frame)); // Verify that point (100, 100) no longer falls on the child surface. // Verify that the transform to the child surface's space has also shifted. @@ -272,8 +278,8 @@ TEST(SurfaceHittestTest, Hittest_ChildSurface) { EXPECT_EQ(gfx::Point(25, 25), point_in_target_space); } - root_factory.EvictSurface(); - child_factory.EvictSurface(); + root_support->EvictFrame(); + child_support->EvictFrame(); } // This test verifies that hit testing will progress to the next quad if it @@ -282,14 +288,18 @@ TEST(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) { SurfaceManager manager; // Set up root FrameSink. - EmptySurfaceFactoryClient root_client; FrameSinkId root_frame_sink_id(1, 1); - SurfaceFactory root_factory(root_frame_sink_id, &manager, &root_client); + std::unique_ptr<CompositorFrameSinkSupport> root_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, root_frame_sink_id, kIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Set up child FrameSink. - EmptySurfaceFactoryClient child_client; FrameSinkId child_frame_sink_id(2, 2); - SurfaceFactory child_factory(child_frame_sink_id, &manager, &child_client); + std::unique_ptr<CompositorFrameSinkSupport> child_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, child_frame_sink_id, kIsChildRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Creates a root surface. gfx::Rect root_rect(300, 300); @@ -319,9 +329,8 @@ TEST(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) { LocalSurfaceIdAllocator root_allocator; LocalSurfaceId root_local_surface_id = root_allocator.GenerateId(); SurfaceId root_surface_id(root_frame_sink_id, root_local_surface_id); - root_factory.SubmitCompositorFrame(root_local_surface_id, - std::move(root_frame), - SurfaceFactory::DrawCallback()); + root_support->SubmitCompositorFrame(root_local_surface_id, + std::move(root_frame)); // Creates a child surface. RenderPass* child_pass = nullptr; @@ -338,9 +347,8 @@ TEST(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) { child_solid_quad_rect); // Submit the frame. - child_factory.SubmitCompositorFrame(child_local_surface_id, - std::move(child_frame), - SurfaceFactory::DrawCallback()); + child_support->SubmitCompositorFrame(child_local_surface_id, + std::move(child_frame)); TestCase tests[] = { { @@ -383,15 +391,17 @@ TEST(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) { RunTests(nullptr, &manager, tests, arraysize(tests)); - root_factory.EvictSurface(); - child_factory.EvictSurface(); + root_support->EvictFrame(); + child_support->EvictFrame(); } TEST(SurfaceHittestTest, Hittest_RenderPassDrawQuad) { SurfaceManager manager; - EmptySurfaceFactoryClient client; FrameSinkId root_frame_sink_id(kArbitraryFrameSinkId); - SurfaceFactory factory(root_frame_sink_id, &manager, &client); + std::unique_ptr<CompositorFrameSinkSupport> support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, root_frame_sink_id, kIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Create a CompostiorFrame with two RenderPasses. gfx::Rect root_rect(300, 300); @@ -437,8 +447,7 @@ TEST(SurfaceHittestTest, Hittest_RenderPassDrawQuad) { LocalSurfaceIdAllocator root_allocator; LocalSurfaceId root_local_surface_id = root_allocator.GenerateId(); SurfaceId root_surface_id(root_frame_sink_id, root_local_surface_id); - factory.SubmitCompositorFrame(root_local_surface_id, std::move(root_frame), - SurfaceFactory::DrawCallback()); + support->SubmitCompositorFrame(root_local_surface_id, std::move(root_frame)); TestCase tests[] = { // These tests just miss the RenderPassDrawQuad. @@ -486,21 +495,25 @@ TEST(SurfaceHittestTest, Hittest_RenderPassDrawQuad) { RunTests(nullptr, &manager, tests, arraysize(tests)); - factory.EvictSurface(); + support->EvictFrame(); } TEST(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) { SurfaceManager manager; // Set up root FrameSink. - EmptySurfaceFactoryClient root_client; FrameSinkId root_frame_sink_id(1, 1); - SurfaceFactory root_factory(root_frame_sink_id, &manager, &root_client); + std::unique_ptr<CompositorFrameSinkSupport> root_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, root_frame_sink_id, kIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Set up child FrameSink. - EmptySurfaceFactoryClient child_client; FrameSinkId child_frame_sink_id(2, 2); - SurfaceFactory child_factory(child_frame_sink_id, &manager, &child_client); + std::unique_ptr<CompositorFrameSinkSupport> child_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, child_frame_sink_id, kIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); // Creates a root surface. gfx::Rect root_rect(300, 300); @@ -524,9 +537,8 @@ TEST(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) { LocalSurfaceIdAllocator root_allocator; LocalSurfaceId root_local_surface_id = root_allocator.GenerateId(); SurfaceId root_surface_id(root_frame_sink_id, root_local_surface_id); - root_factory.SubmitCompositorFrame(root_local_surface_id, - std::move(root_frame), - SurfaceFactory::DrawCallback()); + root_support->SubmitCompositorFrame(root_local_surface_id, + std::move(root_frame)); // Creates a child surface. RenderPass* child_pass = nullptr; @@ -541,9 +553,8 @@ TEST(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) { root_rect, child_solid_quad_rect); // Submit the frame. - child_factory.SubmitCompositorFrame(child_local_surface_id, - std::move(child_frame), - SurfaceFactory::DrawCallback()); + child_support->SubmitCompositorFrame(child_local_surface_id, + std::move(child_frame)); TestCase test_expectations_without_insets[] = { {root_surface_id, gfx::Point(55, 55), child_surface_id, gfx::Point(5, 5)}, @@ -622,8 +633,8 @@ TEST(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) { EXPECT_EQ(0, accept_delegate.reject_target_overrides()); EXPECT_EQ(2, accept_delegate.accept_target_overrides()); - root_factory.EvictSurface(); - child_factory.EvictSurface(); + root_support->EvictFrame(); + child_support->EvictFrame(); } } // namespace cc diff --git a/chromium/cc/surfaces/surface_manager.cc b/chromium/cc/surfaces/surface_manager.cc index e73e814e105..d4b0d01397f 100644 --- a/chromium/cc/surfaces/surface_manager.cc +++ b/chromium/cc/surfaces/surface_manager.cc @@ -23,17 +23,6 @@ namespace cc { -SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping() - : client(nullptr), source(nullptr) {} - -SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping( - const FrameSinkSourceMapping& other) = default; - -SurfaceManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() { - DCHECK(is_empty()) << "client: " << client - << ", children: " << children.size(); -} - SurfaceManager::SurfaceManager(LifetimeType lifetime_type) : lifetime_type_(lifetime_type), root_surface_id_(FrameSinkId(0u, 0u), @@ -58,14 +47,9 @@ SurfaceManager::~SurfaceManager() { for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); it != surfaces_to_destroy_.end(); ++it) { - DeregisterSurface((*it)->surface_id()); + UnregisterSurface((*it)->surface_id()); } surfaces_to_destroy_.clear(); - - // All hierarchies, sources, and surface factory clients should be - // unregistered prior to SurfaceManager destruction. - DCHECK_EQ(frame_sink_source_map_.size(), 0u); - DCHECK_EQ(registered_sources_.size(), 0u); } #if DCHECK_IS_ON() @@ -90,22 +74,45 @@ void SurfaceManager::RequestSurfaceResolution(Surface* pending_surface) { dependency_tracker_->RequestSurfaceResolution(pending_surface); } -void SurfaceManager::RegisterSurface(Surface* surface) { +std::unique_ptr<Surface> SurfaceManager::CreateSurface( + base::WeakPtr<SurfaceFactory> surface_factory, + const LocalSurfaceId& local_surface_id) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(surface); - DCHECK(!surface_map_.count(surface->surface_id())); - surface_map_[surface->surface_id()] = surface; -} + DCHECK(local_surface_id.is_valid() && surface_factory); -void SurfaceManager::DeregisterSurface(const SurfaceId& surface_id) { - DCHECK(thread_checker_.CalledOnValidThread()); - SurfaceMap::iterator it = surface_map_.find(surface_id); - DCHECK(it != surface_map_.end()); - surface_map_.erase(it); - RemoveAllSurfaceReferences(surface_id); -} + SurfaceId surface_id(surface_factory->frame_sink_id(), local_surface_id); -void SurfaceManager::Destroy(std::unique_ptr<Surface> surface) { + // If no surface with this SurfaceId exists, simply create the surface and + // return. + auto surface_iter = surface_map_.find(surface_id); + if (surface_iter == surface_map_.end()) { + auto surface = base::MakeUnique<Surface>(surface_id, surface_factory); + surface_map_[surface->surface_id()] = surface.get(); + return surface; + } + + // If a surface with this SurfaceId exists and it's not marked as destroyed, + // we should not receive a request to create a new surface with the same + // SurfaceId. + DCHECK(surface_iter->second->destroyed()); + + // If a surface with this SurfaceId exists and it's marked as destroyed, + // it means it's in the garbage collector's queue. We simply take it out of + // the queue and reuse it. + auto it = + std::find_if(surfaces_to_destroy_.begin(), surfaces_to_destroy_.end(), + [&surface_id](const std::unique_ptr<Surface>& surface) { + return surface->surface_id() == surface_id; + }); + DCHECK(it != surfaces_to_destroy_.end()); + std::unique_ptr<Surface> surface = std::move(*it); + surfaces_to_destroy_.erase(it); + surface->set_destroyed(false); + DCHECK_EQ(surface_factory.get(), surface->factory().get()); + return surface; +} + +void SurfaceManager::DestroySurface(std::unique_ptr<Surface> surface) { DCHECK(thread_checker_.CalledOnValidThread()); surface->set_destroyed(true); surfaces_to_destroy_.push_back(std::move(surface)); @@ -130,12 +137,11 @@ void SurfaceManager::SatisfySequence(const SurfaceSequence& sequence) { } void SurfaceManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) { - bool inserted = valid_frame_sink_ids_.insert(frame_sink_id).second; - DCHECK(inserted); + framesink_manager_.RegisterFrameSinkId(frame_sink_id); } void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { - valid_frame_sink_ids_.erase(frame_sink_id); + framesink_manager_.InvalidateFrameSinkId(frame_sink_id); if (using_surface_references()) { // Remove any temporary references owned by |frame_sink_id|. @@ -213,7 +219,7 @@ void SurfaceManager::GarbageCollectSurfaces() { iter != surfaces_to_destroy_.end();) { SurfaceId surface_id = (*iter)->surface_id(); if (reachable_surfaces.count(surface_id) == 0) { - DeregisterSurface(surface_id); + UnregisterSurface(surface_id); surfaces_to_delete.push_back(std::move(*iter)); iter = surfaces_to_destroy_.erase(iter); } else { @@ -271,7 +277,7 @@ SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForSequences() { const SurfaceId& surface_id = map_entry.first; Surface* surface = map_entry.second; surface->SatisfyDestructionDependencies(&satisfied_sequences_, - &valid_frame_sink_ids_); + framesink_manager_.GetValidFrameSinkIds()); if (!surface->destroyed() || surface->GetDestructionDependencyCount() > 0) { live_surfaces_set.insert(surface_id); @@ -313,6 +319,13 @@ void SurfaceManager::AddSurfaceReferenceImpl(const SurfaceId& parent_id, return; } + // We trust that |parent_id| either exists or is about to exist, since is not + // sent over IPC. We don't trust |child_id|, since it is sent over IPC. + if (surface_map_.count(child_id) == 0) { + DLOG(ERROR) << "No surface in map for " << child_id.ToString(); + return; + } + parent_to_child_refs_[parent_id].insert(child_id); child_to_parent_refs_[child_id].insert(parent_id); @@ -397,186 +410,36 @@ void SurfaceManager::RemoveTemporaryReference(const SurfaceId& surface_id, void SurfaceManager::RegisterSurfaceFactoryClient( const FrameSinkId& frame_sink_id, SurfaceFactoryClient* client) { - DCHECK(client); - DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); - - // Will create a new FrameSinkSourceMapping for |frame_sink_id| if necessary. - FrameSinkSourceMapping& frame_sink_source = - frame_sink_source_map_[frame_sink_id]; - DCHECK(!frame_sink_source.client); - frame_sink_source.client = client; - - // Propagate any previously set sources to the new client. - if (frame_sink_source.source) - client->SetBeginFrameSource(frame_sink_source.source); + framesink_manager_.RegisterSurfaceFactoryClient(frame_sink_id, client); } void SurfaceManager::UnregisterSurfaceFactoryClient( const FrameSinkId& frame_sink_id) { - DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); - DCHECK_EQ(frame_sink_source_map_.count(frame_sink_id), 1u); - - auto iter = frame_sink_source_map_.find(frame_sink_id); - if (iter->second.source) - iter->second.client->SetBeginFrameSource(nullptr); - iter->second.client = nullptr; - - // The SurfaceFactoryClient and hierarchy can be registered/unregistered - // in either order, so empty namespace_client_map entries need to be - // checked when removing either clients or relationships. - if (iter->second.is_empty()) - frame_sink_source_map_.erase(iter); + framesink_manager_.UnregisterSurfaceFactoryClient(frame_sink_id); } void SurfaceManager::RegisterBeginFrameSource( BeginFrameSource* source, const FrameSinkId& frame_sink_id) { - DCHECK(source); - DCHECK_EQ(registered_sources_.count(source), 0u); - DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); - - registered_sources_[source] = frame_sink_id; - RecursivelyAttachBeginFrameSource(frame_sink_id, source); + framesink_manager_.RegisterBeginFrameSource(source, frame_sink_id); } void SurfaceManager::UnregisterBeginFrameSource(BeginFrameSource* source) { - DCHECK(source); - DCHECK_EQ(registered_sources_.count(source), 1u); - - FrameSinkId frame_sink_id = registered_sources_[source]; - registered_sources_.erase(source); - - if (frame_sink_source_map_.count(frame_sink_id) == 0u) - return; - - // TODO(enne): these walks could be done in one step. - // Remove this begin frame source from its subtree. - RecursivelyDetachBeginFrameSource(frame_sink_id, source); - // Then flush every remaining registered source to fix any sources that - // became null because of the previous step but that have an alternative. - for (auto source_iter : registered_sources_) - RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); -} - -void SurfaceManager::RecursivelyAttachBeginFrameSource( - const FrameSinkId& frame_sink_id, - BeginFrameSource* source) { - FrameSinkSourceMapping& mapping = frame_sink_source_map_[frame_sink_id]; - if (!mapping.source) { - mapping.source = source; - if (mapping.client) - mapping.client->SetBeginFrameSource(source); - } - for (size_t i = 0; i < mapping.children.size(); ++i) - RecursivelyAttachBeginFrameSource(mapping.children[i], source); -} - -void SurfaceManager::RecursivelyDetachBeginFrameSource( - const FrameSinkId& frame_sink_id, - BeginFrameSource* source) { - auto iter = frame_sink_source_map_.find(frame_sink_id); - if (iter == frame_sink_source_map_.end()) - return; - if (iter->second.source == source) { - iter->second.source = nullptr; - if (iter->second.client) - iter->second.client->SetBeginFrameSource(nullptr); - } - - if (iter->second.is_empty()) { - frame_sink_source_map_.erase(iter); - return; - } - - std::vector<FrameSinkId>& children = iter->second.children; - for (size_t i = 0; i < children.size(); ++i) { - RecursivelyDetachBeginFrameSource(children[i], source); - } -} - -bool SurfaceManager::ChildContains( - const FrameSinkId& child_frame_sink_id, - const FrameSinkId& search_frame_sink_id) const { - auto iter = frame_sink_source_map_.find(child_frame_sink_id); - if (iter == frame_sink_source_map_.end()) - return false; - - const std::vector<FrameSinkId>& children = iter->second.children; - for (size_t i = 0; i < children.size(); ++i) { - if (children[i] == search_frame_sink_id) - return true; - if (ChildContains(children[i], search_frame_sink_id)) - return true; - } - return false; + framesink_manager_.UnregisterBeginFrameSource(source); } void SurfaceManager::RegisterFrameSinkHierarchy( const FrameSinkId& parent_frame_sink_id, const FrameSinkId& child_frame_sink_id) { - // If it's possible to reach the parent through the child's descendant chain, - // then this will create an infinite loop. Might as well just crash here. - CHECK(!ChildContains(child_frame_sink_id, parent_frame_sink_id)); - - std::vector<FrameSinkId>& children = - frame_sink_source_map_[parent_frame_sink_id].children; - for (size_t i = 0; i < children.size(); ++i) - DCHECK(children[i] != child_frame_sink_id); - children.push_back(child_frame_sink_id); - - // If the parent has no source, then attaching it to this child will - // not change any downstream sources. - BeginFrameSource* parent_source = - frame_sink_source_map_[parent_frame_sink_id].source; - if (!parent_source) - return; - - DCHECK_EQ(registered_sources_.count(parent_source), 1u); - RecursivelyAttachBeginFrameSource(child_frame_sink_id, parent_source); + framesink_manager_.RegisterFrameSinkHierarchy(parent_frame_sink_id, + child_frame_sink_id); } void SurfaceManager::UnregisterFrameSinkHierarchy( const FrameSinkId& parent_frame_sink_id, const FrameSinkId& child_frame_sink_id) { - // Deliberately do not check validity of either parent or child namespace - // here. They were valid during the registration, so were valid at some - // point in time. This makes it possible to invalidate parent and child - // namespaces independently of each other and not have an ordering dependency - // of unregistering the hierarchy first before either of them. - DCHECK_EQ(frame_sink_source_map_.count(parent_frame_sink_id), 1u); - - auto iter = frame_sink_source_map_.find(parent_frame_sink_id); - - std::vector<FrameSinkId>& children = iter->second.children; - bool found_child = false; - for (size_t i = 0; i < children.size(); ++i) { - if (children[i] == child_frame_sink_id) { - found_child = true; - children[i] = children.back(); - children.resize(children.size() - 1); - break; - } - } - DCHECK(found_child); - - // The SurfaceFactoryClient and hierarchy can be registered/unregistered - // in either order, so empty namespace_client_map entries need to be - // checked when removing either clients or relationships. - if (iter->second.is_empty()) { - frame_sink_source_map_.erase(iter); - return; - } - - // If the parent does not have a begin frame source, then disconnecting it - // will not change any of its children. - BeginFrameSource* parent_source = iter->second.source; - if (!parent_source) - return; - - // TODO(enne): these walks could be done in one step. - RecursivelyDetachBeginFrameSource(child_frame_sink_id, parent_source); - for (auto source_iter : registered_sources_) - RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); + framesink_manager_.UnregisterFrameSinkHierarchy(parent_frame_sink_id, + child_frame_sink_id); } Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) { @@ -605,20 +468,21 @@ void SurfaceManager::SurfaceCreated(const SurfaceInfo& surface_info) { // destroyed in SurfaceFactory and then if there are no references it will // be deleted during surface GC. A temporary reference, removed when a // real reference is received, is added to prevent this from happening. - auto it = child_to_parent_refs_.find(surface_info.id()); - // TODO(fsamuel): Tests create empty sets and so we also need to check that - // they're not empty here. Ideally tests shouldn't do that and we shouldn't - // use array notation into maps in tests (see https://crbug.com/691115). - bool has_real_reference = - it != child_to_parent_refs_.end() && !it->second.empty(); - if (!has_real_reference) - AddTemporaryReference(surface_info.id()); + AddTemporaryReference(surface_info.id()); } for (auto& observer : observer_list_) observer.OnSurfaceCreated(surface_info); } +void SurfaceManager::UnregisterSurface(const SurfaceId& surface_id) { + DCHECK(thread_checker_.CalledOnValidThread()); + SurfaceMap::iterator it = surface_map_.find(surface_id); + DCHECK(it != surface_map_.end()); + surface_map_.erase(it); + RemoveAllSurfaceReferences(surface_id); +} + #if DCHECK_IS_ON() void SurfaceManager::SurfaceReferencesToStringImpl(const SurfaceId& surface_id, std::string indent, diff --git a/chromium/cc/surfaces/surface_manager.h b/chromium/cc/surfaces/surface_manager.h index 569c6e44c03..53998ec5cb9 100644 --- a/chromium/cc/surfaces/surface_manager.h +++ b/chromium/cc/surfaces/surface_manager.h @@ -19,6 +19,7 @@ #include "base/observer_list.h" #include "base/threading/thread_checker.h" #include "cc/surfaces/frame_sink_id.h" +#include "cc/surfaces/framesink_manager.h" #include "cc/surfaces/surface_dependency_tracker.h" #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_observer.h" @@ -36,6 +37,7 @@ namespace cc { class BeginFrameSource; class CompositorFrame; class Surface; +class SurfaceFactory; class SurfaceFactoryClient; namespace test { @@ -65,11 +67,12 @@ class CC_SURFACES_EXPORT SurfaceManager { void RequestSurfaceResolution(Surface* pending_surface); - void RegisterSurface(Surface* surface); - void DeregisterSurface(const SurfaceId& surface_id); + std::unique_ptr<Surface> CreateSurface( + base::WeakPtr<SurfaceFactory> surface_factory, + const LocalSurfaceId& local_surface_id); // Destroy the Surface once a set of sequence numbers has been satisfied. - void Destroy(std::unique_ptr<Surface> surface); + void DestroySurface(std::unique_ptr<Surface> surface); Surface* GetSurfaceForId(const SurfaceId& surface_id); @@ -173,16 +176,6 @@ class CC_SURFACES_EXPORT SurfaceManager { using SurfaceIdSet = std::unordered_set<SurfaceId, SurfaceIdHash>; - void RecursivelyAttachBeginFrameSource(const FrameSinkId& frame_sink_id, - BeginFrameSource* source); - void RecursivelyDetachBeginFrameSource(const FrameSinkId& frame_sink_id, - BeginFrameSource* source); - - // Returns true if |child namespace| is or has |search_frame_sink_id| as a - // child. - bool ChildContains(const FrameSinkId& child_frame_sink_id, - const FrameSinkId& search_frame_sink_id) const; - // Garbage collects all destroyed surfaces that aren't live. void GarbageCollectSurfaces(); @@ -216,6 +209,10 @@ class CC_SURFACES_EXPORT SurfaceManager { // |surface_id| that were added before |surface_id| will also be removed. void RemoveTemporaryReference(const SurfaceId& surface_id, bool remove_range); + // Called when a surface is destroyed and it needs to be removed from the + // surface map. + void UnregisterSurface(const SurfaceId& surface_id); + #if DCHECK_IS_ON() // Recursively prints surface references starting at |surface_id| to |str|. void SurfaceReferencesToStringImpl(const SurfaceId& surface_id, @@ -226,6 +223,8 @@ class CC_SURFACES_EXPORT SurfaceManager { // Use reference or sequence based lifetime management. LifetimeType lifetime_type_; + FrameSinkManager framesink_manager_; + using SurfaceMap = std::unordered_map<SurfaceId, Surface*, SurfaceIdHash>; SurfaceMap surface_map_; base::ObserverList<SurfaceObserver> observer_list_; @@ -240,28 +239,6 @@ class CC_SURFACES_EXPORT SurfaceManager { // waited on. std::unordered_set<SurfaceSequence, SurfaceSequenceHash> 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. - std::unordered_set<FrameSinkId, FrameSinkIdHash> valid_frame_sink_ids_; - - // Begin frame source routing. Both BeginFrameSource and SurfaceFactoryClient - // pointers guaranteed alive by callers until unregistered. - struct FrameSinkSourceMapping { - FrameSinkSourceMapping(); - FrameSinkSourceMapping(const FrameSinkSourceMapping& other); - ~FrameSinkSourceMapping(); - bool is_empty() const { return !client && children.empty(); } - // The client that's responsible for creating this namespace. Never null. - SurfaceFactoryClient* client; - // The currently assigned begin frame source for this client. - BeginFrameSource* source; - // This represents a dag of parent -> children mapping. - std::vector<FrameSinkId> children; - }; - std::unordered_map<FrameSinkId, FrameSinkSourceMapping, FrameSinkIdHash> - frame_sink_source_map_; - // Tracks references from the child surface to parent surface. If there are // zero entries in the set for a SurfaceId then nothing is referencing the // surface and it can be garbage collected. @@ -272,11 +249,6 @@ class CC_SURFACES_EXPORT SurfaceManager { std::unordered_map<SurfaceId, SurfaceIdSet, SurfaceIdHash> parent_to_child_refs_; - // Set of which sources are registered to which namespace. Any child - // that is implicitly using this namespace must be reachable by the - // parent in the dag. - std::unordered_map<BeginFrameSource*, FrameSinkId> registered_sources_; - // Root SurfaceId that references display root surfaces. There is no Surface // with this id, it's for bookkeeping purposes only. const SurfaceId root_surface_id_; diff --git a/chromium/cc/surfaces/surface_manager_ref_unittest.cc b/chromium/cc/surfaces/surface_manager_ref_unittest.cc index fb21ce3f39a..eb678f8f0c9 100644 --- a/chromium/cc/surfaces/surface_manager_ref_unittest.cc +++ b/chromium/cc/surfaces/surface_manager_ref_unittest.cc @@ -8,9 +8,8 @@ #include <vector> #include "base/memory/ptr_util.h" +#include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/surface.h" -#include "cc/surfaces/surface_factory.h" -#include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_manager.h" #include "testing/gmock/include/gmock/gmock.h" @@ -29,12 +28,6 @@ constexpr FrameSinkId kFrameSink1(1, 0); constexpr FrameSinkId kFrameSink2(2, 0); constexpr FrameSinkId kFrameSink3(3, 0); -class StubSurfaceFactoryClient : public SurfaceFactoryClient { - public: - void ReturnResources(const ReturnedResourceArray& resources) override {} - void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override {} -}; - } // namespace // Tests for reference tracking in SurfaceManager. @@ -43,27 +36,38 @@ class SurfaceManagerRefTest : public testing::Test { SurfaceManager& manager() { return *manager_; } // Creates a new Surface with the provided |frame_sink_id| and |local_id|. - // Will first create a SurfaceFactory for |frame_sink_id| if necessary. + // Will first create a Surfacesupport for |frame_sink_id| if necessary. SurfaceId CreateSurface(const FrameSinkId& frame_sink_id, uint32_t local_id) { LocalSurfaceId local_surface_id(local_id, base::UnguessableToken::Deserialize(0, 1u)); - GetFactory(frame_sink_id) - .SubmitCompositorFrame(local_surface_id, CompositorFrame(), - SurfaceFactory::DrawCallback()); + GetCompositorFrameSinkSupport(frame_sink_id) + .SubmitCompositorFrame(local_surface_id, CompositorFrame()); return SurfaceId(frame_sink_id, local_surface_id); } // Destroy Surface with |surface_id|. void DestroySurface(const SurfaceId& surface_id) { - GetFactory(surface_id.frame_sink_id()).EvictSurface(); + GetCompositorFrameSinkSupport(surface_id.frame_sink_id()).EvictFrame(); } - SurfaceFactory& GetFactory(const FrameSinkId& frame_sink_id) { - auto& factory_ptr = factories_[frame_sink_id]; - if (!factory_ptr) - factory_ptr = base::MakeUnique<SurfaceFactory>(frame_sink_id, - manager_.get(), &client_); - return *factory_ptr; + CompositorFrameSinkSupport& GetCompositorFrameSinkSupport( + const FrameSinkId& frame_sink_id) { + auto& support_ptr = supports_[frame_sink_id]; + if (!support_ptr) { + constexpr bool is_root = false; + constexpr bool handles_frame_sink_id_invalidation = true; + constexpr bool needs_sync_points = true; + support_ptr = CompositorFrameSinkSupport::Create( + nullptr, manager_.get(), frame_sink_id, is_root, + handles_frame_sink_id_invalidation, needs_sync_points); + } + return *support_ptr; + } + + void DestroyCompositorFrameSinkSupport(const FrameSinkId& frame_sink_id) { + auto support_ptr = supports_.find(frame_sink_id); + ASSERT_NE(support_ptr, supports_.end()); + supports_.erase(support_ptr); } void RemoveSurfaceReference(const SurfaceId& parent_id, @@ -105,18 +109,17 @@ class SurfaceManagerRefTest : public testing::Test { SurfaceManager::LifetimeType::REFERENCES); } void TearDown() override { - for (auto& factory : factories_) - factory.second->EvictSurface(); - factories_.clear(); + for (auto& support : supports_) + support.second->EvictFrame(); + supports_.clear(); manager_.reset(); } std::unordered_map<FrameSinkId, - std::unique_ptr<SurfaceFactory>, + std::unique_ptr<CompositorFrameSinkSupport>, FrameSinkIdHash> - factories_; + supports_; std::unique_ptr<SurfaceManager> manager_; - StubSurfaceFactoryClient client_; }; TEST_F(SurfaceManagerRefTest, AddReference) { @@ -464,7 +467,7 @@ TEST_F(SurfaceManagerRefTest, InvalidateHasNoEffectOnSurfaceReferences) { // When |kFrameSink1| is invalidated it shouldn't change the surface // references. - manager().InvalidateFrameSinkId(kFrameSink1); + DestroyCompositorFrameSinkSupport(kFrameSink1); ASSERT_THAT(GetReferencesFor(id1), UnorderedElementsAre(parent_id)); } @@ -499,7 +502,7 @@ TEST_F(SurfaceManagerRefTest, TempReferencesWithClientCrash) { // If the parent client crashes then the CompositorFrameSink connection will // be closed and the FrameSinkId invalidated. The temporary reference // |kFrameSink1| owns to |id2a| will be removed. - manager().InvalidateFrameSinkId(kFrameSink1); + DestroyCompositorFrameSinkSupport(kFrameSink1); ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id1b)); // If the parent has crashed then the window server will have already removed diff --git a/chromium/cc/surfaces/surface_manager_unittest.cc b/chromium/cc/surfaces/surface_manager_unittest.cc index e1c6c2b6711..6142560acb4 100644 --- a/chromium/cc/surfaces/surface_manager_unittest.cc +++ b/chromium/cc/surfaces/surface_manager_unittest.cc @@ -27,14 +27,14 @@ class FakeSurfaceFactoryClient : public SurfaceFactoryClient { if (manager_) { Unregister(); } - EXPECT_EQ(source_, nullptr); + EXPECT_EQ(nullptr, source_); } BeginFrameSource* source() { return source_; } const FrameSinkId& frame_sink_id() { return frame_sink_id_; } void Register(SurfaceManager* manager) { - EXPECT_EQ(manager_, nullptr); + EXPECT_EQ(nullptr, manager_); manager_ = manager; manager_->RegisterSurfaceFactoryClient(frame_sink_id_, this); } @@ -84,34 +84,34 @@ TEST_F(SurfaceManagerTest, SingleClients) { FakeSurfaceFactoryClient other_client(FrameSinkId(2, 2)); StubBeginFrameSource source; - EXPECT_EQ(client.source(), nullptr); - EXPECT_EQ(other_client.source(), nullptr); + EXPECT_EQ(nullptr, client.source()); + EXPECT_EQ(nullptr, other_client.source()); client.Register(&manager_); other_client.Register(&manager_); - EXPECT_EQ(client.source(), nullptr); - EXPECT_EQ(other_client.source(), nullptr); + EXPECT_EQ(nullptr, client.source()); + EXPECT_EQ(nullptr, other_client.source()); // Test setting unsetting BFS manager_.RegisterBeginFrameSource(&source, client.frame_sink_id()); - EXPECT_EQ(client.source(), &source); - EXPECT_EQ(other_client.source(), nullptr); + EXPECT_EQ(&source, client.source()); + EXPECT_EQ(nullptr, other_client.source()); manager_.UnregisterBeginFrameSource(&source); - EXPECT_EQ(client.source(), nullptr); - EXPECT_EQ(other_client.source(), nullptr); + EXPECT_EQ(nullptr, client.source()); + EXPECT_EQ(nullptr, other_client.source()); // Set BFS for other namespace manager_.RegisterBeginFrameSource(&source, other_client.frame_sink_id()); - EXPECT_EQ(other_client.source(), &source); - EXPECT_EQ(client.source(), nullptr); + EXPECT_EQ(&source, other_client.source()); + EXPECT_EQ(nullptr, client.source()); manager_.UnregisterBeginFrameSource(&source); - EXPECT_EQ(client.source(), nullptr); - EXPECT_EQ(other_client.source(), nullptr); + EXPECT_EQ(nullptr, client.source()); + EXPECT_EQ(nullptr, other_client.source()); // Re-set BFS for original manager_.RegisterBeginFrameSource(&source, client.frame_sink_id()); - EXPECT_EQ(client.source(), &source); + EXPECT_EQ(&source, client.source()); manager_.UnregisterBeginFrameSource(&source); - EXPECT_EQ(client.source(), nullptr); + EXPECT_EQ(nullptr, client.source()); } TEST_F(SurfaceManagerTest, MultipleDisplays) { @@ -162,15 +162,15 @@ TEST_F(SurfaceManagerTest, MultipleDisplays) { // Detach root1 from BFS. root1 should now have no source. manager_.UnregisterBeginFrameSource(&root1_source); - EXPECT_EQ(root1.source(), nullptr); - EXPECT_NE(root2.source(), nullptr); + EXPECT_EQ(nullptr, root1.source()); + EXPECT_NE(nullptr, root2.source()); // Detatch root2 from BFS. manager_.UnregisterBeginFrameSource(&root2_source); - EXPECT_EQ(client_a.source(), nullptr); - EXPECT_EQ(client_b.source(), nullptr); - EXPECT_EQ(client_c.source(), nullptr); - EXPECT_EQ(root2.source(), nullptr); + EXPECT_EQ(nullptr, client_a.source()); + EXPECT_EQ(nullptr, client_b.source()); + EXPECT_EQ(nullptr, client_c.source()); + EXPECT_EQ(nullptr, root2.source()); // Cleanup hierarchy. manager_.UnregisterFrameSinkHierarchy(root2.frame_sink_id(), @@ -181,6 +181,83 @@ TEST_F(SurfaceManagerTest, MultipleDisplays) { client_b.frame_sink_id()); } +// This test verifies that a BeginFrameSource path to the root from a +// FrameSinkId is preserved even if that FrameSinkId has no children +// and does not have a corresponding SurfaceFactoryClient. +TEST_F(SurfaceManagerTest, ParentWithoutClientRetained) { + StubBeginFrameSource root_source; + + constexpr FrameSinkId kFrameSinkIdRoot(1, 1); + constexpr FrameSinkId kFrameSinkIdA(2, 2); + constexpr FrameSinkId kFrameSinkIdB(3, 3); + constexpr FrameSinkId kFrameSinkIdC(4, 4); + + FakeSurfaceFactoryClient root(kFrameSinkIdRoot, &manager_); + FakeSurfaceFactoryClient client_b(kFrameSinkIdB, &manager_); + FakeSurfaceFactoryClient client_c(kFrameSinkIdC, &manager_); + + manager_.RegisterBeginFrameSource(&root_source, root.frame_sink_id()); + EXPECT_EQ(&root_source, root.source()); + + // Set up initial hierarchy: root -> A -> B. + // Note that A does not have a SurfaceFactoryClient. + manager_.RegisterFrameSinkHierarchy(kFrameSinkIdRoot, kFrameSinkIdA); + manager_.RegisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdB); + // The root's BeginFrameSource should propagate to B. + EXPECT_EQ(root.source(), client_b.source()); + + // Unregister B, and attach C to A: root -> A -> C + manager_.UnregisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdB); + EXPECT_EQ(nullptr, client_b.source()); + manager_.RegisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdC); + // The root's BeginFrameSource should propagate to C. + EXPECT_EQ(root.source(), client_c.source()); + + manager_.UnregisterBeginFrameSource(&root_source); + EXPECT_EQ(nullptr, root.source()); + EXPECT_EQ(nullptr, client_c.source()); +} + +// This test sets up the same hierarchy as ParentWithoutClientRetained. +// However, this unit test registers the BeginFrameSource AFTER C +// has been attached to A. This test verifies that the BeginFrameSource +// propagates all the way to C. +TEST_F(SurfaceManagerTest, + ParentWithoutClientRetained_LateBeginFrameRegistration) { + StubBeginFrameSource root_source; + + constexpr FrameSinkId kFrameSinkIdRoot(1, 1); + constexpr FrameSinkId kFrameSinkIdA(2, 2); + constexpr FrameSinkId kFrameSinkIdB(3, 3); + constexpr FrameSinkId kFrameSinkIdC(4, 4); + + FakeSurfaceFactoryClient root(kFrameSinkIdRoot, &manager_); + FakeSurfaceFactoryClient client_b(kFrameSinkIdB, &manager_); + FakeSurfaceFactoryClient client_c(kFrameSinkIdC, &manager_); + + // Set up initial hierarchy: root -> A -> B. + // Note that A does not have a SurfaceFactoryClient. + manager_.RegisterFrameSinkHierarchy(kFrameSinkIdRoot, kFrameSinkIdA); + manager_.RegisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdB); + // The root does not yet have a BeginFrameSource so client B should not have + // one either. + EXPECT_EQ(nullptr, client_b.source()); + + // Unregister B, and attach C to A: root -> A -> C + manager_.UnregisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdB); + manager_.RegisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdC); + + // Registering a BeginFrameSource at the root should propagate it to C. + manager_.RegisterBeginFrameSource(&root_source, root.frame_sink_id()); + // The root's BeginFrameSource should propagate to C. + EXPECT_EQ(&root_source, root.source()); + EXPECT_EQ(root.source(), client_c.source()); + + manager_.UnregisterBeginFrameSource(&root_source); + EXPECT_EQ(nullptr, root.source()); + EXPECT_EQ(nullptr, client_c.source()); +} + // In practice, registering and unregistering both parent/child relationships // and SurfaceFactoryClients can happen in any ordering with respect to // each other. These following tests verify that all the data structures @@ -200,9 +277,9 @@ class SurfaceManagerOrderingTest : public SurfaceManagerTest { } ~SurfaceManagerOrderingTest() override { - EXPECT_EQ(hierarchy_registered_, false); - EXPECT_EQ(clients_registered_, false); - EXPECT_EQ(bfs_registered_, false); + EXPECT_FALSE(hierarchy_registered_); + EXPECT_FALSE(clients_registered_); + EXPECT_FALSE(bfs_registered_); AssertCorrectBFSState(); } @@ -257,15 +334,15 @@ class SurfaceManagerOrderingTest : public SurfaceManagerTest { } void AssertEmptyBFS() { - EXPECT_EQ(client_a_.source(), nullptr); - EXPECT_EQ(client_b_.source(), nullptr); - EXPECT_EQ(client_c_.source(), nullptr); + EXPECT_EQ(nullptr, client_a_.source()); + EXPECT_EQ(nullptr, client_b_.source()); + EXPECT_EQ(nullptr, client_c_.source()); } void AssertAllValidBFS() { - EXPECT_EQ(client_a_.source(), &source_); - EXPECT_EQ(client_b_.source(), &source_); - EXPECT_EQ(client_c_.source(), &source_); + EXPECT_EQ(&source_, client_a_.source()); + EXPECT_EQ(&source_, client_b_.source()); + EXPECT_EQ(&source_, client_c_.source()); } protected: @@ -276,9 +353,9 @@ class SurfaceManagerOrderingTest : public SurfaceManagerTest { } if (!hierarchy_registered_) { // A valid but not attached to anything. - EXPECT_EQ(client_a_.source(), &source_); - EXPECT_EQ(client_b_.source(), nullptr); - EXPECT_EQ(client_c_.source(), nullptr); + EXPECT_EQ(&source_, client_a_.source()); + EXPECT_EQ(nullptr, client_b_.source()); + EXPECT_EQ(nullptr, client_c_.source()); return; } diff --git a/chromium/cc/surfaces/surface_unittest.cc b/chromium/cc/surfaces/surface_unittest.cc index 7aa75828482..e40cc05f9b3 100644 --- a/chromium/cc/surfaces/surface_unittest.cc +++ b/chromium/cc/surfaces/surface_unittest.cc @@ -5,10 +5,9 @@ #include "cc/surfaces/surface.h" #include "base/memory/ptr_util.h" #include "cc/output/copy_output_result.h" +#include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface_dependency_tracker.h" -#include "cc/surfaces/surface_factory.h" -#include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_manager.h" #include "cc/test/begin_frame_args_test.h" #include "cc/test/fake_external_begin_frame_source.h" @@ -19,36 +18,23 @@ namespace cc { namespace { -static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1); - -class FakeSurfaceFactoryClient : public SurfaceFactoryClient { - public: - FakeSurfaceFactoryClient() : begin_frame_source_(nullptr) {} - - void ReturnResources(const ReturnedResourceArray& resources) override {} - - void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override { - begin_frame_source_ = begin_frame_source; - } - - BeginFrameSource* begin_frame_source() { return begin_frame_source_; } - - private: - BeginFrameSource* begin_frame_source_; -}; +constexpr FrameSinkId kArbitraryFrameSinkId(1, 1); +constexpr bool kIsRoot = true; +constexpr bool kHandlesFrameSinkIdInvalidation = true; +constexpr bool kNeedsSyncPoints = true; TEST(SurfaceTest, SurfaceLifetime) { SurfaceManager manager; - FakeSurfaceFactoryClient surface_factory_client; - SurfaceFactory factory(kArbitraryFrameSinkId, &manager, - &surface_factory_client); + std::unique_ptr<CompositorFrameSinkSupport> support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, kArbitraryFrameSinkId, kIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create()); SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id); - factory.SubmitCompositorFrame(local_surface_id, CompositorFrame(), - SurfaceFactory::DrawCallback()); + support->SubmitCompositorFrame(local_surface_id, CompositorFrame()); EXPECT_TRUE(manager.GetSurfaceForId(surface_id)); - factory.EvictSurface(); + support->EvictFrame(); EXPECT_EQ(NULL, manager.GetSurfaceForId(surface_id)); } @@ -71,34 +57,40 @@ void TestCopyResultCallback(bool* called, // aggregated on the next frame. TEST(SurfaceTest, CopyRequestLifetime) { SurfaceManager manager; - FakeSurfaceFactoryClient surface_factory_client; - SurfaceFactory factory(kArbitraryFrameSinkId, &manager, - &surface_factory_client); + std::unique_ptr<CompositorFrameSinkSupport> support = + CompositorFrameSinkSupport::Create( + nullptr, &manager, kArbitraryFrameSinkId, kIsRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create()); SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id); CompositorFrame frame; frame.render_pass_list.push_back(RenderPass::Create()); - factory.SubmitCompositorFrame(local_surface_id, std::move(frame), - SurfaceFactory::DrawCallback()); + support->SubmitCompositorFrame(local_surface_id, std::move(frame)); Surface* surface = manager.GetSurfaceForId(surface_id); ASSERT_TRUE(!!surface); bool copy_called = false; - factory.RequestCopyOfSurface(CopyOutputRequest::CreateRequest( + support->RequestCopyOfSurface(CopyOutputRequest::CreateRequest( base::Bind(&TestCopyResultCallback, ©_called))); EXPECT_TRUE(manager.GetSurfaceForId(surface_id)); EXPECT_FALSE(copy_called); - CompositorFrame frame2; - frame2.render_pass_list.push_back(RenderPass::Create()); - frame2.render_pass_list.back()->id = 1; - frame2.render_pass_list.push_back(RenderPass::Create()); - frame2.render_pass_list.back()->id = 2; - factory.SubmitCompositorFrame(local_surface_id, std::move(frame2), - SurfaceFactory::DrawCallback()); + int max_frame = 3, start_id = 200; + for (int i = 0; i < max_frame; ++i) { + CompositorFrame frame; + frame.render_pass_list.push_back(RenderPass::Create()); + frame.render_pass_list.back()->id = i * 3 + start_id; + frame.render_pass_list.push_back(RenderPass::Create()); + frame.render_pass_list.back()->id = i * 3 + start_id + 1; + frame.render_pass_list.push_back(RenderPass::Create()); + frame.render_pass_list.back()->id = i * 3 + start_id + 2; + support->SubmitCompositorFrame(local_surface_id, std::move(frame)); + } - // The copy request should stay on the Surface after a new frame is created. + int last_pass_id = (max_frame - 1) * 3 + start_id + 2; + // The copy request should stay on the Surface until TakeCopyOutputRequests + // is called. EXPECT_FALSE(copy_called); EXPECT_EQ( 1u, @@ -108,12 +100,12 @@ TEST(SurfaceTest, CopyRequestLifetime) { surface->TakeCopyOutputRequests(©_requests); EXPECT_EQ(1u, copy_requests.size()); // Last (root) pass should receive copy request. - ASSERT_EQ(1u, copy_requests.count(2)); + ASSERT_EQ(1u, copy_requests.count(last_pass_id)); EXPECT_FALSE(copy_called); - copy_requests.find(2)->second->SendEmptyResult(); + copy_requests.find(last_pass_id)->second->SendEmptyResult(); EXPECT_TRUE(copy_called); - factory.EvictSurface(); + support->EvictFrame(); } } // namespace diff --git a/chromium/cc/surfaces/surfaces_pixeltest.cc b/chromium/cc/surfaces/surfaces_pixeltest.cc index b9809807035..0b81474ccb5 100644 --- a/chromium/cc/surfaces/surfaces_pixeltest.cc +++ b/chromium/cc/surfaces/surfaces_pixeltest.cc @@ -6,11 +6,10 @@ #include "cc/quads/render_pass.h" #include "cc/quads/solid_color_draw_quad.h" #include "cc/quads/surface_draw_quad.h" +#include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_aggregator.h" -#include "cc/surfaces/surface_factory.h" -#include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_manager.h" #include "cc/test/pixel_comparator.h" #include "cc/test/pixel_test.h" @@ -21,28 +20,31 @@ namespace cc { namespace { -static constexpr FrameSinkId kArbitraryRootFrameSinkId(1, 1); -static constexpr FrameSinkId kArbitraryChildFrameSinkId(2, 2); -static constexpr FrameSinkId kArbitraryLeftFrameSinkId(3, 3); -static constexpr FrameSinkId kArbitraryRightFrameSinkId(4, 4); - -class EmptySurfaceFactoryClient : public SurfaceFactoryClient { - public: - void ReturnResources(const ReturnedResourceArray& resources) override {} - void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override {} -}; +constexpr FrameSinkId kArbitraryRootFrameSinkId(1, 1); +constexpr FrameSinkId kArbitraryChildFrameSinkId(2, 2); +constexpr FrameSinkId kArbitraryLeftFrameSinkId(3, 3); +constexpr FrameSinkId kArbitraryRightFrameSinkId(4, 4); +constexpr bool kIsRoot = true; +constexpr bool kIsChildRoot = false; +constexpr bool kHandlesFrameSinkIdInvalidation = true; +constexpr bool kNeedsSyncPoints = true; class SurfacesPixelTest : public RendererPixelTest<GLRenderer> { public: SurfacesPixelTest() - : factory_(kArbitraryRootFrameSinkId, &manager_, &client_) {} - ~SurfacesPixelTest() override { factory_.EvictSurface(); } + : support_( + CompositorFrameSinkSupport::Create(nullptr, + &manager_, + kArbitraryRootFrameSinkId, + kIsRoot, + kHandlesFrameSinkIdInvalidation, + kNeedsSyncPoints)) {} + ~SurfacesPixelTest() override { support_->EvictFrame(); } protected: SurfaceManager manager_; LocalSurfaceIdAllocator allocator_; - EmptySurfaceFactoryClient client_; - SurfaceFactory factory_; + std::unique_ptr<CompositorFrameSinkSupport> support_; }; SharedQuadState* CreateAndAppendTestSharedQuadState( @@ -85,9 +87,8 @@ TEST_F(SurfacesPixelTest, DrawSimpleFrame) { root_frame.render_pass_list.push_back(std::move(pass)); LocalSurfaceId root_local_surface_id = allocator_.GenerateId(); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id); - factory_.SubmitCompositorFrame(root_local_surface_id, std::move(root_frame), - SurfaceFactory::DrawCallback()); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id); + support_->SubmitCompositorFrame(root_local_surface_id, std::move(root_frame)); SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true); CompositorFrame aggregated_frame = aggregator.Aggregate(root_surface_id); @@ -103,12 +104,16 @@ TEST_F(SurfacesPixelTest, DrawSimpleFrame) { // Draws a frame with simple surface embedding. TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) { gfx::Size child_size(200, 100); - SurfaceFactory child_factory(kArbitraryChildFrameSinkId, &manager_, &client_); + std::unique_ptr<CompositorFrameSinkSupport> child_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryChildFrameSinkId, kIsChildRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + LocalSurfaceId child_local_surface_id = allocator_.GenerateId(); - SurfaceId child_surface_id(child_factory.frame_sink_id(), + SurfaceId child_surface_id(child_support->frame_sink_id(), child_local_surface_id); LocalSurfaceId root_local_surface_id = allocator_.GenerateId(); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id); { gfx::Rect rect(device_viewport_size_); @@ -138,8 +143,8 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) { CompositorFrame root_frame; root_frame.render_pass_list.push_back(std::move(pass)); - factory_.SubmitCompositorFrame(root_local_surface_id, std::move(root_frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(root_local_surface_id, + std::move(root_frame)); } { @@ -163,9 +168,8 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) { CompositorFrame child_frame; child_frame.render_pass_list.push_back(std::move(pass)); - child_factory.SubmitCompositorFrame(child_local_surface_id, - std::move(child_frame), - SurfaceFactory::DrawCallback()); + child_support->SubmitCompositorFrame(child_local_surface_id, + std::move(child_frame)); } SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true); @@ -178,7 +182,7 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) { base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")), pixel_comparator)); - child_factory.EvictSurface(); + child_support->EvictFrame(); } // Tests a surface quad that has a non-identity transform into its pass. @@ -192,14 +196,21 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) { // bottom_blue_quad (100x100 @ 0x100) // right_child -> top_blue_quad (100x100 @ 0x0), // bottom_green_quad (100x100 @ 0x100) - SurfaceFactory left_factory(kArbitraryLeftFrameSinkId, &manager_, &client_); - SurfaceFactory right_factory(kArbitraryRightFrameSinkId, &manager_, &client_); + std::unique_ptr<CompositorFrameSinkSupport> left_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryLeftFrameSinkId, kIsChildRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); + std::unique_ptr<CompositorFrameSinkSupport> right_support = + CompositorFrameSinkSupport::Create( + nullptr, &manager_, kArbitraryRightFrameSinkId, kIsChildRoot, + kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId left_child_local_id = allocator_.GenerateId(); - SurfaceId left_child_id(left_factory.frame_sink_id(), left_child_local_id); + SurfaceId left_child_id(left_support->frame_sink_id(), left_child_local_id); LocalSurfaceId right_child_local_id = allocator_.GenerateId(); - SurfaceId right_child_id(right_factory.frame_sink_id(), right_child_local_id); + SurfaceId right_child_id(right_support->frame_sink_id(), + right_child_local_id); LocalSurfaceId root_local_surface_id = allocator_.GenerateId(); - SurfaceId root_surface_id(factory_.frame_sink_id(), root_local_surface_id); + SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id); { gfx::Rect rect(device_viewport_size_); @@ -232,8 +243,8 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) { CompositorFrame root_frame; root_frame.render_pass_list.push_back(std::move(pass)); - factory_.SubmitCompositorFrame(root_local_surface_id, std::move(root_frame), - SurfaceFactory::DrawCallback()); + support_->SubmitCompositorFrame(root_local_surface_id, + std::move(root_frame)); } { @@ -265,9 +276,8 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) { CompositorFrame child_frame; child_frame.render_pass_list.push_back(std::move(pass)); - left_factory.SubmitCompositorFrame(left_child_local_id, - std::move(child_frame), - SurfaceFactory::DrawCallback()); + left_support->SubmitCompositorFrame(left_child_local_id, + std::move(child_frame)); } { @@ -299,9 +309,8 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) { CompositorFrame child_frame; child_frame.render_pass_list.push_back(std::move(pass)); - right_factory.SubmitCompositorFrame(right_child_local_id, - std::move(child_frame), - SurfaceFactory::DrawCallback()); + right_support->SubmitCompositorFrame(right_child_local_id, + std::move(child_frame)); } SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true); @@ -315,8 +324,8 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) { base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")), pixel_comparator)); - left_factory.EvictSurface(); - right_factory.EvictSurface(); + left_support->EvictFrame(); + right_support->EvictFrame(); } } // namespace diff --git a/chromium/cc/tiles/checker_image_tracker.cc b/chromium/cc/tiles/checker_image_tracker.cc index c8113d4d560..8bbcbebe839 100644 --- a/chromium/cc/tiles/checker_image_tracker.cc +++ b/chromium/cc/tiles/checker_image_tracker.cc @@ -5,6 +5,7 @@ #include "cc/tiles/checker_image_tracker.h" #include "base/bind.h" +#include "base/stl_util.h" #include "base/trace_event/trace_event.h" namespace cc { @@ -39,24 +40,27 @@ void CheckerImageTracker::FilterImagesForCheckeringForTile( std::vector<DrawImage>* images, ImageIdFlatSet* checkered_images, WhichTree tree) { + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "CheckerImageTracker::FilterImagesForCheckeringForTile", "tree", + tree); DCHECK(checkered_images->empty()); - auto images_to_checker = std::remove_if( - images->begin(), images->end(), - [this, tree, &checkered_images](const DrawImage& draw_image) { - const sk_sp<const SkImage>& image = draw_image.image(); - DCHECK(image->isLazyGenerated()); - if (ShouldCheckerImage(image, tree)) { - ScheduleImageDecodeIfNecessary(image); - checkered_images->insert(image->uniqueID()); - return true; - } - return false; - }); - images->erase(images_to_checker, images->end()); + base::EraseIf(*images, + [this, tree, &checkered_images](const DrawImage& draw_image) { + const sk_sp<const SkImage>& image = draw_image.image(); + DCHECK(image->isLazyGenerated()); + if (ShouldCheckerImage(image, tree)) { + ScheduleImageDecodeIfNecessary(image); + checkered_images->insert(image->uniqueID()); + return true; + } + return false; + }); } const ImageIdFlatSet& CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "CheckerImageTracker::TakeImagesToInvalidateOnSyncTree"); DCHECK_EQ(invalidated_images_on_current_sync_tree_.size(), 0u) << "Sync tree can not be invalidated more than once"; @@ -66,6 +70,8 @@ const ImageIdFlatSet& CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() { } void CheckerImageTracker::DidActivateSyncTree() { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "CheckerImageTracker::DidActivateSyncTree"); for (auto image_id : invalidated_images_on_current_sync_tree_) { auto it = image_id_to_decode_request_id_.find(image_id); image_controller_->UnlockImageDecode(it->second); @@ -79,6 +85,8 @@ void CheckerImageTracker::DidFinishImageDecode( ImageId image_id, ImageController::ImageDecodeRequestId request_id, ImageController::ImageDecodeResult result) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "CheckerImageTracker::DidFinishImageDecode"); TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", image_id); @@ -131,6 +139,8 @@ bool CheckerImageTracker::ShouldCheckerImage(const sk_sp<const SkImage>& image, void CheckerImageTracker::ScheduleImageDecodeIfNecessary( const sk_sp<const SkImage>& image) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "CheckerImageTracker::ScheduleImageDecodeIfNecessary"); ImageId image_id = image->uniqueID(); // If the image has already been decoded, or a decode request is pending, we diff --git a/chromium/cc/tiles/checker_image_tracker.h b/chromium/cc/tiles/checker_image_tracker.h index b2a16ecf9b2..3bc29f55294 100644 --- a/chromium/cc/tiles/checker_image_tracker.h +++ b/chromium/cc/tiles/checker_image_tracker.h @@ -8,8 +8,8 @@ #include <unordered_map> #include <vector> -#include "cc/base/cc_export.h" -#include "cc/playback/image_id.h" +#include "cc/cc_export.h" +#include "cc/paint/image_id.h" #include "cc/tiles/image_controller.h" #include "third_party/skia/include/core/SkImage.h" diff --git a/chromium/cc/tiles/checker_image_tracker_unittest.cc b/chromium/cc/tiles/checker_image_tracker_unittest.cc index a60bcf75f5b..9ca8d39f344 100644 --- a/chromium/cc/tiles/checker_image_tracker_unittest.cc +++ b/chromium/cc/tiles/checker_image_tracker_unittest.cc @@ -50,7 +50,7 @@ class TestImageController : public ImageController { // ImageController. worker_task_runner_->PostTask( FROM_HERE, - base::Bind(callback, request_id, ImageDecodeResult::SUCCESS)); + base::BindOnce(callback, request_id, ImageDecodeResult::SUCCESS)); return request_id; } @@ -79,8 +79,9 @@ class CheckerImageTrackerTest : public testing::Test, : kNonCheckerableImageDimension; sk_sp<SkImage> image = CreateDiscardableImage(gfx::Size(dimension, dimension)); + gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB(); return DrawImage(image, SkIRect::MakeWH(image->width(), image->height()), - kNone_SkFilterQuality, SkMatrix::I()); + kNone_SkFilterQuality, SkMatrix::I(), target_color_space); } // CheckerImageTrackerClient implementation. diff --git a/chromium/cc/playback/decoded_draw_image.cc b/chromium/cc/tiles/decoded_draw_image.cc index fa5c3b49e33..f68c6c0c269 100644 --- a/chromium/cc/playback/decoded_draw_image.cc +++ b/chromium/cc/tiles/decoded_draw_image.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/playback/decoded_draw_image.h" +#include "cc/tiles/decoded_draw_image.h" namespace cc { diff --git a/chromium/cc/playback/decoded_draw_image.h b/chromium/cc/tiles/decoded_draw_image.h index 8003fa6074f..24e4ac4a921 100644 --- a/chromium/cc/playback/decoded_draw_image.h +++ b/chromium/cc/tiles/decoded_draw_image.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_PLAYBACK_DECODED_DRAW_IMAGE_H_ -#define CC_PLAYBACK_DECODED_DRAW_IMAGE_H_ +#ifndef CC_TILES_DECODED_DRAW_IMAGE_H_ +#define CC_TILES_DECODED_DRAW_IMAGE_H_ #include <cfloat> #include <cmath> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "third_party/skia/include/core/SkFilterQuality.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkRefCnt.h" @@ -50,4 +50,4 @@ class CC_EXPORT DecodedDrawImage { } // namespace cc -#endif // CC_PLAYBACK_DECODED_DRAW_IMAGE_H_ +#endif // CC_TILES_DECODED_DRAW_IMAGE_H_ diff --git a/chromium/cc/tiles/decoded_image_tracker.h b/chromium/cc/tiles/decoded_image_tracker.h index a0016a3be33..01597026138 100644 --- a/chromium/cc/tiles/decoded_image_tracker.h +++ b/chromium/cc/tiles/decoded_image_tracker.h @@ -9,7 +9,7 @@ #include <vector> #include "base/bind.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/tiles/image_controller.h" class SkImage; diff --git a/chromium/cc/tiles/eviction_tile_priority_queue.h b/chromium/cc/tiles/eviction_tile_priority_queue.h index d97bee6a238..2e76ee8c619 100644 --- a/chromium/cc/tiles/eviction_tile_priority_queue.h +++ b/chromium/cc/tiles/eviction_tile_priority_queue.h @@ -10,7 +10,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/picture_layer_impl.h" #include "cc/tiles/tile_priority.h" #include "cc/tiles/tiling_set_eviction_queue.h" diff --git a/chromium/cc/debug/frame_viewer_instrumentation.cc b/chromium/cc/tiles/frame_viewer_instrumentation.cc index d34907a8746..e04f2018bf5 100644 --- a/chromium/cc/debug/frame_viewer_instrumentation.cc +++ b/chromium/cc/tiles/frame_viewer_instrumentation.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/frame_viewer_instrumentation.h" +#include "cc/tiles/frame_viewer_instrumentation.h" #include "cc/debug/traced_value.h" diff --git a/chromium/cc/debug/frame_viewer_instrumentation.h b/chromium/cc/tiles/frame_viewer_instrumentation.h index 119e523df23..d4cef013021 100644 --- a/chromium/cc/debug/frame_viewer_instrumentation.h +++ b/chromium/cc/tiles/frame_viewer_instrumentation.h @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_FRAME_VIEWER_INSTRUMENTATION_H_ -#define CC_DEBUG_FRAME_VIEWER_INSTRUMENTATION_H_ +#ifndef CC_TILES_FRAME_VIEWER_INSTRUMENTATION_H_ +#define CC_TILES_FRAME_VIEWER_INSTRUMENTATION_H_ #include "base/macros.h" #include "base/trace_event/trace_event.h" -#include "cc/tiles/tile.h" #include "cc/tiles/tile_priority.h" namespace cc { @@ -44,4 +43,4 @@ bool IsTracingLayerTreeSnapshots(); } // namespace frame_viewer_instrumentation } // namespace cc -#endif // CC_DEBUG_FRAME_VIEWER_INSTRUMENTATION_H_ +#endif // CC_TILES_FRAME_VIEWER_INSTRUMENTATION_H_ diff --git a/chromium/cc/tiles/gpu_image_decode_cache.cc b/chromium/cc/tiles/gpu_image_decode_cache.cc index 735afc7f6cb..39a822617db 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache.cc @@ -8,6 +8,7 @@ #include "base/auto_reset.h" #include "base/debug/alias.h" +#include "base/hash.h" #include "base/memory/discardable_memory_allocator.h" #include "base/memory/memory_coordinator_client_registry.h" #include "base/memory/ptr_util.h" @@ -16,7 +17,7 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/output/context_provider.h" #include "cc/raster/tile_task.h" #include "cc/resources/resource_format_utils.h" @@ -109,30 +110,37 @@ gfx::Size CalculateSizeForMipLevel(const DrawImage& draw_image, int mip_level) { return MipMapUtil::GetSizeForLevel(base_size, mip_level); } -// Generates a uint64_t which uniquely identifies a DrawImage for the purposes -// of the |in_use_cache_|. The key is generated as follows: -// ╔══════════════════════╤═══════════╤═══════════╗ -// ║ image_id │ mip_level │ quality ║ -// ╚════════32═bits═══════╧══16═bits══╧══16═bits══╝ -uint64_t GenerateInUseCacheKey(const DrawImage& draw_image) { - static_assert( - kLast_SkFilterQuality <= std::numeric_limits<uint16_t>::max(), - "InUseCacheKey depends on SkFilterQuality fitting in a uint16_t."); - - SkFilterQuality filter_quality = - CalculateUploadScaleFilterQuality(draw_image); - DCHECK_LE(filter_quality, kLast_SkFilterQuality); - - // An image has at most log_2(max(width, height)) mip levels, so given our - // usage of 32-bit sizes for images, key.mip_level is at most 31. - int32_t mip_level = CalculateUploadScaleMipLevel(draw_image); - DCHECK_LT(mip_level, 32); - - return (static_cast<uint64_t>(draw_image.image()->uniqueID()) << 32) | - (mip_level << 16) | filter_quality; +} // namespace + +// static +GpuImageDecodeCache::InUseCacheKey +GpuImageDecodeCache::InUseCacheKey::FromDrawImage(const DrawImage& draw_image) { + return InUseCacheKey(draw_image); } -} // namespace +// Extract the information to uniquely identify a DrawImage for the purposes of +// the |in_use_cache_|. +GpuImageDecodeCache::InUseCacheKey::InUseCacheKey(const DrawImage& draw_image) + : image_id(draw_image.image()->uniqueID()), + mip_level(CalculateUploadScaleMipLevel(draw_image)), + filter_quality(CalculateUploadScaleFilterQuality(draw_image)), + target_color_space(draw_image.target_color_space()) {} + +bool GpuImageDecodeCache::InUseCacheKey::operator==( + const InUseCacheKey& other) const { + return image_id == other.image_id && mip_level == other.mip_level && + filter_quality == other.filter_quality && + target_color_space == other.target_color_space; +} + +size_t GpuImageDecodeCache::InUseCacheKeyHash::operator()( + const InUseCacheKey& cache_key) const { + return base::HashInts( + cache_key.target_color_space.GetHash(), + base::HashInts( + cache_key.image_id, + base::HashInts(cache_key.mip_level, cache_key.filter_quality))); +} GpuImageDecodeCache::InUseCacheEntry::InUseCacheEntry( scoped_refptr<ImageData> image_data) @@ -326,8 +334,12 @@ void GpuImageDecodeCache::UploadedImageData::ReportUsageStats() const { GpuImageDecodeCache::ImageData::ImageData( DecodedDataMode mode, size_t size, + const gfx::ColorSpace& target_color_space, const SkImage::DeferredTextureImageUsageParams& upload_params) - : mode(mode), size(size), upload_params(upload_params) {} + : mode(mode), + size(size), + target_color_space(target_color_space), + upload_params(upload_params) {} GpuImageDecodeCache::ImageData::~ImageData() { // We should never delete ImageData while it is in use or before it has been @@ -342,11 +354,15 @@ GpuImageDecodeCache::ImageData::~ImageData() { GpuImageDecodeCache::GpuImageDecodeCache(ContextProvider* context, ResourceFormat decode_format, - size_t max_gpu_image_bytes) + size_t max_working_set_bytes, + size_t max_cache_bytes) : format_(decode_format), context_(context), persistent_cache_(PersistentCache::NO_AUTO_EVICT), - normal_max_gpu_image_bytes_(max_gpu_image_bytes) { + max_working_set_bytes_(max_working_set_bytes), + normal_max_cache_bytes_(max_cache_bytes) { + DCHECK_GE(max_working_set_bytes_, normal_max_cache_bytes_); + // Acquire the context_lock so that we can safely retrieve the // GrContextThreadSafeProxy. This proxy can then be used with no lock held. { @@ -576,7 +592,27 @@ void GpuImageDecodeCache::SetShouldAggressivelyFreeResources( DeletePendingImages(); } else { base::AutoLock lock(lock_); - cached_bytes_limit_ = normal_max_gpu_image_bytes_; + cached_bytes_limit_ = normal_max_cache_bytes_; + } +} + +void GpuImageDecodeCache::ClearCache() { + base::AutoLock lock(lock_); + for (auto it = persistent_cache_.begin(); it != persistent_cache_.end();) { + if (it->second->decode.ref_count != 0 || + it->second->upload.ref_count != 0) { + ++it; + continue; + } + + if (it->second->upload.image()) { + bytes_used_ -= it->second->size; + images_pending_deletion_.push_back(it->second->upload.image()); + it->second->upload.SetImage(nullptr); + it->second->upload.budgeted = false; + } + + it = persistent_cache_.Erase(it); } } @@ -762,7 +798,7 @@ void GpuImageDecodeCache::RefImageDecode(const DrawImage& draw_image) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "GpuImageDecodeCache::RefImageDecode"); lock_.AssertAcquired(); - auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image)); + auto found = in_use_cache_.find(InUseCacheKey::FromDrawImage(draw_image)); DCHECK(found != in_use_cache_.end()); ++found->second.ref_count; ++found->second.image_data->decode.ref_count; @@ -773,7 +809,7 @@ void GpuImageDecodeCache::UnrefImageDecode(const DrawImage& draw_image) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "GpuImageDecodeCache::UnrefImageDecode"); lock_.AssertAcquired(); - auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image)); + auto found = in_use_cache_.find(InUseCacheKey::FromDrawImage(draw_image)); DCHECK(found != in_use_cache_.end()); DCHECK_GT(found->second.image_data->decode.ref_count, 0u); DCHECK_GT(found->second.ref_count, 0u); @@ -789,7 +825,7 @@ void GpuImageDecodeCache::RefImage(const DrawImage& draw_image) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "GpuImageDecodeCache::RefImage"); lock_.AssertAcquired(); - InUseCacheKey key = GenerateInUseCacheKey(draw_image); + InUseCacheKey key = InUseCacheKey::FromDrawImage(draw_image); auto found = in_use_cache_.find(key); // If no secondary cache entry was found for the given |draw_image|, then @@ -798,8 +834,7 @@ void GpuImageDecodeCache::RefImage(const DrawImage& draw_image) { if (found == in_use_cache_.end()) { auto found_image = persistent_cache_.Peek(draw_image.image()->uniqueID()); DCHECK(found_image != persistent_cache_.end()); - DCHECK(found_image->second->upload_params.fPreScaleMipLevel <= - CalculateUploadScaleMipLevel(draw_image)); + DCHECK(IsCompatible(found_image->second.get(), draw_image)); found = in_use_cache_ .insert(InUseCache::value_type( key, InUseCacheEntry(found_image->second))) @@ -814,7 +849,7 @@ void GpuImageDecodeCache::RefImage(const DrawImage& draw_image) { void GpuImageDecodeCache::UnrefImageInternal(const DrawImage& draw_image) { lock_.AssertAcquired(); - auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image)); + auto found = in_use_cache_.find(InUseCacheKey::FromDrawImage(draw_image)); DCHECK(found != in_use_cache_.end()); DCHECK_GT(found->second.image_data->upload.ref_count, 0u); DCHECK_GT(found->second.ref_count, 0u); @@ -862,7 +897,7 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, if (image_data->is_at_raster && !has_any_refs) { // We have an at-raster image which has reached zero refs. If it won't fit // in our cache, delete the image to allow it to fit. - if (image_data->upload.image() && !CanFitSize(image_data->size)) { + if (image_data->upload.image() && !CanFitInCache(image_data->size)) { images_pending_deletion_.push_back(image_data->upload.image()); image_data->upload.SetImage(nullptr); } @@ -881,7 +916,7 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, if (image_data->upload.ref_count > 0 && !image_data->upload.budgeted && !image_data->is_at_raster) { // We should only be taking non-at-raster refs on images that fit in cache. - DCHECK(CanFitSize(image_data->size)); + DCHECK(CanFitInWorkingSet(image_data->size)); bytes_used_ += image_data->size; image_data->upload.budgeted = true; @@ -911,6 +946,9 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, image_data->decode.Unlock(); } + // EnsureCapacity to make sure we are under our cache limits. + EnsureCapacity(0); + #if DCHECK_IS_ON() // Sanity check the above logic. if (image_data->upload.image()) { @@ -923,15 +961,19 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, #endif } -// Ensures that we can fit a new image of size |required_size| in our cache. In -// doing so, this function will free unreferenced image data as necessary to -// create rooom. +// Ensures that we can fit a new image of size |required_size| in our working +// set. In doing so, this function will free unreferenced image data as +// necessary to create rooom. bool GpuImageDecodeCache::EnsureCapacity(size_t required_size) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "GpuImageDecodeCache::EnsureCapacity"); lock_.AssertAcquired(); - if (CanFitSize(required_size) && !ExceedsPreferredCount()) + // While we only care whether |required_size| fits in our working set, we + // also want to keep our cache under-budget if possible. Working set size + // will always match or exceed cache size, so keeping the cache under budget + // may be impossible. + if (CanFitInCache(required_size) && !ExceedsPreferredCount()) return true; // While we are over memory or preferred item capacity, we iterate through @@ -970,16 +1012,14 @@ bool GpuImageDecodeCache::EnsureCapacity(size_t required_size) { ++it; } - if (CanFitSize(required_size) && !ExceedsPreferredCount()) + if (CanFitInCache(required_size) && !ExceedsPreferredCount()) return true; } - // Preferred count is only used as a guideline when triming the cache. Allow - // new elements to be added as long as we are below our size limit. - return CanFitSize(required_size); + return CanFitInWorkingSet(required_size); } -bool GpuImageDecodeCache::CanFitSize(size_t size) const { +bool GpuImageDecodeCache::CanFitInCache(size_t size) const { lock_.AssertAcquired(); size_t bytes_limit; @@ -997,6 +1037,14 @@ bool GpuImageDecodeCache::CanFitSize(size_t size) const { return new_size.IsValid() && new_size.ValueOrDie() <= bytes_limit; } +bool GpuImageDecodeCache::CanFitInWorkingSet(size_t size) const { + lock_.AssertAcquired(); + + base::CheckedNumeric<uint32_t> new_size(bytes_used_); + new_size += size; + return new_size.IsValid() && new_size.ValueOrDie() <= max_working_set_bytes_; +} + bool GpuImageDecodeCache::ExceedsPreferredCount() const { lock_.AssertAcquired(); @@ -1059,6 +1107,7 @@ void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image, if (!draw_image.image()->scalePixels( image_pixmap, CalculateUploadScaleFilterQuality(draw_image), SkImage::kDisallow_CachingHint)) { + DLOG(ERROR) << "scalePixels failed."; backing_memory->Unlock(); backing_memory.reset(); } @@ -1068,10 +1117,11 @@ void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image, // TODO(crbug.com/649167): Params should not have changed since initial // sizing. Somehow this still happens. We should investigate and re-add // DCHECKs here to enforce this. - if (!draw_image.image()->getDeferredTextureImageData( *context_threadsafe_proxy_.get(), &image_data->upload_params, 1, - backing_memory->data())) { + backing_memory->data(), nullptr)) { + DLOG(ERROR) << "getDeferredTextureImageData failed despite params " + << "having validated."; backing_memory->Unlock(); backing_memory.reset(); } @@ -1143,6 +1193,14 @@ void GpuImageDecodeCache::UploadImageIfNecessary(const DrawImage& draw_image, image_data->decode.mark_used(); DCHECK(uploaded_image); + if (draw_image.target_color_space().IsValid()) { + TRACE_EVENT0("cc", "GpuImageDecodeCache::UploadImage - color conversion"); + uploaded_image = uploaded_image->makeColorSpace( + draw_image.target_color_space().ToSkColorSpace(), + SkTransferFunctionBehavior::kIgnore); + } + DCHECK(uploaded_image); + // At-raster may have decoded this while we were unlocked. If so, ignore our // result. if (!image_data->upload.image()) @@ -1161,7 +1219,7 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image) { draw_image.matrix(), CalculateUploadScaleFilterQuality(draw_image), upload_scale_mip_level); size_t data_size = draw_image.image()->getDeferredTextureImageData( - *context_threadsafe_proxy_.get(), ¶ms, 1, nullptr); + *context_threadsafe_proxy_.get(), ¶ms, 1, nullptr, nullptr); if (data_size == 0) { // Can't upload image, too large or other failure. Try to use SW fallback. @@ -1173,7 +1231,8 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image) { mode = DecodedDataMode::GPU; } - return make_scoped_refptr(new ImageData(mode, data_size, params)); + return make_scoped_refptr( + new ImageData(mode, data_size, draw_image.target_color_space(), params)); } void GpuImageDecodeCache::DeletePendingImages() { @@ -1189,7 +1248,8 @@ SkImageInfo GpuImageDecodeCache::CreateImageInfoForDrawImage( CalculateSizeForMipLevel(draw_image, upload_scale_mip_level); return SkImageInfo::Make(mip_size.width(), mip_size.height(), ResourceFormatToClosestSkColorType(format_), - kPremul_SkAlphaType); + kPremul_SkAlphaType, + draw_image.target_color_space().ToSkColorSpace()); } // Tries to find an ImageData that can be used to draw the provided @@ -1200,7 +1260,8 @@ GpuImageDecodeCache::ImageData* GpuImageDecodeCache::GetImageDataForDrawImage( TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "GpuImageDecodeCache::GetImageDataForDrawImage"); lock_.AssertAcquired(); - auto found_in_use = in_use_cache_.find(GenerateInUseCacheKey(draw_image)); + auto found_in_use = + in_use_cache_.find(InUseCacheKey::FromDrawImage(draw_image)); if (found_in_use != in_use_cache_.end()) return found_in_use->second.image_data.get(); @@ -1233,7 +1294,13 @@ bool GpuImageDecodeCache::IsCompatible(const ImageData* image_data, image_data->upload_params.fPreScaleMipLevel; bool quality_is_compatible = CalculateUploadScaleFilterQuality(draw_image) <= image_data->upload_params.fQuality; - return !is_scaled || (scale_is_compatible && quality_is_compatible); + bool color_is_compatible = + image_data->target_color_space == draw_image.target_color_space(); + if (!color_is_compatible) + return false; + if (is_scaled && (!scale_is_compatible || !quality_is_compatible)) + return false; + return true; } size_t GpuImageDecodeCache::GetDrawImageSizeForTesting(const DrawImage& image) { @@ -1262,7 +1329,7 @@ bool GpuImageDecodeCache::DiscardableIsLockedForTesting( bool GpuImageDecodeCache::IsInInUseCacheForTesting( const DrawImage& image) const { - auto found = in_use_cache_.find(GenerateInUseCacheKey(image)); + auto found = in_use_cache_.find(InUseCacheKey::FromDrawImage(image)); return found != in_use_cache_.end(); } diff --git a/chromium/cc/tiles/gpu_image_decode_cache.h b/chromium/cc/tiles/gpu_image_decode_cache.h index 14e49961fae..391f048c2e9 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache.h +++ b/chromium/cc/tiles/gpu_image_decode_cache.h @@ -14,7 +14,7 @@ #include "base/memory/memory_coordinator_client.h" #include "base/synchronization/lock.h" #include "base/trace_event/memory_dump_provider.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/resources/resource_format.h" #include "cc/tiles/image_decode_cache.h" #include "third_party/skia/include/core/SkRefCnt.h" @@ -103,7 +103,8 @@ class CC_EXPORT GpuImageDecodeCache explicit GpuImageDecodeCache(ContextProvider* context, ResourceFormat decode_format, - size_t max_gpu_image_bytes); + size_t max_working_set_bytes, + size_t max_cache_bytes); ~GpuImageDecodeCache() override; // ImageDecodeCache overrides. @@ -123,6 +124,7 @@ class CC_EXPORT GpuImageDecodeCache void ReduceCacheUsage() override; void SetShouldAggressivelyFreeResources( bool aggressively_free_resources) override; + void ClearCache() override; // MemoryDumpProvider overrides. bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, @@ -142,8 +144,9 @@ class CC_EXPORT GpuImageDecodeCache void OnImageUploadTaskCompleted(const DrawImage& image); // For testing only. - void SetCachedBytesLimitForTesting(size_t limit) { + void SetAllByteLimitsForTesting(size_t limit) { cached_bytes_limit_ = limit; + max_working_set_bytes_ = limit; } size_t GetBytesUsedForTesting() const { return bytes_used_; } size_t GetNumCacheEntriesForTesting() const { @@ -230,10 +233,12 @@ class CC_EXPORT GpuImageDecodeCache struct ImageData : public base::RefCounted<ImageData> { ImageData(DecodedDataMode mode, size_t size, + const gfx::ColorSpace& target_color_space, const SkImage::DeferredTextureImageUsageParams& upload_params); const DecodedDataMode mode; const size_t size; + gfx::ColorSpace target_color_space; bool is_at_raster = false; SkImage::DeferredTextureImageUsageParams upload_params; @@ -263,7 +268,23 @@ class CC_EXPORT GpuImageDecodeCache // Uniquely identifies (without collisions) a specific DrawImage for use in // the |in_use_cache_|. - using InUseCacheKey = uint64_t; + struct InUseCacheKeyHash; + struct InUseCacheKey { + static InUseCacheKey FromDrawImage(const DrawImage& draw_image); + bool operator==(const InUseCacheKey& other) const; + + private: + friend struct GpuImageDecodeCache::InUseCacheKeyHash; + explicit InUseCacheKey(const DrawImage& draw_image); + + uint32_t image_id; + int mip_level; + SkFilterQuality filter_quality; + gfx::ColorSpace target_color_space; + }; + struct InUseCacheKeyHash { + size_t operator()(const InUseCacheKey&) const; + }; // All private functions should only be called while holding |lock_|. Some // functions also require the |context_| lock. These are indicated by @@ -292,10 +313,11 @@ class CC_EXPORT GpuImageDecodeCache // to ref-count or to orphaned status. void OwnershipChanged(const DrawImage& draw_image, ImageData* image_data); - // Ensures that the cache can hold an element of |required_size|, freeing - // unreferenced cache entries if necessary to make room. + // Ensures that the working set can hold an element of |required_size|, + // freeing unreferenced cache entries to make room. bool EnsureCapacity(size_t required_size); - bool CanFitSize(size_t size) const; + bool CanFitInWorkingSet(size_t size) const; + bool CanFitInCache(size_t size) const; bool ExceedsPreferredCount() const; void DecodeImageIfNecessary(const DrawImage& draw_image, @@ -334,11 +356,13 @@ class CC_EXPORT GpuImageDecodeCache // |in_use_cache_| represents the in-use (short-lived) cache. Entries are // cleaned up as soon as their ref count reaches zero. - using InUseCache = std::unordered_map<InUseCacheKey, InUseCacheEntry>; + using InUseCache = + std::unordered_map<InUseCacheKey, InUseCacheEntry, InUseCacheKeyHash>; InUseCache in_use_cache_; - const size_t normal_max_gpu_image_bytes_; - size_t cached_bytes_limit_ = normal_max_gpu_image_bytes_; + size_t max_working_set_bytes_; + const size_t normal_max_cache_bytes_; + size_t cached_bytes_limit_ = normal_max_cache_bytes_; size_t bytes_used_ = 0; base::MemoryState memory_state_ = base::MemoryState::NORMAL; diff --git a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc index 901c7f8476f..91a08d1f40c 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc @@ -4,7 +4,7 @@ #include "cc/tiles/gpu_image_decode_cache.h" -#include "cc/playback/draw_image.h" +#include "cc/paint/draw_image.h" #include "cc/test/test_context_provider.h" #include "cc/test/test_tile_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,18 +13,25 @@ namespace cc { namespace { +gfx::ColorSpace DefaultColorSpace() { + return gfx::ColorSpace::CreateSRGB(); +} + size_t kGpuMemoryLimitBytes = 96 * 1024 * 1024; class TestGpuImageDecodeCache : public GpuImageDecodeCache { public: explicit TestGpuImageDecodeCache(ContextProvider* context) : GpuImageDecodeCache(context, ResourceFormat::RGBA_8888, + kGpuMemoryLimitBytes, kGpuMemoryLimitBytes) {} }; sk_sp<SkImage> CreateImage(int width, int height) { SkBitmap bitmap; - bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height)); + gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB(); + bitmap.allocPixels( + SkImageInfo::MakeN32Premul(width, height, color_space.ToSkColorSpace())); return SkImage::MakeFromBitmap(bitmap); } @@ -50,7 +57,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageSameImage) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -59,7 +67,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageSameImage) { DrawImage another_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> another_task; need_unref = cache.GetTaskForImageAndRef( another_draw_image, ImageDecodeCache::TracingInfo(), &another_task); @@ -83,7 +92,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageSmallerScale) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -92,7 +102,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageSmallerScale) { DrawImage another_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> another_task; need_unref = cache.GetTaskForImageAndRef( another_draw_image, ImageDecodeCache::TracingInfo(), &another_task); @@ -106,7 +117,13 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageSmallerScale) { cache.UnrefImage(another_draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageLowerQuality) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageLowerQuality DISABLED_GetTaskForImageLowerQuality +#else +#define MAYBE_GetTaskForImageLowerQuality GetTaskForImageLowerQuality +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLowerQuality) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -115,16 +132,16 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLowerQuality) { SkMatrix matrix = CreateMatrix(SkSize::Make(0.4f, 0.4f), is_decomposable); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), - kHigh_SkFilterQuality, matrix); + kHigh_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); EXPECT_TRUE(need_unref); EXPECT_TRUE(task); - DrawImage another_draw_image(image, - SkIRect::MakeWH(image->width(), image->height()), - kLow_SkFilterQuality, matrix); + DrawImage another_draw_image( + image, SkIRect::MakeWH(image->width(), image->height()), + kLow_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> another_task; need_unref = cache.GetTaskForImageAndRef( another_draw_image, ImageDecodeCache::TracingInfo(), &another_task); @@ -138,7 +155,14 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLowerQuality) { cache.UnrefImage(another_draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentImage) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageDifferentImage \ + DISABLED_GetTaskForImageDifferentImage +#else +#define MAYBE_GetTaskForImageDifferentImage GetTaskForImageDifferentImage +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentImage) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -148,7 +172,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentImage) { sk_sp<SkImage> first_image = CreateImage(100, 100); DrawImage first_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> first_task; bool need_unref = cache.GetTaskForImageAndRef( first_draw_image, ImageDecodeCache::TracingInfo(), &first_task); @@ -159,7 +184,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentImage) { DrawImage second_draw_image( second_image, SkIRect::MakeWH(second_image->width(), second_image->height()), quality, - CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable)); + CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> second_task; need_unref = cache.GetTaskForImageAndRef( second_draw_image, ImageDecodeCache::TracingInfo(), &second_task); @@ -176,7 +202,13 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentImage) { cache.UnrefImage(second_draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScale) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageLargerScale DISABLED_GetTaskForImageLargerScale +#else +#define MAYBE_GetTaskForImageLargerScale GetTaskForImageLargerScale +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScale) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -186,7 +218,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScale) { sk_sp<SkImage> first_image = CreateImage(100, 100); DrawImage first_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> first_task; bool need_unref = cache.GetTaskForImageAndRef( first_draw_image, ImageDecodeCache::TracingInfo(), &first_task); @@ -200,7 +233,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScale) { DrawImage second_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> second_task; need_unref = cache.GetTaskForImageAndRef( second_draw_image, ImageDecodeCache::TracingInfo(), &second_task); @@ -210,7 +244,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScale) { DrawImage third_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> third_task; need_unref = cache.GetTaskForImageAndRef( third_draw_image, ImageDecodeCache::TracingInfo(), &third_task); @@ -224,7 +259,15 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScale) { cache.UnrefImage(third_draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScaleNoReuse) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageLargerScaleNoReuse \ + DISABLED_GetTaskForImageLargerScaleNoReuse +#else +#define MAYBE_GetTaskForImageLargerScaleNoReuse \ + GetTaskForImageLargerScaleNoReuse +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScaleNoReuse) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -234,7 +277,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScaleNoReuse) { sk_sp<SkImage> first_image = CreateImage(100, 100); DrawImage first_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> first_task; bool need_unref = cache.GetTaskForImageAndRef( first_draw_image, ImageDecodeCache::TracingInfo(), &first_task); @@ -243,7 +287,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScaleNoReuse) { DrawImage second_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> second_task; need_unref = cache.GetTaskForImageAndRef( second_draw_image, ImageDecodeCache::TracingInfo(), &second_task); @@ -253,7 +298,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScaleNoReuse) { DrawImage third_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> third_task; need_unref = cache.GetTaskForImageAndRef( third_draw_image, ImageDecodeCache::TracingInfo(), &third_task); @@ -270,7 +316,13 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageLargerScaleNoReuse) { cache.UnrefImage(third_draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageHigherQuality) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageHigherQuality DISABLED_GetTaskForImageHigherQuality +#else +#define MAYBE_GetTaskForImageHigherQuality GetTaskForImageHigherQuality +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageHigherQuality) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -280,7 +332,7 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageHigherQuality) { sk_sp<SkImage> first_image = CreateImage(100, 100); DrawImage first_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - kLow_SkFilterQuality, matrix); + kLow_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> first_task; bool need_unref = cache.GetTaskForImageAndRef( first_draw_image, ImageDecodeCache::TracingInfo(), &first_task); @@ -294,7 +346,7 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageHigherQuality) { DrawImage second_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - kHigh_SkFilterQuality, matrix); + kHigh_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> second_task; need_unref = cache.GetTaskForImageAndRef( second_draw_image, ImageDecodeCache::TracingInfo(), &second_task); @@ -308,7 +360,15 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageHigherQuality) { cache.UnrefImage(second_draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageAlreadyDecodedAndLocked) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageAlreadyDecodedAndLocked \ + DISABLED_GetTaskForImageAlreadyDecodedAndLocked +#else +#define MAYBE_GetTaskForImageAlreadyDecodedAndLocked \ + GetTaskForImageAlreadyDecodedAndLocked +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageAlreadyDecodedAndLocked) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -318,7 +378,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageAlreadyDecodedAndLocked) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -353,7 +414,15 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageAlreadyDecodedAndLocked) { cache.UnrefImage(draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageAlreadyDecodedNotLocked) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageAlreadyDecodedNotLocked \ + DISABLED_GetTaskForImageAlreadyDecodedNotLocked +#else +#define MAYBE_GetTaskForImageAlreadyDecodedNotLocked \ + GetTaskForImageAlreadyDecodedNotLocked +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageAlreadyDecodedNotLocked) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -363,7 +432,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageAlreadyDecodedNotLocked) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -398,7 +468,14 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageAlreadyDecodedNotLocked) { cache.UnrefImage(draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageAlreadyUploaded) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageAlreadyUploaded \ + DISABLED_GetTaskForImageAlreadyUploaded +#else +#define MAYBE_GetTaskForImageAlreadyUploaded GetTaskForImageAlreadyUploaded +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageAlreadyUploaded) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -408,7 +485,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageAlreadyUploaded) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -433,7 +511,15 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageAlreadyUploaded) { cache.UnrefImage(draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageCanceledGetsNewTask) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageCanceledGetsNewTask \ + DISABLED_GetTaskForImageCanceledGetsNewTask +#else +#define MAYBE_GetTaskForImageCanceledGetsNewTask \ + GetTaskForImageCanceledGetsNewTask +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageCanceledGetsNewTask) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -443,7 +529,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageCanceledGetsNewTask) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -480,7 +567,16 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageCanceledGetsNewTask) { cache.UnrefImage(draw_image); } -TEST(GpuImageDecodeCacheTest, GetTaskForImageCanceledWhileReffedGetsNewTask) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetTaskForImageCanceledWhileReffedGetsNewTask \ + DISABLED_GetTaskForImageCanceledWhileReffedGetsNewTask +#else +#define MAYBE_GetTaskForImageCanceledWhileReffedGetsNewTask \ + GetTaskForImageCanceledWhileReffedGetsNewTask +#endif +TEST(GpuImageDecodeCacheTest, + MAYBE_GetTaskForImageCanceledWhileReffedGetsNewTask) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -490,7 +586,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageCanceledWhileReffedGetsNewTask) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -531,7 +628,15 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageCanceledWhileReffedGetsNewTask) { cache.UnrefImage(draw_image); } -TEST(GpuImageDecodeCacheTest, NoTaskForImageAlreadyFailedDecoding) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_NoTaskForImageAlreadyFailedDecoding \ + DISABLED_NoTaskForImageAlreadyFailedDecoding +#else +#define MAYBE_NoTaskForImageAlreadyFailedDecoding \ + NoTaskForImageAlreadyFailedDecoding +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_NoTaskForImageAlreadyFailedDecoding) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -541,7 +646,8 @@ TEST(GpuImageDecodeCacheTest, NoTaskForImageAlreadyFailedDecoding) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -564,7 +670,13 @@ TEST(GpuImageDecodeCacheTest, NoTaskForImageAlreadyFailedDecoding) { cache.UnrefImage(draw_image); } -TEST(GpuImageDecodeCacheTest, GetDecodedImageForDraw) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetDecodedImageForDraw DISABLED_GetDecodedImageForDraw +#else +#define MAYBE_GetDecodedImageForDraw GetDecodedImageForDraw +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDraw) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -574,7 +686,8 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDraw) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -608,7 +721,8 @@ TEST(GpuImageDecodeCacheTest, GetLargeDecodedImageForDraw) { sk_sp<SkImage> image = CreateImage(1, 24000); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -640,12 +754,13 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) { bool is_decomposable = true; SkFilterQuality quality = kHigh_SkFilterQuality; - cache.SetCachedBytesLimitForTesting(0); + cache.SetAllByteLimitsForTesting(0); sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -666,7 +781,15 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) { cache.DrawWithImageFinished(draw_image, decoded_draw_image); } -TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawLargerScale) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetDecodedImageForDrawLargerScale \ + DISABLED_GetDecodedImageForDrawLargerScale +#else +#define MAYBE_GetDecodedImageForDrawLargerScale \ + GetDecodedImageForDrawLargerScale +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawLargerScale) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -676,7 +799,8 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawLargerScale) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -688,7 +812,8 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawLargerScale) { DrawImage larger_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> larger_task; bool larger_need_unref = cache.GetTaskForImageAndRef( larger_draw_image, ImageDecodeCache::TracingInfo(), &larger_task); @@ -723,7 +848,15 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawLargerScale) { cache.UnrefImage(larger_draw_image); } -TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawHigherQuality) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetDecodedImageForDrawHigherQuality \ + DISABLED_GetDecodedImageForDrawHigherQuality +#else +#define MAYBE_GetDecodedImageForDrawHigherQuality \ + GetDecodedImageForDrawHigherQuality +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawHigherQuality) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -732,7 +865,7 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawHigherQuality) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), - kLow_SkFilterQuality, matrix); + kLow_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -744,7 +877,7 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawHigherQuality) { DrawImage higher_quality_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), - kHigh_SkFilterQuality, matrix); + kHigh_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> hq_task; bool hq_needs_unref = cache.GetTaskForImageAndRef( higher_quality_draw_image, ImageDecodeCache::TracingInfo(), &hq_task); @@ -780,7 +913,14 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawHigherQuality) { cache.UnrefImage(higher_quality_draw_image); } -TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawNegative) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetDecodedImageForDrawNegative \ + DISABLED_GetDecodedImageForDrawNegative +#else +#define MAYBE_GetDecodedImageForDrawNegative GetDecodedImageForDrawNegative +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawNegative) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -788,9 +928,10 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawNegative) { SkFilterQuality quality = kHigh_SkFilterQuality; sk_sp<SkImage> image = CreateImage(100, 100); - DrawImage draw_image( - image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(-0.5f, 0.5f), is_decomposable)); + DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), + quality, + CreateMatrix(SkSize::Make(-0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -816,7 +957,15 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawNegative) { cache.UnrefImage(draw_image); } -TEST(GpuImageDecodeCacheTest, GetLargeScaledDecodedImageForDraw) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetLargeScaledDecodedImageForDraw \ + DISABLED_GetLargeScaledDecodedImageForDraw +#else +#define MAYBE_GetLargeScaledDecodedImageForDraw \ + GetLargeScaledDecodedImageForDraw +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_GetLargeScaledDecodedImageForDraw) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -826,7 +975,8 @@ TEST(GpuImageDecodeCacheTest, GetLargeScaledDecodedImageForDraw) { sk_sp<SkImage> image = CreateImage(1, 48000); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -854,19 +1004,28 @@ TEST(GpuImageDecodeCacheTest, GetLargeScaledDecodedImageForDraw) { EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image)); } -TEST(GpuImageDecodeCacheTest, AtRasterUsedDirectlyIfSpaceAllows) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_AtRasterUsedDirectlyIfSpaceAllows \ + DISABLED_AtRasterUsedDirectlyIfSpaceAllows +#else +#define MAYBE_AtRasterUsedDirectlyIfSpaceAllows \ + AtRasterUsedDirectlyIfSpaceAllows +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_AtRasterUsedDirectlyIfSpaceAllows) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); bool is_decomposable = true; SkFilterQuality quality = kHigh_SkFilterQuality; - cache.SetCachedBytesLimitForTesting(0); + cache.SetAllByteLimitsForTesting(0); sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -884,7 +1043,7 @@ TEST(GpuImageDecodeCacheTest, AtRasterUsedDirectlyIfSpaceAllows) { EXPECT_TRUE(decoded_draw_image.is_at_raster_decode()); EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image)); - cache.SetCachedBytesLimitForTesting(96 * 1024 * 1024); + cache.SetAllByteLimitsForTesting(96 * 1024 * 1024); // Finish our draw after increasing the memory limit, image should be added to // cache. @@ -898,20 +1057,29 @@ TEST(GpuImageDecodeCacheTest, AtRasterUsedDirectlyIfSpaceAllows) { cache.UnrefImage(draw_image); } +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_GetDecodedImageForDrawAtRasterDecodeMultipleTimes \ + DISABLED_GetDecodedImageForDrawAtRasterDecodeMultipleTimes +#else +#define MAYBE_GetDecodedImageForDrawAtRasterDecodeMultipleTimes \ + GetDecodedImageForDrawAtRasterDecodeMultipleTimes +#endif TEST(GpuImageDecodeCacheTest, - GetDecodedImageForDrawAtRasterDecodeMultipleTimes) { + MAYBE_GetDecodedImageForDrawAtRasterDecodeMultipleTimes) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); bool is_decomposable = true; SkFilterQuality quality = kHigh_SkFilterQuality; - cache.SetCachedBytesLimitForTesting(0); + cache.SetAllByteLimitsForTesting(0); sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); // Must hold context lock before calling GetDecodedImageForDraw / // DrawWithImageFinished. @@ -943,7 +1111,8 @@ TEST(GpuImageDecodeCacheTest, sk_sp<SkImage> image = CreateImage(1, 24000); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); // Must hold context lock before calling GetDecodedImageForDraw / // DrawWithImageFinished. @@ -979,7 +1148,8 @@ TEST(GpuImageDecodeCacheTest, ZeroSizedImagesAreSkipped) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable)); + CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1007,7 +1177,8 @@ TEST(GpuImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image( image, SkIRect::MakeXYWH(150, 150, image->width(), image->height()), - quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1035,7 +1206,8 @@ TEST(GpuImageDecodeCacheTest, CanceledTasksDoNotCountAgainstBudget) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image( image, SkIRect::MakeXYWH(0, 0, image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1053,7 +1225,14 @@ TEST(GpuImageDecodeCacheTest, CanceledTasksDoNotCountAgainstBudget) { EXPECT_EQ(0u, cache.GetBytesUsedForTesting()); } -TEST(GpuImageDecodeCacheTest, ShouldAggressivelyFreeResources) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_ShouldAggressivelyFreeResources \ + DISABLED_ShouldAggressivelyFreeResources +#else +#define MAYBE_ShouldAggressivelyFreeResources ShouldAggressivelyFreeResources +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_ShouldAggressivelyFreeResources) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -1063,7 +1242,8 @@ TEST(GpuImageDecodeCacheTest, ShouldAggressivelyFreeResources) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; { bool need_unref = cache.GetTaskForImageAndRef( @@ -1078,39 +1258,53 @@ TEST(GpuImageDecodeCacheTest, ShouldAggressivelyFreeResources) { cache.UnrefImage(draw_image); // We should now have data image in our cache. - DCHECK_GT(cache.GetBytesUsedForTesting(), 0u); + EXPECT_GT(cache.GetBytesUsedForTesting(), 0u); // Tell our cache to aggressively free resources. cache.SetShouldAggressivelyFreeResources(true); - DCHECK_EQ(0u, cache.GetBytesUsedForTesting()); + EXPECT_EQ(0u, cache.GetBytesUsedForTesting()); - // Attempting to upload a new image should result in at-raster decode. + // Attempting to upload a new image should succeed, but the image should not + // be cached past its use. { bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); - EXPECT_FALSE(need_unref); - EXPECT_FALSE(task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(task); + + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(task.get()); + cache.UnrefImage(draw_image); + + EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u); } - // We now tell the cache to not aggressively free resources. Uploads - // should work again. + // We now tell the cache to not aggressively free resources. The image may + // now be cached past its use. cache.SetShouldAggressivelyFreeResources(false); { bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); EXPECT_TRUE(need_unref); EXPECT_TRUE(task); - } - TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); - TestTileTaskRunner::ProcessTask(task.get()); + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(task.get()); + cache.UnrefImage(draw_image); - // The image should be in our cache after un-ref. - cache.UnrefImage(draw_image); - DCHECK_GT(cache.GetBytesUsedForTesting(), 0u); + EXPECT_GT(cache.GetBytesUsedForTesting(), 0u); + } } -TEST(GpuImageDecodeCacheTest, OrphanedImagesFreeOnReachingZeroRefs) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_OrphanedImagesFreeOnReachingZeroRefs \ + DISABLED_OrphanedImagesFreeOnReachingZeroRefs +#else +#define MAYBE_OrphanedImagesFreeOnReachingZeroRefs \ + OrphanedImagesFreeOnReachingZeroRefs +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_OrphanedImagesFreeOnReachingZeroRefs) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -1121,7 +1315,8 @@ TEST(GpuImageDecodeCacheTest, OrphanedImagesFreeOnReachingZeroRefs) { sk_sp<SkImage> first_image = CreateImage(100, 100); DrawImage first_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> first_task; bool need_unref = cache.GetTaskForImageAndRef( first_draw_image, ImageDecodeCache::TracingInfo(), &first_task); @@ -1136,7 +1331,8 @@ TEST(GpuImageDecodeCacheTest, OrphanedImagesFreeOnReachingZeroRefs) { // memory used by |first_image| for the smaller scale. DrawImage second_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> second_task; need_unref = cache.GetTaskForImageAndRef( second_draw_image, ImageDecodeCache::TracingInfo(), &second_task); @@ -1165,7 +1361,15 @@ TEST(GpuImageDecodeCacheTest, OrphanedImagesFreeOnReachingZeroRefs) { cache.GetDrawImageSizeForTesting(second_draw_image)); } -TEST(GpuImageDecodeCacheTest, OrphanedZeroRefImagesImmediatelyDeleted) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_OrphanedZeroRefImagesImmediatelyDeleted \ + DISABLED_OrphanedZeroRefImagesImmediatelyDeleted +#else +#define MAYBE_OrphanedZeroRefImagesImmediatelyDeleted \ + OrphanedZeroRefImagesImmediatelyDeleted +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_OrphanedZeroRefImagesImmediatelyDeleted) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -1176,7 +1380,8 @@ TEST(GpuImageDecodeCacheTest, OrphanedZeroRefImagesImmediatelyDeleted) { sk_sp<SkImage> first_image = CreateImage(100, 100); DrawImage first_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> first_task; bool need_unref = cache.GetTaskForImageAndRef( first_draw_image, ImageDecodeCache::TracingInfo(), &first_task); @@ -1195,7 +1400,8 @@ TEST(GpuImageDecodeCacheTest, OrphanedZeroRefImagesImmediatelyDeleted) { // memory used by |first_image| for the smaller scale. DrawImage second_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> second_task; need_unref = cache.GetTaskForImageAndRef( second_draw_image, ImageDecodeCache::TracingInfo(), &second_task); @@ -1213,7 +1419,13 @@ TEST(GpuImageDecodeCacheTest, OrphanedZeroRefImagesImmediatelyDeleted) { cache.GetDrawImageSizeForTesting(second_draw_image)); } -TEST(GpuImageDecodeCacheTest, QualityCappedAtMedium) { +// crbug.com/709341. +#if defined(MEMORY_SANITIZER) +#define MAYBE_QualityCappedAtMedium DISABLED_QualityCappedAtMedium +#else +#define MAYBE_QualityCappedAtMedium QualityCappedAtMedium +#endif +TEST(GpuImageDecodeCacheTest, MAYBE_QualityCappedAtMedium) { auto context_provider = TestContextProvider::Create(); context_provider->BindToCurrentThread(); TestGpuImageDecodeCache cache(context_provider.get()); @@ -1224,7 +1436,7 @@ TEST(GpuImageDecodeCacheTest, QualityCappedAtMedium) { // Create an image with kLow_FilterQuality. DrawImage low_draw_image(image, SkIRect::MakeWH(image->width(), image->height()), - kLow_SkFilterQuality, matrix); + kLow_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> low_task; bool need_unref = cache.GetTaskForImageAndRef( low_draw_image, ImageDecodeCache::TracingInfo(), &low_task); @@ -1233,9 +1445,9 @@ TEST(GpuImageDecodeCacheTest, QualityCappedAtMedium) { // Get the same image at kMedium_FilterQuality. We can't re-use low, so we // should get a new task/ref. - DrawImage medium_draw_image(image, - SkIRect::MakeWH(image->width(), image->height()), - kMedium_SkFilterQuality, matrix); + DrawImage medium_draw_image( + image, SkIRect::MakeWH(image->width(), image->height()), + kMedium_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> medium_task; need_unref = cache.GetTaskForImageAndRef( medium_draw_image, ImageDecodeCache::TracingInfo(), &medium_task); @@ -1244,9 +1456,9 @@ TEST(GpuImageDecodeCacheTest, QualityCappedAtMedium) { EXPECT_FALSE(low_task.get() == medium_task.get()); // Get the same image at kHigh_FilterQuality. We should re-use medium. - DrawImage large_draw_image(image, - SkIRect::MakeWH(image->width(), image->height()), - kHigh_SkFilterQuality, matrix); + DrawImage large_draw_image( + image, SkIRect::MakeWH(image->width(), image->height()), + kHigh_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> large_task; need_unref = cache.GetTaskForImageAndRef( large_draw_image, ImageDecodeCache::TracingInfo(), &large_task); @@ -1276,7 +1488,8 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawMipUsageChange) { sk_sp<SkImage> image = CreateImage(4000, 4000); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -1298,7 +1511,8 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawMipUsageChange) { // Do an at-raster decode of the above image that *does* require mips. DrawImage draw_image_mips( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.6f, 0.6f), is_decomposable)); + CreateMatrix(SkSize::Make(0.6f, 0.6f), is_decomposable), + DefaultColorSpace()); DecodedDrawImage decoded_draw_image = cache.GetDecodedImageForDraw(draw_image_mips); cache.DrawWithImageFinished(draw_image_mips, decoded_draw_image); @@ -1314,7 +1528,7 @@ TEST(GpuImageDecodeCacheTest, MemoryStateSuspended) { bool is_decomposable = true; SkMatrix matrix = CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), - kLow_SkFilterQuality, matrix); + kLow_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -1326,30 +1540,38 @@ TEST(GpuImageDecodeCacheTest, MemoryStateSuspended) { cache.UnrefImage(draw_image); // The image should be cached. - DCHECK_GT(cache.GetBytesUsedForTesting(), 0u); - DCHECK_EQ(cache.GetNumCacheEntriesForTesting(), 1u); + EXPECT_GT(cache.GetBytesUsedForTesting(), 0u); + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 1u); // Set us to the not visible state (prerequisite for SUSPENDED). cache.SetShouldAggressivelyFreeResources(true); // Image should be cached, but not using memory budget. - DCHECK_EQ(cache.GetBytesUsedForTesting(), 0u); - DCHECK_EQ(cache.GetNumCacheEntriesForTesting(), 1u); + EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u); + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 1u); // Set us to the SUSPENDED state with purging. cache.OnPurgeMemory(); cache.OnMemoryStateChange(base::MemoryState::SUSPENDED); // Nothing should be cached. - DCHECK_EQ(cache.GetBytesUsedForTesting(), 0u); - DCHECK_EQ(cache.GetNumCacheEntriesForTesting(), 0u); + EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u); + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 0u); - // Attempts to get a task for the image should fail, as we have no space (at - // raster only). + // Attempts to get a task for the image will still succeed, as SUSPENDED + // doesn't impact working set size. need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); - EXPECT_FALSE(need_unref); - EXPECT_FALSE(task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(task); + + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(task.get()); + cache.UnrefImage(draw_image); + + // Nothing should be cached. + EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u); + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 0u); // Restore us to visible and NORMAL memory state. cache.OnMemoryStateChange(base::MemoryState::NORMAL); @@ -1375,7 +1597,7 @@ TEST(GpuImageDecodeCacheTest, OutOfRasterDecodeTask) { bool is_decomposable = true; SkMatrix matrix = CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), - kLow_SkFilterQuality, matrix); + kLow_SkFilterQuality, matrix, DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = @@ -1392,5 +1614,240 @@ TEST(GpuImageDecodeCacheTest, OutOfRasterDecodeTask) { cache.UnrefImage(draw_image); } +TEST(GpuImageDecodeCacheTest, ZeroCacheNormalWorkingSet) { + // Setup - Image cache has a normal working set, but zero cache size. + auto context_provider = TestContextProvider::Create(); + context_provider->BindToCurrentThread(); + GpuImageDecodeCache cache(context_provider.get(), ResourceFormat::RGBA_8888, + kGpuMemoryLimitBytes, 0); + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + // Add an image to the cache. Due to normal working set, this should produce + // a task and a ref. + sk_sp<SkImage> image = CreateImage(100, 100); + DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), + quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); + scoped_refptr<TileTask> task; + bool need_unref = cache.GetTaskForImageAndRef( + draw_image, ImageDecodeCache::TracingInfo(), &task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(task); + EXPECT_EQ(task->dependencies().size(), 1u); + EXPECT_TRUE(task->dependencies()[0]); + + // Run the task. + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(task.get()); + + // Request the same image - it should be cached. + scoped_refptr<TileTask> task2; + need_unref = cache.GetTaskForImageAndRef( + draw_image, ImageDecodeCache::TracingInfo(), &task2); + EXPECT_TRUE(need_unref); + EXPECT_FALSE(task2); + + // Unref both images. + cache.UnrefImage(draw_image); + cache.UnrefImage(draw_image); + + // Get the image again. As it was fully unreffed, it is no longer in the + // working set and will be evicted due to 0 cache size. + scoped_refptr<TileTask> task3; + need_unref = cache.GetTaskForImageAndRef( + draw_image, ImageDecodeCache::TracingInfo(), &task3); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(task3); + EXPECT_EQ(task3->dependencies().size(), 1u); + EXPECT_TRUE(task->dependencies()[0]); + + TestTileTaskRunner::ProcessTask(task3->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(task3.get()); + + cache.UnrefImage(draw_image); +} + +TEST(GpuImageDecodeCacheTest, SmallCacheNormalWorkingSet) { + // Cache will fit one (but not two) 100x100 images. + size_t cache_size = 190 * 100 * 4; + + auto context_provider = TestContextProvider::Create(); + context_provider->BindToCurrentThread(); + GpuImageDecodeCache cache(context_provider.get(), ResourceFormat::RGBA_8888, + kGpuMemoryLimitBytes, cache_size); + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + sk_sp<SkImage> image = CreateImage(100, 100); + DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), + quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); + + sk_sp<SkImage> image2 = CreateImage(100, 100); + DrawImage draw_image2( + image2, SkIRect::MakeWH(image2->width(), image2->height()), quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); + + // Add an image to the cache and un-ref it. + { + scoped_refptr<TileTask> task; + bool need_unref = cache.GetTaskForImageAndRef( + draw_image, ImageDecodeCache::TracingInfo(), &task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(task); + EXPECT_EQ(task->dependencies().size(), 1u); + EXPECT_TRUE(task->dependencies()[0]); + + // Run the task and unref the image. + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(task.get()); + cache.UnrefImage(draw_image); + } + + // Request the same image - it should be cached. + { + scoped_refptr<TileTask> task; + bool need_unref = cache.GetTaskForImageAndRef( + draw_image, ImageDecodeCache::TracingInfo(), &task); + EXPECT_TRUE(need_unref); + EXPECT_FALSE(task); + cache.UnrefImage(draw_image); + } + + // Add a new image to the cache. It should push out the old one. + { + scoped_refptr<TileTask> task; + bool need_unref = cache.GetTaskForImageAndRef( + draw_image2, ImageDecodeCache::TracingInfo(), &task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(task); + EXPECT_EQ(task->dependencies().size(), 1u); + EXPECT_TRUE(task->dependencies()[0]); + + // Run the task and unref the image. + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(task.get()); + cache.UnrefImage(draw_image2); + } + + // Request the second image - it should be cached. + { + scoped_refptr<TileTask> task; + bool need_unref = cache.GetTaskForImageAndRef( + draw_image2, ImageDecodeCache::TracingInfo(), &task); + EXPECT_TRUE(need_unref); + EXPECT_FALSE(task); + cache.UnrefImage(draw_image2); + } + + // Request the first image - it should have been evicted and return a new + // task. + { + scoped_refptr<TileTask> task; + bool need_unref = cache.GetTaskForImageAndRef( + draw_image, ImageDecodeCache::TracingInfo(), &task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(task); + EXPECT_EQ(task->dependencies().size(), 1u); + EXPECT_TRUE(task->dependencies()[0]); + + // Run the task and unref the image. + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(task.get()); + cache.UnrefImage(draw_image); + } +} + +TEST(GpuImageDecodeCacheTest, ClearCache) { + auto context_provider = TestContextProvider::Create(); + context_provider->BindToCurrentThread(); + TestGpuImageDecodeCache cache(context_provider.get()); + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + for (int i = 0; i < 10; ++i) { + sk_sp<SkImage> image = CreateImage(100, 100); + DrawImage draw_image( + image, SkIRect::MakeWH(image->width(), image->height()), quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); + scoped_refptr<TileTask> task; + bool need_unref = cache.GetTaskForImageAndRef( + draw_image, ImageDecodeCache::TracingInfo(), &task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(task); + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(task.get()); + cache.UnrefImage(draw_image); + } + + // We should now have data image in our cache. + EXPECT_GT(cache.GetBytesUsedForTesting(), 0u); + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 10u); + + // Tell our cache to clear resources. + cache.ClearCache(); + + // We should now have nothing in our cache. + EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u); + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 0u); +} + +TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) { + auto context_provider = TestContextProvider::Create(); + context_provider->BindToCurrentThread(); + TestGpuImageDecodeCache cache(context_provider.get()); + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + gfx::ColorSpace color_space_a = gfx::ColorSpace::CreateSRGB(); + gfx::ColorSpace color_space_b = gfx::ColorSpace::CreateXYZD50(); + + sk_sp<SkImage> first_image = CreateImage(100, 100); + DrawImage first_draw_image( + first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), + quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + color_space_a); + scoped_refptr<TileTask> first_task; + bool need_unref = cache.GetTaskForImageAndRef( + first_draw_image, ImageDecodeCache::TracingInfo(), &first_task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(first_task); + + DrawImage second_draw_image( + first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), + quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + color_space_b); + scoped_refptr<TileTask> second_task; + need_unref = cache.GetTaskForImageAndRef( + second_draw_image, ImageDecodeCache::TracingInfo(), &second_task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(second_task); + EXPECT_TRUE(first_task.get() != second_task.get()); + + DrawImage third_draw_image( + first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), + quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + color_space_a); + scoped_refptr<TileTask> third_task; + need_unref = cache.GetTaskForImageAndRef( + third_draw_image, ImageDecodeCache::TracingInfo(), &third_task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(third_task.get() == first_task.get()); + + TestTileTaskRunner::ProcessTask(first_task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(first_task.get()); + TestTileTaskRunner::ProcessTask(second_task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(second_task.get()); + + cache.UnrefImage(first_draw_image); + cache.UnrefImage(second_draw_image); + cache.UnrefImage(third_draw_image); +} + } // namespace } // namespace cc diff --git a/chromium/cc/tiles/image_controller.cc b/chromium/cc/tiles/image_controller.cc index ce6968b412d..ae81e64f96d 100644 --- a/chromium/cc/tiles/image_controller.cc +++ b/chromium/cc/tiles/image_controller.cc @@ -47,8 +47,8 @@ void ImageController::StopWorkerTasks() { // "flush" any scheduled tasks (they will abort). CompletionEvent completion_event; worker_task_runner_->PostTask( - FROM_HERE, base::Bind([](CompletionEvent* event) { event->Signal(); }, - base::Unretained(&completion_event))); + FROM_HERE, base::BindOnce([](CompletionEvent* event) { event->Signal(); }, + base::Unretained(&completion_event))); completion_event.Wait(); // Reset the abort flag so that new tasks can be scheduled. @@ -183,11 +183,17 @@ ImageController::ImageDecodeRequestId ImageController::QueueImageDecode( // Generate the next id. ImageDecodeRequestId id = s_next_image_decode_queue_id_++; + // TODO(ccameron): The target color space specified here should match the + // target color space that will be used at rasterization time. Leave this + // unspecified now, since that will match the rasterization-time color + // space while color correct rendering is disabled. + gfx::ColorSpace target_color_space; + DCHECK(image); bool is_image_lazy = image->isLazyGenerated(); auto image_bounds = image->bounds(); DrawImage draw_image(std::move(image), image_bounds, kNone_SkFilterQuality, - SkMatrix::I()); + SkMatrix::I(), target_color_space); // Get the tasks for this decode. scoped_refptr<TileTask> task; @@ -210,8 +216,8 @@ ImageController::ImageDecodeRequestId ImageController::QueueImageDecode( // Post a worker task. worker_task_runner_->PostTask( FROM_HERE, - base::Bind(&ImageController::ProcessNextImageDecodeOnWorkerThread, - base::Unretained(this))); + base::BindOnce(&ImageController::ProcessNextImageDecodeOnWorkerThread, + base::Unretained(this))); } return id; @@ -266,8 +272,8 @@ void ImageController::ProcessNextImageDecodeOnWorkerThread() { decode.task->state().DidFinish(); } origin_task_runner_->PostTask( - FROM_HERE, base::Bind(&ImageController::ImageDecodeCompleted, - weak_ptr_factory_.GetWeakPtr(), decode.id)); + FROM_HERE, base::BindOnce(&ImageController::ImageDecodeCompleted, + weak_ptr_factory_.GetWeakPtr(), decode.id)); } void ImageController::ImageDecodeCompleted(ImageDecodeRequestId id) { @@ -314,8 +320,8 @@ void ImageController::ImageDecodeCompleted(ImageDecodeRequestId id) { // Post another task to run. worker_task_runner_->PostTask( FROM_HERE, - base::Bind(&ImageController::ProcessNextImageDecodeOnWorkerThread, - base::Unretained(this))); + base::BindOnce(&ImageController::ProcessNextImageDecodeOnWorkerThread, + base::Unretained(this))); // Finally run the requested callback. callback.Run(id, result); @@ -343,8 +349,8 @@ void ImageController::GenerateTasksForOrphanedRequests() { // Post a worker task. worker_task_runner_->PostTask( FROM_HERE, - base::Bind(&ImageController::ProcessNextImageDecodeOnWorkerThread, - base::Unretained(this))); + base::BindOnce(&ImageController::ProcessNextImageDecodeOnWorkerThread, + base::Unretained(this))); } } diff --git a/chromium/cc/tiles/image_controller.h b/chromium/cc/tiles/image_controller.h index f62638a1c07..d9253368bb8 100644 --- a/chromium/cc/tiles/image_controller.h +++ b/chromium/cc/tiles/image_controller.h @@ -8,13 +8,14 @@ #include <set> #include <vector> +#include "base/callback.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/threading/simple_thread.h" -#include "cc/base/cc_export.h" #include "cc/base/unique_notifier.h" -#include "cc/playback/draw_image.h" +#include "cc/cc_export.h" +#include "cc/paint/draw_image.h" #include "cc/raster/tile_task.h" #include "cc/tiles/image_decode_cache.h" diff --git a/chromium/cc/tiles/image_controller_unittest.cc b/chromium/cc/tiles/image_controller_unittest.cc index 90b708f3047..3a89afb2b64 100644 --- a/chromium/cc/tiles/image_controller_unittest.cc +++ b/chromium/cc/tiles/image_controller_unittest.cc @@ -3,11 +3,15 @@ // found in the LICENSE file. #include "cc/tiles/image_controller.h" + +#include <utility> + #include "base/bind.h" #include "base/optional.h" #include "base/run_loop.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "base/threading/thread_checker_impl.h" #include "cc/test/skia_common.h" #include "cc/tiles/image_decode_cache.h" #include "testing/gtest/include/gtest/gtest.h" @@ -22,7 +26,7 @@ class TestWorkerThread : public base::SimpleThread { void Run() override { for (;;) { - base::Closure task; + base::OnceClosure task; { base::AutoLock hold(lock_); if (shutdown_) @@ -33,10 +37,10 @@ class TestWorkerThread : public base::SimpleThread { continue; } - task = queue_.front(); + task = std::move(queue_.front()); queue_.erase(queue_.begin()); } - task.Run(); + std::move(task).Run(); } } @@ -46,16 +50,16 @@ class TestWorkerThread : public base::SimpleThread { condition_.Signal(); } - void PostTask(const base::Closure& task) { + void PostTask(base::OnceClosure task) { base::AutoLock hold(lock_); - queue_.push_back(task); + queue_.push_back(std::move(task)); condition_.Signal(); } private: base::Lock lock_; base::ConditionVariable condition_; - std::vector<base::Closure> queue_; + std::vector<base::OnceClosure> queue_; bool shutdown_ = false; }; @@ -64,15 +68,15 @@ class WorkerTaskRunner : public base::SequencedTaskRunner { WorkerTaskRunner() { thread_.Start(); } bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, + base::OnceClosure task, base::TimeDelta delay) override { - return PostDelayedTask(from_here, task, delay); + return PostDelayedTask(from_here, std::move(task), delay); } bool PostDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, + base::OnceClosure task, base::TimeDelta delay) override { - thread_.PostTask(task); + thread_.PostTask(std::move(task)); return true; } @@ -124,6 +128,7 @@ class TestableCache : public ImageDecodeCache { void ReduceCacheUsage() override {} void SetShouldAggressivelyFreeResources( bool aggressively_free_resources) override {} + void ClearCache() override {} int number_of_refs() const { return number_of_refs_; } void SetTaskToUse(scoped_refptr<TileTask> task) { task_to_use_ = task; } @@ -137,12 +142,12 @@ class TestableCache : public ImageDecodeCache { class DecodeClient { public: DecodeClient() {} - void Callback(const base::Closure& quit_closure, + void Callback(base::OnceClosure quit_closure, ImageController::ImageDecodeRequestId id, ImageController::ImageDecodeResult result) { id_ = id; result_ = result; - quit_closure.Run(); + std::move(quit_closure).Run(); } ImageController::ImageDecodeRequestId id() { return id_; } @@ -212,7 +217,8 @@ class BlockingTask : public TileTask { private: ~BlockingTask() override = default; - base::ThreadChecker thread_checker_; + // Use ThreadCheckerImpl, so that release builds also get correct behavior. + base::ThreadCheckerImpl thread_checker_; bool has_run_ = false; base::Lock lock_; base::ConditionVariable run_cv_; @@ -222,8 +228,7 @@ class BlockingTask : public TileTask { }; // For tests that exercise image controller's thread, this is the timeout value -// to -// allow the worker thread to do its work. +// to allow the worker thread to do its work. int kDefaultTimeoutSeconds = 10; class ImageControllerTest : public testing::Test { @@ -261,7 +266,8 @@ class ImageControllerTest : public testing::Test { void RunOrTimeout(base::RunLoop* run_loop) { task_runner_->PostDelayedTask( FROM_HERE, - base::Bind(&ImageControllerTest::Timeout, base::Unretained(run_loop)), + base::BindOnce(&ImageControllerTest::Timeout, + base::Unretained(run_loop)), base::TimeDelta::FromSeconds(kDefaultTimeoutSeconds)); run_loop->Run(); } diff --git a/chromium/cc/tiles/image_decode_cache.h b/chromium/cc/tiles/image_decode_cache.h index 4cba352d68b..ca1f41e4cd9 100644 --- a/chromium/cc/tiles/image_decode_cache.h +++ b/chromium/cc/tiles/image_decode_cache.h @@ -6,8 +6,8 @@ #define CC_TILES_IMAGE_DECODE_CACHE_H_ #include "base/memory/ref_counted.h" -#include "cc/playback/decoded_draw_image.h" -#include "cc/playback/draw_image.h" +#include "cc/paint/draw_image.h" +#include "cc/tiles/decoded_draw_image.h" #include "cc/tiles/tile_priority.h" namespace cc { @@ -93,6 +93,9 @@ class CC_EXPORT ImageDecodeCache { // retaining cached resources longer than needed. virtual void SetShouldAggressivelyFreeResources( bool aggressively_free_resources) = 0; + + // Clears all elements from the cache. + virtual void ClearCache() = 0; }; } // namespace cc diff --git a/chromium/cc/tiles/mipmap_util.h b/chromium/cc/tiles/mipmap_util.h index 9aeeefa5bb3..400d0e4441c 100644 --- a/chromium/cc/tiles/mipmap_util.h +++ b/chromium/cc/tiles/mipmap_util.h @@ -5,7 +5,7 @@ #ifndef CC_TILES_MIPMAP_UTIL_H_ #define CC_TILES_MIPMAP_UTIL_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "third_party/skia/include/core/SkSize.h" #include "ui/gfx/skia_util.h" diff --git a/chromium/cc/tiles/picture_layer_tiling.cc b/chromium/cc/tiles/picture_layer_tiling.cc index ce6b1d8f1e9..344cb32b6c0 100644 --- a/chromium/cc/tiles/picture_layer_tiling.cc +++ b/chromium/cc/tiles/picture_layer_tiling.cc @@ -18,7 +18,7 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/base/math_util.h" -#include "cc/playback/raster_source.h" +#include "cc/raster/raster_source.h" #include "cc/tiles/prioritized_tile.h" #include "cc/tiles/tile.h" #include "cc/tiles/tile_priority.h" @@ -32,29 +32,36 @@ namespace cc { PictureLayerTiling::PictureLayerTiling( WhichTree tree, - float contents_scale, + const gfx::AxisTransform2d& raster_transform, scoped_refptr<RasterSource> raster_source, PictureLayerTilingClient* client, float min_preraster_distance, float max_preraster_distance) - : contents_scale_(contents_scale), + : raster_transform_(raster_transform), client_(client), tree_(tree), raster_source_(raster_source), min_preraster_distance_(min_preraster_distance), max_preraster_distance_(max_preraster_distance) { DCHECK(!raster_source->IsSolidColor()); - gfx::Size content_bounds = - gfx::ScaleToCeiledSize(raster_source_->GetSize(), contents_scale_); - gfx::Size tile_size = client_->CalculateTileSize(content_bounds); + DCHECK_GE(raster_transform.translation().x(), 0.f); + DCHECK_LT(raster_transform.translation().x(), 1.f); + DCHECK_GE(raster_transform.translation().y(), 0.f); + DCHECK_LT(raster_transform.translation().y(), 1.f); - DCHECK(!gfx::ScaleToFlooredSize(raster_source_->GetSize(), contents_scale_) + DCHECK(!gfx::ScaleToFlooredSize(raster_source_->GetSize(), + raster_transform.scale()) .IsEmpty()) << "Tiling created with scale too small as contents become empty." << " Layer bounds: " << raster_source_->GetSize().ToString() - << " Raster scale: " << contents_scale_; - - tiling_data_.SetTilingSize(content_bounds); + << " Raster transform: " << raster_transform_.ToString(); + + gfx::Rect content_bounds_rect = + EnclosingContentsRectFromLayerRect(gfx::Rect(raster_source_->GetSize())); + gfx::Size tiling_size = gfx::Size(content_bounds_rect.bottom_right().x(), + content_bounds_rect.bottom_right().y()); + tiling_data_.SetTilingSize(tiling_size); + gfx::Size tile_size = client_->CalculateTileSize(tiling_size); tiling_data_.SetMaxTextureSize(tile_size); } @@ -108,7 +115,7 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { for (Region::Iterator iter(*invalidation); iter.has_rect(); iter.next()) { gfx::Rect invalid_content_rect = - gfx::ScaleToEnclosingRect(iter.rect(), contents_scale_); + EnclosingContentsRectFromLayerRect(iter.rect()); invalid_content_rect.Intersect(tile_rect); invalidated.Union(invalid_content_rect); } @@ -117,7 +124,7 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { } } } - VerifyLiveTilesRect(false); + VerifyLiveTilesRect(); } void PictureLayerTiling::TakeTilesAndPropertiesFrom( @@ -151,7 +158,7 @@ void PictureLayerTiling::TakeTilesAndPropertiesFrom( if (create_missing_tiles) CreateMissingTilesInLiveTilesRect(); - VerifyLiveTilesRect(false); + VerifyLiveTilesRect(); SetTilePriorityRects(pending_twin->current_content_to_screen_scale_, pending_twin->current_visible_rect_, @@ -167,12 +174,13 @@ void PictureLayerTiling::SetRasterSourceAndResize( gfx::Size old_layer_bounds = raster_source_->GetSize(); raster_source_ = std::move(raster_source); gfx::Size new_layer_bounds = raster_source_->GetSize(); - gfx::Size content_bounds = - gfx::ScaleToCeiledSize(new_layer_bounds, contents_scale_); - gfx::Size tile_size = client_->CalculateTileSize(content_bounds); + gfx::Rect content_rect = + EnclosingContentsRectFromLayerRect(gfx::Rect(new_layer_bounds)); + DCHECK(content_rect.origin() == gfx::Point()); + gfx::Size tile_size = client_->CalculateTileSize(content_rect.size()); if (tile_size != tiling_data_.max_texture_size()) { - tiling_data_.SetTilingSize(content_bounds); + tiling_data_.SetTilingSize(content_rect.size()); tiling_data_.SetMaxTextureSize(tile_size); // When the tile size changes, the TilingData positions no longer work // as valid keys to the TileMap, so just drop all tiles and clear the live @@ -187,7 +195,6 @@ void PictureLayerTiling::SetRasterSourceAndResize( // The SetLiveTilesRect() method would drop tiles outside the new bounds, // but may do so incorrectly if resizing the tiling causes the number of // tiles in the tiling_data_ to change. - gfx::Rect content_rect(content_bounds); int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x()); int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y()); int before_right = @@ -198,7 +205,7 @@ void PictureLayerTiling::SetRasterSourceAndResize( // The live_tiles_rect_ is clamped to stay within the tiling size as we // change it. live_tiles_rect_.Intersect(content_rect); - tiling_data_.SetTilingSize(content_bounds); + tiling_data_.SetTilingSize(content_rect.size()); int after_right = -1; int after_bottom = -1; @@ -214,11 +221,11 @@ void PictureLayerTiling::SetRasterSourceAndResize( // Drop tiles outside the new layer bounds if the layer shrank. for (int i = after_right + 1; i <= before_right; ++i) { for (int j = before_top; j <= before_bottom; ++j) - RemoveTileAt(i, j); + TakeTileAt(i, j); } for (int i = before_left; i <= after_right; ++i) { for (int j = after_bottom + 1; j <= before_bottom; ++j) - RemoveTileAt(i, j); + TakeTileAt(i, j); } if (after_right > before_right) { @@ -263,7 +270,7 @@ void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_invalidation, gfx::Rect layer_rect = iter.rect(); // The pixels which are invalid in content space. gfx::Rect invalid_content_rect = - gfx::ScaleToEnclosingRect(layer_rect, contents_scale_); + EnclosingContentsRectFromLayerRect(layer_rect); gfx::Rect coverage_content_rect = invalid_content_rect; // Avoid needless work by not bothering to invalidate where there aren't // tiles. @@ -300,9 +307,9 @@ Tile::CreateInfo PictureLayerTiling::CreateInfoForTile(int i, int j) const { gfx::Rect tile_rect = tiling_data_.TileBoundsWithBorder(i, j); tile_rect.set_size(tiling_data_.max_texture_size()); gfx::Rect enclosing_layer_rect = - gfx::ScaleToEnclosingRect(tile_rect, 1.f / contents_scale_); + EnclosingLayerRectFromContentsRect(tile_rect); return Tile::CreateInfo(this, i, j, enclosing_layer_rect, tile_rect, - contents_scale_); + raster_transform_); } bool PictureLayerTiling::ShouldCreateTileAt( @@ -342,7 +349,7 @@ bool PictureLayerTiling::ShouldCreateTileAt( for (Region::Iterator iter(*layer_invalidation); iter.has_rect(); iter.next()) { gfx::Rect invalid_content_rect = - gfx::ScaleToEnclosingRect(iter.rect(), contents_scale_); + EnclosingContentsRectFromLayerRect(iter.rect()); if (invalid_content_rect.Intersects(info.content_rect)) return true; } @@ -371,12 +378,16 @@ PictureLayerTiling::CoverageIterator::CoverageIterator( const PictureLayerTiling* tiling, float coverage_scale, const gfx::Rect& coverage_rect) - : tiling_(tiling), coverage_rect_(coverage_rect) { + : tiling_(tiling), + coverage_rect_(coverage_rect), + coverage_to_content_( + gfx::PreScaleAxisTransform2d(tiling->raster_transform(), + 1.f / coverage_scale)) { DCHECK(tiling_); // In order to avoid artifacts in geometry_rect scaling and clamping to ints, // the |coverage_scale| should always be at least as big as the tiling's // raster scales. - DCHECK_GE(coverage_scale, tiling_->contents_scale_); + DCHECK_GE(coverage_scale, tiling_->raster_transform_.scale()); // Clamp |coverage_rect| to the bounds of this tiling's raster source. coverage_rect_max_bounds_ = @@ -385,8 +396,6 @@ PictureLayerTiling::CoverageIterator::CoverageIterator( if (coverage_rect_.IsEmpty()) return; - coverage_to_content_scale_ = tiling_->contents_scale_ / coverage_scale; - // Find the indices of the texel samples that enclose the rect we want to // cover. // Because we don't know the target transform at this point, we have to be @@ -394,8 +403,8 @@ PictureLayerTiling::CoverageIterator::CoverageIterator( // snapped to a pixel sample) inside of the content rect may be sampled. // This code maps the boundary points into contents space, then find out the // enclosing texture samples. For example, assume we have: - // dest_scale : content_scale = 1.23 : 1 - // dest_rect = (l:123, t:234, r:345, b:456) + // coverage_scale : content_scale = 1.23 : 1 + // coverage_rect = (l:123, t:234, r:345, b:456) // Then it follows that: // content_rect = (l:100.00, t:190.24, r:280.49, b:370.73) // Without MSAA, the sample point of a texel is at the center of that texel, @@ -404,7 +413,7 @@ PictureLayerTiling::CoverageIterator::CoverageIterator( // Or in integer index: // wanted_texels(integer index) = (l:99, t:189, r:280, b:371) gfx::RectF content_rect = - gfx::ScaleRect(gfx::RectF(coverage_rect_), coverage_to_content_scale_); + coverage_to_content_.MapRect(gfx::RectF(coverage_rect_)); content_rect.Offset(-0.5f, -0.5f); gfx::Rect wanted_texels = gfx::ToEnclosingRect(content_rect); @@ -465,8 +474,8 @@ PictureLayerTiling::CoverageIterator::operator++() { // Convert texel_extent to coverage scale, which is what we have to report // geometry_rect in. - current_geometry_rect_ = gfx::ToEnclosedRect( - gfx::ScaleRect(texel_extent, 1.f / coverage_to_content_scale_)); + current_geometry_rect_ = + gfx::ToEnclosedRect(coverage_to_content_.InverseMapRect(texel_extent)); { // Adjust external edges to cover the whole layer in dest space. // @@ -529,12 +538,9 @@ gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const { auto tex_origin = gfx::PointF( tiling_->tiling_data_.TileBoundsWithBorder(tile_i_, tile_j_).origin()); - // Convert from dest space => content space => texture space. + // Convert from coverage space => content space => texture space. gfx::RectF texture_rect(current_geometry_rect_); - texture_rect.Scale(coverage_to_content_scale_); - texture_rect.Intersect(gfx::RectF(gfx::SizeF(tiling_->tiling_size()))); - if (texture_rect.IsEmpty()) - return texture_rect; + texture_rect = coverage_to_content_.MapRect(texture_rect); texture_rect.Offset(-tex_origin.OffsetFromOrigin()); return texture_rect; @@ -549,14 +555,6 @@ std::unique_ptr<Tile> PictureLayerTiling::TakeTileAt(int i, int j) { return result; } -bool PictureLayerTiling::RemoveTileAt(int i, int j) { - TileMap::iterator found = tiles_.find(TileMapKey(i, j)); - if (found == tiles_.end()) - return false; - tiles_.erase(found); - return true; -} - void PictureLayerTiling::Reset() { live_tiles_rect_ = gfx::Rect(); tiles_.clear(); @@ -577,16 +575,15 @@ void PictureLayerTiling::ComputeTilePriorityRects( set_all_tiles_done(false); } - float content_to_screen_scale = ideal_contents_scale / contents_scale_; + const float content_to_screen_scale = + ideal_contents_scale / raster_transform_.scale(); const gfx::Rect* input_rects[] = { &visible_rect_in_layer_space, &skewport_in_layer_space, &soon_border_rect_in_layer_space, &eventually_rect_in_layer_space}; gfx::Rect output_rects[4]; - for (size_t i = 0; i < arraysize(input_rects); ++i) { - output_rects[i] = gfx::ToEnclosingRect( - gfx::ScaleRect(gfx::RectF(*input_rects[i]), contents_scale_)); - } + for (size_t i = 0; i < arraysize(input_rects); ++i) + output_rects[i] = EnclosingContentsRectFromLayerRect(*input_rects[i]); // Make sure the eventually rect is aligned to tile bounds. output_rects[3] = tiling_data_.ExpandRectIgnoringBordersToTileBounds(output_rects[3]); @@ -644,14 +641,14 @@ void PictureLayerTiling::SetLiveTilesRect( for (TilingData::DifferenceIterator iter(&tiling_data_, live_tiles_rect_, new_live_tiles_rect); iter; ++iter) { - RemoveTileAt(iter.index_x(), iter.index_y()); + TakeTileAt(iter.index_x(), iter.index_y()); } // We don't rasterize non ideal resolution tiles, so there is no need to // create any new tiles. if (resolution_ == NON_IDEAL_RESOLUTION) { live_tiles_rect_.Intersect(new_live_tiles_rect); - VerifyLiveTilesRect(false); + VerifyLiveTilesRect(); return; } @@ -665,14 +662,13 @@ void PictureLayerTiling::SetLiveTilesRect( } live_tiles_rect_ = new_live_tiles_rect; - VerifyLiveTilesRect(false); + VerifyLiveTilesRect(); } -void PictureLayerTiling::VerifyLiveTilesRect(bool is_on_recycle_tree) const { +void PictureLayerTiling::VerifyLiveTilesRect() const { #if DCHECK_IS_ON() for (auto it = tiles_.begin(); it != tiles_.end(); ++it) { - if (!it->second) - continue; + DCHECK(it->second); TileMapKey key = it->first; DCHECK(key.index_x < tiling_data_.num_tiles_x()) << this << " " << key.index_x << "," << key.index_y << " num_tiles_x " @@ -731,10 +727,7 @@ bool PictureLayerTiling::IsTileOccludedOnCurrentTree(const Tile* tile) const { if (tile_query_rect.IsEmpty()) return false; - if (contents_scale_ != 1.f) { - tile_query_rect = - gfx::ScaleToEnclosingRect(tile_query_rect, 1.f / contents_scale_); - } + tile_query_rect = EnclosingLayerRectFromContentsRect(tile_query_rect); return current_occlusion_in_layer_space_.IsOccluded(tile_query_rect); } @@ -825,7 +818,8 @@ PrioritizedTile PictureLayerTiling::MakePrioritizedTile( PriorityRectType priority_rect_type) const { DCHECK(tile); DCHECK(raster_source()->CoversRect(tile->enclosing_layer_rect())) - << "Tile layer rect: " << tile->enclosing_layer_rect().ToString(); + << "Recording rect: " + << EnclosingLayerRectFromContentsRect(tile->content_rect()).ToString(); UpdateRequiredStatesOnTile(tile); const auto& tile_priority = ComputePriorityForTile(tile, priority_rect_type); @@ -925,7 +919,13 @@ void PictureLayerTiling::GetAllPrioritizedTilesForTracing( void PictureLayerTiling::AsValueInto( base::trace_event::TracedValue* state) const { state->SetInteger("num_tiles", base::saturated_cast<int>(tiles_.size())); - state->SetDouble("content_scale", contents_scale()); + state->SetDouble("content_scale", contents_scale_key()); + + state->BeginArray("raster_transform"); + state->AppendDouble(raster_transform_.scale()); + state->AppendDouble(raster_transform_.translation().x()); + state->AppendDouble(raster_transform_.translation().y()); + state->EndArray(); MathUtil::AddToTracedValue("visible_rect", current_visible_rect_, state); MathUtil::AddToTracedValue("skewport_rect", current_skewport_rect_, state); @@ -944,4 +944,15 @@ size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { return amount; } +gfx::Rect PictureLayerTiling::EnclosingContentsRectFromLayerRect( + const gfx::Rect& layer_rect) const { + return ToEnclosingRect(raster_transform_.MapRect(gfx::RectF(layer_rect))); +} + +gfx::Rect PictureLayerTiling::EnclosingLayerRectFromContentsRect( + const gfx::Rect& contents_rect) const { + return ToEnclosingRect( + raster_transform_.InverseMapRect(gfx::RectF(contents_rect))); +} + } // namespace cc diff --git a/chromium/cc/tiles/picture_layer_tiling.h b/chromium/cc/tiles/picture_layer_tiling.h index e9c192c0180..ecf1974efa8 100644 --- a/chromium/cc/tiles/picture_layer_tiling.h +++ b/chromium/cc/tiles/picture_layer_tiling.h @@ -15,12 +15,13 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" #include "cc/base/region.h" #include "cc/base/tiling_data.h" +#include "cc/cc_export.h" #include "cc/tiles/tile.h" #include "cc/tiles/tile_priority.h" #include "cc/trees/occlusion.h" +#include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect.h" namespace base { @@ -80,8 +81,13 @@ class CC_EXPORT PictureLayerTiling { public: static const int kBorderTexels = 1; + // Note on raster_transform: In general raster_transform could be arbitrary, + // the only restriction is that the layer bounds after transform should + // be positive (because the tiling logic doesn't support negative space). + // Also the implementation checks the transformed bounds leaves less than + // 1px margin on top left edges, because there is few reason to do so. PictureLayerTiling(WhichTree tree, - float raster_scale, + const gfx::AxisTransform2d& raster_transform, scoped_refptr<RasterSource> raster_source, PictureLayerTilingClient* client, float min_preraster_distance, @@ -120,7 +126,14 @@ class CC_EXPORT PictureLayerTiling { gfx::Size tiling_size() const { return tiling_data_.tiling_size(); } gfx::Rect live_tiles_rect() const { return live_tiles_rect_; } gfx::Size tile_size() const { return tiling_data_.max_texture_size(); } - float contents_scale() const { return contents_scale_; } + // PictureLayerTilingSet uses the scale component of the raster transform + // as the key for indexing and sorting. In theory we can have multiple + // tilings with the same scale but different translation, but currently + // we only allow tilings with unique scale for the sake of simplicity. + float contents_scale_key() const { return raster_transform_.scale(); } + const gfx::AxisTransform2d& raster_transform() const { + return raster_transform_; + } const TilingData* tiling_data() const { return &tiling_data_; } Tile* TileAt(int i, int j) const { @@ -169,7 +182,7 @@ class CC_EXPORT PictureLayerTiling { void SetAllTilesOccludedForTesting() { gfx::Rect viewport_in_layer_space = - ScaleToEnclosingRect(current_visible_rect_, 1.f / contents_scale_); + EnclosingLayerRectFromContentsRect(current_visible_rect_); current_occlusion_in_layer_space_ = Occlusion(gfx::Transform(), SimpleEnclosedRegion(viewport_in_layer_space), @@ -220,7 +233,7 @@ class CC_EXPORT PictureLayerTiling { const PictureLayerTiling* tiling_ = nullptr; gfx::Size coverage_rect_max_bounds_; gfx::Rect coverage_rect_; - float coverage_to_content_scale_; + gfx::AxisTransform2d coverage_to_content_; Tile* current_tile_ = nullptr; gfx::Rect current_geometry_rect_; @@ -275,11 +288,11 @@ class CC_EXPORT PictureLayerTiling { std::unordered_map<TileMapKey, std::unique_ptr<Tile>, TileMapKeyHash>; void SetLiveTilesRect(const gfx::Rect& live_tiles_rect); - void VerifyLiveTilesRect(bool is_on_recycle_tree) const; + void VerifyLiveTilesRect() const; Tile* CreateTile(const Tile::CreateInfo& info); + // Removes the tile at i, j and returns it. Returns nullptr if the tile did + // not exist. std::unique_ptr<Tile> 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; // Save the required data for computing tile priorities later. @@ -330,8 +343,13 @@ class CC_EXPORT PictureLayerTiling { } void RemoveTilesInRegion(const Region& layer_region, bool recreate_tiles); + gfx::Rect EnclosingContentsRectFromLayerRect( + const gfx::Rect& layer_rect) const; + gfx::Rect EnclosingLayerRectFromContentsRect( + const gfx::Rect& contents_rect) const; + // Given properties. - const float contents_scale_; + const gfx::AxisTransform2d raster_transform_; PictureLayerTilingClient* const client_; const WhichTree tree_; scoped_refptr<RasterSource> raster_source_; @@ -353,7 +371,7 @@ class CC_EXPORT PictureLayerTiling { gfx::Rect current_soon_border_rect_; gfx::Rect current_eventually_rect_; // Other properties used for tile iteration and prioritization. - float current_content_to_screen_scale_; + float current_content_to_screen_scale_ = 0.f; Occlusion current_occlusion_in_layer_space_; float max_skewport_extent_in_screen_space_ = 0.f; diff --git a/chromium/cc/tiles/picture_layer_tiling_set.cc b/chromium/cc/tiles/picture_layer_tiling_set.cc index 4817cbd87fe..5452019117b 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set.cc +++ b/chromium/cc/tiles/picture_layer_tiling_set.cc @@ -11,8 +11,9 @@ #include <vector> #include "base/memory/ptr_util.h" +#include "base/stl_util.h" #include "base/trace_event/trace_event.h" -#include "cc/playback/raster_source.h" +#include "cc/raster/raster_source.h" #include "ui/gfx/geometry/rect_conversions.h" namespace cc { @@ -23,7 +24,7 @@ class LargestToSmallestScaleFunctor { public: bool operator()(const std::unique_ptr<PictureLayerTiling>& left, const std::unique_ptr<PictureLayerTiling>& right) { - return left->contents_scale() > right->contents_scale(); + return left->contents_scale_key() > right->contents_scale_key(); } }; @@ -83,11 +84,17 @@ void PictureLayerTilingSet::CopyTilingsAndPropertiesFromPendingTwin( bool tiling_sort_required = false; for (const auto& pending_twin_tiling : pending_twin_set->tilings_) { + gfx::AxisTransform2d raster_transform = + pending_twin_tiling->raster_transform(); PictureLayerTiling* this_tiling = - FindTilingWithScaleKey(pending_twin_tiling->contents_scale()); + FindTilingWithScaleKey(pending_twin_tiling->contents_scale_key()); + if (this_tiling && this_tiling->raster_transform() != raster_transform) { + Remove(this_tiling); + this_tiling = nullptr; + } if (!this_tiling) { std::unique_ptr<PictureLayerTiling> new_tiling(new PictureLayerTiling( - tree_, pending_twin_tiling->contents_scale(), raster_source_, client_, + tree_, raster_transform, raster_source_, client_, kMaxSoonBorderDistanceInScreenPixels, max_preraster_distance_)); tilings_.push_back(std::move(new_tiling)); this_tiling = tilings_.back().get(); @@ -123,7 +130,7 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForActivation( // If the tiling is not shared (FindTilingWithScale returns nullptr), then // invalidate tiles and update them to the new raster source. for (const auto& tiling : tilings_) { - if (pending_twin_set->FindTilingWithScaleKey(tiling->contents_scale())) + if (pending_twin_set->FindTilingWithScaleKey(tiling->contents_scale_key())) continue; tiling->SetRasterSourceAndResize(raster_source); @@ -240,8 +247,8 @@ void PictureLayerTilingSet::CleanUpTilings( std::vector<PictureLayerTiling*> to_remove; for (const auto& tiling : tilings_) { // Keep all tilings within the min/max scales. - if (tiling->contents_scale() >= min_acceptable_high_res_scale_key && - tiling->contents_scale() <= max_acceptable_high_res_scale_key) { + if (tiling->contents_scale_key() >= min_acceptable_high_res_scale_key && + tiling->contents_scale_key() <= max_acceptable_high_res_scale_key) { continue; } @@ -265,12 +272,9 @@ void PictureLayerTilingSet::CleanUpTilings( } void PictureLayerTilingSet::RemoveNonIdealTilings() { - auto to_remove = - std::remove_if(tilings_.begin(), tilings_.end(), - [](const std::unique_ptr<PictureLayerTiling>& t) { - return t->resolution() == NON_IDEAL_RESOLUTION; - }); - tilings_.erase(to_remove, tilings_.end()); + base::EraseIf(tilings_, [](const std::unique_ptr<PictureLayerTiling>& t) { + return t->resolution() == NON_IDEAL_RESOLUTION; + }); } void PictureLayerTilingSet::MarkAllTilingsNonIdeal() { @@ -279,20 +283,20 @@ void PictureLayerTilingSet::MarkAllTilingsNonIdeal() { } PictureLayerTiling* PictureLayerTilingSet::AddTiling( - float contents_scale, + const gfx::AxisTransform2d& raster_transform, scoped_refptr<RasterSource> raster_source) { if (!raster_source_) raster_source_ = raster_source; #if DCHECK_IS_ON() for (size_t i = 0; i < tilings_.size(); ++i) { - DCHECK_NE(tilings_[i]->contents_scale(), contents_scale); + DCHECK_NE(tilings_[i]->contents_scale_key(), raster_transform.scale()); DCHECK_EQ(tilings_[i]->raster_source(), raster_source.get()); } #endif // DCHECK_IS_ON() tilings_.push_back(base::MakeUnique<PictureLayerTiling>( - tree_, contents_scale, raster_source, client_, + tree_, raster_transform, raster_source, client_, kMaxSoonBorderDistanceInScreenPixels, max_preraster_distance_)); PictureLayerTiling* appended = tilings_.back().get(); state_since_last_tile_priority_update_.added_tilings = true; @@ -311,7 +315,7 @@ int PictureLayerTilingSet::NumHighResTilings() const { PictureLayerTiling* PictureLayerTilingSet::FindTilingWithScaleKey( float scale_key) const { for (size_t i = 0; i < tilings_.size(); ++i) { - if (tilings_[i]->contents_scale() == scale_key) + if (tilings_[i]->contents_scale_key() == scale_key) return tilings_[i].get(); } return nullptr; @@ -331,22 +335,20 @@ PictureLayerTiling* PictureLayerTilingSet::FindTilingWithResolution( void PictureLayerTilingSet::RemoveTilingsBelowScaleKey( float minimum_scale_key) { - auto to_remove = std::remove_if( - tilings_.begin(), tilings_.end(), + base::EraseIf( + tilings_, [minimum_scale_key](const std::unique_ptr<PictureLayerTiling>& tiling) { - return tiling->contents_scale() < minimum_scale_key; + return tiling->contents_scale_key() < minimum_scale_key; }); - tilings_.erase(to_remove, tilings_.end()); } void PictureLayerTilingSet::RemoveTilingsAboveScaleKey( float maximum_scale_key) { - auto to_remove = std::remove_if( - tilings_.begin(), tilings_.end(), + base::EraseIf( + tilings_, [maximum_scale_key](const std::unique_ptr<PictureLayerTiling>& tiling) { - return tiling->contents_scale() > maximum_scale_key; + return tiling->contents_scale_key() > maximum_scale_key; }); - tilings_.erase(to_remove, tilings_.end()); } void PictureLayerTilingSet::RemoveAllTilings() { @@ -376,7 +378,7 @@ float PictureLayerTilingSet::GetSnappedContentsScaleKey( float snapped_contents_scale = start_scale; float snapped_ratio = snap_to_existing_tiling_ratio; for (const auto& tiling : tilings_) { - float tiling_contents_scale = tiling->contents_scale(); + float tiling_contents_scale = tiling->contents_scale_key(); float ratio = LargerRatio(tiling_contents_scale, start_scale); if (ratio < snapped_ratio) { snapped_contents_scale = tiling_contents_scale; @@ -390,7 +392,7 @@ float PictureLayerTilingSet::GetMaximumContentsScale() const { if (tilings_.empty()) return 0.f; // The first tiling has the largest contents scale. - return tilings_[0]->contents_scale(); + return tilings_[0]->raster_transform().scale(); } bool PictureLayerTilingSet::TilingsNeedUpdate( @@ -578,7 +580,7 @@ PictureLayerTilingSet::CoverageIterator::CoverageIterator( size_t tilings_size = set_->tilings_.size(); for (ideal_tiling_ = 0; ideal_tiling_ < tilings_size; ++ideal_tiling_) { PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_].get(); - if (tiling->contents_scale() < ideal_contents_scale) { + if (tiling->contents_scale_key() < ideal_contents_scale) { if (ideal_tiling_ > 0) ideal_tiling_--; break; diff --git a/chromium/cc/tiles/picture_layer_tiling_set.h b/chromium/cc/tiles/picture_layer_tiling_set.h index 608c43c2ba3..30c1d2967d7 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set.h +++ b/chromium/cc/tiles/picture_layer_tiling_set.h @@ -80,7 +80,7 @@ class CC_EXPORT PictureLayerTilingSet { void UpdateTilingsForImplSideInvalidation(const Region& layer_invalidation); - PictureLayerTiling* AddTiling(float contents_scale, + PictureLayerTiling* AddTiling(const gfx::AxisTransform2d& raster_transform, scoped_refptr<RasterSource> raster_source); size_t num_tilings() const { return tilings_.size(); } int NumHighResTilings() const; diff --git a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc index 2bc927406d2..c113b6dfab4 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc +++ b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc @@ -67,9 +67,9 @@ TEST(PictureLayerTilingSetTest, NoResources) { scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateEmpty(layer_bounds); - set->AddTiling(1.0, raster_source); - set->AddTiling(1.5, raster_source); - set->AddTiling(2.0, raster_source); + set->AddTiling(gfx::AxisTransform2d(), raster_source); + set->AddTiling(gfx::AxisTransform2d(1.5, gfx::Vector2dF()), raster_source); + set->AddTiling(gfx::AxisTransform2d(2.0, gfx::Vector2dF()), raster_source); float contents_scale = 2.0; gfx::Size content_bounds( @@ -106,13 +106,14 @@ TEST(PictureLayerTilingSetTest, TilingRange) { FakeRasterSource::CreateFilled(layer_bounds); std::unique_ptr<TestablePictureLayerTilingSet> set = CreateTilingSet(&client); - set->AddTiling(2.0, raster_source); - high_res_tiling = set->AddTiling(1.0, raster_source); + set->AddTiling(gfx::AxisTransform2d(2.0, gfx::Vector2dF()), raster_source); + high_res_tiling = set->AddTiling(gfx::AxisTransform2d(), raster_source); high_res_tiling->set_resolution(HIGH_RESOLUTION); - set->AddTiling(0.5, raster_source); - low_res_tiling = set->AddTiling(0.25, raster_source); + set->AddTiling(gfx::AxisTransform2d(0.5, gfx::Vector2dF()), raster_source); + low_res_tiling = set->AddTiling(gfx::AxisTransform2d(0.25, gfx::Vector2dF()), + raster_source); low_res_tiling->set_resolution(LOW_RESOLUTION); - set->AddTiling(0.125, raster_source); + set->AddTiling(gfx::AxisTransform2d(0.125, gfx::Vector2dF()), raster_source); higher_than_high_res_range = set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); @@ -139,11 +140,15 @@ TEST(PictureLayerTilingSetTest, TilingRange) { std::unique_ptr<TestablePictureLayerTilingSet> set_without_low_res = CreateTilingSet(&client); - set_without_low_res->AddTiling(2.0, raster_source); - high_res_tiling = set_without_low_res->AddTiling(1.0, raster_source); + set_without_low_res->AddTiling(gfx::AxisTransform2d(2.0, gfx::Vector2dF()), + raster_source); + high_res_tiling = + set_without_low_res->AddTiling(gfx::AxisTransform2d(), raster_source); high_res_tiling->set_resolution(HIGH_RESOLUTION); - set_without_low_res->AddTiling(0.5, raster_source); - set_without_low_res->AddTiling(0.25, raster_source); + set_without_low_res->AddTiling(gfx::AxisTransform2d(0.5, gfx::Vector2dF()), + raster_source); + set_without_low_res->AddTiling(gfx::AxisTransform2d(0.25, gfx::Vector2dF()), + raster_source); higher_than_high_res_range = set_without_low_res->GetTilingRange( PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); @@ -170,11 +175,11 @@ TEST(PictureLayerTilingSetTest, TilingRange) { std::unique_ptr<TestablePictureLayerTilingSet> set_with_only_high_and_low_res = CreateTilingSet(&client); - high_res_tiling = - set_with_only_high_and_low_res->AddTiling(1.0, raster_source); + high_res_tiling = set_with_only_high_and_low_res->AddTiling( + gfx::AxisTransform2d(), raster_source); high_res_tiling->set_resolution(HIGH_RESOLUTION); - low_res_tiling = - set_with_only_high_and_low_res->AddTiling(0.5, raster_source); + low_res_tiling = set_with_only_high_and_low_res->AddTiling( + gfx::AxisTransform2d(0.5, gfx::Vector2dF()), raster_source); low_res_tiling->set_resolution(LOW_RESOLUTION); higher_than_high_res_range = set_with_only_high_and_low_res->GetTilingRange( @@ -204,7 +209,8 @@ TEST(PictureLayerTilingSetTest, TilingRange) { std::unique_ptr<TestablePictureLayerTilingSet> set_with_only_high_res = CreateTilingSet(&client); - high_res_tiling = set_with_only_high_res->AddTiling(1.0, raster_source); + high_res_tiling = + set_with_only_high_res->AddTiling(gfx::AxisTransform2d(), raster_source); high_res_tiling->set_resolution(HIGH_RESOLUTION); higher_than_high_res_range = set_with_only_high_res->GetTilingRange( @@ -256,7 +262,8 @@ class PictureLayerTilingSetTestWithResources : public testing::Test { float scale = min_scale; for (int i = 0; i < num_tilings; ++i, scale += scale_increment) { - PictureLayerTiling* tiling = set->AddTiling(scale, raster_source); + PictureLayerTiling* tiling = set->AddTiling( + gfx::AxisTransform2d(scale, gfx::Vector2dF()), raster_source); tiling->set_resolution(HIGH_RESOLUTION); tiling->CreateAllTilesForTesting(); std::vector<Tile*> tiles = tiling->AllTilesForTesting(); @@ -277,7 +284,7 @@ class PictureLayerTilingSetTestWithResources : public testing::Test { ASSERT_TRUE(remaining.Contains(geometry_rect)); remaining.Subtract(geometry_rect); - float scale = iter.CurrentTiling()->contents_scale(); + float scale = iter.CurrentTiling()->contents_scale_key(); EXPECT_EQ(expected_scale, scale); if (num_tilings) @@ -341,7 +348,7 @@ TEST(PictureLayerTilingSetTest, TileSizeChange) { gfx::Size tile_size3(20, 20); pending_client.SetTileSize(tile_size1); - pending_set->AddTiling(1.f, raster_source); + pending_set->AddTiling(gfx::AxisTransform2d(), raster_source); // New tilings get the correct tile size. EXPECT_EQ(tile_size1, pending_set->tiling_at(0)->tile_size()); @@ -366,7 +373,7 @@ TEST(PictureLayerTilingSetTest, TileSizeChange) { // 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, raster_source); + pending_set->AddTiling(gfx::AxisTransform2d(), raster_source); pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION); pending_client.SetTileSize(tile_size2); pending_set->UpdateTilingsToCurrentRasterSourceForCommit(raster_source.get(), @@ -446,9 +453,11 @@ TEST(PictureLayerTilingSetTest, MaxContentScale) { FakeRasterSource::CreateEmpty(layer_bounds); // Tilings can be added of any scale, the tiling client can controls this. - pending_set->AddTiling(1.f, raster_source); - pending_set->AddTiling(2.f, raster_source); - pending_set->AddTiling(3.f, raster_source); + pending_set->AddTiling(gfx::AxisTransform2d(), raster_source); + pending_set->AddTiling(gfx::AxisTransform2d(2.f, gfx::Vector2dF()), + raster_source); + pending_set->AddTiling(gfx::AxisTransform2d(3.f, gfx::Vector2dF()), + raster_source); // Set some expected things for the tiling set to function. pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION); @@ -503,7 +512,7 @@ TEST(PictureLayerTilingSetTest, SkewportLimits) { CreateTilingSetWithSettings(&client, settings); EXPECT_FALSE(tiling_set->TilingsNeedUpdate(viewport, 1.0)); - tiling_set->AddTiling(1.f, raster_source); + tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); EXPECT_TRUE(tiling_set->TilingsNeedUpdate(viewport, 1.0)); tiling_set->UpdateTilePriorities(viewport, 1.f, 1.0, Occlusion(), true); @@ -589,7 +598,7 @@ TEST(PictureLayerTilingSetTest, ComputeSkewportExtremeCases) { FakeRasterSource::CreateFilled(layer_bounds); std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSetWithSettings(&client, settings); - tiling_set->AddTiling(1.f, raster_source); + tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); gfx::Rect viewport1(-1918, 255860, 4010, 2356); gfx::Rect viewport2(-7088, -91738, 14212, 8350); @@ -606,7 +615,8 @@ TEST(PictureLayerTilingSetTest, ComputeSkewportExtremeCases) { // Use a tiling with a large scale, so the viewport times the scale no longer // fits into integers, and the viewport is not anywhere close to the tiling. - PictureLayerTiling* tiling = tiling_set->AddTiling(1000.f, raster_source); + PictureLayerTiling* tiling = tiling_set->AddTiling( + gfx::AxisTransform2d(1000.f, gfx::Vector2dF()), raster_source); EXPECT_TRUE(tiling_set->TilingsNeedUpdate(viewport3, time)); tiling_set->UpdateTilePriorities(viewport3, 1.f, time, Occlusion(), true); EXPECT_TRUE(tiling->GetCurrentVisibleRectForTesting().IsEmpty()); @@ -624,7 +634,7 @@ TEST(PictureLayerTilingSetTest, ComputeSkewport) { FakeRasterSource::CreateFilled(layer_bounds); std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSet(&client); - tiling_set->AddTiling(1.f, raster_source); + tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); tiling_set->UpdateTilePriorities(viewport, 1.f, 1.0, Occlusion(), true); @@ -686,7 +696,7 @@ TEST(PictureLayerTilingSetTest, SkewportThroughUpdateTilePriorities) { FakeRasterSource::CreateFilled(layer_bounds); std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSet(&client); - tiling_set->AddTiling(1.f, raster_source); + tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); tiling_set->UpdateTilePriorities(viewport, 1.f, 1.0, Occlusion(), true); @@ -760,7 +770,8 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) { FakeRasterSource::CreateFilled(layer_bounds); std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSet(&client); - auto* tiling = tiling_set->AddTiling(0.25f, raster_source); + auto* tiling = tiling_set->AddTiling( + gfx::AxisTransform2d(0.25f, gfx::Vector2dF()), raster_source); tiling->set_resolution(HIGH_RESOLUTION); gfx::Rect viewport_in_content_space = gfx::ScaleToEnclosedRect(viewport, 0.25f); @@ -921,7 +932,8 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) { EXPECT_FLOAT_EQ(8.f, priority.distance_to_visible); // Test additional scales. - tiling = tiling_set->AddTiling(0.2f, raster_source); + tiling = tiling_set->AddTiling(gfx::AxisTransform2d(0.2f, gfx::Vector2dF()), + raster_source); tiling->set_resolution(HIGH_RESOLUTION); tiling_set->UpdateTilePriorities(viewport, 1.0f, 4.0, Occlusion(), true); prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting(); @@ -956,7 +968,8 @@ TEST(PictureLayerTilingTest, InvalidateAfterComputeTilePriorityRects) { FakeRasterSource::CreateFilled(gfx::Size(100, 100)); std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSet(&pending_client); - auto* pending_tiling = tiling_set->AddTiling(1.f, raster_source); + auto* pending_tiling = + tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); pending_tiling->set_resolution(HIGH_RESOLUTION); // Ensure that we can compute tile priority rects, invalidate, and compute the @@ -999,7 +1012,8 @@ TEST(PictureLayerTilingTest, InvalidateAfterUpdateRasterSourceForCommit) { scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds); - auto* pending_tiling = pending_set->AddTiling(1.f, raster_source); + auto* pending_tiling = + pending_set->AddTiling(gfx::AxisTransform2d(), raster_source); pending_tiling->set_resolution(HIGH_RESOLUTION); active_client.set_twin_tiling_set(pending_set.get()); @@ -1038,5 +1052,64 @@ TEST(PictureLayerTilingTest, InvalidateAfterUpdateRasterSourceForCommit) { active_set->UpdateTilePriorities(viewport, 1.f, time, Occlusion(), true)); } +TEST(PictureLayerTilingSetTest, TilingTranslationChanges) { + gfx::Size tile_size(64, 64); + FakePictureLayerTilingClient pending_client; + FakePictureLayerTilingClient active_client; + pending_client.SetTileSize(tile_size); + active_client.SetTileSize(tile_size); + std::unique_ptr<PictureLayerTilingSet> pending_set = + PictureLayerTilingSet::Create(PENDING_TREE, &pending_client, 0, 1.f, 0, + 0.f); + std::unique_ptr<PictureLayerTilingSet> active_set = + PictureLayerTilingSet::Create(ACTIVE_TREE, &active_client, 0, 1.f, 0, + 0.f); + active_client.set_twin_tiling_set(pending_set.get()); + + gfx::Size layer_bounds(100, 100); + scoped_refptr<FakeRasterSource> raster_source = + FakeRasterSource::CreateFilled(layer_bounds); + + gfx::AxisTransform2d raster_transform1(1.f, gfx::Vector2dF(0.25f, 0.25f)); + pending_set->AddTiling(raster_transform1, raster_source); + pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION); + + // Set a priority rect so we get tiles. + pending_set->UpdateTilePriorities(gfx::Rect(layer_bounds), 1.f, 1.0, + Occlusion(), false); + + // Make sure all tiles are generated. + EXPECT_EQ(4u, pending_set->tiling_at(0)->AllTilesForTesting().size()); + + // Clone from the pending to the active tree. + active_set->UpdateTilingsToCurrentRasterSourceForActivation( + raster_source.get(), pending_set.get(), Region(), 1.f, 1.f); + + // Verifies active tree cloned the tiling correctly. + ASSERT_EQ(1u, active_set->num_tilings()); + EXPECT_EQ(active_set->tiling_at(0)->raster_transform(), raster_transform1); + EXPECT_EQ(4u, active_set->tiling_at(0)->AllTilesForTesting().size()); + + // Change raster translation on the pending set. + gfx::AxisTransform2d raster_transform2(1.f, gfx::Vector2dF(0.75f, 0.75f)); + pending_set->RemoveAllTilings(); + pending_set->AddTiling(raster_transform2, raster_source); + pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION); + + // Set a different priority rect to get one tile. + pending_set->UpdateTilePriorities(gfx::Rect(1, 1), 1.f, 1.0, Occlusion(), + false); + EXPECT_EQ(1u, pending_set->tiling_at(0)->AllTilesForTesting().size()); + + // Commit the pending to the active tree again. + active_set->UpdateTilingsToCurrentRasterSourceForActivation( + raster_source.get(), pending_set.get(), Region(), 1.f, 1.f); + + // Verifies the old tiling with a different translation is dropped. + ASSERT_EQ(1u, active_set->num_tilings()); + EXPECT_EQ(active_set->tiling_at(0)->raster_transform(), raster_transform2); + EXPECT_EQ(1u, active_set->tiling_at(0)->AllTilesForTesting().size()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/tiles/picture_layer_tiling_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_unittest.cc index fdafb2dea3c..f6185bf3638 100644 --- a/chromium/cc/tiles/picture_layer_tiling_unittest.cc +++ b/chromium/cc/tiles/picture_layer_tiling_unittest.cc @@ -47,12 +47,12 @@ class TestablePictureLayerTiling : public PictureLayerTiling { static std::unique_ptr<TestablePictureLayerTiling> Create( WhichTree tree, - float contents_scale, + const gfx::AxisTransform2d& raster_transform, scoped_refptr<RasterSource> raster_source, PictureLayerTilingClient* client, const LayerTreeSettings& settings) { return base::WrapUnique(new TestablePictureLayerTiling( - tree, contents_scale, raster_source, client, + tree, raster_transform, raster_source, client, settings.tiling_interest_area_padding, settings.skewport_target_time_in_seconds, settings.skewport_extrapolation_limit_in_screen_pixels, @@ -65,13 +65,12 @@ class TestablePictureLayerTiling : public PictureLayerTiling { return PriorityRectType::VISIBLE_RECT; } - using PictureLayerTiling::RemoveTileAt; using PictureLayerTiling::RemoveTilesInRegion; using PictureLayerTiling::ComputePriorityRectTypeForTile; protected: TestablePictureLayerTiling(WhichTree tree, - float contents_scale, + const gfx::AxisTransform2d& raster_transform, scoped_refptr<RasterSource> raster_source, PictureLayerTilingClient* client, size_t tiling_interest_area_padding, @@ -80,7 +79,7 @@ class TestablePictureLayerTiling : public PictureLayerTiling { float min_preraster_distance, float max_preraster_distance) : PictureLayerTiling(tree, - contents_scale, + raster_transform, raster_source, client, min_preraster_distance, @@ -98,7 +97,19 @@ class PictureLayerTilingIteratorTest : public testing::Test { client_.SetTileSize(tile_size); scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds); - tiling_ = TestablePictureLayerTiling::Create(PENDING_TREE, contents_scale, + tiling_ = TestablePictureLayerTiling::Create( + PENDING_TREE, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + raster_source, &client_, LayerTreeSettings()); + tiling_->set_resolution(HIGH_RESOLUTION); + } + + void InitializeWithTranslation(const gfx::Size& tile_size, + const gfx::AxisTransform2d& raster_transform, + const gfx::Size& layer_bounds) { + client_.SetTileSize(tile_size); + scoped_refptr<FakeRasterSource> raster_source = + FakeRasterSource::CreateFilled(layer_bounds); + tiling_ = TestablePictureLayerTiling::Create(PENDING_TREE, raster_transform, raster_source, &client_, LayerTreeSettings()); tiling_->set_resolution(HIGH_RESOLUTION); @@ -110,9 +121,9 @@ class PictureLayerTilingIteratorTest : public testing::Test { client_.SetTileSize(tile_size); scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds); - tiling_ = TestablePictureLayerTiling::Create(ACTIVE_TREE, contents_scale, - raster_source, &client_, - LayerTreeSettings()); + tiling_ = TestablePictureLayerTiling::Create( + ACTIVE_TREE, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + raster_source, &client_, LayerTreeSettings()); tiling_->set_resolution(HIGH_RESOLUTION); } @@ -137,7 +148,7 @@ class PictureLayerTilingIteratorTest : public testing::Test { // tiling scale. This is because coverage computation is done in integer // grids in the dest space, and the overlap between tiles may not guarantee // to enclose an integer grid line to round to if scaled down. - ASSERT_GE(rect_scale, tiling_->contents_scale()); + ASSERT_GE(rect_scale, tiling_->contents_scale_key()); Region remaining = expect_rect; for (PictureLayerTiling::CoverageIterator @@ -205,7 +216,7 @@ class PictureLayerTilingIteratorTest : public testing::Test { void VerifyTilesCoverNonContainedRect(float rect_scale, const gfx::Rect& dest_rect) { - float dest_to_contents_scale = tiling_->contents_scale() / rect_scale; + float dest_to_contents_scale = tiling_->contents_scale_key() / rect_scale; gfx::Rect clamped_rect = gfx::ScaleToEnclosingRect( gfx::Rect(tiling_->tiling_size()), 1.f / dest_to_contents_scale); clamped_rect.Intersect(dest_rect); @@ -498,9 +509,9 @@ TEST_F(PictureLayerTilingIteratorTest, CreateTileJustCoverBorderUp) { scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_size); std::unique_ptr<TestablePictureLayerTiling> active_tiling = - TestablePictureLayerTiling::Create(ACTIVE_TREE, content_scale, - raster_source, &active_client, - LayerTreeSettings()); + TestablePictureLayerTiling::Create( + ACTIVE_TREE, gfx::AxisTransform2d(content_scale, gfx::Vector2dF()), + raster_source, &active_client, LayerTreeSettings()); active_tiling->set_resolution(HIGH_RESOLUTION); gfx::Rect invalid_rect(0, 750, 220, 100); @@ -715,8 +726,8 @@ TEST_F(PictureLayerTilingIteratorTest, scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds); - tiling_ = TestablePictureLayerTiling::Create(PENDING_TREE, 1.f, raster_source, - &client_, settings); + tiling_ = TestablePictureLayerTiling::Create( + PENDING_TREE, gfx::AxisTransform2d(), raster_source, &client_, settings); tiling_->set_resolution(HIGH_RESOLUTION); VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds)); VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false)); @@ -753,8 +764,9 @@ TEST(ComputeTilePriorityRectsTest, VisibleTiles) { scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(current_layer_bounds); std::unique_ptr<TestablePictureLayerTiling> tiling = - TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source, - &client, LayerTreeSettings()); + TestablePictureLayerTiling::Create(ACTIVE_TREE, gfx::AxisTransform2d(), + raster_source, &client, + LayerTreeSettings()); tiling->set_resolution(HIGH_RESOLUTION); LayerTreeSettings settings; @@ -811,8 +823,9 @@ TEST(ComputeTilePriorityRectsTest, OffscreenTiles) { scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(current_layer_bounds); std::unique_ptr<TestablePictureLayerTiling> tiling = - TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source, - &client, LayerTreeSettings()); + TestablePictureLayerTiling::Create(ACTIVE_TREE, gfx::AxisTransform2d(), + raster_source, &client, + LayerTreeSettings()); tiling->set_resolution(HIGH_RESOLUTION); LayerTreeSettings settings; @@ -879,8 +892,9 @@ TEST(ComputeTilePriorityRectsTest, PartiallyOffscreenLayer) { scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(current_layer_bounds); std::unique_ptr<TestablePictureLayerTiling> tiling = - TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source, - &client, LayerTreeSettings()); + TestablePictureLayerTiling::Create(ACTIVE_TREE, gfx::AxisTransform2d(), + raster_source, &client, + LayerTreeSettings()); tiling->set_resolution(HIGH_RESOLUTION); LayerTreeSettings settings; @@ -921,8 +935,9 @@ TEST(PictureLayerTilingTest, RecycledTilesClearedOnReset) { scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(gfx::Size(100, 100)); std::unique_ptr<TestablePictureLayerTiling> active_tiling = - TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source, - &active_client, LayerTreeSettings()); + TestablePictureLayerTiling::Create(ACTIVE_TREE, gfx::AxisTransform2d(), + raster_source, &active_client, + LayerTreeSettings()); active_tiling->set_resolution(HIGH_RESOLUTION); // Create all tiles on this tiling. gfx::Rect visible_rect = gfx::Rect(0, 0, 100, 100); @@ -937,8 +952,9 @@ TEST(PictureLayerTilingTest, RecycledTilesClearedOnReset) { raster_source = FakeRasterSource::CreateFilled(gfx::Size(100, 100)); std::unique_ptr<TestablePictureLayerTiling> recycle_tiling = - TestablePictureLayerTiling::Create(PENDING_TREE, 1.0f, raster_source, - &recycle_client, settings); + TestablePictureLayerTiling::Create(PENDING_TREE, gfx::AxisTransform2d(), + raster_source, &recycle_client, + settings); recycle_tiling->set_resolution(HIGH_RESOLUTION); // Create all tiles on the recycle tiling. @@ -966,8 +982,9 @@ TEST(PictureLayerTilingTest, EdgeCaseTileNowAndRequired) { scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(gfx::Size(500, 500)); std::unique_ptr<TestablePictureLayerTiling> pending_tiling = - TestablePictureLayerTiling::Create(PENDING_TREE, 1.0f, raster_source, - &pending_client, LayerTreeSettings()); + TestablePictureLayerTiling::Create(PENDING_TREE, gfx::AxisTransform2d(), + raster_source, &pending_client, + LayerTreeSettings()); pending_tiling->set_resolution(HIGH_RESOLUTION); pending_tiling->set_can_require_tiles_for_activation(true); @@ -1038,9 +1055,9 @@ TEST_F(PictureLayerTilingIteratorTest, GiantRect) { client_.SetTileSize(tile_size); scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateEmpty(layer_size); - tiling_ = TestablePictureLayerTiling::Create(PENDING_TREE, contents_scale, - raster_source, &client_, - LayerTreeSettings()); + tiling_ = TestablePictureLayerTiling::Create( + PENDING_TREE, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + raster_source, &client_, LayerTreeSettings()); gfx::Rect content_rect(25554432, 25554432, 950, 860); VerifyTilesExactlyCoverRect(contents_scale, content_rect); @@ -1126,7 +1143,8 @@ TEST_F(PictureLayerTilingIteratorTest, TilesStoreTilings) { scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(bounds); auto active_tiling = TestablePictureLayerTiling::Create( - ACTIVE_TREE, 1.f, raster_source, &client_, LayerTreeSettings()); + ACTIVE_TREE, gfx::AxisTransform2d(), raster_source, &client_, + LayerTreeSettings()); active_tiling->set_resolution(HIGH_RESOLUTION); active_tiling->TakeTilesAndPropertiesFrom(tiling_.get(), @@ -1136,5 +1154,106 @@ TEST_F(PictureLayerTilingIteratorTest, TilesStoreTilings) { } } +TEST_F(PictureLayerTilingIteratorTest, FractionalTranslatedTiling) { + InitializeWithTranslation( + gfx::Size(256, 256), + gfx::AxisTransform2d(1.f, gfx::Vector2dF(0.125f, 0.125f)), + gfx::Size(1000, 1)); + EXPECT_EQ(tiling_->tiling_size(), gfx::Size(1001, 2)); + SetLiveRectAndVerifyTiles(gfx::Rect(1000, 1)); + + // Verifies the texture coordinate is correctly translated. + for (PictureLayerTiling::CoverageIterator iter(tiling_.get(), 1.f, + gfx::Rect(1000, 1)); + iter; ++iter) { + gfx::Rect geometry_rect = iter.geometry_rect(); + gfx::RectF texture_rect = iter.texture_rect(); + if (geometry_rect == gfx::Rect(0, 0, 255, 1)) { + EXPECT_EQ(gfx::RectF(0.125f, 0.125f, 255.f, 1.f), texture_rect); + } else if (geometry_rect == gfx::Rect(255, 0, 254, 1)) { + EXPECT_EQ(gfx::RectF(1.125f, 0.125f, 254.f, 1.f), texture_rect); + } else if (geometry_rect == gfx::Rect(509, 0, 254, 1)) { + EXPECT_EQ(gfx::RectF(1.125f, 0.125f, 254.f, 1.f), texture_rect); + } else { + EXPECT_EQ(gfx::Rect(763, 0, 237, 1), geometry_rect); + EXPECT_EQ(gfx::RectF(1.125f, 0.125f, 237.f, 1.f), texture_rect); + } + } + + // Similar to above, with a different coverage scale. + for (PictureLayerTiling::CoverageIterator iter(tiling_.get(), 1.375f, + gfx::Rect(1375, 2)); + iter; ++iter) { + gfx::Rect geometry_rect = iter.geometry_rect(); + gfx::RectF texture_rect = iter.texture_rect(); + if (geometry_rect == gfx::Rect(0, 0, 351, 2)) { + gfx::RectF expectation(geometry_rect); + expectation.Scale(1.f / 1.375f); + expectation.Offset(0.125f, 0.125f); + EXPECT_FLOAT_EQ(expectation.x(), texture_rect.x()); + EXPECT_FLOAT_EQ(expectation.y(), texture_rect.y()); + EXPECT_FLOAT_EQ(expectation.width(), texture_rect.width()); + EXPECT_FLOAT_EQ(expectation.height(), texture_rect.height()); + } else if (geometry_rect == gfx::Rect(351, 0, 349, 2)) { + gfx::RectF expectation(geometry_rect); + expectation.Scale(1.f / 1.375f); + expectation.Offset(0.125f - 254.f, 0.125f); + EXPECT_FLOAT_EQ(expectation.x(), texture_rect.x()); + EXPECT_FLOAT_EQ(expectation.y(), texture_rect.y()); + EXPECT_FLOAT_EQ(expectation.width(), texture_rect.width()); + EXPECT_FLOAT_EQ(expectation.height(), texture_rect.height()); + } else if (geometry_rect == gfx::Rect(700, 0, 349, 2)) { + gfx::RectF expectation(geometry_rect); + expectation.Scale(1.f / 1.375f); + expectation.Offset(0.125f - 254.f * 2.f, 0.125f); + EXPECT_FLOAT_EQ(expectation.x(), texture_rect.x()); + EXPECT_FLOAT_EQ(expectation.y(), texture_rect.y()); + EXPECT_FLOAT_EQ(expectation.width(), texture_rect.width()); + EXPECT_FLOAT_EQ(expectation.height(), texture_rect.height()); + } else { + EXPECT_EQ(gfx::Rect(1049, 0, 326, 2), geometry_rect); + gfx::RectF expectation(geometry_rect); + expectation.Scale(1.f / 1.375f); + expectation.Offset(0.125f - 254.f * 3.f, 0.125f); + EXPECT_FLOAT_EQ(expectation.x(), texture_rect.x()); + EXPECT_FLOAT_EQ(expectation.y(), texture_rect.y()); + EXPECT_FLOAT_EQ(expectation.width(), texture_rect.width()); + EXPECT_FLOAT_EQ(expectation.height(), texture_rect.height()); + } + } +} + +TEST_F(PictureLayerTilingIteratorTest, FractionalTranslatedTilingOverflow) { + // This tests a corner case where the coverage rect is slightly greater + // than the layer rect due to rounding up, and the bottom right edge of + // the tiling coincide with actual layer bound. That is, the requested + // coverage rect slightly exceed the valid extent, but we still return + // full coverage as a special case for external edges. + + // The layer bounds is (9, 9), which after scale and translation + // becomes (l=0.5, t=0.5, r=14, b=14) in the contents space. + InitializeWithTranslation( + gfx::Size(256, 256), + gfx::AxisTransform2d(1.5f, gfx::Vector2dF(0.5f, 0.5f)), gfx::Size(9, 9)); + EXPECT_EQ(tiling_->tiling_size(), gfx::Size(14, 14)); + SetLiveRectAndVerifyTiles(gfx::Rect(9, 9)); + + PictureLayerTiling::CoverageIterator iter(tiling_.get(), 1.56f, + gfx::Rect(15, 15)); + ASSERT_TRUE(iter); + gfx::Rect geometry_rect = iter.geometry_rect(); + gfx::RectF texture_rect = iter.texture_rect(); + EXPECT_EQ(gfx::Rect(0, 0, 15, 15), geometry_rect); + gfx::RectF expectation(geometry_rect); + expectation.Scale(1.5f / 1.56f); + expectation.Offset(0.5f, 0.5f); + EXPECT_FLOAT_EQ(expectation.x(), texture_rect.x()); + EXPECT_FLOAT_EQ(expectation.y(), texture_rect.y()); + EXPECT_FLOAT_EQ(expectation.width(), texture_rect.width()); + EXPECT_FLOAT_EQ(expectation.height(), texture_rect.height()); + + EXPECT_FALSE(++iter); +} + } // namespace } // namespace cc diff --git a/chromium/cc/tiles/prioritized_tile.h b/chromium/cc/tiles/prioritized_tile.h index db7967e2bde..7decc73cca1 100644 --- a/chromium/cc/tiles/prioritized_tile.h +++ b/chromium/cc/tiles/prioritized_tile.h @@ -5,8 +5,8 @@ #ifndef CC_TILES_PRIORITIZED_TILE_H_ #define CC_TILES_PRIORITIZED_TILE_H_ -#include "cc/base/cc_export.h" -#include "cc/playback/raster_source.h" +#include "cc/cc_export.h" +#include "cc/raster/raster_source.h" #include "cc/tiles/picture_layer_tiling.h" #include "cc/tiles/tile.h" #include "cc/tiles/tile_priority.h" diff --git a/chromium/cc/tiles/raster_tile_priority_queue.h b/chromium/cc/tiles/raster_tile_priority_queue.h index 5a41827f69c..98860762d58 100644 --- a/chromium/cc/tiles/raster_tile_priority_queue.h +++ b/chromium/cc/tiles/raster_tile_priority_queue.h @@ -8,7 +8,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/picture_layer_impl.h" #include "cc/tiles/tile_priority.h" diff --git a/chromium/cc/tiles/raster_tile_priority_queue_all.h b/chromium/cc/tiles/raster_tile_priority_queue_all.h index af4983ae51b..698dfe0319b 100644 --- a/chromium/cc/tiles/raster_tile_priority_queue_all.h +++ b/chromium/cc/tiles/raster_tile_priority_queue_all.h @@ -10,7 +10,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/picture_layer_impl.h" #include "cc/tiles/raster_tile_priority_queue.h" #include "cc/tiles/tile_priority.h" diff --git a/chromium/cc/tiles/software_image_decode_cache.cc b/chromium/cc/tiles/software_image_decode_cache.cc index e5d3319ceb4..716d1f45ef3 100644 --- a/chromium/cc/tiles/software_image_decode_cache.cc +++ b/chromium/cc/tiles/software_image_decode_cache.cc @@ -19,7 +19,7 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/raster/tile_task.h" #include "cc/resources/resource_format_utils.h" #include "cc/tiles/mipmap_util.h" @@ -138,7 +138,7 @@ class ImageDecodeTaskImpl : public TileTask { SkSize GetScaleAdjustment(const ImageDecodeCacheKey& key) { // If the requested filter quality did not require scale, then the adjustment // is identity. - if (key.can_use_original_decode() || key.should_use_subrect()) { + if (key.can_use_original_size_decode() || key.should_use_subrect()) { return SkSize::Make(1.f, 1.f); } else if (key.filter_quality() == kMedium_SkFilterQuality) { return MipMapUtil::GetScaleAdjustmentForSize(key.src_rect().size(), @@ -274,7 +274,6 @@ bool SoftwareImageDecodeCache::GetTaskForImageAndRefInternal( (new_image_fits_in_memory && decoded_it->second->Lock())) { RefImage(key); *task = nullptr; - SanityCheckState(__LINE__, true); // If the image wasn't locked, then we just succeeded in locking it. if (!image_was_locked) { @@ -305,7 +304,6 @@ bool SoftwareImageDecodeCache::GetTaskForImageAndRefInternal( if (existing_task) { RefImage(key); *task = existing_task; - SanityCheckState(__LINE__, true); return true; } @@ -317,7 +315,6 @@ bool SoftwareImageDecodeCache::GetTaskForImageAndRefInternal( if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == decoded_images_ref_counts_.end())) { *task = nullptr; - SanityCheckState(__LINE__, true); return false; } @@ -327,7 +324,6 @@ bool SoftwareImageDecodeCache::GetTaskForImageAndRefInternal( existing_task = make_scoped_refptr( new ImageDecodeTaskImpl(this, key, image, task_type, tracing_info)); *task = existing_task; - SanityCheckState(__LINE__, true); return true; } @@ -365,14 +361,11 @@ void SoftwareImageDecodeCache::UnrefImage(const DrawImage& image) { auto decoded_image_it = decoded_images_.Peek(key); // If we've never decoded the image before ref reached 0, then we wouldn't // have it in our cache. This would happen if we canceled tasks. - if (decoded_image_it == decoded_images_.end()) { - SanityCheckState(__LINE__, true); + if (decoded_image_it == decoded_images_.end()) return; - } DCHECK(decoded_image_it->second->is_locked()); decoded_image_it->second->Unlock(); } - SanityCheckState(__LINE__, true); } void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key, @@ -436,7 +429,6 @@ void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key, } decoded_images_.Put(key, std::move(decoded_image)); - SanityCheckState(__LINE__, true); } std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> @@ -454,7 +446,7 @@ SoftwareImageDecodeCache::DecodeImageInternal(const ImageKey& key, case kLow_SkFilterQuality: if (key.should_use_subrect()) return GetSubrectImageDecode(key, std::move(image)); - return GetOriginalImageDecode(std::move(image)); + return GetOriginalSizeImageDecode(key, std::move(image)); case kMedium_SkFilterQuality: case kHigh_SkFilterQuality: return GetScaledImageDecode(key, std::move(image)); @@ -494,7 +486,6 @@ DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDrawInternal( if (decoded_image->is_locked()) { RefImage(key); decoded_image->mark_used(); - SanityCheckState(__LINE__, true); return DecodedDrawImage( decoded_image->image(), decoded_image->src_rect_offset(), GetScaleAdjustment(key), GetDecodedFilterQuality(key)); @@ -510,7 +501,6 @@ DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDrawInternal( if (at_raster_images_it != at_raster_decoded_images_.end()) { DCHECK(at_raster_images_it->second->is_locked()); RefAtRasterImage(key); - SanityCheckState(__LINE__, true); DecodedImage* at_raster_decoded_image = at_raster_images_it->second.get(); at_raster_decoded_image->mark_used(); auto decoded_draw_image = @@ -564,7 +554,6 @@ DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDrawInternal( DCHECK(decoded_image); DCHECK(decoded_image->is_locked()); RefAtRasterImage(key); - SanityCheckState(__LINE__, true); decoded_image->mark_used(); auto decoded_draw_image = DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), @@ -574,22 +563,35 @@ DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDrawInternal( } std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> -SoftwareImageDecodeCache::GetOriginalImageDecode(sk_sp<const SkImage> image) { +SoftwareImageDecodeCache::GetOriginalSizeImageDecode( + const ImageKey& key, + sk_sp<const SkImage> image) { SkImageInfo decoded_info = CreateImageInfo(image->width(), image->height(), format_); + sk_sp<SkColorSpace> target_color_space = + key.target_color_space().ToSkColorSpace(); + std::unique_ptr<base::DiscardableMemory> decoded_pixels; { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "SoftwareImageDecodeCache::GetOriginalImageDecode - " + "SoftwareImageDecodeCache::GetOriginalSizeImageDecode - " "allocate decoded pixels"); decoded_pixels = base::DiscardableMemoryAllocator::GetInstance() ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * decoded_info.height()); } + if (target_color_space) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::GetOriginalSizeImageDecode - " + "color conversion"); + image = image->makeColorSpace(target_color_space, + SkTransferFunctionBehavior::kIgnore); + DCHECK(image); + } { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "SoftwareImageDecodeCache::GetOriginalImageDecode - " + "SoftwareImageDecodeCache::GetOriginalSizeImageDecode - " "read pixels"); bool result = image->readPixels(decoded_info, decoded_pixels->data(), decoded_info.minRowBytes(), 0, 0, @@ -600,9 +602,11 @@ SoftwareImageDecodeCache::GetOriginalImageDecode(sk_sp<const SkImage> image) { return nullptr; } } - return base::MakeUnique<DecodedImage>(decoded_info, std::move(decoded_pixels), - SkSize::Make(0, 0), - next_tracing_id_.GetNext()); + + return base::MakeUnique<DecodedImage>( + decoded_info.makeColorSpace(target_color_space), + std::move(decoded_pixels), SkSize::Make(0, 0), + next_tracing_id_.GetNext()); } std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> @@ -611,13 +615,16 @@ SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key, // Construct a key to use in GetDecodedImageForDrawInternal(). // This allows us to reuse an image in any cache if available. gfx::Rect full_image_rect(image->width(), image->height()); - DrawImage original_size_draw_image(std::move(image), - gfx::RectToSkIRect(full_image_rect), - kNone_SkFilterQuality, SkMatrix::I()); + DrawImage original_size_draw_image( + std::move(image), gfx::RectToSkIRect(full_image_rect), + kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space()); ImageKey original_size_key = ImageKey::FromDrawImage(original_size_draw_image); + sk_sp<SkColorSpace> target_color_space = + key.target_color_space().ToSkColorSpace(); + // Sanity checks. - DCHECK(original_size_key.can_use_original_decode()) + DCHECK(original_size_key.can_use_original_size_decode()) << original_size_key.ToString(); DCHECK(full_image_rect.size() == original_size_key.target_size()); @@ -628,6 +635,8 @@ SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key, if (!decoded_draw_image.image()) return nullptr; + DCHECK(SkColorSpace::Equals(decoded_draw_image.image()->colorSpace(), + target_color_space.get())); SkImageInfo subrect_info = CreateImageInfo( key.target_size().width(), key.target_size().height(), format_); std::unique_ptr<base::DiscardableMemory> subrect_pixels; @@ -655,8 +664,10 @@ SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key, // This should never fail. DCHECK(result); } + return base::WrapUnique( - new DecodedImage(subrect_info, std::move(subrect_pixels), + new DecodedImage(subrect_info.makeColorSpace(target_color_space), + std::move(subrect_pixels), SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), next_tracing_id_.GetNext())); } @@ -667,13 +678,16 @@ SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key, // Construct a key to use in GetDecodedImageForDrawInternal(). // This allows us to reuse an image in any cache if available. gfx::Rect full_image_rect(image->width(), image->height()); - DrawImage original_size_draw_image(std::move(image), - gfx::RectToSkIRect(full_image_rect), - kNone_SkFilterQuality, SkMatrix::I()); + DrawImage original_size_draw_image( + std::move(image), gfx::RectToSkIRect(full_image_rect), + kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space()); ImageKey original_size_key = ImageKey::FromDrawImage(original_size_draw_image); + sk_sp<SkColorSpace> target_color_space = + key.target_color_space().ToSkColorSpace(); + // Sanity checks. - DCHECK(original_size_key.can_use_original_decode()) + DCHECK(original_size_key.can_use_original_size_decode()) << original_size_key.ToString(); DCHECK(full_image_rect.size() == original_size_key.target_size()); @@ -694,6 +708,8 @@ SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key, } DCHECK(!key.target_size().IsEmpty()); + DCHECK(SkColorSpace::Equals(decoded_draw_image.image()->colorSpace(), + target_color_space.get())); SkImageInfo scaled_info = CreateImageInfo( key.target_size().width(), key.target_size().height(), format_); std::unique_ptr<base::DiscardableMemory> scaled_pixels; @@ -718,7 +734,8 @@ SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key, } return base::MakeUnique<DecodedImage>( - scaled_info, std::move(scaled_pixels), + scaled_info.makeColorSpace(decoded_draw_image.image()->refColorSpace()), + std::move(scaled_pixels), SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), next_tracing_id_.GetNext()); } @@ -737,7 +754,6 @@ void SoftwareImageDecodeCache::DrawWithImageFinished( UnrefAtRasterImage(key); else UnrefImage(image); - SanityCheckState(__LINE__, false); } void SoftwareImageDecodeCache::RefAtRasterImage(const ImageKey& key) { @@ -818,6 +834,11 @@ void SoftwareImageDecodeCache::ReduceCacheUsage() { ReduceCacheUsageUntilWithinLimit(max_items_in_cache_); } +void SoftwareImageDecodeCache::ClearCache() { + base::AutoLock lock(lock_); + ReduceCacheUsageUntilWithinLimit(0); +} + void SoftwareImageDecodeCache::RemovePendingTask(const ImageKey& key, DecodeTaskType task_type) { base::AutoLock lock(lock_); @@ -876,38 +897,6 @@ void SoftwareImageDecodeCache::DumpImageMemoryForCache( } } -void SoftwareImageDecodeCache::SanityCheckState(int line, bool lock_acquired) { -#if DCHECK_IS_ON() - if (!lock_acquired) { - base::AutoLock lock(lock_); - SanityCheckState(line, true); - return; - } - - MemoryBudget budget(locked_images_budget_.total_limit_bytes()); - for (const auto& image_pair : decoded_images_) { - const auto& key = image_pair.first; - const auto& image = image_pair.second; - - auto ref_it = decoded_images_ref_counts_.find(key); - if (image->is_locked()) { - budget.AddUsage(key.locked_bytes()); - DCHECK(ref_it != decoded_images_ref_counts_.end()) << line; - } else { - DCHECK(ref_it == decoded_images_ref_counts_.end() || - pending_in_raster_image_tasks_.find(key) != - pending_in_raster_image_tasks_.end() || - pending_out_of_raster_image_tasks_.find(key) != - pending_out_of_raster_image_tasks_.end()) - << line; - } - } - DCHECK_GE(budget.AvailableMemoryBytes(), - locked_images_budget_.AvailableMemoryBytes()) - << line; -#endif // DCHECK_IS_ON() -} - // SoftwareImageDecodeCacheKey ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) { const SkSize& scale = image.scale(); @@ -961,10 +950,11 @@ ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) { } } - bool can_use_original_decode = + bool can_use_original_size_decode = quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality; + bool should_use_subrect = false; - if (can_use_original_decode && + if (can_use_original_size_decode && (image.image()->width() >= kMinDimensionToSubrect || image.image()->height() >= kMinDimensionToSubrect)) { base::CheckedNumeric<size_t> checked_original_size = 4u; @@ -981,7 +971,7 @@ ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) { if (original_size > kMemoryThresholdToSubrect && src_rect_size <= original_size * kMemoryRatioToSubrect) { should_use_subrect = true; - can_use_original_decode = false; + can_use_original_size_decode = false; } } @@ -992,7 +982,7 @@ ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) { if (!target_size.IsEmpty()) { if (should_use_subrect) target_size = src_rect.size(); - else if (can_use_original_decode) + else if (can_use_original_size_decode) target_size = gfx::Size(image.image()->width(), image.image()->height()); } @@ -1004,23 +994,26 @@ ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) { } return ImageDecodeCacheKey(image.image()->uniqueID(), src_rect, target_size, - quality, can_use_original_decode, - should_use_subrect); + image.target_color_space(), quality, + can_use_original_size_decode, should_use_subrect); } -ImageDecodeCacheKey::ImageDecodeCacheKey(uint32_t image_id, - const gfx::Rect& src_rect, - const gfx::Size& target_size, - SkFilterQuality filter_quality, - bool can_use_original_decode, - bool should_use_subrect) +ImageDecodeCacheKey::ImageDecodeCacheKey( + uint32_t image_id, + const gfx::Rect& src_rect, + const gfx::Size& target_size, + const gfx::ColorSpace& target_color_space, + SkFilterQuality filter_quality, + bool can_use_original_size_decode, + bool should_use_subrect) : image_id_(image_id), src_rect_(src_rect), target_size_(target_size), + target_color_space_(target_color_space), filter_quality_(filter_quality), - can_use_original_decode_(can_use_original_decode), + can_use_original_size_decode_(can_use_original_size_decode), should_use_subrect_(should_use_subrect) { - if (can_use_original_decode_) { + if (can_use_original_size_decode_) { hash_ = std::hash<uint32_t>()(image_id_); } else { // TODO(vmpstr): This is a mess. Maybe it's faster to just search the vector @@ -1036,6 +1029,8 @@ ImageDecodeCacheKey::ImageDecodeCacheKey(uint32_t image_id, hash_ = base::HashInts(base::HashInts(src_rect_hash, target_size_hash), base::HashInts(image_id_, filter_quality_)); } + // Include the target color space in the hash regardless of scaling. + hash_ = base::HashInts(hash_, target_color_space.GetHash()); } ImageDecodeCacheKey::ImageDecodeCacheKey(const ImageDecodeCacheKey& other) = @@ -1046,8 +1041,9 @@ std::string ImageDecodeCacheKey::ToString() const { str << "id[" << image_id_ << "] src_rect[" << src_rect_.x() << "," << src_rect_.y() << " " << src_rect_.width() << "x" << src_rect_.height() << "] target_size[" << target_size_.width() << "x" - << target_size_.height() << "] filter_quality[" << filter_quality_ - << "] can_use_original_decode [" << can_use_original_decode_ + << target_size_.height() << "] target_color_space" + << target_color_space_.ToString() << " filter_quality[" << filter_quality_ + << "] can_use_original_size_decode [" << can_use_original_size_decode_ << "] should_use_subrect [" << should_use_subrect_ << "] hash [" << hash_ << "]"; return str.str(); diff --git a/chromium/cc/tiles/software_image_decode_cache.h b/chromium/cc/tiles/software_image_decode_cache.h index 277d4e77f58..1d3e2ac75c4 100644 --- a/chromium/cc/tiles/software_image_decode_cache.h +++ b/chromium/cc/tiles/software_image_decode_cache.h @@ -20,10 +20,10 @@ #include "base/numerics/safe_math.h" #include "base/threading/thread_checker.h" #include "base/trace_event/memory_dump_provider.h" -#include "cc/base/cc_export.h" -#include "cc/playback/decoded_draw_image.h" -#include "cc/playback/draw_image.h" +#include "cc/cc_export.h" +#include "cc/paint/draw_image.h" #include "cc/resources/resource_format.h" +#include "cc/tiles/decoded_draw_image.h" #include "cc/tiles/image_decode_cache.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "ui/gfx/geometry/rect.h" @@ -45,8 +45,10 @@ class CC_EXPORT ImageDecodeCacheKey { // decodes are the same, so if we can use the original decode, return true. // If not, then we have to compare every field. return image_id_ == other.image_id_ && - can_use_original_decode_ == other.can_use_original_decode_ && - (can_use_original_decode_ || + can_use_original_size_decode_ == + other.can_use_original_size_decode_ && + target_color_space_ == other.target_color_space_ && + (can_use_original_size_decode_ || (src_rect_ == other.src_rect_ && target_size_ == other.target_size_ && filter_quality_ == other.filter_quality_)); @@ -60,8 +62,13 @@ class CC_EXPORT ImageDecodeCacheKey { SkFilterQuality filter_quality() const { return filter_quality_; } gfx::Rect src_rect() const { return src_rect_; } gfx::Size target_size() const { return target_size_; } + const gfx::ColorSpace& target_color_space() const { + return target_color_space_; + } - bool can_use_original_decode() const { return can_use_original_decode_; } + bool can_use_original_size_decode() const { + return can_use_original_size_decode_; + } bool should_use_subrect() const { return should_use_subrect_; } size_t get_hash() const { return hash_; } @@ -81,15 +88,17 @@ class CC_EXPORT ImageDecodeCacheKey { ImageDecodeCacheKey(uint32_t image_id, const gfx::Rect& src_rect, const gfx::Size& size, + const gfx::ColorSpace& target_color_space, SkFilterQuality filter_quality, - bool can_use_original_decode, + bool can_use_original_size_decode, bool should_use_subrect); uint32_t image_id_; gfx::Rect src_rect_; gfx::Size target_size_; + gfx::ColorSpace target_color_space_; SkFilterQuality filter_quality_; - bool can_use_original_decode_; + bool can_use_original_size_decode_; bool should_use_subrect_; size_t hash_; }; @@ -130,6 +139,7 @@ class CC_EXPORT SoftwareImageDecodeCache // Software doesn't keep outstanding images pinned, so this is a no-op. void SetShouldAggressivelyFreeResources( bool aggressively_free_resources) override {} + void ClearCache() override; // Decode the given image and store it in the cache. This is only called by an // image decode task from a worker thread. @@ -143,6 +153,8 @@ class CC_EXPORT SoftwareImageDecodeCache bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) override; + size_t GetNumCacheEntriesForTesting() const { return decoded_images_.size(); } + private: // DecodedImage is a convenience storage for discardable memory. It can also // construct an image out of SkImageInfo and stored discardable memory. @@ -237,18 +249,20 @@ class CC_EXPORT SoftwareImageDecodeCache DecodedDrawImage GetDecodedImageForDrawInternal(const ImageKey& key, const DrawImage& draw_image); - // GetOriginalImageDecode is called by DecodeImageInternal when the quality - // does not scale the image. Like DecodeImageInternal, it should be called - // with no lock acquired and it returns nullptr if the decoding failed. - std::unique_ptr<DecodedImage> GetOriginalImageDecode( + // GetOriginalSizeImageDecode is called by DecodeImageInternal when the + // quality does not scale the image. Like DecodeImageInternal, it should be + // called with no lock acquired and it returns nullptr if the decoding failed. + std::unique_ptr<DecodedImage> GetOriginalSizeImageDecode( + const ImageKey& key, sk_sp<const SkImage> image); - // GetSubrectImageDecode is similar to GetOriginalImageDecode in that no scale - // is performed on the image. However, we extract a subrect (copy it out) and - // only return this subrect in order to cache a smaller amount of memory. Note - // that this uses GetOriginalImageDecode to get the initial data, which - // ensures that we cache an unlocked version of the original image in case we - // need to extract multiple subrects (as would be the case in an atlas). + // GetSubrectImageDecode is similar to GetOriginalSizeImageDecode in that no + // scale is performed on the image. However, we extract a subrect (copy it + // out) and only return this subrect in order to cache a smaller amount of + // memory. Note that this uses GetOriginalSizeImageDecode to get the initial + // data, which ensures that we cache an unlocked version of the original image + // in case we need to extract multiple subrects (as would be the case in an + // atlas). std::unique_ptr<DecodedImage> GetSubrectImageDecode( const ImageKey& key, sk_sp<const SkImage> image); @@ -261,7 +275,6 @@ class CC_EXPORT SoftwareImageDecodeCache const ImageKey& key, sk_sp<const SkImage> image); - void SanityCheckState(int line, bool lock_acquired); void RefImage(const ImageKey& key); void RefAtRasterImage(const ImageKey& key); void UnrefAtRasterImage(const ImageKey& key); diff --git a/chromium/cc/tiles/software_image_decode_cache_perftest.cc b/chromium/cc/tiles/software_image_decode_cache_perftest.cc index be32b580585..0267f20d4f4 100644 --- a/chromium/cc/tiles/software_image_decode_cache_perftest.cc +++ b/chromium/cc/tiles/software_image_decode_cache_perftest.cc @@ -4,8 +4,8 @@ #include <vector> -#include "cc/debug/lap_timer.h" -#include "cc/playback/draw_image.h" +#include "cc/base/lap_timer.h" +#include "cc/paint/draw_image.h" #include "cc/raster/tile_task.h" #include "cc/tiles/software_image_decode_cache.h" #include "testing/gtest/include/gtest/gtest.h" @@ -57,7 +57,8 @@ class SoftwareImageDecodeCachePerfTest : public testing::Test { for (auto& scale : scales) { images.emplace_back( CreateImage(rect.width(), rect.height()), subrect, quality, - CreateMatrix(SkSize::Make(scale.first, scale.second))); + CreateMatrix(SkSize::Make(scale.first, scale.second)), + gfx::ColorSpace()); } } } diff --git a/chromium/cc/tiles/software_image_decode_cache_unittest.cc b/chromium/cc/tiles/software_image_decode_cache_unittest.cc index 67855fbd19a..7d26359ba3d 100644 --- a/chromium/cc/tiles/software_image_decode_cache_unittest.cc +++ b/chromium/cc/tiles/software_image_decode_cache_unittest.cc @@ -4,7 +4,7 @@ #include "cc/tiles/software_image_decode_cache.h" -#include "cc/playback/draw_image.h" +#include "cc/paint/draw_image.h" #include "cc/resources/resource_format.h" #include "cc/test/test_tile_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,6 +13,10 @@ namespace cc { namespace { +gfx::ColorSpace DefaultColorSpace() { + return gfx::ColorSpace::CreateSRGB(); +} + size_t kLockedMemoryLimitBytes = 128 * 1024 * 1024; class TestSoftwareImageDecodeCache : public SoftwareImageDecodeCache { public: @@ -21,12 +25,19 @@ class TestSoftwareImageDecodeCache : public SoftwareImageDecodeCache { kLockedMemoryLimitBytes) {} }; -sk_sp<SkImage> CreateImage(int width, int height) { +sk_sp<SkImage> CreateImageWithColorSpace(int width, + int height, + const gfx::ColorSpace& color_space) { SkBitmap bitmap; - bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height)); + bitmap.allocPixels( + SkImageInfo::MakeN32Premul(width, height, color_space.ToSkColorSpace())); return SkImage::MakeFromBitmap(bitmap); } +sk_sp<SkImage> CreateImage(int width, int height) { + return CreateImageWithColorSpace(width, height, DefaultColorSpace()); +} + SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) { SkMatrix matrix; matrix.setScale(scale.width(), scale.height()); @@ -46,14 +57,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQuality) { for (auto quality : qualities) { DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(quality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); // Since the original decode will be used, the locked_bytes is that of the // original image. EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); @@ -67,14 +79,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQuality) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(quality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -85,14 +98,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfEnlarging) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -103,14 +117,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfIdentity) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -122,14 +137,15 @@ TEST(SoftwareImageDecodeCacheTest, DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable)); + CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -141,14 +157,15 @@ TEST(SoftwareImageDecodeCacheTest, DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable)); + CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -160,14 +177,15 @@ TEST(SoftwareImageDecodeCacheTest, DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -178,14 +196,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_5Scale) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(500, key.target_size().width()); EXPECT_EQ(200, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(500u * 200u * 4u, key.locked_bytes()); } @@ -196,14 +215,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_0cale) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(500, key.target_size().width()); EXPECT_EQ(200, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(500u * 200u * 4u, key.locked_bytes()); } @@ -214,14 +234,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_75Scale) { DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable)); + CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(quality, key.filter_quality()); EXPECT_EQ(500, key.target_size().width()); EXPECT_EQ(200, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(500u * 200u * 4u, key.locked_bytes()); } @@ -232,14 +253,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_5Scale) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(quality, key.filter_quality()); EXPECT_EQ(250, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(250u * 100u * 4u, key.locked_bytes()); } @@ -250,14 +272,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_49Scale) { DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable)); + CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(quality, key.filter_quality()); EXPECT_EQ(250, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(250u * 100u * 4u, key.locked_bytes()); } @@ -268,14 +291,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_1Scale) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable)); + CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(quality, key.filter_quality()); EXPECT_EQ(62, key.target_size().width()); EXPECT_EQ(25, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(62u * 25u * 4u, key.locked_bytes()); } @@ -286,14 +310,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_01Scale) { DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable)); + CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(quality, key.filter_quality()); EXPECT_EQ(7, key.target_size().width()); EXPECT_EQ(3, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(7u * 3u * 4u, key.locked_bytes()); } @@ -305,14 +330,15 @@ TEST(SoftwareImageDecodeCacheTest, DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kMedium_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -324,14 +350,15 @@ TEST(SoftwareImageDecodeCacheTest, DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.2f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.2f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kMedium_SkFilterQuality, key.filter_quality()); EXPECT_EQ(50, key.target_size().width()); EXPECT_EQ(50, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(50u * 50u * 4u, key.locked_bytes()); } @@ -342,14 +369,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyDowscalesHighQuality) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(2.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(2.5f, 1.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(quality, key.filter_quality()); EXPECT_EQ(250, key.target_size().width()); EXPECT_EQ(150, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(250u * 150u * 4u, key.locked_bytes()); } @@ -363,14 +391,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToMediumIfTooLarge) { // become low. DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.9f, 2.f), is_decomposable)); + CreateMatrix(SkSize::Make(0.9f, 2.f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kMedium_SkFilterQuality, key.filter_quality()); EXPECT_EQ(4555, key.target_size().width()); EXPECT_EQ(2048, key.target_size().height()); - EXPECT_FALSE(key.can_use_original_decode()); + EXPECT_FALSE(key.can_use_original_size_decode()); EXPECT_EQ(4555u * 2048u * 4u, key.locked_bytes()); } @@ -382,14 +411,15 @@ TEST(SoftwareImageDecodeCacheTest, DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -400,14 +430,15 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToLowIfIdentity) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -419,14 +450,15 @@ TEST(SoftwareImageDecodeCacheTest, DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable)); + CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -438,14 +470,15 @@ TEST(SoftwareImageDecodeCacheTest, DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable)); + CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); } @@ -456,26 +489,28 @@ TEST(SoftwareImageDecodeCacheTest, OriginalDecodesAreEqual) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality()); EXPECT_EQ(100, key.target_size().width()); EXPECT_EQ(100, key.target_size().height()); - EXPECT_TRUE(key.can_use_original_decode()); + EXPECT_TRUE(key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, key.locked_bytes()); DrawImage another_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.5f, 1.5), is_decomposable)); + CreateMatrix(SkSize::Make(1.5f, 1.5), is_decomposable), + DefaultColorSpace()); auto another_key = ImageDecodeCacheKey::FromDrawImage(another_draw_image); EXPECT_EQ(image->uniqueID(), another_key.image_id()); EXPECT_EQ(kLow_SkFilterQuality, another_key.filter_quality()); EXPECT_EQ(100, another_key.target_size().width()); EXPECT_EQ(100, another_key.target_size().height()); - EXPECT_TRUE(another_key.can_use_original_decode()); + EXPECT_TRUE(another_key.can_use_original_size_decode()); EXPECT_EQ(100u * 100u * 4u, another_key.locked_bytes()); EXPECT_TRUE(key == another_key); @@ -488,7 +523,8 @@ TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRect) { DrawImage draw_image( image, SkIRect::MakeXYWH(25, 35, image->width(), image->height()), - quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); @@ -506,7 +542,8 @@ TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRectWithScale) { DrawImage draw_image( image, SkIRect::MakeXYWH(20, 30, image->width(), image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); auto key = ImageDecodeCacheKey::FromDrawImage(draw_image); EXPECT_EQ(image->uniqueID(), key.image_id()); @@ -525,7 +562,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImage) { DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -534,7 +572,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImage) { DrawImage another_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> another_task; need_unref = cache.GetTaskForImageAndRef( another_draw_image, ImageDecodeCache::TracingInfo(), &another_task); @@ -555,7 +594,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentQuality) { DrawImage high_quality_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), kHigh_SkFilterQuality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> high_quality_task; bool need_unref = cache.GetTaskForImageAndRef(high_quality_draw_image, ImageDecodeCache::TracingInfo(), @@ -566,7 +606,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentQuality) { DrawImage low_quality_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), kLow_SkFilterQuality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> low_quality_task; need_unref = cache.GetTaskForImageAndRef(low_quality_draw_image, ImageDecodeCache::TracingInfo(), @@ -590,7 +631,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentSize) { DrawImage half_size_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> half_size_task; bool need_unref = cache.GetTaskForImageAndRef( half_size_draw_image, ImageDecodeCache::TracingInfo(), &half_size_task); @@ -599,7 +641,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentSize) { DrawImage quarter_size_draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable)); + CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> quarter_size_task; need_unref = cache.GetTaskForImageAndRef(quarter_size_draw_image, ImageDecodeCache::TracingInfo(), @@ -623,7 +666,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) { sk_sp<SkImage> first_image = CreateImage(100, 100); DrawImage first_draw_image( first_image, SkIRect::MakeWH(first_image->width(), first_image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> first_task; bool need_unref = cache.GetTaskForImageAndRef( first_draw_image, ImageDecodeCache::TracingInfo(), &first_task); @@ -634,7 +678,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) { DrawImage second_draw_image( second_image, SkIRect::MakeWH(second_image->width(), second_image->height()), quality, - CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable)); + CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> second_task; need_unref = cache.GetTaskForImageAndRef( second_draw_image, ImageDecodeCache::TracingInfo(), &second_task); @@ -649,6 +694,55 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) { cache.UnrefImage(second_draw_image); } +TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) { + TestSoftwareImageDecodeCache cache; + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + gfx::ColorSpace color_space_a(gfx::ColorSpace::PrimaryID::XYZ_D50, + gfx::ColorSpace::TransferID::IEC61966_2_1); + gfx::ColorSpace color_space_b(gfx::ColorSpace::PrimaryID::SMPTE170M, + gfx::ColorSpace::TransferID::IEC61966_2_1); + gfx::ColorSpace color_space_c = gfx::ColorSpace::CreateSRGB(); + + sk_sp<SkImage> image = CreateImageWithColorSpace(100, 100, color_space_a); + DrawImage first_draw_image( + image, SkIRect::MakeWH(image->width(), image->height()), quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), color_space_b); + scoped_refptr<TileTask> first_task; + bool need_unref = cache.GetTaskForImageAndRef( + first_draw_image, ImageDecodeCache::TracingInfo(), &first_task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(first_task); + + DrawImage second_draw_image( + image, SkIRect::MakeWH(image->width(), image->height()), quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), color_space_c); + scoped_refptr<TileTask> second_task; + need_unref = cache.GetTaskForImageAndRef( + second_draw_image, ImageDecodeCache::TracingInfo(), &second_task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(second_task); + EXPECT_TRUE(first_task.get() != second_task.get()); + + DrawImage third_draw_image( + image, SkIRect::MakeWH(image->width(), image->height()), quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), color_space_b); + scoped_refptr<TileTask> third_task; + need_unref = cache.GetTaskForImageAndRef( + third_draw_image, ImageDecodeCache::TracingInfo(), &third_task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(third_task); + EXPECT_TRUE(first_task.get() == third_task.get()); + + TestTileTaskRunner::ProcessTask(first_task.get()); + TestTileTaskRunner::ProcessTask(second_task.get()); + + cache.UnrefImage(first_draw_image); + cache.UnrefImage(second_draw_image); + cache.UnrefImage(third_draw_image); +} + TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyDecoded) { TestSoftwareImageDecodeCache cache; bool is_decomposable = true; @@ -657,7 +751,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyDecoded) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -687,7 +782,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyPrerolled) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -724,7 +820,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageCanceledGetsNewTask) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -767,7 +864,8 @@ TEST(SoftwareImageDecodeCacheTest, sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -809,7 +907,8 @@ TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDraw) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -842,7 +941,8 @@ TEST(SoftwareImageDecodeCacheTest, sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image( image, SkIRect::MakeXYWH(20, 30, image->width(), image->height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo(), &task); @@ -874,7 +974,8 @@ TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); DecodedDrawImage decoded_draw_image = cache.GetDecodedImageForDraw(draw_image); @@ -899,7 +1000,8 @@ TEST(SoftwareImageDecodeCacheTest, sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); DecodedDrawImage decoded_draw_image = cache.GetDecodedImageForDraw(draw_image); @@ -930,7 +1032,8 @@ TEST(SoftwareImageDecodeCacheTest, sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); DecodedDrawImage decoded_draw_image = cache.GetDecodedImageForDraw(draw_image); @@ -975,7 +1078,8 @@ TEST(SoftwareImageDecodeCacheTest, sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); DecodedDrawImage decoded_draw_image = cache.GetDecodedImageForDraw(draw_image); @@ -1020,7 +1124,8 @@ TEST(SoftwareImageDecodeCacheTest, ZeroSizedImagesAreSkipped) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable)); + CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1043,7 +1148,8 @@ TEST(SoftwareImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image( image, SkIRect::MakeXYWH(150, 150, image->width(), image->height()), - quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1066,7 +1172,8 @@ TEST(SoftwareImageDecodeCacheTest, LowQualityFilterIsHandled) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1094,7 +1201,8 @@ TEST(SoftwareImageDecodeCacheTest, LowQualityScaledSubrectIsHandled) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeXYWH(10, 10, 80, 80), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1124,7 +1232,8 @@ TEST(SoftwareImageDecodeCacheTest, NoneQualityScaledSubrectIsHandled) { sk_sp<SkImage> image = CreateImage(100, 100); DrawImage draw_image(image, SkIRect::MakeXYWH(10, 10, 80, 80), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1155,7 +1264,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt01_5ScaleIsHandled) { sk_sp<SkImage> image = CreateImage(500, 200); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable)); + CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1187,7 +1297,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt1_0ScaleIsHandled) { sk_sp<SkImage> image = CreateImage(500, 200); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable)); + CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1219,7 +1330,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_75ScaleIsHandled) { sk_sp<SkImage> image = CreateImage(500, 200); DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable)); + CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1251,7 +1363,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_5ScaleIsHandled) { sk_sp<SkImage> image = CreateImage(500, 200); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1283,7 +1396,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_49ScaleIsHandled) { sk_sp<SkImage> image = CreateImage(500, 200); DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable)); + CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1315,7 +1429,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_1ScaleIsHandled) { sk_sp<SkImage> image = CreateImage(500, 200); DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable)); + CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1347,7 +1462,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_01ScaleIsHandled) { sk_sp<SkImage> image = CreateImage(500, 200); DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable)); + CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1379,7 +1495,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_001ScaleIsHandled) { sk_sp<SkImage> image = CreateImage(500, 200); DrawImage draw_image( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.001f, 0.001f), is_decomposable)); + CreateMatrix(SkSize::Make(0.001f, 0.001f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task; bool need_unref = cache.GetTaskForImageAndRef( @@ -1403,10 +1520,12 @@ TEST(SoftwareImageDecodeCacheTest, sk_sp<SkImage> image = CreateImage(500, 200); DrawImage draw_image_50( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + DefaultColorSpace()); DrawImage draw_image_49( image, SkIRect::MakeWH(image->width(), image->height()), quality, - CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable)); + CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable), + DefaultColorSpace()); scoped_refptr<TileTask> task_50; bool need_unref_50 = cache.GetTaskForImageAndRef( @@ -1446,5 +1565,33 @@ TEST(SoftwareImageDecodeCacheTest, cache.UnrefImage(draw_image_49); } +TEST(SoftwareImageDecodeCacheTest, ClearCache) { + TestSoftwareImageDecodeCache cache; + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + for (int i = 0; i < 10; ++i) { + sk_sp<SkImage> image = CreateImage(100, 100); + DrawImage draw_image( + image, SkIRect::MakeWH(image->width(), image->height()), quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + DefaultColorSpace()); + scoped_refptr<TileTask> task; + bool need_unref = cache.GetTaskForImageAndRef( + draw_image, ImageDecodeCache::TracingInfo(), &task); + EXPECT_TRUE(need_unref); + EXPECT_TRUE(task); + TestTileTaskRunner::ProcessTask(task.get()); + cache.UnrefImage(draw_image); + } + + EXPECT_EQ(10u, cache.GetNumCacheEntriesForTesting()); + + // Tell our cache to clear resources. + cache.ClearCache(); + + EXPECT_EQ(0u, cache.GetNumCacheEntriesForTesting()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/tiles/tile.cc b/chromium/cc/tiles/tile.cc index b43383fd68b..4432d98c52d 100644 --- a/chromium/cc/tiles/tile.cc +++ b/chromium/cc/tiles/tile.cc @@ -26,7 +26,7 @@ Tile::Tile(TileManager* tile_manager, tiling_(info.tiling), content_rect_(info.content_rect), enclosing_layer_rect_(info.enclosing_layer_rect), - contents_scale_(info.contents_scale), + raster_transform_(info.raster_transform), layer_id_(layer_id), source_frame_number_(source_frame_number), flags_(flags), @@ -49,7 +49,13 @@ Tile::~Tile() { void Tile::AsValueInto(base::trace_event::TracedValue* value) const { TracedValue::MakeDictIntoImplicitSnapshotWithCategory( TRACE_DISABLED_BY_DEFAULT("cc.debug"), value, "cc::Tile", this); - value->SetDouble("contents_scale", contents_scale()); + value->SetDouble("contents_scale", contents_scale_key()); + + value->BeginArray("raster_transform"); + value->AppendDouble(raster_transform_.scale()); + value->AppendDouble(raster_transform_.translation().x()); + value->AppendDouble(raster_transform_.translation().y()); + value->EndArray(); MathUtil::AddToTracedValue("content_rect", content_rect_, value); diff --git a/chromium/cc/tiles/tile.h b/chromium/cc/tiles/tile.h index 16d37d1491d..435d5f0552e 100644 --- a/chromium/cc/tiles/tile.h +++ b/chromium/cc/tiles/tile.h @@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "cc/raster/tile_task.h" #include "cc/tiles/tile_draw_info.h" +#include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -29,20 +30,20 @@ class CC_EXPORT Tile { int tiling_j_index; gfx::Rect enclosing_layer_rect; gfx::Rect content_rect; - float contents_scale; + gfx::AxisTransform2d raster_transform; CreateInfo(const PictureLayerTiling* tiling, int tiling_i_index, int tiling_j_index, const gfx::Rect& enclosing_layer_rect, const gfx::Rect& content_rect, - float contents_scale) + const gfx::AxisTransform2d& raster_transform) : tiling(tiling), tiling_i_index(tiling_i_index), tiling_j_index(tiling_j_index), enclosing_layer_rect(enclosing_layer_rect), content_rect(content_rect), - contents_scale(contents_scale) {} + raster_transform(raster_transform) {} }; enum TileRasterFlags { USE_PICTURE_ANALYSIS = 1 << 0, IS_OPAQUE = 1 << 1 }; @@ -76,7 +77,10 @@ class CC_EXPORT Tile { const TileDrawInfo& draw_info() const { return draw_info_; } TileDrawInfo& draw_info() { return draw_info_; } - float contents_scale() const { return contents_scale_; } + float contents_scale_key() const { return raster_transform_.scale(); } + const gfx::AxisTransform2d& raster_transform() const { + return raster_transform_; + } const gfx::Rect& content_rect() const { return content_rect_; } const gfx::Rect& enclosing_layer_rect() const { return enclosing_layer_rect_; @@ -132,7 +136,7 @@ class CC_EXPORT Tile { const PictureLayerTiling* tiling_; const gfx::Rect content_rect_; const gfx::Rect enclosing_layer_rect_; - const float contents_scale_; + const gfx::AxisTransform2d raster_transform_; TileDrawInfo draw_info_; diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc index 9a63601f151..5639661f713 100644 --- a/chromium/cc/tiles/tile_manager.cc +++ b/chromium/cc/tiles/tile_manager.cc @@ -21,14 +21,15 @@ #include "base/optional.h" #include "base/threading/thread_checker.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/devtools_instrumentation.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" #include "cc/layers/picture_layer_impl.h" #include "cc/raster/raster_buffer.h" #include "cc/raster/task_category.h" +#include "cc/tiles/frame_viewer_instrumentation.h" #include "cc/tiles/tile.h" +#include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect_conversions.h" namespace cc { @@ -98,7 +99,7 @@ class RasterTaskImpl : public TileTask { raster_source_(std::move(raster_source)), content_rect_(tile->content_rect()), invalid_content_rect_(invalidated_rect), - raster_scale_(tile->contents_scale()), + raster_transform_(tile->raster_transform()), playback_settings_(playback_settings), tile_resolution_(tile_resolution), layer_id_(tile->layer_id()), @@ -128,7 +129,7 @@ class RasterTaskImpl : public TileTask { raster_buffer_->Playback(raster_source_.get(), content_rect_, invalid_content_rect_, new_content_id_, - raster_scale_, playback_settings_); + raster_transform_, playback_settings_); } // Overridden from TileTask: @@ -162,7 +163,7 @@ class RasterTaskImpl : public TileTask { scoped_refptr<RasterSource> raster_source_; gfx::Rect content_rect_; gfx::Rect invalid_content_rect_; - float raster_scale_; + gfx::AxisTransform2d raster_transform_; RasterSource::PlaybackSettings playback_settings_; TileResolution tile_resolution_; int layer_id_; @@ -664,9 +665,11 @@ TileManager::PrioritizedWorkToSchedule TileManager::AssignGpuMemoryToTiles() { // canvas which is reset between tiles. tile->set_solid_color_analysis_performed(true); SkColor color = SK_ColorTRANSPARENT; + gfx::RectF layer_rect = tile->raster_transform().InverseMapRect( + gfx::RectF(tile->content_rect())); bool is_solid_color = prioritized_tile.raster_source()->PerformSolidColorAnalysis( - tile->content_rect(), tile->contents_scale(), &color); + gfx::ToEnclosingRect(layer_rect), 1.f, &color); if (is_solid_color) { tile->draw_info().set_solid_color(color); client_->NotifyTileStateChanged(tile); @@ -802,7 +805,7 @@ void TileManager::ScheduleTasks( graph_.Reset(); - gfx::ColorSpace target_color_space = client_->GetTileColorSpace(); + gfx::ColorSpace raster_color_space = client_->GetRasterColorSpace(); scoped_refptr<TileTask> required_for_activation_done_task = CreateTaskSetFinishedTask( @@ -823,7 +826,7 @@ void TileManager::ScheduleTasks( if (!tile->raster_task_) { tile->raster_task_ = - CreateRasterTask(prioritized_tile, target_color_space); + CreateRasterTask(prioritized_tile, raster_color_space); } TileTask* task = tile->raster_task_.get(); @@ -863,7 +866,8 @@ void TileManager::ScheduleTasks( // the CheckerImageTracker as well. See crbug.com/691087. std::vector<DrawImage> images; prioritized_tile.raster_source()->GetDiscardableImagesInRect( - tile->enclosing_layer_rect(), tile->contents_scale(), &images); + tile->enclosing_layer_rect(), tile->raster_transform().scale(), + raster_color_space, &images); new_locked_images.insert(new_locked_images.end(), images.begin(), images.end()); } @@ -967,7 +971,8 @@ scoped_refptr<TileTask> TileManager::CreateRasterTask( images.clear(); if (!playback_settings.skip_images) { prioritized_tile.raster_source()->GetDiscardableImagesInRect( - tile->enclosing_layer_rect(), tile->contents_scale(), &images); + tile->enclosing_layer_rect(), tile->raster_transform().scale(), + color_space, &images); checker_image_tracker_.FilterImagesForCheckeringForTile( &images, &images_to_skip, prioritized_tile.tile()->tiling()->tree()); } @@ -1356,6 +1361,67 @@ scoped_refptr<TileTask> TileManager::CreateTaskSetFinishedTask( base::Bind(callback, task_set_finished_weak_ptr_factory_.GetWeakPtr()))); } +std::unique_ptr<base::trace_event::ConvertableToTraceFormat> +TileManager::ActivationStateAsValue() { + auto state = base::MakeUnique<base::trace_event::TracedValue>(); + state->SetString("tree_priority", + TreePriorityToString(global_state_.tree_priority)); + state->SetInteger("soft_memory_limit", + global_state_.soft_memory_limit_in_bytes); + state->SetInteger("hard_memory_limit", + global_state_.soft_memory_limit_in_bytes); + state->SetInteger("pending_required_for_activation_callback_id", + pending_required_for_activation_callback_id_); + state->SetInteger("current_memory_usage", + resource_pool_->memory_usage_bytes()); + state->SetInteger("current_resource_usage", resource_pool_->resource_count()); + + // Use a custom tile_as_value, instead of Tile::AsValueInto, since we don't + // need all of the state that would be captured by other functions. + auto tile_as_value = [](const PrioritizedTile& prioritized_tile, + base::trace_event::TracedValue* value) { + Tile* tile = prioritized_tile.tile(); + TilePriority priority = prioritized_tile.priority(); + + value->SetInteger("id", tile->id()); + value->SetString("content_rect", tile->content_rect().ToString()); + value->SetDouble("contents_scale", tile->contents_scale_key()); + value->SetBoolean("is_ready_to_draw", tile->draw_info().IsReadyToDraw()); + value->SetString("resolution", TileResolutionToString(priority.resolution)); + value->SetString("priority_bin", + TilePriorityBinToString(priority.priority_bin)); + value->SetDouble("distance_to_visible", priority.distance_to_visible); + value->SetBoolean("required_for_activation", + tile->required_for_activation()); + value->SetBoolean("required_for_draw", tile->required_for_draw()); + }; + + std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue( + client_->BuildRasterQueue(global_state_.tree_priority, + RasterTilePriorityQueue::Type::ALL)); + state->BeginArray("raster_tiles"); + for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) { + state->BeginDictionary(); + tile_as_value(raster_priority_queue->Top(), state.get()); + state->EndDictionary(); + } + state->EndArray(); + + std::unique_ptr<RasterTilePriorityQueue> required_priority_queue( + client_->BuildRasterQueue( + global_state_.tree_priority, + RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION)); + state->BeginArray("activation_tiles"); + for (; !required_priority_queue->IsEmpty(); required_priority_queue->Pop()) { + state->BeginDictionary(); + tile_as_value(required_priority_queue->Top(), state.get()); + state->EndDictionary(); + } + state->EndArray(); + + return std::move(state); +} + TileManager::MemoryUsage::MemoryUsage() : memory_bytes_(0), resource_count_(0) {} diff --git a/chromium/cc/tiles/tile_manager.h b/chromium/cc/tiles/tile_manager.h index e8b561c1284..3327cf1bf99 100644 --- a/chromium/cc/tiles/tile_manager.h +++ b/chromium/cc/tiles/tile_manager.h @@ -17,8 +17,8 @@ #include "base/macros.h" #include "base/values.h" #include "cc/base/unique_notifier.h" -#include "cc/playback/raster_source.h" #include "cc/raster/raster_buffer_provider.h" +#include "cc/raster/raster_source.h" #include "cc/resources/memory_history.h" #include "cc/resources/resource_pool.h" #include "cc/tiles/checker_image_tracker.h" @@ -79,7 +79,7 @@ class CC_EXPORT TileManagerClient { virtual void SetIsLikelyToRequireADraw(bool is_likely_to_require_a_draw) = 0; // Requests the color space into which tiles should be rasterized. - virtual gfx::ColorSpace GetTileColorSpace() const = 0; + virtual gfx::ColorSpace GetRasterColorSpace() const = 0; // Requests that a pending tree be scheduled to invalidate content on the // pending on active tree. This is currently used when tiles that are @@ -167,7 +167,7 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { draw_info.set_resource(resource_pool_->AcquireResource( tiles[i]->desired_texture_size(), raster_buffer_provider_->GetResourceFormat(false), - client_->GetTileColorSpace())); + client_->GetRasterColorSpace())); draw_info.set_resource_ready_for_draw(); } } @@ -229,6 +229,11 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { // CheckerImageTrackerClient implementation. void NeedsInvalidationForCheckerImagedTiles() override; + // This method can only be used for debugging information, since it performs a + // non trivial amount of work. + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> + ActivationStateAsValue(); + protected: friend class Tile; // Must be called by tile during destruction. diff --git a/chromium/cc/tiles/tile_manager_perftest.cc b/chromium/cc/tiles/tile_manager_perftest.cc index 93b4dee0d0e..c87e217a5d8 100644 --- a/chromium/cc/tiles/tile_manager_perftest.cc +++ b/chromium/cc/tiles/tile_manager_perftest.cc @@ -10,7 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/raster/raster_buffer.h" #include "cc/test/begin_frame_args_test.h" #include "cc/test/fake_compositor_frame_sink.h" diff --git a/chromium/cc/tiles/tile_manager_settings.h b/chromium/cc/tiles/tile_manager_settings.h index db086d1b2b5..65da9e426e1 100644 --- a/chromium/cc/tiles/tile_manager_settings.h +++ b/chromium/cc/tiles/tile_manager_settings.h @@ -5,7 +5,7 @@ #ifndef CC_TILES_TILE_MANAGER_SETTINGS_H_ #define CC_TILES_TILE_MANAGER_SETTINGS_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc index 59f1fd34d64..b410cc006af 100644 --- a/chromium/cc/tiles/tile_manager_unittest.cc +++ b/chromium/cc/tiles/tile_manager_unittest.cc @@ -5,15 +5,17 @@ #include <stddef.h> #include <stdint.h> +#include <utility> + #include "base/bind.h" #include "base/callback.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "cc/playback/raster_source.h" -#include "cc/playback/recording_source.h" +#include "cc/layers/recording_source.h" #include "cc/raster/raster_buffer.h" +#include "cc/raster/raster_source.h" #include "cc/raster/synchronous_task_graph_runner.h" #include "cc/resources/resource_pool.h" #include "cc/test/begin_frame_args_test.h" @@ -27,7 +29,6 @@ #include "cc/test/fake_recording_source.h" #include "cc/test/fake_tile_manager.h" #include "cc/test/fake_tile_task_manager.h" -#include "cc/test/layer_tree_settings_for_testing.h" #include "cc/test/test_layer_tree_host_base.h" #include "cc/test/test_task_graph_runner.h" #include "cc/test/test_tile_priorities.h" @@ -56,18 +57,18 @@ namespace { class SynchronousSimpleTaskRunner : public base::TestSimpleTaskRunner { public: bool PostDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, + base::OnceClosure task, base::TimeDelta delay) override { - TestSimpleTaskRunner::PostDelayedTask(from_here, task, delay); + TestSimpleTaskRunner::PostDelayedTask(from_here, std::move(task), delay); if (run_tasks_synchronously_) RunUntilIdle(); return true; } bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, + base::OnceClosure task, base::TimeDelta delay) override { - return PostDelayedTask(from_here, task, delay); + return PostDelayedTask(from_here, std::move(task), delay); } void set_run_tasks_synchronously(bool run_tasks_synchronously) { @@ -83,7 +84,7 @@ class SynchronousSimpleTaskRunner : public base::TestSimpleTaskRunner { class TileManagerTilePriorityQueueTest : public TestLayerTreeHostBase { public: LayerTreeSettings CreateSettings() override { - LayerTreeSettingsForTesting settings; + LayerTreeSettings settings; settings.create_low_res_tiling = true; settings.renderer_settings.buffer_to_texture_target_map = DefaultBufferToTextureTargetMapForTesting(); @@ -355,10 +356,18 @@ TEST_F(TileManagerTilePriorityQueueTest, host_impl()->SetViewportSize(viewport); SetupDefaultTrees(layer_bounds); - pending_layer()->tilings()->AddTiling(1.5f, pending_layer()->raster_source()); - active_layer()->tilings()->AddTiling(1.5f, active_layer()->raster_source()); - pending_layer()->tilings()->AddTiling(1.7f, pending_layer()->raster_source()); - active_layer()->tilings()->AddTiling(1.7f, active_layer()->raster_source()); + pending_layer()->tilings()->AddTiling( + gfx::AxisTransform2d(1.5f, gfx::Vector2dF()), + pending_layer()->raster_source()); + active_layer()->tilings()->AddTiling( + gfx::AxisTransform2d(1.5f, gfx::Vector2dF()), + active_layer()->raster_source()); + pending_layer()->tilings()->AddTiling( + gfx::AxisTransform2d(1.7f, gfx::Vector2dF()), + pending_layer()->raster_source()); + active_layer()->tilings()->AddTiling( + gfx::AxisTransform2d(1.7f, gfx::Vector2dF()), + active_layer()->raster_source()); pending_layer()->tilings()->UpdateTilePriorities(gfx::Rect(viewport), 1.f, 5.0, Occlusion(), true); @@ -368,7 +377,7 @@ TEST_F(TileManagerTilePriorityQueueTest, std::set<Tile*> all_expected_tiles; for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) { PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i); - if (tiling->contents_scale() == 1.f) { + if (tiling->contents_scale_key() == 1.f) { tiling->set_resolution(HIGH_RESOLUTION); const auto& all_tiles = tiling->AllTilesForTesting(); all_expected_tiles.insert(all_tiles.begin(), all_tiles.end()); @@ -379,7 +388,7 @@ TEST_F(TileManagerTilePriorityQueueTest, for (size_t i = 0; i < active_layer()->num_tilings(); ++i) { PictureLayerTiling* tiling = active_layer()->tilings()->tiling_at(i); - if (tiling->contents_scale() == 1.5f) { + if (tiling->contents_scale_key() == 1.5f) { tiling->set_resolution(HIGH_RESOLUTION); const auto& all_tiles = tiling->AllTilesForTesting(); all_expected_tiles.insert(all_tiles.begin(), all_tiles.end()); @@ -387,7 +396,7 @@ TEST_F(TileManagerTilePriorityQueueTest, tiling->set_resolution(NON_IDEAL_RESOLUTION); // Non ideal tilings with a high res pending twin have to be processed // because of possible activation tiles. - if (tiling->contents_scale() == 1.f) { + if (tiling->contents_scale_key() == 1.f) { tiling->UpdateAndGetAllPrioritizedTilesForTesting(); const auto& all_tiles = tiling->AllTilesForTesting(); for (auto* tile : all_tiles) @@ -422,10 +431,18 @@ TEST_F(TileManagerTilePriorityQueueTest, host_impl()->SetViewportSize(viewport); SetupDefaultTrees(layer_bounds); - pending_layer()->tilings()->AddTiling(1.5f, pending_layer()->raster_source()); - active_layer()->tilings()->AddTiling(1.5f, active_layer()->raster_source()); - pending_layer()->tilings()->AddTiling(1.7f, pending_layer()->raster_source()); - active_layer()->tilings()->AddTiling(1.7f, active_layer()->raster_source()); + pending_layer()->tilings()->AddTiling( + gfx::AxisTransform2d(1.5f, gfx::Vector2dF()), + pending_layer()->raster_source()); + active_layer()->tilings()->AddTiling( + gfx::AxisTransform2d(1.5f, gfx::Vector2dF()), + active_layer()->raster_source()); + pending_layer()->tilings()->AddTiling( + gfx::AxisTransform2d(1.7f, gfx::Vector2dF()), + pending_layer()->raster_source()); + active_layer()->tilings()->AddTiling( + gfx::AxisTransform2d(1.7f, gfx::Vector2dF()), + active_layer()->raster_source()); pending_layer()->tilings()->UpdateTilePriorities(gfx::Rect(viewport), 1.f, 5.0, Occlusion(), true); @@ -435,7 +452,7 @@ TEST_F(TileManagerTilePriorityQueueTest, std::set<Tile*> all_expected_tiles; for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) { PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i); - if (tiling->contents_scale() == 1.f) { + if (tiling->contents_scale_key() == 1.f) { tiling->set_resolution(HIGH_RESOLUTION); const auto& all_tiles = tiling->AllTilesForTesting(); all_expected_tiles.insert(all_tiles.begin(), all_tiles.end()); @@ -446,7 +463,7 @@ TEST_F(TileManagerTilePriorityQueueTest, for (size_t i = 0; i < active_layer()->num_tilings(); ++i) { PictureLayerTiling* tiling = active_layer()->tilings()->tiling_at(i); - if (tiling->contents_scale() == 1.5f) { + if (tiling->contents_scale_key() == 1.5f) { tiling->set_resolution(HIGH_RESOLUTION); const auto& all_tiles = tiling->AllTilesForTesting(); all_expected_tiles.insert(all_tiles.begin(), all_tiles.end()); @@ -454,7 +471,7 @@ TEST_F(TileManagerTilePriorityQueueTest, tiling->set_resolution(LOW_RESOLUTION); // Low res tilings with a high res pending twin have to be processed // because of possible activation tiles. - if (tiling->contents_scale() == 1.f) { + if (tiling->contents_scale_key() == 1.f) { tiling->UpdateAndGetAllPrioritizedTilesForTesting(); const auto& all_tiles = tiling->AllTilesForTesting(); for (auto* tile : all_tiles) @@ -912,8 +929,8 @@ TEST_F(TileManagerTilePriorityQueueTest, EXPECT_TRUE((tile_priority_bin < last_tile_priority_bin) || prioritized_tile.tile()->required_for_activation() || - (prioritized_tile.tile()->contents_scale() != - last_tile.tile()->contents_scale())); + (prioritized_tile.tile()->raster_transform() != + last_tile.tile()->raster_transform())); } } last_tile = prioritized_tile; @@ -950,9 +967,8 @@ TEST_F(TileManagerTilePriorityQueueTest, host_impl()->pending_tree()->BuildLayerListAndPropertyTreesForTesting(); host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text); - host_impl()->pending_tree()->property_trees()->effect_tree.OnOpacityAnimated( - 0.0f, pending_child_layer->effect_tree_index(), - host_impl()->pending_tree()); + host_impl()->pending_tree()->SetOpacityMutated( + pending_child_layer->element_id(), 0.0f); host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text); @@ -1125,7 +1141,6 @@ TEST_F(TileManagerTilePriorityQueueTest, client.SetTileSize(gfx::Size(30, 30)); LayerTreeSettings settings; - settings.verify_clip_tree_calculations = true; std::unique_ptr<PictureLayerTilingSet> tiling_set = PictureLayerTilingSet::Create( @@ -1136,7 +1151,8 @@ TEST_F(TileManagerTilePriorityQueueTest, scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds); - PictureLayerTiling* tiling = tiling_set->AddTiling(1.0f, raster_source); + PictureLayerTiling* tiling = + tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); tiling->set_resolution(HIGH_RESOLUTION); tiling_set->UpdateTilePriorities(viewport, 1.0f, 1.0, Occlusion(), true); @@ -1237,7 +1253,6 @@ TEST_F(TileManagerTilePriorityQueueTest, client.SetTileSize(gfx::Size(30, 30)); LayerTreeSettings settings; - settings.verify_clip_tree_calculations = true; std::unique_ptr<PictureLayerTilingSet> tiling_set = PictureLayerTilingSet::Create( @@ -1248,7 +1263,8 @@ TEST_F(TileManagerTilePriorityQueueTest, scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds); - PictureLayerTiling* tiling = tiling_set->AddTiling(1.0f, raster_source); + PictureLayerTiling* tiling = + tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); tiling->set_resolution(HIGH_RESOLUTION); tiling_set->UpdateTilePriorities(viewport, 1.0f, 1.0, Occlusion(), true); @@ -1404,7 +1420,7 @@ TEST_F(TileManagerTilePriorityQueueTest, RasterQueueAllUsesCorrectTileBounds) { 1.0f, 1.0f, 1000, 1000.f); pending_client.set_twin_tiling_set(tiling_set.get()); - auto* tiling = tiling_set->AddTiling(1.0f, raster_source); + auto* tiling = tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); tiling->set_resolution(HIGH_RESOLUTION); tiling->CreateAllTilesForTesting(); @@ -1480,7 +1496,8 @@ TEST_F(TileManagerTilePriorityQueueTest, NoRasterTasksforSolidColorTiles) { layer_impl->set_is_drawn_render_surface_layer_list_member(true); PictureLayerTilingSet* tiling_set = layer_impl->picture_layer_tiling_set(); - PictureLayerTiling* tiling = tiling_set->AddTiling(1.0f, raster_source); + PictureLayerTiling* tiling = + tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); tiling->set_resolution(HIGH_RESOLUTION); tiling->CreateAllTilesForTesting(); tiling->SetTilePriorityRectsForTesting( @@ -1683,7 +1700,7 @@ TEST_F(TileManagerTest, LowResHasNoImage) { PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set(); layer->set_is_drawn_render_surface_layer_list_member(true); - auto* tiling = tiling_set->AddTiling(1.0f, raster); + auto* tiling = tiling_set->AddTiling(gfx::AxisTransform2d(), raster); tiling->set_resolution(resolutions[i]); tiling->CreateAllTilesForTesting(); tiling->SetTilePriorityRectsForTesting( @@ -1990,7 +2007,7 @@ class MockReadyToDrawRasterBufferProviderImpl const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, uint64_t new_content_id, - float scale, + const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings) override {} }; }; @@ -2036,7 +2053,7 @@ class TileManagerReadyToDrawTest : public TileManagerTest { } LayerTreeSettings CreateSettings() override { - LayerTreeSettingsForTesting settings; + LayerTreeSettings settings; settings.renderer_settings.buffer_to_texture_target_map = DefaultBufferToTextureTargetMapForTesting(); return settings; @@ -2365,7 +2382,8 @@ TEST_F(CheckerImagingTileManagerTest, layer_impl->set_is_drawn_render_surface_layer_list_member(true); PictureLayerTilingSet* tiling_set = layer_impl->picture_layer_tiling_set(); - PictureLayerTiling* tiling = tiling_set->AddTiling(1.0f, raster_source); + PictureLayerTiling* tiling = + tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); tiling->set_resolution(HIGH_RESOLUTION); tiling->CreateAllTilesForTesting(); tiling->SetTilePriorityRectsForTesting( diff --git a/chromium/cc/tiles/tile_priority.h b/chromium/cc/tiles/tile_priority.h index cf0bbd13817..15746de6506 100644 --- a/chromium/cc/tiles/tile_priority.h +++ b/chromium/cc/tiles/tile_priority.h @@ -13,7 +13,7 @@ #include <string> #include "base/trace_event/trace_event_argument.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { class Value; diff --git a/chromium/cc/tiles/tiling_set_eviction_queue.h b/chromium/cc/tiles/tiling_set_eviction_queue.h index 493d74a8c82..e6055e5cd33 100644 --- a/chromium/cc/tiles/tiling_set_eviction_queue.h +++ b/chromium/cc/tiles/tiling_set_eviction_queue.h @@ -9,7 +9,7 @@ #include <vector> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/tiles/picture_layer_tiling_set.h" #include "cc/tiles/prioritized_tile.h" diff --git a/chromium/cc/tiles/tiling_set_raster_queue_all.h b/chromium/cc/tiles/tiling_set_raster_queue_all.h index c49a37e7928..318156380a1 100644 --- a/chromium/cc/tiles/tiling_set_raster_queue_all.h +++ b/chromium/cc/tiles/tiling_set_raster_queue_all.h @@ -9,7 +9,7 @@ #include "base/containers/stack_container.h" #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/tiles/picture_layer_tiling_set.h" #include "cc/tiles/prioritized_tile.h" #include "cc/tiles/tile.h" diff --git a/chromium/cc/tiles/tiling_set_raster_queue_required.h b/chromium/cc/tiles/tiling_set_raster_queue_required.h index 4573d040939..3bc8a96037f 100644 --- a/chromium/cc/tiles/tiling_set_raster_queue_required.h +++ b/chromium/cc/tiles/tiling_set_raster_queue_required.h @@ -5,7 +5,7 @@ #ifndef CC_TILES_TILING_SET_RASTER_QUEUE_REQUIRED_H_ #define CC_TILES_TILING_SET_RASTER_QUEUE_REQUIRED_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/tiles/picture_layer_tiling_set.h" #include "cc/tiles/raster_tile_priority_queue.h" #include "cc/tiles/tile.h" diff --git a/chromium/cc/trees/blocking_task_runner.h b/chromium/cc/trees/blocking_task_runner.h index 515cb258945..d34e2f20cd4 100644 --- a/chromium/cc/trees/blocking_task_runner.h +++ b/chromium/cc/trees/blocking_task_runner.h @@ -13,7 +13,7 @@ #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/trees/clip_expander.h b/chromium/cc/trees/clip_expander.h index 781d489ba04..209477a2553 100644 --- a/chromium/cc/trees/clip_expander.h +++ b/chromium/cc/trees/clip_expander.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_CLIP_EXPANDER_H_ #define CC_TREES_CLIP_EXPANDER_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/rect.h" namespace cc { diff --git a/chromium/cc/trees/clip_node.cc b/chromium/cc/trees/clip_node.cc index d3c1863d448..c8d2eff7f65 100644 --- a/chromium/cc/trees/clip_node.cc +++ b/chromium/cc/trees/clip_node.cc @@ -15,14 +15,10 @@ ClipNode::ClipNode() : id(ClipTree::kInvalidNodeId), parent_id(ClipTree::kInvalidNodeId), owning_layer_id(Layer::INVALID_ID), - clip_type(ClipType::NONE), - transform_id(TransformTree::kInvalidNodeId), - target_transform_id(TransformTree::kInvalidNodeId), - target_effect_id(EffectTree::kInvalidNodeId), - layer_clipping_uses_only_local_clip(false), - layers_are_clipped(false), - layers_are_clipped_when_surfaces_disabled(false), - resets_clip(false) {} + clip_type(ClipType::APPLIES_LOCAL_CLIP), + transform_id(TransformTree::kInvalidNodeId) { + cached_clip_rects = std::vector<ClipRectData>(defaultCachedClipsSize); +} ClipNode::ClipNode(const ClipNode& other) : id(other.id), @@ -30,21 +26,14 @@ ClipNode::ClipNode(const ClipNode& other) owning_layer_id(other.owning_layer_id), clip_type(other.clip_type), clip(other.clip), - combined_clip_in_target_space(other.combined_clip_in_target_space), - clip_in_target_space(other.clip_in_target_space), - transform_id(other.transform_id), - target_transform_id(other.target_transform_id), - target_effect_id(other.target_effect_id), - layer_clipping_uses_only_local_clip( - other.layer_clipping_uses_only_local_clip), - layers_are_clipped(other.layers_are_clipped), - layers_are_clipped_when_surfaces_disabled( - other.layers_are_clipped_when_surfaces_disabled), - resets_clip(other.resets_clip) { + transform_id(other.transform_id) { if (other.clip_expander) { DCHECK_EQ(clip_type, ClipType::EXPANDS_CLIP); clip_expander = base::MakeUnique<ClipExpander>(*other.clip_expander); } + cached_clip_rects = other.cached_clip_rects; + cached_accumulated_rect_in_screen_space = + other.cached_accumulated_rect_in_screen_space; } ClipNode& ClipNode::operator=(const ClipNode& other) { @@ -53,17 +42,7 @@ ClipNode& ClipNode::operator=(const ClipNode& other) { owning_layer_id = other.owning_layer_id; clip_type = other.clip_type; clip = other.clip; - combined_clip_in_target_space = other.combined_clip_in_target_space; - clip_in_target_space = other.clip_in_target_space; transform_id = other.transform_id; - target_transform_id = other.target_transform_id; - target_effect_id = other.target_effect_id; - layer_clipping_uses_only_local_clip = - other.layer_clipping_uses_only_local_clip; - layers_are_clipped = other.layers_are_clipped; - layers_are_clipped_when_surfaces_disabled = - other.layers_are_clipped_when_surfaces_disabled; - resets_clip = other.resets_clip; if (other.clip_expander) { DCHECK_EQ(clip_type, ClipType::EXPANDS_CLIP); @@ -71,7 +50,9 @@ ClipNode& ClipNode::operator=(const ClipNode& other) { } else { clip_expander.reset(); } - + cached_clip_rects = other.cached_clip_rects; + cached_accumulated_rect_in_screen_space = + other.cached_accumulated_rect_in_screen_space; return *this; } @@ -87,17 +68,7 @@ bool ClipNode::operator==(const ClipNode& other) const { return id == other.id && parent_id == other.parent_id && owning_layer_id == other.owning_layer_id && clip_type == other.clip_type && clip == other.clip && - combined_clip_in_target_space == other.combined_clip_in_target_space && - clip_in_target_space == other.clip_in_target_space && - transform_id == other.transform_id && - target_transform_id == other.target_transform_id && - target_effect_id == other.target_effect_id && - layer_clipping_uses_only_local_clip == - other.layer_clipping_uses_only_local_clip && - layers_are_clipped == other.layers_are_clipped && - layers_are_clipped_when_surfaces_disabled == - other.layers_are_clipped_when_surfaces_disabled && - resets_clip == other.resets_clip; + transform_id == other.transform_id; } void ClipNode::AsValueInto(base::trace_event::TracedValue* value) const { @@ -107,14 +78,6 @@ void ClipNode::AsValueInto(base::trace_event::TracedValue* value) const { value->SetInteger("clip_type", static_cast<int>(clip_type)); MathUtil::AddToTracedValue("clip", clip, value); value->SetInteger("transform_id", transform_id); - value->SetInteger("target_transform_id", target_transform_id); - value->SetInteger("target_effect_id", target_effect_id); - value->SetBoolean("layer_clipping_uses_only_local_clip", - layer_clipping_uses_only_local_clip); - value->SetBoolean("layers_are_clipped", layers_are_clipped); - value->SetBoolean("layers_are_clipped_when_surfaces_disabled", - layers_are_clipped_when_surfaces_disabled); - value->SetBoolean("resets_clip", resets_clip); } } // namespace cc diff --git a/chromium/cc/trees/clip_node.h b/chromium/cc/trees/clip_node.h index b81c72c235e..5c204549d1c 100644 --- a/chromium/cc/trees/clip_node.h +++ b/chromium/cc/trees/clip_node.h @@ -7,7 +7,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/trees/clip_expander.h" #include "ui/gfx/geometry/rect_f.h" @@ -27,6 +27,8 @@ struct CC_EXPORT ClipNode { ~ClipNode(); + static const int defaultCachedClipsSize = 1; + // The node index of this node in the clip tree node vector. int id; // The node index of the parent node in the clip tree node vector. @@ -35,10 +37,6 @@ struct CC_EXPORT ClipNode { int owning_layer_id; enum class ClipType { - // The node doesn't contribute a new clip. It exists only for caching clips - // or for resetting clipping state. - NONE, - // The node contributes a new clip (that is, |clip| needs to be applied). APPLIES_LOCAL_CLIP, @@ -57,46 +55,20 @@ struct CC_EXPORT ClipNode { // transform node. gfx::RectF clip; + // Each element of this cache stores the accumulated clip from this clip + // node to a particular target. + mutable std::vector<ClipRectData> cached_clip_rects; + + // This rect accumulates all clips from this node to the root in screen space. + // It is used in the computation of layer's visible rect. + gfx::RectF cached_accumulated_rect_in_screen_space; + // For nodes that expand, this represents the amount of expansion. std::unique_ptr<ClipExpander> clip_expander; - // Clip nodes are used for two reasons. First, they are used for determining - // which parts of each layer are visible. Second, they are used for - // determining whether a clip needs to be applied when drawing a layer, and if - // so, the rect that needs to be used. These can be different since not all - // clips need to be applied directly to each layer. For example, a layer is - // implicitly clipped by the bounds of its target render surface and by clips - // applied to this surface. |combined_clip_in_target_space| is used for - // computing visible rects, and |clip_in_target_space| is used for computing - // clips applied at draw time. Both rects are expressed in the space of the - // target transform node, and may include clips contributed by ancestors. - gfx::RectF combined_clip_in_target_space; - gfx::RectF clip_in_target_space; - // The id of the transform node that defines the clip node's local space. int transform_id; - // The id of the transform node that defines the clip node's target space. - int target_transform_id; - - // The id of the effect node that defines the clip node's target space. - // TODO(crbug.com/642581 crbug.com/642584): As we progress toward SPv2 and - // layer list mode, there may be layers having the same clip but draw onto - // different target. Target information shall be removed from here. - int target_effect_id; - - // When true, |clip_in_target_space| does not include clips from ancestor - // nodes. - bool layer_clipping_uses_only_local_clip : 1; - - // True if layers with this clip tree node need to be drawn with a clip - // applied. - bool layers_are_clipped : 1; - bool layers_are_clipped_when_surfaces_disabled : 1; - - // Nodes that correspond to unclipped surfaces disregard ancestor clips. - bool resets_clip : 1; - bool operator==(const ClipNode& other) const; void AsValueInto(base::trace_event::TracedValue* value) const; diff --git a/chromium/cc/trees/damage_tracker.cc b/chromium/cc/trees/damage_tracker.cc index ae311dd2cfd..aa4a6236801 100644 --- a/chromium/cc/trees/damage_tracker.cc +++ b/chromium/cc/trees/damage_tracker.cc @@ -9,11 +9,11 @@ #include <algorithm> #include "base/memory/ptr_util.h" +#include "cc/base/filter_operations.h" #include "cc/base/math_util.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer_impl.h" #include "cc/layers/render_surface_impl.h" -#include "cc/output/filter_operations.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -128,8 +128,8 @@ void DamageTracker::UpdateDamageTrackingState( gfx::Rect damage_rect; bool is_rect_valid = damage_for_this_update.GetAsRect(&damage_rect); if (is_rect_valid) { - damage_rect = filters.MapRect( - damage_rect, target_surface->FiltersTransform().matrix()); + damage_rect = + filters.MapRect(damage_rect, target_surface->SurfaceScale().matrix()); damage_for_this_update = DamageAccumulator(); damage_for_this_update.Union(damage_rect); } diff --git a/chromium/cc/trees/damage_tracker.h b/chromium/cc/trees/damage_tracker.h index e41a1cf8573..6ddc504dafa 100644 --- a/chromium/cc/trees/damage_tracker.h +++ b/chromium/cc/trees/damage_tracker.h @@ -9,7 +9,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_collections.h" #include "ui/gfx/geometry/rect.h" diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc index 13f8742476f..91cec6dc030 100644 --- a/chromium/cc/trees/damage_tracker_unittest.cc +++ b/chromium/cc/trees/damage_tracker_unittest.cc @@ -6,10 +6,10 @@ #include <stddef.h> +#include "cc/base/filter_operation.h" +#include "cc/base/filter_operations.h" #include "cc/base/math_util.h" #include "cc/layers/layer_impl.h" -#include "cc/output/filter_operation.h" -#include "cc/output/filter_operations.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/geometry_test_utils.h" @@ -27,18 +27,14 @@ namespace { void ExecuteCalculateDrawProperties(LayerImpl* root, float device_scale_factor, - bool skip_verify_visible_rect_calculations, LayerImplList* render_surface_layer_list) { // Sanity check: The test itself should create the root layer's render // surface, so that the surface (and its damage tracker) can // persist across multiple calls to this function. ASSERT_FALSE(render_surface_layer_list->size()); - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root); LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), device_scale_factor, render_surface_layer_list); - if (skip_verify_visible_rect_calculations) - inputs.verify_visible_rect_calculations = false; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); ASSERT_TRUE(root->GetRenderSurface()); } @@ -50,10 +46,7 @@ void ClearDamageForAllSurfaces(LayerImpl* root) { } } -void EmulateDrawingOneFrame( - LayerImpl* root, - float device_scale_factor = 1.f, - bool skip_verify_visible_rect_calculations = false) { +void EmulateDrawingOneFrame(LayerImpl* root, float device_scale_factor = 1.f) { // 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 @@ -62,7 +55,6 @@ void EmulateDrawingOneFrame( LayerImplList render_surface_layer_list; ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); // Iterate back-to-front, so that damage correctly propagates from descendant @@ -106,6 +98,7 @@ class DamageTrackerTest : public testing::Test { root->test_properties()->AddChild(std::move(child)); } host_impl_.active_tree()->SetRootLayerForTesting(std::move(root)); + host_impl_.active_tree()->SetElementIdsForTesting(); return host_impl_.active_tree()->root_layer_for_testing(); } @@ -157,6 +150,7 @@ class DamageTrackerTest : public testing::Test { root->test_properties()->AddChild(std::move(child1)); root->test_properties()->AddChild(std::move(child2)); host_impl_.active_tree()->SetRootLayerForTesting(std::move(root)); + host_impl_.active_tree()->SetElementIdsForTesting(); return host_impl_.active_tree()->root_layer_for_testing(); } @@ -393,8 +387,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) { EmulateDrawingOneFrame(root); ClearDamageForAllSurfaces(root); child->SetUpdateRect(gfx::Rect(10, 11, 12, 13)); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.5f, child->effect_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(child->element_id(), 0.5f); EmulateDrawingOneFrame(root); ASSERT_EQ(2u, root->GetRenderSurface()->layer_list().size()); @@ -423,8 +416,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) { ClearDamageForAllSurfaces(root); gfx::Transform translation; translation.Translate(100.f, 130.f); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - translation, child->transform_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(child->element_id(), + translation); EmulateDrawingOneFrame(root); // Expect damage to be the combination of the previous one and the new one. @@ -482,8 +475,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForTransformedLayer) { // With the anchor on the layer's center, now we can test the rotation more // intuitively, since it applies about the layer's anchor. ClearDamageForAllSurfaces(root); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - rotation, child->transform_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(child->element_id(), rotation); EmulateDrawingOneFrame(root); // Since the child layer is square, rotation by 45 degrees about the center @@ -530,9 +522,9 @@ TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) { // Sanity check that the child layer's bounds would actually get clipped by // w < 0, otherwise this test is not actually testing the intended scenario. - gfx::QuadF test_quad(gfx::RectF(gfx::PointF(), gfx::SizeF(100.f, 100.f))); + gfx::RectF test_rect(child->position(), gfx::SizeF(child->bounds())); bool clipped = false; - MathUtil::MapQuad(transform, test_quad, &clipped); + MathUtil::MapQuad(transform, gfx::QuadF(test_rect), &clipped); EXPECT_TRUE(clipped); // Damage the child without moving it. @@ -540,8 +532,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root); ClearDamageForAllSurfaces(root); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.5f, child->effect_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(child->element_id(), 0.5f); EmulateDrawingOneFrame(root); // The expected damage should cover the entire root surface (500x500), but we @@ -601,8 +592,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) { child->test_properties()->force_render_surface = true; root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root); - child->layer_tree_impl()->property_trees()->effect_tree.OnFilterAnimated( - filters, child->effect_tree_index(), child->layer_tree_impl()); + child->layer_tree_impl()->SetFilterMutated(child->element_id(), filters); EmulateDrawingOneFrame(root); EXPECT_TRUE(root->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( &root_damage_rect)); @@ -652,8 +642,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForTransformedImageFilter) { child->test_properties()->transform = transform; root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root); - child->layer_tree_impl()->property_trees()->effect_tree.OnFilterAnimated( - filters, child->effect_tree_index(), child->layer_tree_impl()); + child->layer_tree_impl()->SetFilterMutated(child->element_id(), filters); EmulateDrawingOneFrame(root); EXPECT_TRUE(root->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( &root_damage_rect)); @@ -708,8 +697,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForHighDPIImageFilter) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; int device_scale_factor = 2; EmulateDrawingOneFrame(root, device_scale_factor); - child->layer_tree_impl()->property_trees()->effect_tree.OnFilterAnimated( - filters, child->effect_tree_index(), child->layer_tree_impl()); + child->layer_tree_impl()->SetFilterMutated(child->element_id(), filters); EmulateDrawingOneFrame(root, device_scale_factor); EXPECT_TRUE(root->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( &root_damage_rect)); @@ -1009,8 +997,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForNestedSurfaces) { // CASE 1: Damage to a descendant surface should propagate properly to // ancestor surface. ClearDamageForAllSurfaces(root); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.5f, grand_child1->effect_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(grand_child1->element_id(), 0.5f); EmulateDrawingOneFrame(root); EXPECT_TRUE( child1->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( @@ -1027,10 +1014,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForNestedSurfaces) { // - child2 damage in root surface space: // gfx::Rect(11, 11, 18, 18); ClearDamageForAllSurfaces(root); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.7f, grand_child1->effect_tree_index(), root->layer_tree_impl()); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.7f, child2->effect_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(grand_child1->element_id(), 0.7f); + root->layer_tree_impl()->SetOpacityMutated(child2->element_id(), 0.7f); EmulateDrawingOneFrame(root); EXPECT_TRUE( child1->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( @@ -1099,8 +1084,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromAncestorLayer) { ClearDamageForAllSurfaces(root); gfx::Transform translation; translation.Translate(-50.f, -50.f); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - translation, child1->transform_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(child1->element_id(), + translation); EmulateDrawingOneFrame(root); EXPECT_TRUE( child1->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( @@ -1451,9 +1436,7 @@ TEST_F(DamageTrackerTest, HugeDamageRect) { // Visible rects computed from combining clips in target space and root // space don't match because of the loss in floating point accuracy. So, we // skip verify_clip_tree_calculations. - bool skip_verify_visible_rect_calculations = true; - EmulateDrawingOneFrame(root, device_scale_factor, - skip_verify_visible_rect_calculations); + EmulateDrawingOneFrame(root, device_scale_factor); // The expected damage should cover the visible part of the child layer, // which is (0, 0, i, i) in the viewport. @@ -1482,9 +1465,7 @@ TEST_F(DamageTrackerTest, DamageRectTooBig) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; float device_scale_factor = 1.f; - bool skip_verify_visible_rect_calculations = true; - EmulateDrawingOneFrame(root, device_scale_factor, - skip_verify_visible_rect_calculations); + EmulateDrawingOneFrame(root, device_scale_factor); // The expected damage would be too large to store in a gfx::Rect, so we // should damage everything (ie, we don't have a valid rect). @@ -1515,9 +1496,7 @@ TEST_F(DamageTrackerTest, DamageRectTooBigWithFilter) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; float device_scale_factor = 1.f; - bool skip_verify_visible_rect_calculations = true; - EmulateDrawingOneFrame(root, device_scale_factor, - skip_verify_visible_rect_calculations); + EmulateDrawingOneFrame(root, device_scale_factor); // The expected damage would be too large to store in a gfx::Rect, so we // should damage everything (ie, we don't have a valid rect). @@ -1548,10 +1527,8 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurface) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; float device_scale_factor = 1.f; - bool skip_verify_visible_rect_calculations = true; LayerImplList render_surface_layer_list; ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); auto* surface = child1->GetRenderSurface(); @@ -1590,7 +1567,6 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurface) { // Recompute all damage / properties. render_surface_layer_list.clear(); ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); surface = child1->GetRenderSurface(); surface->damage_tracker()->UpdateDamageTrackingState( @@ -1645,10 +1621,8 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurfaceWithFilter) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; float device_scale_factor = 1.f; - bool skip_verify_visible_rect_calculations = true; LayerImplList render_surface_layer_list; ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); auto* surface = child1->GetRenderSurface(); @@ -1687,7 +1661,6 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurfaceWithFilter) { // Recompute all damage / properties. render_surface_layer_list.clear(); ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); surface = child1->GetRenderSurface(); surface->damage_tracker()->UpdateDamageTrackingState( diff --git a/chromium/cc/debug/debug_rect_history.cc b/chromium/cc/trees/debug_rect_history.cc index 33a9a35340a..243c610214c 100644 --- a/chromium/cc/debug/debug_rect_history.cc +++ b/chromium/cc/trees/debug_rect_history.cc @@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/debug_rect_history.h" +#include "cc/trees/debug_rect_history.h" #include <stddef.h> #include "base/memory/ptr_util.h" #include "cc/base/math_util.h" #include "cc/layers/layer_impl.h" -#include "cc/layers/layer_iterator.h" #include "cc/layers/layer_list_iterator.h" #include "cc/layers/layer_utils.h" #include "cc/layers/render_surface_impl.h" @@ -64,7 +63,7 @@ void DebugRectHistory::SaveDebugRectsForCurrentFrame( SaveScreenSpaceRects(render_surface_layer_list); if (debug_state.show_layer_animation_bounds_rects) - SaveLayerAnimationBoundsRects(render_surface_layer_list); + SaveLayerAnimationBoundsRects(tree_impl); } void DebugRectHistory::SavePaintRects(LayerTreeImpl* tree_impl) { @@ -96,8 +95,7 @@ void DebugRectHistory::SavePropertyChangedRects( DCHECK(render_surface); const LayerImplList& layer_list = render_surface->layer_list(); - for (unsigned layer_index = 0; - layer_index < layer_list.size(); + for (unsigned layer_index = 0; layer_index < layer_list.size(); ++layer_index) { LayerImpl* layer = layer_list[layer_index]; @@ -144,11 +142,10 @@ void DebugRectHistory::SaveScreenSpaceRects( render_surface_layer->GetRenderSurface(); DCHECK(render_surface); - debug_rects_.push_back( - DebugRect(SCREEN_SPACE_RECT_TYPE, - MathUtil::MapEnclosingClippedRect( - render_surface->screen_space_transform(), - render_surface->content_rect()))); + debug_rects_.push_back(DebugRect( + SCREEN_SPACE_RECT_TYPE, MathUtil::MapEnclosingClippedRect( + render_surface->screen_space_transform(), + render_surface->content_rect()))); } } @@ -160,8 +157,7 @@ void DebugRectHistory::SaveTouchEventHandlerRects(LayerTreeImpl* tree_impl) { void DebugRectHistory::SaveTouchEventHandlerRectsCallback(LayerImpl* layer) { for (Region::Iterator iter(layer->touch_event_handler_region()); - iter.has_rect(); - iter.next()) { + iter.has_rect(); iter.next()) { debug_rects_.push_back( DebugRect(TOUCH_EVENT_HANDLER_RECT_TYPE, MathUtil::MapEnclosingClippedRect( @@ -212,8 +208,7 @@ void DebugRectHistory::SaveNonFastScrollableRects(LayerTreeImpl* tree_impl) { void DebugRectHistory::SaveNonFastScrollableRectsCallback(LayerImpl* layer) { for (Region::Iterator iter(layer->non_fast_scrollable_region()); - iter.has_rect(); - iter.next()) { + iter.has_rect(); iter.next()) { debug_rects_.push_back( DebugRect(NON_FAST_SCROLLABLE_RECT_TYPE, MathUtil::MapEnclosingClippedRect( @@ -221,12 +216,9 @@ void DebugRectHistory::SaveNonFastScrollableRectsCallback(LayerImpl* layer) { } } -void DebugRectHistory::SaveLayerAnimationBoundsRects( - const LayerImplList& 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()) +void DebugRectHistory::SaveLayerAnimationBoundsRects(LayerTreeImpl* tree_impl) { + for (auto it = tree_impl->rbegin(); it != tree_impl->rend(); ++it) { + if (!(*it)->is_drawn_render_surface_layer_list_member()) continue; // TODO(avallee): Figure out if we should show something for a layer who's @@ -237,10 +229,9 @@ void DebugRectHistory::SaveLayerAnimationBoundsRects( debug_rects_.push_back( DebugRect(ANIMATION_BOUNDS_RECT_TYPE, - gfx::ToEnclosingRect(gfx::RectF(inflated_bounds.x(), - inflated_bounds.y(), - inflated_bounds.width(), - inflated_bounds.height())))); + gfx::ToEnclosingRect(gfx::RectF( + inflated_bounds.x(), inflated_bounds.y(), + inflated_bounds.width(), inflated_bounds.height())))); } } diff --git a/chromium/cc/debug/debug_rect_history.h b/chromium/cc/trees/debug_rect_history.h index 514a72bfd33..183cddeb775 100644 --- a/chromium/cc/debug/debug_rect_history.h +++ b/chromium/cc/trees/debug_rect_history.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_DEBUG_RECT_HISTORY_H_ -#define CC_DEBUG_DEBUG_RECT_HISTORY_H_ +#ifndef CC_TREES_DEBUG_RECT_HISTORY_H_ +#define CC_TREES_DEBUG_RECT_HISTORY_H_ #include <memory> #include <vector> @@ -78,10 +78,8 @@ class DebugRectHistory { void SavePaintRects(LayerTreeImpl* tree_impl); void SavePropertyChangedRects(const LayerImplList& render_surface_layer_list, LayerImpl* hud_layer); - void SaveSurfaceDamageRects( - const LayerImplList& render_surface_layer_list); - void SaveScreenSpaceRects( - const LayerImplList& render_surface_layer_list); + void SaveSurfaceDamageRects(const LayerImplList& render_surface_layer_list); + void SaveScreenSpaceRects(const LayerImplList& render_surface_layer_list); void SaveTouchEventHandlerRects(LayerTreeImpl* layer); void SaveTouchEventHandlerRectsCallback(LayerImpl* layer); void SaveWheelEventHandlerRects(LayerTreeImpl* tree_impl); @@ -89,8 +87,7 @@ class DebugRectHistory { void SaveScrollEventHandlerRectsCallback(LayerImpl* layer); void SaveNonFastScrollableRects(LayerTreeImpl* layer); void SaveNonFastScrollableRectsCallback(LayerImpl* layer); - void SaveLayerAnimationBoundsRects( - const LayerImplList& render_surface_layer_list); + void SaveLayerAnimationBoundsRects(LayerTreeImpl* tree_impl); std::vector<DebugRect> debug_rects_; @@ -99,4 +96,4 @@ class DebugRectHistory { } // namespace cc -#endif // CC_DEBUG_DEBUG_RECT_HISTORY_H_ +#endif // CC_TREES_DEBUG_RECT_HISTORY_H_ diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc index c5128934db9..5af6686aa61 100644 --- a/chromium/cc/trees/draw_property_utils.cc +++ b/chromium/cc/trees/draw_property_utils.cc @@ -17,6 +17,7 @@ #include "cc/trees/layer_tree_impl.h" #include "cc/trees/property_tree.h" #include "cc/trees/property_tree_builder.h" +#include "cc/trees/scroll_node.h" #include "cc/trees/transform_node.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -34,54 +35,45 @@ static bool IsRootLayer(const LayerImpl* layer) { return layer->layer_tree_impl()->IsRootLayer(layer); } -static const EffectNode* ContentsTargetEffectNode( - const int effect_tree_index, - const EffectTree& effect_tree) { - const EffectNode* effect_node = effect_tree.Node(effect_tree_index); - return effect_tree.GetRenderSurface(effect_tree_index) - ? effect_node - : effect_tree.Node(effect_node->target_id); +static void PostConcatSurfaceContentsScale(const EffectNode* effect_node, + gfx::Transform* transform) { + if (!effect_node) { + // This can happen when PaintArtifactCompositor builds property trees as it + // doesn't set effect ids on clip nodes. + return; + } + DCHECK(effect_node->has_render_surface); + transform->matrix().postScale(effect_node->surface_contents_scale.x(), + effect_node->surface_contents_scale.y(), 1.f); } -bool ComputeClipRectInTargetSpace(const LayerImpl* layer, - const ClipNode* clip_node, - const PropertyTrees* property_trees, - int target_node_id, - bool for_visible_rect_calculation, - gfx::RectF* clip_rect_in_target_space) { - DCHECK(layer->clip_tree_index() == clip_node->id); - DCHECK(clip_node->target_transform_id != target_node_id); - - const EffectTree& effect_tree = property_trees->effect_tree; - const EffectNode* target_effect_node = - ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree); - gfx::Transform clip_to_target; - // We use the local clip for clip rect calculation and combined clip for - // visible rect calculation. - gfx::RectF clip_from_clip_node = - for_visible_rect_calculation ? clip_node->combined_clip_in_target_space - : clip_node->clip_in_target_space; - - if (clip_node->target_transform_id > target_node_id) { - // In this case, layer has a scroll parent. We need to keep the scale - // at the layer's target but remove the scale at the scroll parent's - // target. - if (property_trees->GetToTarget(clip_node->target_transform_id, - target_effect_node->id, &clip_to_target)) { - const EffectNode* source_node = - effect_tree.Node(clip_node->target_effect_id); - ConcatInverseSurfaceContentsScale(source_node, &clip_to_target); - *clip_rect_in_target_space = - MathUtil::MapClippedRect(clip_to_target, clip_from_clip_node); +static bool ConvertRectBetweenSurfaceSpaces(const PropertyTrees* property_trees, + int source_effect_id, + int dest_effect_id, + gfx::RectF clip_in_source_space, + gfx::RectF* clip_in_dest_space) { + const EffectNode* source_effect_node = + property_trees->effect_tree.Node(source_effect_id); + int source_transform_id = source_effect_node->transform_id; + const EffectNode* dest_effect_node = + property_trees->effect_tree.Node(dest_effect_id); + int dest_transform_id = dest_effect_node->transform_id; + gfx::Transform source_to_dest; + if (source_transform_id > dest_transform_id) { + if (property_trees->GetToTarget(source_transform_id, dest_effect_id, + &source_to_dest)) { + ConcatInverseSurfaceContentsScale(source_effect_node, &source_to_dest); + *clip_in_dest_space = + MathUtil::MapClippedRect(source_to_dest, clip_in_source_space); } else { return false; } } else { - if (property_trees->GetFromTarget( - target_node_id, clip_node->target_effect_id, &clip_to_target)) { - PostConcatSurfaceContentsScale(target_effect_node, &clip_to_target); - *clip_rect_in_target_space = - MathUtil::ProjectClippedRect(clip_to_target, clip_from_clip_node); + if (property_trees->GetFromTarget(dest_transform_id, source_effect_id, + &source_to_dest)) { + PostConcatSurfaceContentsScale(dest_effect_node, &source_to_dest); + *clip_in_dest_space = + MathUtil::ProjectClippedRect(source_to_dest, clip_in_source_space); } else { return false; } @@ -89,11 +81,6 @@ bool ComputeClipRectInTargetSpace(const LayerImpl* layer, return true; } -struct ConditionalClip { - bool is_clipped; - gfx::RectF clip_rect; -}; - static ConditionalClip ComputeTargetRectInLocalSpace( gfx::RectF rect, const PropertyTrees* property_trees, @@ -103,8 +90,8 @@ static ConditionalClip ComputeTargetRectInLocalSpace( gfx::Transform target_to_local; bool success = property_trees->GetFromTarget( local_transform_id, target_effect_id, &target_to_local); + // If transform is not invertible, cannot apply clip. if (!success) - // If transform is not invertible, cannot apply clip. return ConditionalClip{false, gfx::RectF()}; if (target_transform_id > local_transform_id) @@ -115,29 +102,6 @@ static ConditionalClip ComputeTargetRectInLocalSpace( MathUtil::ProjectClippedRect(target_to_local, rect)}; } -static ConditionalClip ConvertRectBetweenSurfaceSpaces( - gfx::RectF rect, - const PropertyTrees* property_trees, - int source_transform_id, - int source_effect_id, - int dest_transform_id, - int dest_effect_id) { - gfx::Transform source_to_dest; - bool success = property_trees->GetToTarget(source_transform_id, - dest_effect_id, &source_to_dest); - if (!success) - return ConditionalClip{false, gfx::RectF()}; - const EffectTree& effect_tree = property_trees->effect_tree; - const EffectNode* source_effect_node = effect_tree.Node(source_effect_id); - ConcatInverseSurfaceContentsScale(source_effect_node, &source_to_dest); - if (source_transform_id > dest_transform_id) { - return ConditionalClip{true, // is_clipped - MathUtil::MapClippedRect(source_to_dest, rect)}; - } - return ConditionalClip{true, // is_clipped - MathUtil::ProjectClippedRect(source_to_dest, rect)}; -} - static ConditionalClip ComputeLocalRectInTargetSpace( gfx::RectF rect, const PropertyTrees* property_trees, @@ -206,362 +170,149 @@ static bool ApplyClipNodeToAccumulatedClip(const PropertyTrees* property_trees, const EffectNode* expanding_effect_node = property_trees->effect_tree.Node( clip_node->clip_expander->target_effect_id()); - ConditionalClip accumulated_clip_in_expanding_space = - ConvertRectBetweenSurfaceSpaces( - *accumulated_clip, property_trees, target_transform_id, target_id, - expanding_effect_node->transform_id, expanding_effect_node->id); + gfx::RectF accumulated_clip_rect_in_expanding_space; + bool success = ConvertRectBetweenSurfaceSpaces( + property_trees, target_id, expanding_effect_node->id, + *accumulated_clip, &accumulated_clip_rect_in_expanding_space); // If transform is not invertible, no clip will be applied. - if (!accumulated_clip_in_expanding_space.is_clipped) + if (!success) return false; // Do the expansion. gfx::RectF expanded_clip_in_expanding_space = gfx::RectF(clip_node->clip_expander->MapRectReverse( - gfx::ToEnclosingRect( - accumulated_clip_in_expanding_space.clip_rect), + gfx::ToEnclosingRect(accumulated_clip_rect_in_expanding_space), property_trees)); // Put the expanded clip back into the original target space. - ConditionalClip expanded_clip_in_target_space = - ConvertRectBetweenSurfaceSpaces( - expanded_clip_in_expanding_space, property_trees, - expanding_effect_node->transform_id, expanding_effect_node->id, - target_transform_id, target_id); + success = ConvertRectBetweenSurfaceSpaces( + property_trees, expanding_effect_node->id, target_id, + expanded_clip_in_expanding_space, accumulated_clip); // If transform is not invertible, no clip will be applied. - if (!expanded_clip_in_target_space.is_clipped) + if (!success) return false; - *accumulated_clip = expanded_clip_in_target_space.clip_rect; return true; } - case ClipNode::ClipType::NONE: - return true; } NOTREACHED(); return true; } -static ConditionalClip ComputeAccumulatedClip( - const PropertyTrees* property_trees, - bool include_viewport_clip, - bool include_expanding_clips, - int local_clip_id, - int target_id) { - DCHECK(!include_viewport_clip || - target_id == EffectTree::kContentsRootNodeId); - const ClipTree& clip_tree = property_trees->clip_tree; - const EffectTree& effect_tree = property_trees->effect_tree; +static ConditionalClip ComputeAccumulatedClip(PropertyTrees* property_trees, + bool include_expanding_clips, + int local_clip_id, + int target_id) { + ClipRectData* cached_data = + property_trees->FetchClipRectFromCache(local_clip_id, target_id); + if (cached_data->target_id != EffectTree::kInvalidNodeId) { + // Cache hit + return cached_data->clip; + } + cached_data->target_id = target_id; + const ClipTree& clip_tree = property_trees->clip_tree; const ClipNode* clip_node = clip_tree.Node(local_clip_id); + const EffectTree& effect_tree = property_trees->effect_tree; const EffectNode* target_node = effect_tree.Node(target_id); int target_transform_id = target_node->transform_id; + bool cache_hit = false; + ConditionalClip cached_clip = ConditionalClip{false, gfx::RectF()}; + ConditionalClip unclipped = ConditionalClip{false, gfx::RectF()}; + // Collect all the clips that need to be accumulated. - std::stack<const ClipNode*> parent_chain; + std::stack<const ClipNode*, std::vector<const ClipNode*>> parent_chain; // If target is not direct ancestor of clip, this will find least common - // ancestor between the target and the clip. + // ancestor between the target and the clip. Or, if the target has a + // contributing layer that escapes clip, this will find the nearest ancestor + // that doesn't. while (target_node->clip_id > clip_node->id || - target_node->has_unclipped_descendants) { + effect_tree.GetRenderSurface(target_node->id) + ->has_contributing_layer_that_escapes_clip()) { target_node = effect_tree.Node(target_node->target_id); } - // Collect clip nodes up to the least common ancestor. + // Collect clip nodes up to the least common ancestor or till we get a cache + // hit. while (target_node->clip_id < clip_node->id) { + if (parent_chain.size() > 0) { + // Search the cache. + for (auto& data : clip_node->cached_clip_rects) { + if (data.target_id == target_id) { + cache_hit = true; + cached_clip = data.clip; + } + } + } parent_chain.push(clip_node); clip_node = clip_tree.parent(clip_node); } - DCHECK_EQ(target_node->clip_id, clip_node->id); - if (!include_viewport_clip && parent_chain.size() == 0) { - // There aren't any clips to apply. - return ConditionalClip{false, gfx::RectF()}; + if (parent_chain.size() == 0) { + // No accumulated clip nodes. + cached_data->clip = unclipped; + return unclipped; } - if (!include_viewport_clip) { - clip_node = parent_chain.top(); - parent_chain.pop(); - } - - // Find the first clip in the chain that we need to apply. - while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP && - parent_chain.size() > 0) { - clip_node = parent_chain.top(); - parent_chain.pop(); - } + clip_node = parent_chain.top(); + parent_chain.pop(); - if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) { - // No clip node applying clip in between. - return ConditionalClip{false, gfx::RectF()}; - } - - ConditionalClip current_clip = ComputeCurrentClip( - clip_node, property_trees, target_transform_id, target_id); - - // If transform is not invertible, no clip will be applied. - if (!current_clip.is_clipped) - return ConditionalClip{false, gfx::RectF()}; - gfx::RectF accumulated_clip = current_clip.clip_rect; - - while (parent_chain.size() > 0) { - clip_node = parent_chain.top(); - parent_chain.pop(); + gfx::RectF accumulated_clip; + if (cache_hit && cached_clip.is_clipped) { + // Apply the first clip in parent_chain to the cached clip. + accumulated_clip = cached_clip.clip_rect; bool success = ApplyClipNodeToAccumulatedClip( property_trees, include_expanding_clips, target_id, target_transform_id, clip_node, &accumulated_clip); - - // Failure to apply the clip means we encountered an uninvertible transform, - // so no clip will be applied. - if (!success) - return ConditionalClip{false /* is_clipped */, gfx::RectF()}; - } - - return ConditionalClip{true /* is_clipped */, accumulated_clip.IsEmpty() - ? gfx::RectF() - : accumulated_clip}; -} - -static gfx::RectF ComputeAccumulatedClipInRootSpaceForVisibleRect( - const PropertyTrees* property_trees, - int local_clip_id) { - const int root_effect_id = EffectTree::kContentsRootNodeId; - bool include_viewport_clip = true; - bool include_expanding_clips = true; - ConditionalClip accumulated_clip = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - local_clip_id, root_effect_id); - DCHECK(accumulated_clip.is_clipped); - return accumulated_clip.clip_rect; -} - -void CalculateClipRects(const std::vector<LayerImpl*>& visible_layer_list, - const PropertyTrees* property_trees, - bool non_root_surfaces_enabled) { - const ClipTree& clip_tree = property_trees->clip_tree; - for (auto* layer : visible_layer_list) { - const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); - bool layer_needs_clip_rect = - non_root_surfaces_enabled - ? clip_node->layers_are_clipped - : clip_node->layers_are_clipped_when_surfaces_disabled; - if (!layer_needs_clip_rect) { - layer->set_clip_rect(gfx::Rect()); - continue; + if (!success) { + // Singular transform + cached_data->clip = unclipped; + return unclipped; } - if (!non_root_surfaces_enabled) { - layer->set_clip_rect( - gfx::ToEnclosingRect(clip_node->clip_in_target_space)); - continue; + } else { + // No cache hit or the cached clip has no clip to apply. We need to find + // the first clip that applies clip as there is no clip to expand. + while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP && + parent_chain.size() > 0) { + clip_node = parent_chain.top(); + parent_chain.pop(); } - const TransformTree& transform_tree = property_trees->transform_tree; - const TransformNode* transform_node = - transform_tree.Node(layer->transform_tree_index()); - int target_node_id = transform_tree.ContentTargetId(transform_node->id); - - // The clip node stores clip rect in its target space. - gfx::RectF clip_rect_in_target_space = clip_node->clip_in_target_space; - - // If required, this clip rect should be mapped to the current layer's - // target space. - if (clip_node->target_transform_id != target_node_id) { - // In this case, layer has a clip parent or scroll parent (or shares the - // target with an ancestor layer that has clip parent) and the clip - // parent's target is different from the layer's target. As the layer's - // target has unclippped descendants, it is unclippped. - if (!clip_node->layers_are_clipped) - continue; - - // Compute the clip rect in target space and store it. - bool for_visible_rect_calculation = false; - if (!ComputeClipRectInTargetSpace( - layer, clip_node, property_trees, target_node_id, - for_visible_rect_calculation, &clip_rect_in_target_space)) - continue; + if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) { + // No clip to apply. + cached_data->clip = unclipped; + return unclipped; } - - if (!clip_rect_in_target_space.IsEmpty()) { - layer->set_clip_rect(gfx::ToEnclosingRect(clip_rect_in_target_space)); - } else { - layer->set_clip_rect(gfx::Rect()); + ConditionalClip current_clip = ComputeCurrentClip( + clip_node, property_trees, target_transform_id, target_id); + if (!current_clip.is_clipped) { + // Singular transform + cached_data->clip = unclipped; + return unclipped; } + accumulated_clip = current_clip.clip_rect; } -} - -void CalculateVisibleRects(const LayerImplList& visible_layer_list, - const PropertyTrees* property_trees, - bool non_root_surfaces_enabled) { - const EffectTree& effect_tree = property_trees->effect_tree; - const TransformTree& transform_tree = property_trees->transform_tree; - const ClipTree& clip_tree = property_trees->clip_tree; - for (auto* layer : visible_layer_list) { - gfx::Size layer_bounds = layer->bounds(); - - int effect_ancestor_with_copy_request = - effect_tree.ClosestAncestorWithCopyRequest(layer->effect_tree_index()); - if (effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId) { - // Non root copy request. - bool include_viewport_clip = false; - bool include_expanding_clips = true; - ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - layer->clip_tree_index(), effect_ancestor_with_copy_request); - if (!accumulated_clip_rect.is_clipped) { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; - } - - gfx::RectF accumulated_clip_in_copy_request_space = - accumulated_clip_rect.clip_rect; - - const EffectNode* copy_request_effect_node = - effect_tree.Node(effect_ancestor_with_copy_request); - ConditionalClip clip_in_layer_space = ComputeTargetRectInLocalSpace( - accumulated_clip_in_copy_request_space, property_trees, - copy_request_effect_node->transform_id, layer->transform_tree_index(), - copy_request_effect_node->id); - - if (clip_in_layer_space.is_clipped) { - gfx::RectF clip_rect = clip_in_layer_space.clip_rect; - clip_rect.Offset(-layer->offset_to_transform_parent()); - gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_rect); - visible_rect.Intersect(gfx::Rect(layer_bounds)); - layer->set_visible_layer_rect(visible_rect); - } else { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - } - continue; - } - - const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); - const TransformNode* transform_node = - transform_tree.Node(layer->transform_tree_index()); - if (!non_root_surfaces_enabled) { - // When we only have a root surface, the clip node and the layer must - // necessarily have the same target (the root). - if (transform_node->ancestors_are_invertible) { - gfx::RectF combined_clip_rect_in_target_space = - clip_node->combined_clip_in_target_space; - gfx::Transform target_to_content; - target_to_content.Translate(-layer->offset_to_transform_parent().x(), - -layer->offset_to_transform_parent().y()); - target_to_content.PreconcatTransform( - transform_tree.FromScreen(transform_node->id)); - - gfx::Rect visible_rect = - gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - target_to_content, combined_clip_rect_in_target_space)); - visible_rect.Intersect(gfx::Rect(layer_bounds)); - layer->set_visible_layer_rect(visible_rect); - } else { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - } - continue; - } - - // When both the layer and the target are unclipped, we only have to apply - // the viewport clip. - const bool fully_visible = - !clip_node->layers_are_clipped && - !effect_tree.Node(clip_node->target_effect_id)->surface_is_clipped; - - if (fully_visible) { - if (!transform_node->ancestors_are_invertible) { - // An animated singular transform may become non-singular during the - // animation, so we still need to compute a visible rect. In this - // situation, we treat the entire layer as visible. - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - } else { - gfx::Transform from_screen; - from_screen.Translate(-layer->offset_to_transform_parent().x(), - -layer->offset_to_transform_parent().y()); - from_screen.PreconcatTransform( - property_trees->transform_tree.FromScreen(transform_node->id)); - gfx::Rect visible_rect = - gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - from_screen, property_trees->clip_tree.ViewportClip())); - visible_rect.Intersect(gfx::Rect(layer_bounds)); - layer->set_visible_layer_rect(visible_rect); - } - continue; - } - - int target_node_id = transform_tree.ContentTargetId(transform_node->id); - - // The clip node stores clip rect in its target space. If required, - // this clip rect should be mapped to the current layer's target space. - gfx::RectF combined_clip_rect_in_target_space; - if (clip_node->target_transform_id != target_node_id) { - // In this case, layer has a clip parent or scroll parent (or shares the - // target with an ancestor layer that has clip parent) and the clip - // parent's target is different from the layer's target. As the layer's - // target has unclippped descendants, it is unclippped. - if (!clip_node->layers_are_clipped) { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; - } - - bool for_visible_rect_calculation = true; - if (!ComputeClipRectInTargetSpace(layer, clip_node, property_trees, - target_node_id, - for_visible_rect_calculation, - &combined_clip_rect_in_target_space)) { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; - } - } else { - combined_clip_rect_in_target_space = - clip_node->combined_clip_in_target_space; - } - - // The clip rect should be intersected with layer rect in target space. - gfx::Transform content_to_target; - property_trees->GetToTarget(transform_node->id, - layer->render_target_effect_tree_index(), - &content_to_target); - content_to_target.Translate(layer->offset_to_transform_parent().x(), - layer->offset_to_transform_parent().y()); - gfx::Rect layer_content_rect = gfx::Rect(layer_bounds); - gfx::RectF layer_content_bounds_in_target_space = MathUtil::MapClippedRect( - content_to_target, gfx::RectF(layer_content_rect)); - // If the layer is fully contained within the clip, treat it as fully - // visible. - if (!layer_content_bounds_in_target_space.IsEmpty() && - combined_clip_rect_in_target_space.Contains( - layer_content_bounds_in_target_space)) { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; - } - - combined_clip_rect_in_target_space.Intersect( - layer_content_bounds_in_target_space); - if (combined_clip_rect_in_target_space.IsEmpty()) { - layer->set_visible_layer_rect(gfx::Rect()); - continue; - } - - gfx::Transform target_to_layer; - const EffectNode* target_effect_node = - ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree); - bool success = property_trees->GetFromTarget( - transform_node->id, target_effect_node->id, &target_to_layer); + // Apply remaining clips + while (parent_chain.size() > 0) { + clip_node = parent_chain.top(); + parent_chain.pop(); + bool success = ApplyClipNodeToAccumulatedClip( + property_trees, include_expanding_clips, target_id, target_transform_id, + clip_node, &accumulated_clip); if (!success) { - // An animated singular transform may become non-singular during the - // animation, so we still need to compute a visible rect. In this - // situation, we treat the entire layer as visible. - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; + // Singular transform + cached_data->clip = unclipped; + return unclipped; } - gfx::Transform target_to_content; - target_to_content.Translate(-layer->offset_to_transform_parent().x(), - -layer->offset_to_transform_parent().y()); - target_to_content.PreconcatTransform(target_to_layer); - - gfx::Rect visible_rect = gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - target_to_content, combined_clip_rect_in_target_space)); - visible_rect.Intersect(gfx::Rect(layer_bounds)); - layer->set_visible_layer_rect(visible_rect); } + + ConditionalClip clip = ConditionalClip{ + true /* is_clipped */, + accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip}; + cached_data->clip = clip; + return clip; } static bool HasSingularTransform(int transform_tree_index, @@ -570,6 +321,36 @@ static bool HasSingularTransform(int transform_tree_index, return !node->is_invertible || !node->ancestors_are_invertible; } +static int LowestCommonAncestor(int clip_id_1, + int clip_id_2, + const ClipTree* clip_tree) { + const ClipNode* clip_node_1 = clip_tree->Node(clip_id_1); + const ClipNode* clip_node_2 = clip_tree->Node(clip_id_2); + while (clip_node_1->id != clip_node_2->id) { + if (clip_node_1->id < clip_node_2->id) + clip_node_2 = clip_tree->parent(clip_node_2); + else + clip_node_1 = clip_tree->parent(clip_node_1); + } + return clip_node_1->id; +} + +static void SetHasContributingLayerThatEscapesClip(int lca_clip_id, + int target_effect_id, + EffectTree* effect_tree) { + const EffectNode* effect_node = effect_tree->Node(target_effect_id); + // Find all ancestor targets starting from effect_node who are clipped by + // a descendant of lowest ancestor clip and set their + // has_contributing_layer_that_escapes_clip to true. + while (effect_node->clip_id > lca_clip_id) { + RenderSurfaceImpl* render_surface = + effect_tree->GetRenderSurface(effect_node->id); + DCHECK(render_surface); + render_surface->set_has_contributing_layer_that_escapes_clip(true); + effect_node = effect_tree->Node(effect_node->target_id); + } +} + template <typename LayerType> static int TransformTreeIndexForBackfaceVisibility(LayerType* layer, const TransformTree& tree) { @@ -668,27 +449,6 @@ static bool LayerNeedsUpdateInternal(LayerType* layer, return true; } -void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, - const PropertyTrees* property_trees, - std::vector<LayerImpl*>* visible_layer_list) { - const TransformTree& transform_tree = property_trees->transform_tree; - const EffectTree& effect_tree = property_trees->effect_tree; - - for (auto* layer_impl : *layer_tree_impl) { - if (!IsRootLayer(layer_impl) && - LayerShouldBeSkipped(layer_impl, transform_tree, effect_tree)) - continue; - - bool layer_is_drawn = - effect_tree.Node(layer_impl->effect_tree_index())->is_drawn; - - if (LayerNeedsUpdate(layer_impl, layer_is_drawn, property_trees)) - visible_layer_list->push_back(layer_impl); - } -} - -} // namespace - template <typename LayerType> static inline bool LayerShouldBeSkippedInternal( LayerType* layer, @@ -701,6 +461,7 @@ static inline bool LayerShouldBeSkippedInternal( if (effect_node->has_render_surface && effect_node->num_copy_requests_in_subtree > 0) return false; + // If the layer transform is not invertible, it should be skipped. // TODO(ajuma): Correctly process subtrees with singular transform for the // case where we may animate to a non-singular transform and wish to @@ -709,6 +470,345 @@ static inline bool LayerShouldBeSkippedInternal( effect_node->hidden_by_backface_visibility || !effect_node->is_drawn; } +template <typename LayerType> +static void UpdateElasticOverscrollInternal( + PropertyTrees* property_trees, + const LayerType* overscroll_elasticity_layer, + const gfx::Vector2dF& elastic_overscroll) { + if (!overscroll_elasticity_layer) { + DCHECK(elastic_overscroll.IsZero()); + return; + } + + TransformNode* node = property_trees->transform_tree.Node( + overscroll_elasticity_layer->transform_tree_index()); + DCHECK(node); + + // TODO(pdr): This is a workaround for https://crbug.com/721772 to avoid + // crashing when there's no transform node. This workaround should be removed. + if (!node) + return; + + if (node->scroll_offset == gfx::ScrollOffset(elastic_overscroll)) + return; + + node->scroll_offset = gfx::ScrollOffset(elastic_overscroll); + node->needs_local_transform_update = true; + property_trees->transform_tree.set_needs_update(true); +} + +#if DCHECK_IS_ON() +static void ValidatePageScaleLayer(const Layer* page_scale_layer) { + DCHECK_EQ(page_scale_layer->position().ToString(), gfx::PointF().ToString()); + DCHECK_EQ(page_scale_layer->transform_origin().ToString(), + gfx::Point3F().ToString()); +} + +static void ValidatePageScaleLayer(const LayerImpl* page_scale_layer) {} +#endif + +template <typename LayerType> +static void UpdatePageScaleFactorInternal(PropertyTrees* property_trees, + const LayerType* page_scale_layer, + float page_scale_factor, + float device_scale_factor, + gfx::Transform device_transform) { + if (property_trees->transform_tree.page_scale_factor() == page_scale_factor) + return; + + property_trees->transform_tree.set_page_scale_factor(page_scale_factor); + DCHECK(page_scale_layer); + DCHECK_GE(page_scale_layer->transform_tree_index(), + TransformTree::kRootNodeId); + TransformNode* node = property_trees->transform_tree.Node( + page_scale_layer->transform_tree_index()); +// TODO(enne): property trees can't ask the layer these things, but +// the page scale layer should *just* be the page scale. +#if DCHECK_IS_ON() + ValidatePageScaleLayer(page_scale_layer); +#endif + + if (IsRootLayer(page_scale_layer)) { + // When the page scale layer is also the root layer, the node should also + // store the combined scale factor and not just the page scale factor. + float post_local_scale_factor = page_scale_factor * device_scale_factor; + node->post_local_scale_factor = post_local_scale_factor; + node->post_local = device_transform; + node->post_local.Scale(post_local_scale_factor, post_local_scale_factor); + } else { + node->post_local_scale_factor = page_scale_factor; + node->update_post_local_transform(gfx::PointF(), gfx::Point3F()); + } + node->needs_local_transform_update = true; + property_trees->transform_tree.set_needs_update(true); +} + +static gfx::Rect LayerDrawableContentRect( + const LayerImpl* layer, + const gfx::Rect& layer_bounds_in_target_space, + const gfx::Rect& clip_rect) { + if (layer->is_clipped()) + return IntersectRects(layer_bounds_in_target_space, clip_rect); + + return layer_bounds_in_target_space; +} + +static void SetSurfaceIsClipped(const ClipTree& clip_tree, + RenderSurfaceImpl* render_surface) { + bool is_clipped; + if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) { + // Root render surface is always clipped. + is_clipped = true; + } else if (render_surface->has_contributing_layer_that_escapes_clip()) { + // We cannot clip a surface that has a contribuitng layer which escapes the + // clip. + is_clipped = false; + } else if (render_surface->ClipTreeIndex() == + render_surface->render_target()->ClipTreeIndex()) { + // There is no clip between between the render surface and its target, so + // the surface need not be clipped. + is_clipped = false; + } else { + // If the clips between the render surface and its target only expand the + // clips and do not apply any new clip, we need not clip the render surface. + const ClipNode* clip_node = clip_tree.Node(render_surface->ClipTreeIndex()); + is_clipped = clip_node->clip_type != ClipNode::ClipType::EXPANDS_CLIP; + } + render_surface->SetIsClipped(is_clipped); +} + +static void SetSurfaceDrawOpacity(const EffectTree& tree, + RenderSurfaceImpl* render_surface) { + // Draw opacity of a surface is the product of opacities between the surface + // (included) and its target surface (excluded). + const EffectNode* node = tree.Node(render_surface->EffectTreeIndex()); + float draw_opacity = tree.EffectiveOpacity(node); + for (node = tree.parent(node); node && !node->has_render_surface; + node = tree.parent(node)) { + draw_opacity *= tree.EffectiveOpacity(node); + } + render_surface->SetDrawOpacity(draw_opacity); +} + +static float LayerDrawOpacity(const LayerImpl* layer, const EffectTree& tree) { + if (!layer->render_target()) + return 0.f; + + const EffectNode* target_node = + tree.Node(layer->render_target()->EffectTreeIndex()); + const EffectNode* node = tree.Node(layer->effect_tree_index()); + if (node == target_node) + return 1.f; + + float draw_opacity = 1.f; + while (node != target_node) { + draw_opacity *= tree.EffectiveOpacity(node); + node = tree.parent(node); + } + return draw_opacity; +} + +template <typename LayerType> +static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer, + const TransformTree& tree) { + gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), + layer->offset_to_transform_parent().y()); + gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index()); + xform.ConcatTransform(ssxform); + if (layer->should_flatten_transform_from_property_tree()) + xform.FlattenTo2d(); + return xform; +} + +static void SetSurfaceClipRect(const ClipNode* parent_clip_node, + PropertyTrees* property_trees, + RenderSurfaceImpl* render_surface) { + if (!render_surface->is_clipped()) { + render_surface->SetClipRect(gfx::Rect()); + return; + } + + const EffectTree& effect_tree = property_trees->effect_tree; + const ClipTree& clip_tree = property_trees->clip_tree; + const EffectNode* effect_node = + effect_tree.Node(render_surface->EffectTreeIndex()); + const EffectNode* target_node = effect_tree.Node(effect_node->target_id); + bool include_expanding_clips = false; + if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) { + render_surface->SetClipRect( + gfx::ToEnclosingRect(clip_tree.Node(effect_node->clip_id)->clip)); + } else { + ConditionalClip accumulated_clip_rect = + ComputeAccumulatedClip(property_trees, include_expanding_clips, + effect_node->clip_id, target_node->id); + render_surface->SetClipRect( + gfx::ToEnclosingRect(accumulated_clip_rect.clip_rect)); + } +} + +static void SetSurfaceDrawTransform(const PropertyTrees* property_trees, + RenderSurfaceImpl* render_surface) { + const TransformTree& transform_tree = property_trees->transform_tree; + const EffectTree& effect_tree = property_trees->effect_tree; + const TransformNode* transform_node = + transform_tree.Node(render_surface->TransformTreeIndex()); + const EffectNode* effect_node = + effect_tree.Node(render_surface->EffectTreeIndex()); + // The draw transform of root render surface is identity tranform. + if (transform_node->id == TransformTree::kRootNodeId) { + render_surface->SetDrawTransform(gfx::Transform()); + return; + } + + gfx::Transform render_surface_transform; + const EffectNode* target_effect_node = + effect_tree.Node(effect_node->target_id); + property_trees->GetToTarget(transform_node->id, target_effect_node->id, + &render_surface_transform); + + ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform); + render_surface->SetDrawTransform(render_surface_transform); +} + +static gfx::Rect LayerVisibleRect(PropertyTrees* property_trees, + LayerImpl* layer) { + int effect_ancestor_with_copy_request = + property_trees->effect_tree.ClosestAncestorWithCopyRequest( + layer->effect_tree_index()); + bool non_root_copy_request = + effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId; + gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); + gfx::RectF accumulated_clip_in_root_space; + if (non_root_copy_request) { + bool include_expanding_clips = true; + ConditionalClip accumulated_clip = ComputeAccumulatedClip( + property_trees, include_expanding_clips, layer->clip_tree_index(), + effect_ancestor_with_copy_request); + if (!accumulated_clip.is_clipped) + return layer_content_rect; + accumulated_clip_in_root_space = accumulated_clip.clip_rect; + } else { + const ClipNode* clip_node = + property_trees->clip_tree.Node(layer->clip_tree_index()); + accumulated_clip_in_root_space = + clip_node->cached_accumulated_rect_in_screen_space; + } + + const EffectNode* root_effect_node = + non_root_copy_request + ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request) + : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); + ConditionalClip accumulated_clip_in_layer_space = + ComputeTargetRectInLocalSpace( + accumulated_clip_in_root_space, property_trees, + root_effect_node->transform_id, layer->transform_tree_index(), + root_effect_node->id); + if (!accumulated_clip_in_layer_space.is_clipped) { + return layer_content_rect; + } + gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect; + clip_in_layer_space.Offset(-layer->offset_to_transform_parent()); + + gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space); + visible_rect.Intersect(layer_content_rect); + return visible_rect; +} + +static ConditionalClip LayerClipRect(PropertyTrees* property_trees, + LayerImpl* layer) { + const EffectTree* effect_tree = &property_trees->effect_tree; + const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); + const EffectNode* target_node = + effect_node->has_render_surface + ? effect_node + : effect_tree->Node(effect_node->target_id); + // TODO(weiliangc): When effect node has up to date render surface info on + // compositor thread, no need to check for resourceless draw mode + if (!property_trees->non_root_surfaces_enabled) { + target_node = effect_tree->Node(1); + } + + bool include_expanding_clips = false; + return ComputeAccumulatedClip(property_trees, include_expanding_clips, + layer->clip_tree_index(), target_node->id); +} + +static void UpdateRenderTarget(EffectTree* effect_tree, + bool can_render_to_separate_surface) { + for (int i = EffectTree::kContentsRootNodeId; + i < static_cast<int>(effect_tree->size()); ++i) { + EffectNode* node = effect_tree->Node(i); + if (i == EffectTree::kContentsRootNodeId) { + // Render target of the node corresponding to root is itself. + node->target_id = EffectTree::kContentsRootNodeId; + } else if (!can_render_to_separate_surface) { + node->target_id = EffectTree::kContentsRootNodeId; + } else if (effect_tree->parent(node)->has_render_surface) { + node->target_id = node->parent_id; + } else { + node->target_id = effect_tree->parent(node)->target_id; + } + } +} + +static void UpdateScrollTree(ScrollTree* scroll_tree, + const LayerTreeHost* layer_tree_host) { + if (!scroll_tree->needs_update()) + return; + + for (int i = ScrollTree::kRootNodeId; + i < static_cast<int>(scroll_tree->size()); ++i) { + ScrollNode* scroll_node = scroll_tree->Node(i); + if (Layer* scroll_layer = + layer_tree_host->LayerById(scroll_node->owning_layer_id)) { + if (Layer* scroll_clip_layer = scroll_layer->scroll_clip_layer()) { + scroll_node->scroll_clip_layer_bounds = scroll_clip_layer->bounds(); + } + } + } +} + +static void ComputeClips(PropertyTrees* property_trees) { + DCHECK(!property_trees->transform_tree.needs_update()); + ClipTree* clip_tree = &property_trees->clip_tree; + if (!clip_tree->needs_update()) + return; + const int target_effect_id = EffectTree::kContentsRootNodeId; + const int target_transform_id = TransformTree::kRootNodeId; + const bool include_expanding_clips = true; + for (int i = ClipTree::kViewportNodeId; + i < static_cast<int>(clip_tree->size()); ++i) { + ClipNode* clip_node = clip_tree->Node(i); + // Clear the clip rect cache + clip_node->cached_clip_rects = std::vector<ClipRectData>(1); + if (clip_node->id == ClipTree::kViewportNodeId) { + clip_node->cached_accumulated_rect_in_screen_space = clip_node->clip; + continue; + } + ClipNode* parent_clip_node = clip_tree->parent(clip_node); + DCHECK(parent_clip_node); + gfx::RectF accumulated_clip = + parent_clip_node->cached_accumulated_rect_in_screen_space; + bool success = ApplyClipNodeToAccumulatedClip( + property_trees, include_expanding_clips, target_effect_id, + target_transform_id, clip_node, &accumulated_clip); + DCHECK(success); + clip_node->cached_accumulated_rect_in_screen_space = accumulated_clip; + } + clip_tree->set_needs_update(false); +} + +} // namespace + +void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, + gfx::Transform* transform) { + DCHECK(effect_node->has_render_surface); + if (effect_node->surface_contents_scale.x() != 0.0 && + effect_node->surface_contents_scale.y() != 0.0) + transform->Scale(1.0 / effect_node->surface_contents_scale.x(), + 1.0 / effect_node->surface_contents_scale.y()); +} + bool LayerShouldBeSkipped(LayerImpl* layer, const TransformTree& transform_tree, const EffectTree& effect_tree) { @@ -745,184 +845,31 @@ void FindLayersThatNeedUpdates(LayerTreeHost* layer_tree_host, } } -static void ResetIfHasNanCoordinate(gfx::RectF* rect) { - if (std::isnan(rect->x()) || std::isnan(rect->y()) || - std::isnan(rect->right()) || std::isnan(rect->bottom())) - *rect = gfx::RectF(); -} - -void PostConcatSurfaceContentsScale(const EffectNode* effect_node, - gfx::Transform* transform) { - if (!effect_node) { - // This can happen when PaintArtifactCompositor builds property trees as it - // doesn't set effect ids on clip nodes. - return; - } - DCHECK(effect_node->has_render_surface); - transform->matrix().postScale(effect_node->surface_contents_scale.x(), - effect_node->surface_contents_scale.y(), 1.f); -} - -void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, - gfx::Transform* transform) { - DCHECK(effect_node->has_render_surface); - if (effect_node->surface_contents_scale.x() != 0.0 && - effect_node->surface_contents_scale.y() != 0.0) - transform->Scale(1.0 / effect_node->surface_contents_scale.x(), - 1.0 / effect_node->surface_contents_scale.y()); -} - -void ComputeClips(PropertyTrees* property_trees, - bool non_root_surfaces_enabled) { - ClipTree* clip_tree = &property_trees->clip_tree; - if (!clip_tree->needs_update()) - return; - for (int i = ClipTree::kViewportNodeId; - i < static_cast<int>(clip_tree->size()); ++i) { - ClipNode* clip_node = clip_tree->Node(i); +void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, + const PropertyTrees* property_trees, + std::vector<LayerImpl*>* visible_layer_list) { + const TransformTree& transform_tree = property_trees->transform_tree; + const EffectTree& effect_tree = property_trees->effect_tree; - if (clip_node->id == ClipTree::kViewportNodeId) { - ResetIfHasNanCoordinate(&clip_node->clip); - clip_node->clip_in_target_space = clip_node->clip; - clip_node->combined_clip_in_target_space = clip_node->clip; + for (auto* layer_impl : *layer_tree_impl) { + DCHECK(layer_impl); + DCHECK(layer_impl->layer_tree_impl()); + // TODO(crbug.com/726423) : This is a workaround for crbug.com/725851 to + // avoid crashing when layer_impl is nullptr. This workaround should be + // removed as layer_impl should not be nullptr here. + if (!layer_impl || !layer_impl->HasValidPropertyTreeIndices()) continue; - } - const TransformTree& transform_tree = property_trees->transform_tree; - const EffectTree& effect_tree = property_trees->effect_tree; - const TransformNode* transform_node = - transform_tree.Node(clip_node->transform_id); - ClipNode* parent_clip_node = clip_tree->parent(clip_node); - bool target_is_clipped = - effect_tree.Node(clip_node->target_effect_id)->surface_is_clipped; - - gfx::Transform parent_to_current; - const TransformNode* parent_target_transform_node = - transform_tree.Node(parent_clip_node->target_transform_id); - bool success = true; - - // Clips must be combined in target space. We cannot, for example, combine - // clips in the space of the child clip. The reason is non-affine - // transforms. Say we have the following tree T->A->B->C, and B clips C, but - // draw into target T. It may be the case that A applies a perspective - // transform, and B and C are at different z positions. When projected into - // target space, the relative sizes and positions of B and C can shift. - // Since it's the relationship in target space that matters, that's where we - // must combine clips. For each clip node, we save the clip rects in its - // target space. So, we need to get the ancestor clip rect in the current - // clip node's target space. - gfx::RectF parent_combined_clip_in_target_space = - parent_clip_node->combined_clip_in_target_space; - gfx::RectF parent_clip_in_target_space = - parent_clip_node->clip_in_target_space; - if (parent_target_transform_node && - parent_target_transform_node->id != clip_node->target_transform_id && - non_root_surfaces_enabled) { - success &= property_trees->GetFromTarget( - clip_node->target_transform_id, parent_clip_node->target_effect_id, - &parent_to_current); - const EffectNode* target_effect_node = - effect_tree.Node(clip_node->target_effect_id); - PostConcatSurfaceContentsScale(target_effect_node, &parent_to_current); - // If we can't compute a transform, it's because we had to use the inverse - // of a singular transform. We won't draw in this case, so there's no need - // to compute clips. - if (!success) - continue; - parent_combined_clip_in_target_space = MathUtil::ProjectClippedRect( - parent_to_current, parent_clip_node->combined_clip_in_target_space); - if (clip_node->clip_type == ClipNode::ClipType::EXPANDS_CLIP) { - parent_combined_clip_in_target_space = - gfx::RectF(clip_node->clip_expander->MapRectReverse( - gfx::ToEnclosingRect(parent_combined_clip_in_target_space), - property_trees)); - } - parent_clip_in_target_space = MathUtil::ProjectClippedRect( - parent_to_current, parent_clip_node->clip_in_target_space); - } - // Only nodes affected by ancestor clips will have their clip adjusted due - // to intersecting with an ancestor clip. But, we still need to propagate - // the combined clip to our children because if they are clipped, they may - // need to clip using our parent clip and if we don't propagate it here, - // it will be lost. - if (clip_node->resets_clip && non_root_surfaces_enabled) { - if (clip_node->clip_type == ClipNode::ClipType::APPLIES_LOCAL_CLIP) { - gfx::Transform to_target; - property_trees->GetToTarget(clip_node->transform_id, - clip_node->target_effect_id, &to_target); - clip_node->clip_in_target_space = - MathUtil::MapClippedRect(to_target, clip_node->clip); - ResetIfHasNanCoordinate(&clip_node->clip_in_target_space); - clip_node->combined_clip_in_target_space = - gfx::IntersectRects(clip_node->clip_in_target_space, - parent_combined_clip_in_target_space); - } else { - DCHECK(!target_is_clipped); - DCHECK(!clip_node->layers_are_clipped); - clip_node->combined_clip_in_target_space = - parent_combined_clip_in_target_space; - } - ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space); + if (!IsRootLayer(layer_impl) && + LayerShouldBeSkipped(layer_impl, transform_tree, effect_tree)) continue; - } - bool use_only_parent_clip = - clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP; - if (use_only_parent_clip) { - clip_node->combined_clip_in_target_space = - parent_combined_clip_in_target_space; - if (!non_root_surfaces_enabled) { - clip_node->clip_in_target_space = - parent_clip_node->clip_in_target_space; - } else if (!target_is_clipped) { - clip_node->clip_in_target_space = parent_clip_in_target_space; - } else { - // Render Surface applies clip and the owning layer itself applies - // no clip. So, clip_in_target_space is not used and hence we can set - // it to an empty rect. - clip_node->clip_in_target_space = gfx::RectF(); - } - } else { - gfx::Transform source_to_target; - - if (!non_root_surfaces_enabled) { - source_to_target = transform_tree.ToScreen(clip_node->transform_id); - } else if (transform_tree.ContentTargetId(transform_node->id) == - clip_node->target_transform_id) { - property_trees->GetToTarget(clip_node->transform_id, - clip_node->target_effect_id, - &source_to_target); - } else { - success = property_trees->GetToTarget( - transform_node->id, clip_node->target_effect_id, &source_to_target); - // source_to_target computation should be successful as target is an - // ancestor of the transform node. - DCHECK(success); - } - gfx::RectF source_clip_in_target_space = - MathUtil::MapClippedRect(source_to_target, clip_node->clip); - - // With surfaces disabled, the only case where we use only the local clip - // for layer clipping is the case where no non-viewport ancestor node - // applies a local clip. - bool layer_clipping_uses_only_local_clip = - non_root_surfaces_enabled - ? clip_node->layer_clipping_uses_only_local_clip - : !parent_clip_node->layers_are_clipped_when_surfaces_disabled; - if (!layer_clipping_uses_only_local_clip) { - clip_node->clip_in_target_space = gfx::IntersectRects( - parent_clip_in_target_space, source_clip_in_target_space); - } else { - clip_node->clip_in_target_space = source_clip_in_target_space; - } + bool layer_is_drawn = + effect_tree.Node(layer_impl->effect_tree_index())->is_drawn; - clip_node->combined_clip_in_target_space = gfx::IntersectRects( - parent_combined_clip_in_target_space, source_clip_in_target_space); - } - ResetIfHasNanCoordinate(&clip_node->clip_in_target_space); - ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space); + if (LayerNeedsUpdate(layer_impl, layer_is_drawn, property_trees)) + visible_layer_list->push_back(layer_impl); } - clip_tree->set_needs_update(false); } void ComputeTransforms(TransformTree* transform_tree) { @@ -934,24 +881,6 @@ void ComputeTransforms(TransformTree* transform_tree) { transform_tree->set_needs_update(false); } -void UpdateRenderTarget(EffectTree* effect_tree, - bool can_render_to_separate_surface) { - for (int i = EffectTree::kContentsRootNodeId; - i < static_cast<int>(effect_tree->size()); ++i) { - EffectNode* node = effect_tree->Node(i); - if (i == EffectTree::kContentsRootNodeId) { - // Render target of the node corresponding to root is itself. - node->target_id = EffectTree::kContentsRootNodeId; - } else if (!can_render_to_separate_surface) { - node->target_id = EffectTree::kContentsRootNodeId; - } else if (effect_tree->parent(node)->has_render_surface) { - node->target_id = node->parent_id; - } else { - node->target_id = effect_tree->parent(node)->target_id; - } - } -} - void ComputeEffects(EffectTree* effect_tree) { if (!effect_tree->needs_update()) return; @@ -961,220 +890,62 @@ void ComputeEffects(EffectTree* effect_tree) { effect_tree->set_needs_update(false); } -static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) { - EffectTree* effect_tree = &property_trees->effect_tree; - const ClipTree* clip_tree = &property_trees->clip_tree; - EffectNode* root_effect_node = - effect_tree->Node(EffectTree::kContentsRootNodeId); - const RenderSurfaceImpl* root_render_surface = - effect_tree->GetRenderSurface(EffectTree::kContentsRootNodeId); - gfx::Rect root_clip = - gfx::ToEnclosingRect(clip_tree->Node(root_effect_node->clip_id)->clip); - if (root_render_surface->is_clipped()) - DCHECK(root_clip == root_render_surface->clip_rect()) - << "clip on root render surface: " - << root_render_surface->clip_rect().ToString() - << " v.s. root effect node's clip: " << root_clip.ToString(); - for (int i = 2; i < static_cast<int>(effect_tree->size()); ++i) { - EffectNode* effect_node = effect_tree->Node(i); - const EffectNode* target_node = effect_tree->Node(effect_node->target_id); - bool include_viewport_clip = false; - bool include_expanding_clips = false; - ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - effect_node->clip_id, target_node->id); - gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect; - const RenderSurfaceImpl* render_surface = effect_tree->GetRenderSurface(i); - if (render_surface && render_surface->is_clipped()) { - DCHECK(gfx::ToEnclosingRect(accumulated_clip) == - render_surface->clip_rect()) - << " render surface's clip rect: " - << render_surface->clip_rect().ToString() - << " v.s. accumulated clip: " - << gfx::ToEnclosingRect(accumulated_clip).ToString(); - } - } -} - -static void ComputeLayerClipRect(const PropertyTrees* property_trees, - const LayerImpl* layer) { - const EffectTree* effect_tree = &property_trees->effect_tree; - const ClipTree* clip_tree = &property_trees->clip_tree; - const ClipNode* clip_node = clip_tree->Node(layer->clip_tree_index()); - const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); - const EffectNode* target_node = - effect_node->has_render_surface - ? effect_node - : effect_tree->Node(effect_node->target_id); - // TODO(weiliangc): When effect node has up to date render surface info on - // compositor thread, no need to check for resourceless draw mode - if (!property_trees->non_root_surfaces_enabled) { - target_node = effect_tree->Node(1); - } - - bool include_viewport_clip = false; - bool include_expanding_clips = false; - ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - layer->clip_tree_index(), target_node->id); - - bool is_clipped_from_clip_tree = - property_trees->non_root_surfaces_enabled - ? clip_node->layers_are_clipped - : clip_node->layers_are_clipped_when_surfaces_disabled; - DCHECK_EQ(is_clipped_from_clip_tree, accumulated_clip_rect.is_clipped); - - gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect; - - DCHECK(layer->clip_rect() == gfx::ToEnclosingRect(accumulated_clip)) - << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index() - << " layer clip: " << layer->clip_rect().ToString() << " v.s. " - << gfx::ToEnclosingRect(accumulated_clip).ToString() - << " and clip node clip: " - << gfx::ToEnclosingRect(clip_node->clip_in_target_space).ToString(); -} - -void ComputeVisibleRects(LayerImpl* root_layer, +void UpdatePropertyTrees(LayerTreeHost* layer_tree_host, PropertyTrees* property_trees, - bool can_render_to_separate_surface, - LayerImplList* visible_layer_list) { - bool render_surfaces_need_update = false; + bool can_render_to_separate_surface) { + DCHECK(layer_tree_host); + DCHECK(property_trees); + DCHECK_EQ(layer_tree_host->property_trees(), property_trees); if (property_trees->non_root_surfaces_enabled != can_render_to_separate_surface) { property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; property_trees->transform_tree.set_needs_update(true); - render_surfaces_need_update = true; } if (property_trees->transform_tree.needs_update()) { property_trees->clip_tree.set_needs_update(true); property_trees->effect_tree.set_needs_update(true); } - - if (render_surfaces_need_update) { - property_trees->effect_tree.UpdateRenderSurfaces( - root_layer->layer_tree_impl(), - property_trees->non_root_surfaces_enabled); - } - UpdateRenderTarget(&property_trees->effect_tree, - property_trees->non_root_surfaces_enabled); + UpdateScrollTree(&property_trees->scroll_tree, layer_tree_host); ComputeTransforms(&property_trees->transform_tree); - // Computation of clips uses surface contents scale which is updated while - // computing effects. So, ComputeEffects should be before ComputeClips. ComputeEffects(&property_trees->effect_tree); - ComputeClips(property_trees, can_render_to_separate_surface); - - FindLayersThatNeedUpdates(root_layer->layer_tree_impl(), property_trees, - visible_layer_list); - CalculateClipRects(*visible_layer_list, property_trees, - can_render_to_separate_surface); - CalculateVisibleRects(*visible_layer_list, property_trees, - can_render_to_separate_surface); + // Computation of clips uses ToScreen which is updated while computing + // transforms. So, ComputeTransforms should be before ComputeClips. + ComputeClips(property_trees); } -void UpdatePropertyTrees(PropertyTrees* property_trees, - bool can_render_to_separate_surface) { +void UpdatePropertyTreesAndRenderSurfaces(LayerImpl* root_layer, + PropertyTrees* property_trees, + bool can_render_to_separate_surface, + bool can_adjust_raster_scales) { + bool render_surfaces_need_update = false; if (property_trees->non_root_surfaces_enabled != can_render_to_separate_surface) { property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; property_trees->transform_tree.set_needs_update(true); + render_surfaces_need_update = true; + } + if (property_trees->can_adjust_raster_scales != can_adjust_raster_scales) { + property_trees->can_adjust_raster_scales = can_adjust_raster_scales; + property_trees->transform_tree.set_needs_update(true); + render_surfaces_need_update = true; } if (property_trees->transform_tree.needs_update()) { property_trees->clip_tree.set_needs_update(true); property_trees->effect_tree.set_needs_update(true); } - ComputeTransforms(&property_trees->transform_tree); - // Computation of clips uses surface contents scale which is updated while - // computing effects. So, ComputeEffects should be before ComputeClips. - ComputeEffects(&property_trees->effect_tree); - ComputeClips(property_trees, can_render_to_separate_surface); -} - -void BuildPropertyTreesAndComputeVisibleRects( - LayerImpl* root_layer, - const LayerImpl* page_scale_layer, - const LayerImpl* inner_viewport_scroll_layer, - const LayerImpl* outer_viewport_scroll_layer, - const LayerImpl* overscroll_elasticity_layer, - const gfx::Vector2dF& elastic_overscroll, - float page_scale_factor, - float device_scale_factor, - const gfx::Rect& viewport, - const gfx::Transform& device_transform, - bool can_render_to_separate_surface, - PropertyTrees* property_trees, - LayerImplList* visible_layer_list) { - PropertyTreeBuilder::BuildPropertyTrees( - root_layer, page_scale_layer, inner_viewport_scroll_layer, - outer_viewport_scroll_layer, overscroll_elasticity_layer, - elastic_overscroll, page_scale_factor, device_scale_factor, viewport, - device_transform, property_trees); - ComputeVisibleRects(root_layer, property_trees, - can_render_to_separate_surface, visible_layer_list); -} - -void VerifyClipTreeCalculations(const LayerImplList& layer_list, - PropertyTrees* property_trees) { - if (property_trees->non_root_surfaces_enabled) { - ComputeClipsWithEffectTree(property_trees); - } - for (auto* layer : layer_list) - ComputeLayerClipRect(property_trees, layer); -} - -gfx::Rect ComputeLayerVisibleRectDynamic(const PropertyTrees* property_trees, - const LayerImpl* layer) { - int effect_ancestor_with_copy_request = - property_trees->effect_tree.ClosestAncestorWithCopyRequest( - layer->effect_tree_index()); - bool non_root_copy_request = - effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId; - gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); - gfx::RectF accumulated_clip_in_root_space; - if (non_root_copy_request) { - bool include_viewport_clip = false; - bool include_expanding_clips = true; - ConditionalClip accumulated_clip = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - layer->clip_tree_index(), effect_ancestor_with_copy_request); - if (!accumulated_clip.is_clipped) - return layer_content_rect; - accumulated_clip_in_root_space = accumulated_clip.clip_rect; - } else { - accumulated_clip_in_root_space = - ComputeAccumulatedClipInRootSpaceForVisibleRect( - property_trees, layer->clip_tree_index()); + if (render_surfaces_need_update) { + property_trees->effect_tree.UpdateRenderSurfaces( + root_layer->layer_tree_impl(), + property_trees->non_root_surfaces_enabled); } + UpdateRenderTarget(&property_trees->effect_tree, + property_trees->non_root_surfaces_enabled); - const EffectNode* root_effect_node = - non_root_copy_request - ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request) - : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); - ConditionalClip accumulated_clip_in_layer_space = - ComputeTargetRectInLocalSpace( - accumulated_clip_in_root_space, property_trees, - root_effect_node->transform_id, layer->transform_tree_index(), - root_effect_node->id); - if (!accumulated_clip_in_layer_space.is_clipped) - return layer_content_rect; - gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect; - clip_in_layer_space.Offset(-layer->offset_to_transform_parent()); - - gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space); - visible_rect.Intersect(layer_content_rect); - return visible_rect; -} - -void VerifyVisibleRectsCalculations(const LayerImplList& layer_list, - const PropertyTrees* property_trees) { - for (auto* layer : layer_list) { - gfx::Rect visible_rect_dynamic = - ComputeLayerVisibleRectDynamic(property_trees, layer); - DCHECK(layer->visible_layer_rect() == visible_rect_dynamic) - << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index() - << " visible rect cached: " << layer->visible_layer_rect().ToString() - << " v.s. " - << " visible rect dynamic: " << visible_rect_dynamic.ToString(); - } + ComputeTransforms(&property_trees->transform_tree); + ComputeEffects(&property_trees->effect_tree); + // Computation of clips uses ToScreen which is updated while computing + // transforms. So, ComputeTransforms should be before ComputeClips. + ComputeClips(property_trees); } bool LayerNeedsUpdate(Layer* layer, @@ -1209,88 +980,6 @@ gfx::Transform DrawTransform(const LayerImpl* layer, return xform; } -static void SetSurfaceDrawTransform(const PropertyTrees* property_trees, - RenderSurfaceImpl* render_surface) { - const TransformTree& transform_tree = property_trees->transform_tree; - const EffectTree& effect_tree = property_trees->effect_tree; - const TransformNode* transform_node = - transform_tree.Node(render_surface->TransformTreeIndex()); - const EffectNode* effect_node = - effect_tree.Node(render_surface->EffectTreeIndex()); - // The draw transform of root render surface is identity tranform. - if (transform_node->id == TransformTree::kRootNodeId) { - render_surface->SetDrawTransform(gfx::Transform()); - return; - } - - gfx::Transform render_surface_transform; - const EffectNode* target_effect_node = - effect_tree.Node(effect_node->target_id); - property_trees->GetToTarget(transform_node->id, target_effect_node->id, - &render_surface_transform); - - ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform); - render_surface->SetDrawTransform(render_surface_transform); -} - -static void SetSurfaceClipRect(const ClipNode* parent_clip_node, - const PropertyTrees* property_trees, - RenderSurfaceImpl* render_surface) { - if (!render_surface->is_clipped()) { - render_surface->SetClipRect(gfx::Rect()); - return; - } - - const EffectTree& effect_tree = property_trees->effect_tree; - const TransformTree& transform_tree = property_trees->transform_tree; - const TransformNode* transform_node = - transform_tree.Node(render_surface->TransformTreeIndex()); - if (transform_tree.TargetId(transform_node->id) == - parent_clip_node->target_transform_id) { - render_surface->SetClipRect( - gfx::ToEnclosingRect(parent_clip_node->clip_in_target_space)); - return; - } - - // In this case, the clip child has reset the clip node for subtree and hence - // the parent clip node's clip rect is in clip parent's target space and not - // our target space. We need to transform it to our target space. - gfx::Transform clip_parent_target_to_target; - const EffectNode* effect_node = - effect_tree.Node(render_surface->EffectTreeIndex()); - int target_effect_id = effect_node->target_id; - const bool success = property_trees->GetToTarget( - parent_clip_node->target_transform_id, target_effect_id, - &clip_parent_target_to_target); - - if (!success) { - render_surface->SetClipRect(gfx::Rect()); - return; - } - - if (parent_clip_node->target_transform_id < - transform_tree.TargetId(transform_node->id)) { - render_surface->SetClipRect(gfx::ToEnclosingRect( - MathUtil::ProjectClippedRect(clip_parent_target_to_target, - parent_clip_node->clip_in_target_space))); - } else { - render_surface->SetClipRect(gfx::ToEnclosingRect(MathUtil::MapClippedRect( - clip_parent_target_to_target, parent_clip_node->clip_in_target_space))); - } -} - -template <typename LayerType> -static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer, - const TransformTree& tree) { - gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), - layer->offset_to_transform_parent().y()); - gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index()); - xform.ConcatTransform(ssxform); - if (layer->should_flatten_transform_from_property_tree()) - xform.FlattenTo2d(); - return xform; -} - gfx::Transform ScreenSpaceTransform(const Layer* layer, const TransformTree& tree) { return ScreenSpaceTransformInternal(layer, tree); @@ -1301,81 +990,68 @@ gfx::Transform ScreenSpaceTransform(const LayerImpl* layer, return ScreenSpaceTransformInternal(layer, tree); } -static float LayerDrawOpacity(const LayerImpl* layer, const EffectTree& tree) { - if (!layer->render_target()) - return 0.f; - - const EffectNode* target_node = - tree.Node(layer->render_target()->EffectTreeIndex()); - const EffectNode* node = tree.Node(layer->effect_tree_index()); - if (node == target_node) - return 1.f; - - float draw_opacity = 1.f; - while (node != target_node) { - draw_opacity *= tree.EffectiveOpacity(node); - node = tree.parent(node); +void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, + PropertyTrees* property_trees) { + // Compute transforms + for (LayerImpl* layer : *layer_list) { + const TransformNode* transform_node = + property_trees->transform_tree.Node(layer->transform_tree_index()); + + layer->draw_properties().screen_space_transform = + ScreenSpaceTransformInternal(layer, property_trees->transform_tree); + layer->draw_properties().target_space_transform = DrawTransform( + layer, property_trees->transform_tree, property_trees->effect_tree); + layer->draw_properties().screen_space_transform_is_animating = + transform_node->to_screen_is_potentially_animated; } - return draw_opacity; -} -static void SetSurfaceDrawOpacity(const EffectTree& tree, - RenderSurfaceImpl* render_surface) { - // Draw opacity of a surface is the product of opacities between the surface - // (included) and its target surface (excluded). - const EffectNode* node = tree.Node(render_surface->EffectTreeIndex()); - float draw_opacity = tree.EffectiveOpacity(node); - for (node = tree.parent(node); node && !node->has_render_surface; - node = tree.parent(node)) { - draw_opacity *= tree.EffectiveOpacity(node); + // Compute effects and determine if render surfaces have contributing layers + // that escape clip. + for (LayerImpl* layer : *layer_list) { + layer->draw_properties().opacity = + LayerDrawOpacity(layer, property_trees->effect_tree); + RenderSurfaceImpl* render_target = layer->render_target(); + int lca_clip_id = LowestCommonAncestor(layer->clip_tree_index(), + render_target->ClipTreeIndex(), + &property_trees->clip_tree); + if (lca_clip_id != render_target->ClipTreeIndex()) { + SetHasContributingLayerThatEscapesClip(lca_clip_id, + render_target->EffectTreeIndex(), + &property_trees->effect_tree); + } } - render_surface->SetDrawOpacity(draw_opacity); -} -static gfx::Rect LayerDrawableContentRect( - const LayerImpl* layer, - const gfx::Rect& layer_bounds_in_target_space, - const gfx::Rect& clip_rect) { - if (layer->is_clipped()) - return IntersectRects(layer_bounds_in_target_space, clip_rect); - - return layer_bounds_in_target_space; -} - -void ComputeLayerDrawProperties(LayerImpl* layer, - const PropertyTrees* property_trees) { - const TransformNode* transform_node = - property_trees->transform_tree.Node(layer->transform_tree_index()); - const ClipNode* clip_node = - property_trees->clip_tree.Node(layer->clip_tree_index()); - - layer->draw_properties().screen_space_transform = - ScreenSpaceTransformInternal(layer, property_trees->transform_tree); - layer->draw_properties().target_space_transform = DrawTransform( - layer, property_trees->transform_tree, property_trees->effect_tree); - layer->draw_properties().screen_space_transform_is_animating = - transform_node->to_screen_is_potentially_animated; - - layer->draw_properties().opacity = - LayerDrawOpacity(layer, property_trees->effect_tree); - if (property_trees->non_root_surfaces_enabled) { - layer->draw_properties().is_clipped = clip_node->layers_are_clipped; - } else { - layer->draw_properties().is_clipped = - clip_node->layers_are_clipped_when_surfaces_disabled; + // Compute clips and visible rects + for (LayerImpl* layer : *layer_list) { + ConditionalClip clip = LayerClipRect(property_trees, layer); + // is_clipped should be set before visible rect computation as it is used + // there. + layer->draw_properties().is_clipped = clip.is_clipped; + layer->draw_properties().clip_rect = gfx::ToEnclosingRect(clip.clip_rect); + layer->draw_properties().visible_layer_rect = + LayerVisibleRect(property_trees, layer); } - gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( - layer->draw_properties().target_space_transform, - gfx::Rect(layer->bounds())); - layer->draw_properties().drawable_content_rect = LayerDrawableContentRect( - layer, bounds_in_target_space, layer->draw_properties().clip_rect); + // Compute drawable content rects + for (LayerImpl* layer : *layer_list) { + gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( + layer->draw_properties().target_space_transform, + gfx::Rect(layer->bounds())); + layer->draw_properties().drawable_content_rect = LayerDrawableContentRect( + layer, bounds_in_target_space, layer->draw_properties().clip_rect); + } } void ComputeMaskDrawProperties(LayerImpl* mask_layer, const PropertyTrees* property_trees) { // Mask draw properties are used only for rastering, so most of the draw // properties computed for other layers are not needed. + // Draw transform of a mask layer has to be a 2d scale. + // TODO(sunxd): the draw transform of a mask layer misses the "scale to fit" + // factor from mask layer to its parent. So does the screen space transform. + // It does not cause a problem because currently we only have 1:1 mask layer. + mask_layer->draw_properties().target_space_transform = DrawTransform( + mask_layer, property_trees->transform_tree, property_trees->effect_tree); mask_layer->draw_properties().screen_space_transform = ScreenSpaceTransformInternal(mask_layer, property_trees->transform_tree); @@ -1383,11 +1059,10 @@ void ComputeMaskDrawProperties(LayerImpl* mask_layer, gfx::Rect(mask_layer->bounds()); } -void ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, - RenderSurfaceImpl* render_surface) { - const EffectNode* effect_node = - property_trees->effect_tree.Node(render_surface->EffectTreeIndex()); - render_surface->SetIsClipped(effect_node->surface_is_clipped); +void ComputeSurfaceDrawProperties(PropertyTrees* property_trees, + RenderSurfaceImpl* render_surface, + const bool use_layer_lists) { + SetSurfaceIsClipped(property_trees->clip_tree, render_surface); SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); SetSurfaceDrawTransform(property_trees, render_surface); render_surface->SetScreenSpaceTransform( @@ -1400,52 +1075,6 @@ void ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, SetSurfaceClipRect(clip_node, property_trees, render_surface); } -#if DCHECK_IS_ON() -static void ValidatePageScaleLayer(const Layer* page_scale_layer) { - DCHECK_EQ(page_scale_layer->position().ToString(), gfx::PointF().ToString()); - DCHECK_EQ(page_scale_layer->transform_origin().ToString(), - gfx::Point3F().ToString()); -} - -static void ValidatePageScaleLayer(const LayerImpl* page_scale_layer) {} -#endif - -template <typename LayerType> -static void UpdatePageScaleFactorInternal(PropertyTrees* property_trees, - const LayerType* page_scale_layer, - float page_scale_factor, - float device_scale_factor, - gfx::Transform device_transform) { - if (property_trees->transform_tree.page_scale_factor() == page_scale_factor) - return; - - property_trees->transform_tree.set_page_scale_factor(page_scale_factor); - DCHECK(page_scale_layer); - DCHECK_GE(page_scale_layer->transform_tree_index(), - TransformTree::kRootNodeId); - TransformNode* node = property_trees->transform_tree.Node( - page_scale_layer->transform_tree_index()); - // TODO(enne): property trees can't ask the layer these things, but - // the page scale layer should *just* be the page scale. -#if DCHECK_IS_ON() - ValidatePageScaleLayer(page_scale_layer); -#endif - - if (IsRootLayer(page_scale_layer)) { - // When the page scale layer is also the root layer, the node should also - // store the combined scale factor and not just the page scale factor. - float post_local_scale_factor = page_scale_factor * device_scale_factor; - node->post_local_scale_factor = post_local_scale_factor; - node->post_local = device_transform; - node->post_local.Scale(post_local_scale_factor, post_local_scale_factor); - } else { - node->post_local_scale_factor = page_scale_factor; - node->update_post_local_transform(gfx::PointF(), gfx::Point3F()); - } - node->needs_local_transform_update = true; - property_trees->transform_tree.set_needs_update(true); -} - void UpdatePageScaleFactor(PropertyTrees* property_trees, const LayerImpl* page_scale_layer, float page_scale_factor, @@ -1466,26 +1095,6 @@ void UpdatePageScaleFactor(PropertyTrees* property_trees, device_transform); } -template <typename LayerType> -static void UpdateElasticOverscrollInternal( - PropertyTrees* property_trees, - const LayerType* overscroll_elasticity_layer, - const gfx::Vector2dF& elastic_overscroll) { - if (!overscroll_elasticity_layer) { - DCHECK(elastic_overscroll.IsZero()); - return; - } - - TransformNode* node = property_trees->transform_tree.Node( - overscroll_elasticity_layer->transform_tree_index()); - if (node->scroll_offset == gfx::ScrollOffset(elastic_overscroll)) - return; - - node->scroll_offset = gfx::ScrollOffset(elastic_overscroll); - node->needs_local_transform_update = true; - property_trees->transform_tree.set_needs_update(true); -} - void UpdateElasticOverscroll(PropertyTrees* property_trees, const LayerImpl* overscroll_elasticity_layer, const gfx::Vector2dF& elastic_overscroll) { diff --git a/chromium/cc/trees/draw_property_utils.h b/chromium/cc/trees/draw_property_utils.h index 4f19d144f88..b5ff981c579 100644 --- a/chromium/cc/trees/draw_property_utils.h +++ b/chromium/cc/trees/draw_property_utils.h @@ -5,11 +5,10 @@ #ifndef CC_TREES_DRAW_PROPERTY_UTILS_H_ #define CC_TREES_DRAW_PROPERTY_UTILS_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_collections.h" namespace gfx { -class Rect; class Transform; class Vector2dF; } // namespace gfx @@ -19,6 +18,7 @@ namespace cc { class Layer; class LayerImpl; class LayerTreeHost; +class LayerTreeImpl; class RenderSurfaceImpl; class EffectTree; class TransformTree; @@ -27,15 +27,8 @@ struct EffectNode; namespace draw_property_utils { -void CC_EXPORT PostConcatSurfaceContentsScale(const EffectNode* effect_node, - gfx::Transform* transform); - void CC_EXPORT ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, gfx::Transform* transform); -// Computes combined clips for every node in |clip_tree|. This function requires -// that |transform_tree| has been updated via |ComputeTransforms|. -void CC_EXPORT ComputeClips(PropertyTrees* property_trees, - bool non_root_surfaces_enabled); // Computes combined (screen space) transforms for every node in the transform // tree. This must be done prior to calling |ComputeClips|. @@ -44,48 +37,36 @@ void CC_EXPORT ComputeTransforms(TransformTree* transform_tree); // Computes screen space opacity for every node in the opacity tree. void CC_EXPORT ComputeEffects(EffectTree* effect_tree); -void CC_EXPORT BuildPropertyTreesAndComputeVisibleRects( - LayerImpl* root_layer, - const LayerImpl* page_scale_layer, - const LayerImpl* inner_viewport_scroll_layer, - const LayerImpl* outer_viewport_scroll_layer, - const LayerImpl* overscroll_elasticity_layer, - const gfx::Vector2dF& elastic_overscroll, - float page_scale_factor, - float device_scale_factor, - const gfx::Rect& viewport, - const gfx::Transform& device_transform, - bool can_render_to_separate_surface, - PropertyTrees* property_trees, - LayerImplList* visible_layer_list); - -void CC_EXPORT UpdatePropertyTrees(PropertyTrees* property_trees, + +void CC_EXPORT UpdatePropertyTrees(LayerTreeHost* layer_tree_host, + PropertyTrees* property_trees, bool can_render_to_separate_surface); +void CC_EXPORT +UpdatePropertyTreesAndRenderSurfaces(LayerImpl* root_layer, + PropertyTrees* property_trees, + bool can_render_to_separate_surface, + bool can_adjust_raster_scales); + void CC_EXPORT FindLayersThatNeedUpdates(LayerTreeHost* layer_tree_host, const PropertyTrees* property_trees, LayerList* update_layer_list); -void CC_EXPORT ComputeVisibleRects(LayerImpl* root_layer, - PropertyTrees* property_trees, - bool can_render_to_separate_surface, - LayerImplList* visible_layer_list); - -gfx::Rect CC_EXPORT -ComputeLayerVisibleRectDynamic(const PropertyTrees* property_trees, - const LayerImpl* layer); void CC_EXPORT -VerifyVisibleRectsCalculations(const LayerImplList& layer_list, - const PropertyTrees* property_trees); +FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, + const PropertyTrees* property_trees, + std::vector<LayerImpl*>* visible_layer_list); -void CC_EXPORT ComputeLayerDrawProperties(LayerImpl* layer, - const PropertyTrees* property_trees); +void CC_EXPORT +ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, + PropertyTrees* property_trees); void CC_EXPORT ComputeMaskDrawProperties(LayerImpl* mask_layer, const PropertyTrees* property_trees); -void CC_EXPORT ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, - RenderSurfaceImpl* render_surface); +void CC_EXPORT ComputeSurfaceDrawProperties(PropertyTrees* property_trees, + RenderSurfaceImpl* render_surface, + const bool use_layer_lists); bool CC_EXPORT LayerShouldBeSkipped(LayerImpl* layer, const TransformTree& transform_tree, @@ -99,9 +80,6 @@ bool CC_EXPORT LayerNeedsUpdate(LayerImpl* layer, bool layer_is_drawn, const PropertyTrees* property_trees); -void CC_EXPORT VerifyClipTreeCalculations(const LayerImplList& layer_list, - PropertyTrees* property_trees); - gfx::Transform CC_EXPORT DrawTransform(const LayerImpl* layer, const TransformTree& transform_tree, const EffectTree& effect_tree); diff --git a/chromium/cc/trees/effect_node.cc b/chromium/cc/trees/effect_node.cc index 5385b35286c..142cb08db41 100644 --- a/chromium/cc/trees/effect_node.cc +++ b/chromium/cc/trees/effect_node.cc @@ -17,7 +17,6 @@ EffectNode::EffectNode() screen_space_opacity(1.f), blend_mode(SkBlendMode::kSrcOver), has_render_surface(false), - surface_is_clipped(false), has_copy_request(false), hidden_by_backface_visibility(false), double_sided(false), @@ -29,7 +28,6 @@ EffectNode::EffectNode() is_currently_animating_opacity(false), effect_changed(false), num_copy_requests_in_subtree(0), - has_unclipped_descendants(false), transform_id(0), clip_id(0), target_id(1), @@ -42,7 +40,6 @@ bool EffectNode::operator==(const EffectNode& other) const { owning_layer_id == other.owning_layer_id && opacity == other.opacity && screen_space_opacity == other.screen_space_opacity && has_render_surface == other.has_render_surface && - surface_is_clipped == other.surface_is_clipped && has_copy_request == other.has_copy_request && filters == other.filters && background_filters == other.background_filters && @@ -72,7 +69,6 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const { value->SetInteger("owning_layer_id", owning_layer_id); value->SetDouble("opacity", opacity); value->SetBoolean("has_render_surface", has_render_surface); - value->SetBoolean("surface_is_clipped", surface_is_clipped); value->SetBoolean("has_copy_request", has_copy_request); value->SetBoolean("double_sided", double_sided); value->SetBoolean("is_drawn", is_drawn); diff --git a/chromium/cc/trees/effect_node.h b/chromium/cc/trees/effect_node.h index a5a1385de5b..48997c03823 100644 --- a/chromium/cc/trees/effect_node.h +++ b/chromium/cc/trees/effect_node.h @@ -5,8 +5,8 @@ #ifndef CC_TREES_EFFECT_NODE_H_ #define CC_TREES_EFFECT_NODE_H_ -#include "cc/base/cc_export.h" -#include "cc/output/filter_operations.h" +#include "cc/base/filter_operations.h" +#include "cc/cc_export.h" #include "third_party/skia/include/core/SkBlendMode.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size_f.h" @@ -44,13 +44,6 @@ struct CC_EXPORT EffectNode { gfx::Size unscaled_mask_target_size; bool has_render_surface; - // Only applicable if has render surface. A true value means a clip needs to - // be applied to the output of the surface when it is drawn onto its parent - // surface. - // TODO(crbug.com/504464): There is ongoing work to delay render surface - // decision to later phase of the pipeline. This flag shall be removed and - // computed during render surface decision. - bool surface_is_clipped; bool has_copy_request; bool hidden_by_backface_visibility; bool double_sided; @@ -66,7 +59,6 @@ struct CC_EXPORT EffectNode { // rect. bool effect_changed; int num_copy_requests_in_subtree; - bool has_unclipped_descendants; int transform_id; int clip_id; // Effect node id of which this effect contributes to. diff --git a/chromium/cc/trees/element_id.h b/chromium/cc/trees/element_id.h index 4c0b652cc88..74de4c9995f 100644 --- a/chromium/cc/trees/element_id.h +++ b/chromium/cc/trees/element_id.h @@ -13,7 +13,7 @@ #include <memory> #include "base/hash.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { class Value; diff --git a/chromium/cc/debug/frame_rate_counter.cc b/chromium/cc/trees/frame_rate_counter.cc index c523f6d8e99..f801dbf640d 100644 --- a/chromium/cc/debug/frame_rate_counter.cc +++ b/chromium/cc/trees/frame_rate_counter.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/debug/frame_rate_counter.h" +#include "cc/trees/frame_rate_counter.h" #include <stddef.h> @@ -11,7 +11,6 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" -#include "cc/trees/proxy.h" namespace cc { @@ -62,16 +61,11 @@ void FrameRateCounter::SaveTimeStamp(base::TimeTicks timestamp, bool software) { if (software) { UMA_HISTOGRAM_CUSTOM_COUNTS( "Renderer4.SoftwareCompositorThreadImplDrawDelay", - frame_interval_seconds.InMilliseconds(), - 1, - 120, - 60); + frame_interval_seconds.InMilliseconds(), 1, 120, 60); } else { UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CompositorThreadImplDrawDelay", - frame_interval_seconds.InMilliseconds(), - 1, - 120, - 60); + frame_interval_seconds.InMilliseconds(), 1, + 120, 60); } } @@ -129,8 +123,7 @@ double FrameRateCounter::GetAverageFPS() const { // IsBadFrameInterval encapsulates the frame too slow/frame too fast logic. for (RingBufferType::Iterator it = --ring_buffer_.End(); - it && frame_times_total < 1.0; - --it) { + it && frame_times_total < 1.0; --it) { base::TimeDelta delta = RecentFrameInterval(it.index() + 1); if (!IsBadFrameInterval(delta)) { diff --git a/chromium/cc/debug/frame_rate_counter.h b/chromium/cc/trees/frame_rate_counter.h index ba2d122cf1d..83e8cf7151f 100644 --- a/chromium/cc/debug/frame_rate_counter.h +++ b/chromium/cc/trees/frame_rate_counter.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_DEBUG_FRAME_RATE_COUNTER_H_ -#define CC_DEBUG_FRAME_RATE_COUNTER_H_ +#ifndef CC_TREES_FRAME_RATE_COUNTER_H_ +#define CC_TREES_FRAME_RATE_COUNTER_H_ #include <stddef.h> @@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/time/time.h" -#include "cc/debug/ring_buffer.h" +#include "cc/base/ring_buffer.h" namespace cc { @@ -57,4 +57,4 @@ class FrameRateCounter { } // namespace cc -#endif // CC_DEBUG_FRAME_RATE_COUNTER_H_ +#endif // CC_TREES_FRAME_RATE_COUNTER_H_ diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index 942d5938681..e8a6f4b0c07 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -29,19 +29,18 @@ #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/base/histograms.h" #include "cc/base/math_util.h" -#include "cc/debug/devtools_instrumentation.h" -#include "cc/debug/frame_viewer_instrumentation.h" #include "cc/debug/rendering_stats_instrumentation.h" #include "cc/input/layer_selection_bound.h" #include "cc/input/page_scale_animation.h" #include "cc/layers/heads_up_display_layer.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer.h" -#include "cc/layers/layer_iterator.h" #include "cc/layers/painted_scrollbar_layer.h" #include "cc/resources/ui_resource_manager.h" +#include "cc/tiles/frame_viewer_instrumentation.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host_client.h" @@ -161,6 +160,8 @@ void LayerTreeHost::InitializeProxy(std::unique_ptr<Proxy> proxy) { proxy_ = std::move(proxy); proxy_->Start(); + UpdateDeferCommitsInternal(); + mutator_host_->SetSupportsScrollAnimations(proxy_->SupportsImplScrolling()); } @@ -315,6 +316,11 @@ void LayerTreeHost::FinishCommitOnImplThread( sync_tree->SetDeviceScaleFactor(device_scale_factor_); host_impl->SetDebugState(debug_state_); + if (did_navigate_) { + did_navigate_ = false; + host_impl->ClearImageCacheOnNavigation(); + } + sync_tree->set_ui_resource_request_queue( ui_resource_manager_->TakeUIResourcesRequests()); @@ -340,6 +346,11 @@ void LayerTreeHost::FinishCommitOnImplThread( mutator_host_->PushPropertiesTo(host_impl->mutator_host()); } + // Transfer image decode requests to the impl thread. + for (auto& request : queued_image_decodes_) + host_impl->QueueImageDecode(std::move(request.first), request.second); + queued_image_decodes_.clear(); + micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl); property_trees_.ResetAllChangeTracking(); } @@ -349,7 +360,12 @@ void LayerTreeHost::WillCommit() { client_->WillCommit(); } -void LayerTreeHost::UpdateHudLayer() {} + +void LayerTreeHost::UpdateDeferCommitsInternal() { + proxy_->SetDeferCommits(defer_commits_ || + (settings_.enable_surface_synchronization && + !local_surface_id_.is_valid())); +} void LayerTreeHost::CommitComplete() { source_frame_number_++; @@ -427,7 +443,10 @@ void LayerTreeHost::DidLoseCompositorFrameSink() { } void LayerTreeHost::SetDeferCommits(bool defer_commits) { - proxy_->SetDeferCommits(defer_commits); + if (defer_commits_ == defer_commits) + return; + defer_commits_ = defer_commits; + UpdateDeferCommitsInternal(); } DISABLE_CFI_PERF @@ -464,9 +483,9 @@ void LayerTreeHost::SetNextCommitWaitsForActivation() { proxy_->SetNextCommitWaitsForActivation(); } -void LayerTreeHost::SetNextCommitForcesRedraw() { +void LayerTreeHost::SetNeedsCommitWithForcedRedraw() { next_commit_forces_redraw_ = true; - proxy_->SetNeedsUpdateLayers(); + proxy_->SetNeedsCommit(); } void LayerTreeHost::SetAnimationEvents( @@ -581,7 +600,7 @@ bool LayerTreeHost::UpdateLayers() { ->Add(timer.Elapsed().InMicroseconds()); } - return result || next_commit_forces_redraw_; + return result; } void LayerTreeHost::DidCompletePageScaleAnimation() { @@ -630,7 +649,6 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { "source_frame_number", SourceFrameNumber()); UpdateHudLayer(debug_state_.ShowHudInfo()); - UpdateHudLayer(); Layer* root_scroll = PropertyTreeBuilder::FindFirstScrollableLayer(root_layer); @@ -641,6 +659,16 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { if (hud_layer_) { hud_layer_->PrepareForCalculateDrawProperties(device_viewport_size_, device_scale_factor_); + // The HUD layer is managed outside the layer list sent to LayerTreeHost + // and needs to have its property tree state set. + if (settings_.use_layer_lists && root_layer_.get()) { + hud_layer_->SetTransformTreeIndex(root_layer_->transform_tree_index()); + hud_layer_->SetEffectTreeIndex(root_layer_->effect_tree_index()); + hud_layer_->SetClipTreeIndex(root_layer_->clip_tree_index()); + hud_layer_->SetScrollTreeIndex(root_layer_->scroll_tree_index()); + hud_layer_->set_property_tree_sequence_number( + root_layer_->property_tree_sequence_number()); + } } gfx::Transform identity_transform; @@ -654,7 +682,6 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { TRACE_EVENT0( TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), "LayerTreeHostInProcessCommon::ComputeVisibleRectsWithPropertyTrees"); - PropertyTreeBuilder::PreCalculateMetaInformation(root_layer); bool can_render_to_separate_surface = true; PropertyTrees* property_trees = &property_trees_; if (!settings_.use_layer_lists) { @@ -675,7 +702,7 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { TRACE_EVENT_SCOPE_THREAD, "property_trees", property_trees->AsTracedValue()); } - draw_property_utils::UpdatePropertyTrees(property_trees, + draw_property_utils::UpdatePropertyTrees(this, property_trees, can_render_to_separate_surface); draw_property_utils::FindLayersThatNeedUpdates(this, property_trees, &update_layer_list); @@ -732,6 +759,16 @@ void LayerTreeHost::ApplyViewportDeltas(ScrollAndScaleSet* info) { SetNeedsUpdateLayers(); } +void LayerTreeHost::RecordWheelAndTouchScrollingCount(ScrollAndScaleSet* info) { + bool has_scrolled_by_wheel = info->has_scrolled_by_wheel; + bool has_scrolled_by_touch = info->has_scrolled_by_touch; + + if (has_scrolled_by_wheel || has_scrolled_by_touch) { + client_->RecordWheelAndTouchScrollingCount(has_scrolled_by_wheel, + has_scrolled_by_touch); + } +} + void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) { for (auto& swap_promise : info->swap_promises) { TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow", @@ -762,6 +799,8 @@ void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) { // controls from clamping the layout viewport both on the compositor and // on the main thread. ApplyViewportDeltas(info); + + RecordWheelAndTouchScrollingCount(info); } const base::WeakPtr<InputHandler>& LayerTreeHost::GetInputHandler() @@ -839,6 +878,7 @@ void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) { ResetGpuRasterizationTracking(); SetNeedsFullTreeSync(); + did_navigate_ = true; } void LayerTreeHost::RegisterViewportLayers( @@ -964,11 +1004,11 @@ void LayerTreeHost::SetPaintedDeviceScaleFactor( SetNeedsCommit(); } -void LayerTreeHost::SetDeviceColorSpace( - const gfx::ColorSpace& device_color_space) { - if (device_color_space_ == device_color_space) +void LayerTreeHost::SetRasterColorSpace( + const gfx::ColorSpace& raster_color_space) { + if (raster_color_space_ == raster_color_space) return; - device_color_space_ = device_color_space; + raster_color_space_ = raster_color_space; LayerTreeHostCommon::CallFunctionForEveryLayer( this, [](Layer* layer) { layer->SetNeedsDisplay(); }); } @@ -980,6 +1020,14 @@ void LayerTreeHost::SetContentSourceId(uint32_t id) { SetNeedsCommit(); } +void LayerTreeHost::SetLocalSurfaceId(const LocalSurfaceId& local_surface_id) { + if (local_surface_id_ == local_surface_id) + return; + local_surface_id_ = local_surface_id; + UpdateDeferCommitsInternal(); + SetNeedsCommit(); +} + void LayerTreeHost::RegisterLayer(Layer* layer) { DCHECK(!LayerById(layer->id())); DCHECK(!in_paint_layer_contents_); @@ -1038,10 +1086,6 @@ bool LayerTreeHost::LayerNeedsPushPropertiesForTesting(Layer* layer) const { layers_that_should_push_properties_.end(); } -void LayerTreeHost::SetNeedsMetaInfoRecomputation(bool needs_recomputation) { - needs_meta_info_recomputation_ = needs_recomputation; -} - void LayerTreeHost::SetPageScaleFromImplSide(float page_scale) { DCHECK(CommitRequested()); page_scale_factor_ = page_scale; @@ -1070,8 +1114,6 @@ void LayerTreeHost::UpdateHudLayer(bool show_hud_info) { void LayerTreeHost::SetNeedsFullTreeSync() { needs_full_tree_sync_ = true; - needs_meta_info_recomputation_ = true; - property_trees_.needs_rebuild = true; SetNeedsCommit(); } @@ -1148,10 +1190,12 @@ void LayerTreeHost::PushPropertiesTo(LayerTreeImpl* tree_impl) { tree_impl->set_painted_device_scale_factor(painted_device_scale_factor_); - tree_impl->SetDeviceColorSpace(device_color_space_); + tree_impl->SetRasterColorSpace(raster_color_space_); tree_impl->set_content_source_id(content_source_id_); + tree_impl->set_local_surface_id(local_surface_id_); + if (pending_page_scale_animation_) { tree_impl->SetPendingPageScaleAnimation( std::move(pending_page_scale_animation_)); @@ -1196,7 +1240,6 @@ void LayerTreeHost::SetElementIdsForTesting() { } void LayerTreeHost::BuildPropertyTreesForTesting() { - PropertyTreeBuilder::PreCalculateMetaInformation(root_layer()); gfx::Transform identity_transform; PropertyTreeBuilder::BuildPropertyTrees( root_layer(), page_scale_layer(), inner_viewport_scroll_layer(), @@ -1235,12 +1278,10 @@ void LayerTreeHost::SetElementOpacityMutated(ElementId element_id, DCHECK_LE(opacity, 1.f); layer->OnOpacityAnimated(opacity); - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, - layer->id())) { - DCHECK_EQ(layer->effect_tree_index(), - property_trees_.layer_id_to_effect_node_index[layer->id()]); - EffectNode* node = - property_trees_.effect_tree.Node(layer->effect_tree_index()); + if (EffectNode* node = + property_trees_.effect_tree.UpdateNodeFromOwningLayerId( + layer->id())) { + DCHECK_EQ(layer->effect_tree_index(), node->id); if (node->opacity == opacity) return; @@ -1259,12 +1300,10 @@ void LayerTreeHost::SetElementTransformMutated( DCHECK(layer); layer->OnTransformAnimated(transform); - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - layer->id())) { - DCHECK_EQ(layer->transform_tree_index(), - property_trees_.layer_id_to_transform_node_index[layer->id()]); - TransformNode* node = - property_trees_.transform_tree.Node(layer->transform_tree_index()); + if (TransformNode* node = + property_trees_.transform_tree.UpdateNodeFromOwningLayerId( + layer->id())) { + DCHECK_EQ(layer->transform_tree_index(), node->id); if (node->local == transform) return; @@ -1291,9 +1330,79 @@ void LayerTreeHost::ElementIsAnimatingChanged( ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) { - Layer* layer = LayerByElementId(element_id); - if (layer) - layer->OnIsAnimatingChanged(mask, state); + // TODO(weiliangc): Most of the code is duplicated with LayerTeeHostImpl + // version of function. Should try to share code. + DCHECK_EQ(ElementListType::ACTIVE, list_type); + + for (int property = TargetProperty::FIRST_TARGET_PROPERTY; + property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) { + if (!mask.currently_running[property] && + !mask.potentially_animating[property]) + continue; + + switch (property) { + case TargetProperty::TRANSFORM: + if (TransformNode* transform_node = + property_trees()->transform_tree.FindNodeFromElementId( + element_id)) { + if (mask.currently_running[property]) + transform_node->is_currently_animating = + state.currently_running[property]; + if (mask.potentially_animating[property]) { + transform_node->has_potential_animation = + state.potentially_animating[property]; + transform_node->has_only_translation_animations = + mutator_host()->HasOnlyTranslationTransforms(element_id, + list_type); + property_trees()->transform_tree.set_needs_update(true); + } + } else { + if (state.currently_running[property] || + state.potentially_animating[property]) + DCHECK(property_trees()->needs_rebuild) + << "Attempting to animate non existent transform node"; + } + break; + case TargetProperty::OPACITY: + if (EffectNode* effect_node = + property_trees()->effect_tree.FindNodeFromElementId( + element_id)) { + if (mask.currently_running[property]) + effect_node->is_currently_animating_opacity = + state.currently_running[property]; + if (mask.potentially_animating[property]) { + effect_node->has_potential_opacity_animation = + state.potentially_animating[property]; + property_trees()->effect_tree.set_needs_update(true); + } + } else { + if (state.currently_running[property] || + state.potentially_animating[property]) + DCHECK(property_trees()->needs_rebuild) + << "Attempting to animate opacity on non existent effect node"; + } + break; + case TargetProperty::FILTER: + if (EffectNode* effect_node = + property_trees()->effect_tree.FindNodeFromElementId( + element_id)) { + if (mask.currently_running[property]) + effect_node->is_currently_animating_filter = + state.currently_running[property]; + if (mask.potentially_animating[property]) + effect_node->has_potential_filter_animation = + state.potentially_animating[property]; + } else { + if (state.currently_running[property] || + state.potentially_animating[property]) + DCHECK(property_trees()->needs_rebuild) + << "Attempting to animate filter on non existent effect node"; + } + break; + default: + break; + } + } } gfx::ScrollOffset LayerTreeHost::GetScrollOffsetForAnimation( @@ -1303,6 +1412,14 @@ gfx::ScrollOffset LayerTreeHost::GetScrollOffsetForAnimation( return layer->ScrollOffsetForAnimation(); } +void LayerTreeHost::QueueImageDecode( + sk_sp<const SkImage> image, + const base::Callback<void(bool)>& callback) { + TRACE_EVENT0("cc", "LayerTreeHost::QueueImageDecode"); + queued_image_decodes_.emplace_back(std::move(image), callback); + SetNeedsCommit(); +} + LayerListIterator<Layer> LayerTreeHost::begin() const { return LayerListIterator<Layer>(root_layer_.get()); } diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index 9a5deabf7aa..bf5520e2a39 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -20,9 +20,9 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" -#include "cc/debug/micro_benchmark.h" -#include "cc/debug/micro_benchmark_controller.h" +#include "cc/benchmarks/micro_benchmark.h" +#include "cc/benchmarks/micro_benchmark_controller.h" +#include "cc/cc_export.h" #include "cc/input/browser_controls_state.h" #include "cc/input/event_listener_properties.h" #include "cc/input/input_handler.h" @@ -45,6 +45,8 @@ #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/rect.h" +class SkImage; + namespace cc { class HeadsUpDisplayLayer; class Layer; @@ -191,7 +193,7 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), // Requests a main frame (including layer updates) and ensures that this main // frame results in a redraw for the complete viewport when producing the // CompositorFrame. - void SetNextCommitForcesRedraw(); + void SetNeedsCommitWithForcedRedraw(); // Input Handling --------------------------------------------- @@ -312,9 +314,14 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), void SetContentSourceId(uint32_t); uint32_t content_source_id() const { return content_source_id_; } - void SetDeviceColorSpace(const gfx::ColorSpace& device_color_space); - const gfx::ColorSpace& device_color_space() const { - return device_color_space_; + // If this LayerTreeHost needs a valid LocalSurfaceId then commits will be + // deferred until a valid LocalSurfaceId is provided. + void SetLocalSurfaceId(const LocalSurfaceId& local_surface_id); + const LocalSurfaceId& local_surface_id() const { return local_surface_id_; } + + void SetRasterColorSpace(const gfx::ColorSpace& raster_color_space); + const gfx::ColorSpace& raster_color_space() const { + return raster_color_space_; } // Used externally by blink for setting the PropertyTrees when @@ -339,12 +346,6 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), std::unordered_set<Layer*>& LayersThatShouldPushProperties(); bool LayerNeedsPushPropertiesForTesting(Layer* layer) const; - virtual void SetNeedsMetaInfoRecomputation( - bool needs_meta_info_recomputation); - bool needs_meta_info_recomputation() const { - return needs_meta_info_recomputation_; - } - void SetPageScaleFromImplSide(float page_scale); void SetElasticOverscrollFromImplSide(gfx::Vector2dF elastic_overscroll); gfx::Vector2dF elastic_overscroll() const { return elastic_overscroll_; } @@ -457,6 +458,9 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), gfx::ScrollOffset GetScrollOffsetForAnimation( ElementId element_id) const override; + void QueueImageDecode(sk_sp<const SkImage> image, + const base::Callback<void(bool)>& callback); + protected: LayerTreeHost(InitParams* params, CompositorMode mode); @@ -496,15 +500,13 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), enum { kNumFramesToConsiderBeforeGpuRasterization = 60 }; void ApplyViewportDeltas(ScrollAndScaleSet* info); + void RecordWheelAndTouchScrollingCount(ScrollAndScaleSet* info); void ApplyPageScaleDeltaFromImplSide(float page_scale_delta); void InitializeProxy(std::unique_ptr<Proxy> proxy); bool DoUpdateLayers(Layer* root_layer); - void UpdateHudLayer(); - - bool AnimateLayersRecursive(Layer* current, base::TimeTicks time); - void CalculateLCDTextMetricsCallback(Layer* layer); + void UpdateDeferCommitsInternal(); const CompositorMode compositor_mode_; @@ -571,9 +573,11 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), float page_scale_factor_ = 1.f; float min_page_scale_factor_ = 1.f; float max_page_scale_factor_ = 1.f; - gfx::ColorSpace device_color_space_; + gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; + LocalSurfaceId local_surface_id_; + bool defer_commits_ = false; SkColor background_color_ = SK_ColorWHITE; bool has_transparent_background_ = false; @@ -591,7 +595,6 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), PropertyTrees property_trees_; bool needs_full_tree_sync_ = true; - bool needs_meta_info_recomputation_ = true; gfx::Vector2dF elastic_overscroll_; @@ -610,6 +613,11 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), MutatorHost* mutator_host_; + std::vector<std::pair<sk_sp<const SkImage>, base::Callback<void(bool)>>> + queued_image_decodes_; + + bool did_navigate_ = false; + DISALLOW_COPY_AND_ASSIGN(LayerTreeHost); }; diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h index c0fcb4bef14..84416d60ef0 100644 --- a/chromium/cc/trees/layer_tree_host_client.h +++ b/chromium/cc/trees/layer_tree_host_client.h @@ -43,6 +43,9 @@ class LayerTreeHostClient { const gfx::Vector2dF& elastic_overscroll_delta, float page_scale, float top_controls_delta) = 0; + virtual void RecordWheelAndTouchScrollingCount( + bool has_scrolled_by_wheel, + bool has_scrolled_by_touch) = 0; // Request an CompositorFrameSink from the client. When the client has one it // should call LayerTreeHost::SetCompositorFrameSink. This will result in // either DidFailToInitializeCompositorFrameSink or @@ -55,6 +58,10 @@ class LayerTreeHostClient { virtual void DidCommitAndDrawFrame() = 0; virtual void DidReceiveCompositorFrameAck() = 0; virtual void DidCompletePageScaleAnimation() = 0; + // The only time a subframe ever gets its own LayerTree is when the subframe + // renders in a different process its ancestors; this returns true in + // that case. + virtual bool IsForSubframe() = 0; protected: virtual ~LayerTreeHostClient() {} diff --git a/chromium/cc/trees/layer_tree_host_common.cc b/chromium/cc/trees/layer_tree_host_common.cc index 2e4ded747af..8d09c07ec1d 100644 --- a/chromium/cc/trees/layer_tree_host_common.cc +++ b/chromium/cc/trees/layer_tree_host_common.cc @@ -14,7 +14,6 @@ #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" -#include "cc/layers/layer_iterator.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" @@ -80,8 +79,7 @@ LayerTreeHostCommon::CalcDrawPropsImplInputs::CalcDrawPropsImplInputs( int max_texture_size, bool can_render_to_separate_surface, bool can_adjust_raster_scales, - bool verify_clip_tree_calculations, - bool verify_visible_rect_calculations, + bool use_layer_lists, LayerImplList* render_surface_layer_list, PropertyTrees* property_trees) : root_layer(root_layer), @@ -98,8 +96,7 @@ LayerTreeHostCommon::CalcDrawPropsImplInputs::CalcDrawPropsImplInputs( max_texture_size(max_texture_size), can_render_to_separate_surface(can_render_to_separate_surface), can_adjust_raster_scales(can_adjust_raster_scales), - verify_clip_tree_calculations(verify_clip_tree_calculations), - verify_visible_rect_calculations(verify_visible_rect_calculations), + use_layer_lists(use_layer_lists), render_surface_layer_list(render_surface_layer_list), property_trees(property_trees) {} @@ -122,8 +119,7 @@ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting:: std::numeric_limits<int>::max() / 2, true, false, - true, - true, + false, render_surface_layer_list, GetPropertyTrees(root_layer)) { DCHECK(root_layer); @@ -183,8 +179,10 @@ bool LayerTreeHostCommon::ScrollbarsUpdateInfo::operator==( } ScrollAndScaleSet::ScrollAndScaleSet() - : page_scale_delta(1.f), top_controls_delta(0.f) { -} + : page_scale_delta(1.f), + top_controls_delta(0.f), + has_scrolled_by_wheel(false), + has_scrolled_by_touch(false) {} ScrollAndScaleSet::~ScrollAndScaleSet() {} @@ -286,11 +284,23 @@ static void ComputeInitialRenderSurfaceLayerList( LayerTreeImpl* layer_tree_impl, PropertyTrees* property_trees, LayerImplList* render_surface_layer_list, - bool can_render_to_separate_surface) { + bool can_render_to_separate_surface, + bool use_layer_lists) { // Add all non-skipped surfaces to the initial render surface layer list. Add // all non-skipped layers to the layer list of their target surface, and // add their content rect to their target surface's accumulated content rect. for (LayerImpl* layer : *layer_tree_impl) { + DCHECK(layer); + + // TODO(crbug.com/726423): LayerImpls should never have invalid PropertyTree + // indices. + if (!layer) + continue; + + layer->set_is_drawn_render_surface_layer_list_member(false); + if (!layer->HasValidPropertyTreeIndices()) + continue; + RenderSurfaceImpl* render_surface = layer->GetRenderSurface(); if (render_surface) { render_surface->ClearLayerLists(); @@ -326,8 +336,8 @@ static void ComputeInitialRenderSurfaceLayerList( contributes_to_drawn_surface); } - draw_property_utils::ComputeSurfaceDrawProperties(property_trees, - render_surface); + draw_property_utils::ComputeSurfaceDrawProperties( + property_trees, render_surface, use_layer_lists); // Ignore occlusion from outside the surface when surface contents need to // be fully drawn. Layers with copy-request need to be complete. We could @@ -437,6 +447,7 @@ static void CalculateRenderSurfaceLayerList( PropertyTrees* property_trees, LayerImplList* render_surface_layer_list, const bool can_render_to_separate_surface, + const bool use_layer_lists, const int max_texture_size) { // This calculates top level Render Surface Layer List, and Layer List for all // Render Surfaces. @@ -447,9 +458,9 @@ static void CalculateRenderSurfaceLayerList( // First compute an RSLL that might include surfaces that later turn out to // have an empty content rect. After surface content rects are computed, // produce a final RSLL that omits empty surfaces. - ComputeInitialRenderSurfaceLayerList(layer_tree_impl, property_trees, - &initial_render_surface_list, - can_render_to_separate_surface); + ComputeInitialRenderSurfaceLayerList( + layer_tree_impl, property_trees, &initial_render_surface_list, + can_render_to_separate_surface, use_layer_lists); ComputeSurfaceContentRects(layer_tree_impl, property_trees, &initial_render_surface_list, max_texture_size); ComputeListOfNonEmptySurfaces(layer_tree_impl, property_trees, @@ -477,15 +488,18 @@ void CalculateDrawPropertiesInternal( "LayerTreeHostCommon::ComputeVisibleRectsWithPropertyTrees"); } - draw_property_utils::BuildPropertyTreesAndComputeVisibleRects( + PropertyTreeBuilder::BuildPropertyTrees( inputs->root_layer, inputs->page_scale_layer, inputs->inner_viewport_scroll_layer, inputs->outer_viewport_scroll_layer, inputs->elastic_overscroll_application_layer, inputs->elastic_overscroll, inputs->page_scale_factor, inputs->device_scale_factor, gfx::Rect(inputs->device_viewport_size), - inputs->device_transform, inputs->can_render_to_separate_surface, - inputs->property_trees, &visible_layer_list); + inputs->device_transform, inputs->property_trees); + draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( + inputs->root_layer, inputs->property_trees, + inputs->can_render_to_separate_surface, + inputs->can_adjust_raster_scales); // Property trees are normally constructed on the main thread and // passed to compositor thread. Source to parent updates on them are not @@ -529,9 +543,10 @@ void CalculateDrawPropertiesInternal( property_trees->transform_tree.SetRootTransformsAndScales( inputs->device_scale_factor, page_scale_factor_for_root, inputs->device_transform, inputs->root_layer->position()); - draw_property_utils::ComputeVisibleRects( + draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( inputs->root_layer, inputs->property_trees, - inputs->can_render_to_separate_surface, &visible_layer_list); + inputs->can_render_to_separate_surface, + inputs->can_adjust_raster_scales); break; } } @@ -541,24 +556,18 @@ void CalculateDrawPropertiesInternal( "LayerTreeHostCommon::CalculateDrawProperties"); } + draw_property_utils::FindLayersThatNeedUpdates( + inputs->root_layer->layer_tree_impl(), inputs->property_trees, + &visible_layer_list); DCHECK(inputs->can_render_to_separate_surface == inputs->property_trees->non_root_surfaces_enabled); - for (LayerImpl* layer : visible_layer_list) { - draw_property_utils::ComputeLayerDrawProperties(layer, - inputs->property_trees); - } + draw_property_utils::ComputeDrawPropertiesOfVisibleLayers( + &visible_layer_list, inputs->property_trees); CalculateRenderSurfaceLayerList( inputs->root_layer->layer_tree_impl(), inputs->property_trees, inputs->render_surface_layer_list, inputs->can_render_to_separate_surface, - inputs->max_texture_size); - - if (inputs->verify_clip_tree_calculations) - draw_property_utils::VerifyClipTreeCalculations(visible_layer_list, - inputs->property_trees); - if (inputs->verify_visible_rect_calculations) - draw_property_utils::VerifyVisibleRectsCalculations(visible_layer_list, - inputs->property_trees); + inputs->use_layer_lists, inputs->max_texture_size); if (should_measure_property_tree_performance) { TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), @@ -585,8 +594,9 @@ void LayerTreeHostCommon::CalculateDrawPropertiesForTesting( inputs->page_scale_factor, inputs->device_scale_factor, gfx::Rect(inputs->device_viewport_size), inputs->device_transform, property_trees); - draw_property_utils::UpdatePropertyTrees(property_trees, - can_render_to_separate_surface); + draw_property_utils::UpdatePropertyTrees( + inputs->root_layer->layer_tree_host(), property_trees, + can_render_to_separate_surface); draw_property_utils::FindLayersThatNeedUpdates( inputs->root_layer->layer_tree_host(), property_trees, &update_layer_list); @@ -641,8 +651,6 @@ void LayerTreeHostCommon::CalculateDrawProperties( void LayerTreeHostCommon::CalculateDrawPropertiesForTesting( CalcDrawPropsImplInputsForTesting* inputs) { - PropertyTreeBuilder::PreCalculateMetaInformationForTesting( - inputs->root_layer); CalculateDrawPropertiesInternal(inputs, BUILD_PROPERTY_TREES_IF_NEEDED); } diff --git a/chromium/cc/trees/layer_tree_host_common.h b/chromium/cc/trees/layer_tree_host_common.h index de96d955c5a..dd668caa88e 100644 --- a/chromium/cc/trees/layer_tree_host_common.h +++ b/chromium/cc/trees/layer_tree_host_common.h @@ -13,7 +13,7 @@ #include "base/bind.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/layers/layer_collections.h" #include "cc/layers/layer_impl.h" @@ -74,8 +74,7 @@ class CC_EXPORT LayerTreeHostCommon { int max_texture_size, bool can_render_to_separate_surface, bool can_adjust_raster_scales, - bool verify_clip_tree_calculations, - bool verify_visible_rect_calculations, + bool use_layer_lists, LayerImplList* render_surface_layer_list, PropertyTrees* property_trees); @@ -92,8 +91,7 @@ class CC_EXPORT LayerTreeHostCommon { int max_texture_size; bool can_render_to_separate_surface; bool can_adjust_raster_scales; - bool verify_clip_tree_calculations; - bool verify_visible_rect_calculations; + bool use_layer_lists; LayerImplList* render_surface_layer_list; PropertyTrees* property_trees; }; @@ -177,6 +175,8 @@ struct CC_EXPORT ScrollAndScaleSet { float top_controls_delta; std::vector<LayerTreeHostCommon::ScrollbarsUpdateInfo> scrollbars; std::vector<std::unique_ptr<SwapPromise>> swap_promises; + bool has_scrolled_by_wheel; + bool has_scrolled_by_touch; private: DISALLOW_COPY_AND_ASSIGN(ScrollAndScaleSet); diff --git a/chromium/cc/trees/layer_tree_host_common_perftest.cc b/chromium/cc/trees/layer_tree_host_common_perftest.cc index 132872c5a67..89946eea48a 100644 --- a/chromium/cc/trees/layer_tree_host_common_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_common_perftest.cc @@ -14,7 +14,7 @@ #include "base/strings/string_piece.h" #include "base/threading/thread.h" #include "base/time/time.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/layers/layer.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -114,9 +114,8 @@ class CalcDrawPropsTest : public LayerTreeHostCommonPerfTest { active_tree->elastic_overscroll()->Current(active_tree->IsActiveTree()), active_tree->OverscrollElasticityLayer(), max_texture_size, can_render_to_separate_surface, + false, // don't use layer lists for perf tests host_impl->settings().layer_transforms_should_scale_layer_contents, - false, // do not verify_clip_tree_calculation for perf tests - false, // do not verify_visible_rect_calculation for perf tests &update_list, active_tree->property_trees()); LayerTreeHostCommon::CalculateDrawProperties(&inputs); } diff --git a/chromium/cc/trees/layer_tree_host_common_unittest.cc b/chromium/cc/trees/layer_tree_host_common_unittest.cc index 45782b01bf6..e6f69f6dd99 100644 --- a/chromium/cc/trees/layer_tree_host_common_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_common_unittest.cc @@ -20,10 +20,10 @@ #include "cc/base/math_util.h" #include "cc/input/main_thread_scrolling_reason.h" #include "cc/layers/content_layer_client.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/layers/layer.h" #include "cc/layers/layer_client.h" #include "cc/layers/layer_impl.h" -#include "cc/layers/layer_iterator.h" #include "cc/layers/render_surface_impl.h" #include "cc/layers/texture_layer_impl.h" #include "cc/output/copy_output_request.h" @@ -62,7 +62,6 @@ namespace { class VerifyTreeCalcsLayerTreeSettings : public LayerTreeSettings { public: VerifyTreeCalcsLayerTreeSettings() { - verify_clip_tree_calculations = true; } }; @@ -104,8 +103,6 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { Layer* page_scale_layer, Layer* inner_viewport_scroll_layer, Layer* outer_viewport_scroll_layer) { - PropertyTreeBuilder::PreCalculateMetaInformation(root_layer); - EXPECT_TRUE(page_scale_layer || (page_scale_factor == 1.f)); gfx::Size device_viewport_size = gfx::Size(root_layer->bounds().width() * device_scale_factor, @@ -124,14 +121,12 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } - void ExecuteCalculateDrawProperties( - LayerImpl* root_layer, - float device_scale_factor, - float page_scale_factor, - LayerImpl* page_scale_layer, - LayerImpl* inner_viewport_scroll_layer, - LayerImpl* outer_viewport_scroll_layer, - bool skip_verify_visible_rect_calculations = false) { + void ExecuteCalculateDrawProperties(LayerImpl* root_layer, + float device_scale_factor, + float page_scale_factor, + LayerImpl* page_scale_layer, + LayerImpl* inner_viewport_scroll_layer, + LayerImpl* outer_viewport_scroll_layer) { if (device_scale_factor != root_layer->layer_tree_impl()->device_scale_factor()) root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true; @@ -158,8 +153,6 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { inputs.inner_viewport_scroll_layer = inner_viewport_scroll_layer; inputs.outer_viewport_scroll_layer = outer_viewport_scroll_layer; inputs.can_adjust_raster_scales = true; - if (skip_verify_visible_rect_calculations) - inputs.verify_visible_rect_calculations = false; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } @@ -189,8 +182,6 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { void ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(Layer* root_layer) { DCHECK(root_layer->layer_tree_host()); - PropertyTreeBuilder::PreCalculateMetaInformation(root_layer); - bool can_render_to_separate_surface = true; const Layer* page_scale_layer = @@ -216,26 +207,25 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { outer_viewport_scroll_layer, overscroll_elasticity_layer, elastic_overscroll, page_scale_factor, device_scale_factor, gfx::Rect(device_viewport_size), gfx::Transform(), property_trees); - draw_property_utils::UpdatePropertyTrees(property_trees, + draw_property_utils::UpdatePropertyTrees(root_layer->layer_tree_host(), + property_trees, can_render_to_separate_surface); draw_property_utils::FindLayersThatNeedUpdates( root_layer->layer_tree_host(), property_trees, &update_layer_list_); } void ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList( - LayerImpl* root_layer, - bool skip_verify_visible_rect_calculations = false) { + LayerImpl* root_layer) { DCHECK(root_layer->layer_tree_impl()); - PropertyTreeBuilder::PreCalculateMetaInformationForTesting(root_layer); - bool can_render_to_separate_surface = true; + bool can_adjust_raster_scales = true; - LayerImpl* page_scale_layer = nullptr; + const LayerImpl* page_scale_layer = nullptr; LayerImpl* inner_viewport_scroll_layer = root_layer->layer_tree_impl()->InnerViewportScrollLayer(); LayerImpl* outer_viewport_scroll_layer = root_layer->layer_tree_impl()->OuterViewportScrollLayer(); - LayerImpl* overscroll_elasticity_layer = + const LayerImpl* overscroll_elasticity_layer = root_layer->layer_tree_impl()->OverscrollElasticityLayer(); gfx::Vector2dF elastic_overscroll = root_layer->layer_tree_impl()->elastic_overscroll()->Current( @@ -249,18 +239,19 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { root_layer->layer_tree_impl()->BuildLayerListForTesting(); PropertyTrees* property_trees = root_layer->layer_tree_impl()->property_trees(); - draw_property_utils::BuildPropertyTreesAndComputeVisibleRects( + PropertyTreeBuilder::BuildPropertyTrees( root_layer, page_scale_layer, inner_viewport_scroll_layer, outer_viewport_scroll_layer, overscroll_elasticity_layer, elastic_overscroll, page_scale_factor, device_scale_factor, - gfx::Rect(device_viewport_size), gfx::Transform(), - can_render_to_separate_surface, property_trees, + gfx::Rect(device_viewport_size), gfx::Transform(), property_trees); + draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( + root_layer, property_trees, can_render_to_separate_surface, + can_adjust_raster_scales); + draw_property_utils::FindLayersThatNeedUpdates( + root_layer->layer_tree_impl(), property_trees, update_layer_list_impl_.get()); - draw_property_utils::VerifyClipTreeCalculations(*update_layer_list_impl_, - property_trees); - if (!skip_verify_visible_rect_calculations) - draw_property_utils::VerifyVisibleRectsCalculations( - *update_layer_list_impl_, property_trees); + draw_property_utils::ComputeDrawPropertiesOfVisibleLayers( + update_layer_list_impl(), property_trees); } void ExecuteCalculateDrawPropertiesWithoutSeparateSurfaces( @@ -279,6 +270,22 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } + void ExecuteCalculateDrawPropertiesWithoutAdjustingRasterScales( + LayerImpl* root_layer) { + gfx::Size device_viewport_size = + gfx::Size(root_layer->bounds().width(), root_layer->bounds().height()); + render_surface_layer_list_impl_.reset(new LayerImplList); + + DCHECK(!root_layer->bounds().IsEmpty()); + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root_layer, device_viewport_size, + render_surface_layer_list_impl_.get()); + inputs.can_render_to_separate_surface = true; + inputs.can_adjust_raster_scales = false; + + LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); + } + bool UpdateLayerListImplContains(int id) const { for (auto* layer : *update_layer_list_impl_) { if (layer->id() == id) @@ -1125,18 +1132,16 @@ TEST_F(LayerTreeHostCommonTest, LayerFullyContainedWithinClipInTargetSpace) { LayerImpl* page_scale_layer = nullptr; LayerImpl* inner_viewport_scroll_layer = nullptr; LayerImpl* outer_viewport_scroll_layer = nullptr; - // Visible rects computed by combining clips in target space and root space - // don't match because of rotation transforms. So, we skip - // verify_visible_rect_calculations. - bool skip_verify_visible_rect_calculations = true; ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor, page_scale_layer, inner_viewport_scroll_layer, - outer_viewport_scroll_layer, - skip_verify_visible_rect_calculations); + outer_viewport_scroll_layer); - // Mapping grand_child's bounds to target space produces a non-empty rect - // that is fully contained within the target's bounds, so grand_child should - // be considered fully visible. + // Mapping grand_child's bounds to screen space produces an empty rect, but + // only because it is turned sideways. The entire rect is contained inside + // the clip, and is only empty so long as the numerical precision of the + // transform is effectively perfect. Currently we do the calculation the + // other way around, and the Projection of the screen space clip into layer + // space includes the entire bounds. EXPECT_EQ(gfx::Rect(grand_child->bounds()), grand_child->visible_layer_rect()); } @@ -1434,6 +1439,7 @@ TEST_F(LayerTreeHostCommonTest, render_surface1->test_properties()->background_filters = filters; child->SetBounds(gfx::Size(10, 10)); child->SetDrawsContent(true); + root->layer_tree_impl()->SetElementIdsForTesting(); { LayerImplList render_surface_layer_list; @@ -1455,10 +1461,9 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_TRUE(node->is_drawn); // When root is transparent, the layer should not be drawn. - effect_tree.OnOpacityAnimated(0.f, root->effect_tree_index(), - root->layer_tree_impl()); - effect_tree.OnOpacityAnimated(1.f, render_surface1->effect_tree_index(), - root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(root->element_id(), 0.f); + root->layer_tree_impl()->SetOpacityMutated(render_surface1->element_id(), + 1.f); render_surface1->set_visible_layer_rect(gfx::Rect()); { LayerImplList render_surface_layer_list; @@ -1575,13 +1580,11 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceForBlendMode) { ExecuteCalculateDrawProperties(root); // Since the child layer has a blend mode other than normal, it should get - // its own render surface. Also, layer's draw_properties should contain the - // default blend mode, since the render surface becomes responsible for - // applying the blend mode. + // its own render surface. ASSERT_TRUE(child->GetRenderSurface()); EXPECT_EQ(1.0f, child->draw_opacity()); EXPECT_EQ(0.5f, child->GetRenderSurface()->draw_opacity()); - EXPECT_EQ(SkBlendMode::kSrcOver, child->draw_blend_mode()); + EXPECT_EQ(SkBlendMode::kMultiply, child->GetRenderSurface()->BlendMode()); } TEST_F(LayerTreeHostCommonTest, RenderSurfaceDrawOpacity) { @@ -2552,7 +2555,6 @@ TEST_F(LayerTreeHostCommonTest, AnimationsForRenderSurfaceHierarchy) { gfx::Point3F(0.25f, 0.f, 0.f); root->layer_tree_impl()->BuildLayerListAndPropertyTreesForTesting(); - SetElementIdsForTesting(); // Put an animated opacity on the render surface. AddOpacityTransitionToElementWithPlayer( @@ -2966,6 +2968,21 @@ TEST_F(LayerTreeHostCommonDrawRectsTest, drawing_layer->drawable_content_rect()); } +static bool ProjectionClips(const gfx::Transform& map_transform, + const gfx::RectF& mapped_rect) { + gfx::Transform inverse(Inverse(map_transform)); + bool clipped = false; + if (!clipped) + MathUtil::ProjectPoint(inverse, mapped_rect.top_right(), &clipped); + if (!clipped) + MathUtil::ProjectPoint(inverse, mapped_rect.origin(), &clipped); + if (!clipped) + MathUtil::ProjectPoint(inverse, mapped_rect.bottom_right(), &clipped); + if (!clipped) + MathUtil::ProjectPoint(inverse, mapped_rect.bottom_left(), &clipped); + return clipped; +} + TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsForPerspectiveUnprojection) { // To determine visible rect in layer space, there needs to be an // un-projection from surface space to layer space. When the original @@ -2988,12 +3005,9 @@ TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsForPerspectiveUnprojection) { // Sanity check that un-projection does indeed cause w < 0, otherwise this // code is not testing the intended scenario. - bool clipped; gfx::RectF clipped_rect = MathUtil::MapClippedRect( layer_to_surface_transform, gfx::RectF(layer_content_rect)); - MathUtil::ProjectQuad( - Inverse(layer_to_surface_transform), gfx::QuadF(clipped_rect), &clipped); - ASSERT_TRUE(clipped); + ASSERT_TRUE(ProjectionClips(layer_to_surface_transform, clipped_rect)); // Only the corner of the layer is not visible on the surface because of being // clipped. But, the net result of rounding visible region to an axis-aligned @@ -4011,7 +4025,8 @@ TEST_F(LayerTreeHostCommonTest, TEST_F(LayerTreeHostCommonTest, ClipRectOfSurfaceWhoseParentIsAClipChild) { LayerImpl* root = root_layer_for_testing(); LayerImpl* clip_parent = AddChildToRoot<LayerImpl>(); - LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_parent); + LayerImpl* clip_layer = AddChild<LayerImpl>(clip_parent); + LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_layer); LayerImpl* clip_child = AddChild<LayerImpl>(render_surface1); LayerImpl* render_surface2 = AddChild<LayerImpl>(clip_child); @@ -4023,6 +4038,8 @@ TEST_F(LayerTreeHostCommonTest, ClipRectOfSurfaceWhoseParentIsAClipChild) { base::MakeUnique<std::set<LayerImpl*>>(); clip_parent->test_properties()->clip_children->insert(clip_child); + clip_layer->SetBounds(gfx::Size(50, 50)); + render_surface1->SetBounds(gfx::Size(20, 20)); render_surface1->SetDrawsContent(true); render_surface1->test_properties()->force_render_surface = true; @@ -4036,11 +4053,17 @@ TEST_F(LayerTreeHostCommonTest, ClipRectOfSurfaceWhoseParentIsAClipChild) { render_surface2->test_properties()->force_render_surface = true; clip_parent->SetMasksToBounds(true); + clip_layer->SetMasksToBounds(true); render_surface1->SetMasksToBounds(true); - ExecuteCalculateDrawProperties(root); + float device_scale_factor = 1.f; + ExecuteCalculateDrawProperties(root, device_scale_factor); EXPECT_EQ(gfx::Rect(50, 50), render_surface2->GetRenderSurface()->clip_rect()); + device_scale_factor = 2.f; + ExecuteCalculateDrawProperties(root, device_scale_factor); + EXPECT_EQ(gfx::Rect(100, 100), + render_surface2->GetRenderSurface()->clip_rect()); } TEST_F(LayerTreeHostCommonTest, RenderSurfaceContentRectWhenLayerNotDrawn) { @@ -5055,7 +5078,6 @@ TEST_F(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) { scoped_refptr<AnimationTimeline> timeline = AnimationTimeline::Create(AnimationIdProvider::NextTimelineId()); host_impl.animation_host()->AddAnimationTimeline(timeline); - host_impl.pending_tree()->SetElementIdsForTesting(); ElementId child_element_id = host_impl.pending_tree()->LayerById(child_id)->element_id(); @@ -5723,7 +5745,7 @@ TEST_F(LayerTreeHostCommonTest, TransformedClipParent) { clip_child->test_properties()->clip_parent = clip_parent; std::unique_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>); clip_children->insert(clip_child); - clip_parent->test_properties()->clip_children.reset(clip_children.release()); + clip_parent->test_properties()->clip_children = std::move(clip_children); intervening->SetMasksToBounds(true); clip_parent->SetMasksToBounds(true); @@ -5812,37 +5834,40 @@ TEST_F(LayerTreeHostCommonTest, ClipParentWithInterveningRenderSurface) { EXPECT_TRUE(render_surface1->GetRenderSurface()); EXPECT_TRUE(render_surface2->GetRenderSurface()); - // Since the render surfaces could have expanded, they should not clip (their - // bounds would no longer be reliable). We should resort to layer clipping - // in this case. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), + // render_surface1 should apply the clip from clip_parent. Though there is a + // clip child, render_surface1 can apply the clip as there are no clips + // between the clip parent and render_surface1 + EXPECT_EQ(gfx::Rect(1, 1, 40, 40), render_surface1->GetRenderSurface()->clip_rect()); - EXPECT_FALSE(render_surface1->GetRenderSurface()->is_clipped()); + EXPECT_TRUE(render_surface1->GetRenderSurface()->is_clipped()); + EXPECT_EQ(gfx::Rect(), render_surface1->clip_rect()); + EXPECT_FALSE(render_surface1->is_clipped()); + + // render_surface2 could have expanded, as there is a clip between + // clip_child's clip (clip_parent) and render_surface2's clip (intervening). + // So, it should not be clipped (their bounds would no longer be reliable). + // We should resort to layer clipping in this case. EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface2->GetRenderSurface()->clip_rect()); EXPECT_FALSE(render_surface2->GetRenderSurface()->is_clipped()); - // NB: clip rects are in target space. - EXPECT_EQ(gfx::Rect(0, 0, 40, 40), render_surface1->clip_rect()); - EXPECT_TRUE(render_surface1->is_clipped()); - // This value is inherited from the clipping ancestor layer, 'intervening'. EXPECT_EQ(gfx::Rect(0, 0, 5, 5), render_surface2->clip_rect()); EXPECT_TRUE(render_surface2->is_clipped()); - // The content rects of both render surfaces should both have expanded to - // contain the clip child. + // The content rects of render_surface2 should have expanded to contain the + // clip child. EXPECT_EQ(gfx::Rect(0, 0, 40, 40), render_surface1->GetRenderSurface()->content_rect()); - EXPECT_EQ(gfx::Rect(-1, -1, 40, 40), + EXPECT_EQ(gfx::Rect(-10, -10, 60, 60), render_surface2->GetRenderSurface()->content_rect()); // The clip child should have inherited the clip parent's clip (projected to - // the right space, of course), and should have the correctly sized visible - // content rect. - EXPECT_EQ(gfx::Rect(-1, -1, 40, 40), clip_child->clip_rect()); + // the right space, of course), but as render_surface1 already applies that + // clip, clip_child need not apply it again. + EXPECT_EQ(gfx::Rect(), clip_child->clip_rect()); EXPECT_EQ(gfx::Rect(9, 9, 40, 40), clip_child->visible_layer_rect()); - EXPECT_TRUE(clip_child->is_clipped()); + EXPECT_FALSE(clip_child->is_clipped()); } TEST_F(LayerTreeHostCommonTest, ClipParentScrolledInterveningLayer) { @@ -5895,37 +5920,39 @@ TEST_F(LayerTreeHostCommonTest, ClipParentScrolledInterveningLayer) { EXPECT_TRUE(render_surface1->GetRenderSurface()); EXPECT_TRUE(render_surface2->GetRenderSurface()); - // Since the render surfaces could have expanded, they should not clip (their - // bounds would no longer be reliable). We should resort to layer clipping - // in this case. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), + // render_surface1 should apply the clip from clip_parent. Though there is a + // clip child, render_surface1 can apply the clip as there are no clips + // between the clip parent and render_surface1 + EXPECT_EQ(gfx::Rect(3, 3, 40, 40), render_surface1->GetRenderSurface()->clip_rect()); - EXPECT_FALSE(render_surface1->GetRenderSurface()->is_clipped()); + EXPECT_TRUE(render_surface1->GetRenderSurface()->is_clipped()); + EXPECT_EQ(gfx::Rect(), render_surface1->clip_rect()); + EXPECT_FALSE(render_surface1->is_clipped()); + + // render_surface2 could have expanded, as there is a clip between + // clip_child's clip (clip_parent) and render_surface2's clip (intervening). + // So, it should not be clipped (their bounds would no longer be reliable). + // We should resort to layer clipping in this case. EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface2->GetRenderSurface()->clip_rect()); EXPECT_FALSE(render_surface2->GetRenderSurface()->is_clipped()); - - // NB: clip rects are in target space. - EXPECT_EQ(gfx::Rect(0, 0, 40, 40), render_surface1->clip_rect()); - EXPECT_TRUE(render_surface1->is_clipped()); - // This value is inherited from the clipping ancestor layer, 'intervening'. - EXPECT_EQ(gfx::Rect(2, 2, 3, 3), render_surface2->clip_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 5, 5), render_surface2->clip_rect()); EXPECT_TRUE(render_surface2->is_clipped()); - // The content rects of both render surfaces should both have expanded to - // contain the clip child. + // The content rects of render_surface2 should have expanded to contain the + // clip child. EXPECT_EQ(gfx::Rect(0, 0, 40, 40), render_surface1->GetRenderSurface()->content_rect()); - EXPECT_EQ(gfx::Rect(2, 2, 40, 40), + EXPECT_EQ(gfx::Rect(-10, -10, 60, 60), render_surface2->GetRenderSurface()->content_rect()); // The clip child should have inherited the clip parent's clip (projected to - // the right space, of course), and should have the correctly sized visible - // content rect. - EXPECT_EQ(gfx::Rect(2, 2, 40, 40), clip_child->clip_rect()); + // the right space, of course), but as render_surface1 already applies that + // clip, clip_child need not apply it again. + EXPECT_EQ(gfx::Rect(), clip_child->clip_rect()); EXPECT_EQ(gfx::Rect(12, 12, 40, 40), clip_child->visible_layer_rect()); - EXPECT_TRUE(clip_child->is_clipped()); + EXPECT_FALSE(clip_child->is_clipped()); } TEST_F(LayerTreeHostCommonTest, DescendantsOfClipChildren) { @@ -5977,17 +6004,19 @@ TEST_F(LayerTreeHostCommonTest, // // root (a render surface) // + clip_parent (masks to bounds) - // + render_surface1 - // + clip_child - // + render_surface2 - // + non_clip_child + // + clip_layer (masks to bounds) + // + render_surface1 + // + clip_child + // + render_surface2 + // + non_clip_child // // In this example render_surface2 should be unaffected by clip_child. LayerImpl* root = root_layer_for_testing(); LayerImpl* clip_parent = AddChildToRoot<LayerImpl>(); - LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_parent); + LayerImpl* clip_layer = AddChild<LayerImpl>(clip_parent); + LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_layer); LayerImpl* clip_child = AddChild<LayerImpl>(render_surface1); - LayerImpl* render_surface2 = AddChild<LayerImpl>(clip_parent); + LayerImpl* render_surface2 = AddChild<LayerImpl>(clip_layer); LayerImpl* non_clip_child = AddChild<LayerImpl>(render_surface2); clip_child->test_properties()->clip_parent = clip_parent; @@ -5996,7 +6025,7 @@ TEST_F(LayerTreeHostCommonTest, clip_parent->test_properties()->clip_children->insert(clip_child); clip_parent->SetMasksToBounds(true); - render_surface1->SetMasksToBounds(true); + clip_layer->SetMasksToBounds(true); render_surface1->SetDrawsContent(true); clip_child->SetDrawsContent(true); @@ -6005,6 +6034,7 @@ TEST_F(LayerTreeHostCommonTest, root->SetBounds(gfx::Size(15, 15)); clip_parent->SetBounds(gfx::Size(10, 10)); + clip_layer->SetBounds(gfx::Size(10, 10)); render_surface1->SetPosition(gfx::PointF(5, 5)); render_surface1->SetBounds(gfx::Size(5, 5)); render_surface1->test_properties()->force_render_surface = true; @@ -6020,7 +6050,7 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_TRUE(render_surface1->GetRenderSurface()); EXPECT_TRUE(render_surface2->GetRenderSurface()); - EXPECT_EQ(gfx::Rect(0, 0, 5, 5), render_surface1->clip_rect()); + EXPECT_EQ(gfx::Rect(-5, -5, 10, 10), render_surface1->clip_rect()); EXPECT_TRUE(render_surface1->is_clipped()); // The render surface should not clip (it has unclipped descendants), instead @@ -6043,10 +6073,6 @@ TEST_F(LayerTreeHostCommonTest, // It also shouldn't have grown to accomodate the clip child. EXPECT_EQ(gfx::Rect(0, 0, 5, 5), render_surface2->GetRenderSurface()->content_rect()); - - // Sanity check our num_unclipped_descendants values. - EXPECT_EQ(1u, render_surface1->test_properties()->num_unclipped_descendants); - EXPECT_EQ(0u, render_surface2->test_properties()->num_unclipped_descendants); } TEST_F(LayerTreeHostCommonTest, @@ -6121,7 +6147,6 @@ TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { { LayerImplList render_surface_layer_list; - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root_layer); LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_layer_list); inputs.can_render_to_separate_surface = true; @@ -6132,15 +6157,16 @@ TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { int count_represents_target_render_surface = 0; int count_represents_contributing_render_surface = 0; int count_represents_itself = 0; - 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()) + for (EffectTreeLayerListIterator it(host_impl.active_tree()); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + if (it.state() == EffectTreeLayerListIterator::State::TARGET_SURFACE) { count_represents_target_render_surface++; - if (it.represents_contributing_render_surface()) + } else if (it.state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) { count_represents_contributing_render_surface++; - if (it.represents_itself()) + } else { count_represents_itself++; + } } // Two render surfaces. @@ -6163,15 +6189,16 @@ TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { int count_represents_target_render_surface = 0; int count_represents_contributing_render_surface = 0; int count_represents_itself = 0; - 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()) + for (EffectTreeLayerListIterator it(host_impl.active_tree()); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + if (it.state() == EffectTreeLayerListIterator::State::TARGET_SURFACE) { count_represents_target_render_surface++; - if (it.represents_contributing_render_surface()) + } else if (it.state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) { count_represents_contributing_render_surface++; - if (it.represents_itself()) + } else { count_represents_itself++; + } } // Only root layer has a render surface. @@ -6368,6 +6395,7 @@ TEST_F(LayerTreeHostCommonTest, TransformAnimationUpdatesBackfaceVisibility) { render_surface2->test_properties()->double_sided = false; render_surface2->test_properties()->force_render_surface = true; render_surface2->test_properties()->sorting_context_id = 1; + SetElementIdsForTesting(); ExecuteCalculateDrawProperties(root); const EffectTree& tree = @@ -6377,21 +6405,18 @@ TEST_F(LayerTreeHostCommonTest, TransformAnimationUpdatesBackfaceVisibility) { EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index()) ->hidden_by_backface_visibility); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - gfx::Transform(), back_facing->transform_tree_index(), - root->layer_tree_impl()); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - rotate_about_y, render_surface2->transform_tree_index(), - root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(back_facing->element_id(), + gfx::Transform()); + root->layer_tree_impl()->SetTransformMutated(render_surface2->element_id(), + rotate_about_y); ExecuteCalculateDrawProperties(root); EXPECT_FALSE(tree.Node(render_surface1->effect_tree_index()) ->hidden_by_backface_visibility); EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index()) ->hidden_by_backface_visibility); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - rotate_about_y, render_surface1->transform_tree_index(), - root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(render_surface1->element_id(), + rotate_about_y); ExecuteCalculateDrawProperties(root); EXPECT_TRUE(tree.Node(render_surface1->effect_tree_index()) ->hidden_by_backface_visibility); @@ -6484,50 +6509,6 @@ TEST_F(LayerTreeHostCommonTest, ScrollChildAndScrollParentDifferentTargets) { EXPECT_TRANSFORMATION_MATRIX_EQ(scroll_child->DrawTransform(), scale); } -TEST_F(LayerTreeHostCommonTest, TargetBetweenScrollChildandScrollParentTarget) { - LayerImpl* root = root_layer_for_testing(); - LayerImpl* scroll_child_target = AddChildToRoot<LayerImpl>(); - LayerImpl* scroll_child = AddChild<LayerImpl>(scroll_child_target); - LayerImpl* child_of_scroll_child = AddChild<LayerImpl>(scroll_child); - LayerImpl* intervening_target = AddChild<LayerImpl>(scroll_child_target); - LayerImpl* clip = AddChild<LayerImpl>(intervening_target); - LayerImpl* scroll_parent_target = AddChild<LayerImpl>(clip); - LayerImpl* scroll_parent = AddChild<LayerImpl>(scroll_parent_target); - - scroll_parent->SetDrawsContent(true); - child_of_scroll_child->SetDrawsContent(true); - - scroll_child->test_properties()->scroll_parent = scroll_parent; - scroll_parent->test_properties()->scroll_children = - base::MakeUnique<std::set<LayerImpl*>>(); - scroll_parent->test_properties()->scroll_children->insert(scroll_child); - - root->SetBounds(gfx::Size(50, 50)); - scroll_child_target->SetBounds(gfx::Size(50, 50)); - scroll_child_target->SetMasksToBounds(true); - scroll_child_target->test_properties()->force_render_surface = true; - scroll_child->SetBounds(gfx::Size(50, 50)); - child_of_scroll_child->SetBounds(gfx::Size(50, 50)); - child_of_scroll_child->test_properties()->force_render_surface = true; - intervening_target->SetBounds(gfx::Size(50, 50)); - intervening_target->test_properties()->force_render_surface = true; - clip->SetBounds(gfx::Size(50, 50)); - clip->SetMasksToBounds(true); - scroll_parent_target->SetBounds(gfx::Size(50, 50)); - scroll_parent_target->SetMasksToBounds(true); - scroll_parent_target->test_properties()->force_render_surface = true; - scroll_parent->SetBounds(gfx::Size(50, 50)); - - ExecuteCalculateDrawProperties(root); - PropertyTrees* property_trees = root->layer_tree_impl()->property_trees(); - ClipNode* clip_node = - property_trees->clip_tree.Node(child_of_scroll_child->clip_tree_index()); - ClipNode* parent_clip_node = property_trees->clip_tree.parent(clip_node); - DCHECK_GT(parent_clip_node->target_transform_id, - property_trees->transform_tree.TargetId( - child_of_scroll_child->transform_tree_index())); -} - TEST_F(LayerTreeHostCommonTest, SingularTransformSubtreesDoNotDraw) { LayerImpl* root = root_layer_for_testing(); LayerImpl* parent = AddChildToRoot<LayerImpl>(); @@ -7138,6 +7119,9 @@ TEST_F(LayerTreeHostCommonTest, StickyPositionTopScrollParent) { host()->SetRootLayer(root); scroller->SetScrollClipLayerId(container->id()); + // The sticky layer has already been scrolled on the main thread side, and has + // stuck. This test then checks that further changes from cc-only scrolling + // are handled correctly. LayerStickyPositionConstraint sticky_position; sticky_position.is_sticky = true; sticky_position.is_anchored_top = true; @@ -7915,6 +7899,106 @@ TEST_F(LayerTreeHostCommonTest, StickyPositionScaledContainer) { sticky_pos_impl->ScreenSpaceTransform().To2dTranslation()); } +TEST_F(LayerTreeHostCommonTest, StickyPositionNested) { + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> container = Layer::Create(); + scoped_refptr<Layer> scroller = Layer::Create(); + scoped_refptr<Layer> outer_sticky = Layer::Create(); + scoped_refptr<Layer> inner_sticky = Layer::Create(); + + root->AddChild(container); + container->AddChild(scroller); + scroller->AddChild(outer_sticky); + outer_sticky->AddChild(inner_sticky); + host()->SetRootLayer(root); + scroller->SetScrollClipLayerId(container->id()); + + root->SetBounds(gfx::Size(100, 100)); + container->SetBounds(gfx::Size(100, 100)); + scroller->SetBounds(gfx::Size(100, 1000)); + outer_sticky->SetBounds(gfx::Size(10, 50)); + outer_sticky->SetPosition(gfx::PointF(0, 50)); + inner_sticky->SetBounds(gfx::Size(10, 10)); + inner_sticky->SetPosition(gfx::PointF(0, 0)); + + LayerStickyPositionConstraint outer_sticky_pos; + outer_sticky_pos.is_sticky = true; + outer_sticky_pos.is_anchored_top = true; + outer_sticky_pos.top_offset = 10.0f; + outer_sticky_pos.parent_relative_sticky_box_offset = gfx::Point(0, 50); + outer_sticky_pos.scroll_container_relative_sticky_box_rect = + gfx::Rect(0, 50, 10, 50); + outer_sticky_pos.scroll_container_relative_containing_block_rect = + gfx::Rect(0, 0, 50, 400); + outer_sticky->SetStickyPositionConstraint(outer_sticky_pos); + + LayerStickyPositionConstraint inner_sticky_pos; + inner_sticky_pos.is_sticky = true; + inner_sticky_pos.is_anchored_top = true; + inner_sticky_pos.top_offset = 25.0f; + inner_sticky_pos.parent_relative_sticky_box_offset = gfx::Point(0, 0); + inner_sticky_pos.scroll_container_relative_sticky_box_rect = + gfx::Rect(0, 50, 10, 10); + inner_sticky_pos.scroll_container_relative_containing_block_rect = + gfx::Rect(0, 50, 10, 50); + inner_sticky_pos.nearest_layer_shifting_containing_block = outer_sticky->id(); + inner_sticky->SetStickyPositionConstraint(inner_sticky_pos); + + ExecuteCalculateDrawProperties(root.get()); + host()->host_impl()->CreatePendingTree(); + host()->CommitAndCreatePendingTree(); + host()->host_impl()->ActivateSyncTree(); + LayerTreeImpl* layer_tree_impl = host()->host_impl()->active_tree(); + + LayerImpl* root_impl = layer_tree_impl->LayerById(root->id()); + LayerImpl* scroller_impl = layer_tree_impl->LayerById(scroller->id()); + LayerImpl* outer_sticky_impl = layer_tree_impl->LayerById(outer_sticky->id()); + LayerImpl* inner_sticky_impl = layer_tree_impl->LayerById(inner_sticky->id()); + + ExecuteCalculateDrawProperties(root_impl); + + // Before any scrolling is done, the sticky elements should still be at their + // original positions. + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 50.f), + outer_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 50.f), + inner_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + + // Scroll less than the sticking point. Both sticky elements should move with + // scroll as we haven't gotten to the sticky item locations yet. + SetScrollOffsetDelta(scroller_impl, gfx::Vector2dF(0.f, 5.f)); + ExecuteCalculateDrawProperties(root_impl); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 45.f), + outer_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 45.f), + inner_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + + // Scroll such that the inner sticky should stick, but the outer one should + // keep going as it hasn't reached its position yet. + SetScrollOffsetDelta(scroller_impl, gfx::Vector2dF(0.f, 30.f)); + ExecuteCalculateDrawProperties(root_impl); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 20.f), + outer_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 25.f), + inner_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + + // Keep going, both should stick. + SetScrollOffsetDelta(scroller_impl, gfx::Vector2dF(0.f, 100.f)); + ExecuteCalculateDrawProperties(root_impl); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 10.f), + outer_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 25.f), + inner_sticky_impl->ScreenSpaceTransform().To2dTranslation()); +} + TEST_F(LayerTreeHostCommonTest, NonFlatContainerForFixedPosLayer) { scoped_refptr<Layer> root = Layer::Create(); scoped_refptr<Layer> container = Layer::Create(); @@ -8266,20 +8350,18 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); } -static void GatherDrawnLayers(const LayerImplList* rsll, +static void GatherDrawnLayers(LayerTreeImpl* tree_impl, std::set<LayerImpl*>* drawn_layers) { - for (LayerIterator it = LayerIterator::Begin(rsll), - end = LayerIterator::End(rsll); - it != end; ++it) { - LayerImpl* layer = *it; - if (it.represents_itself()) - drawn_layers->insert(layer); - - if (!it.represents_contributing_render_surface()) + for (EffectTreeLayerListIterator it(tree_impl); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + if (it.state() == EffectTreeLayerListIterator::State::LAYER) + drawn_layers->insert(it.current_layer()); + + if (it.state() != EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) continue; - if (layer->GetRenderSurface()->MaskLayer()) - drawn_layers->insert(layer->GetRenderSurface()->MaskLayer()); + if (it.current_render_surface()->MaskLayer()) + drawn_layers->insert(it.current_render_surface()->MaskLayer()); } } @@ -8328,7 +8410,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { std::set<LayerImpl*> expected; std::set<LayerImpl*> actual; - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // If we force render surface, but none of the layers are in the layer list, @@ -8346,7 +8428,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.clear(); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // However, if we say that this layer also draws content, it will appear in @@ -8365,7 +8447,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(grand_child1_raw); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // Now child is forced to have a render surface, and one if its children draws @@ -8388,7 +8470,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(grand_child2_raw); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // Add a mask layer to child. @@ -8415,7 +8497,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(child_raw->test_properties()->mask_layer); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); ExecuteCalculateDrawProperties(grand_parent_raw); @@ -8433,7 +8515,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(child_raw->test_properties()->mask_layer); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true; @@ -8453,7 +8535,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.clear(); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // Child itself draws means that we should have the child and the mask in the @@ -8474,7 +8556,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(child_raw); expected.insert(child_raw->test_properties()->mask_layer); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); child_raw->test_properties()->SetMaskLayer(nullptr); @@ -8503,7 +8585,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(grand_child2_raw); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); } @@ -8679,11 +8761,8 @@ TEST_F(LayerTreeHostCommonTest, AnimationScales) { // Correctly updates animation scale when layer property changes. child1_layer->test_properties()->transform = gfx::Transform(); - root_layer->layer_tree_impl() - ->property_trees() - ->transform_tree.OnTransformAnimated(gfx::Transform(), - child1_layer->transform_tree_index(), - root_layer->layer_tree_impl()); + root_layer->layer_tree_impl()->SetTransformMutated(child1_layer->element_id(), + gfx::Transform()); root_layer->layer_tree_impl()->property_trees()->needs_rebuild = false; ExecuteCalculateDrawProperties(root_layer); EXPECT_FLOAT_EQ(8.f, GetMaximumAnimationScale(child2_layer)); @@ -8959,32 +9038,19 @@ TEST_F(LayerTreeHostCommonTest, gfx::Transform zero_matrix; zero_matrix.Scale3d(0.f, 0.f, 0.f); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - zero_matrix, animated->transform_tree_index(), root->layer_tree_impl()); - // While computing visible rects by combining clips in screen space, we set - // the entire layer as visible if the screen space transform is singular. This - // is not always true when we combine clips in target space because if the - // intersection of combined_clip in taret space with layer_rect projected to - // target space is empty, we set it to an empty rect. - bool skip_verify_visible_rect_calculations = true; - ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList( - root, skip_verify_visible_rect_calculations); - - // The animated layer maps to the empty rect in clipped target space, so is - // treated as having an empty visible rect. - EXPECT_EQ(gfx::Rect(), animated->visible_layer_rect()); + root->layer_tree_impl()->SetTransformMutated(animated->element_id(), + zero_matrix); + ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root); // The animated layer will be treated as fully visible when we combine clips // in screen space. - gfx::Rect visible_rect = draw_property_utils::ComputeLayerVisibleRectDynamic( - root->layer_tree_impl()->property_trees(), animated); - EXPECT_EQ(gfx::Rect(120, 120), visible_rect); + EXPECT_EQ(gfx::Rect(120, 120), animated->visible_layer_rect()); // This time, flattening does not make |animated|'s transform invertible. This // means the clip cannot be projected into |surface|'s space, so we treat // |surface| and layers that draw into it as having empty visible rect. - EXPECT_EQ(gfx::Rect(), surface->visible_layer_rect()); - EXPECT_EQ(gfx::Rect(), descendant_of_animation->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(100, 100), surface->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(200, 200), descendant_of_animation->visible_layer_rect()); } // Verify that having animated opacity but current opacity 1 still creates @@ -9473,8 +9539,8 @@ TEST_F(LayerTreeHostCommonTest, SkippingLayerImpl) { EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_layer_rect()); child_ptr->test_properties()->hide_layer_and_subtree = false; - child_ptr->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.f, child_ptr->effect_tree_index(), child_ptr->layer_tree_impl()); + child_ptr->test_properties()->opacity = 0.f; + host_impl.active_tree()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr); EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_layer_rect()); child_ptr->test_properties()->opacity = 1.f; @@ -9715,9 +9781,8 @@ TEST_F(LayerTreeHostCommonTest, LayerTreeRebuildTest) { CopyOutputRequest::CreateRequest(base::Bind(&EmptyCopyOutputCallback))); ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); - EXPECT_EQ(parent->num_unclipped_descendants(), 1u); - EXPECT_GT(root->num_copy_requests_in_target_subtree(), 0); + ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); EXPECT_GT(root->num_copy_requests_in_target_subtree(), 0); } @@ -9781,14 +9846,9 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceClipsSubtree) { LayerImpl* page_scale_layer = nullptr; LayerImpl* inner_viewport_scroll_layer = nullptr; LayerImpl* outer_viewport_scroll_layer = nullptr; - // Visible rects computed by combining clips in target space and root space - // don't match because of rotation transforms. So, we skip - // verify_visible_rect_calculations. - bool skip_verify_visible_rect_calculations = true; ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor, page_scale_layer, inner_viewport_scroll_layer, - outer_viewport_scroll_layer, - skip_verify_visible_rect_calculations); + outer_viewport_scroll_layer); TransformTree& transform_tree = root->layer_tree_impl()->property_trees()->transform_tree; @@ -9802,15 +9862,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceClipsSubtree) { EXPECT_TRUE(render_surface->GetRenderSurface()); EXPECT_FALSE(test_layer->GetRenderSurface()); - ClipTree& clip_tree = root->layer_tree_impl()->property_trees()->clip_tree; - ClipNode* clip_node = clip_tree.Node(render_surface->clip_tree_index()); - EXPECT_EQ(clip_node->clip_type, ClipNode::ClipType::NONE); - EXPECT_EQ(gfx::Rect(20, 20), test_layer->visible_layer_rect()); - - // Also test the visible rects computed by combining clips in root space. - gfx::Rect visible_rect = draw_property_utils::ComputeLayerVisibleRectDynamic( - root->layer_tree_impl()->property_trees(), test_layer); - EXPECT_EQ(gfx::Rect(30, 20), visible_rect); + EXPECT_EQ(gfx::Rect(30, 20), test_layer->visible_layer_rect()); } TEST_F(LayerTreeHostCommonTest, TransformOfParentClipNodeAncestorOfTarget) { @@ -9860,6 +9912,7 @@ TEST_F(LayerTreeHostCommonTest, clip_parent->SetMasksToBounds(true); between_clip_parent_and_child->test_properties()->transform = translate; between_clip_parent_and_child->SetBounds(gfx::Size(30, 30)); + between_clip_parent_and_child->SetMasksToBounds(true); render_surface->SetBounds(gfx::Size(30, 30)); render_surface->test_properties()->force_render_surface = true; test_layer->SetBounds(gfx::Size(30, 30)); @@ -9979,7 +10032,8 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceContentRectWithMultipleSurfaces) { LayerImpl* root = root_layer_for_testing(); LayerImpl* unclipped_surface = AddChildToRoot<LayerImpl>(); LayerImpl* clip_parent = AddChild<LayerImpl>(unclipped_surface); - LayerImpl* unclipped_desc_surface = AddChild<LayerImpl>(clip_parent); + LayerImpl* clip_layer = AddChild<LayerImpl>(clip_parent); + LayerImpl* unclipped_desc_surface = AddChild<LayerImpl>(clip_layer); LayerImpl* unclipped_desc_surface2 = AddChild<LayerImpl>(unclipped_desc_surface); LayerImpl* clip_child = AddChild<LayerImpl>(unclipped_desc_surface2); @@ -9992,8 +10046,9 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceContentRectWithMultipleSurfaces) { unclipped_surface->test_properties()->force_render_surface = true; clip_parent->SetBounds(gfx::Size(50, 50)); clip_parent->SetMasksToBounds(true); + clip_layer->SetMasksToBounds(true); + clip_layer->SetBounds(gfx::Size(100, 100)); unclipped_desc_surface->SetBounds(gfx::Size(100, 100)); - unclipped_desc_surface->SetMasksToBounds(true); unclipped_desc_surface->SetDrawsContent(true); unclipped_desc_surface->test_properties()->force_render_surface = true; unclipped_desc_surface2->SetBounds(gfx::Size(60, 60)); @@ -10014,7 +10069,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceContentRectWithMultipleSurfaces) { unclipped_surface->GetRenderSurface()->content_rect()); EXPECT_EQ(gfx::Rect(50, 50), unclipped_desc_surface->GetRenderSurface()->content_rect()); - EXPECT_EQ(gfx::Rect(50, 50), + EXPECT_EQ(gfx::Rect(60, 60), unclipped_desc_surface2->GetRenderSurface()->content_rect()); EXPECT_EQ(gfx::Rect(50, 50), clipped_surface->GetRenderSurface()->content_rect()); @@ -10125,13 +10180,16 @@ TEST_F(LayerTreeHostCommonTest, ClipParentDrawsIntoScaledRootSurface) { LayerImpl* root = root_layer_for_testing(); LayerImpl* clip_layer = AddChild<LayerImpl>(root); LayerImpl* clip_parent = AddChild<LayerImpl>(clip_layer); - LayerImpl* unclipped_desc_surface = AddChild<LayerImpl>(clip_parent); + LayerImpl* clip_parent_child = AddChild<LayerImpl>(clip_parent); + LayerImpl* unclipped_desc_surface = AddChild<LayerImpl>(clip_parent_child); LayerImpl* clip_child = AddChild<LayerImpl>(unclipped_desc_surface); root->SetBounds(gfx::Size(100, 100)); clip_layer->SetBounds(gfx::Size(20, 20)); clip_layer->SetMasksToBounds(true); clip_parent->SetBounds(gfx::Size(50, 50)); + clip_parent_child->SetBounds(gfx::Size(20, 20)); + clip_parent_child->SetMasksToBounds(true); unclipped_desc_surface->SetBounds(gfx::Size(100, 100)); unclipped_desc_surface->SetDrawsContent(true); unclipped_desc_surface->test_properties()->force_render_surface = true; @@ -10219,22 +10277,27 @@ TEST_F(LayerTreeHostCommonTest, SubtreeIsHiddenTest) { test->test_properties()->force_render_surface = true; ExecuteCalculateDrawProperties(root); - EXPECT_TRUE(test->IsHidden()); + EXPECT_EQ(0.f, + test->GetRenderSurface()->OwningEffectNode()->screen_space_opacity); hidden->test_properties()->hide_layer_and_subtree = false; root->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root); - EXPECT_FALSE(test->IsHidden()); + EXPECT_EQ(1.f, + test->GetRenderSurface()->OwningEffectNode()->screen_space_opacity); } TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) { LayerImpl* root = root_layer_for_testing(); - LayerImpl* render_surface1 = AddChild<LayerImpl>(root); + LayerImpl* clip_layer = AddChild<LayerImpl>(root); + LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_layer); LayerImpl* render_surface2 = AddChild<LayerImpl>(render_surface1); LayerImpl* clip_child = AddChild<LayerImpl>(render_surface2); root->SetBounds(gfx::Size(30, 30)); root->SetMasksToBounds(true); + clip_layer->SetBounds(gfx::Size(30, 30)); + clip_layer->SetMasksToBounds(true); render_surface1->SetPosition(gfx::PointF(10, 10)); render_surface1->SetBounds(gfx::Size(30, 30)); render_surface1->SetDrawsContent(true); @@ -10243,6 +10306,7 @@ TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) { render_surface2->SetDrawsContent(true); render_surface2->test_properties()->force_render_surface = true; clip_child->SetBounds(gfx::Size(30, 30)); + clip_child->SetDrawsContent(true); clip_child->test_properties()->clip_parent = root; root->test_properties()->clip_children = @@ -10252,9 +10316,6 @@ TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) { ExecuteCalculateDrawProperties(root); EXPECT_EQ(gfx::Rect(-10, -10, 30, 30), render_surface2->clip_rect()); - // A clip node is created for every render surface and for layers that have - // local clip. So, here it should be craeted for every layer. - EXPECT_EQ(root->layer_tree_impl()->property_trees()->clip_tree.size(), 5u); } TEST_F(LayerTreeHostCommonTest, MaskLayerDrawProperties) { @@ -10443,8 +10504,8 @@ TEST_F(LayerTreeHostCommonTest, PropertyTreesRebuildWithOpacityChanges) { EXPECT_TRUE(property_trees->needs_rebuild); ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); - EXPECT_NE(property_trees->layer_id_to_effect_node_index.find(child->id()), - property_trees->layer_id_to_effect_node_index.end()); + EXPECT_NE(property_trees->effect_tree.FindNodeFromOwningLayerId(child->id()), + nullptr); // child already has an effect node. Changing its opacity shouldn't trigger // a property trees rebuild. @@ -10453,8 +10514,8 @@ TEST_F(LayerTreeHostCommonTest, PropertyTreesRebuildWithOpacityChanges) { EXPECT_FALSE(property_trees->needs_rebuild); ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); - EXPECT_NE(property_trees->layer_id_to_effect_node_index.find(child->id()), - property_trees->layer_id_to_effect_node_index.end()); + EXPECT_NE(property_trees->effect_tree.FindNodeFromOwningLayerId(child->id()), + nullptr); // Changing the opacity from non-1 value to 1 should trigger a rebuild of // property trees as the effect node may no longer be needed. @@ -10463,8 +10524,8 @@ TEST_F(LayerTreeHostCommonTest, PropertyTreesRebuildWithOpacityChanges) { EXPECT_TRUE(property_trees->needs_rebuild); ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); - EXPECT_EQ(property_trees->layer_id_to_effect_node_index.find(child->id()), - property_trees->layer_id_to_effect_node_index.end()); + EXPECT_EQ(property_trees->effect_tree.FindNodeFromOwningLayerId(child->id()), + nullptr); } TEST_F(LayerTreeHostCommonTest, OpacityAnimationsTrackingTest) { @@ -10685,6 +10746,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_root1.user_scrollable_vertical = true; scroll_root1.transform_id = root1->transform_tree_index(); expected_scroll_tree.Insert(scroll_root1, 0); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + root1->id()); // The node owned by parent2 ScrollNode scroll_parent2; @@ -10701,6 +10764,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_parent2.user_scrollable_vertical = true; scroll_parent2.transform_id = parent2->transform_tree_index(); expected_scroll_tree.Insert(scroll_parent2, 1); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + parent2->id()); // The node owned by child6 ScrollNode scroll_child6; @@ -10713,6 +10778,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_child6.user_scrollable_vertical = true; scroll_child6.transform_id = child6->transform_tree_index(); expected_scroll_tree.Insert(scroll_child6, 2); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + child6->id()); // The node owned by child7, child7 also owns a transform node ScrollNode scroll_child7; @@ -10725,6 +10792,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_child7.user_scrollable_vertical = true; scroll_child7.transform_id = child7->transform_tree_index(); expected_scroll_tree.Insert(scroll_child7, 1); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + child7->id()); // The node owned by grand_child11, grand_child11 also owns a transform node ScrollNode scroll_grand_child11; @@ -10735,6 +10804,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_grand_child11.user_scrollable_vertical = true; scroll_grand_child11.transform_id = grand_child11->transform_tree_index(); expected_scroll_tree.Insert(scroll_grand_child11, 4); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + grand_child11->id()); // The node owned by parent5 ScrollNode scroll_parent5; @@ -10747,6 +10818,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_parent5.user_scrollable_vertical = true; scroll_parent5.transform_id = parent5->transform_tree_index(); expected_scroll_tree.Insert(scroll_parent5, 1); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + parent5->id()); expected_scroll_tree.SetScrollOffset(parent2->id(), gfx::ScrollOffset(0, 0)); expected_scroll_tree.SetScrollOffset(child7->id(), gfx::ScrollOffset(0, 0)); @@ -10766,5 +10839,38 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { EXPECT_EQ(scroll_root1.id, grand_child12->scroll_tree_index()); } +TEST_F(LayerTreeHostCommonTest, CanAdjustRasterScaleTest) { + LayerImpl* root = root_layer_for_testing(); + LayerImpl* render_surface = AddChild<LayerImpl>(root); + LayerImpl* child = AddChild<LayerImpl>(render_surface); + + root->SetBounds(gfx::Size(50, 50)); + + render_surface->SetBounds(gfx::Size(10, 10)); + render_surface->test_properties()->force_render_surface = true; + gfx::Transform transform; + transform.Scale(5.f, 5.f); + render_surface->test_properties()->transform = transform; + + child->SetDrawsContent(true); + child->SetMasksToBounds(true); + child->SetBounds(gfx::Size(10, 10)); + + ExecuteCalculateDrawPropertiesWithoutAdjustingRasterScales(root); + + // Check surface draw properties. + EXPECT_EQ(gfx::Rect(10, 10), + render_surface->GetRenderSurface()->content_rect()); + EXPECT_EQ(transform, render_surface->GetRenderSurface()->draw_transform()); + EXPECT_EQ(gfx::RectF(50.0f, 50.0f), + render_surface->GetRenderSurface()->DrawableContentRect()); + + // Check child layer draw properties. + EXPECT_EQ(gfx::Rect(10, 10), child->visible_layer_rect()); + EXPECT_EQ(gfx::Transform(), child->DrawTransform()); + EXPECT_EQ(gfx::Rect(10, 10), child->clip_rect()); + EXPECT_EQ(gfx::Rect(10, 10), child->drawable_content_rect()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index ecfd4d84487..05e4e3add0a 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -24,13 +24,10 @@ #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/base/histograms.h" #include "cc/base/math_util.h" -#include "cc/debug/benchmark_instrumentation.h" -#include "cc/debug/debug_rect_history.h" -#include "cc/debug/devtools_instrumentation.h" -#include "cc/debug/frame_rate_counter.h" -#include "cc/debug/frame_viewer_instrumentation.h" +#include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/debug/rendering_stats_instrumentation.h" #include "cc/debug/traced_value.h" #include "cc/input/browser_controls_offset_manager.h" @@ -40,9 +37,9 @@ #include "cc/input/scroll_state.h" #include "cc/input/scrollbar_animation_controller.h" #include "cc/layers/append_quads_data.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer_impl.h" -#include "cc/layers/layer_iterator.h" #include "cc/layers/painted_scrollbar_layer_impl.h" #include "cc/layers/render_surface_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" @@ -67,18 +64,23 @@ #include "cc/resources/ui_resource_bitmap.h" #include "cc/scheduler/delay_based_time_source.h" #include "cc/tiles/eviction_tile_priority_queue.h" +#include "cc/tiles/frame_viewer_instrumentation.h" #include "cc/tiles/gpu_image_decode_cache.h" #include "cc/tiles/picture_layer_tiling.h" #include "cc/tiles/raster_tile_priority_queue.h" #include "cc/tiles/software_image_decode_cache.h" #include "cc/trees/damage_tracker.h" +#include "cc/trees/debug_rect_history.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" +#include "cc/trees/frame_rate_counter.h" #include "cc/trees/latency_info_swap_promise_monitor.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/mutator_host.h" #include "cc/trees/scroll_node.h" #include "cc/trees/single_thread_proxy.h" +#include "cc/trees/transform_node.h" #include "cc/trees/tree_synchronizer.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" @@ -237,7 +239,11 @@ LayerTreeHostImpl::LayerTreeHostImpl( requires_high_res_to_draw_(false), is_likely_to_require_a_draw_(false), has_valid_compositor_frame_sink_(false), - mutator_(nullptr) { + mutator_(nullptr), + scroll_animating_latched_node_id_(ScrollTree::kInvalidNodeId), + has_scrolled_by_wheel_(false), + has_scrolled_by_touch_(false), + touchpad_and_wheel_scroll_latching_enabled_(false) { DCHECK(mutator_host_); mutator_host_->SetMutatorHostClient(this); @@ -598,13 +604,12 @@ EventListenerProperties LayerTreeHostImpl::GetEventListenerProperties( // Return true if scrollable node for 'ancestor' is the same as 'child' or an // ancestor along the scroll tree. -bool IsScrolledBy(LayerImpl* child, ScrollNode* ancestor) { +bool LayerTreeHostImpl::IsScrolledBy(LayerImpl* child, ScrollNode* ancestor) { DCHECK(ancestor && ancestor->scrollable); if (!child) return false; - - auto* property_trees = child->layer_tree_impl()->property_trees(); - ScrollTree& scroll_tree = property_trees->scroll_tree; + DCHECK_EQ(child->layer_tree_impl(), active_tree_.get()); + ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; for (ScrollNode* scroll_node = scroll_tree.Node(child->scroll_tree_index()); scroll_node; scroll_node = scroll_tree.parent(scroll_node)) { if (scroll_node->id == ancestor->id) @@ -621,15 +626,22 @@ LayerTreeHostImpl::EventListenerTypeForTouchStartAt( // Now determine if there are actually any handlers at that point. // TODO(rbyers): Consider also honoring touch-action (crbug.com/347272). - LayerImpl* layer_impl = + LayerImpl* layer_impl_with_touch_handler = active_tree_->FindLayerThatIsHitByPointInTouchHandlerRegion( device_viewport_point); - if (layer_impl == NULL) + if (layer_impl_with_touch_handler == NULL) return InputHandler::TouchStartEventListenerType::NO_HANDLER; if (!CurrentlyScrollingNode()) return InputHandler::TouchStartEventListenerType::HANDLER; + // Check if the touch start hits on the current scrolling layer or its + // descendant. layer_impl_with_touch_handler is the layer hit by the pointer + // and has an event handler, otherwise it is null. + // We want to compare the most inner layer we are hitting on which may not + // have an event listener with the actual scrolling layer. + LayerImpl* layer_impl = + active_tree_->FindLayerThatIsHitByPoint(device_viewport_point); bool is_ancestor = IsScrolledBy(layer_impl, CurrentlyScrollingNode()); return is_ancestor ? InputHandler::TouchStartEventListenerType:: HANDLER_ON_SCROLLING_LAYER @@ -673,6 +685,22 @@ bool LayerTreeHostImpl::ScrollLayerTo(int layer_id, return true; } +bool LayerTreeHostImpl::ScrollingShouldSwitchtoMainThread() { + ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; + ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + + if (!scroll_node) + return true; + + for (; scroll_tree.parent(scroll_node); + scroll_node = scroll_tree.parent(scroll_node)) { + if (!!scroll_node->main_thread_scrolling_reasons) + return true; + } + + return false; +} + void LayerTreeHostImpl::QueueSwapPromiseForMainThreadScrollUpdate( std::unique_ptr<SwapPromise> swap_promise) { swap_promises_for_main_thread_scroll_update_.push_back( @@ -720,11 +748,6 @@ void LayerTreeHostImpl::FrameData::AsValueInto( } } -void LayerTreeHostImpl::FrameData::AppendRenderPass( - std::unique_ptr<RenderPass> render_pass) { - render_passes.push_back(std::move(render_pass)); -} - DrawMode LayerTreeHostImpl::GetDrawMode() const { if (resourceless_software_draw_) { return DRAW_MODE_RESOURCELESS_SOFTWARE; @@ -837,7 +860,7 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { render_surface->contributes_to_drawn_surface() || render_surface->HasCopyRequest(); if (should_draw_into_render_pass) - render_surface->AppendRenderPasses(frame); + frame->render_passes.push_back(render_surface->CreateRenderPass()); } // Damage rects for non-root passes aren't meaningful, so set them to be @@ -885,19 +908,16 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { active_tree()->property_trees()->effect_tree.HasCopyRequests(); bool have_missing_animated_tiles = false; - LayerIterator end = LayerIterator::End(frame->render_surface_layer_list); - for (LayerIterator it = - LayerIterator::Begin(frame->render_surface_layer_list); - it != end; ++it) { - auto target_render_pass_id = - it.target_render_surface_layer()->GetRenderSurface()->GetRenderPassId(); + for (EffectTreeLayerListIterator it(active_tree()); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + auto target_render_pass_id = it.target_render_surface()->GetRenderPassId(); RenderPass* target_render_pass = FindRenderPassById(frame->render_passes, target_render_pass_id); AppendQuadsData append_quads_data; - RenderSurfaceImpl* render_surface = it->GetRenderSurface(); - if (it.represents_target_render_surface()) { + if (it.state() == EffectTreeLayerListIterator::State::TARGET_SURFACE) { + RenderSurfaceImpl* render_surface = it.target_render_surface(); if (render_surface->HasCopyRequest()) { active_tree() ->property_trees() @@ -905,50 +925,57 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { render_surface->EffectTreeIndex(), &target_render_pass->copy_requests); } - } else if (it.represents_contributing_render_surface() && - render_surface->contributes_to_drawn_surface()) { - render_surface->AppendQuads(target_render_pass, &append_quads_data); - } else if (it.represents_itself() && !it->visible_layer_rect().IsEmpty()) { + } else if (it.state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) { + RenderSurfaceImpl* render_surface = it.current_render_surface(); + if (render_surface->contributes_to_drawn_surface()) + render_surface->AppendQuads(target_render_pass, &append_quads_data); + } else if (it.state() == EffectTreeLayerListIterator::State::LAYER && + !it.current_layer()->visible_layer_rect().IsEmpty()) { + LayerImpl* layer = it.current_layer(); bool occluded = - it->draw_properties().occlusion_in_content_space.IsOccluded( - it->visible_layer_rect()); - if (!occluded && it->WillDraw(draw_mode, resource_provider_.get())) { - DCHECK_EQ(active_tree_.get(), it->layer_tree_impl()); + layer->draw_properties().occlusion_in_content_space.IsOccluded( + layer->visible_layer_rect()); + if (!occluded && layer->WillDraw(draw_mode, resource_provider_.get())) { + DCHECK_EQ(active_tree_.get(), layer->layer_tree_impl()); - frame->will_draw_layers.push_back(*it); - if (it->may_contain_video()) + frame->will_draw_layers.push_back(layer); + if (layer->may_contain_video()) frame->may_contain_video = true; - it->AppendQuads(target_render_pass, &append_quads_data); + layer->AppendQuads(target_render_pass, &append_quads_data); } ++layers_drawn; - } - rendering_stats_instrumentation_->AddVisibleContentArea( - append_quads_data.visible_layer_area); - rendering_stats_instrumentation_->AddApproximatedVisibleContentArea( - append_quads_data.approximated_visible_content_area); - rendering_stats_instrumentation_->AddCheckerboardedVisibleContentArea( - append_quads_data.checkerboarded_visible_content_area); - rendering_stats_instrumentation_->AddCheckerboardedNoRecordingContentArea( - append_quads_data.checkerboarded_no_recording_content_area); - rendering_stats_instrumentation_->AddCheckerboardedNeedsRasterContentArea( - append_quads_data.checkerboarded_needs_raster_content_area); - - num_missing_tiles += append_quads_data.num_missing_tiles; - num_incomplete_tiles += append_quads_data.num_incomplete_tiles; - checkerboarded_no_recording_content_area += - append_quads_data.checkerboarded_no_recording_content_area; - checkerboarded_needs_raster_content_area += - append_quads_data.checkerboarded_needs_raster_content_area; - if (append_quads_data.num_missing_tiles > 0) { - have_missing_animated_tiles |= - !it->was_ever_ready_since_last_transform_animation() || - it->screen_space_transform_is_animating(); - } else { - it->set_was_ever_ready_since_last_transform_animation(true); + rendering_stats_instrumentation_->AddVisibleContentArea( + append_quads_data.visible_layer_area); + rendering_stats_instrumentation_->AddApproximatedVisibleContentArea( + append_quads_data.approximated_visible_content_area); + rendering_stats_instrumentation_->AddCheckerboardedVisibleContentArea( + append_quads_data.checkerboarded_visible_content_area); + rendering_stats_instrumentation_->AddCheckerboardedNoRecordingContentArea( + append_quads_data.checkerboarded_no_recording_content_area); + rendering_stats_instrumentation_->AddCheckerboardedNeedsRasterContentArea( + append_quads_data.checkerboarded_needs_raster_content_area); + + num_missing_tiles += append_quads_data.num_missing_tiles; + num_incomplete_tiles += append_quads_data.num_incomplete_tiles; + checkerboarded_no_recording_content_area += + append_quads_data.checkerboarded_no_recording_content_area; + checkerboarded_needs_raster_content_area += + append_quads_data.checkerboarded_needs_raster_content_area; + if (append_quads_data.num_missing_tiles > 0) { + have_missing_animated_tiles |= + !layer->was_ever_ready_since_last_transform_animation() || + layer->screen_space_transform_is_animating(); + } else { + layer->set_was_ever_ready_since_last_transform_animation(true); + } } + frame->embedded_surfaces.insert(frame->embedded_surfaces.end(), + append_quads_data.embedded_surfaces.begin(), + append_quads_data.embedded_surfaces.end()); } // If CommitToActiveTree() is true, then we wait to draw until @@ -1020,11 +1047,6 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { checkerboarded_needs_raster_content_area); } - // Should only have one render pass in resourceless software mode. - DCHECK(draw_mode != DRAW_MODE_RESOURCELESS_SOFTWARE || - frame->render_passes.size() == 1u) - << frame->render_passes.size(); - TRACE_EVENT_END2("cc", "LayerTreeHostImpl::CalculateRenderPasses", "draw_result", draw_result, "missing tiles", num_missing_tiles); @@ -1169,7 +1191,8 @@ void LayerTreeHostImpl::RemoveRenderPasses(FrameData* frame) { break; } - if (pass->quad_list.empty() && pass->copy_requests.empty()) { + if (pass->quad_list.empty() && pass->copy_requests.empty() && + pass->filters.IsEmpty() && pass->background_filters.IsEmpty()) { // Remove the pass and decrement |i| to counter the for loop's increment, // so we don't skip the next pass in the loop. frame->render_passes.erase(frame->render_passes.begin() + i); @@ -1328,10 +1351,12 @@ void LayerTreeHostImpl::SetIsLikelyToRequireADraw( is_likely_to_require_a_draw_ = is_likely_to_require_a_draw; } -gfx::ColorSpace LayerTreeHostImpl::GetTileColorSpace() const { - if (!sync_tree()) +gfx::ColorSpace LayerTreeHostImpl::GetRasterColorSpace() const { + if (!settings_.enable_color_correct_rasterization) return gfx::ColorSpace(); - return sync_tree()->device_color_space(); + if (!sync_tree()) + return gfx::ColorSpace::CreateSRGB(); + return sync_tree()->raster_color_space(); } void LayerTreeHostImpl::RequestImplSideInvalidation() { @@ -1600,13 +1625,14 @@ CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const { for (LayerImpl* surface_layer : active_tree_->SurfaceLayers()) { SurfaceLayerImpl* surface_layer_impl = static_cast<SurfaceLayerImpl*>(surface_layer); - metadata.referenced_surfaces.push_back( - surface_layer_impl->primary_surface_info().id()); - // We need to retain a reference to the fallback surface too so that it's - // guaranteed to be available when needed. - if (surface_layer_impl->fallback_surface_info().is_valid()) { + if (settings_.enable_surface_synchronization) { + if (surface_layer_impl->fallback_surface_info().is_valid()) { + metadata.referenced_surfaces.push_back( + surface_layer_impl->fallback_surface_info().id()); + } + } else { metadata.referenced_surfaces.push_back( - surface_layer_impl->fallback_surface_info().id()); + surface_layer_impl->primary_surface_info().id()); } } if (!InnerViewportScrollLayer()) @@ -1683,6 +1709,7 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { CompositorFrameMetadata metadata = MakeCompositorFrameMetadata(); metadata.may_contain_video = frame->may_contain_video; + metadata.embedded_surfaces = std::move(frame->embedded_surfaces); active_tree()->FinishSwapPromises(&metadata); for (auto& latency : metadata.latency_info) { TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow", @@ -1707,11 +1734,21 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { } } + DCHECK_LE(BeginFrameArgs::kStartingFrameNumber, + frame->begin_frame_ack.sequence_number); + metadata.begin_frame_ack = frame->begin_frame_ack; + CompositorFrame compositor_frame; compositor_frame.metadata = std::move(metadata); resource_provider_->PrepareSendToParent(resources, &compositor_frame.resource_list); compositor_frame.render_pass_list = std::move(frame->render_passes); + // TODO(fsamuel): Once all clients get their LocalSurfaceId from their parent, + // the LocalSurfaceId should hang off CompositorFrameMetadata. + if (active_tree()->local_surface_id().is_valid()) { + compositor_frame_sink_->SetLocalSurfaceId( + active_tree()->local_surface_id()); + } compositor_frame_sink_->SubmitCompositorFrame(std::move(compositor_frame)); // Clears the list of swap promises after calling DidSwap on each of them to @@ -2041,10 +2078,10 @@ void LayerTreeHostImpl::ActivateSyncTree() { else active_tree_->MoveChangeTrackingToLayers(); } + TreeSynchronizer::PushLayerProperties(pending_tree(), active_tree()); active_tree_->property_trees()->PushOpacityIfNeeded( pending_tree_->property_trees()); - TreeSynchronizer::PushLayerProperties(pending_tree(), active_tree()); pending_tree_->PushPropertiesTo(active_tree_.get()); if (!pending_tree_->LayerListIsEmpty()) pending_tree_->property_trees()->ResetAllChangeTracking(); @@ -2108,6 +2145,17 @@ void LayerTreeHostImpl::SetVisible(bool visible) { if (visible_) { // TODO(crbug.com/469175): Replace with RequiresHighResToDraw. SetRequiresHighResToDraw(); + // Prior CompositorFrame may have been discarded and thus we need to ensure + // that we submit a new one, even if there are no tiles. Therefore, force a + // full viewport redraw. However, this is unnecessary when we become visible + // for the first time (before the first commit) as there is no prior + // CompositorFrame to replace. We can safely use |!active_tree_-> + // LayerListIsEmpty()| as a proxy for this, because we wouldn't be able to + // draw anything even if this is not the first time we become visible. + if (!active_tree_->LayerListIsEmpty()) { + SetFullViewportDamage(); + SetNeedsRedraw(); + } } else { EvictAllUIResources(); // Call PrepareTiles to evict tiles when we become invisible. @@ -2174,11 +2222,12 @@ void LayerTreeHostImpl::CreateTileManagerResources() { image_decode_cache_ = base::MakeUnique<GpuImageDecodeCache>( compositor_frame_sink_->worker_context_provider(), settings_.renderer_settings.preferred_tile_format, - settings_.gpu_decoded_image_budget_bytes); + settings_.decoded_image_working_set_budget_bytes, + settings_.decoded_image_cache_budget_bytes); } else { image_decode_cache_ = base::MakeUnique<SoftwareImageDecodeCache>( settings_.renderer_settings.preferred_tile_format, - settings_.software_decoded_image_budget_bytes); + settings_.decoded_image_working_set_budget_bytes); } // Pass the single-threaded synchronous task graph runner to the worker pool @@ -2237,7 +2286,8 @@ void LayerTreeHostImpl::CreateResourceAndRasterBufferProvider( *raster_buffer_provider = base::MakeUnique<GpuRasterBufferProvider>( compositor_context_provider, worker_context_provider, resource_provider_.get(), settings_.use_distance_field_text, - msaa_sample_count, settings_.async_worker_context_enabled); + msaa_sample_count, settings_.renderer_settings.preferred_tile_format, + settings_.async_worker_context_enabled); return; } @@ -2293,7 +2343,38 @@ LayerImpl* LayerTreeHostImpl::ViewportMainScrollLayer() { return viewport()->MainScrollLayer(); } +void LayerTreeHostImpl::QueueImageDecode( + sk_sp<const SkImage> image, + const base::Callback<void(bool)>& embedder_callback) { + decoded_image_tracker_.QueueImageDecode( + std::move(image), base::Bind(&LayerTreeHostImpl::ImageDecodeFinished, + base::Unretained(this), embedder_callback)); +} + +void LayerTreeHostImpl::ImageDecodeFinished( + const base::Callback<void(bool)>& embedder_callback, + bool decode_succeeded) { + completed_image_decode_callbacks_.emplace_back( + base::Bind(embedder_callback, decode_succeeded)); + client_->SetNeedsCommitOnImplThread(); +} + +std::vector<base::Closure> +LayerTreeHostImpl::TakeCompletedImageDecodeCallbacks() { + auto result = std::move(completed_image_decode_callbacks_); + completed_image_decode_callbacks_.clear(); + return result; +} + +void LayerTreeHostImpl::ClearImageCacheOnNavigation() { + if (image_decode_cache_) + image_decode_cache_->ClearCache(); +} + void LayerTreeHostImpl::DidChangeScrollbarVisibility() { + // Need a commit since input handling for scrollbars is handled in Blink so + // we need to communicate to Blink when the compositor shows/hides the + // scrollbars. client_->SetNeedsCommitOnImplThread(); } @@ -2380,7 +2461,7 @@ bool LayerTreeHostImpl::InitializeRenderer( settings_.renderer_settings.texture_id_allocation_chunk_size, compositor_frame_sink_->capabilities().delegated_sync_points_required, settings_.renderer_settings.use_gpu_memory_buffer_resources, - settings_.enable_color_correct_rendering, + settings_.enable_color_correct_rasterization, settings_.renderer_settings.buffer_to_texture_target_map); // Since the new context may be capable of MSAA, update status here. We don't @@ -2480,9 +2561,11 @@ float LayerTreeHostImpl::CurrentBrowserControlsShownRatio() const { return active_tree_->CurrentBrowserControlsShownRatio(); } -void LayerTreeHostImpl::BindToClient(InputHandlerClient* client) { +void LayerTreeHostImpl::BindToClient(InputHandlerClient* client, + bool wheel_scroll_latching_enabled) { DCHECK(input_handler_client_ == NULL); input_handler_client_ = client; + touchpad_and_wheel_scroll_latching_enabled_ = wheel_scroll_latching_enabled; } InputHandler::ScrollStatus LayerTreeHostImpl::TryScroll( @@ -2668,6 +2751,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( client_->RenewTreePriority(); RecordCompositorSlowScrollMetric(type, CC_THREAD); + UpdateScrollSourceInfo(wheel_scrolling_); + return scroll_status; } @@ -2805,8 +2890,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( // this does not currently go through the scroll customization machinery // that ScrollBy uses for non-animated wheel scrolls. scroll_status = ScrollBegin(&scroll_state, WHEEL); - scroll_node = scroll_tree.CurrentlyScrollingNode(); if (scroll_status.thread == SCROLL_ON_IMPL_THREAD) { + scroll_animating_latched_node_id_ = ScrollTree::kInvalidNodeId; ScrollStateData scroll_state_end_data; scroll_state_end_data.is_ending = true; ScrollState scroll_state_end(scroll_state_end_data); @@ -2878,7 +2963,15 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( MainThreadScrollingReason::kNotScrollingOnMain; ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + if (scroll_node) { + // Flash the overlay scrollbar even if the scroll dalta is 0. + ScrollbarAnimationController* animation_controller = + ScrollbarAnimationControllerForId(scroll_node->owning_layer_id); + + if (animation_controller) + animation_controller->WillUpdateScroll(); + gfx::Vector2dF delta = scroll_delta; if (!scroll_node->user_scrollable_horizontal) delta.set_x(0); @@ -2913,29 +3006,54 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( if (!scroll_node->scrollable) continue; + if (touchpad_and_wheel_scroll_latching_enabled_ && + scroll_animating_latched_node_id_ != ScrollTree::kInvalidNodeId && + scroll_node->id != scroll_animating_latched_node_id_) { + continue; + } + bool scrolls_main_viewport_scroll_layer = viewport()->MainScrollLayer() && viewport()->MainScrollLayer()->scroll_tree_index() == scroll_node->id; if (scrolls_main_viewport_scroll_layer) { + // Flash the overlay scrollbar even if the scroll dalta is 0. + ScrollbarAnimationController* animation_controller = + ScrollbarAnimationControllerForId(scroll_node->owning_layer_id); + + if (animation_controller) + animation_controller->WillUpdateScroll(); + gfx::Vector2dF scrolled = viewport()->ScrollAnimated(pending_delta, delayed_by); // Viewport::ScrollAnimated returns pending_delta as long as it starts // an animation. - if (scrolled == pending_delta) + if (scrolled == pending_delta) { + scroll_animating_latched_node_id_ = scroll_node->id; return scroll_status; + } break; } gfx::Vector2dF scroll_delta = ComputeScrollDelta(scroll_node, pending_delta); - if (ScrollAnimationCreate(scroll_node, scroll_delta, delayed_by)) + if (ScrollAnimationCreate(scroll_node, scroll_delta, delayed_by)) { + scroll_animating_latched_node_id_ = scroll_node->id; return scroll_status; + } pending_delta -= scroll_delta; } } scroll_state.set_is_ending(true); ScrollEnd(&scroll_state); + if (settings_.is_layer_tree_for_subframe && + scroll_status.thread == SCROLL_ON_IMPL_THREAD) { + // If we get to here, we shouldn't return SCROLL_ON_IMPL_THREAD as otherwise + // we'll mark the scroll as handled and the scroll won't bubble. + scroll_status.thread = SCROLL_IGNORED; + scroll_status.main_thread_scrolling_reasons = + MainThreadScrollingReason::kNotScrollable; + } return scroll_status; } @@ -3161,9 +3279,18 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( DCHECK(scroll_state); TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); - if (!CurrentlyScrollingNode()) + ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; + ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + + if (!scroll_node) return InputHandlerScrollResult(); + ScrollbarAnimationController* animation_controller = + ScrollbarAnimationControllerForId(scroll_node->owning_layer_id); + + if (animation_controller) + animation_controller->WillUpdateScroll(); + float initial_top_controls_offset = browser_controls_offset_manager_->ControlsTopOffset(); @@ -3464,6 +3591,11 @@ std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { active_tree_->elastic_overscroll()->PullDeltaForMainThread(); scroll_info->swap_promises.swap(swap_promises_for_main_thread_scroll_update_); + // Record and reset scroll source flags. + scroll_info->has_scrolled_by_wheel = has_scrolled_by_wheel_; + scroll_info->has_scrolled_by_touch = has_scrolled_by_touch_; + has_scrolled_by_wheel_ = has_scrolled_by_touch_ = false; + return scroll_info; } @@ -3785,7 +3917,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, id = resource_provider_->CreateResource( upload_size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format, - gfx::ColorSpace()); + gfx::ColorSpace::CreateSRGB()); if (!scaled) { AutoLockUIResourceBitmap bitmap_lock(bitmap); @@ -3965,55 +4097,6 @@ void LayerTreeHostImpl::SetMutatorsNeedCommit() {} void LayerTreeHostImpl::SetMutatorsNeedRebuildPropertyTrees() {} -void LayerTreeHostImpl::SetTreeLayerFilterMutated( - ElementId element_id, - LayerTreeImpl* tree, - const FilterOperations& filters) { - if (!tree) - return; - - PropertyTrees* property_trees = tree->property_trees(); - DCHECK_EQ(1u, - property_trees->element_id_to_effect_node_index.count(element_id)); - const int effect_node_index = - property_trees->element_id_to_effect_node_index[element_id]; - property_trees->effect_tree.OnFilterAnimated(filters, effect_node_index, - tree); -} - -void LayerTreeHostImpl::SetTreeLayerOpacityMutated(ElementId element_id, - LayerTreeImpl* tree, - float opacity) { - if (!tree) - return; - - PropertyTrees* property_trees = tree->property_trees(); - DCHECK_EQ(1u, - property_trees->element_id_to_effect_node_index.count(element_id)); - const int effect_node_index = - property_trees->element_id_to_effect_node_index[element_id]; - property_trees->effect_tree.OnOpacityAnimated(opacity, effect_node_index, - tree); -} - -void LayerTreeHostImpl::SetTreeLayerTransformMutated( - ElementId element_id, - LayerTreeImpl* tree, - const gfx::Transform& transform) { - if (!tree) - return; - - PropertyTrees* property_trees = tree->property_trees(); - DCHECK_EQ( - 1u, property_trees->element_id_to_transform_node_index.count(element_id)); - const int transform_node_index = - property_trees->element_id_to_transform_node_index[element_id]; - property_trees->transform_tree.OnTransformAnimated( - transform, transform_node_index, tree); - if (LayerImpl* layer = tree->LayerByElementId(element_id)) - layer->set_was_ever_ready_since_last_transform_animation(false); -} - void LayerTreeHostImpl::SetTreeLayerScrollOffsetMutated( ElementId element_id, LayerTreeImpl* tree, @@ -4047,10 +4130,12 @@ void LayerTreeHostImpl::SetElementFilterMutated( ElementListType list_type, const FilterOperations& filters) { if (list_type == ElementListType::ACTIVE) { - SetTreeLayerFilterMutated(element_id, active_tree(), filters); + active_tree()->SetFilterMutated(element_id, filters); } else { - SetTreeLayerFilterMutated(element_id, pending_tree(), filters); - SetTreeLayerFilterMutated(element_id, recycle_tree(), filters); + if (pending_tree()) + pending_tree()->SetFilterMutated(element_id, filters); + if (recycle_tree()) + recycle_tree()->SetFilterMutated(element_id, filters); } } @@ -4058,10 +4143,12 @@ void LayerTreeHostImpl::SetElementOpacityMutated(ElementId element_id, ElementListType list_type, float opacity) { if (list_type == ElementListType::ACTIVE) { - SetTreeLayerOpacityMutated(element_id, active_tree(), opacity); + active_tree()->SetOpacityMutated(element_id, opacity); } else { - SetTreeLayerOpacityMutated(element_id, pending_tree(), opacity); - SetTreeLayerOpacityMutated(element_id, recycle_tree(), opacity); + if (pending_tree()) + pending_tree()->SetOpacityMutated(element_id, opacity); + if (recycle_tree()) + recycle_tree()->SetOpacityMutated(element_id, opacity); } } @@ -4070,10 +4157,12 @@ void LayerTreeHostImpl::SetElementTransformMutated( ElementListType list_type, const gfx::Transform& transform) { if (list_type == ElementListType::ACTIVE) { - SetTreeLayerTransformMutated(element_id, active_tree(), transform); + active_tree()->SetTransformMutated(element_id, transform); } else { - SetTreeLayerTransformMutated(element_id, pending_tree(), transform); - SetTreeLayerTransformMutated(element_id, recycle_tree(), transform); + if (pending_tree()) + pending_tree()->SetTransformMutated(element_id, transform); + if (recycle_tree()) + recycle_tree()->SetTransformMutated(element_id, transform); } } @@ -4094,13 +4183,75 @@ void LayerTreeHostImpl::ElementIsAnimatingChanged( ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) { + // TODO(weiliangc): Most of the code is duplicated with LayerTeeHost version + // of function. Should try to share code. LayerTreeImpl* tree = list_type == ElementListType::ACTIVE ? active_tree() : pending_tree(); if (!tree) return; - LayerImpl* layer = tree->LayerByElementId(element_id); - if (layer) - layer->OnIsAnimatingChanged(mask, state); + PropertyTrees* property_trees = tree->property_trees(); + + for (int property = TargetProperty::FIRST_TARGET_PROPERTY; + property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) { + if (!mask.currently_running[property] && + !mask.potentially_animating[property]) + continue; + + switch (property) { + case TargetProperty::TRANSFORM: + if (TransformNode* transform_node = + property_trees->transform_tree.FindNodeFromElementId( + element_id)) { + if (mask.currently_running[property]) + transform_node->is_currently_animating = + state.currently_running[property]; + if (mask.potentially_animating[property]) { + transform_node->has_potential_animation = + state.potentially_animating[property]; + transform_node->has_only_translation_animations = + mutator_host()->HasOnlyTranslationTransforms(element_id, + list_type); + property_trees->transform_tree.set_needs_update(true); + tree->set_needs_update_draw_properties(); + // TODO(crbug.com/702777): + // was_ever_ready_since_last_transform_animation should not live on + // layers. + if (LayerImpl* layer = tree->LayerByElementId(element_id)) { + layer->set_was_ever_ready_since_last_transform_animation(false); + } + } + } + break; + case TargetProperty::OPACITY: + if (EffectNode* effect_node = + property_trees->effect_tree.FindNodeFromElementId(element_id)) { + if (mask.currently_running[property]) + effect_node->is_currently_animating_opacity = + state.currently_running[property]; + if (mask.potentially_animating[property]) { + effect_node->has_potential_opacity_animation = + state.potentially_animating[property]; + property_trees->effect_tree.set_needs_update(true); + } + } + break; + case TargetProperty::FILTER: + if (EffectNode* effect_node = + property_trees->effect_tree.FindNodeFromElementId(element_id)) { + if (mask.currently_running[property]) + effect_node->is_currently_animating_filter = + state.currently_running[property]; + if (mask.potentially_animating[property]) + effect_node->has_potential_filter_animation = + state.potentially_animating[property]; + // Filter animation changes only the node, and the subtree does not + // care. There is no need to request update on property trees here. + } + break; + default: + break; + } + } } void LayerTreeHostImpl::ScrollOffsetAnimationFinished() { @@ -4166,4 +4317,11 @@ void LayerTreeHostImpl::SetContextVisibility(bool is_visible) { } } +void LayerTreeHostImpl::UpdateScrollSourceInfo(bool is_wheel_scroll) { + if (is_wheel_scroll) + has_scrolled_by_wheel_ = true; + else + has_scrolled_by_touch_ = true; +} + } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index 704eb1ab922..0b72dc47333 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -17,14 +17,13 @@ #include "base/callback.h" #include "base/macros.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" #include "cc/base/synced_property.h" -#include "cc/debug/micro_benchmark_controller_impl.h" +#include "cc/benchmarks/micro_benchmark_controller_impl.h" +#include "cc/cc_export.h" #include "cc/input/browser_controls_offset_manager_client.h" #include "cc/input/input_handler.h" #include "cc/input/scrollbar_animation_controller.h" #include "cc/layers/layer_collections.h" -#include "cc/layers/render_pass_sink.h" #include "cc/output/begin_frame_args.h" #include "cc/output/compositor_frame_sink_client.h" #include "cc/output/context_cache_controller.h" @@ -36,6 +35,8 @@ #include "cc/scheduler/commit_earlyout_reason.h" #include "cc/scheduler/draw_result.h" #include "cc/scheduler/video_frame_controller.h" +#include "cc/surfaces/local_surface_id.h" +#include "cc/surfaces/surface_id.h" #include "cc/tiles/decoded_image_tracker.h" #include "cc/tiles/image_decode_cache.h" #include "cc/tiles/tile_manager.h" @@ -152,7 +153,8 @@ class CC_EXPORT LayerTreeHostImpl ~LayerTreeHostImpl() override; // InputHandler implementation - void BindToClient(InputHandlerClient* client) override; + void BindToClient(InputHandlerClient* client, + bool wheel_scroll_latching_enabled) override; InputHandler::ScrollStatus ScrollBegin( ScrollState* scroll_state, InputHandler::ScrollInputType type) override; @@ -200,6 +202,7 @@ class CC_EXPORT LayerTreeHostImpl bool GetScrollOffsetForLayer(int layer_id, gfx::ScrollOffset* offset) override; bool ScrollLayerTo(int layer_id, const gfx::ScrollOffset& offset) override; + bool ScrollingShouldSwitchtoMainThread() override; // BrowserControlsOffsetManagerClient implementation. float TopControlsHeight() const override; @@ -215,11 +218,12 @@ class CC_EXPORT LayerTreeHostImpl resourceless_software_draw_ = true; } - struct CC_EXPORT FrameData : public RenderPassSink { + struct CC_EXPORT FrameData { FrameData(); - ~FrameData() override; + ~FrameData(); void AsValueInto(base::trace_event::TracedValue* value) const; + std::vector<SurfaceId> embedded_surfaces; std::vector<gfx::Rect> occluding_screen_space_rects; std::vector<gfx::Rect> non_occluding_screen_space_rects; RenderPassList render_passes; @@ -227,9 +231,7 @@ class CC_EXPORT LayerTreeHostImpl LayerImplList will_draw_layers; bool has_no_damage; bool may_contain_video; - - // RenderPassSink implementation. - void AppendRenderPass(std::unique_ptr<RenderPass> render_pass) override; + BeginFrameAck begin_frame_ack; private: DISALLOW_COPY_AND_ASSIGN(FrameData); @@ -257,15 +259,6 @@ class CC_EXPORT LayerTreeHostImpl // virtual for testing. virtual void InvalidateContentOnImplSide(); - void SetTreeLayerFilterMutated(ElementId element_id, - LayerTreeImpl* tree, - const FilterOperations& filters); - void SetTreeLayerOpacityMutated(ElementId element_id, - LayerTreeImpl* tree, - float opacity); - void SetTreeLayerTransformMutated(ElementId element_id, - LayerTreeImpl* tree, - const gfx::Transform& transform); void SetTreeLayerScrollOffsetMutated(ElementId element_id, LayerTreeImpl* tree, const gfx::ScrollOffset& scroll_offset); @@ -354,7 +347,7 @@ class CC_EXPORT LayerTreeHostImpl std::unique_ptr<EvictionTilePriorityQueue> BuildEvictionQueue( TreePriority tree_priority) override; void SetIsLikelyToRequireADraw(bool is_likely_to_require_a_draw) override; - gfx::ColorSpace GetTileColorSpace() const override; + gfx::ColorSpace GetRasterColorSpace() const override; void RequestImplSideInvalidation() override; // ScrollbarAnimationControllerClient implementation. @@ -603,6 +596,12 @@ class CC_EXPORT LayerTreeHostImpl LayerImpl* ViewportMainScrollLayer(); + void QueueImageDecode(sk_sp<const SkImage> image, + const base::Callback<void(bool)>& embedder_callback); + std::vector<base::Closure> TakeCompletedImageDecodeCallbacks(); + + void ClearImageCacheOnNavigation(); + protected: LayerTreeHostImpl( const LayerTreeSettings& settings, @@ -702,6 +701,18 @@ class CC_EXPORT LayerTreeHostImpl base::TimeDelta delayed_by); void SetContextVisibility(bool is_visible); + void ImageDecodeFinished(const base::Callback<void(bool)>& embedder_callback, + bool decode_succeeded); + + // This function keeps track of sources of scrolls that are handled in the + // compositor side. The information gets shared by the main thread as part of + // the begin_main_frame_state. Finally Use counters are updated in the main + // thread side to keep track of the frequency of scrolling with different + // sources per page load. TODO(crbug.com/691886): Use GRC API to plumb the + // scroll source info for Use Counters. + void UpdateScrollSourceInfo(bool is_wheel_scroll); + + bool IsScrolledBy(LayerImpl* child, ScrollNode* ancestor); using UIResourceMap = std::unordered_map<UIResourceId, UIResourceData>; UIResourceMap ui_resource_map_; @@ -713,6 +724,8 @@ class CC_EXPORT LayerTreeHostImpl CompositorFrameSink* compositor_frame_sink_; + LocalSurfaceId local_surface_id_; + // The following scoped variables must not outlive the // |compositor_frame_sink_|. // These should be transfered to ContextCacheController's @@ -843,6 +856,22 @@ class CC_EXPORT LayerTreeHostImpl std::unique_ptr<PendingTreeDurationHistogramTimer> pending_tree_duration_timer_; + // The id of the scroll node to which scroll animations must latch. + // This gets reset at ScrollAnimatedBegin, and updated the first time that a + // scroll animation is created in ScrollAnimated. + int scroll_animating_latched_node_id_; + + // These callbacks are stored here to be transfered to the main thread when we + // begin main frame. These callbacks must only be called on the main thread. + std::vector<base::Closure> completed_image_decode_callbacks_; + + // These are used to transfer usage of touch and wheel scrolls to the main + // thread. + bool has_scrolled_by_wheel_; + bool has_scrolled_by_touch_; + + bool touchpad_and_wheel_scroll_latching_enabled_; + DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl); }; diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc index 5c12dbc07db..a52bdf7996c 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -30,6 +30,7 @@ #include "cc/layers/render_surface_impl.h" #include "cc/layers/solid_color_layer_impl.h" #include "cc/layers/solid_color_scrollbar_layer_impl.h" +#include "cc/layers/surface_layer_impl.h" #include "cc/layers/texture_layer_impl.h" #include "cc/layers/video_layer_impl.h" #include "cc/layers/viewport.h" @@ -93,6 +94,19 @@ using media::VideoFrame; namespace cc { namespace { +SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) { + return SurfaceId( + frame_sink_id, + LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u))); +} + +struct TestFrameData : public LayerTreeHostImpl::FrameData { + TestFrameData() { + // Set ack to something valid, so DCHECKs don't complain. + begin_frame_ack = BeginFrameAck(0, 1, 1, true); + } +}; + class LayerTreeHostImplTest : public testing::Test, public LayerTreeHostImplClient { public: @@ -115,7 +129,6 @@ class LayerTreeHostImplTest : public testing::Test, LayerTreeSettings settings; settings.minimum_occlusion_tracking_size = gfx::Size(); settings.renderer_settings.texture_id_allocation_chunk_size = 1; - settings.verify_clip_tree_calculations = true; settings.renderer_settings.buffer_to_texture_target_map = DefaultBufferToTextureTargetMapForTesting(); return settings; @@ -166,8 +179,7 @@ class LayerTreeHostImplTest : public testing::Test, did_complete_page_scale_animation_ = true; } void OnDrawForCompositorFrameSink(bool resourceless_software_draw) override { - std::unique_ptr<LayerTreeHostImpl::FrameData> frame( - new LayerTreeHostImpl::FrameData); + std::unique_ptr<TestFrameData> frame(new TestFrameData); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(frame.get())); last_on_draw_render_passes_.clear(); RenderPass::CopyAll(frame->render_passes, &last_on_draw_render_passes_); @@ -326,6 +338,8 @@ class LayerTreeHostImplTest : public testing::Test, LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); inner_scroll->SetScrollClipLayer(inner_clip->id()); + inner_scroll->SetElementId( + LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(content_size); inner_scroll->SetPosition(gfx::PointF()); @@ -338,6 +352,8 @@ class LayerTreeHostImplTest : public testing::Test, std::unique_ptr<LayerImpl> outer_scroll = LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId); outer_scroll->SetScrollClipLayer(outer_clip->id()); + outer_scroll->SetElementId( + LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(outer_scroll->id(), @@ -401,9 +417,6 @@ class LayerTreeHostImplTest : public testing::Test, inner_clip_layer->SetBounds(viewport_size); host_impl_->InnerViewportScrollLayer()->SetBounds(viewport_size); - // Needs to happen before building property trees as the latter propagates - // these element ids to property tree nodes. - host_impl_->active_tree()->SetElementIdsForTesting(); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->SetViewportSize(viewport_size); @@ -420,6 +433,7 @@ class LayerTreeHostImplTest : public testing::Test, std::unique_ptr<LayerImpl> layer = LayerImpl::Create(host_impl_->active_tree(), id); layer->SetScrollClipLayer(clip_layer->id()); + layer->SetElementId(LayerIdToElementIdForTesting(layer->id())); layer->SetDrawsContent(true); layer->SetBounds(size); clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2)); @@ -457,7 +471,7 @@ class LayerTreeHostImplTest : public testing::Test, } void DrawFrame() { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -481,7 +495,7 @@ class LayerTreeHostImplTest : public testing::Test, } void DrawOneFrame() { - LayerTreeHostImpl::FrameData frame_data; + TestFrameData frame_data; host_impl_->PrepareToDraw(&frame_data); host_impl_->DidDrawAllLayers(frame_data); } @@ -531,7 +545,7 @@ class LayerTreeHostImplTest : public testing::Test, bool did_request_impl_side_invalidation_; base::Closure animation_task_; base::TimeDelta requested_animation_delay_; - std::unique_ptr<LayerTreeHostImpl::FrameData> last_on_draw_frame_; + std::unique_ptr<TestFrameData> last_on_draw_frame_; RenderPassList last_on_draw_render_passes_; scoped_refptr<AnimationTimeline> timeline_; std::unique_ptr<base::Thread> image_worker_; @@ -545,6 +559,58 @@ class LayerTreeHostImplTimelinesTest : public LayerTreeHostImplTest { } }; +class TestInputHandlerClient : public InputHandlerClient { + public: + TestInputHandlerClient() + : page_scale_factor_(0.f), + min_page_scale_factor_(-1.f), + max_page_scale_factor_(-1.f) {} + ~TestInputHandlerClient() override {} + + // InputHandlerClient implementation. + void WillShutdown() override {} + void Animate(base::TimeTicks time) override {} + void MainThreadHasStoppedFlinging() override {} + void ReconcileElasticOverscrollAndRootScroll() override {} + void UpdateRootLayerStateForSynchronousInputHandler( + const gfx::ScrollOffset& total_scroll_offset, + const gfx::ScrollOffset& max_scroll_offset, + const gfx::SizeF& scrollable_size, + float page_scale_factor, + float min_page_scale_factor, + float max_page_scale_factor) override { + DCHECK(total_scroll_offset.x() <= max_scroll_offset.x()); + DCHECK(total_scroll_offset.y() <= max_scroll_offset.y()); + last_set_scroll_offset_ = total_scroll_offset; + max_scroll_offset_ = max_scroll_offset; + scrollable_size_ = scrollable_size; + page_scale_factor_ = page_scale_factor; + min_page_scale_factor_ = min_page_scale_factor; + max_page_scale_factor_ = max_page_scale_factor; + } + void DeliverInputForBeginFrame() override {} + + gfx::ScrollOffset last_set_scroll_offset() { return last_set_scroll_offset_; } + + gfx::ScrollOffset max_scroll_offset() const { return max_scroll_offset_; } + + gfx::SizeF scrollable_size() const { return scrollable_size_; } + + float page_scale_factor() const { return page_scale_factor_; } + + float min_page_scale_factor() const { return min_page_scale_factor_; } + + float max_page_scale_factor() const { return max_page_scale_factor_; } + + private: + gfx::ScrollOffset last_set_scroll_offset_; + gfx::ScrollOffset max_scroll_offset_; + gfx::SizeF scrollable_size_; + float page_scale_factor_; + float min_page_scale_factor_; + float max_page_scale_factor_; +}; + TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) { // Note: It is not possible to disable the renderer once it has been set, // so we do not need to test that disabling the renderer notifies us @@ -661,6 +727,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) { root_clip->test_properties()->AddChild(std::move(root_owned)); root->SetBounds(gfx::Size(110, 110)); root->SetScrollClipLayer(root_clip->id()); + root->SetElementId(LayerIdToElementIdForTesting(root->id())); root->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(root->id(), scroll_offset); @@ -966,6 +1033,7 @@ TEST_F(LayerTreeHostImplTest, ScrollWithOverlappingNonScrollableLayer) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar = @@ -1037,6 +1105,7 @@ TEST_F(LayerTreeHostImplTest, ScrolledOverlappingDrawnScrollbarLayer) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); std::unique_ptr<SolidColorScrollbarLayerImpl> drawn_scrollbar = @@ -1281,6 +1350,7 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { overflow->SetBounds(overflow_size); overflow->SetScrollClipLayer( scroll_layer->test_properties()->parent->test_properties()->parent->id()); + overflow->SetElementId(LayerIdToElementIdForTesting(overflow->id())); overflow->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(overflow->id(), @@ -1628,7 +1698,7 @@ TEST_F(LayerTreeHostImplTest, AnimationMarksLayerNotReady) { host_impl_->ResetRequiresHighResToDraw(); // Child layer has an animating transform but missing tiles. - FakeLayerTreeHostImpl::FrameData frame; + TestFrameData frame; DrawResult result = host_impl_->PrepareToDraw(&frame); EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS, result); host_impl_->DidDrawAllLayers(frame); @@ -2105,7 +2175,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDoesntBubble) { std::unique_ptr<std::set<LayerImpl*>> scroll_children( new std::set<LayerImpl*>); scroll_children->insert(child_clip); - parent->test_properties()->scroll_children.reset(scroll_children.release()); + parent->test_properties()->scroll_children = std::move(scroll_children); host_impl_->active_tree()->BuildPropertyTreesForTesting(); DrawFrame(); @@ -2791,15 +2861,19 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->DidBecomeActive(); DrawFrame(); + + // SetScrollLayerId will initialize the scrollbar which will cause it to + // show and request a redraw. + did_request_redraw_ = false; } void RunTest(LayerTreeSettings::ScrollbarAnimator animator) { LayerTreeSettings settings = DefaultSettings(); settings.scrollbar_animator = animator; - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_duration = + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_out_resize_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(20); // If no animator is set, scrollbar won't show and no animation is expected. bool expecting_animations = animator != LayerTreeSettings::NO_ANIMATOR; @@ -2831,6 +2905,25 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); EXPECT_TRUE(animation_task_.Equals(base::Closure())); + // For Aura Overlay Scrollbar, if no scroll happened during a scroll + // gesture, shows scrollbars and schedules a delay fade out. + host_impl_->ScrollBegin(BeginState(gfx::Point()).get(), + InputHandler::WHEEL); + host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 0)).get()); + host_impl_->ScrollEnd(EndState().get()); + EXPECT_FALSE(did_request_next_frame_); + EXPECT_FALSE(did_request_redraw_); + if (animator == LayerTreeSettings::AURA_OVERLAY) { + EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), + requested_animation_delay_); + EXPECT_FALSE(animation_task_.Equals(base::Closure())); + requested_animation_delay_ = base::TimeDelta(); + animation_task_ = base::Closure(); + } else { + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + } + // Before the scrollbar animation exists, we should not get redraws. BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, fake_now); @@ -2938,7 +3031,9 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { host_impl_->DidFinishImplFrame(); } - // Scrollbar animation is not triggered unnecessarily. + // For Andrdoid, scrollbar animation is not triggered unnecessarily. + // For Aura Overlay Scrollbar, scrollbar appears even if scroll offset did + // not change. host_impl_->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL); host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(5, 0)).get()); @@ -2951,8 +3046,16 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { host_impl_->ScrollEnd(EndState().get()); EXPECT_FALSE(did_request_next_frame_); EXPECT_FALSE(did_request_redraw_); - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + if (animator == LayerTreeSettings::AURA_OVERLAY) { + EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), + requested_animation_delay_); + EXPECT_FALSE(animation_task_.Equals(base::Closure())); + requested_animation_delay_ = base::TimeDelta(); + animation_task_ = base::Closure(); + } else { + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + } // Changing page scale triggers scrollbar animation. host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f); @@ -2989,10 +3092,8 @@ class LayerTreeHostImplTestScrollbarOpacity : public LayerTreeHostImplTest { void RunTest(LayerTreeSettings::ScrollbarAnimator animator) { LayerTreeSettings settings = DefaultSettings(); settings.scrollbar_animator = animator; - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_duration = - base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(20); gfx::Size content_size(100, 100); // If no animator is set, scrollbar won't show and no animation is expected. @@ -3085,6 +3186,75 @@ TEST_F(LayerTreeHostImplTestScrollbarOpacity, NoAnimator) { RunTest(LayerTreeSettings::NO_ANIMATOR); } +TEST_F(LayerTreeHostImplTest, ScrollbarVisibilityChangeCausesRedrawAndCommit) { + LayerTreeSettings settings = DefaultSettings(); + settings.scrollbar_animator = LayerTreeSettings::AURA_OVERLAY; + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(20); + gfx::Size content_size(100, 100); + + CreateHostImpl(settings, CreateCompositorFrameSink()); + host_impl_->CreatePendingTree(); + CreateScrollAndContentsLayers(host_impl_->pending_tree(), content_size); + std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar = + SolidColorScrollbarLayerImpl::Create(host_impl_->pending_tree(), 400, + VERTICAL, 10, 0, false, true); + scrollbar->test_properties()->opacity = 0.f; + LayerImpl* scroll = host_impl_->pending_tree()->OuterViewportScrollLayer(); + LayerImpl* container = + host_impl_->pending_tree()->InnerViewportContainerLayer(); + scrollbar->SetScrollLayerId(scroll->id()); + container->test_properties()->AddChild(std::move(scrollbar)); + host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f); + host_impl_->pending_tree()->BuildPropertyTreesForTesting(); + host_impl_->ActivateSyncTree(); + + ScrollbarAnimationController* scrollbar_controller = + host_impl_->ScrollbarAnimationControllerForId(scroll->id()); + + // Scrollbars will flash shown but we should have a fade out animation + // queued. Run it and fade out the scrollbars. + { + ASSERT_FALSE(animation_task_.Equals(base::Closure())); + ASSERT_FALSE(animation_task_.IsCancelled()); + animation_task_.Run(); + + base::TimeTicks fake_now = base::TimeTicks::Now(); + scrollbar_controller->Animate(fake_now); + fake_now += settings.scrollbar_fade_delay; + scrollbar_controller->Animate(fake_now); + + ASSERT_TRUE(scrollbar_controller->ScrollbarsHidden()); + } + + // Move the mouse over the scrollbar region. This should post a delayed fade + // in task. Execute it to show the scrollbars. + { + animation_task_ = base::Closure(); + scrollbar_controller->DidMouseMoveNear(VERTICAL, 0); + ASSERT_FALSE(animation_task_.Equals(base::Closure())); + ASSERT_FALSE(animation_task_.IsCancelled()); + } + + // The fade in task should cause the scrollbars to show. Ensure that we + // requested a redraw and a commit. + { + did_request_redraw_ = false; + did_request_commit_ = false; + ASSERT_TRUE(scrollbar_controller->ScrollbarsHidden()); + animation_task_.Run(); + + base::TimeTicks fake_now = base::TimeTicks::Now(); + scrollbar_controller->Animate(fake_now); + fake_now += settings.scrollbar_fade_duration; + scrollbar_controller->Animate(fake_now); + + ASSERT_FALSE(scrollbar_controller->ScrollbarsHidden()); + EXPECT_TRUE(did_request_redraw_); + EXPECT_TRUE(did_request_commit_); + } +} + TEST_F(LayerTreeHostImplTest, ScrollbarInnerLargerThanOuter) { LayerTreeSettings settings = DefaultSettings(); CreateHostImpl(settings, CreateCompositorFrameSink()); @@ -3122,9 +3292,8 @@ TEST_F(LayerTreeHostImplTest, ScrollbarInnerLargerThanOuter) { TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { LayerTreeSettings settings = DefaultSettings(); settings.scrollbar_animator = LayerTreeSettings::ANDROID_OVERLAY; - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_duration = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(20); CreateHostImpl(settings, CreateCompositorFrameSink()); gfx::Size viewport_size(300, 200); @@ -3192,6 +3361,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { // Check scrollbar registration on a sublayer. child->SetScrollClipLayer(child_clip->id()); + child->SetElementId(LayerIdToElementIdForTesting(child->id())); child_clip->test_properties()->AddChild(std::move(child)); root_scroll->test_properties()->AddChild(std::move(child_clip)); EXPECT_EQ(0ul, host_impl_->ScrollbarsFor(child_scroll_id).size()); @@ -3243,9 +3413,8 @@ TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( float device_scale_factor) { LayerTreeSettings settings = DefaultSettings(); - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(500); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(500); - settings.scrollbar_fade_out_duration = base::TimeDelta::FromMilliseconds(300); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(500); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(300); settings.scrollbar_animator = LayerTreeSettings::AURA_OVERLAY; gfx::Size viewport_size(300, 200); @@ -3290,31 +3459,24 @@ void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation * 2, 1)); - EXPECT_FALSE( - scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation - 1, 50)); - EXPECT_TRUE( - scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsNearScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation, 100)); - EXPECT_FALSE( - scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbar(VERTICAL)); did_request_redraw_ = false; - EXPECT_FALSE( - scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 100)); - EXPECT_TRUE( - scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 120)); - EXPECT_TRUE( - scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(150, 120)); - EXPECT_FALSE( - scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsOverScrollbar(VERTICAL)); } TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) { @@ -3325,6 +3487,43 @@ TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) { SetupMouseMoveAtWithDeviceScale(2.f); } +// This test verifies that only SurfaceLayers in the viewport are included +// in CompositorFrameMetadata's |embedded_surfaces|. +TEST_F(LayerTreeHostImplTest, EmbeddedSurfacesInMetadata) { + SetupScrollAndContentsLayers(gfx::Size(100, 100)); + host_impl_->SetViewportSize(gfx::Size(50, 50)); + LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing(); + + std::vector<SurfaceId> children = {MakeSurfaceId(FrameSinkId(1, 1), 1), + MakeSurfaceId(FrameSinkId(2, 2), 2), + MakeSurfaceId(FrameSinkId(3, 3), 3)}; + for (size_t i = 0; i < children.size(); ++i) { + std::unique_ptr<SurfaceLayerImpl> child = + SurfaceLayerImpl::Create(host_impl_->active_tree(), i + 6); + child->SetPosition(gfx::PointF(25.f * i, 0.f)); + child->SetBounds(gfx::Size(1, 1)); + child->SetDrawsContent(true); + child->SetPrimarySurfaceInfo( + SurfaceInfo(children[i], 1.f /* device_scale_factor */, + gfx::Size(10, 10) /* size_in_pixels */)); + root->test_properties()->AddChild(std::move(child)); + } + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + DrawFrame(); + + FakeCompositorFrameSink* fake_compositor_frame_sink = + static_cast<FakeCompositorFrameSink*>( + host_impl_->compositor_frame_sink()); + const CompositorFrameMetadata& metadata = + fake_compositor_frame_sink->last_sent_frame()->metadata; + EXPECT_THAT(metadata.embedded_surfaces, + testing::UnorderedElementsAre(children[0], children[1])); + EXPECT_THAT( + metadata.referenced_surfaces, + testing::UnorderedElementsAre(children[0], children[1], children[2])); +} + TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) { SetupScrollAndContentsLayers(gfx::Size(100, 100)); host_impl_->SetViewportSize(gfx::Size(50, 50)); @@ -3526,7 +3725,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) { host_impl_->active_tree()->BuildPropertyTreesForTesting(); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -3539,7 +3738,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) { host_impl_->SetViewportDamage(gfx::Rect(10, 10)); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; layer->set_will_draw_returns_false(); layer->ClearDidDrawCheck(); @@ -3572,7 +3771,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { layer->SetBounds(gfx::Size(10, 10)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_FALSE(layer->will_draw_called()); EXPECT_FALSE(layer->did_draw_called()); @@ -3629,7 +3828,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) { top_layer->SetContentsOpaque(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_FALSE(occluded_layer->will_draw_called()); EXPECT_FALSE(occluded_layer->did_draw_called()); @@ -3671,9 +3870,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) { EXPECT_FALSE(layer1->did_draw_called()); EXPECT_FALSE(layer2->did_draw_called()); - LayerTreeHostImpl::FrameData frame; - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren( - *host_impl_->active_tree()->begin()); + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -3842,7 +4039,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) { root->test_properties()->force_render_surface = true; host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -3869,7 +4066,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) { if (testcase.high_res_required) host_impl_->SetRequiresHighResToDraw(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -4038,6 +4235,7 @@ class LayerTreeHostImplBrowserControlsTest : public LayerTreeHostImplTest { root_clip->SetBounds(inner_viewport_size); root->SetScrollClipLayer(root_clip->id()); + root->SetElementId(LayerIdToElementIdForTesting(root->id())); root->SetBounds(outer_viewport_size); root->SetPosition(gfx::PointF()); root->SetDrawsContent(false); @@ -4045,6 +4243,8 @@ class LayerTreeHostImplBrowserControlsTest : public LayerTreeHostImplTest { root->test_properties()->is_container_for_fixed_position_layers = true; outer_clip->SetBounds(outer_viewport_size); outer_scroll->SetScrollClipLayer(outer_clip->id()); + outer_scroll->SetElementId( + LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->SetBounds(scroll_layer_size); outer_scroll->SetPosition(gfx::PointF()); outer_scroll->SetDrawsContent(false); @@ -4398,6 +4598,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, child_clip->SetBounds(sub_content_layer_size); child->SetScrollClipLayer(child_clip->id()); + child->SetElementId(LayerIdToElementIdForTesting(child->id())); child->SetBounds(sub_content_size); child->SetPosition(gfx::PointF()); child->SetDrawsContent(true); @@ -4944,6 +5145,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) { std::unique_ptr<LayerImpl> scroll_layer = LayerImpl::Create(host_impl_->active_tree(), 12); scroll_layer->SetScrollClipLayer(scroll_clip_layer->id()); + scroll_layer->SetElementId(LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(contents_size); scroll_layer->SetPosition(gfx::PointF()); scroll_layer->test_properties()->AddChild(std::move(content_layer)); @@ -5229,7 +5431,7 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) { // 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; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -5349,6 +5551,106 @@ TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) { } } +TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedLatchToChild) { + // Enable wheel scroll latching flag. + TestInputHandlerClient input_handler_client; + host_impl_->BindToClient(&input_handler_client, true); + + // Scroll a child layer beyond its maximum scroll range and make sure the + // parent layer isn't scrolled. + gfx::Size surface_size(100, 100); + gfx::Size content_size(150, 150); + + LayerImpl* root = + CreateBasicVirtualViewportLayers(surface_size, surface_size); + root->test_properties()->force_render_surface = true; + + root->test_properties()->force_render_surface = true; + std::unique_ptr<LayerImpl> grand_child = + CreateScrollableLayer(13, content_size, root); + + std::unique_ptr<LayerImpl> child = + CreateScrollableLayer(12, content_size, root); + LayerImpl* grand_child_layer = grand_child.get(); + child->test_properties()->AddChild(std::move(grand_child)); + + LayerImpl* child_layer = child.get(); + root->test_properties()->AddChild(std::move(child)); + host_impl_->active_tree()->SetElementIdsForTesting(); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + host_impl_->active_tree()->DidBecomeActive(); + + grand_child_layer->layer_tree_impl() + ->property_trees() + ->scroll_tree.UpdateScrollOffsetBaseForTesting(grand_child_layer->id(), + gfx::ScrollOffset(0, 30)); + child_layer->layer_tree_impl() + ->property_trees() + ->scroll_tree.UpdateScrollOffsetBaseForTesting(child_layer->id(), + gfx::ScrollOffset(0, 50)); + + host_impl_->SetViewportSize(surface_size); + DrawFrame(); + + base::TimeTicks start_time = + base::TimeTicks() + base::TimeDelta::FromMilliseconds(10); + + BeginFrameArgs begin_frame_args = + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); + + EXPECT_EQ( + InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, -100)).thread); + + begin_frame_args.frame_time = start_time; + begin_frame_args.sequence_number++; + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + + EXPECT_EQ(gfx::ScrollOffset(0, 30), grand_child_layer->CurrentScrollOffset()); + host_impl_->DidFinishImplFrame(); + + begin_frame_args.frame_time = + start_time + base::TimeDelta::FromMilliseconds(200); + begin_frame_args.sequence_number++; + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + + EXPECT_EQ(gfx::ScrollOffset(0, 0), grand_child_layer->CurrentScrollOffset()); + EXPECT_EQ(gfx::ScrollOffset(0, 50), child_layer->CurrentScrollOffset()); + host_impl_->DidFinishImplFrame(); + + // Second ScrollAnimated should still latch to the grand_child_layer. + EXPECT_EQ( + InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, -100)).thread); + + begin_frame_args.frame_time = + start_time + base::TimeDelta::FromMilliseconds(250); + begin_frame_args.sequence_number++; + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + host_impl_->DidFinishImplFrame(); + + begin_frame_args.frame_time = + start_time + base::TimeDelta::FromMilliseconds(450); + begin_frame_args.sequence_number++; + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + + EXPECT_EQ(gfx::ScrollOffset(0, 0), grand_child_layer->CurrentScrollOffset()); + EXPECT_EQ(gfx::ScrollOffset(0, 50), child_layer->CurrentScrollOffset()); + host_impl_->DidFinishImplFrame(); + + // Tear down the LayerTreeHostImpl before the InputHandlerClient. + host_impl_->ReleaseCompositorFrameSink(); + host_impl_ = nullptr; +} + TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) { // Scroll a child layer beyond its maximum scroll range and make sure the // the scroll doesn't bubble up to the parent layer. @@ -5894,58 +6196,6 @@ TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) { inner_viewport_scroll_layer->MaxScrollOffset()); } -class TestInputHandlerClient : public InputHandlerClient { - public: - TestInputHandlerClient() - : page_scale_factor_(0.f), - min_page_scale_factor_(-1.f), - max_page_scale_factor_(-1.f) {} - ~TestInputHandlerClient() override {} - - // InputHandlerClient implementation. - void WillShutdown() override {} - void Animate(base::TimeTicks time) override {} - void MainThreadHasStoppedFlinging() override {} - void ReconcileElasticOverscrollAndRootScroll() override {} - void UpdateRootLayerStateForSynchronousInputHandler( - const gfx::ScrollOffset& total_scroll_offset, - const gfx::ScrollOffset& max_scroll_offset, - const gfx::SizeF& scrollable_size, - float page_scale_factor, - float min_page_scale_factor, - float max_page_scale_factor) override { - DCHECK(total_scroll_offset.x() <= max_scroll_offset.x()); - DCHECK(total_scroll_offset.y() <= max_scroll_offset.y()); - last_set_scroll_offset_ = total_scroll_offset; - max_scroll_offset_ = max_scroll_offset; - scrollable_size_ = scrollable_size; - page_scale_factor_ = page_scale_factor; - min_page_scale_factor_ = min_page_scale_factor; - max_page_scale_factor_ = max_page_scale_factor; - } - void DeliverInputForBeginFrame() override {} - - gfx::ScrollOffset last_set_scroll_offset() { return last_set_scroll_offset_; } - - gfx::ScrollOffset max_scroll_offset() const { return max_scroll_offset_; } - - gfx::SizeF scrollable_size() const { return scrollable_size_; } - - float page_scale_factor() const { return page_scale_factor_; } - - float min_page_scale_factor() const { return min_page_scale_factor_; } - - float max_page_scale_factor() const { return max_page_scale_factor_; } - - private: - gfx::ScrollOffset last_set_scroll_offset_; - gfx::ScrollOffset max_scroll_offset_; - gfx::SizeF scrollable_size_; - float page_scale_factor_; - float min_page_scale_factor_; - float max_page_scale_factor_; -}; - TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { TestInputHandlerClient scroll_watcher; host_impl_->SetViewportSize(gfx::Size(10, 20)); @@ -5955,7 +6205,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { clip_layer->SetBounds(gfx::Size(10, 20)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - host_impl_->BindToClient(&scroll_watcher); + host_impl_->BindToClient(&scroll_watcher, false); gfx::Vector2dF initial_scroll_delta(10.f, 10.f); scroll_layer->layer_tree_impl() @@ -6078,7 +6328,7 @@ TEST_F(LayerTreeHostImplTest, host_impl_->active_tree()->BuildPropertyTreesForTesting(); // Check scroll delta reflected in layer. - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -6527,6 +6777,7 @@ TEST_F(LayerTreeHostImplTest, ScrollFromOuterViewportSibling) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); scroll_layer = scroll.get(); @@ -6617,6 +6868,7 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); std::unique_ptr<LayerImpl> clip2 = LayerImpl::Create(layer_tree_impl, 12); @@ -6627,6 +6879,7 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) { std::unique_ptr<LayerImpl> scroll2 = LayerImpl::Create(layer_tree_impl, 13); scroll2->SetBounds(gfx::Size(500, 500)); scroll2->SetScrollClipLayer(clip2->id()); + scroll2->SetElementId(LayerIdToElementIdForTesting(scroll2->id())); scroll2->SetDrawsContent(true); scroll_layer = scroll.get(); @@ -6748,6 +7001,7 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(1200, 1200)); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); outer_scroll_layer = scroll.get(); @@ -6763,6 +7017,7 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) { std::unique_ptr<LayerImpl> scroll2 = LayerImpl::Create(layer_tree_impl, 15); scroll2->SetBounds(gfx::Size(1200, 1200)); scroll2->SetScrollClipLayer(clip2->id()); + scroll2->SetElementId(LayerIdToElementIdForTesting(scroll2->id())); scroll2->SetDrawsContent(true); sibling_scroll_layer = scroll2.get(); @@ -7027,7 +7282,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { static_cast<BlendStateCheckLayer*>(root->test_properties()->children[0]); layer1->SetPosition(gfx::PointF(2.f, 2.f)); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; // Opaque layer, drawn without blending. layer1->SetContentsOpaque(true); @@ -7142,8 +7397,6 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetExpectation(false, false); layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren( - host_impl_->active_tree()->root_layer_for_testing()); host_impl_->active_tree()->BuildPropertyTreesForTesting(); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); @@ -7269,7 +7522,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { static bool MayContainVideoBitSetOnFrameData(LayerTreeHostImpl* host_impl) { host_impl->active_tree()->BuildPropertyTreesForTesting(); host_impl->active_tree()->set_needs_update_draw_properties(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl->PrepareToDraw(&frame)); host_impl->DrawLayers(&frame); host_impl->DidDrawAllLayers(frame); @@ -7359,7 +7612,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); ASSERT_EQ(1u, frame.render_passes.size()); @@ -7393,7 +7646,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { void TestEmptyLayer() { SetUpEmptylayer(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); VerifyEmptyLayerRenderPasses(frame.render_passes); host_impl_->DidDrawAllLayers(frame); @@ -7430,7 +7683,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { void TestLayerInMiddleOfViewport() { SetUpLayerInMiddleOfViewport(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); VerifyLayerInMiddleOfViewport(frame.render_passes); host_impl_->DidDrawAllLayers(frame); @@ -7466,7 +7719,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { void TestLayerIsLargerThanViewport() { SetUpLayerIsLargerThanViewport(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); VerifyLayerIsLargerThanViewport(frame.render_passes); host_impl_->DidDrawAllLayers(frame); @@ -7664,7 +7917,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { layer_tree_host_impl->active_tree()->SetRootLayerForTesting(std::move(root)); layer_tree_host_impl->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; // First frame, the entire screen should get swapped. EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame)); @@ -7726,7 +7979,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) { host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); EXPECT_EQ(1u, frame.render_surface_layer_list->size()); @@ -7845,7 +8098,7 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) { DefaultSettings(), true, this, &task_runner_provider_, &task_graph_runner, &stats_instrumentation_, compositor_frame_sink.get()); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); // Verify all quads have been computed @@ -7874,7 +8127,7 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) { DefaultSettings(), false, this, &task_runner_provider_, &task_graph_runner, &stats_instrumentation_, compositor_frame_sink.get()); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); // Verify all quads have been computed @@ -7920,7 +8173,7 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { EXPECT_EQ(0u, context3d->NumTextures()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -7948,7 +8201,7 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) { // Verify one quad is drawn when transparent background set is not set. host_impl_->active_tree()->set_has_transparent_background(false); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); { const auto& root_pass = frame.render_passes.back(); @@ -7982,7 +8235,7 @@ class LayerTreeHostImplTestDrawAndTestDamage : public LayerTreeHostImplTest { void DrawFrameAndTestDamage(const gfx::Rect& expected_damage) { bool expect_to_draw = !expected_damage.IsEmpty(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); if (!expect_to_draw) { @@ -8024,6 +8277,7 @@ TEST_F(LayerTreeHostImplTestDrawAndTestDamage, FrameIncludesDamageRect) { root->SetPosition(gfx::PointF()); root->SetBounds(gfx::Size(10, 10)); root->SetDrawsContent(true); + root->SetBackgroundColor(SK_ColorRED); root->test_properties()->force_render_surface = true; // Child layer is in the bottom right corner. @@ -8032,6 +8286,7 @@ TEST_F(LayerTreeHostImplTestDrawAndTestDamage, FrameIncludesDamageRect) { child->SetPosition(gfx::PointF(9.f, 9.f)); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); + child->SetBackgroundColor(SK_ColorRED); root->test_properties()->AddChild(std::move(child)); host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); @@ -8100,6 +8355,8 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) { gfx::ScrollOffset scroll_offset(100000, 0); scrolling_layer->SetScrollClipLayer(root->id()); + scrolling_layer->SetElementId( + LayerIdToElementIdForTesting(scrolling_layer->id())); host_impl_->pending_tree()->BuildPropertyTreesForTesting(); scrolling_layer->layer_tree_impl() @@ -8112,7 +8369,7 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) { host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text); ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); ASSERT_EQ(1u, frame.render_passes.size()); @@ -8147,7 +8404,7 @@ TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) { SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -8301,12 +8558,36 @@ TEST_F(LayerTreeHostImplTest, MemoryLimits) { } } -TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) { +namespace { +void ExpectFullDamageAndDraw(LayerTreeHostImpl* host_impl) { + gfx::Rect full_frame_damage(host_impl->DeviceViewport().size()); + TestFrameData frame; + EXPECT_EQ(DRAW_SUCCESS, host_impl->PrepareToDraw(&frame)); + ASSERT_EQ(1u, frame.render_passes.size()); + const RenderPass* root_render_pass = frame.render_passes.back().get(); + EXPECT_EQ(full_frame_damage, root_render_pass->damage_rect); + EXPECT_TRUE(host_impl->DrawLayers(&frame)); + host_impl->DidDrawAllLayers(frame); +} +} // namespace + +TEST_F(LayerTreeHostImplTestDrawAndTestDamage, + RequireHighResAndRedrawWhenVisible) { ASSERT_TRUE(host_impl_->active_tree()); + std::unique_ptr<SolidColorLayerImpl> root = + SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); + root->SetBackgroundColor(SK_ColorRED); + SetupRootLayerImpl(std::move(root)); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + // RequiresHighResToDraw is set when new output surface is used. EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); + // Expect full frame damage for first frame. + EXPECT_SCOPED(ExpectFullDamageAndDraw(host_impl_.get())); + host_impl_->ResetRequiresHighResToDraw(); host_impl_->SetVisible(false); @@ -8319,8 +8600,12 @@ TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) { host_impl_->ResetRequiresHighResToDraw(); EXPECT_FALSE(host_impl_->RequiresHighResToDraw()); + did_request_redraw_ = false; host_impl_->SetVisible(true); EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); + // Expect redraw and full frame damage when becoming visible. + EXPECT_TRUE(did_request_redraw_); + EXPECT_SCOPED(ExpectFullDamageAndDraw(host_impl_.get())); } TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) { @@ -8432,7 +8717,7 @@ TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { // correct width/height are passed directly to UIResourceBitmap. SkImageInfo info = SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType); - sk_sp<SkPixelRef> pixel_ref(SkMallocPixelRef::NewAllocate(info, 0, 0)); + sk_sp<SkPixelRef> pixel_ref(SkMallocPixelRef::MakeAllocate(info, 0, 0)); pixel_ref->setImmutable(); UIResourceBitmap bitmap(std::move(pixel_ref), size); UIResourceId ui_resource_id = 1; @@ -8456,6 +8741,8 @@ class FrameSinkClient : public TestCompositorFrameSinkClient { return FakeOutputSurface::Create3d(std::move(display_context_provider_)); } + void DisplayReceivedLocalSurfaceId( + const LocalSurfaceId& local_surface_id) override {} void DisplayReceivedCompositorFrame(const CompositorFrame& frame) override {} void DisplayWillDrawAndSwap(bool will_draw_and_swap, const RenderPassList& render_passes) override {} @@ -8487,7 +8774,7 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) { base::Bind(&ShutdownReleasesContext_Callback))); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -8836,7 +9123,7 @@ TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) { host_impl_->active_tree()->QueuePinnedSwapPromise(std::move(swap_promise)); gfx::Rect full_frame_damage(host_impl_->DrawViewportSize()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); EXPECT_TRUE(host_impl_->DrawLayers(&frame)); host_impl_->DidDrawAllLayers(frame); @@ -8880,7 +9167,7 @@ TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) { host_impl_->SetNeedsRedraw(); gfx::Rect full_frame_damage(host_impl_->DrawViewportSize()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); EXPECT_TRUE(host_impl_->DrawLayers(&frame)); host_impl_->DidDrawAllLayers(frame); @@ -9550,6 +9837,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(scroll_content_size); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); scroll_layer = scroll.get(); @@ -9611,6 +9899,8 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); inner_scroll->SetScrollClipLayer(inner_clip->id()); + inner_scroll->SetElementId( + LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(outer_viewport); inner_scroll->SetPosition(gfx::PointF()); @@ -9623,6 +9913,8 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { std::unique_ptr<LayerImpl> outer_scroll = LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId); outer_scroll->SetScrollClipLayer(outer_clip->id()); + outer_scroll->SetElementId( + LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(outer_scroll->id(), @@ -10065,26 +10357,31 @@ TEST_F(LayerTreeHostImplTest, OnDrawConstraintSetNeedsRedraw) { EXPECT_FALSE(last_on_draw_frame_->has_no_damage); } -// We will force the touch event handler to be passive if we touch on a -// layer which is the current scrolling layer or its descendant. -TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { +// We will force the touch event handler to be passive if we touch on a layer +// which is the current scrolling layer. +TEST_F(LayerTreeHostImplTest, TouchInsideFlingLayer) { gfx::Size surface_size(100, 100); - gfx::Size inner_size(50, 50); + gfx::Size content_size(200, 200); LayerImpl* root = CreateBasicVirtualViewportLayers(surface_size, surface_size); root->test_properties()->force_render_surface = true; + // A div layer which has an event handler. std::unique_ptr<LayerImpl> child = CreateScrollableLayer(26, surface_size, root); LayerImpl* child_layer = child.get(); + // The layer tree should create a layer for the div layer, which is the + // actual scrolling layer. std::unique_ptr<LayerImpl> grand_child = - CreateScrollableLayer(27, inner_size, root); + CreateScrollableLayer(27, content_size, root); LayerImpl* grand_child_layer = grand_child.get(); + child->test_properties()->AddChild(std::move(grand_child)); root->test_properties()->AddChild(std::move(child)); + host_impl_->SetViewportSize(surface_size); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->DidBecomeActive(); DrawFrame(); @@ -10094,10 +10391,9 @@ TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { EXPECT_EQ(InputHandler::TouchStartEventListenerType::NO_HANDLER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(10, 10))); child_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100)); - grand_child_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100)); EXPECT_EQ(InputHandler::TouchStartEventListenerType::HANDLER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(10, 10))); - // Flinging the child layer. + // Flinging the grand_child layer. EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, host_impl_ ->ScrollBegin(BeginState(gfx::Point(60, 60)).get(), @@ -10105,20 +10401,78 @@ TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { .thread); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, host_impl_->FlingScrollBegin().thread); - EXPECT_EQ(child_layer->scroll_tree_index(), + EXPECT_EQ(grand_child_layer->scroll_tree_index(), host_impl_->CurrentlyScrollingNode()->id); - // Touch on the child layer, which is an active fling layer, the touch + // Touch on the grand_child layer, which is an active fling layer, the touch // event handler will force to be passive. EXPECT_EQ( InputHandler::TouchStartEventListenerType::HANDLER_ON_SCROLLING_LAYER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(70, 80))); - // Touch on the grand child layer, which is a descendant of an active fling - // layer, the touch event handler will force to be passive. + } +} + +// We will force the touch event handler to be passive if we touch on a layer +// which is a descendant of the current scrolling layer. If we touch on its +// ancestor, then the touch event handler will still be blocked. +TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { + gfx::Size surface_size(100, 100); + gfx::Size content_size(200, 200); + gfx::Size inner_size(50, 50); + + LayerImpl* root = + CreateBasicVirtualViewportLayers(surface_size, surface_size); + root->test_properties()->force_render_surface = true; + + // A div layer which has an event handler. + std::unique_ptr<LayerImpl> child = + CreateScrollableLayer(26, surface_size, root); + LayerImpl* child_layer = child.get(); + + // The layer tree should create a layer for the div layer, which is the + // actual scrolling layer. + std::unique_ptr<LayerImpl> grand_child = + CreateScrollableLayer(27, content_size, root); + LayerImpl* grand_child_layer = grand_child.get(); + + // A child scrollable layer inside grand_child_layer. + std::unique_ptr<LayerImpl> great_grand_child = + CreateScrollableLayer(28, inner_size, root); + LayerImpl* great_grand_child_layer = great_grand_child.get(); + + grand_child->test_properties()->AddChild(std::move(great_grand_child)); + child->test_properties()->AddChild(std::move(grand_child)); + root->test_properties()->AddChild(std::move(child)); + + host_impl_->SetViewportSize(surface_size); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + host_impl_->active_tree()->DidBecomeActive(); + DrawFrame(); + + { + child_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100)); + grand_child_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 50, 50)); + // Flinging the grand_child layer. + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_ + ->ScrollBegin(BeginState(gfx::Point(60, 60)).get(), + InputHandler::TOUCHSCREEN) + .thread); + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_->FlingScrollBegin().thread); + EXPECT_EQ(grand_child_layer->scroll_tree_index(), + host_impl_->CurrentlyScrollingNode()->id); + // Touch on the grand_child layer, which is an active fling layer, the touch + // event handler will force to be passive. + EXPECT_EQ( + InputHandler::TouchStartEventListenerType::HANDLER_ON_SCROLLING_LAYER, + host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(70, 80))); + // Touch on the great_grand_child_layer layer, which is the child of the + // active fling layer, the touch event handler will force to be passive. EXPECT_EQ( InputHandler::TouchStartEventListenerType::HANDLER_ON_SCROLLING_LAYER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(20, 30))); - // Now flinging on the grand child layer. + // Now flinging on the great_grand_child_layer. EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, host_impl_ ->ScrollBegin(BeginState(gfx::Point(10, 10)).get(), @@ -10126,9 +10480,9 @@ TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { .thread); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, host_impl_->FlingScrollBegin().thread); - EXPECT_EQ(grand_child_layer->scroll_tree_index(), + EXPECT_EQ(great_grand_child_layer->scroll_tree_index(), host_impl_->CurrentlyScrollingNode()->id); - // Touch on the child layer, the touch event handler will still be blocking. + // Touch on the child layer, the touch event handler will be blocked. EXPECT_EQ(InputHandler::TouchStartEventListenerType::HANDLER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(60, 60))); } @@ -11007,7 +11361,7 @@ TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) { layer->SetBounds(gfx::Size(10, 10)); layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size()); layer->SetDrawsContent(true); - layer->tilings()->AddTiling(1.0f, raster_source_with_tiles); + layer->tilings()->AddTiling(gfx::AxisTransform2d(), raster_source_with_tiles); layer->UpdateRasterSource(raster_source_with_tiles, &empty_invalidation, nullptr); layer->tilings()->tiling_at(0)->set_resolution( @@ -11141,7 +11495,7 @@ size_t CountRenderPassesWithId(const RenderPassList& list, int id) { } TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; frame.render_passes.push_back(RenderPass::Create()); RenderPass* pass3 = frame.render_passes.back().get(); frame.render_passes.push_back(RenderPass::Create()); @@ -11178,7 +11532,7 @@ TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) { } TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; frame.render_passes.push_back(RenderPass::Create()); RenderPass* pass3 = frame.render_passes.back().get(); frame.render_passes.push_back(RenderPass::Create()); @@ -11220,7 +11574,7 @@ TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) { } TEST_F(LayerTreeHostImplTest, DoNotRemoveEmptyRootRenderPass) { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; frame.render_passes.push_back(RenderPass::Create()); RenderPass* pass3 = frame.render_passes.back().get(); frame.render_passes.push_back(RenderPass::Create()); @@ -11286,7 +11640,7 @@ TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) { host_impl_->DidFinishImplFrame(); EXPECT_FALSE(controller.did_draw_frame()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; host_impl_->DidDrawAllLayers(frame); EXPECT_TRUE(controller.did_draw_frame()); @@ -11315,7 +11669,7 @@ TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) { EXPECT_TRUE(controller.begin_frame_args().IsValid()); EXPECT_FALSE(controller.did_draw_frame()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; host_impl_->DidDrawAllLayers(frame); EXPECT_TRUE(controller.did_draw_frame()); @@ -11707,9 +12061,8 @@ TEST_F(LayerTreeHostImplTest, RecomputeGpuRasterOnCompositorFrameSinkChange) { void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( bool main_thread_scrolling) { LayerTreeSettings settings = DefaultSettings(); - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(500); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(500); - settings.scrollbar_fade_out_duration = base::TimeDelta::FromMilliseconds(300); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(500); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(300); settings.scrollbar_animator = LayerTreeSettings::AURA_OVERLAY; gfx::Size viewport_size(300, 200); @@ -11770,32 +12123,28 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation, 150)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(14 + kMouseDistanceToTriggerAnimation, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(14 + kMouseDistanceToTriggerAnimation, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation, 150)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); // scrollbar_2 on child. std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar_2 = @@ -11810,6 +12159,7 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( child->SetBounds(child_layer_size); child->SetDrawsContent(true); child->SetScrollClipLayer(child_clip_id); + child->SetElementId(LayerIdToElementIdForTesting(child->id())); if (main_thread_scrolling) { child->set_main_thread_scrolling_reasons( @@ -11835,42 +12185,36 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( // scrollbar_1, goes over scrollbar_1. host_impl_->MouseMoveAt(gfx::Point(60, 150)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(64 + kMouseDistanceToTriggerAnimation, 150)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(14 + kMouseDistanceToTriggerAnimation, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsOverScrollbar(VERTICAL)); // Capture scrollbar_1, then move mouse to scrollbar_2's layer, should post an // event to fade out scrollbar_1. diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc index 1a25a13cb11..ff17af70317 100644 --- a/chromium/cc/trees/layer_tree_host_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_perftest.cc @@ -13,7 +13,7 @@ #include "base/path_service.h" #include "base/strings/string_piece.h" #include "base/time/time.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/layers/nine_patch_layer.h" #include "cc/layers/solid_color_layer.h" #include "cc/layers/texture_layer.h" @@ -59,10 +59,8 @@ class LayerTreeHostPerfTest : public LayerTreeTest { } void BeginMainFrame(const BeginFrameArgs& args) override { - if (begin_frame_driven_drawing_ && !TestEnded()) { - layer_tree_host()->SetNeedsAnimate(); - layer_tree_host()->SetNextCommitForcesRedraw(); - } + if (begin_frame_driven_drawing_ && !TestEnded()) + layer_tree_host()->SetNeedsCommitWithForcedRedraw(); } void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override { @@ -309,9 +307,9 @@ class BrowserCompositorInvalidateLayerTreePerfTest clean_up_started_ = true; MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&BrowserCompositorInvalidateLayerTreePerfTest:: - CleanUpAndEndTestOnMainThread, - base::Unretained(this))); + base::BindOnce(&BrowserCompositorInvalidateLayerTreePerfTest:: + CleanUpAndEndTestOnMainThread, + base::Unretained(this))); } void CleanUpAndEndTestOnMainThread() { diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc index bd43e52f94f..eed99f6a625 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -9,10 +9,9 @@ #include "cc/layers/picture_image_layer.h" #include "cc/layers/picture_layer.h" #include "cc/layers/solid_color_layer.h" +#include "cc/paint/drawing_display_item.h" #include "cc/paint/paint_flags.h" #include "cc/paint/paint_recorder.h" -#include "cc/paint/paint_surface.h" -#include "cc/playback/drawing_display_item.h" #include "cc/test/layer_tree_pixel_resource_test.h" #include "cc/test/pixel_comparator.h" #include "cc/test/solid_color_content_layer_client.h" diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc index b74968e44c3..d6145d577c8 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc @@ -7,11 +7,11 @@ #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_layer.h" #include "cc/output/copy_output_request.h" +#include "cc/paint/display_item_list.h" +#include "cc/paint/drawing_display_item.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" #include "cc/paint/paint_recorder.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_compositor_frame_sink.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -203,15 +203,30 @@ TEST_F(LayerTreeHostTilesTestPartialInvalidation, base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png"))); } +// crbug.com/707711 +#if defined(OS_LINUX) +#define MAYBE_PartialRaster_MultiThread_OneCopy \ + DISABLED_PartialRaster_MultiThread_OneCopy +#else +#define MAYBE_PartialRaster_MultiThread_OneCopy \ + PartialRaster_MultiThread_OneCopy +#endif TEST_F(LayerTreeHostTilesTestPartialInvalidation, - PartialRaster_MultiThread_OneCopy) { + MAYBE_PartialRaster_MultiThread_OneCopy) { RunRasterPixelTest( true, PARTIAL_ONE_COPY, picture_layer_, base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png"))); } +// crbug.com/707711 +#if defined(OS_LINUX) +#define MAYBE_FullRaster_MultiThread_OneCopy \ + DISABLED_FullRaster_MultiThread_OneCopy +#else +#define MAYBE_FullRaster_MultiThread_OneCopy FullRaster_MultiThread_OneCopy +#endif TEST_F(LayerTreeHostTilesTestPartialInvalidation, - FullRaster_MultiThread_OneCopy) { + MAYBE_FullRaster_MultiThread_OneCopy) { RunRasterPixelTest( true, FULL_ONE_COPY, picture_layer_, base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png"))); diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index 1f2059cb0c3..2e7457a49aa 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -17,9 +17,9 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/timing_function.h" -#include "cc/debug/frame_rate_counter.h" #include "cc/input/scroll_elasticity_helper.h" #include "cc/layers/content_layer_client.h" +#include "cc/layers/heads_up_display_layer.h" #include "cc/layers/layer_impl.h" #include "cc/layers/painted_scrollbar_layer.h" #include "cc/layers/picture_layer.h" @@ -34,6 +34,7 @@ #include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/tile_draw_quad.h" #include "cc/resources/ui_resource_manager.h" +#include "cc/test/begin_frame_args_test.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_output_surface.h" @@ -52,7 +53,9 @@ #include "cc/test/skia_common.h" #include "cc/test/test_compositor_frame_sink.h" #include "cc/test/test_web_graphics_context_3d.h" +#include "cc/trees/clip_node.h" #include "cc/trees/effect_node.h" +#include "cc/trees/frame_rate_counter.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" @@ -802,7 +805,7 @@ class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest { void DidCommit() override { switch (layer_tree_host()->SourceFrameNumber()) { case 1: - // child_ should create transform, effect, clip node. + // child_ should create transform, effect node. child_->SetForceRenderSurfaceForTesting(true); break; case 2: @@ -810,7 +813,12 @@ class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest { child_->SetScrollClipLayerId(root_->id()); break; case 3: + // child_ should create a clip node. + child_->SetMasksToBounds(true); + break; + case 4: // child_ should not create any property tree node. + child_->SetMasksToBounds(false); child_->SetForceRenderSurfaceForTesting(false); child_->SetScrollClipLayerId(Layer::INVALID_ID); } @@ -818,92 +826,64 @@ class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest { void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { PropertyTrees* property_trees = impl->sync_tree()->property_trees(); - auto root_transform_id_to_index = - property_trees->layer_id_to_transform_node_index.find(root_->id()); - auto child_transform_id_to_index = - property_trees->layer_id_to_transform_node_index.find(child_->id()); - auto root_effect_id_to_index = - property_trees->layer_id_to_effect_node_index.find(root_->id()); - auto child_effect_id_to_index = - property_trees->layer_id_to_effect_node_index.find(child_->id()); - auto root_clip_id_to_index = - property_trees->layer_id_to_clip_node_index.find(root_->id()); - auto child_clip_id_to_index = - property_trees->layer_id_to_clip_node_index.find(child_->id()); - auto root_scroll_id_to_index = - property_trees->layer_id_to_scroll_node_index.find(root_->id()); - auto child_scroll_id_to_index = - property_trees->layer_id_to_scroll_node_index.find(child_->id()); + const TransformNode* root_transform_node = + property_trees->transform_tree.FindNodeFromOwningLayerId(root_->id()); + const TransformNode* child_transform_node = + property_trees->transform_tree.FindNodeFromOwningLayerId(child_->id()); + const EffectNode* root_effect_node = + property_trees->effect_tree.FindNodeFromOwningLayerId(root_->id()); + const EffectNode* child_effect_node = + property_trees->effect_tree.FindNodeFromOwningLayerId(child_->id()); + const ClipNode* root_clip_node = + property_trees->clip_tree.FindNodeFromOwningLayerId(root_->id()); + const ClipNode* child_clip_node = + property_trees->clip_tree.FindNodeFromOwningLayerId(child_->id()); + const ScrollNode* root_scroll_node = + property_trees->scroll_tree.FindNodeFromOwningLayerId(root_->id()); + const ScrollNode* child_scroll_node = + property_trees->scroll_tree.FindNodeFromOwningLayerId(child_->id()); switch (impl->sync_tree()->source_frame_number()) { case 0: - // root_ should create every property tree node and child_ should not - // create any. - EXPECT_NE(root_transform_id_to_index, - property_trees->layer_id_to_transform_node_index.end()); - EXPECT_EQ(root_transform_id_to_index->second, - root_->transform_tree_index()); - EXPECT_NE(root_effect_id_to_index, - property_trees->layer_id_to_effect_node_index.end()); - EXPECT_EQ(root_effect_id_to_index->second, root_->effect_tree_index()); - EXPECT_NE(root_clip_id_to_index, - property_trees->layer_id_to_clip_node_index.end()); - EXPECT_EQ(root_clip_id_to_index->second, root_->clip_tree_index()); - EXPECT_NE(root_scroll_id_to_index, - property_trees->layer_id_to_scroll_node_index.end()); - EXPECT_EQ(root_scroll_id_to_index->second, root_->scroll_tree_index()); - EXPECT_EQ(child_transform_id_to_index, - property_trees->layer_id_to_transform_node_index.end()); - EXPECT_EQ(child_effect_id_to_index, - property_trees->layer_id_to_effect_node_index.end()); - EXPECT_EQ(child_clip_id_to_index, - property_trees->layer_id_to_clip_node_index.end()); - EXPECT_EQ(child_scroll_id_to_index, - property_trees->layer_id_to_scroll_node_index.end()); + // root_ should create transform, scroll and effect tree nodes but not + // a clip node. + EXPECT_NE(root_transform_node, nullptr); + EXPECT_EQ(root_transform_node->id, root_->transform_tree_index()); + EXPECT_NE(root_effect_node, nullptr); + EXPECT_EQ(root_effect_node->id, root_->effect_tree_index()); + EXPECT_NE(root_scroll_node, nullptr); + EXPECT_EQ(root_scroll_node->id, root_->scroll_tree_index()); + EXPECT_EQ(root_clip_node, nullptr); + EXPECT_EQ(child_transform_node, nullptr); + EXPECT_EQ(child_effect_node, nullptr); + EXPECT_EQ(child_clip_node, nullptr); + EXPECT_EQ(child_scroll_node, nullptr); break; case 1: - // child_ should create a transfrom, clip, effect nodes but not a scroll + // child_ should create a transfrom, effect nodes but not a scroll, clip // node. - EXPECT_NE( - property_trees->layer_id_to_transform_node_index.find(child_->id()), - property_trees->layer_id_to_transform_node_index.end()); - EXPECT_EQ(child_transform_id_to_index->second, - child_->transform_tree_index()); - EXPECT_NE( - property_trees->layer_id_to_effect_node_index.find(child_->id()), - property_trees->layer_id_to_effect_node_index.end()); - EXPECT_EQ(child_effect_id_to_index->second, - child_->effect_tree_index()); - EXPECT_NE( - property_trees->layer_id_to_clip_node_index.find(child_->id()), - property_trees->layer_id_to_clip_node_index.end()); - EXPECT_EQ(child_clip_id_to_index->second, child_->clip_tree_index()); - EXPECT_EQ( - property_trees->layer_id_to_scroll_node_index.find(child_->id()), - property_trees->layer_id_to_scroll_node_index.end()); + EXPECT_NE(child_transform_node, nullptr); + EXPECT_EQ(child_transform_node->id, child_->transform_tree_index()); + EXPECT_NE(child_effect_node, nullptr); + EXPECT_EQ(child_effect_node->id, child_->effect_tree_index()); + EXPECT_EQ(child_clip_node, nullptr); + EXPECT_EQ(child_scroll_node, nullptr); break; case 2: // child_ should create a scroll node. - EXPECT_NE( - property_trees->layer_id_to_scroll_node_index.find(child_->id()), - property_trees->layer_id_to_scroll_node_index.end()); - EXPECT_EQ(child_scroll_id_to_index->second, - child_->scroll_tree_index()); + EXPECT_NE(child_scroll_node, nullptr); + EXPECT_EQ(child_scroll_node->id, child_->scroll_tree_index()); break; case 3: + // child_ should create a clip node. + EXPECT_NE(child_clip_node, nullptr); + EXPECT_EQ(child_clip_node->id, child_->clip_tree_index()); + break; + case 4: // child_ should not create any property tree nodes. - EXPECT_EQ( - property_trees->layer_id_to_transform_node_index.find(child_->id()), - property_trees->layer_id_to_transform_node_index.end()); - EXPECT_EQ( - property_trees->layer_id_to_effect_node_index.find(child_->id()), - property_trees->layer_id_to_effect_node_index.end()); - EXPECT_EQ( - property_trees->layer_id_to_clip_node_index.find(child_->id()), - property_trees->layer_id_to_clip_node_index.end()); - EXPECT_EQ( - property_trees->layer_id_to_scroll_node_index.find(child_->id()), - property_trees->layer_id_to_scroll_node_index.end()); - + EXPECT_EQ(child_transform_node, nullptr); + EXPECT_EQ(child_effect_node, nullptr); + EXPECT_EQ(child_clip_node, nullptr); + EXPECT_EQ(child_scroll_node, nullptr); EndTest(); break; } @@ -923,7 +903,6 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { void SetupTree() override { root_ = Layer::Create(); child_ = Layer::Create(); - child_->SetElementId(kTestElementId); root_->AddChild(child_); layer_tree_host()->SetRootLayer(root_); LayerTreeHostTest::SetupTree(); @@ -961,13 +940,13 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { ->property_trees() ->scroll_tree.size()); EXPECT_TRUE(property_trees->element_id_to_transform_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_transform_node_index.end()); EXPECT_TRUE(property_trees->element_id_to_effect_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_effect_node_index.end()); EXPECT_TRUE(property_trees->element_id_to_scroll_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_scroll_node_index.end()); break; case 1: @@ -981,12 +960,14 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { ->property_trees() ->scroll_tree.size()); EXPECT_EQ( - 2, - property_trees->element_id_to_transform_node_index[kTestElementId]); - EXPECT_EQ( - 2, property_trees->element_id_to_effect_node_index[kTestElementId]); - EXPECT_EQ( - 2, property_trees->element_id_to_scroll_node_index[kTestElementId]); + 2, property_trees + ->element_id_to_transform_node_index[child_->element_id()]); + EXPECT_EQ(2, + property_trees + ->element_id_to_effect_node_index[child_->element_id()]); + EXPECT_EQ(2, + property_trees + ->element_id_to_scroll_node_index[child_->element_id()]); break; case 2: EXPECT_EQ(2U, child_impl_->layer_tree_impl() @@ -996,13 +977,13 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { ->property_trees() ->effect_tree.size()); EXPECT_TRUE(property_trees->element_id_to_transform_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_transform_node_index.end()); EXPECT_TRUE(property_trees->element_id_to_effect_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_effect_node_index.end()); EXPECT_TRUE(property_trees->element_id_to_scroll_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_scroll_node_index.end()); break; } @@ -1012,8 +993,6 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { void AfterTest() override {} private: - const ElementId kTestElementId = ElementId(42, 8118); - scoped_refptr<Layer> root_; scoped_refptr<Layer> child_; }; @@ -1149,8 +1128,7 @@ class LayerTreeHostTestPropertyTreesChangedSync : public LayerTreeHostTest { case OPACITY: index_++; impl->active_tree()->ResetAllChangeTracking(); - impl->active_tree()->property_trees()->effect_tree.OnOpacityAnimated( - 0.5f, root->effect_tree_index(), impl->active_tree()); + impl->active_tree()->SetOpacityMutated(root->element_id(), 0.5f); PostSetNeedsCommitToMainThread(); break; case TRANSFORM: @@ -1166,10 +1144,7 @@ class LayerTreeHostTestPropertyTreesChangedSync : public LayerTreeHostTest { ->LayerById(child_->id()) ->LayerPropertyChanged()); transform.Translate(10, 10); - impl->active_tree() - ->property_trees() - ->transform_tree.OnTransformAnimated( - transform, root->transform_tree_index(), impl->active_tree()); + impl->active_tree()->SetTransformMutated(root->element_id(), transform); PostSetNeedsCommitToMainThread(); break; case FILTER: @@ -1184,8 +1159,7 @@ class LayerTreeHostTestPropertyTreesChangedSync : public LayerTreeHostTest { ->LayerById(child_->id()) ->LayerPropertyChanged()); filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); - impl->active_tree()->property_trees()->effect_tree.OnFilterAnimated( - filters, root->effect_tree_index(), impl->active_tree()); + impl->active_tree()->SetFilterMutated(root->element_id(), filters); PostSetNeedsCommitToMainThread(); break; case END: @@ -1259,8 +1233,7 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { EffectNode* node = effect_tree.Node(root->effect_tree_index()); switch (impl->sync_tree()->source_frame_number()) { case 0: - effect_tree.OnOpacityAnimated(0.75f, root->effect_tree_index(), - impl->sync_tree()); + impl->sync_tree()->SetOpacityMutated(root->element_id(), 0.75f); PostSetNeedsCommitToMainThread(); break; case 1: @@ -1269,8 +1242,7 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { break; case 2: EXPECT_EQ(node->opacity, 0.75f); - effect_tree.OnOpacityAnimated(0.75f, root->effect_tree_index(), - impl->sync_tree()); + impl->sync_tree()->SetOpacityMutated(root->element_id(), 0.75f); PostSetNeedsCommitToMainThread(); break; case 3: @@ -1279,8 +1251,8 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { break; case 4: EXPECT_EQ(node->opacity, 0.25f); - impl->sync_tree()->property_trees()->effect_tree.OnFilterAnimated( - brightness_filter_, root->effect_tree_index(), impl->sync_tree()); + impl->sync_tree()->SetFilterMutated(root->element_id(), + brightness_filter_); PostSetNeedsCommitToMainThread(); break; case 5: @@ -1289,8 +1261,8 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { break; case 6: EXPECT_EQ(node->filters, brightness_filter_); - impl->sync_tree()->property_trees()->effect_tree.OnFilterAnimated( - brightness_filter_, root->effect_tree_index(), impl->sync_tree()); + impl->sync_tree()->SetFilterMutated(root->element_id(), + brightness_filter_); PostSetNeedsCommitToMainThread(); break; case 7: @@ -1352,16 +1324,17 @@ class LayerTreeHostTestTransformTreeSync : public LayerTreeHostTest { void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { TransformTree& transform_tree = impl->sync_tree()->property_trees()->transform_tree; - TransformNode* node = transform_tree.Node( - impl->sync_tree()->root_layer_for_testing()->transform_tree_index()); + const LayerImpl* root_layer = impl->sync_tree()->root_layer_for_testing(); + const TransformNode* node = + transform_tree.Node(root_layer->transform_tree_index()); gfx::Transform rotate10; rotate10.Rotate(10.f); gfx::Transform rotate20; rotate20.Rotate(20.f); switch (impl->sync_tree()->source_frame_number()) { case 0: - impl->sync_tree()->property_trees()->transform_tree.OnTransformAnimated( - rotate20, node->id, impl->sync_tree()); + impl->sync_tree()->SetTransformMutated(root_layer->element_id(), + rotate20); PostSetNeedsCommitToMainThread(); break; case 1: @@ -1370,8 +1343,8 @@ class LayerTreeHostTestTransformTreeSync : public LayerTreeHostTest { break; case 2: EXPECT_EQ(node->local, rotate20); - impl->sync_tree()->property_trees()->transform_tree.OnTransformAnimated( - rotate20, node->id, impl->sync_tree()); + impl->sync_tree()->SetTransformMutated(root_layer->element_id(), + rotate20); PostSetNeedsCommitToMainThread(); break; case 3: @@ -1455,8 +1428,7 @@ class LayerTreeHostTestTransformTreeDamageIsUpdated : public LayerTreeHostTest { if (impl->active_tree()->source_frame_number() == 0) { gfx::Transform scale; scale.Scale(2.0, 2.0); - impl->active_tree()->property_trees()->transform_tree.OnTransformAnimated( - scale, child_->transform_tree_index(), impl->active_tree()); + impl->active_tree()->SetTransformMutated(child_->element_id(), scale); } } @@ -1888,7 +1860,7 @@ class LayerTreeHostTestDeviceScaleFactorChange : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceScaleFactorChange); -class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { +class LayerTreeHostTestRasterColorSpaceChange : public LayerTreeHostTest { public: void SetupTree() override { space1_ = gfx::ColorSpace::CreateXYZD50(); @@ -1902,7 +1874,7 @@ class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { root_layer_->AddChild(child_layer_); layer_tree_host()->SetRootLayer(root_layer_); - layer_tree_host()->SetDeviceColorSpace(space1_); + layer_tree_host()->SetRasterColorSpace(space1_); LayerTreeHostTest::SetupTree(); client_.set_bounds(root_layer_->bounds()); } @@ -1920,32 +1892,32 @@ class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { // The first frame will have full damage, and should be in the initial // color space. EXPECT_FALSE(frame_data->has_no_damage); - EXPECT_TRUE(space1_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space1_ == host_impl->active_tree()->raster_color_space()); break; case 1: // Empty commit. EXPECT_TRUE(frame_data->has_no_damage); - EXPECT_TRUE(space1_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space1_ == host_impl->active_tree()->raster_color_space()); break; case 2: // The change from space1 to space2 should cause full damage. EXPECT_FALSE(frame_data->has_no_damage); - EXPECT_TRUE(space2_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space2_ == host_impl->active_tree()->raster_color_space()); break; case 3: // Empty commit with the color space set to space2 redundantly. EXPECT_TRUE(frame_data->has_no_damage); - EXPECT_TRUE(space2_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space2_ == host_impl->active_tree()->raster_color_space()); break; case 4: // The change from space2 to space1 should cause full damage. EXPECT_FALSE(frame_data->has_no_damage); - EXPECT_TRUE(space1_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space1_ == host_impl->active_tree()->raster_color_space()); break; case 5: // Empty commit. EXPECT_TRUE(frame_data->has_no_damage); - EXPECT_TRUE(space1_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space1_ == host_impl->active_tree()->raster_color_space()); EndTest(); break; default: @@ -1972,19 +1944,19 @@ class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { break; case 2: EXPECT_FALSE(child_layer_->NeedsDisplayForTesting()); - layer_tree_host()->SetDeviceColorSpace(space2_); + layer_tree_host()->SetRasterColorSpace(space2_); EXPECT_TRUE(child_layer_->NeedsDisplayForTesting()); break; case 3: - // The redundant SetDeviceColorSpace should cause no commit and no + // The redundant SetRasterColorSpace should cause no commit and no // damage. Force a commit for the test to continue. - layer_tree_host()->SetDeviceColorSpace(space2_); + layer_tree_host()->SetRasterColorSpace(space2_); PostSetNeedsCommitToMainThread(); EXPECT_FALSE(child_layer_->NeedsDisplayForTesting()); break; case 4: EXPECT_FALSE(child_layer_->NeedsDisplayForTesting()); - layer_tree_host()->SetDeviceColorSpace(space1_); + layer_tree_host()->SetRasterColorSpace(space1_); EXPECT_TRUE(child_layer_->NeedsDisplayForTesting()); break; case 5: @@ -2009,11 +1981,12 @@ class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { scoped_refptr<Layer> child_layer_; }; -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceColorSpaceChange); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestRasterColorSpaceChange); -class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { +class LayerTreeHostTestSetNeedsCommitWithForcedRedraw + : public LayerTreeHostTest { public: - LayerTreeHostTestSetNextCommitForcesRedraw() + LayerTreeHostTestSetNeedsCommitWithForcedRedraw() : num_draws_(0), bounds_(50, 50), invalid_rect_(10, 10, 20, 20) {} void BeginTest() override { @@ -2073,8 +2046,7 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { break; case 2: // Should force full frame damage on the next commit - PostSetNextCommitForcesRedrawToMainThread(); - PostSetNeedsCommitToMainThread(); + PostSetNeedsCommitWithForcedRedrawToMainThread(); host_impl->BlockNotifyReadyToActivateForTesting(true); break; case 3: @@ -2098,7 +2070,8 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { }; // This test blocks activation which is not supported for single thread mode. -MULTI_THREAD_BLOCKNOTIFY_TEST_F(LayerTreeHostTestSetNextCommitForcesRedraw); +MULTI_THREAD_BLOCKNOTIFY_TEST_F( + LayerTreeHostTestSetNeedsCommitWithForcedRedraw); // 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. @@ -2715,17 +2688,20 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousInvalidate); class LayerTreeHostTestDeferCommits : public LayerTreeHostTest { public: - LayerTreeHostTestDeferCommits() - : num_will_begin_impl_frame_(0), num_send_begin_main_frame_(0) {} + LayerTreeHostTestDeferCommits() = default; - void BeginTest() override { PostSetNeedsCommitToMainThread(); } + void BeginTest() override { + // Start with commits deferred. + PostSetDeferCommitsToMainThread(true); + PostSetNeedsCommitToMainThread(); + } void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl, const BeginFrameArgs& args) override { + // Impl frames happen while commits are deferred. num_will_begin_impl_frame_++; switch (num_will_begin_impl_frame_) { case 1: - break; case 2: case 3: case 4: @@ -2735,7 +2711,12 @@ class LayerTreeHostTestDeferCommits : public LayerTreeHostTest { PostSetNeedsRedrawToMainThread(); break; case 5: - PostSetDeferCommitsToMainThread(false); + MainThreadTaskRunner()->PostTask( + FROM_HERE, + // Unretained because the test should not end before allowing + // commits via this running. + base::BindOnce(&LayerTreeHostTestDeferCommits::AllowCommits, + base::Unretained(this))); break; default: // Sometimes |num_will_begin_impl_frame_| will be greater than 5 if the @@ -2745,32 +2726,128 @@ class LayerTreeHostTestDeferCommits : public LayerTreeHostTest { } void WillBeginMainFrame() override { + EXPECT_TRUE(allow_commits_); num_send_begin_main_frame_++; - switch (num_send_begin_main_frame_) { - case 1: - layer_tree_host()->SetDeferCommits(true); - break; - case 2: - EndTest(); - break; - default: - NOTREACHED(); - break; - } + EndTest(); + } + + void AllowCommits() { + allow_commits_ = true; + layer_tree_host()->SetDeferCommits(false); } void AfterTest() override { EXPECT_GE(num_will_begin_impl_frame_, 5); - EXPECT_EQ(2, num_send_begin_main_frame_); + EXPECT_EQ(1, num_send_begin_main_frame_); } private: - int num_will_begin_impl_frame_; - int num_send_begin_main_frame_; + bool allow_commits_ = false; + int num_will_begin_impl_frame_ = 0; + int num_send_begin_main_frame_ = 0; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeferCommits); +// This verifies that we can abort a commit inside the main frame, and +// we don't leave any weird states around if we never allow the commit +// to happen. +class LayerTreeHostTestDeferCommitsInsideBeginMainFrame + : public LayerTreeHostTest { + public: + LayerTreeHostTestDeferCommitsInsideBeginMainFrame() = default; + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginMainFrame() override { + ++begin_main_frame_count_; + if (allow_commits_) + return; + + // This should prevent the commit from happening. + layer_tree_host()->SetDeferCommits(true); + // Wait to see if the commit happens. It's possible the deferred + // commit happens when it shouldn't but takes long enough that + // this passes. But it won't fail when it shouldn't. + MainThreadTaskRunner()->PostDelayedTask( + FROM_HERE, + // Unretained because the test doesn't end before this runs. + base::BindOnce(&LayerTreeTest::EndTest, base::Unretained(this)), + base::TimeDelta::FromMilliseconds(100)); + } + + void DidCommit() override { ++commit_count_; } + + void AfterTest() override { + EXPECT_EQ(0, commit_count_); + EXPECT_EQ(1, begin_main_frame_count_); + } + + private: + bool allow_commits_ = false; + int commit_count_ = 0; + int begin_main_frame_count_ = 0; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTestDeferCommitsInsideBeginMainFrame); + +// This verifies that we can abort a commit inside the main frame, and +// we will finish the commit once it is allowed. +class LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter + : public LayerTreeHostTest { + public: + LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter() = default; + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginMainFrame() override { + ++begin_main_frame_count_; + if (allow_commits_) + return; + + // This should prevent the commit from happening. + layer_tree_host()->SetDeferCommits(true); + // Wait to see if the commit happens. It's possible the deferred + // commit happens when it shouldn't but takes long enough that + // this passes. But it won't fail when it shouldn't. + MainThreadTaskRunner()->PostDelayedTask( + FROM_HERE, + // Unretained because the test doesn't end before this runs. + base::BindOnce( + &LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter:: + AllowCommits, + base::Unretained(this)), + base::TimeDelta::FromMilliseconds(100)); + } + + void AllowCommits() { + // Once we've waited and seen that commit did not happen, we + // allow commits and should see this one go through. + allow_commits_ = true; + layer_tree_host()->SetDeferCommits(false); + } + + void DidCommit() override { + ++commit_count_; + EXPECT_TRUE(allow_commits_); + EndTest(); + } + + void AfterTest() override { + EXPECT_EQ(1, commit_count_); + EXPECT_EQ(2, begin_main_frame_count_); + } + + private: + bool allow_commits_ = false; + int commit_count_ = 0; + int begin_main_frame_count_ = 0; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter); + class LayerTreeHostTestCompositeImmediatelyStateTransitions : public LayerTreeHostTest { public: @@ -2944,7 +3021,7 @@ class LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled // once we return. End test while it's enabled. ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostTest::EndTest, base::Unretained(this))); + base::BindOnce(&LayerTreeHostTest::EndTest, base::Unretained(this))); } void AfterTest() override {} @@ -3065,9 +3142,9 @@ class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor // surface. But it needs to be done on a new stack frame. bool resourceless_software_draw = false; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&OnDrawCompositorFrameSink::OnDraw, - base::Unretained(compositor_frame_sink_), - resourceless_software_draw)); + FROM_HERE, base::BindOnce(&OnDrawCompositorFrameSink::OnDraw, + base::Unretained(compositor_frame_sink_), + resourceless_software_draw)); } } @@ -4544,8 +4621,7 @@ class TestSwapPromise : public SwapPromise { class PinnedLayerTreeSwapPromise : public LayerTreeHostTest { protected: void BeginTest() override { - PostSetNextCommitForcesRedrawToMainThread(); - PostSetNeedsCommitToMainThread(); + layer_tree_host()->SetNeedsCommitWithForcedRedraw(); } void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { @@ -4700,8 +4776,9 @@ class LayerTreeHostTestKeepSwapPromise : public LayerTreeHostTest { void DidCommit() override { MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostTestKeepSwapPromise::ChangeFrame, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostTestKeepSwapPromise::ChangeFrame, + base::Unretained(this))); } void ChangeFrame() { @@ -4805,8 +4882,8 @@ class LayerTreeHostTestKeepSwapPromiseMFBA : public LayerTreeHostTest { void DidCommit() override { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostTestKeepSwapPromiseMFBA::ChangeFrame, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostTestKeepSwapPromiseMFBA::ChangeFrame, + base::Unretained(this))); } void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, @@ -4905,9 +4982,10 @@ class LayerTreeHostTestBreakSwapPromiseForVisibility void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl, const BeginFrameArgs& args) override { MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostTestBreakSwapPromiseForVisibility:: - SetVisibleFalseAndQueueSwapPromise, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostTestBreakSwapPromiseForVisibility:: + SetVisibleFalseAndQueueSwapPromise, + base::Unretained(this))); } void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, @@ -5916,8 +5994,9 @@ class LayerTreeHostTestCrispUpAfterPinchEnds : public LayerTreeHostTest { return; posted_ = true; ImplThreadTaskRunner()->PostDelayedTask( - FROM_HERE, base::Bind(&LayerTreeHostTestCrispUpAfterPinchEnds::Next, - base::Unretained(this), host_impl), + FROM_HERE, + base::BindOnce(&LayerTreeHostTestCrispUpAfterPinchEnds::Next, + base::Unretained(this), host_impl), // Use a delay to allow raster/upload to happen in between frames. This // should cause flakiness if we fail to block raster/upload when // desired. @@ -5957,14 +6036,15 @@ class LayerTreeHostTestCrispUpAfterPinchEnds : public LayerTreeHostTest { // On frame 3, we will have a lower res tile complete for the pinch-out // gesture even though it's not displayed. We wait for it here to prevent // flakiness. - EXPECT_EQ(0.75f, tile->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(0.75f, gfx::Vector2dF()), + tile->raster_transform()); PostNextAfterDraw(host_impl); } // On frame_ == 4, we are preventing texture uploads from completing, // so this verifies they are not completing before frame_ == 5. // Flaky failures here indicate we're failing to prevent uploads from // completing. - EXPECT_NE(4, frame_) << tile->contents_scale(); + EXPECT_NE(4, frame_) << tile->contents_scale_key(); } void AfterTest() override {} @@ -6387,9 +6467,10 @@ class LayerTreeHostTestNoTasksBetweenWillAndDidCommit void WillCommit() override { MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostTestNoTasksBetweenWillAndDidCommit:: - EndTestShouldRunAfterDidCommit, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostTestNoTasksBetweenWillAndDidCommit:: + EndTestShouldRunAfterDidCommit, + base::Unretained(this))); } void EndTestShouldRunAfterDidCommit() { @@ -6465,6 +6546,104 @@ class LayerTreeHostTestUpdateCopyRequests : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestUpdateCopyRequests); +class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin + : public LayerTreeTest { + protected: + void SetupTree() override { + // The masked layer has bounds 50x50, but it has a child that causes + // the surface bounds to be larger. It also has a parent that clips the + // masked layer and its surface. + + scoped_refptr<Layer> root = Layer::Create(); + + scoped_refptr<FakePictureLayer> content_layer = + FakePictureLayer::Create(&client_); + + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + + scoped_refptr<FakePictureLayer> mask_layer = + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); + content_layer->SetMaskLayer(mask_layer.get()); + + gfx::Size root_size(100, 100); + root->SetBounds(root_size); + + gfx::Size layer_size(100, 100); + content_layer->SetBounds(layer_size); + + gfx::Size mask_size(100, 100); + mask_layer->SetBounds(mask_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer_id_ = mask_layer->id(); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create(); + outer_viewport_scroll_layer->SetBounds(layer_size); + CreateVirtualViewportLayers(root.get(), outer_viewport_scroll_layer, + gfx::Size(50, 50), gfx::Size(50, 50), + layer_tree_host()); + outer_viewport_scroll_layer->scroll_clip_layer()->SetMasksToBounds(true); + outer_viewport_scroll_layer->AddChild(content_layer); + + client_.set_bounds(root->bounds()); + outer_viewport_scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50)); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(2u, frame_data->render_passes.size()); + RenderPass* root_pass = frame_data->render_passes.back().get(); + EXPECT_EQ(2u, root_pass->quad_list.size()); + + // There's a solid color quad under everything. + EXPECT_EQ(DrawQuad::SOLID_COLOR, root_pass->quad_list.back()->material); + + EXPECT_EQ(DrawQuad::RENDER_PASS, root_pass->quad_list.front()->material); + const RenderPassDrawQuad* render_pass_quad = + RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(), + render_pass_quad->rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( + host_impl->active_tree()->LayerById(mask_layer_id_)); + gfx::SizeF texture_size( + mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); + EXPECT_EQ( + gfx::RectF(50.f / texture_size.width(), 50.f / texture_size.height(), + 50.f / texture_size.width(), 50.f / texture_size.height()) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(50.f, 50.f, 50.f, 50.f), 1.f / 100.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } + EndTest(); + return draw_result; + } + + void AfterTest() override {} + + int mask_layer_id_; + FakeContentLayerClient client_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin); + class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { protected: void SetupTree() override { @@ -6485,8 +6664,19 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { FakePictureLayer::Create(&client_); content_layer->AddChild(content_child_layer); + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); content_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -6510,6 +6700,7 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { gfx::Size mask_size(100, 100); mask_layer->SetBounds(mask_size); mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer_id_ = mask_layer->id(); layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); @@ -6538,15 +6729,28 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { // coords in the mask are scaled by 10/50 and 20/50. // The surface is clipped to (20,10) so the mask texture coords are offset // by 20/50 and 10/50 - EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( + host_impl->active_tree()->LayerById(mask_layer_id_)); + gfx::SizeF texture_size( + mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); + EXPECT_EQ( + gfx::RectF(20.f / texture_size.width(), 10.f / texture_size.height(), + 10.f / texture_size.width(), 20.f / texture_size.height()) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } EndTest(); return draw_result; } void AfterTest() override {} + int mask_layer_id_; FakeContentLayerClient client_; }; @@ -6576,8 +6780,19 @@ class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { FakePictureLayer::Create(&client_); scaling_layer->AddChild(content_layer); + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 10), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 10, 100, 90), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); content_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -6620,16 +6835,28 @@ class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { // mask, that should fully map onto the quad. EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), render_pass_quad->rect.ToString()); - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ( + gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } break; case 1: // Applying a DSF should change the render surface size, but won't // affect which part of the mask is used. EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), render_pass_quad->rect.ToString()); - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ( + gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } EndTest(); break; } @@ -6665,8 +6892,19 @@ class LayerTreeTestMaskLayerWithDifferentBounds : public LayerTreeTest { FakePictureLayer::Create(&client_); root->AddChild(content_layer); + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); content_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -6704,16 +6942,26 @@ class LayerTreeTestMaskLayerWithDifferentBounds : public LayerTreeTest { // Check that the mask fills the surface. EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), render_pass_quad->rect.ToString()); - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 50.f / 128.f, 50.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } break; case 1: // Applying a DSF should change the render surface size, but won't // affect which part of the mask is used. EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), render_pass_quad->rect.ToString()); - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 50.f / 128.f, 50.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } EndTest(); break; } @@ -6851,9 +7099,39 @@ class LayerTreeHostTestPaintedDeviceScaleFactor : public LayerTreeHostTest { void AfterTest() override {} }; - SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPaintedDeviceScaleFactor); +// Makes sure that LocalSurfaceId is propagated to the CompositorFrameSink. +class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { + protected: + void BeginTest() override { + expected_local_surface_id_ = allocator_.GenerateId(); + PostSetLocalSurfaceIdToMainThread(expected_local_surface_id_); + } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(DRAW_SUCCESS, draw_result); + EXPECT_EQ(expected_local_surface_id_, + host_impl->active_tree()->local_surface_id()); + return draw_result; + } + + void DisplayReceivedLocalSurfaceIdOnThread( + const LocalSurfaceId& local_surface_id) override { + EXPECT_EQ(expected_local_surface_id_, local_surface_id); + EndTest(); + } + + void AfterTest() override {} + + LocalSurfaceId expected_local_surface_id_; + LocalSurfaceIdAllocator allocator_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestLocalSurfaceId); + // The GPU image decode controller hands images off to Skia for rasterization. // When used with large images, the images in question could be deleted before // Skia was done with them, causing a crash. This test performs an end-to-end @@ -6870,8 +7148,9 @@ class GpuRasterizationSucceedsWithLargeImage : public LayerTreeHostTest { void InitializeSettings(LayerTreeSettings* settings) override { settings->gpu_rasterization_forced = true; - /// Set to 0 to force at-raster GPU image decode. - settings->gpu_decoded_image_budget_bytes = 0; + // Set to 0 to force at-raster GPU image decode. + settings->decoded_image_working_set_budget_bytes = 0; + settings->decoded_image_cache_budget_bytes = 0; } void SetupTree() override { @@ -7037,5 +7316,191 @@ class LayerTreeHostTestContentSourceId : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestContentSourceId); +class LayerTreeHostTestBeginFrameSequenceNumbers : public LayerTreeHostTest { + protected: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl, + const BeginFrameArgs& args) override { + // First BeginFrame will block activation, second one unblocks. + impl->BlockNotifyReadyToActivateForTesting(false); + + EXPECT_TRUE(args.IsValid()); + current_begin_frame_args_ = args; + } + + void BeginMainFrame(const BeginFrameArgs& args) override { + EXPECT_TRUE(args.IsValid()); + if (!current_begin_main_frame_args_.IsValid()) + current_begin_main_frame_args_ = args; + } + + void BeginCommitOnThread(LayerTreeHostImpl* impl) override { + current_begin_main_frame_args_on_impl_ = current_begin_main_frame_args_; + // Request another subsequent commit. That way, the first commit's + // latest_confirmed_sequence_number should stay at the first BeginFrame's + // sequence number. + PostSetNeedsCommitToMainThread(); + } + + void WillCommitCompleteOnThread(LayerTreeHostImpl* impl) override { + // Defer current commit's activation until second BeginFrame. + impl->BlockNotifyReadyToActivateForTesting(true); + } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + // We should only draw in second BeginFrame. + EXPECT_TRUE(current_begin_main_frame_args_on_impl_.IsValid()); + EXPECT_LT(current_begin_main_frame_args_on_impl_.sequence_number, + current_begin_frame_args_.sequence_number); + frame_data_ = frame_data; + return draw_result; + } + + void DisplayReceivedCompositorFrameOnThread( + const CompositorFrame& frame) override { + if (compositor_frame_submitted_) + return; + compositor_frame_submitted_ = true; + + EXPECT_EQ(BeginFrameAck( + current_begin_frame_args_.source_id, + current_begin_frame_args_.sequence_number, + current_begin_main_frame_args_on_impl_.sequence_number, true), + frame.metadata.begin_frame_ack); + } + + void DrawLayersOnThread(LayerTreeHostImpl* impl) override { + if (layers_drawn_) + return; + layers_drawn_ = true; + + EXPECT_TRUE(frame_data_); + EXPECT_TRUE(compositor_frame_submitted_); + EXPECT_EQ(BeginFrameAck( + current_begin_frame_args_.source_id, + current_begin_frame_args_.sequence_number, + current_begin_main_frame_args_on_impl_.sequence_number, true), + frame_data_->begin_frame_ack); + EndTest(); + } + + void AfterTest() override { EXPECT_TRUE(layers_drawn_); } + + private: + bool compositor_frame_submitted_ = false; + bool layers_drawn_ = false; + BeginFrameArgs current_begin_frame_args_; + BeginFrameArgs current_begin_main_frame_args_; + BeginFrameArgs current_begin_main_frame_args_on_impl_; + LayerTreeHostImpl::FrameData* frame_data_; +}; + +MULTI_THREAD_BLOCKNOTIFY_TEST_F(LayerTreeHostTestBeginFrameSequenceNumbers); + +class LayerTreeHostTestQueueImageDecode : public LayerTreeHostTest { + protected: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginMainFrame() override { + if (!first_) + return; + first_ = false; + + sk_sp<const SkImage> image = CreateDiscardableImage(gfx::Size(10, 10)); + auto callback = + base::Bind(&LayerTreeHostTestQueueImageDecode::ImageDecodeFinished, + base::Unretained(this)); + // Schedule the decode twice for the same image. + layer_tree_host()->QueueImageDecode(image, callback); + layer_tree_host()->QueueImageDecode(image, callback); + } + + void ImageDecodeFinished(bool decode_succeeded) { + EXPECT_TRUE(decode_succeeded); + ++finished_decode_count_; + EXPECT_LE(finished_decode_count_, 2); + if (finished_decode_count_ == 2) + EndTest(); + } + + void AfterTest() override {} + + private: + bool first_ = true; + int finished_decode_count_ = 0; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestQueueImageDecode); + +class LayerTreeHostTestQueueImageDecodeNonLazy : public LayerTreeHostTest { + protected: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginMainFrame() override { + if (!first_) + return; + first_ = false; + + bitmap_.allocN32Pixels(10, 10); + sk_sp<const SkImage> image = SkImage::MakeFromBitmap(bitmap_); + auto callback = base::Bind( + &LayerTreeHostTestQueueImageDecodeNonLazy::ImageDecodeFinished, + base::Unretained(this)); + layer_tree_host()->QueueImageDecode(image, callback); + } + + void ImageDecodeFinished(bool decode_succeeded) { + EXPECT_TRUE(decode_succeeded); + EndTest(); + } + + void AfterTest() override {} + + private: + bool first_ = true; + SkBitmap bitmap_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestQueueImageDecodeNonLazy); + +class LayerTreeHostTestHudLayerWithLayerLists : public LayerTreeHostTest { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->initial_debug_state.show_paint_rects = true; + settings->use_layer_lists = true; + } + + void SetupTree() override { + LayerTreeHostTest::SetupTree(); + + // Build the property trees for the root layer. + layer_tree_host()->BuildPropertyTreesForTesting(); + + // The HUD layer should not have been setup by the property tree building. + DCHECK_EQ(layer_tree_host()->hud_layer(), nullptr); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { EndTest(); } + + void DidCommit() override { + auto* hud = layer_tree_host()->hud_layer(); + DCHECK(hud); + auto* root_layer = layer_tree_host()->root_layer(); + DCHECK_EQ(hud->transform_tree_index(), root_layer->transform_tree_index()); + DCHECK_EQ(hud->clip_tree_index(), root_layer->clip_tree_index()); + DCHECK_EQ(hud->effect_tree_index(), root_layer->effect_tree_index()); + DCHECK_EQ(hud->scroll_tree_index(), root_layer->scroll_tree_index()); + } + + void AfterTest() override {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestHudLayerWithLayerLists); + } // 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 f77964271d5..f25dc93e40f 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc @@ -573,7 +573,7 @@ class LayerTreeHostAnimationTestForceRedraw } void UpdateLayerTreeHost() override { - layer_tree_host()->SetNextCommitForcesRedraw(); + layer_tree_host()->SetNeedsCommitWithForcedRedraw(); } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { @@ -1355,9 +1355,9 @@ class LayerTreeHostAnimationTestAddAnimationAfterAnimating if (!TestEnded()) { ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostAnimationTestAddAnimationAfterAnimating:: - CheckAnimations, - base::Unretained(this), host_impl)); + base::BindOnce(&LayerTreeHostAnimationTestAddAnimationAfterAnimating:: + CheckAnimations, + base::Unretained(this), host_impl)); } } diff --git a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc index 580fa3e8363..37b3e1b006f 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc @@ -51,8 +51,8 @@ class LayerTreeHostCheckerImagingTest : public LayerTreeTest { CompletionEvent completion_event; image_worker_task_runner()->PostTask( FROM_HERE, - base::Bind([](CompletionEvent* event) { event->Signal(); }, - base::Unretained(&completion_event))); + base::BindOnce([](CompletionEvent* event) { event->Signal(); }, + base::Unretained(&completion_event))); completion_event.Wait(); } diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc index f59b200beda..3c7351f3ff4 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_context.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc @@ -6,6 +6,7 @@ #include <stdint.h> #include "base/memory/ptr_util.h" +#include "cc/base/filter_operations.h" #include "cc/layers/heads_up_display_layer.h" #include "cc/layers/layer_impl.h" #include "cc/layers/painted_scrollbar_layer.h" @@ -14,7 +15,6 @@ #include "cc/layers/texture_layer_impl.h" #include "cc/layers/video_layer.h" #include "cc/layers/video_layer_impl.h" -#include "cc/output/filter_operations.h" #include "cc/paint/paint_flags.h" #include "cc/resources/single_release_callback.h" #include "cc/resources/ui_resource_manager.h" @@ -181,9 +181,10 @@ class LayerTreeHostContextTestLostContextSucceeds void RequestNewCompositorFrameSink() override { if (async_compositor_frame_sink_creation_) { MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostContextTestLostContextSucceeds:: - AsyncRequestNewCompositorFrameSink, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostContextTestLostContextSucceeds:: + AsyncRequestNewCompositorFrameSink, + base::Unretained(this))); } else { AsyncRequestNewCompositorFrameSink(); } @@ -408,8 +409,9 @@ class LayerTreeHostClientTakeAwayCompositorFrameSink CHECK(surface); MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostClientTakeAwayCompositorFrameSink::MakeVisible, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostClientTakeAwayCompositorFrameSink::MakeVisible, + base::Unretained(this))); } void DidInitializeCompositorFrameSink() override { @@ -417,9 +419,9 @@ class LayerTreeHostClientTakeAwayCompositorFrameSink if (setos_counter_ == 1) { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostClientTakeAwayCompositorFrameSink:: - HideAndReleaseCompositorFrameSink, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostClientTakeAwayCompositorFrameSink:: + HideAndReleaseCompositorFrameSink, + base::Unretained(this))); } else { EndTest(); } @@ -539,7 +541,7 @@ class LayerTreeHostContextTestCommitAfterDelayedCompositorFrameSink void RequestNewCompositorFrameSink() override { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostContextTestCommitAfterDelayedCompositorFrameSink:: CreateAndSetCompositorFrameSink, base::Unretained(this))); @@ -708,9 +710,9 @@ class LayerTreeHostContextTestLostContextAndEvictTextures if (HasImplThread()) { ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures:: - EvictTexturesOnImplThread, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostContextTestLostContextAndEvictTextures:: + EvictTexturesOnImplThread, + base::Unretained(this))); } else { DebugScopedSetImplThread impl(task_runner_provider()); EvictTexturesOnImplThread(); @@ -1149,15 +1151,15 @@ class UIResourceLostTest : public LayerTreeHostContextTest { void PostStepCompleteToMainThread() { task_runner_provider()->MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal, - base::Unretained(this), time_step_)); + base::BindOnce(&UIResourceLostTest::StepCompleteOnMainThreadInternal, + base::Unretained(this), time_step_)); } void PostLoseContextToImplThread() { EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostContextTest::LoseContext, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&LayerTreeHostContextTest::LoseContext, + base::Unretained(this))); } protected: @@ -1563,9 +1565,9 @@ class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame // Meanwhile, lose the context while we are in defer commits. ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame:: - LoseContextOnImplThread, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame:: + LoseContextOnImplThread, + base::Unretained(this))); // After the first frame, we will lose the context and then not start // allowing commits until that happens. The 2nd frame should not happen diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc index 201c30f9fab..7805b3d76cf 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc @@ -8,7 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "cc/layers/layer_iterator.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" #include "cc/output/direct_renderer.h" @@ -55,8 +55,8 @@ class LayerTreeHostCopyRequestTestMultipleRequests void WaitForCallback() { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep, + base::Unretained(this))); } void NextStep() { @@ -597,6 +597,10 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestClippedOut); class LayerTreeHostCopyRequestTestScaledLayer : public LayerTreeHostCopyRequestTest { protected: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->layer_transforms_should_scale_layer_contents = true; + } + void SetupTree() override { root_ = Layer::Create(); root_->SetBounds(gfx::Size(20, 20)); @@ -780,9 +784,9 @@ class LayerTreeHostCopyRequestTestDeleteTexture result_ = nullptr; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostCopyRequestTestDeleteTexture:: - CheckNumTexturesAfterReadbackDestroyed, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&LayerTreeHostCopyRequestTestDeleteTexture:: + CheckNumTexturesAfterReadbackDestroyed, + base::Unretained(this))); } void CheckNumTexturesAfterReadbackDestroyed() { @@ -809,7 +813,7 @@ class LayerTreeHostCopyRequestTestDeleteTexture // Request a copy of the layer. This will use another texture. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostCopyRequestTestDeleteTexture::InsertCopyRequest, base::Unretained(this))); break; @@ -828,9 +832,10 @@ class LayerTreeHostCopyRequestTestDeleteTexture // to the compositor. Then check the resulting number of allocated // textures. MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostCopyRequestTestDeleteTexture:: - DestroyCopyResultAndCheckNumTextures, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostCopyRequestTestDeleteTexture:: + DestroyCopyResultAndCheckNumTextures, + base::Unretained(this))); break; } } @@ -880,6 +885,11 @@ class LayerTreeHostCopyRequestTestCountTextures copy_layer_ = FakePictureLayer::Create(©_client_); copy_layer_->SetBounds(gfx::Size(10, 10)); copy_client_.set_bounds(copy_layer_->bounds()); + PaintFlags flags; + flags.setColor(SK_ColorRED); + // Ensure the layer isn't completely transparent so the RenderPass isn't + // optimized away. + copy_client_.add_draw_rect(gfx::Rect(0, 0, 10, 10), flags); // Doing a copy makes the layer have a render surface which can cause // texture allocations. So get those allocations out of the way in the // first frame by forcing it to have a render surface. @@ -927,8 +937,9 @@ class LayerTreeHostCopyRequestTestCountTextures // readback. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestCountTextures::DoEndTest, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostCopyRequestTestCountTextures::DoEndTest, + base::Unretained(this))); break; } } @@ -1065,8 +1076,9 @@ class LayerTreeHostCopyRequestTestDestroyBeforeCopy void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate, + base::Unretained(this))); } void DidActivate() { @@ -1142,8 +1154,9 @@ class LayerTreeHostCopyRequestTestShutdownBeforeCopy void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::DidActivate, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostCopyRequestTestShutdownBeforeCopy::DidActivate, + base::Unretained(this))); } void DidActivate() { @@ -1168,8 +1181,9 @@ class LayerTreeHostCopyRequestTestShutdownBeforeCopy // the main thread. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::EndTest, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostCopyRequestTestShutdownBeforeCopy::EndTest, + base::Unretained(this))); break; } } @@ -1227,14 +1241,12 @@ class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest bool saw_root = false; bool saw_child = false; - 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) + for (EffectTreeLayerListIterator it(host_impl->active_tree()); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + if (it.state() == EffectTreeLayerListIterator::State::LAYER) { + if (it.current_layer() == root) saw_root = true; - else if (*it == child) + else if (it.current_layer() == child) saw_child = true; else NOTREACHED(); @@ -1268,7 +1280,7 @@ class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest // to the main thread. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest:: TryEndTest, base::Unretained(this), WhatHappened::DRAW)); diff --git a/chromium/cc/trees/layer_tree_host_unittest_damage.cc b/chromium/cc/trees/layer_tree_host_unittest_damage.cc index 5873138ce5f..73d71a2d6dd 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_damage.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_damage.cc @@ -354,7 +354,6 @@ class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest { FakePaintedScrollbarLayer::Create(false, true, content_layer_->id()); scrollbar_layer->SetPosition(gfx::PointF(300.f, 300.f)); scrollbar_layer->SetBounds(gfx::Size(10, 100)); - scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer_->id()); root_layer->AddChild(scrollbar_layer); gfx::RectF content_rect(content_layer_->position(), @@ -421,9 +420,10 @@ class LayerTreeHostDamageTestScrollbarDoesDamage // Test that modifying the position of the content layer (not // scrolling) won't damage the scrollbar. MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostDamageTestScrollbarDoesDamage:: - ModifyContentLayerPosition, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostDamageTestScrollbarDoesDamage:: + ModifyContentLayerPosition, + base::Unretained(this))); break; case 2: scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f)); @@ -433,7 +433,7 @@ class LayerTreeHostDamageTestScrollbarDoesDamage // We will resize the content layer, on the main thread. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostDamageTestScrollbarDoesDamage::ResizeScrollLayer, base::Unretained(this))); break; diff --git a/chromium/cc/trees/layer_tree_host_unittest_picture.cc b/chromium/cc/trees/layer_tree_host_unittest_picture.cc index cbdd64173b9..55eabcb1eb7 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_picture.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_picture.cc @@ -250,11 +250,8 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree // Make the bottom of the layer visible. gfx::Transform transform; transform.Translate(0.f, -100000.f + 100.f); - impl->active_tree() - ->property_trees() - ->transform_tree.OnTransformAnimated( - transform, picture_impl->transform_tree_index(), - impl->active_tree()); + impl->active_tree()->SetTransformMutated(picture_impl->element_id(), + transform); impl->SetNeedsRedraw(); break; } @@ -265,11 +262,8 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree EXPECT_FALSE(tiling->TileAt(0, 0)); // Make the top of the layer visible again. - impl->active_tree() - ->property_trees() - ->transform_tree.OnTransformAnimated( - gfx::Transform(), picture_impl->transform_tree_index(), - impl->active_tree()); + impl->active_tree()->SetTransformMutated(picture_impl->element_id(), + gfx::Transform()); impl->SetNeedsRedraw(); break; } @@ -458,19 +452,22 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale case 0: // On 1st commit the pending layer has tilings. ASSERT_EQ(1u, picture->tilings()->num_tilings()); - EXPECT_EQ(1.f, picture->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(), + picture->tilings()->tiling_at(0)->raster_transform()); break; case 1: // On 2nd commit, the pending layer is transparent, so has a stale // value. ASSERT_EQ(1u, picture->tilings()->num_tilings()); - EXPECT_EQ(1.f, picture->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(), + picture->tilings()->tiling_at(0)->raster_transform()); break; case 2: // On 3rd commit, the pending layer is visible again, so has tilings and // is updated for the pinch. ASSERT_EQ(1u, picture->tilings()->num_tilings()); - EXPECT_EQ(2.f, picture->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(2.f, gfx::Vector2dF()), + picture->tilings()->tiling_at(0)->raster_transform()); } } @@ -488,7 +485,8 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale if (draws_in_frame_ == 1) { // On 1st commit the layer has tilings. EXPECT_GT(picture->tilings()->num_tilings(), 0u); - EXPECT_EQ(1.f, picture->HighResTiling()->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(), + picture->HighResTiling()->raster_transform()); // Pinch zoom in to change the scale on the active tree. impl->PinchGestureBegin(); @@ -498,7 +496,8 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale // If the pinch gesture caused a commit we could get here with a // pending tree. EXPECT_FALSE(impl->pending_tree()); - EXPECT_EQ(2.f, picture->HighResTiling()->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(2.f, gfx::Vector2dF()), + picture->HighResTiling()->raster_transform()); // Need to wait for ready to draw here so that the pinch is // entirely complete, otherwise another draw might come in before @@ -507,7 +506,7 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale ++frame_; MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep, base::Unretained(this))); } @@ -524,7 +523,7 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale ++frame_; MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep, base::Unretained(this))); break; @@ -616,14 +615,16 @@ class LayerTreeHostPictureTestForceRecalculateScales case 0: // On first commit, both layers are at the default scale. ASSERT_EQ(1u, will_change_layer->tilings()->num_tilings()); - EXPECT_EQ(1.f, - will_change_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ( + gfx::AxisTransform2d(), + will_change_layer->tilings()->tiling_at(0)->raster_transform()); ASSERT_EQ(1u, normal_layer->tilings()->num_tilings()); - EXPECT_EQ(1.f, normal_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(), + normal_layer->tilings()->tiling_at(0)->raster_transform()); MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostPictureTestForceRecalculateScales::ScaleRootUp, base::Unretained(this))); break; @@ -631,25 +632,29 @@ class LayerTreeHostPictureTestForceRecalculateScales // On 2nd commit after scaling up to 2, the normal layer will adjust its // scale and the will change layer should not (as it is will change. ASSERT_EQ(1u, will_change_layer->tilings()->num_tilings()); - EXPECT_EQ(1.f, - will_change_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ( + gfx::AxisTransform2d(), + will_change_layer->tilings()->tiling_at(0)->raster_transform()); ASSERT_EQ(1u, normal_layer->tilings()->num_tilings()); - EXPECT_EQ(2.f, normal_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(2.f, gfx::Vector2dF()), + normal_layer->tilings()->tiling_at(0)->raster_transform()); MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostPictureTestForceRecalculateScales:: - ScaleRootUpAndRecalculateScales, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostPictureTestForceRecalculateScales:: + ScaleRootUpAndRecalculateScales, + base::Unretained(this))); break; case 2: // On 3rd commit, both layers should adjust scales due to forced // recalculating. ASSERT_EQ(1u, will_change_layer->tilings()->num_tilings()); - EXPECT_EQ(4.f, - will_change_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ( + gfx::AxisTransform2d(4.f, gfx::Vector2dF()), + will_change_layer->tilings()->tiling_at(0)->raster_transform()); ASSERT_EQ(1u, normal_layer->tilings()->num_tilings()); - EXPECT_EQ(4.f, normal_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(4.f, gfx::Vector2dF()), + normal_layer->tilings()->tiling_at(0)->raster_transform()); EndTest(); break; } diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc index ec968022fe0..b547fefcc45 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc @@ -9,7 +9,6 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" #include "cc/animation/animation_host.h" #include "cc/base/completion_event.h" #include "cc/input/main_thread_scrolling_reason.h" @@ -570,6 +569,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { root_layer->SetBounds(gfx::Size(10, 10)); root_scroll_layer_ = FakePictureLayer::Create(&fake_content_layer_client_); + root_scroll_layer_->SetElementId( + LayerIdToElementIdForTesting(root_scroll_layer_->id())); root_scroll_layer_->SetBounds(gfx::Size(110, 110)); root_scroll_layer_->SetPosition(gfx::PointF()); root_scroll_layer_->SetIsDrawable(true); @@ -582,6 +583,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { child_layer_->set_did_scroll_callback( base::Bind(&LayerTreeHostScrollTestCaseWithChild::DidScroll, base::Unretained(this))); + child_layer_->SetElementId( + LayerIdToElementIdForTesting(child_layer_->id())); child_layer_->SetBounds(gfx::Size(110, 110)); if (scroll_child_layer_) { @@ -599,6 +602,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { child_layer_->SetIsDrawable(true); child_layer_->SetScrollClipLayerId(outer_container_layer->id()); + child_layer_->SetElementId( + LayerIdToElementIdForTesting(child_layer_->id())); child_layer_->SetBounds(root_scroll_layer_->bounds()); root_scroll_layer_->AddChild(child_layer_); @@ -1314,7 +1319,7 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient { void BindInputHandlerOnCompositorThread( const base::WeakPtr<InputHandler>& input_handler, ThreadCheckingInputHandlerClient* client) { - input_handler->BindToClient(client); + input_handler->BindToClient(client, false); } TEST(LayerTreeHostFlingTest, DidStopFlingingThread) { @@ -1342,9 +1347,9 @@ TEST(LayerTreeHostFlingTest, DidStopFlingingThread) { ThreadCheckingInputHandlerClient input_handler_client( impl_thread.task_runner().get(), &received_stop_flinging); impl_thread.task_runner()->PostTask( - FROM_HERE, base::Bind(&BindInputHandlerOnCompositorThread, - layer_tree_host->GetInputHandler(), - base::Unretained(&input_handler_client))); + FROM_HERE, base::BindOnce(&BindInputHandlerOnCompositorThread, + layer_tree_host->GetInputHandler(), + base::Unretained(&input_handler_client))); layer_tree_host->DidStopFlinging(); @@ -1435,6 +1440,8 @@ class LayerTreeHostScrollTestLayerStructureChange scroll_layer->SetPosition(gfx::PointF()); scroll_layer->SetIsDrawable(true); scroll_layer->SetScrollClipLayerId(parent->id()); + scroll_layer->SetElementId( + LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(gfx::Size(parent->bounds().width() + 100, parent->bounds().height() + 100)); scroll_layer->set_did_scroll_callback(base::Bind( @@ -1861,15 +1868,15 @@ class LayerTreeHostScrollTestElasticOverscroll DCHECK(HasImplThread()); ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostScrollTestElasticOverscroll::BindInputHandler, - base::Unretained(this), - layer_tree_host()->GetInputHandler())); + base::BindOnce( + &LayerTreeHostScrollTestElasticOverscroll::BindInputHandler, + base::Unretained(this), layer_tree_host()->GetInputHandler())); PostSetNeedsCommitToMainThread(); } void BindInputHandler(base::WeakPtr<InputHandler> input_handler) { DCHECK(task_runner_provider()->IsImplThread()); - input_handler->BindToClient(&input_handler_client_); + input_handler->BindToClient(&input_handler_client_, false); scroll_elasticity_helper_ = input_handler->CreateScrollElasticityHelper(); DCHECK(scroll_elasticity_helper_); } @@ -2072,20 +2079,11 @@ class LayerTreeHostScrollTestPropertyTreeUpdate SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostScrollTestPropertyTreeUpdate); -// Disabled due to flakes/crashes on Linux TSan Tests and on -// linux_chromium_asan_rel; see https://crbug.com/697652. -#if defined(OS_LINUX) -#define MAYBE_LayerTreeHostScrollTestImplSideInvalidation \ - DISABLED_LayerTreeHostScrollTestImplSideInvalidation -#else -#define MAYBE_LayerTreeHostScrollTestImplSideInvalidation \ - LayerTreeHostScrollTestImplSideInvalidation -#endif -class MAYBE_LayerTreeHostScrollTestImplSideInvalidation +class LayerTreeHostScrollTestImplSideInvalidation : public LayerTreeHostScrollTest { void BeginTest() override { layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback( - base::Bind(&MAYBE_LayerTreeHostScrollTestImplSideInvalidation:: + base::Bind(&LayerTreeHostScrollTestImplSideInvalidation:: DidScrollOuterViewport, base::Unretained(this))); PostSetNeedsCommitToMainThread(); @@ -2098,9 +2096,9 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation CompletionEvent completion; task_runner_provider()->ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&MAYBE_LayerTreeHostScrollTestImplSideInvalidation:: - WaitForInvalidationOnImplThread, - base::Unretained(this), &completion)); + base::BindOnce(&LayerTreeHostScrollTestImplSideInvalidation:: + WaitForInvalidationOnImplThread, + base::Unretained(this), &completion)); completion.Wait(); } @@ -2172,18 +2170,11 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, CommitEarlyOutReason reason) override { - // The aborted main frame is bound to come after the fourth activation, - // since the activation should occur synchronously after the impl-side - // invalidation, and the main thread is released after this activation. It - // should leave the scroll offset unchanged. - EXPECT_EQ(reason, CommitEarlyOutReason::FINISHED_NO_UPDATES); - EXPECT_EQ(num_of_activations_, 4); - EXPECT_EQ(num_of_main_frames_, 3); - EXPECT_EQ(host_impl->active_tree() - ->OuterViewportScrollLayer() - ->CurrentScrollOffset(), - outer_viewport_offsets_[2]); - EndTest(); + EXPECT_EQ(CommitEarlyOutReason::FINISHED_NO_UPDATES, reason); + EXPECT_EQ(3, num_of_main_frames_); + EXPECT_EQ(outer_viewport_offsets_[2], host_impl->active_tree() + ->OuterViewportScrollLayer() + ->CurrentScrollOffset()); } void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { @@ -2200,11 +2191,10 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation // The second activation is from an impl-side pending tree so the source // frame number on the active tree remains unchanged, and the scroll // offset on the active tree should also remain unchanged. - EXPECT_EQ(host_impl->active_tree()->source_frame_number(), 0); - EXPECT_EQ(host_impl->active_tree() - ->OuterViewportScrollLayer() - ->CurrentScrollOffset(), - outer_viewport_offsets_[1]); + EXPECT_EQ(0, host_impl->active_tree()->source_frame_number()); + EXPECT_EQ(outer_viewport_offsets_[1], host_impl->active_tree() + ->OuterViewportScrollLayer() + ->CurrentScrollOffset()); break; case 3: // The third activation is from a commit. The scroll offset on the @@ -2218,21 +2208,25 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation case 4: // The fourth activation is from an impl-side pending tree, which should // leave the scroll offset unchanged. - EXPECT_EQ(host_impl->active_tree()->source_frame_number(), 1); - EXPECT_EQ(host_impl->active_tree() - ->OuterViewportScrollLayer() - ->CurrentScrollOffset(), - outer_viewport_offsets_[2]); + EXPECT_EQ(1, host_impl->active_tree()->source_frame_number()); + EXPECT_EQ(outer_viewport_offsets_[2], host_impl->active_tree() + ->OuterViewportScrollLayer() + ->CurrentScrollOffset()); break; default: NOTREACHED(); } } + void DrawLayersOnThread(LayerTreeHostImpl* impl) override { + if (++num_of_draws_ == 4) + EndTest(); + } + void AfterTest() override { - EXPECT_EQ(num_of_activations_, 4); - EXPECT_EQ(num_of_deltas_, 2); - EXPECT_EQ(num_of_main_frames_, 3); + EXPECT_EQ(4, num_of_activations_); + EXPECT_EQ(2, num_of_deltas_); + EXPECT_EQ(3, num_of_main_frames_); } const gfx::ScrollOffset outer_viewport_offsets_[3] = { @@ -2241,6 +2235,7 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation // Impl thread. int num_of_activations_ = 0; + int num_of_draws_ = 0; int num_of_main_frames_ = 0; bool invalidated_on_impl_thread_ = false; CompletionEvent* impl_side_invalidation_event_ = nullptr; @@ -2249,7 +2244,7 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation int num_of_deltas_ = 0; }; -MULTI_THREAD_TEST_F(MAYBE_LayerTreeHostScrollTestImplSideInvalidation); +MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplSideInvalidation); } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index 08ca53054cb..12ebf3fa413 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -17,16 +17,16 @@ #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/base/histograms.h" #include "cc/base/math_util.h" #include "cc/base/synced_property.h" -#include "cc/debug/devtools_instrumentation.h" #include "cc/debug/traced_value.h" #include "cc/input/page_scale_animation.h" #include "cc/input/scrollbar_animation_controller.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer.h" -#include "cc/layers/layer_iterator.h" #include "cc/layers/layer_list_iterator.h" #include "cc/layers/render_surface_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" @@ -243,27 +243,31 @@ void LayerTreeImpl::UpdateScrollbars(int scroll_layer_id, int clip_layer_id) { } bool scrollbar_needs_animation = false; + bool clip_layer_size_did_change = false; bool scroll_layer_size_did_change = false; bool y_offset_did_change = false; for (ScrollbarLayerImplBase* scrollbar : ScrollbarsFor(scroll_layer_id)) { if (scrollbar->orientation() == HORIZONTAL) { scrollbar_needs_animation |= scrollbar->SetCurrentPos(current_offset.x()); - scrollbar_needs_animation |= + clip_layer_size_did_change |= scrollbar->SetClipLayerLength(clip_size.width()); - scrollbar_needs_animation |= scroll_layer_size_did_change |= + scroll_layer_size_did_change |= scrollbar->SetScrollLayerLength(scroll_size.width()); } else { scrollbar_needs_animation |= y_offset_did_change |= scrollbar->SetCurrentPos(current_offset.y()); - scrollbar_needs_animation |= + clip_layer_size_did_change |= scrollbar->SetClipLayerLength(clip_size.height()); - scrollbar_needs_animation |= scroll_layer_size_did_change |= + scroll_layer_size_did_change |= scrollbar->SetScrollLayerLength(scroll_size.height()); } scrollbar_needs_animation |= scrollbar->SetVerticalAdjust(clip_layer->bounds_delta().y()); } + scrollbar_needs_animation |= + (clip_layer_size_did_change || scroll_layer_size_did_change); + if (y_offset_did_change && IsViewportLayerId(scroll_layer_id)) TRACE_COUNTER_ID1("cc", "scroll_offset_y", scroll_layer->id(), current_offset.y()); @@ -272,8 +276,16 @@ void LayerTreeImpl::UpdateScrollbars(int scroll_layer_id, int clip_layer_id) { ScrollbarAnimationController* controller = layer_tree_host_impl_->ScrollbarAnimationControllerForId( scroll_layer_id); - if (controller) - controller->DidScrollUpdate(scroll_layer_size_did_change); + if (!controller) + return; + + // TODO(chaopeng) clip_layer_size_did_change should call DidResize after + // crbug.com/701810 got fixed. + if (scroll_layer_size_did_change) { + controller->DidResize(); + } else { + controller->DidScrollUpdate(); + } } } @@ -485,11 +497,13 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { max_page_scale_factor()); target_tree->SetDeviceScaleFactor(device_scale_factor()); target_tree->set_painted_device_scale_factor(painted_device_scale_factor()); - target_tree->SetDeviceColorSpace(device_color_space_); + target_tree->SetRasterColorSpace(raster_color_space_); target_tree->elastic_overscroll()->PushPendingToActive(); target_tree->set_content_source_id(content_source_id()); + target_tree->set_local_surface_id(local_surface_id()); + target_tree->pending_page_scale_animation_ = std::move(pending_page_scale_animation_); @@ -527,6 +541,23 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { target_tree->set_hud_layer(NULL); target_tree->has_ever_been_drawn_ = false; + + // Note: this needs to happen after SetPropertyTrees. + target_tree->ShowScrollbars(); +} + +void LayerTreeImpl::ShowScrollbars() { + LayerTreeHostCommon::CallFunctionForEveryLayer(this, [this]( + LayerImpl* layer) { + if (!layer->needs_show_scrollbars()) + return; + ScrollbarAnimationController* controller = + layer_tree_host_impl_->ScrollbarAnimationControllerForId(layer->id()); + if (controller) { + controller->DidRequestShowFromMainThread(); + layer->set_needs_show_scrollbars(false); + } + }); } void LayerTreeImpl::MoveChangeTrackingToLayers() { @@ -624,17 +655,40 @@ void LayerTreeImpl::RemoveFromElementMap(LayerImpl* layer) { } void LayerTreeImpl::AddToOpacityAnimationsMap(int id, float opacity) { - opacity_animations_map_[id] = opacity; + if (LayerImpl* layer = LayerById(id)) + element_id_to_opacity_animations_[layer->element_id()] = opacity; +} + +void LayerTreeImpl::SetTransformMutated(ElementId element_id, + const gfx::Transform& transform) { + DCHECK_EQ(1u, property_trees()->element_id_to_transform_node_index.count( + element_id)); + element_id_to_transform_animations_[element_id] = transform; + if (!property_trees()->transform_tree.OnTransformAnimated(element_id, + transform)) + return; + + if (LayerImpl* layer = LayerByElementId(element_id)) + layer->set_was_ever_ready_since_last_transform_animation(false); + + set_needs_update_draw_properties(); } -void LayerTreeImpl::AddToTransformAnimationsMap(int id, - gfx::Transform transform) { - transform_animations_map_[id] = transform; +void LayerTreeImpl::SetOpacityMutated(ElementId element_id, float opacity) { + DCHECK_EQ( + 1u, property_trees()->element_id_to_effect_node_index.count(element_id)); + element_id_to_opacity_animations_[element_id] = opacity; + if (property_trees()->effect_tree.OnOpacityAnimated(element_id, opacity)) + set_needs_update_draw_properties(); } -void LayerTreeImpl::AddToFilterAnimationsMap(int id, - const FilterOperations& filters) { - filter_animations_map_[id] = filters; +void LayerTreeImpl::SetFilterMutated(ElementId element_id, + const FilterOperations& filters) { + DCHECK_EQ( + 1u, property_trees()->element_id_to_effect_node_index.count(element_id)); + element_id_to_filter_animations_[element_id] = filters; + if (property_trees()->effect_tree.OnFilterAnimated(element_id, filters)) + set_needs_update_draw_properties(); } LayerImpl* LayerTreeImpl::InnerViewportContainerLayer() const { @@ -668,17 +722,28 @@ void LayerTreeImpl::SetCurrentlyScrollingNode(ScrollNode* node) { ScrollTree& scroll_tree = property_trees()->scroll_tree; ScrollNode* old_node = scroll_tree.CurrentlyScrollingNode(); - // TODO(pdr): Refactor these to not use owning_layer_id. + + ElementId old_element_id = old_node ? old_node->element_id : ElementId(); + ElementId new_element_id = node ? node->element_id : ElementId(); + +#if DCHECK_IS_ON() int old_layer_id = old_node ? old_node->owning_layer_id : Layer::INVALID_ID; int new_layer_id = node ? node->owning_layer_id : Layer::INVALID_ID; + DCHECK(old_layer_id == LayerIdByElementId(old_element_id)); + DCHECK(new_layer_id == LayerIdByElementId(new_element_id)); +#endif - if (old_layer_id == new_layer_id) + if (old_element_id == new_element_id) return; + // TODO(pdr): Make the scrollbar animation controller lookup based on + // element ids instead of layer ids. ScrollbarAnimationController* old_animation_controller = - layer_tree_host_impl_->ScrollbarAnimationControllerForId(old_layer_id); + layer_tree_host_impl_->ScrollbarAnimationControllerForId( + LayerIdByElementId(old_element_id)); ScrollbarAnimationController* new_animation_controller = - layer_tree_host_impl_->ScrollbarAnimationControllerForId(new_layer_id); + layer_tree_host_impl_->ScrollbarAnimationControllerForId( + LayerIdByElementId(new_element_id)); if (old_animation_controller) old_animation_controller->DidScrollEnd(); @@ -710,61 +775,54 @@ void LayerTreeImpl::UpdatePropertyTreeScrollingAndAnimationFromMainThread() { // frame to a newly-committed property tree. if (layer_list_.empty()) return; - std::vector<int> layer_ids_to_remove; - for (auto& layer_id_to_opacity : opacity_animations_map_) { - const int id = layer_id_to_opacity.first; - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, id)) { - EffectNode* node = property_trees_.effect_tree.Node( - property_trees_.layer_id_to_effect_node_index[id]); + auto element_id_to_opacity = element_id_to_opacity_animations_.begin(); + while (element_id_to_opacity != element_id_to_opacity_animations_.end()) { + const ElementId id = element_id_to_opacity->first; + if (EffectNode* node = + property_trees_.effect_tree.FindNodeFromElementId(id)) { if (!node->is_currently_animating_opacity || - node->opacity == layer_id_to_opacity.second) { - layer_ids_to_remove.push_back(id); + node->opacity == element_id_to_opacity->second) { + element_id_to_opacity_animations_.erase(element_id_to_opacity++); continue; } - node->opacity = layer_id_to_opacity.second; + node->opacity = element_id_to_opacity->second; property_trees_.effect_tree.set_needs_update(true); } + ++element_id_to_opacity; } - for (auto id : layer_ids_to_remove) - opacity_animations_map_.erase(id); - layer_ids_to_remove.clear(); - - for (auto& layer_id_to_transform : transform_animations_map_) { - const int id = layer_id_to_transform.first; - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id)) { - TransformNode* node = property_trees_.transform_tree.Node( - property_trees_.layer_id_to_transform_node_index[id]); - if (!node->is_currently_animating || - node->local == layer_id_to_transform.second) { - layer_ids_to_remove.push_back(id); + + auto element_id_to_filter = element_id_to_filter_animations_.begin(); + while (element_id_to_filter != element_id_to_filter_animations_.end()) { + const ElementId id = element_id_to_filter->first; + if (EffectNode* node = + property_trees_.effect_tree.FindNodeFromElementId(id)) { + if (!node->is_currently_animating_filter || + node->filters == element_id_to_filter->second) { + element_id_to_filter_animations_.erase(element_id_to_filter++); continue; } - node->local = layer_id_to_transform.second; - node->needs_local_transform_update = true; - property_trees_.transform_tree.set_needs_update(true); + node->filters = element_id_to_filter->second; + property_trees_.effect_tree.set_needs_update(true); } + ++element_id_to_filter; } - for (auto id : layer_ids_to_remove) - transform_animations_map_.erase(id); - layer_ids_to_remove.clear(); - - for (auto& layer_id_to_filters : filter_animations_map_) { - const int id = layer_id_to_filters.first; - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, id)) { - EffectNode* node = property_trees_.effect_tree.Node( - property_trees_.layer_id_to_effect_node_index[id]); - if (!node->is_currently_animating_filter || - node->filters == layer_id_to_filters.second) { - layer_ids_to_remove.push_back(id); + + auto element_id_to_transform = element_id_to_transform_animations_.begin(); + while (element_id_to_transform != element_id_to_transform_animations_.end()) { + const ElementId id = element_id_to_transform->first; + if (TransformNode* node = + property_trees_.transform_tree.FindNodeFromElementId(id)) { + if (!node->is_currently_animating || + node->local == element_id_to_transform->second) { + element_id_to_transform_animations_.erase(element_id_to_transform++); continue; } - node->filters = layer_id_to_filters.second; - property_trees_.effect_tree.set_needs_update(true); + node->local = element_id_to_transform->second; + node->needs_local_transform_update = true; + property_trees_.transform_tree.set_needs_update(true); } + ++element_id_to_transform; } - for (auto id : layer_ids_to_remove) - filter_animations_map_.erase(id); LayerTreeHostCommon::CallFunctionForEveryLayer(this, [](LayerImpl* layer) { layer->UpdatePropertyTreeForScrollingAndAnimationIfNeeded(); @@ -926,11 +984,11 @@ void LayerTreeImpl::SetDeviceScaleFactor(float device_scale_factor) { layer_tree_host_impl_->SetNeedUpdateGpuRasterizationStatus(); } -void LayerTreeImpl::SetDeviceColorSpace( - const gfx::ColorSpace& device_color_space) { - if (device_color_space == device_color_space_) +void LayerTreeImpl::SetRasterColorSpace( + const gfx::ColorSpace& raster_color_space) { + if (raster_color_space == raster_color_space_) return; - device_color_space_ = device_color_space; + raster_color_space_ = raster_color_space; } SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() { @@ -999,13 +1057,12 @@ static void SetElementIdForTesting(LayerImpl* layer) { void LayerTreeImpl::SetElementIdsForTesting() { LayerListIterator<LayerImpl> it(root_layer_for_testing_); for (; it != LayerListIterator<LayerImpl>(nullptr); ++it) { - SetElementIdForTesting(*it); + if (!it->element_id()) + SetElementIdForTesting(*it); } } -bool LayerTreeImpl::UpdateDrawProperties( - bool update_lcd_text, - bool force_skip_verify_visible_rect_calculations) { +bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) { if (!needs_update_draw_properties_) return true; @@ -1037,10 +1094,6 @@ bool LayerTreeImpl::UpdateDrawProperties( // We verify visible rect calculations whenever we verify clip tree // calculations except when this function is explicitly passed a flag asking // us to skip it. - bool verify_visible_rect_calculations = - force_skip_verify_visible_rect_calculations - ? false - : settings().verify_clip_tree_calculations; LayerTreeHostCommon::CalcDrawPropsImplInputs inputs( layer_list_[0], DrawViewportSize(), layer_tree_host_impl_->DrawTransform(), device_scale_factor(), @@ -1050,8 +1103,7 @@ bool LayerTreeImpl::UpdateDrawProperties( OverscrollElasticityLayer(), resource_provider()->max_texture_size(), can_render_to_separate_surface, settings().layer_transforms_should_scale_layer_contents, - settings().verify_clip_tree_calculations, - verify_visible_rect_calculations, &render_surface_layer_list_, + settings().use_layer_lists, &render_surface_layer_list_, &property_trees_); LayerTreeHostCommon::CalculateDrawProperties(&inputs); if (const char* client_name = GetClientNameForMetrics()) { @@ -1075,24 +1127,23 @@ bool LayerTreeImpl::UpdateDrawProperties( occlusion_tracker.set_minimum_tracking_size( settings().minimum_occlusion_tracking_size); - // LayerIterator is used here instead of CallFunctionForEveryLayer to only - // UpdateTilePriorities on layers that will be visible (and thus have valid - // draw properties) and not because any ordering is required. - LayerIterator end = LayerIterator::End(&render_surface_layer_list_); - for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list_); - it != end; ++it) { + for (EffectTreeLayerListIterator it(this); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { occlusion_tracker.EnterLayer(it); - if (it.represents_itself()) { - it->draw_properties().occlusion_in_content_space = - occlusion_tracker.GetCurrentOcclusionForLayer(it->DrawTransform()); + if (it.state() == EffectTreeLayerListIterator::State::LAYER) { + LayerImpl* layer = it.current_layer(); + layer->draw_properties().occlusion_in_content_space = + occlusion_tracker.GetCurrentOcclusionForLayer( + layer->DrawTransform()); } - if (it.represents_contributing_render_surface()) { + if (it.state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) { const RenderSurfaceImpl* occlusion_surface = occlusion_tracker.OcclusionSurfaceForContributingSurface(); gfx::Transform draw_transform; - RenderSurfaceImpl* render_surface = it->GetRenderSurface(); + RenderSurfaceImpl* render_surface = it.current_render_surface(); if (occlusion_surface) { // We are calculating transform between two render surfaces. So, we // need to apply the surface contents scale at target and remove the @@ -1116,7 +1167,7 @@ bool LayerTreeImpl::UpdateDrawProperties( if (LayerImpl* mask = render_surface->MaskLayer()) { mask->draw_properties().occlusion_in_content_space = occlusion_tracker.GetCurrentOcclusionForContributingSurface( - draw_transform * it->DrawTransform()); + draw_transform * render_surface->SurfaceScale()); } } @@ -1178,7 +1229,7 @@ void LayerTreeImpl::BuildLayerListAndPropertyTreesForTesting() { } void LayerTreeImpl::BuildPropertyTreesForTesting() { - PropertyTreeBuilder::PreCalculateMetaInformationForTesting(layer_list_[0]); + SetElementIdsForTesting(); property_trees_.needs_rebuild = true; property_trees_.transform_tree.set_source_to_parent_updates_allowed(true); PropertyTreeBuilder::BuildPropertyTrees( @@ -1250,14 +1301,16 @@ void LayerTreeImpl::RegisterLayer(LayerImpl* layer) { void LayerTreeImpl::UnregisterLayer(LayerImpl* layer) { DCHECK(LayerById(layer->id())); layers_that_should_push_properties_.erase(layer); - transform_animations_map_.erase(layer->id()); - opacity_animations_map_.erase(layer->id()); + element_id_to_transform_animations_.erase(layer->element_id()); + element_id_to_opacity_animations_.erase(layer->element_id()); + element_id_to_filter_animations_.erase(layer->element_id()); layer_id_map_.erase(layer->id()); } // These manage ownership of the LayerImpl. void LayerTreeImpl::AddLayer(std::unique_ptr<LayerImpl> layer) { DCHECK(std::find(layers_->begin(), layers_->end(), layer) == layers_->end()); + DCHECK(layer); layers_->push_back(std::move(layer)); set_needs_update_draw_properties(); } @@ -1417,29 +1470,26 @@ const gfx::Rect LayerTreeImpl::ViewportRectForTilePriority() const { std::unique_ptr<ScrollbarAnimationController> LayerTreeImpl::CreateScrollbarAnimationController(int scroll_layer_id) { - DCHECK(!settings().scrollbar_fade_out_delay.is_zero()); - DCHECK(!settings().scrollbar_fade_out_duration.is_zero()); - base::TimeDelta fade_out_delay = settings().scrollbar_fade_out_delay; + DCHECK(!settings().scrollbar_fade_delay.is_zero()); + DCHECK(!settings().scrollbar_fade_duration.is_zero()); + base::TimeDelta fade_delay = settings().scrollbar_fade_delay; base::TimeDelta fade_out_resize_delay = settings().scrollbar_fade_out_resize_delay; - base::TimeDelta fade_out_duration = settings().scrollbar_fade_out_duration; + base::TimeDelta fade_duration = settings().scrollbar_fade_duration; switch (settings().scrollbar_animator) { case LayerTreeSettings::ANDROID_OVERLAY: { return ScrollbarAnimationController:: CreateScrollbarAnimationControllerAndroid( - scroll_layer_id, layer_tree_host_impl_, fade_out_delay, - fade_out_resize_delay, fade_out_duration); + scroll_layer_id, layer_tree_host_impl_, fade_delay, + fade_out_resize_delay, fade_duration); } case LayerTreeSettings::AURA_OVERLAY: { - DCHECK(!settings().scrollbar_show_delay.is_zero()); - base::TimeDelta show_delay = settings().scrollbar_show_delay; base::TimeDelta thinning_duration = settings().scrollbar_thinning_duration; return ScrollbarAnimationController:: CreateScrollbarAnimationControllerAuraOverlay( - scroll_layer_id, layer_tree_host_impl_, show_delay, - fade_out_delay, fade_out_resize_delay, fade_out_duration, - thinning_duration); + scroll_layer_id, layer_tree_host_impl_, fade_delay, + fade_out_resize_delay, fade_duration, thinning_duration); } case LayerTreeSettings::NO_ANIMATOR: NOTREACHED(); @@ -1470,12 +1520,10 @@ void LayerTreeImpl::SetNeedsRedraw() { void LayerTreeImpl::GetAllPrioritizedTilesForTracing( std::vector<PrioritizedTile>* prioritized_tiles) const { - 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; + for (auto it = layer_list_.rbegin(); it != layer_list_.rend(); ++it) { LayerImpl* layer_impl = *it; + if (!layer_impl->is_drawn_render_surface_layer_list_member()) + continue; layer_impl->GetAllPrioritizedTilesForTracing(prioritized_tiles); } } @@ -1485,10 +1533,8 @@ void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->SetInteger("source_frame_number", source_frame_number_); state->BeginArray("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()) + for (auto it = layer_list_.rbegin(); it != layer_list_.rend(); ++it) { + if (!(*it)->is_drawn_render_surface_layer_list_member()) continue; TracedValue::AppendIDRef(*it, state); } @@ -1741,11 +1787,6 @@ void LayerTreeImpl::RemoveSurfaceLayer(LayerImpl* layer) { surface_layers_.erase(it); } -template <typename LayerType> -static inline bool LayerClipsSubtree(LayerType* layer) { - return layer->masks_to_bounds() || layer->mask_layer(); -} - static bool PointHitsRect( const gfx::PointF& screen_space_point, const gfx::Transform& local_space_to_screen_space_transform, diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index 02c6e994d3d..1d785f86e4e 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -145,9 +145,14 @@ class CC_EXPORT LayerTreeImpl { LayerImplList::reverse_iterator rbegin(); LayerImplList::reverse_iterator rend(); + // TODO(crbug.com/702832): This won't be needed if overlay scrollbars have + // element ids. void AddToOpacityAnimationsMap(int id, float opacity); - void AddToTransformAnimationsMap(int id, gfx::Transform transform); - void AddToFilterAnimationsMap(int id, const FilterOperations& filters); + + void SetTransformMutated(ElementId element_id, + const gfx::Transform& transform); + void SetOpacityMutated(ElementId element_id, float opacity); + void SetFilterMutated(ElementId element_id, const FilterOperations& filters); int source_frame_number() const { return source_frame_number_; } void set_source_frame_number(int frame_number) { @@ -232,9 +237,14 @@ class CC_EXPORT LayerTreeImpl { void set_content_source_id(uint32_t id) { content_source_id_ = id; } uint32_t content_source_id() { return content_source_id_; } - void SetDeviceColorSpace(const gfx::ColorSpace& device_color_space); - const gfx::ColorSpace& device_color_space() const { - return device_color_space_; + void set_local_surface_id(const LocalSurfaceId& id) { + local_surface_id_ = id; + } + const LocalSurfaceId& local_surface_id() const { return local_surface_id_; } + + void SetRasterColorSpace(const gfx::ColorSpace& raster_color_space); + const gfx::ColorSpace& raster_color_space() const { + return raster_color_space_; } SyncedElasticOverscroll* elastic_overscroll() { @@ -256,9 +266,7 @@ class CC_EXPORT LayerTreeImpl { // Updates draw properties and render surface layer list, as well as tile // 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, - bool force_skip_verify_visible_rect_calculations = false); + bool UpdateDrawProperties(bool update_lcd_text); void BuildPropertyTreesForTesting(); void BuildLayerListAndPropertyTreesForTesting(); @@ -469,6 +477,7 @@ class CC_EXPORT LayerTreeImpl { float max_page_scale_factor); bool IsViewportLayerId(int id) const; void UpdateScrollbars(int scroll_layer_id, int clip_layer_id); + void ShowScrollbars(); void DidUpdatePageScale(); void PushBrowserControls(const float* top_controls_shown_ratio); bool ClampBrowserControlsShownRatio(); @@ -496,9 +505,10 @@ class CC_EXPORT LayerTreeImpl { float device_scale_factor_; float painted_device_scale_factor_; - gfx::ColorSpace device_color_space_; + gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; + LocalSurfaceId local_surface_id_; scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_; @@ -510,9 +520,12 @@ class CC_EXPORT LayerTreeImpl { std::unordered_map<ElementId, int, ElementIdHash> element_layers_map_; - std::unordered_map<int, float> opacity_animations_map_; - std::unordered_map<int, gfx::Transform> transform_animations_map_; - std::unordered_map<int, FilterOperations> filter_animations_map_; + std::unordered_map<ElementId, float, ElementIdHash> + element_id_to_opacity_animations_; + std::unordered_map<ElementId, gfx::Transform, ElementIdHash> + element_id_to_transform_animations_; + std::unordered_map<ElementId, FilterOperations, ElementIdHash> + element_id_to_filter_animations_; // Maps from clip layer ids to scroll layer ids. Note that this only includes // the subset of clip layers that act as scrolling containers. (This is diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc index 81d2800c986..3b0cbeec663 100644 --- a/chromium/cc/trees/layer_tree_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_impl_unittest.cc @@ -10,7 +10,6 @@ #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/layer_test_common.h" -#include "cc/test/layer_tree_settings_for_testing.h" #include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/layer_tree_host_common.h" @@ -22,7 +21,7 @@ namespace cc { namespace { -class LayerTreeImplTestSettings : public LayerTreeSettingsForTesting { +class LayerTreeImplTestSettings : public LayerTreeSettings { public: LayerTreeImplTestSettings() { layer_transforms_should_scale_layer_contents = true; @@ -41,9 +40,7 @@ class LayerTreeImplTest : public testing::Test { return host_impl().active_tree()->RenderSurfaceLayerList(); } - void ExecuteCalculateDrawProperties( - LayerImpl* root_layer, - bool skip_verify_visible_rect_calculations = false) { + void ExecuteCalculateDrawProperties(LayerImpl* root_layer) { // We are probably not testing what is intended if the root_layer bounds are // empty. DCHECK(!root_layer->bounds().IsEmpty()); @@ -52,8 +49,6 @@ class LayerTreeImplTest : public testing::Test { LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_layer_list_impl_); inputs.can_adjust_raster_scales = true; - if (skip_verify_visible_rect_calculations) - inputs.verify_visible_rect_calculations = false; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } @@ -247,14 +242,7 @@ TEST_F(LayerTreeImplTest, HitTestingForUninvertibleTransform) { root->SetDrawsContent(true); host_impl().SetViewportSize(root->bounds()); - // While computing visible rects by combining clips in screen space, we set - // the entire layer as visible if the screen space transform is singular. This - // is not always true when we combine clips in target space because if the - // intersection of combined_clip in taret space with layer_rect projected to - // target space is empty, we set it to an empty rect. - bool skip_verify_visible_rect_calculations = true; - host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree( - skip_verify_visible_rect_calculations); + host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); // Sanity check the scenario we just created. ASSERT_EQ(1u, RenderSurfaceLayerList().size()); ASSERT_EQ(1u, root_layer()->GetRenderSurface()->layer_list().size()); @@ -441,10 +429,6 @@ TEST_F(LayerTreeImplTest, HitTestingClipNodeDifferentTransformAndTargetIds) { host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point); ASSERT_TRUE(result_layer); EXPECT_EQ(5, result_layer->id()); - - ClipTree& clip_tree = host_impl().active_tree()->property_trees()->clip_tree; - ClipNode* clip_node = clip_tree.Node(result_layer->clip_tree_index()); - EXPECT_NE(clip_node->transform_id, clip_node->target_transform_id); } TEST_F(LayerTreeImplTest, HitTestingSiblings) { @@ -637,7 +621,6 @@ TEST_F(LayerTreeImplTest, HitTestingForMultiClippedRotatedLayer) { // Visible rects computed by combinig clips in target space and root space // don't match because of rotation transforms. So, we skip // verify_visible_rect_calculations. - bool skip_verify_visible_rect_calculations = true; { std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 456); @@ -677,12 +660,11 @@ TEST_F(LayerTreeImplTest, HitTestingForMultiClippedRotatedLayer) { child->test_properties()->AddChild(std::move(grand_child)); root->test_properties()->AddChild(std::move(child)); - ExecuteCalculateDrawProperties(root, skip_verify_visible_rect_calculations); + ExecuteCalculateDrawProperties(root); } host_impl().SetViewportSize(root->bounds()); - host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree( - skip_verify_visible_rect_calculations); + host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); // (11, 89) is close to the the bottom left corner within the clip, but it is // not inside the layer. gfx::PointF test_point(11.f, 89.f); @@ -1073,7 +1055,7 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsClipParents) { std::unique_ptr<std::set<LayerImpl*>> clip_children( new std::set<LayerImpl*>); clip_children->insert(grand_child.get()); - root->test_properties()->clip_children.reset(clip_children.release()); + root->test_properties()->clip_children = std::move(clip_children); child->test_properties()->AddChild(std::move(grand_child)); root->test_properties()->AddChild(std::move(child)); @@ -1343,14 +1325,7 @@ TEST_F(LayerTreeImplTest, root->SetTouchEventHandlerRegion(touch_handler_region); host_impl().SetViewportSize(root->bounds()); - // While computing visible rects by combining clips in screen space, we set - // the entire layer as visible if the screen space transform is singular. This - // is not always true when we combine clips in target space because if the - // intersection of combined_clip in taret space with layer_rect projected to - // target space is empty, we set it to an empty rect. - bool skip_verify_visible_rect_calculations = true; - host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree( - skip_verify_visible_rect_calculations); + host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); // Sanity check the scenario we just created. ASSERT_EQ(1u, RenderSurfaceLayerList().size()); @@ -2242,13 +2217,13 @@ TEST_F(LayerTreeImplTest, DeviceScaleFactorNeedsDrawPropertiesUpdate) { EXPECT_TRUE(host_impl().active_tree()->needs_update_draw_properties()); } -TEST_F(LayerTreeImplTest, DeviceColorSpaceDoesNotNeedDrawPropertiesUpdate) { +TEST_F(LayerTreeImplTest, RasterColorSpaceDoesNotNeedDrawPropertiesUpdate) { host_impl().active_tree()->BuildPropertyTreesForTesting(); - host_impl().active_tree()->SetDeviceColorSpace( + host_impl().active_tree()->SetRasterColorSpace( gfx::ColorSpace::CreateXYZD50()); host_impl().active_tree()->UpdateDrawProperties(false); EXPECT_FALSE(host_impl().active_tree()->needs_update_draw_properties()); - host_impl().active_tree()->SetDeviceColorSpace(gfx::ColorSpace::CreateSRGB()); + host_impl().active_tree()->SetRasterColorSpace(gfx::ColorSpace::CreateSRGB()); EXPECT_FALSE(host_impl().active_tree()->needs_update_draw_properties()); } diff --git a/chromium/cc/trees/layer_tree_mutator.h b/chromium/cc/trees/layer_tree_mutator.h index 9233ca2eec9..f7a1578bec8 100644 --- a/chromium/cc/trees/layer_tree_mutator.h +++ b/chromium/cc/trees/layer_tree_mutator.h @@ -7,7 +7,7 @@ #include "base/callback_forward.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc index de32ad805da..2b8531c9e01 100644 --- a/chromium/cc/trees/layer_tree_settings.cc +++ b/chromium/cc/trees/layer_tree_settings.cc @@ -22,68 +22,6 @@ LayerTreeSettings::LayerTreeSettings() LayerTreeSettings::LayerTreeSettings(const LayerTreeSettings& other) = default; LayerTreeSettings::~LayerTreeSettings() = default; -bool LayerTreeSettings::operator==(const LayerTreeSettings& other) const { - return renderer_settings == other.renderer_settings && - single_thread_proxy_scheduler == other.single_thread_proxy_scheduler && - main_frame_before_activation_enabled == - other.main_frame_before_activation_enabled && - using_synchronous_renderer_compositor == - other.using_synchronous_renderer_compositor && - enable_latency_recovery == other.enable_latency_recovery && - can_use_lcd_text == other.can_use_lcd_text && - use_distance_field_text == other.use_distance_field_text && - gpu_rasterization_forced == other.gpu_rasterization_forced && - async_worker_context_enabled == other.async_worker_context_enabled && - gpu_rasterization_msaa_sample_count == - other.gpu_rasterization_msaa_sample_count && - create_low_res_tiling == other.create_low_res_tiling && - scrollbar_animator == other.scrollbar_animator && - scrollbar_show_delay == other.scrollbar_show_delay && - scrollbar_fade_out_delay == other.scrollbar_fade_out_delay && - scrollbar_fade_out_resize_delay == - other.scrollbar_fade_out_resize_delay && - scrollbar_fade_out_duration == other.scrollbar_fade_out_duration && - solid_color_scrollbar_color == other.solid_color_scrollbar_color && - timeout_and_draw_when_animation_checkerboards == - other.timeout_and_draw_when_animation_checkerboards && - layer_transforms_should_scale_layer_contents == - other.layer_transforms_should_scale_layer_contents && - layers_always_allowed_lcd_text == - other.layers_always_allowed_lcd_text && - minimum_contents_scale == other.minimum_contents_scale && - low_res_contents_scale_factor == other.low_res_contents_scale_factor && - top_controls_show_threshold == other.top_controls_show_threshold && - top_controls_hide_threshold == other.top_controls_hide_threshold && - background_animation_rate == other.background_animation_rate && - default_tile_size == other.default_tile_size && - max_untiled_layer_size == other.max_untiled_layer_size && - minimum_occlusion_tracking_size == - other.minimum_occlusion_tracking_size && - tiling_interest_area_padding == other.tiling_interest_area_padding && - skewport_target_time_in_seconds == - other.skewport_target_time_in_seconds && - skewport_extrapolation_limit_in_screen_pixels == - other.skewport_extrapolation_limit_in_screen_pixels && - max_memory_for_prepaint_percentage == - other.max_memory_for_prepaint_percentage && - use_zero_copy == other.use_zero_copy && - use_partial_raster == other.use_partial_raster && - enable_elastic_overscroll == other.enable_elastic_overscroll && - ignore_root_layer_flings == other.ignore_root_layer_flings && - scheduled_raster_task_limit == other.scheduled_raster_task_limit && - use_occlusion_for_tile_prioritization == - other.use_occlusion_for_tile_prioritization && - verify_clip_tree_calculations == other.verify_clip_tree_calculations && - image_decode_tasks_enabled == other.image_decode_tasks_enabled && - max_staging_buffer_usage_in_bytes == - other.max_staging_buffer_usage_in_bytes && - gpu_memory_policy == other.gpu_memory_policy && - software_memory_policy == other.software_memory_policy && - enable_mask_tiling == other.enable_mask_tiling && - LayerTreeDebugState::Equal(initial_debug_state, - other.initial_debug_state); -} - SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const { SchedulerSettings scheduler_settings; scheduler_settings.main_frame_before_activation_enabled = diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h index 92b759ba864..90348788b5e 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -10,7 +10,7 @@ #include <vector> #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/debug/layer_tree_debug_state.h" #include "cc/output/managed_memory_policy.h" #include "cc/output/renderer_settings.h" @@ -27,8 +27,6 @@ class CC_EXPORT LayerTreeSettings { LayerTreeSettings(const LayerTreeSettings& other); virtual ~LayerTreeSettings(); - bool operator==(const LayerTreeSettings& other) const; - SchedulerSettings ToSchedulerSettings() const; TileManagerSettings ToTileManagerSettings() const; @@ -51,10 +49,9 @@ class CC_EXPORT LayerTreeSettings { AURA_OVERLAY, }; ScrollbarAnimator scrollbar_animator = NO_ANIMATOR; - base::TimeDelta scrollbar_show_delay; - base::TimeDelta scrollbar_fade_out_delay; + base::TimeDelta scrollbar_fade_delay; base::TimeDelta scrollbar_fade_out_resize_delay; - base::TimeDelta scrollbar_fade_out_duration; + base::TimeDelta scrollbar_fade_duration; base::TimeDelta scrollbar_thinning_duration; SkColor solid_color_scrollbar_color = SK_ColorWHITE; bool timeout_and_draw_when_animation_checkerboards = true; @@ -82,7 +79,6 @@ class CC_EXPORT LayerTreeSettings { bool ignore_root_layer_flings = false; size_t scheduled_raster_task_limit = 32; bool use_occlusion_for_tile_prioritization = false; - bool verify_clip_tree_calculations = false; // TODO(khushalsagar): Enable for all client and remove this flag if possible. // See crbug/com/696864. @@ -92,11 +88,11 @@ class CC_EXPORT LayerTreeSettings { int max_staging_buffer_usage_in_bytes = 32 * 1024 * 1024; ManagedMemoryPolicy gpu_memory_policy; ManagedMemoryPolicy software_memory_policy; - size_t gpu_decoded_image_budget_bytes = 96 * 1024 * 1024; - size_t software_decoded_image_budget_bytes = 128 * 1024 * 1024; + size_t decoded_image_cache_budget_bytes = 128 * 1024 * 1024; + size_t decoded_image_working_set_budget_bytes = 128 * 1024 * 1024; int max_preraster_distance_in_screen_pixels = 1000; - bool enable_color_correct_rendering = false; + bool enable_color_correct_rasterization = false; // TODO(sunxd): remove this flag when filter demoting and aa of mask layers // are implemented. @@ -108,6 +104,14 @@ class CC_EXPORT LayerTreeSettings { bool enable_checker_imaging = false; LayerTreeDebugState initial_debug_state; + + // Indicates that the LayerTreeHost should defer commits unless it has a valid + // LocalSurfaceId set. + bool enable_surface_synchronization = false; + + // Indicates the case when a sub-frame gets its own LayerTree because it's + // rendered in a different process from its ancestor frames. + bool is_layer_tree_for_subframe = false; }; } // namespace cc diff --git a/chromium/cc/trees/occlusion.h b/chromium/cc/trees/occlusion.h index 7e856aa66d2..ea38304907f 100644 --- a/chromium/cc/trees/occlusion.h +++ b/chromium/cc/trees/occlusion.h @@ -7,8 +7,8 @@ #include <string> -#include "cc/base/cc_export.h" #include "cc/base/simple_enclosed_region.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/transform.h" diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc index 78f5cc66675..523b01f830f 100644 --- a/chromium/cc/trees/occlusion_tracker.cc +++ b/chromium/cc/trees/occlusion_tracker.cc @@ -56,23 +56,26 @@ OcclusionTracker::OcclusionSurfaceForContributingSurface() const { return (stack_.size() < 2) ? nullptr : stack_[stack_.size() - 2].target; } -void OcclusionTracker::EnterLayer(const LayerIteratorPosition& layer_iterator) { - LayerImpl* render_target = layer_iterator.target_render_surface_layer; +void OcclusionTracker::EnterLayer( + const EffectTreeLayerListIterator::Position& iterator) { + RenderSurfaceImpl* render_target = iterator.target_render_surface; - if (layer_iterator.represents_itself) + if (iterator.state == EffectTreeLayerListIterator::State::LAYER) EnterRenderTarget(render_target); - else if (layer_iterator.represents_target_render_surface) + else if (iterator.state == EffectTreeLayerListIterator::State::TARGET_SURFACE) FinishedRenderTarget(render_target); } -void OcclusionTracker::LeaveLayer(const LayerIteratorPosition& layer_iterator) { - LayerImpl* render_target = layer_iterator.target_render_surface_layer; +void OcclusionTracker::LeaveLayer( + const EffectTreeLayerListIterator::Position& iterator) { + RenderSurfaceImpl* render_target = iterator.target_render_surface; - if (layer_iterator.represents_itself) - MarkOccludedBehindLayer(layer_iterator.current_layer); + if (iterator.state == EffectTreeLayerListIterator::State::LAYER) + MarkOccludedBehindLayer(iterator.current_layer); // TODO(danakj): This should be done when entering the contributing surface, // but in a way that the surface's own occlusion won't occlude itself. - else if (layer_iterator.represents_contributing_render_surface) + else if (iterator.state == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) LeaveToRenderTarget(render_target); } @@ -117,9 +120,9 @@ static SimpleEnclosedRegion TransformSurfaceOpaqueRegion( return transformed_region; } -void OcclusionTracker::EnterRenderTarget(const LayerImpl* new_target) { - DCHECK(new_target->GetRenderSurface()); - RenderSurfaceImpl* new_target_surface = new_target->GetRenderSurface(); +void OcclusionTracker::EnterRenderTarget( + const RenderSurfaceImpl* new_target_surface) { + DCHECK(new_target_surface); if (!stack_.empty() && stack_.back().target == new_target_surface) return; @@ -153,7 +156,7 @@ void OcclusionTracker::EnterRenderTarget(const LayerImpl* new_target) { &inverse_new_target_screen_space_transform); bool entering_root_target = - new_target->layer_tree_impl()->IsRootLayer(new_target); + new_target_surface->render_target() == new_target_surface; bool copy_outside_occlusion_forward = stack_.size() > 1 && @@ -177,22 +180,26 @@ void OcclusionTracker::EnterRenderTarget(const LayerImpl* new_target) { gfx::Rect(), old_target_to_new_target_transform)); } -void OcclusionTracker::FinishedRenderTarget(const LayerImpl* finished_target) { +void OcclusionTracker::FinishedRenderTarget( + const RenderSurfaceImpl* finished_target_surface) { // Make sure we know about the target surface. - EnterRenderTarget(finished_target); + EnterRenderTarget(finished_target_surface); - RenderSurfaceImpl* surface = finished_target->GetRenderSurface(); + bool is_hidden = + finished_target_surface->OwningEffectNode()->screen_space_opacity == 0.f; // Readbacks always happen on render targets so we only need to check // for readbacks here. bool target_is_only_for_copy_request = - surface->HasCopyRequest() && finished_target->IsHidden(); + finished_target_surface->HasCopyRequest() && is_hidden; // 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 (surface->MaskLayer() || surface->draw_opacity() < 1 || - !surface->UsesDefaultBlendMode() || target_is_only_for_copy_request || - surface->Filters().HasFilterThatAffectsOpacity()) { + if (finished_target_surface->HasMask() || + finished_target_surface->draw_opacity() < 1 || + !finished_target_surface->UsesDefaultBlendMode() || + target_is_only_for_copy_request || + finished_target_surface->Filters().HasFilterThatAffectsOpacity()) { stack_.back().occlusion_from_outside_target.Clear(); stack_.back().occlusion_from_inside_target.Clear(); } @@ -252,13 +259,13 @@ static void ReduceOcclusionBelowSurface( } } -void OcclusionTracker::LeaveToRenderTarget(const LayerImpl* new_target) { +void OcclusionTracker::LeaveToRenderTarget( + const RenderSurfaceImpl* new_target_surface) { DCHECK(!stack_.empty()); size_t last_index = stack_.size() - 1; - DCHECK(new_target->GetRenderSurface()); - RenderSurfaceImpl* new_surface = new_target->GetRenderSurface(); + DCHECK(new_target_surface); bool surface_will_be_at_top_after_pop = - stack_.size() > 1 && stack_[last_index - 1].target == new_surface; + stack_.size() > 1 && stack_[last_index - 1].target == new_target_surface; // We merge the screen occlusion from the current RenderSurfaceImpl subtree // out to its parent target RenderSurfaceImpl. The target occlusion can be @@ -285,23 +292,24 @@ void OcclusionTracker::LeaveToRenderTarget(const LayerImpl* new_target) { surface_occlusion.GetUnoccludedContentRect(old_surface->content_rect()); } + bool is_root = new_target_surface->render_target() == new_target_surface; if (surface_will_be_at_top_after_pop) { // Merge the top of the stack down. stack_[last_index - 1].occlusion_from_inside_target.Union( old_occlusion_from_inside_target_in_new_target); // TODO(danakj): Strictly this should subtract the inside target occlusion // before union. - if (!new_target->layer_tree_impl()->IsRootLayer(new_target)) { + if (!is_root) { stack_[last_index - 1].occlusion_from_outside_target.Union( old_occlusion_from_outside_target_in_new_target); } stack_.pop_back(); } else { // Replace the top of the stack with the new pushed surface. - stack_.back().target = new_surface; + stack_.back().target = new_target_surface; stack_.back().occlusion_from_inside_target = old_occlusion_from_inside_target_in_new_target; - if (!new_target->layer_tree_impl()->IsRootLayer(new_target)) { + if (!is_root) { stack_.back().occlusion_from_outside_target = old_occlusion_from_outside_target_in_new_target; } else { @@ -327,10 +335,6 @@ void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) { if (layer->draw_opacity() < 1) return; - // The only currently supported draw_blend_mode is SrcOver mode, so - // draw_blend_mode does not affect occlusion. - DCHECK_EQ(layer->draw_blend_mode(), SkBlendMode::kSrcOver); - if (layer->Is3dSorted()) return; diff --git a/chromium/cc/trees/occlusion_tracker.h b/chromium/cc/trees/occlusion_tracker.h index 13ef757917f..0f360f39313 100644 --- a/chromium/cc/trees/occlusion_tracker.h +++ b/chromium/cc/trees/occlusion_tracker.h @@ -8,9 +8,9 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" #include "cc/base/simple_enclosed_region.h" -#include "cc/layers/layer_iterator.h" +#include "cc/cc_export.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/trees/occlusion.h" #include "ui/gfx/geometry/rect.h" @@ -41,12 +41,12 @@ class CC_EXPORT OcclusionTracker { const gfx::Transform& draw_transform) const; const RenderSurfaceImpl* OcclusionSurfaceForContributingSurface() const; - // Called at the beginning of each step in the LayerIterator's front-to-back - // traversal. - 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& layer_iterator); + // Called at the beginning of each step in EffectTreeLayerListIterator's + // front-to-back traversal. + void EnterLayer(const EffectTreeLayerListIterator::Position& iterator); + // Called at the end of each step in EffectTreeLayerListIterator's + // front-to-back traversal. + void LeaveLayer(const EffectTreeLayerListIterator::Position& iterator); // Gives the region of the screen that is not occluded by something opaque. Region ComputeVisibleRegionInScreen(const LayerTreeImpl* layer_tree) const; @@ -82,20 +82,20 @@ class CC_EXPORT OcclusionTracker { std::vector<StackObject> stack_; 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 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 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 LayerImpl* new_target); + // Called when visiting a layer. If the target was not already current, then + // this indicates we have entered a new surface subtree. + void EnterRenderTarget(const RenderSurfaceImpl* new_target_surface); + + // Called when visiting 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 RenderSurfaceImpl* finished_target_surface); + + // Called when visiting 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 RenderSurfaceImpl* new_target_surface); // Add the layer's occlusion to the tracked state. void MarkOccludedBehindLayer(const LayerImpl* layer); diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc index 2e0d1b6d92a..8f635a30ccd 100644 --- a/chromium/cc/trees/occlusion_tracker_unittest.cc +++ b/chromium/cc/trees/occlusion_tracker_unittest.cc @@ -7,13 +7,13 @@ #include <stddef.h> #include "cc/animation/animation_host.h" +#include "cc/base/filter_operation.h" +#include "cc/base/filter_operations.h" #include "cc/base/math_util.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" -#include "cc/output/filter_operation.h" -#include "cc/output/filter_operations.h" #include "cc/test/animation_test_common.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host.h" @@ -190,7 +190,7 @@ class OcclusionTrackerTest : public testing::Test { host_->host_impl()->active_tree()->SetRootLayerForTesting(nullptr); render_surface_layer_list_impl_.clear(); mask_layers_.clear(); - ResetLayerIterator(); + layer_iterator_.reset(); } void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {} @@ -216,28 +216,28 @@ class OcclusionTrackerTest : public testing::Test { // iterations, so rebuild property trees every time. root->layer_tree_impl()->property_trees()->needs_rebuild = true; - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root); - LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), &render_surface_layer_list_impl_); inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); - layer_iterator_ = layer_iterator_begin_ = - LayerIterator::Begin(&render_surface_layer_list_impl_); + layer_iterator_ = base::MakeUnique<EffectTreeLayerListIterator>( + host_->host_impl()->active_tree()); } void EnterLayer(LayerImpl* layer, OcclusionTracker* occlusion) { - ASSERT_EQ(*layer_iterator_, layer); - ASSERT_TRUE(layer_iterator_.represents_itself()); - occlusion->EnterLayer(layer_iterator_); + ASSERT_EQ(layer_iterator_->current_layer(), layer); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::LAYER); + occlusion->EnterLayer(*layer_iterator_); } void LeaveLayer(LayerImpl* layer, OcclusionTracker* occlusion) { - ASSERT_EQ(*layer_iterator_, layer); - ASSERT_TRUE(layer_iterator_.represents_itself()); - occlusion->LeaveLayer(layer_iterator_); - ++layer_iterator_; + ASSERT_EQ(layer_iterator_->current_layer(), layer); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::LAYER); + occlusion->LeaveLayer(*layer_iterator_); + ++(*layer_iterator_); } void VisitLayer(LayerImpl* layer, OcclusionTracker* occlusion) { @@ -246,20 +246,25 @@ class OcclusionTrackerTest : public testing::Test { } void EnterContributingSurface(LayerImpl* layer, OcclusionTracker* occlusion) { - ASSERT_EQ(*layer_iterator_, layer); - ASSERT_TRUE(layer_iterator_.represents_target_render_surface()); - occlusion->EnterLayer(layer_iterator_); - occlusion->LeaveLayer(layer_iterator_); - ++layer_iterator_; - ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface()); - occlusion->EnterLayer(layer_iterator_); + ASSERT_EQ(layer_iterator_->target_render_surface(), + layer->GetRenderSurface()); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::TARGET_SURFACE); + occlusion->EnterLayer(*layer_iterator_); + occlusion->LeaveLayer(*layer_iterator_); + ++(*layer_iterator_); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE); + occlusion->EnterLayer(*layer_iterator_); } 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_; + ASSERT_EQ(layer_iterator_->current_render_surface(), + layer->GetRenderSurface()); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE); + occlusion->LeaveLayer(*layer_iterator_); + ++(*layer_iterator_); } void VisitContributingSurface(LayerImpl* layer, OcclusionTracker* occlusion) { @@ -267,7 +272,10 @@ class OcclusionTrackerTest : public testing::Test { LeaveContributingSurface(layer, occlusion); } - void ResetLayerIterator() { layer_iterator_ = layer_iterator_begin_; } + void ResetLayerIterator() { + *layer_iterator_ = + EffectTreeLayerListIterator(host_->host_impl()->active_tree()); + } const gfx::Transform identity_matrix; @@ -298,8 +306,7 @@ class OcclusionTrackerTest : public testing::Test { std::unique_ptr<FakeLayerTreeHost> host_; // These hold ownership of the layers for the duration of the test. LayerImplList render_surface_layer_list_impl_; - LayerIterator layer_iterator_begin_; - LayerIterator layer_iterator_; + std::unique_ptr<EffectTreeLayerListIterator> layer_iterator_; LayerList mask_layers_; int next_layer_impl_id_; }; diff --git a/chromium/cc/trees/property_animation_state.h b/chromium/cc/trees/property_animation_state.h index a171a91c0ed..1b7c07a7ed7 100644 --- a/chromium/cc/trees/property_animation_state.h +++ b/chromium/cc/trees/property_animation_state.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_PROPERTY_ANIMATION_STATE_H_ #define CC_TREES_PROPERTY_ANIMATION_STATE_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/trees/target_property.h" namespace cc { diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc index af6e451a922..4d1ca75e387 100644 --- a/chromium/cc/trees/property_tree.cc +++ b/chromium/cc/trees/property_tree.cc @@ -48,7 +48,6 @@ TransformTree::TransformTree() device_scale_factor_(1.f), device_transform_scale_factor_(1.f) { cached_data_.push_back(TransformCachedNodeData()); - cached_data_[kRootNodeId].target_id = kRootNodeId; } TransformTree::~TransformTree() = default; @@ -71,6 +70,7 @@ void PropertyTree<T>::clear() { nodes_.push_back(T()); back()->id = kRootNodeId; back()->parent_id = kInvalidNodeId; + owning_layer_id_to_node_index_.clear(); #if DCHECK_IS_ON() PropertyTree<T> tree; @@ -80,7 +80,8 @@ void PropertyTree<T>::clear() { template <typename T> bool PropertyTree<T>::operator==(const PropertyTree<T>& other) const { - return nodes_ == other.nodes() && needs_update_ == other.needs_update(); + return nodes_ == other.nodes() && needs_update_ == other.needs_update() && + owning_layer_id_to_node_index_ == other.owning_layer_id_to_node_index_; } template <typename T> @@ -117,7 +118,6 @@ void TransformTree::clear() { nodes_affected_by_outer_viewport_bounds_delta_.clear(); cached_data_.clear(); cached_data_.push_back(TransformCachedNodeData()); - cached_data_[kRootNodeId].target_id = kRootNodeId; sticky_position_data_.clear(); #if DCHECK_IS_ON() @@ -130,9 +130,9 @@ void TransformTree::clear() { } void TransformTree::set_needs_update(bool needs_update) { - if (needs_update && !needs_update_) + if (needs_update && !PropertyTree<TransformNode>::needs_update()) property_trees()->UpdateTransformTreeUpdateNumber(); - needs_update_ = needs_update; + PropertyTree<TransformNode>::set_needs_update(needs_update); } bool TransformTree::ComputeTranslation(int source_id, @@ -176,21 +176,26 @@ bool TransformTree::ComputeTranslation(int source_id, return true; } -void TransformTree::OnTransformAnimated(const gfx::Transform& transform, - int id, - LayerTreeImpl* layer_tree_impl) { - TransformNode* node = Node(id); - layer_tree_impl->AddToTransformAnimationsMap(node->owning_layer_id, - transform); - if (node->local == transform) { - return; - } +TransformNode* TransformTree::FindNodeFromElementId(ElementId id) { + auto iterator = property_trees()->element_id_to_transform_node_index.find(id); + if (iterator == property_trees()->element_id_to_transform_node_index.end()) + return nullptr; + + return Node(iterator->second); +} + +bool TransformTree::OnTransformAnimated(ElementId element_id, + const gfx::Transform& transform) { + TransformNode* node = FindNodeFromElementId(element_id); + DCHECK(node); + if (node->local == transform) + return false; node->local = transform; node->needs_local_transform_update = true; node->transform_changed = true; property_trees()->changed = true; set_needs_update(true); - layer_tree_impl->set_needs_update_draw_properties(); + return true; } bool TransformTree::NeedsSourceToParentUpdate(TransformNode* node) { @@ -210,7 +215,6 @@ void TransformTree::UpdateTransforms(int id) { TransformNode* node = Node(id); TransformNode* parent_node = parent(node); DCHECK(parent_node); - TransformNode* target_node = Node(TargetId(id)); TransformNode* source_node = Node(node->source_node_id); // TODO(flackr): Only dirty when scroll offset changes. if (node->sticky_position_constraint_id >= 0 || @@ -219,7 +223,7 @@ void TransformTree::UpdateTransforms(int id) { } else { UndoSnapping(node); } - UpdateScreenSpaceTransform(node, parent_node, target_node); + UpdateScreenSpaceTransform(node, parent_node); UpdateAnimationProperties(node, parent_node); UpdateSnapping(node); UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node); @@ -346,8 +350,7 @@ bool TransformTree::CombineInversesBetween(int source_id, gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { if (node->sticky_position_constraint_id == -1) return gfx::Vector2dF(); - const StickyPositionNodeData* sticky_data = - tree->StickyPositionData(node->id); + StickyPositionNodeData* sticky_data = tree->StickyPositionData(node->id); const LayerStickyPositionConstraint& constraint = sticky_data->constraints; ScrollNode* scroll_node = tree->property_trees()->scroll_tree.Node(sticky_data->scroll_ancestor); @@ -368,10 +371,36 @@ gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { scroll_position, gfx::SizeF(tree->property_trees()->scroll_tree.scroll_clip_layer_bounds( scroll_node->id))); - gfx::Vector2dF sticky_offset( - constraint.scroll_container_relative_sticky_box_rect.OffsetFromOrigin()); gfx::Vector2dF layer_offset(sticky_data->main_thread_offset); + gfx::Vector2dF ancestor_sticky_box_offset; + if (sticky_data->nearest_node_shifting_sticky_box != + TransformTree::kInvalidNodeId) { + ancestor_sticky_box_offset = + tree->StickyPositionData(sticky_data->nearest_node_shifting_sticky_box) + ->total_sticky_box_sticky_offset; + } + + gfx::Vector2dF ancestor_containing_block_offset; + if (sticky_data->nearest_node_shifting_containing_block != + TransformTree::kInvalidNodeId) { + ancestor_containing_block_offset = + tree->StickyPositionData( + sticky_data->nearest_node_shifting_containing_block) + ->total_containing_block_sticky_offset; + } + + // Compute the current position of the constraint rects based on the original + // positions and the offsets from ancestor sticky elements. + gfx::RectF sticky_box_rect = + gfx::RectF(constraint.scroll_container_relative_sticky_box_rect) + + ancestor_sticky_box_offset + ancestor_containing_block_offset; + gfx::RectF containing_block_rect = + gfx::RectF(constraint.scroll_container_relative_containing_block_rect) + + ancestor_containing_block_offset; + + gfx::Vector2dF sticky_offset(sticky_box_rect.OffsetFromOrigin()); + // In each of the following cases, we measure the limit which is the point // that the element should stick to, clamping on one side to 0 (because sticky // only pushes elements in one direction). Then we clamp to how far we can @@ -383,55 +412,52 @@ gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { // over bottom offset. if (constraint.is_anchored_right) { float right_limit = clip.right() - constraint.right_offset; - float right_delta = std::min<float>( - 0, right_limit - - constraint.scroll_container_relative_sticky_box_rect.right()); - float available_space = std::min<float>( - 0, constraint.scroll_container_relative_containing_block_rect.x() - - constraint.scroll_container_relative_sticky_box_rect.x()); + float right_delta = + std::min<float>(0, right_limit - sticky_box_rect.right()); + float available_space = + std::min<float>(0, containing_block_rect.x() - sticky_box_rect.x()); if (right_delta < available_space) right_delta = available_space; sticky_offset.set_x(sticky_offset.x() + right_delta); } if (constraint.is_anchored_left) { float left_limit = clip.x() + constraint.left_offset; - float left_delta = std::max<float>( - 0, - left_limit - constraint.scroll_container_relative_sticky_box_rect.x()); + float left_delta = std::max<float>(0, left_limit - sticky_box_rect.x()); float available_space = std::max<float>( - 0, constraint.scroll_container_relative_containing_block_rect.right() - - constraint.scroll_container_relative_sticky_box_rect.right()); + 0, containing_block_rect.right() - sticky_box_rect.right()); if (left_delta > available_space) left_delta = available_space; sticky_offset.set_x(sticky_offset.x() + left_delta); } if (constraint.is_anchored_bottom) { float bottom_limit = clip.bottom() - constraint.bottom_offset; - float bottom_delta = std::min<float>( - 0, bottom_limit - - constraint.scroll_container_relative_sticky_box_rect.bottom()); - float available_space = std::min<float>( - 0, constraint.scroll_container_relative_containing_block_rect.y() - - constraint.scroll_container_relative_sticky_box_rect.y()); + float bottom_delta = + std::min<float>(0, bottom_limit - sticky_box_rect.bottom()); + float available_space = + std::min<float>(0, containing_block_rect.y() - sticky_box_rect.y()); if (bottom_delta < available_space) bottom_delta = available_space; sticky_offset.set_y(sticky_offset.y() + bottom_delta); } if (constraint.is_anchored_top) { float top_limit = clip.y() + constraint.top_offset; - float top_delta = std::max<float>( - 0, - top_limit - constraint.scroll_container_relative_sticky_box_rect.y()); + float top_delta = std::max<float>(0, top_limit - sticky_box_rect.y()); float available_space = std::max<float>( - 0, constraint.scroll_container_relative_containing_block_rect.bottom() - - constraint.scroll_container_relative_sticky_box_rect.bottom()); + 0, containing_block_rect.bottom() - sticky_box_rect.bottom()); if (top_delta > available_space) top_delta = available_space; sticky_offset.set_y(sticky_offset.y() + top_delta); } + + sticky_data->total_sticky_box_sticky_offset = + ancestor_sticky_box_offset + sticky_offset - + sticky_box_rect.OffsetFromOrigin(); + sticky_data->total_containing_block_sticky_offset = + ancestor_sticky_box_offset + ancestor_containing_block_offset + + sticky_offset - sticky_box_rect.OffsetFromOrigin(); + return sticky_offset - layer_offset - node->source_to_parent - - constraint.scroll_container_relative_sticky_box_rect - .OffsetFromOrigin(); + sticky_box_rect.OffsetFromOrigin(); } void TransformTree::UpdateLocalTransform(TransformNode* node) { @@ -498,8 +524,7 @@ void TransformTree::UpdateLocalTransform(TransformNode* node) { } void TransformTree::UpdateScreenSpaceTransform(TransformNode* node, - TransformNode* parent_node, - TransformNode* target_node) { + TransformNode* parent_node) { DCHECK(parent_node); gfx::Transform to_screen_space_transform = ToScreen(parent_node->id); if (node->flattens_inherited_transform) @@ -705,26 +730,6 @@ void TransformTree::SetToScreen(int node_id, const gfx::Transform& transform) { cached_data_[node_id].is_showing_backface = transform.IsBackFaceVisible(); } -int TransformTree::TargetId(int node_id) const { - DCHECK(static_cast<int>(cached_data_.size()) > node_id); - return cached_data_[node_id].target_id; -} - -void TransformTree::SetTargetId(int node_id, int target_id) { - DCHECK(static_cast<int>(cached_data_.size()) > node_id); - cached_data_[node_id].target_id = target_id; -} - -int TransformTree::ContentTargetId(int node_id) const { - DCHECK(static_cast<int>(cached_data_.size()) > node_id); - return cached_data_[node_id].content_target_id; -} - -void TransformTree::SetContentTargetId(int node_id, int content_target_id) { - DCHECK(static_cast<int>(cached_data_.size()) > node_id); - cached_data_[node_id].content_target_id = content_target_id; -} - bool TransformTree::operator==(const TransformTree& other) const { return PropertyTree::operator==(other) && source_to_parent_updates_allowed_ == @@ -842,37 +847,59 @@ void EffectTree::UpdateSurfaceContentsScale(EffectNode* effect_node) { transform_tree.Node(effect_node->transform_id); if (transform_node->in_subtree_of_page_scale_layer) layer_scale_factor *= transform_tree.page_scale_factor(); + + // Note: Copy requests currently expect transform to effect output size. + bool use_transform_for_contents_scale = + property_trees()->can_adjust_raster_scales || + effect_node->has_copy_request; effect_node->surface_contents_scale = - MathUtil::ComputeTransform2dScaleComponents( - transform_tree.ToScreen(transform_node->id), layer_scale_factor); + use_transform_for_contents_scale + ? MathUtil::ComputeTransform2dScaleComponents( + transform_tree.ToScreen(transform_node->id), layer_scale_factor) + : gfx::Vector2dF(layer_scale_factor, layer_scale_factor); } -void EffectTree::OnOpacityAnimated(float opacity, - int id, - LayerTreeImpl* layer_tree_impl) { - EffectNode* node = Node(id); - layer_tree_impl->AddToOpacityAnimationsMap(node->owning_layer_id, opacity); +EffectNode* EffectTree::FindNodeFromElementId(ElementId id) { + auto iterator = property_trees()->element_id_to_effect_node_index.find(id); + if (iterator == property_trees()->element_id_to_effect_node_index.end()) + return nullptr; + + return Node(iterator->second); +} + +bool EffectTree::OnOpacityAnimated(ElementId id, float opacity) { + EffectNode* node = FindNodeFromElementId(id); + DCHECK(node); + // TODO(crbug.com/706766): Avoid crash. Need more investigation for what is + // calling this without setting element id. + if (!node) + return false; + if (node->opacity == opacity) - return; + return false; node->opacity = opacity; node->effect_changed = true; property_trees()->changed = true; property_trees()->effect_tree.set_needs_update(true); - layer_tree_impl->set_needs_update_draw_properties(); + return true; } -void EffectTree::OnFilterAnimated(const FilterOperations& filters, - int id, - LayerTreeImpl* layer_tree_impl) { - EffectNode* node = Node(id); - layer_tree_impl->AddToFilterAnimationsMap(node->owning_layer_id, filters); +bool EffectTree::OnFilterAnimated(ElementId id, + const FilterOperations& filters) { + EffectNode* node = FindNodeFromElementId(id); + DCHECK(node); + // TODO(crbug.com/706766): Avoid crash. Need more investigation for what is + // calling this without setting element id. + if (!node) + return false; + if (node->filters == filters) - return; + return false; node->filters = filters; node->effect_changed = true; property_trees()->changed = true; property_trees()->effect_tree.set_needs_update(true); - layer_tree_impl->set_needs_update_draw_properties(); + return true; } void EffectTree::UpdateEffects(int id) { @@ -1580,6 +1607,7 @@ PropertyTreesCachedData::~PropertyTreesCachedData() {} PropertyTrees::PropertyTrees() : needs_rebuild(true), non_root_surfaces_enabled(true), + can_adjust_raster_scales(true), changed(false), full_tree_damaged(false), sequence_number(0), @@ -1597,11 +1625,6 @@ bool PropertyTrees::operator==(const PropertyTrees& other) const { return transform_tree == other.transform_tree && effect_tree == other.effect_tree && clip_tree == other.clip_tree && scroll_tree == other.scroll_tree && - layer_id_to_transform_node_index == - other.layer_id_to_transform_node_index && - layer_id_to_effect_node_index == other.layer_id_to_effect_node_index && - layer_id_to_clip_node_index == other.layer_id_to_clip_node_index && - layer_id_to_scroll_node_index == other.layer_id_to_scroll_node_index && element_id_to_effect_node_index == other.element_id_to_effect_node_index && element_id_to_scroll_node_index == @@ -1615,6 +1638,7 @@ bool PropertyTrees::operator==(const PropertyTrees& other) const { is_main_thread == other.is_main_thread && is_active == other.is_active && non_root_surfaces_enabled == other.non_root_surfaces_enabled && + can_adjust_raster_scales == other.can_adjust_raster_scales && sequence_number == other.sequence_number; } @@ -1623,12 +1647,8 @@ PropertyTrees& PropertyTrees::operator=(const PropertyTrees& from) { effect_tree = from.effect_tree; clip_tree = from.clip_tree; scroll_tree = from.scroll_tree; - layer_id_to_transform_node_index = from.layer_id_to_transform_node_index; - layer_id_to_effect_node_index = from.layer_id_to_effect_node_index; always_use_active_tree_opacity_effect_ids = from.always_use_active_tree_opacity_effect_ids; - layer_id_to_clip_node_index = from.layer_id_to_clip_node_index; - layer_id_to_scroll_node_index = from.layer_id_to_scroll_node_index; element_id_to_effect_node_index = from.element_id_to_effect_node_index; element_id_to_scroll_node_index = from.element_id_to_scroll_node_index; element_id_to_transform_node_index = from.element_id_to_transform_node_index; @@ -1636,6 +1656,7 @@ PropertyTrees& PropertyTrees::operator=(const PropertyTrees& from) { changed = from.changed; full_tree_damaged = from.full_tree_damaged; non_root_surfaces_enabled = from.non_root_surfaces_enabled; + can_adjust_raster_scales = from.can_adjust_raster_scales; sequence_number = from.sequence_number; is_main_thread = from.is_main_thread; is_active = from.is_active; @@ -1658,10 +1679,6 @@ void PropertyTrees::clear() { clip_tree.clear(); effect_tree.clear(); scroll_tree.clear(); - layer_id_to_transform_node_index.clear(); - layer_id_to_effect_node_index.clear(); - layer_id_to_clip_node_index.clear(); - layer_id_to_scroll_node_index.clear(); element_id_to_effect_node_index.clear(); element_id_to_scroll_node_index.clear(); element_id_to_transform_node_index.clear(); @@ -1671,6 +1688,7 @@ void PropertyTrees::clear() { full_tree_damaged = false; changed = false; non_root_surfaces_enabled = true; + can_adjust_raster_scales = true; sequence_number++; #if DCHECK_IS_ON() @@ -1713,46 +1731,25 @@ void PropertyTrees::SetInnerViewportScrollBoundsDelta( void PropertyTrees::PushOpacityIfNeeded(PropertyTrees* target_tree) { for (int id : target_tree->always_use_active_tree_opacity_effect_ids) { - if (layer_id_to_effect_node_index.find(id) == - layer_id_to_effect_node_index.end()) - continue; - EffectNode* source_effect_node = - effect_tree.Node(layer_id_to_effect_node_index[id]); - EffectNode* target_effect_node = target_tree->effect_tree.Node( - target_tree->layer_id_to_effect_node_index[id]); - float source_opacity = source_effect_node->opacity; - float target_opacity = target_effect_node->opacity; - if (source_opacity == target_opacity) - continue; - target_effect_node->opacity = source_opacity; - target_tree->effect_tree.set_needs_update(true); + if (const EffectNode* source_effect_node = + effect_tree.FindNodeFromOwningLayerId(id)) { + EffectNode* target_effect_node = + target_tree->effect_tree.UpdateNodeFromOwningLayerId(id); + float source_opacity = source_effect_node->opacity; + float target_opacity = target_effect_node->opacity; + if (source_opacity == target_opacity) + continue; + target_effect_node->opacity = source_opacity; + target_tree->effect_tree.set_needs_update(true); + } } } void PropertyTrees::RemoveIdFromIdToIndexMaps(int id) { - layer_id_to_transform_node_index.erase(id); - layer_id_to_effect_node_index.erase(id); - layer_id_to_clip_node_index.erase(id); - layer_id_to_scroll_node_index.erase(id); -} - -bool PropertyTrees::IsInIdToIndexMap(TreeType tree_type, int id) { - std::unordered_map<int, int>* id_to_index_map = nullptr; - switch (tree_type) { - case TRANSFORM: - id_to_index_map = &layer_id_to_transform_node_index; - break; - case EFFECT: - id_to_index_map = &layer_id_to_effect_node_index; - break; - case CLIP: - id_to_index_map = &layer_id_to_clip_node_index; - break; - case SCROLL: - id_to_index_map = &layer_id_to_scroll_node_index; - break; - } - return id_to_index_map->find(id) != id_to_index_map->end(); + transform_tree.SetOwningLayerIdForNode(nullptr, id); + clip_tree.SetOwningLayerIdForNode(nullptr, id); + scroll_tree.SetOwningLayerIdForNode(nullptr, id); + effect_tree.SetOwningLayerIdForNode(nullptr, id); } void PropertyTrees::UpdateChangeTracking() { @@ -1983,6 +1980,10 @@ void PropertyTrees::SetAnimationScalesForTesting( bool PropertyTrees::GetToTarget(int transform_id, int effect_id, gfx::Transform* to_target) const { + if (effect_id == EffectTree::kContentsRootNodeId) { + *to_target = transform_tree.ToScreen(transform_id); + return true; + } DrawTransforms& transforms = GetDrawTransforms(transform_id, effect_id); if (transforms.to_valid) { *to_target = transforms.to_target; @@ -2001,6 +2002,12 @@ bool PropertyTrees::GetToTarget(int transform_id, bool PropertyTrees::GetFromTarget(int transform_id, int effect_id, gfx::Transform* from_target) const { + const TransformNode* node = transform_tree.Node(transform_id); + if (node->ancestors_are_invertible && + effect_id == EffectTree::kContentsRootNodeId) { + *from_target = transform_tree.FromScreen(transform_id); + return true; + } DrawTransforms& transforms = GetDrawTransforms(transform_id, effect_id); if (transforms.from_valid) { *from_target = transforms.from_target; @@ -2036,6 +2043,17 @@ DrawTransformData& PropertyTrees::FetchDrawTransformsDataFromCache( return data; } +ClipRectData* PropertyTrees::FetchClipRectFromCache(int clip_id, + int target_id) { + ClipNode* clip_node = clip_tree.Node(clip_id); + for (auto& data : clip_node->cached_clip_rects) { + if (data.target_id == target_id || data.target_id == -1) + return &data; + } + clip_node->cached_clip_rects.push_back(ClipRectData()); + return &clip_node->cached_clip_rects.back(); +} + DrawTransforms& PropertyTrees::GetDrawTransforms(int transform_id, int effect_id) const { const EffectNode* effect_node = effect_tree.Node(effect_id); diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h index 8c9d158a7bc..de5cc2823de 100644 --- a/chromium/cc/trees/property_tree.h +++ b/chromium/cc/trees/property_tree.h @@ -11,10 +11,11 @@ #include <unordered_map> #include <vector> -#include "cc/base/cc_export.h" +#include "base/containers/flat_map.h" +#include "cc/base/filter_operations.h" #include "cc/base/synced_property.h" +#include "cc/cc_export.h" #include "cc/layers/layer_sticky_position_constraint.h" -#include "cc/output/filter_operations.h" #include "cc/trees/element_id.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/scroll_offset.h" @@ -53,7 +54,7 @@ class CC_EXPORT PropertyTree { // they are exported by CC_EXPORT. They will be instantiated in every // compilation units that included this header, and compilation can fail // because T may be incomplete. - ~PropertyTree(); + virtual ~PropertyTree(); PropertyTree<T>& operator=(const PropertyTree<T>&); // Property tree node starts from index 0. @@ -82,7 +83,9 @@ class CC_EXPORT PropertyTree { void clear(); size_t size() const { return nodes_.size(); } - void set_needs_update(bool needs_update) { needs_update_ = needs_update; } + virtual void set_needs_update(bool needs_update) { + needs_update_ = needs_update; + } bool needs_update() const { return needs_update_; } std::vector<T>& nodes() { return nodes_; } @@ -97,25 +100,50 @@ class CC_EXPORT PropertyTree { void AsValueInto(base::trace_event::TracedValue* value) const; + const T* FindNodeFromOwningLayerId(int id) const { + return Node(FindNodeIndexFromOwningLayerId(id)); + } + T* UpdateNodeFromOwningLayerId(int id) { + int index = FindNodeIndexFromOwningLayerId(id); + if (index == kInvalidNodeId) { + DCHECK(property_trees()->is_main_thread); + property_trees()->needs_rebuild = true; + } + + return Node(index); + } + + int FindNodeIndexFromOwningLayerId(int id) const { + auto iter = owning_layer_id_to_node_index_.find(id); + if (iter == owning_layer_id_to_node_index_.end()) + return kInvalidNodeId; + else + return iter->second; + } + + void SetOwningLayerIdForNode(const T* node, int id) { + if (!node) { + owning_layer_id_to_node_index_[id] = kInvalidNodeId; + return; + } + + DCHECK(node == Node(node->id)); + owning_layer_id_to_node_index_[id] = node->id; + } + private: std::vector<T> nodes_; - friend class TransformTree; + // Maps from layer id to the property tree node index. This container is + // typically very small and the memory overhead of unordered_map will + // dominate so use a flat_map. See http://crbug.com/709243 + base::flat_map<int, int> owning_layer_id_to_node_index_; + bool needs_update_; PropertyTrees* property_trees_; }; -struct StickyPositionNodeData { - int scroll_ancestor; - LayerStickyPositionConstraint constraints; - - // This is the offset that blink has already applied to counteract the main - // thread scroll offset of the scroll ancestor. We need to account for this - // by computing the additional offset necessary to keep the element stuck. - gfx::Vector2dF main_thread_offset; - - StickyPositionNodeData() : scroll_ancestor(-1) {} -}; +struct StickyPositionNodeData; class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { public: @@ -126,7 +154,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { // compilation units that included this header, and compilation can fail // because TransformCachedNodeData may be incomplete. TransformTree(const TransformTree&) = delete; - ~TransformTree(); + ~TransformTree() final; TransformTree& operator=(const TransformTree&); bool operator==(const TransformTree& other) const; @@ -137,9 +165,9 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { void clear(); - void OnTransformAnimated(const gfx::Transform& transform, - int id, - LayerTreeImpl* layer_tree_impl); + TransformNode* FindNodeFromElementId(ElementId id); + bool OnTransformAnimated(ElementId element_id, + const gfx::Transform& transform); // Computes the change of basis transform from node |source_id| to |dest_id|. // This is used by scroll children to compute transform from their scroll // parent space (source) to their parent space (destination) and it can atmost @@ -160,7 +188,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { TransformNode* node, TransformNode* parent_node); - void set_needs_update(bool needs_update); + void set_needs_update(bool needs_update) final; // 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 @@ -254,8 +282,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { void UpdateLocalTransform(TransformNode* node); void UpdateScreenSpaceTransform(TransformNode* node, - TransformNode* parent_node, - TransformNode* target_node); + TransformNode* parent_node); void UpdateAnimationProperties(TransformNode* node, TransformNode* parent_node); void UndoSnapping(TransformNode* node); @@ -278,6 +305,35 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { std::vector<StickyPositionNodeData> sticky_position_data_; }; +struct StickyPositionNodeData { + int scroll_ancestor; + LayerStickyPositionConstraint constraints; + + // This is the offset that blink has already applied to counteract the main + // thread scroll offset of the scroll ancestor. We need to account for this + // by computing the additional offset necessary to keep the element stuck. + gfx::Vector2dF main_thread_offset; + + // In order to properly compute the sticky offset, we need to know if we have + // any sticky ancestors both between ourselves and our containing block and + // between our containing block and the viewport. These ancestors are then + // used to correct the constraining rect locations. + int nearest_node_shifting_sticky_box; + int nearest_node_shifting_containing_block; + + // For performance we cache our accumulated sticky offset to allow descendant + // sticky elements to offset their constraint rects. Because we can either + // affect the sticky box constraint rect or the containing block constraint + // rect, we need to accumulate both. + gfx::Vector2dF total_sticky_box_sticky_offset; + gfx::Vector2dF total_containing_block_sticky_offset; + + StickyPositionNodeData() + : scroll_ancestor(TransformTree::kInvalidNodeId), + nearest_node_shifting_sticky_box(TransformTree::kInvalidNodeId), + nearest_node_shifting_containing_block(TransformTree::kInvalidNodeId) {} +}; + class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> { public: bool operator==(const ClipTree& other) const; @@ -291,7 +347,7 @@ class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> { class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { public: EffectTree(); - ~EffectTree(); + ~EffectTree() final; EffectTree& operator=(const EffectTree& from); bool operator==(const EffectTree& other) const; @@ -306,10 +362,9 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { void UpdateSurfaceContentsScale(EffectNode* node); - void OnOpacityAnimated(float opacity, int id, LayerTreeImpl* layer_tree_impl); - void OnFilterAnimated(const FilterOperations& filters, - int id, - LayerTreeImpl* layer_tree_impl); + EffectNode* FindNodeFromElementId(ElementId id); + bool OnOpacityAnimated(ElementId id, float opacity); + bool OnFilterAnimated(ElementId id, const FilterOperations& filters); void UpdateEffects(int id); @@ -371,7 +426,7 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { public: ScrollTree(); - ~ScrollTree(); + ~ScrollTree() final; ScrollTree& operator=(const ScrollTree& from); bool operator==(const ScrollTree& other) const; @@ -548,6 +603,18 @@ struct DrawTransformData { transforms(gfx::Transform(), gfx::Transform()) {} }; +struct ConditionalClip { + bool is_clipped; + gfx::RectF clip_rect; +}; + +struct ClipRectData { + int target_id; + ConditionalClip clip; + + ClipRectData() : target_id(-1) {} +}; + struct PropertyTreesCachedData { int transform_tree_update_number; std::vector<AnimationScaleData> animation_scales; @@ -566,14 +633,6 @@ class CC_EXPORT PropertyTrees final { bool operator==(const PropertyTrees& other) const; PropertyTrees& operator=(const PropertyTrees& from); - // These maps map from layer id to the index for each of the respective - // property node types. - std::unordered_map<int, int> layer_id_to_transform_node_index; - std::unordered_map<int, int> layer_id_to_effect_node_index; - std::unordered_map<int, int> layer_id_to_clip_node_index; - std::unordered_map<int, int> layer_id_to_scroll_node_index; - enum TreeType { TRANSFORM, EFFECT, CLIP, SCROLL }; - // These maps allow mapping directly from a compositor element id to the // respective property node. This will eventually allow simplifying logic in // various places that today has to map from element id to layer id, and then @@ -594,6 +653,7 @@ class CC_EXPORT PropertyTrees final { ScrollTree scroll_tree; bool needs_rebuild; bool non_root_surfaces_enabled; + bool can_adjust_raster_scales; // Change tracking done on property trees needs to be preserved across commits // (when they are not rebuild). We cache a global bool which stores whether // we did any change tracking so that we can skip copying the change status @@ -616,7 +676,6 @@ class CC_EXPORT PropertyTrees final { void SetInnerViewportScrollBoundsDelta(gfx::Vector2dF bounds_delta); void PushOpacityIfNeeded(PropertyTrees* target_tree); void RemoveIdFromIdToIndexMaps(int id); - bool IsInIdToIndexMap(TreeType tree_type, int id); void UpdateChangeTracking(); void PushChangeTrackingTo(PropertyTrees* tree); void ResetAllChangeTracking(); @@ -654,6 +713,8 @@ class CC_EXPORT PropertyTrees final { int transform_id, int effect_id) const; + ClipRectData* FetchClipRectFromCache(int clip_id, int target_id); + private: gfx::Vector2dF inner_viewport_container_bounds_delta_; gfx::Vector2dF outer_viewport_container_bounds_delta_; diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc index ef843d5d989..02fb9bd306c 100644 --- a/chromium/cc/trees/property_tree_builder.cc +++ b/chromium/cc/trees/property_tree_builder.cc @@ -50,7 +50,6 @@ struct DataForRecursion { bool affected_by_outer_viewport_bounds_delta; bool should_flatten; bool is_hidden; - bool apply_ancestor_clip; uint32_t main_thread_scrolling_reasons; bool scroll_tree_parent_created_by_uninheritable_criteria; const gfx::Transform* device_transform; @@ -87,93 +86,6 @@ static LayerStickyPositionConstraint StickyPositionConstraint( return layer->test_properties()->sticky_position_constraint; } -struct PreCalculateMetaInformationRecursiveData { - size_t num_unclipped_descendants; - int num_descendants_that_draw_content; - - PreCalculateMetaInformationRecursiveData() - : num_unclipped_descendants(0), - num_descendants_that_draw_content(0) {} - - void Merge(const PreCalculateMetaInformationRecursiveData& data) { - num_unclipped_descendants += data.num_unclipped_descendants; - num_descendants_that_draw_content += data.num_descendants_that_draw_content; - } -}; - -static inline bool IsRootLayer(const Layer* layer) { - return !layer->parent(); -} - -static bool IsMetaInformationRecomputationNeeded(Layer* layer) { - return layer->layer_tree_host()->needs_meta_info_recomputation(); -} - -// Recursively walks the layer tree(if needed) to compute any information -// that is needed before doing the main recursion. -static void PreCalculateMetaInformationInternal( - Layer* layer, - PreCalculateMetaInformationRecursiveData* recursive_data) { - if (!IsMetaInformationRecomputationNeeded(layer)) { - DCHECK(IsRootLayer(layer)); - return; - } - - if (layer->clip_parent()) - recursive_data->num_unclipped_descendants++; - - 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); - recursive_data->Merge(data_for_child); - } - - if (layer->clip_children()) { - 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; - } - - layer->set_num_unclipped_descendants( - recursive_data->num_unclipped_descendants); - - if (IsRootLayer(layer)) - layer->layer_tree_host()->SetNeedsMetaInfoRecomputation(false); -} - -static void PreCalculateMetaInformationInternalForTesting( - LayerImpl* layer, - PreCalculateMetaInformationRecursiveData* recursive_data) { - if (layer->test_properties()->clip_parent) - recursive_data->num_unclipped_descendants++; - - for (size_t i = 0; i < layer->test_properties()->children.size(); ++i) { - LayerImpl* child_layer = layer->test_properties()->children[i]; - - PreCalculateMetaInformationRecursiveData data_for_child; - PreCalculateMetaInformationInternalForTesting(child_layer, &data_for_child); - recursive_data->Merge(data_for_child); - } - - if (layer->test_properties()->clip_children) { - size_t num_clip_children = layer->test_properties()->clip_children->size(); - DCHECK_GE(recursive_data->num_unclipped_descendants, num_clip_children); - recursive_data->num_unclipped_descendants -= num_clip_children; - } - - layer->test_properties()->num_unclipped_descendants = - recursive_data->num_unclipped_descendants; - // TODO(enne): this should be synced from the main thread, so is only - // for tests constructing layers on the compositor thread. - layer->test_properties()->num_descendants_that_draw_content = - recursive_data->num_descendants_that_draw_content; - - if (layer->DrawsContent()) - recursive_data->num_descendants_that_draw_content++; -} - static LayerImplList& Children(LayerImpl* layer) { return layer->test_properties()->children; } @@ -214,14 +126,6 @@ static LayerImpl* ClipParent(LayerImpl* layer) { return layer->test_properties()->clip_parent; } -static size_t NumUnclippedDescendants(Layer* layer) { - return layer->num_unclipped_descendants(); -} - -static size_t NumUnclippedDescendants(LayerImpl* layer) { - return layer->test_properties()->num_unclipped_descendants; -} - static inline const FilterOperations& Filters(Layer* layer) { return layer->filters(); } @@ -246,6 +150,12 @@ static const gfx::Transform& Transform(LayerImpl* layer) { return layer->test_properties()->transform; } +static void SetIsScrollClipLayer(Layer* layer) { + layer->set_is_scroll_clip_layer(); +} + +static void SetIsScrollClipLayer(LayerImpl* layer) {} + // Methods to query state from the AnimationHost ---------------------- template <typename LayerType> bool OpacityIsAnimating(LayerType* layer) { @@ -334,86 +244,36 @@ static LayerImpl* Parent(LayerImpl* layer) { return layer->test_properties()->parent; } -template <typename LayerType> -static void SetSurfaceIsClipped(DataForRecursion<LayerType>* data_for_children, - bool apply_ancestor_clip, - LayerType* layer) { - // A surface with unclipped descendants cannot be clipped by its ancestor - // clip at draw time since the unclipped descendants aren't affected by the - // ancestor clip. - EffectNode* effect_node = data_for_children->property_trees->effect_tree.Node( - data_for_children->render_target); - DCHECK_EQ(effect_node->owning_layer_id, layer->id()); - effect_node->surface_is_clipped = - apply_ancestor_clip && !NumUnclippedDescendants(layer); - // The ancestor clip should propagate to children only if the surface doesn't - // apply the clip. - data_for_children->apply_ancestor_clip = - apply_ancestor_clip && !effect_node->surface_is_clipped; +static inline int SortingContextId(Layer* layer) { + return layer->sorting_context_id(); +} + +static inline int SortingContextId(LayerImpl* layer) { + return layer->test_properties()->sorting_context_id; +} + +static inline bool Is3dSorted(Layer* layer) { + return layer->Is3dSorted(); +} + +static inline bool Is3dSorted(LayerImpl* layer) { + return layer->test_properties()->sorting_context_id != 0; } template <typename LayerType> void AddClipNodeIfNeeded(const DataForRecursion<LayerType>& data_from_ancestor, LayerType* layer, - bool created_render_surface, bool created_transform_node, DataForRecursion<LayerType>* data_for_children) { const bool inherits_clip = !ClipParent(layer); const int parent_id = inherits_clip ? data_from_ancestor.clip_tree_parent : ClipParent(layer)->clip_tree_index(); - ClipNode* parent = - data_from_ancestor.property_trees->clip_tree.Node(parent_id); - - bool apply_ancestor_clip = inherits_clip - ? data_from_ancestor.apply_ancestor_clip - : parent->layers_are_clipped; - - bool layers_are_clipped = false; - bool has_unclipped_surface = false; - - if (created_render_surface) { - SetSurfaceIsClipped(data_for_children, apply_ancestor_clip, layer); - // Clips can usually be applied to a surface's descendants simply by - // clipping the surface (or applied implicitly by the surface's bounds). - // However, if the surface has unclipped descendants (layers that aren't - // affected by the ancestor clip), we cannot clip the surface itself, and - // must instead apply clips to the clipped descendants. - if (apply_ancestor_clip && NumUnclippedDescendants(layer) > 0) { - layers_are_clipped = true; - } else if (!apply_ancestor_clip) { - // When there are no ancestor clips that need to be applied to a render - // surface, we reset clipping state. The surface might contribute a clip - // of its own, but clips from ancestor nodes don't need to be considered - // when computing clip rects or visibility. - has_unclipped_surface = true; - DCHECK_NE(parent->clip_type, ClipNode::ClipType::APPLIES_LOCAL_CLIP); - } - } else { - // Without a new render surface, layer clipping state from ancestors needs - // to continue to propagate. - layers_are_clipped = apply_ancestor_clip; - } bool layer_clips_subtree = LayerClipsSubtree(layer); - if (layer_clips_subtree) { - layers_are_clipped = true; - data_for_children->apply_ancestor_clip = true; - } - - // Without surfaces, all non-viewport clips have to be applied using layer - // clipping. - bool layers_are_clipped_when_surfaces_disabled = - layer_clips_subtree || parent->layers_are_clipped_when_surfaces_disabled; - - // Render surface's clip is needed during hit testing. So, we need to create - // a clip node for every render surface. - bool requires_node = layer_clips_subtree || created_render_surface; - + bool requires_node = + layer_clips_subtree || Filters(layer).HasFilterThatMovesPixels(); if (!requires_node) { data_for_children->clip_tree_parent = parent_id; - DCHECK_EQ(layers_are_clipped, parent->layers_are_clipped); - DCHECK_EQ(layers_are_clipped_when_surfaces_disabled, - parent->layers_are_clipped_when_surfaces_disabled); } else { LayerType* transform_parent = data_for_children->transform_tree_parent; if (PositionConstraint(layer).is_fixed_position() && @@ -424,64 +284,24 @@ void AddClipNodeIfNeeded(const DataForRecursion<LayerType>& data_from_ancestor, node.clip = gfx::RectF(gfx::PointF() + layer->offset_to_transform_parent(), gfx::SizeF(layer->bounds())); node.transform_id = transform_parent->transform_tree_index(); - node.target_effect_id = data_for_children->render_target; - node.target_transform_id = data_for_children->property_trees->effect_tree - .Node(data_for_children->render_target) - ->transform_id; node.owning_layer_id = layer->id(); - - if (apply_ancestor_clip || layer_clips_subtree) { - // Surfaces reset the rect used for layer clipping. At other nodes, layer - // clipping state from ancestors must continue to get propagated. - node.layer_clipping_uses_only_local_clip = - (created_render_surface && NumUnclippedDescendants(layer) == 0) || - !apply_ancestor_clip; - } else { - // Otherwise, we're either unclipped, or exist only in order to apply our - // parent's clips in our space. - node.layer_clipping_uses_only_local_clip = false; - } - if (layer_clips_subtree) { node.clip_type = ClipNode::ClipType::APPLIES_LOCAL_CLIP; - } else if (Filters(layer).HasFilterThatMovesPixels()) { + } else { + DCHECK(Filters(layer).HasFilterThatMovesPixels()); node.clip_type = ClipNode::ClipType::EXPANDS_CLIP; node.clip_expander = base::MakeUnique<ClipExpander>(layer->effect_tree_index()); - } else { - node.clip_type = ClipNode::ClipType::NONE; } - node.resets_clip = has_unclipped_surface; - node.layers_are_clipped = layers_are_clipped; - node.layers_are_clipped_when_surfaces_disabled = - layers_are_clipped_when_surfaces_disabled; - data_for_children->clip_tree_parent = data_for_children->property_trees->clip_tree.Insert(node, parent_id); - data_for_children->property_trees - ->layer_id_to_clip_node_index[layer->id()] = - data_for_children->clip_tree_parent; + data_for_children->property_trees->clip_tree.SetOwningLayerIdForNode( + data_for_children->property_trees->clip_tree.back(), layer->id()); } layer->SetClipTreeIndex(data_for_children->clip_tree_parent); } -static inline int SortingContextId(Layer* layer) { - return layer->sorting_context_id(); -} - -static inline int SortingContextId(LayerImpl* layer) { - return layer->test_properties()->sorting_context_id; -} - -static inline bool Is3dSorted(Layer* layer) { - return layer->Is3dSorted(); -} - -static inline bool Is3dSorted(LayerImpl* layer) { - return layer->test_properties()->sorting_context_id != 0; -} - template <typename LayerType> static inline bool IsAtBoundaryOf3dRenderingContext(LayerType* layer) { return Parent(layer) @@ -565,29 +385,21 @@ bool AddTransformNodeIfNeeded( scroll_child_has_different_target || is_sticky || is_at_boundary_of_3d_rendering_context; - LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer); - DCHECK(is_root || transform_parent); - int parent_index = TransformTree::kRootNodeId; - if (transform_parent) - parent_index = transform_parent->transform_tree_index(); + int source_index = TransformTree::kRootNodeId; + gfx::Vector2dF source_offset; - int source_index = parent_index; + LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer); + DCHECK_EQ(is_root, !transform_parent); - gfx::Vector2dF source_offset; if (transform_parent) { - if (ScrollParent(layer)) { - LayerType* source = Parent(layer); - source_offset += source->offset_to_transform_parent(); - source_index = source->transform_tree_index(); - } else if (!is_fixed) { - source_offset = transform_parent->offset_to_transform_parent(); - } else { - source_offset = data_from_ancestor.transform_tree_parent - ->offset_to_transform_parent(); - source_index = - data_from_ancestor.transform_tree_parent->transform_tree_index(); - } + parent_index = transform_parent->transform_tree_index(); + // Because Blink still provides positions with respect to the parent layer, + // we track both a parent TransformNode (which is the parent in the + // TransformTree) and a 'source' TransformNode (which is the TransformNode + // for the parent in the Layer tree). + source_index = Parent(layer)->transform_tree_index(); + source_offset = Parent(layer)->offset_to_transform_parent(); } if (IsContainerForFixedPositionLayers(layer) || is_root) { @@ -630,8 +442,8 @@ bool AddTransformNodeIfNeeded( TransformNode* node = data_for_children->property_trees->transform_tree.back(); layer->SetTransformTreeIndex(node->id); - data_for_children->property_trees - ->layer_id_to_transform_node_index[layer->id()] = node->id; + data_for_children->property_trees->transform_tree.SetOwningLayerIdForNode( + node, layer->id()); // For animation subsystem purposes, if this layer has a compositor element // id, we build a map from that id to this transform node. @@ -656,18 +468,6 @@ bool AddTransformNodeIfNeeded( ShouldFlattenTransform(layer) || has_surface; DCHECK_GT(data_from_ancestor.property_trees->effect_tree.size(), 0u); - data_for_children->property_trees->transform_tree.SetTargetId( - node->id, data_for_children->property_trees->effect_tree - .Node(data_from_ancestor.render_target) - ->transform_id); - data_for_children->property_trees->transform_tree.SetContentTargetId( - node->id, data_for_children->property_trees->effect_tree - .Node(data_for_children->render_target) - ->transform_id); - DCHECK_NE( - data_for_children->property_trees->transform_tree.TargetId(node->id), - TransformTree::kInvalidNodeId); - node->has_potential_animation = has_potentially_animated_transform; node->is_currently_animating = TransformIsAnimating(layer); if (has_potentially_animated_transform) { @@ -759,10 +559,36 @@ bool AddTransformNodeIfNeeded( .AddNodeAffectedByOuterViewportBoundsDelta(node->id); } } + // TODO(smcgruer): Pass main thread sticky-shifting offsets of + // non-promoted ancestors, or promote all ancestor sticky elements. + // See http://crbug.com/702229 sticky_data->main_thread_offset = layer->position().OffsetFromOrigin() - sticky_data->constraints.parent_relative_sticky_box_offset .OffsetFromOrigin(); + + // Copy the ancestor nodes for later use. These layers are guaranteed to + // have transform nodes at this point because they are our ancestors (so + // have already been processed) and are sticky (so have transform nodes). + int shifting_sticky_box_layer_id = + sticky_data->constraints.nearest_layer_shifting_sticky_box; + if (shifting_sticky_box_layer_id != Layer::INVALID_ID) { + sticky_data->nearest_node_shifting_sticky_box = + data_for_children->property_trees->transform_tree + .FindNodeIndexFromOwningLayerId(shifting_sticky_box_layer_id); + DCHECK(sticky_data->nearest_node_shifting_sticky_box != + TransformTree::kInvalidNodeId); + } + int shifting_containing_block_layer_id = + sticky_data->constraints.nearest_layer_shifting_containing_block; + if (shifting_containing_block_layer_id != Layer::INVALID_ID) { + sticky_data->nearest_node_shifting_containing_block = + data_for_children->property_trees->transform_tree + .FindNodeIndexFromOwningLayerId( + shifting_containing_block_layer_id); + DCHECK(sticky_data->nearest_node_shifting_containing_block != + TransformTree::kInvalidNodeId); + } } node->needs_local_transform_update = true; @@ -822,8 +648,24 @@ static inline int NumDescendantsThatDrawContent(Layer* layer) { return layer->NumDescendantsThatDrawContent(); } +static inline int NumLayerOrDescendantsThatDrawContentRecursive( + LayerImpl* layer) { + int num = layer->DrawsContent() ? 1 : 0; + for (size_t i = 0; i < layer->test_properties()->children.size(); ++i) { + LayerImpl* child_layer = layer->test_properties()->children[i]; + num += NumLayerOrDescendantsThatDrawContentRecursive(child_layer); + } + return num; +} + static inline int NumDescendantsThatDrawContent(LayerImpl* layer) { - return layer->test_properties()->num_descendants_that_draw_content; + int num_descendants_that_draw_content = 0; + for (size_t i = 0; i < layer->test_properties()->children.size(); ++i) { + LayerImpl* child_layer = layer->test_properties()->children[i]; + num_descendants_that_draw_content += + NumLayerOrDescendantsThatDrawContentRecursive(child_layer); + } + return num_descendants_that_draw_content; } static inline float EffectiveOpacity(Layer* layer) { @@ -1088,7 +930,6 @@ bool AddEffectNodeIfNeeded( // transform id. node.transform_id = data_from_ancestor.property_trees->transform_tree.next_available_id(); - node.has_unclipped_descendants = (NumUnclippedDescendants(layer) != 0); } node.clip_id = data_from_ancestor.clip_tree_parent; } else { @@ -1102,8 +943,8 @@ bool AddEffectNodeIfNeeded( int node_id = effect_tree.Insert(node, parent_id); data_for_children->effect_tree_parent = node_id; layer->SetEffectTreeIndex(node_id); - data_for_children->property_trees - ->layer_id_to_effect_node_index[layer->id()] = node_id; + data_for_children->property_trees->effect_tree.SetOwningLayerIdForNode( + effect_tree.back(), layer->id()); // For animation subsystem purposes, if this layer has a compositor element // id, we build a map from that id to this effect node. @@ -1165,13 +1006,14 @@ void AddScrollNodeIfNeeded( node.main_thread_scrolling_reasons = main_thread_scrolling_reasons; node.non_fast_scrollable_region = layer->non_fast_scrollable_region(); gfx::Size clip_bounds; - if (layer->scroll_clip_layer()) { - clip_bounds = layer->scroll_clip_layer()->bounds(); - DCHECK(layer->scroll_clip_layer()->transform_tree_index() != + if (LayerType* scroll_clip_layer = layer->scroll_clip_layer()) { + SetIsScrollClipLayer(scroll_clip_layer); + clip_bounds = scroll_clip_layer->bounds(); + DCHECK(scroll_clip_layer->transform_tree_index() != TransformTree::kInvalidNodeId); node.max_scroll_offset_affected_by_page_scale = !data_from_ancestor.property_trees->transform_tree - .Node(layer->scroll_clip_layer()->transform_tree_index()) + .Node(scroll_clip_layer->transform_tree_index()) ->in_subtree_of_page_scale_layer && data_from_ancestor.in_subtree_of_page_scale_layer; } @@ -1198,8 +1040,8 @@ void AddScrollNodeIfNeeded( node.main_thread_scrolling_reasons; data_for_children->scroll_tree_parent_created_by_uninheritable_criteria = scroll_node_uninheritable_criteria; - data_for_children->property_trees - ->layer_id_to_scroll_node_index[layer->id()] = node_id; + data_for_children->property_trees->scroll_tree.SetOwningLayerIdForNode( + data_for_children->property_trees->scroll_tree.back(), layer->id()); // For animation subsystem purposes, if this layer has a compositor element // id, we build a map from that id to this scroll node. if (layer->element_id()) { @@ -1288,17 +1130,13 @@ void BuildPropertyTreesInternal( bool created_render_surface = AddEffectNodeIfNeeded(data_from_parent, layer, &data_for_children); - if (created_render_surface) { + if (created_render_surface) data_for_children.render_target = data_for_children.effect_tree_parent; - layer->set_draw_blend_mode(SkBlendMode::kSrcOver); - } else { - layer->set_draw_blend_mode(BlendMode(layer)); - } bool created_transform_node = AddTransformNodeIfNeeded( data_from_parent, layer, created_render_surface, &data_for_children); - AddClipNodeIfNeeded(data_from_parent, layer, created_render_surface, - created_transform_node, &data_for_children); + AddClipNodeIfNeeded(data_from_parent, layer, created_transform_node, + &data_for_children); AddScrollNodeIfNeeded(data_from_parent, layer, &data_for_children); @@ -1359,18 +1197,6 @@ void BuildPropertyTreesInternal( } // namespace -void CC_EXPORT -PropertyTreeBuilder::PreCalculateMetaInformation(Layer* root_layer) { - PreCalculateMetaInformationRecursiveData recursive_data; - PreCalculateMetaInformationInternal(root_layer, &recursive_data); -} - -void CC_EXPORT PropertyTreeBuilder::PreCalculateMetaInformationForTesting( - LayerImpl* root_layer) { - PreCalculateMetaInformationRecursiveData recursive_data; - PreCalculateMetaInformationInternalForTesting(root_layer, &recursive_data); -} - Layer* PropertyTreeBuilder::FindFirstScrollableLayer(Layer* layer) { if (!layer) return nullptr; @@ -1435,8 +1261,6 @@ void BuildPropertyTreesTopLevelInternal( data_for_recursion.affected_by_outer_viewport_bounds_delta = false; data_for_recursion.should_flatten = false; data_for_recursion.is_hidden = false; - // The root clip is always applied. - data_for_recursion.apply_ancestor_clip = true; data_for_recursion.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; data_for_recursion.scroll_tree_parent_created_by_uninheritable_criteria = @@ -1451,11 +1275,9 @@ void BuildPropertyTreesTopLevelInternal( data_for_recursion.safe_opaque_background_color = color; ClipNode root_clip; - root_clip.resets_clip = true; root_clip.clip_type = ClipNode::ClipType::APPLIES_LOCAL_CLIP; root_clip.clip = gfx::RectF(viewport); root_clip.transform_id = TransformTree::kRootNodeId; - root_clip.target_transform_id = TransformTree::kRootNodeId; data_for_recursion.clip_tree_parent = data_for_recursion.property_trees->clip_tree.Insert( root_clip, ClipTree::kRootNodeId); diff --git a/chromium/cc/trees/property_tree_builder.h b/chromium/cc/trees/property_tree_builder.h index d4b4eefab94..4418f94ee57 100644 --- a/chromium/cc/trees/property_tree_builder.h +++ b/chromium/cc/trees/property_tree_builder.h @@ -16,10 +16,6 @@ class PropertyTreeBuilder { public: static Layer* FindFirstScrollableLayer(Layer* root_layer); - static void CC_EXPORT PreCalculateMetaInformation(Layer* root_layer); - static void CC_EXPORT - PreCalculateMetaInformationForTesting(LayerImpl* root_layer); - static void CC_EXPORT BuildPropertyTrees(Layer* root_layer, const Layer* page_scale_layer, @@ -32,17 +28,18 @@ class PropertyTreeBuilder { const gfx::Rect& viewport, const gfx::Transform& device_transform, 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, - const LayerImpl* overscroll_elasticity_layer, - const gfx::Vector2dF& elastic_overscroll, - float page_scale_factor, - float device_scale_factor, - const gfx::Rect& viewport, - const gfx::Transform& device_transform, - PropertyTrees* property_trees); + static void CC_EXPORT + BuildPropertyTrees(LayerImpl* root_layer, + const LayerImpl* page_scale_layer, + const LayerImpl* inner_viewport_scroll_layer, + const LayerImpl* outer_viewport_scroll_layer, + const LayerImpl* overscroll_elasticity_layer, + const gfx::Vector2dF& elastic_overscroll, + float page_scale_factor, + float device_scale_factor, + const gfx::Rect& viewport, + const gfx::Transform& device_transform, + PropertyTrees* property_trees); }; } // namespace cc diff --git a/chromium/cc/trees/property_tree_unittest.cc b/chromium/cc/trees/property_tree_unittest.cc index 40113d30f79..1c0c37692fc 100644 --- a/chromium/cc/trees/property_tree_unittest.cc +++ b/chromium/cc/trees/property_tree_unittest.cc @@ -23,7 +23,6 @@ TEST(PropertyTreeTest, ComputeTransformRoot) { contents_root.local.Translate(2, 2); contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); gfx::Transform expected; @@ -46,7 +45,6 @@ TEST(PropertyTreeTest, SetNeedsUpdate) { TransformNode contents_root; contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); EXPECT_FALSE(tree.needs_update()); tree.SetRootTransformsAndScales(0.6f, 1.f, gfx::Transform(), gfx::PointF()); @@ -63,14 +61,12 @@ TEST(PropertyTreeTest, ComputeTransformChild) { contents_root.local.Translate(2, 2); contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(contents_root.id); TransformNode child; child.local.Translate(3, 3); child.source_node_id = 1; child.id = tree.Insert(child, contents_root.id); - tree.SetTargetId(child.id, 0); tree.UpdateTransforms(child.id); @@ -109,20 +105,17 @@ TEST(PropertyTreeTest, ComputeTransformSibling) { contents_root.source_node_id = 0; contents_root.local.Translate(2, 2); contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode child; child.local.Translate(3, 3); child.source_node_id = 1; child.id = tree.Insert(child, 1); - tree.SetTargetId(child.id, 0); TransformNode sibling; sibling.local.Translate(7, 7); sibling.source_node_id = 1; sibling.id = tree.Insert(sibling, 1); - tree.SetTargetId(sibling.id, 0); tree.UpdateTransforms(2); tree.UpdateTransforms(3); @@ -158,26 +151,22 @@ TEST(PropertyTreeTest, ComputeTransformSiblingSingularAncestor) { contents_root.local.Translate(2, 2); contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode singular; singular.local.matrix().set(2, 2, 0.0); singular.source_node_id = 1; singular.id = tree.Insert(singular, 1); - tree.SetTargetId(singular.id, 0); TransformNode child; child.local.Translate(3, 3); child.source_node_id = 2; child.id = tree.Insert(child, 2); - tree.SetTargetId(child.id, 0); TransformNode sibling; sibling.local.Translate(7, 7); sibling.source_node_id = 2; sibling.id = tree.Insert(sibling, 2); - tree.SetTargetId(sibling.id, 0); tree.UpdateTransforms(2); tree.UpdateTransforms(3); @@ -209,8 +198,6 @@ TEST(PropertyTreeTest, TransformsWithFlattening) { effect_tree.Node(effect_grand_parent)->transform_id = grand_parent; effect_tree.Node(effect_grand_parent)->surface_contents_scale = gfx::Vector2dF(1.f, 1.f); - tree.SetContentTargetId(grand_parent, grand_parent); - tree.SetTargetId(grand_parent, grand_parent); tree.Node(grand_parent)->source_node_id = 0; gfx::Transform rotation_about_x; @@ -222,21 +209,15 @@ TEST(PropertyTreeTest, TransformsWithFlattening) { effect_tree.Node(effect_parent)->has_render_surface = true; effect_tree.Node(effect_parent)->surface_contents_scale = gfx::Vector2dF(1.f, 1.f); - tree.SetTargetId(parent, grand_parent); - tree.SetContentTargetId(parent, parent); tree.Node(parent)->source_node_id = grand_parent; tree.Node(parent)->local = rotation_about_x; int child = tree.Insert(TransformNode(), parent); - tree.SetTargetId(child, parent); - tree.SetContentTargetId(child, parent); tree.Node(child)->source_node_id = parent; tree.Node(child)->flattens_inherited_transform = true; tree.Node(child)->local = rotation_about_x; int grand_child = tree.Insert(TransformNode(), child); - tree.SetTargetId(grand_child, parent); - tree.SetContentTargetId(grand_child, parent); tree.Node(grand_child)->source_node_id = child; tree.Node(grand_child)->flattens_inherited_transform = true; tree.Node(grand_child)->local = rotation_about_x; @@ -293,14 +274,12 @@ TEST(PropertyTreeTest, MultiplicationOrder) { contents_root.local.Translate(2, 2); contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode child; child.local.Scale(2, 2); child.source_node_id = 1; child.id = tree.Insert(child, 1); - tree.SetTargetId(child.id, 0); tree.UpdateTransforms(2); @@ -328,14 +307,12 @@ TEST(PropertyTreeTest, ComputeTransformWithUninvertibleTransform) { TransformNode contents_root; contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode child; child.local.Scale(0, 0); child.source_node_id = 1; child.id = tree.Insert(child, 1); - tree.SetTargetId(child.id, 0); tree.UpdateTransforms(2); @@ -360,31 +337,24 @@ TEST(PropertyTreeTest, ComputeTransformToTargetWithZeroSurfaceContentsScale) { TransformNode contents_root; contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode grand_parent; grand_parent.local.Scale(2.f, 0.f); grand_parent.source_node_id = 1; int grand_parent_id = tree.Insert(grand_parent, 1); - tree.SetTargetId(grand_parent_id, 0); - tree.SetContentTargetId(grand_parent_id, grand_parent_id); tree.UpdateTransforms(grand_parent_id); TransformNode parent; parent.local.Translate(1.f, 1.f); parent.source_node_id = grand_parent_id; int parent_id = tree.Insert(parent, grand_parent_id); - tree.SetTargetId(parent_id, grand_parent_id); - tree.SetContentTargetId(parent_id, grand_parent_id); tree.UpdateTransforms(parent_id); TransformNode child; child.local.Translate(3.f, 4.f); child.source_node_id = parent_id; int child_id = tree.Insert(child, parent_id); - tree.SetTargetId(child_id, grand_parent_id); - tree.SetContentTargetId(child_id, grand_parent_id); tree.UpdateTransforms(child_id); gfx::Transform expected_transform; @@ -425,8 +395,6 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { TransformTree& tree = property_trees.transform_tree; int parent = tree.Insert(TransformNode(), 0); - tree.SetContentTargetId(parent, parent); - tree.SetTargetId(parent, parent); tree.Node(parent)->source_node_id = 0; tree.Node(parent)->local.Translate(2, 2); @@ -434,14 +402,10 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { rotation_about_x.RotateAboutXAxis(15); int child = tree.Insert(TransformNode(), parent); - tree.SetContentTargetId(child, child); - tree.SetTargetId(child, child); tree.Node(child)->source_node_id = parent; tree.Node(child)->local = rotation_about_x; int grand_child = tree.Insert(TransformNode(), child); - tree.SetContentTargetId(grand_child, grand_child); - tree.SetTargetId(grand_child, grand_child); tree.Node(grand_child)->source_node_id = child; tree.Node(grand_child)->flattens_inherited_transform = true; @@ -485,12 +449,10 @@ TEST(PropertyTreeTest, NonIntegerTranslationTest) { TransformTree& tree = property_trees.transform_tree; int parent = tree.Insert(TransformNode(), 0); - tree.SetTargetId(parent, parent); tree.Node(parent)->source_node_id = 0; tree.Node(parent)->local.Translate(1.5f, 1.5f); int child = tree.Insert(TransformNode(), parent); - tree.SetTargetId(child, parent); tree.Node(child)->local.Translate(1, 1); tree.Node(child)->source_node_id = parent; tree.set_needs_update(true); @@ -513,7 +475,6 @@ TEST(PropertyTreeTest, NonIntegerTranslationTest) { tree.Node(child)->local.Translate(0.5f, 0.5f); tree.Node(child)->needs_local_transform_update = true; - tree.SetTargetId(child, child); tree.set_needs_update(true); draw_property_utils::ComputeTransforms(&tree); EXPECT_TRUE( @@ -534,13 +495,11 @@ TEST(PropertyTreeTest, SingularTransformSnapTest) { effect_tree.Node(effect_parent)->has_render_surface = true; effect_tree.Node(effect_parent)->surface_contents_scale = gfx::Vector2dF(1.f, 1.f); - tree.SetTargetId(parent, parent); tree.Node(parent)->scrolls = true; tree.Node(parent)->source_node_id = 0; int child = tree.Insert(TransformNode(), parent); TransformNode* child_node = tree.Node(child); - tree.SetTargetId(child, parent); child_node->scrolls = true; child_node->local.Scale3d(6.0f, 6.0f, 0.0f); child_node->local.Translate(1.3f, 1.3f); diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h index 9e6c4c09596..7bb9145a894 100644 --- a/chromium/cc/trees/proxy.h +++ b/chromium/cc/trees/proxy.h @@ -13,7 +13,7 @@ #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "base/values.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/browser_controls_state.h" #include "cc/scheduler/begin_frame_source.h" #include "cc/trees/task_runner_provider.h" diff --git a/chromium/cc/trees/proxy_common.h b/chromium/cc/trees/proxy_common.h index 69ffcfda262..45e16a9bd40 100644 --- a/chromium/cc/trees/proxy_common.h +++ b/chromium/cc/trees/proxy_common.h @@ -8,7 +8,7 @@ #include <stddef.h> #include "base/callback_forward.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/begin_frame_args.h" #include "cc/trees/layer_tree_host_common.h" @@ -26,6 +26,7 @@ struct CC_EXPORT BeginMainFrameAndCommitState { std::unique_ptr<ScrollAndScaleSet> scroll_info; size_t memory_allocation_limit_bytes = 0; bool evicted_ui_resources = false; + std::vector<base::Closure> completed_image_decode_callbacks; }; } // namespace cc diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc index 56919567b05..afced7e5c42 100644 --- a/chromium/cc/trees/proxy_impl.cc +++ b/chromium/cc/trees/proxy_impl.cc @@ -4,16 +4,20 @@ #include "cc/trees/proxy_impl.h" +#include <string.h> + #include <algorithm> #include <string> #include "base/auto_reset.h" +#include "base/debug/alias.h" +#include "base/debug/dump_without_crashing.h" #include "base/memory/ptr_util.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "base/trace_event/trace_event_synthetic_delay.h" -#include "cc/debug/benchmark_instrumentation.h" -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" +#include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/input/browser_controls_offset_manager.h" #include "cc/output/compositor_frame_sink.h" #include "cc/output/context_provider.h" @@ -129,8 +133,8 @@ void ProxyImpl::InitializeCompositorFrameSinkOnImpl( LayerTreeHostImpl* host_impl = layer_tree_host_impl_.get(); bool success = host_impl->InitializeRenderer(compositor_frame_sink); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::DidInitializeCompositorFrameSink, - proxy_main_weak_ptr_, success)); + FROM_HERE, base::BindOnce(&ProxyMain::DidInitializeCompositorFrameSink, + proxy_main_weak_ptr_, success)); if (success) scheduler_->DidCreateAndInitializeCompositorFrameSink(); } @@ -223,6 +227,28 @@ void ProxyImpl::MainFrameWillHappenOnImplForTesting( completion->Signal(); } +// TODO(sunnyps): Remove this code once crbug.com/668892 is fixed. +NOINLINE void ProxyImpl::DumpForBeginMainFrameHang() { + DCHECK(IsImplThread()); + DCHECK(scheduler_); + + char stack_string[20000] = ""; + base::debug::Alias(&stack_string); + + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> scheduler_state = + scheduler_->AsValue(); + strncat(stack_string, scheduler_state->ToString().c_str(), + arraysize(stack_string) - strlen(stack_string) - 1); + + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> + tile_manager_state = + layer_tree_host_impl_->tile_manager()->ActivationStateAsValue(); + strncat(stack_string, tile_manager_state->ToString().c_str(), + arraysize(stack_string) - strlen(stack_string) - 1); + + base::debug::DumpWithoutCrashing(); +} + void ProxyImpl::NotifyReadyToCommitOnImpl( CompletionEvent* completion, LayerTreeHost* layer_tree_host, @@ -259,8 +285,8 @@ void ProxyImpl::DidLoseCompositorFrameSinkOnImplThread() { TRACE_EVENT0("cc", "ProxyImpl::DidLoseCompositorFrameSinkOnImplThread"); DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ProxyMain::DidLoseCompositorFrameSink, proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::DidLoseCompositorFrameSink, + proxy_main_weak_ptr_)); scheduler_->DidLoseCompositorFrameSink(); } @@ -280,8 +306,8 @@ void ProxyImpl::DidReceiveCompositorFrameAckOnImplThread() { DCHECK(IsImplThread()); scheduler_->DidReceiveCompositorFrameAck(); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::DidReceiveCompositorFrameAck, - proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::DidReceiveCompositorFrameAck, + proxy_main_weak_ptr_)); } void ProxyImpl::OnCanDrawStateChanged(bool can_draw) { @@ -339,8 +365,8 @@ void ProxyImpl::PostAnimationEventsToMainThreadOnImplThread( TRACE_EVENT0("cc", "ProxyImpl::PostAnimationEventsToMainThreadOnImplThread"); DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::SetAnimationEvents, - proxy_main_weak_ptr_, base::Passed(&events))); + FROM_HERE, base::BindOnce(&ProxyMain::SetAnimationEvents, + proxy_main_weak_ptr_, base::Passed(&events))); } bool ProxyImpl::IsInsideDraw() { @@ -423,8 +449,8 @@ void ProxyImpl::DidPrepareTiles() { void ProxyImpl::DidCompletePageScaleAnimationOnImplThread() { DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::DidCompletePageScaleAnimation, - proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::DidCompletePageScaleAnimation, + proxy_main_weak_ptr_)); } void ProxyImpl::OnDrawForCompositorFrameSink(bool resourceless_software_draw) { @@ -462,9 +488,12 @@ void ProxyImpl::ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) { layer_tree_host_impl_->ProcessScrollDeltas(); begin_main_frame_state->evicted_ui_resources = layer_tree_host_impl_->EvictedUIResourcesExist(); + begin_main_frame_state->completed_image_decode_callbacks = + layer_tree_host_impl_->TakeCompletedImageDecodeCallbacks(); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::BeginMainFrame, proxy_main_weak_ptr_, - base::Passed(&begin_main_frame_state))); + FROM_HERE, + base::BindOnce(&ProxyMain::BeginMainFrame, proxy_main_weak_ptr_, + base::Passed(&begin_main_frame_state))); layer_tree_host_impl_->DidSendBeginMainFrame(); devtools_instrumentation::DidRequestMainThreadFrame(layer_tree_host_id_); } @@ -493,6 +522,12 @@ void ProxyImpl::ScheduledActionCommit() { DCHECK(IsMainThreadBlocked()); DCHECK(commit_completion_event_); + // Relax the cross-thread access restriction to non-thread-safe RefCount. + // It's safe since the main thread is blocked while a main-thread-bound + // compositor stuff are accessed from the impl thread. + base::ScopedAllowCrossThreadRefCountAccess + allow_cross_thread_ref_count_access; + layer_tree_host_impl_->BeginCommit(); blocked_main_commit().layer_tree_host->FinishCommitOnImplThread( layer_tree_host_impl_.get()); @@ -537,8 +572,8 @@ void ProxyImpl::ScheduledActionBeginCompositorFrameSinkCreation() { "ProxyImpl::ScheduledActionBeginCompositorFrameSinkCreation"); DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::RequestNewCompositorFrameSink, - proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::RequestNewCompositorFrameSink, + proxy_main_weak_ptr_)); } void ProxyImpl::ScheduledActionPrepareTiles() { @@ -563,8 +598,8 @@ void ProxyImpl::ScheduledActionPerformImplSideInvalidation() { void ProxyImpl::SendBeginMainFrameNotExpectedSoon() { DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::BeginMainFrameNotExpectedSoon, - proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::BeginMainFrameNotExpectedSoon, + proxy_main_weak_ptr_)); } DrawResult ProxyImpl::DrawInternal(bool forced_draw) { @@ -593,6 +628,7 @@ DrawResult ProxyImpl::DrawInternal(bool forced_draw) { // CanDraw() as well. LayerTreeHostImpl::FrameData frame; + frame.begin_frame_ack = scheduler_->CurrentBeginFrameAckForActiveTree(); bool draw_frame = false; DrawResult result; @@ -621,8 +657,8 @@ DrawResult ProxyImpl::DrawInternal(bool forced_draw) { if (next_frame_is_newly_committed_frame_) { next_frame_is_newly_committed_frame_ = false; MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ProxyMain::DidCommitAndDrawFrame, proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::DidCommitAndDrawFrame, + proxy_main_weak_ptr_)); } DCHECK_NE(INVALID_RESULT, result); diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h index a0482ea2ff8..68edc334515 100644 --- a/chromium/cc/trees/proxy_impl.h +++ b/chromium/cc/trees/proxy_impl.h @@ -56,6 +56,8 @@ class CC_EXPORT ProxyImpl : public NON_EXPORTED_BASE(LayerTreeHostImplClient), void MainFrameWillHappenOnImplForTesting(CompletionEvent* completion, bool* main_frame_will_happen); + NOINLINE void DumpForBeginMainFrameHang(); + private: // The members of this struct should be accessed on the impl thread only when // the main thread is blocked for a commit. diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc index bab54a09e88..6b06f0ee80f 100644 --- a/chromium/cc/trees/proxy_main.cc +++ b/chromium/cc/trees/proxy_main.cc @@ -12,8 +12,8 @@ #include "base/trace_event/trace_event_argument.h" #include "base/trace_event/trace_event_synthetic_delay.h" #include "cc/base/completion_event.h" -#include "cc/debug/benchmark_instrumentation.h" -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" +#include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/output/compositor_frame_sink.h" #include "cc/output/swap_promise.h" #include "cc/resources/ui_resource_manager.h" @@ -124,16 +124,23 @@ void ProxyMain::BeginMainFrame( DCHECK(IsMainThread()); DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_); + // We need to issue image decode callbacks whether or not we will abort this + // commit, since the callbacks are only stored in |begin_main_frame_state|. + for (auto& callback : + begin_main_frame_state->completed_image_decode_callbacks) { + callback.Run(); + } + if (defer_commits_) { TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit", TRACE_EVENT_SCOPE_THREAD); std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl, - base::Unretained(proxy_impl_.get()), - CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT, - begin_main_frame_start_time, - base::Passed(&empty_swap_promises))); + FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, + base::Unretained(proxy_impl_.get()), + CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT, + begin_main_frame_start_time, + base::Passed(&empty_swap_promises))); return; } @@ -150,11 +157,11 @@ void ProxyMain::BeginMainFrame( TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD); std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl, - base::Unretained(proxy_impl_.get()), - CommitEarlyOutReason::ABORTED_NOT_VISIBLE, - begin_main_frame_start_time, - base::Passed(&empty_swap_promises))); + FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, + base::Unretained(proxy_impl_.get()), + CommitEarlyOutReason::ABORTED_NOT_VISIBLE, + begin_main_frame_start_time, + base::Passed(&empty_swap_promises))); return; } @@ -180,6 +187,26 @@ void ProxyMain::BeginMainFrame( layer_tree_host_->GetUIResourceManager()->RecreateUIResources(); layer_tree_host_->RequestMainFrameUpdate(); + + // At this point the main frame may have deferred commits to avoid committing + // right now. + if (defer_commits_) { + TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame", + TRACE_EVENT_SCOPE_THREAD); + std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises; + ImplThreadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, + base::Unretained(proxy_impl_.get()), + CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT, + begin_main_frame_start_time, + base::Passed(&empty_swap_promises))); + current_pipeline_stage_ = NO_PIPELINE_STAGE; + // We intentionally don't report CommitComplete() here since it was aborted + // prematurely and we're waiting to do another commit in the future. + layer_tree_host_->DidBeginMainFrame(); + return; + } + TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame"); bool can_cancel_this_commit = final_pipeline_stage_ < COMMIT_PIPELINE_STAGE && @@ -200,11 +227,11 @@ void ProxyMain::BeginMainFrame( std::vector<std::unique_ptr<SwapPromise>> swap_promises = layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises(); ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl, - base::Unretained(proxy_impl_.get()), - CommitEarlyOutReason::FINISHED_NO_UPDATES, - begin_main_frame_start_time, base::Passed(&swap_promises))); + FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, + base::Unretained(proxy_impl_.get()), + CommitEarlyOutReason::FINISHED_NO_UPDATES, + begin_main_frame_start_time, + base::Passed(&swap_promises))); // Although the commit is internally aborted, this is because it has been // detected to be a no-op. From the perspective of an embedder, this commit @@ -234,10 +261,11 @@ void ProxyMain::BeginMainFrame( commit_waits_for_activation_ = false; CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::NotifyReadyToCommitOnImpl, - base::Unretained(proxy_impl_.get()), &completion, - layer_tree_host_, begin_main_frame_start_time, - hold_commit_for_activation)); + FROM_HERE, + base::BindOnce(&ProxyImpl::NotifyReadyToCommitOnImpl, + base::Unretained(proxy_impl_.get()), &completion, + layer_tree_host_, begin_main_frame_start_time, + hold_commit_for_activation)); completion.Wait(); } @@ -260,16 +288,16 @@ bool ProxyMain::CommitToActiveTree() const { void ProxyMain::SetCompositorFrameSink( CompositorFrameSink* compositor_frame_sink) { ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ProxyImpl::InitializeCompositorFrameSinkOnImpl, - base::Unretained(proxy_impl_.get()), compositor_frame_sink)); + FROM_HERE, base::BindOnce(&ProxyImpl::InitializeCompositorFrameSinkOnImpl, + base::Unretained(proxy_impl_.get()), + compositor_frame_sink)); } void ProxyMain::SetVisible(bool visible) { TRACE_EVENT1("cc", "ProxyMain::SetVisible", "visible", visible); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::SetVisibleOnImpl, - base::Unretained(proxy_impl_.get()), visible)); + FROM_HERE, base::BindOnce(&ProxyImpl::SetVisibleOnImpl, + base::Unretained(proxy_impl_.get()), visible)); } void ProxyMain::SetNeedsAnimate() { @@ -314,8 +342,9 @@ void ProxyMain::SetNeedsRedraw(const gfx::Rect& damage_rect) { TRACE_EVENT0("cc", "ProxyMain::SetNeedsRedraw"); DCHECK(IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::SetNeedsRedrawOnImpl, - base::Unretained(proxy_impl_.get()), damage_rect)); + FROM_HERE, + base::BindOnce(&ProxyImpl::SetNeedsRedrawOnImpl, + base::Unretained(proxy_impl_.get()), damage_rect)); } void ProxyMain::SetNextCommitWaitsForActivation() { @@ -326,8 +355,8 @@ void ProxyMain::SetNextCommitWaitsForActivation() { void ProxyMain::NotifyInputThrottledUntilCommit() { DCHECK(IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::SetInputThrottledUntilCommitOnImpl, - base::Unretained(proxy_impl_.get()), true)); + FROM_HERE, base::BindOnce(&ProxyImpl::SetInputThrottledUntilCommitOnImpl, + base::Unretained(proxy_impl_.get()), true)); } void ProxyMain::SetDeferCommits(bool defer_commits) { @@ -343,8 +372,8 @@ void ProxyMain::SetDeferCommits(bool defer_commits) { ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ProxyImpl::SetDeferCommitsOnImpl, - base::Unretained(proxy_impl_.get()), defer_commits)); + base::BindOnce(&ProxyImpl::SetDeferCommitsOnImpl, + base::Unretained(proxy_impl_.get()), defer_commits)); } bool ProxyMain::CommitRequested() const { @@ -358,8 +387,8 @@ bool ProxyMain::CommitRequested() const { void ProxyMain::MainThreadHasStoppedFlinging() { DCHECK(IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::MainThreadHasStoppedFlingingOnImpl, - base::Unretained(proxy_impl_.get()))); + FROM_HERE, base::BindOnce(&ProxyImpl::MainThreadHasStoppedFlingingOnImpl, + base::Unretained(proxy_impl_.get()))); } void ProxyMain::Start() { @@ -370,8 +399,8 @@ void ProxyMain::Start() { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::InitializeOnImplThread, - base::Unretained(this), &completion)); + FROM_HERE, base::BindOnce(&ProxyMain::InitializeOnImplThread, + base::Unretained(this), &completion)); completion.Wait(); } @@ -392,16 +421,16 @@ void ProxyMain::Stop() { CompletionEvent completion; ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ProxyImpl::FinishGLOnImpl, - base::Unretained(proxy_impl_.get()), &completion)); + base::BindOnce(&ProxyImpl::FinishGLOnImpl, + base::Unretained(proxy_impl_.get()), &completion)); completion.Wait(); } { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::DestroyProxyImplOnImplThread, - base::Unretained(this), &completion)); + FROM_HERE, base::BindOnce(&ProxyMain::DestroyProxyImplOnImplThread, + base::Unretained(this), &completion)); completion.Wait(); } @@ -413,9 +442,9 @@ void ProxyMain::Stop() { void ProxyMain::SetMutator(std::unique_ptr<LayerTreeMutator> mutator) { TRACE_EVENT0("compositor-worker", "ThreadProxy::SetMutator"); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::InitializeMutatorOnImpl, - base::Unretained(proxy_impl_.get()), - base::Passed(std::move(mutator)))); + FROM_HERE, base::BindOnce(&ProxyImpl::InitializeMutatorOnImpl, + base::Unretained(proxy_impl_.get()), + base::Passed(std::move(mutator)))); } bool ProxyMain::SupportsImplScrolling() const { @@ -429,9 +458,10 @@ bool ProxyMain::MainFrameWillHappenForTesting() { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::MainFrameWillHappenOnImplForTesting, - base::Unretained(proxy_impl_.get()), &completion, - &main_frame_will_happen)); + FROM_HERE, + base::BindOnce(&ProxyImpl::MainFrameWillHappenOnImplForTesting, + base::Unretained(proxy_impl_.get()), &completion, + &main_frame_will_happen)); completion.Wait(); } return main_frame_will_happen; @@ -442,8 +472,9 @@ void ProxyMain::ReleaseCompositorFrameSink() { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::ReleaseCompositorFrameSinkOnImpl, - base::Unretained(proxy_impl_.get()), &completion)); + FROM_HERE, + base::BindOnce(&ProxyImpl::ReleaseCompositorFrameSinkOnImpl, + base::Unretained(proxy_impl_.get()), &completion)); completion.Wait(); } @@ -452,9 +483,9 @@ void ProxyMain::UpdateBrowserControlsState(BrowserControlsState constraints, bool animate) { DCHECK(IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::UpdateBrowserControlsStateOnImpl, - base::Unretained(proxy_impl_.get()), constraints, - current, animate)); + FROM_HERE, base::BindOnce(&ProxyImpl::UpdateBrowserControlsStateOnImpl, + base::Unretained(proxy_impl_.get()), + constraints, current, animate)); } bool ProxyMain::SendCommitRequestToImplThreadIfNeeded( @@ -467,8 +498,8 @@ bool ProxyMain::SendCommitRequestToImplThreadIfNeeded( if (already_posted) return false; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::SetNeedsCommitOnImpl, - base::Unretained(proxy_impl_.get()))); + FROM_HERE, base::BindOnce(&ProxyImpl::SetNeedsCommitOnImpl, + base::Unretained(proxy_impl_.get()))); return true; } diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h index 29f4880a8b6..3d97276193a 100644 --- a/chromium/cc/trees/proxy_main.h +++ b/chromium/cc/trees/proxy_main.h @@ -6,7 +6,7 @@ #define CC_TREES_PROXY_MAIN_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/browser_controls_state.h" #include "cc/trees/proxy.h" #include "cc/trees/proxy_common.h" diff --git a/chromium/cc/trees/scroll_node.h b/chromium/cc/trees/scroll_node.h index 09d7be86ecf..4eefe42aff1 100644 --- a/chromium/cc/trees/scroll_node.h +++ b/chromium/cc/trees/scroll_node.h @@ -5,9 +5,9 @@ #ifndef CC_TREES_SCROLL_NODE_H_ #define CC_TREES_SCROLL_NODE_H_ -#include "cc/base/cc_export.h" +#include "cc/base/filter_operations.h" #include "cc/base/region.h" -#include "cc/output/filter_operations.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/size.h" namespace base { diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index 33ed54ae3a9..07b5afa607a 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -8,8 +8,8 @@ #include "base/memory/ptr_util.h" #include "base/profiler/scoped_tracker.h" #include "base/trace_event/trace_event.h" -#include "cc/debug/benchmark_instrumentation.h" -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" +#include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/output/compositor_frame_sink.h" #include "cc/output/context_provider.h" #include "cc/quads/draw_quad.h" @@ -204,6 +204,12 @@ void SingleThreadProxy::DoCommit() { if (scheduler_on_impl_thread_) scheduler_on_impl_thread_->DidCommit(); + // Issue decode callbacks. + auto completed_decode_callbacks = + layer_tree_host_impl_->TakeCompletedImageDecodeCallbacks(); + for (auto& callback : completed_decode_callbacks) + callback.Run(); + layer_tree_host_impl_->CommitComplete(); // Commit goes directly to the active tree, but we need to synchronously @@ -449,8 +455,9 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { } BeginFrameArgs begin_frame_args(BeginFrameArgs::Create( - BEGINFRAME_FROM_HERE, 0, 1, frame_begin_time, base::TimeTicks(), - BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL)); + BEGINFRAME_FROM_HERE, BeginFrameArgs::kManualSourceId, 1, + frame_begin_time, base::TimeTicks(), BeginFrameArgs::DefaultInterval(), + BeginFrameArgs::NORMAL)); // Start the impl frame. { @@ -464,6 +471,7 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { DCHECK(inside_impl_frame_); #endif DoBeginMainFrame(begin_frame_args); + DoPainting(); DoCommit(); DCHECK_EQ( @@ -485,6 +493,9 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { layer_tree_host_impl_->Animate(); LayerTreeHostImpl::FrameData frame; + frame.begin_frame_ack = BeginFrameAck( + begin_frame_args.source_id, begin_frame_args.sequence_number, + begin_frame_args.sequence_number, true); DoComposite(&frame); // DoComposite could abort, but because this is a synchronous composite @@ -604,8 +615,8 @@ void SingleThreadProxy::ScheduledActionSendBeginMainFrame( #endif task_runner_provider_->MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&SingleThreadProxy::BeginMainFrame, - weak_factory_.GetWeakPtr(), begin_frame_args)); + FROM_HERE, base::BindOnce(&SingleThreadProxy::BeginMainFrame, + weak_factory_.GetWeakPtr(), begin_frame_args)); layer_tree_host_impl_->DidSendBeginMainFrame(); } @@ -648,6 +659,22 @@ void SingleThreadProxy::BeginMainFrame(const BeginFrameArgs& begin_frame_args) { commit_requested_ = true; DoBeginMainFrame(begin_frame_args); + + // New commits requested inside UpdateLayers should be respected. + commit_requested_ = false; + + // At this point the main frame may have deferred commits to avoid committing + // right now. + if (defer_commits_) { + TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame", + TRACE_EVENT_SCOPE_THREAD); + BeginMainFrameAbortedOnImplThread( + CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT); + layer_tree_host_->DidBeginMainFrame(); + return; + } + + DoPainting(); } void SingleThreadProxy::DoBeginMainFrame( @@ -664,10 +691,9 @@ void SingleThreadProxy::DoBeginMainFrame( layer_tree_host_->BeginMainFrame(begin_frame_args); layer_tree_host_->AnimateLayers(begin_frame_args.frame_time); layer_tree_host_->RequestMainFrameUpdate(); +} - // New commits requested inside UpdateLayers should be respected. - commit_requested_ = false; - +void SingleThreadProxy::DoPainting() { layer_tree_host_->UpdateLayers(); // TODO(enne): SingleThreadProxy does not support cancelling commits yet, @@ -692,6 +718,8 @@ void SingleThreadProxy::BeginMainFrameAbortedOnImplThread( DrawResult SingleThreadProxy::ScheduledActionDrawIfPossible() { DebugScopedSetImplThread impl(task_runner_provider_); LayerTreeHostImpl::FrameData frame; + frame.begin_frame_ack = + scheduler_on_impl_thread_->CurrentBeginFrameAckForActiveTree(); return DoComposite(&frame); } diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index 3e9487ea358..4a091950a27 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -112,6 +112,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void BeginMainFrame(const BeginFrameArgs& begin_frame_args); void BeginMainFrameAbortedOnImplThread(CommitEarlyOutReason reason); void DoBeginMainFrame(const BeginFrameArgs& begin_frame_args); + void DoPainting(); void DoCommit(); DrawResult DoComposite(LayerTreeHostImpl::FrameData* frame); void DoSwap(); diff --git a/chromium/cc/trees/swap_promise_manager.h b/chromium/cc/trees/swap_promise_manager.h index 8b5d9a23e56..795493dd3bb 100644 --- a/chromium/cc/trees/swap_promise_manager.h +++ b/chromium/cc/trees/swap_promise_manager.h @@ -9,7 +9,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/swap_promise.h" namespace cc { diff --git a/chromium/cc/trees/swap_promise_monitor.h b/chromium/cc/trees/swap_promise_monitor.h index 550176438e9..cde077e6345 100644 --- a/chromium/cc/trees/swap_promise_monitor.h +++ b/chromium/cc/trees/swap_promise_monitor.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_SWAP_PROMISE_MONITOR_H_ #define CC_TREES_SWAP_PROMISE_MONITOR_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/trees/target_property.h b/chromium/cc/trees/target_property.h index e118c8db6a7..177ef965afa 100644 --- a/chromium/cc/trees/target_property.h +++ b/chromium/cc/trees/target_property.h @@ -7,7 +7,7 @@ #include <bitset> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/trees/task_runner_provider.h b/chromium/cc/trees/task_runner_provider.h index e4c7b195cc4..1a7ebf5adca 100644 --- a/chromium/cc/trees/task_runner_provider.h +++ b/chromium/cc/trees/task_runner_provider.h @@ -16,7 +16,7 @@ #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "base/values.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { class SingleThreadTaskRunner; diff --git a/chromium/cc/trees/transform_node.cc b/chromium/cc/trees/transform_node.cc index 8b9360f9091..6f89261dd29 100644 --- a/chromium/cc/trees/transform_node.cc +++ b/chromium/cc/trees/transform_node.cc @@ -108,9 +108,6 @@ void TransformNode::AsValueInto(base::trace_event::TracedValue* value) const { MathUtil::AddToTracedValue("pre_local", pre_local, value); MathUtil::AddToTracedValue("local", local, value); MathUtil::AddToTracedValue("post_local", post_local, value); - // TODO(sunxd): make frameviewer work without target_id - value->SetInteger("target_id", 0); - value->SetInteger("content_target_id", 0); value->SetInteger("source_node_id", source_node_id); value->SetInteger("sorting_context_id", sorting_context_id); MathUtil::AddToTracedValue("scroll_offset", scroll_offset, value); @@ -118,7 +115,7 @@ void TransformNode::AsValueInto(base::trace_event::TracedValue* value) const { } TransformCachedNodeData::TransformCachedNodeData() - : target_id(-1), content_target_id(-1), is_showing_backface(false) {} + : is_showing_backface(false) {} TransformCachedNodeData::TransformCachedNodeData( const TransformCachedNodeData& other) = default; @@ -128,8 +125,6 @@ TransformCachedNodeData::~TransformCachedNodeData() {} bool TransformCachedNodeData::operator==( const TransformCachedNodeData& other) const { return from_screen == other.from_screen && to_screen == other.to_screen && - target_id == other.target_id && - content_target_id == other.content_target_id && is_showing_backface == other.is_showing_backface; } diff --git a/chromium/cc/trees/transform_node.h b/chromium/cc/trees/transform_node.h index b98e83cdae9..76f2a7c2ffc 100644 --- a/chromium/cc/trees/transform_node.h +++ b/chromium/cc/trees/transform_node.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_TRANSFORM_NODE_H_ #define CC_TREES_TRANSFORM_NODE_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/transform.h" @@ -148,10 +148,6 @@ struct CC_EXPORT TransformCachedNodeData { gfx::Transform from_screen; gfx::Transform to_screen; - int target_id; - // This id is used for all content that draws into a render surface associated - // with this transform node. - int content_target_id; bool is_showing_backface : 1; diff --git a/chromium/cc/trees/tree_synchronizer.cc b/chromium/cc/trees/tree_synchronizer.cc index b593a9d66e9..52f1bb384c7 100644 --- a/chromium/cc/trees/tree_synchronizer.cc +++ b/chromium/cc/trees/tree_synchronizer.cc @@ -28,8 +28,10 @@ void SynchronizeTreesInternal(LayerTreeType* source_tree, std::unique_ptr<OwnedLayerImplList> old_layers(tree_impl->DetachLayers()); OwnedLayerImplMap old_layer_map; - for (auto& it : *old_layers) + for (auto& it : *old_layers) { + DCHECK(it); old_layer_map[it->id()] = std::move(it); + } PushLayerList(&old_layer_map, source_tree, tree_impl); diff --git a/chromium/cc/trees/tree_synchronizer.h b/chromium/cc/trees/tree_synchronizer.h index e5a0b62a0f6..1f0a1a1c8cf 100644 --- a/chromium/cc/trees/tree_synchronizer.h +++ b/chromium/cc/trees/tree_synchronizer.h @@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { |