diff options
Diffstat (limited to 'chromium/cc')
240 files changed, 6085 insertions, 16111 deletions
diff --git a/chromium/cc/BUILD.gn b/chromium/cc/BUILD.gn index 19828e3374a..4f6b936f03f 100644 --- a/chromium/cc/BUILD.gn +++ b/chromium/cc/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. +# Copyright 2014 T/e 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. @@ -33,6 +33,7 @@ cc_component("cc") { "input/input_handler.h", "input/layer_selection_bound.cc", "input/layer_selection_bound.h", + "input/main_thread_scrolling_reason.cc", "input/main_thread_scrolling_reason.h", "input/overscroll_behavior.h", "input/page_scale_animation.cc", @@ -49,6 +50,10 @@ cc_component("cc") { "input/scrollbar_animation_controller.h", "input/single_scrollbar_animation_controller_thinning.cc", "input/single_scrollbar_animation_controller_thinning.h", + "input/snap_fling_controller.cc", + "input/snap_fling_controller.h", + "input/snap_fling_curve.cc", + "input/snap_fling_curve.h", "input/touch_action.h", "layers/append_quads_data.cc", "layers/append_quads_data.h", @@ -137,8 +142,6 @@ cc_component("cc") { "layers/video_layer_impl.h", "layers/viewport.cc", "layers/viewport.h", - "output/overlay_candidate.cc", - "output/overlay_candidate.h", "raster/bitmap_raster_buffer_provider.cc", "raster/bitmap_raster_buffer_provider.h", "raster/gpu_raster_buffer_provider.cc", @@ -177,17 +180,12 @@ cc_component("cc") { "raster/zero_copy_raster_buffer_provider.h", "resources/cross_thread_shared_bitmap.cc", "resources/cross_thread_shared_bitmap.h", - "resources/display_resource_provider.cc", - "resources/display_resource_provider.h", "resources/layer_tree_resource_provider.cc", "resources/layer_tree_resource_provider.h", "resources/memory_history.cc", "resources/memory_history.h", - "resources/resource.h", "resources/resource_pool.cc", "resources/resource_pool.h", - "resources/resource_provider.cc", - "resources/resource_provider.h", "resources/scoped_ui_resource.cc", "resources/scoped_ui_resource.h", "resources/shared_bitmap_id_registrar.cc", @@ -509,6 +507,8 @@ cc_static_library("test_support") { "test/test_layer_tree_host_base.cc", "test/test_layer_tree_host_base.h", "test/test_occlusion_tracker.h", + "test/test_options_provider.cc", + "test/test_options_provider.h", "test/test_skcanvas.cc", "test/test_skcanvas.h", "test/test_task_graph_runner.cc", @@ -527,6 +527,7 @@ cc_static_library("test_support") { ":cc", "//cc/animation", "//gpu:test_support", + "//testing/gmock", ] deps = [ "//base", @@ -545,7 +546,6 @@ cc_static_library("test_support") { "//gpu/skia_bindings", "//media", "//skia", - "//testing/gmock", "//testing/gtest", "//ui/gfx", "//ui/gfx:test_support", @@ -579,11 +579,13 @@ cc_test("cc_unittests") { "benchmarks/micro_benchmark_controller_unittest.cc", "debug/rendering_stats_unittest.cc", "input/browser_controls_offset_manager_unittest.cc", + "input/main_thread_scrolling_reason_unittest.cc", "input/scroll_snap_data_unittest.cc", "input/scroll_state_unittest.cc", "input/scrollbar_animation_controller_unittest.cc", "input/single_scrollbar_animation_controller_thinning_unittest.cc", - "ipc/cc_param_traits_unittest.cc", + "input/snap_fling_controller_unittest.cc", + "input/snap_fling_curve_unittest.cc", "layers/effect_tree_layer_list_iterator_unittest.cc", "layers/heads_up_display_layer_impl_unittest.cc", "layers/heads_up_display_unittest.cc", @@ -638,11 +640,8 @@ cc_test("cc_unittests") { "raster/synchronous_task_graph_runner_unittest.cc", "raster/task_graph_work_queue_unittest.cc", "raster/texture_compressor_etc1_unittest.cc", - "resources/display_resource_provider_unittest.cc", "resources/layer_tree_resource_provider_unittest.cc", "resources/resource_pool_unittest.cc", - "resources/resource_provider_unittest.cc", - "resources/resource_util_unittest.cc", "resources/video_resource_updater_unittest.cc", "scheduler/compositor_timing_history_unittest.cc", "scheduler/scheduler_state_machine_unittest.cc", @@ -677,6 +676,7 @@ cc_test("cc_unittests") { "trees/layer_tree_host_unittest_context.cc", "trees/layer_tree_host_unittest_copyrequest.cc", "trees/layer_tree_host_unittest_damage.cc", + "trees/layer_tree_host_unittest_masks.cc", "trees/layer_tree_host_unittest_occlusion.cc", "trees/layer_tree_host_unittest_picture.cc", "trees/layer_tree_host_unittest_proxy.cc", @@ -729,7 +729,6 @@ cc_test("cc_unittests") { ":cc", ":test_support", "//base/test:test_support", - "//cc/ipc", "//cc/paint", "//components/ukm:test_support", "//components/viz/common", @@ -765,7 +764,6 @@ cc_test("cc_perftests") { sources = [ "animation/animation_host_perftest.cc", "base/rtree_perftest.cc", - "ipc/cc_serialization_perftest.cc", "layers/layer_perftest.cc", "layers/picture_layer_impl_perftest.cc", "paint/paint_op_perftest.cc", @@ -786,7 +784,6 @@ cc_test("cc_perftests") { ":test_support", "//base", "//base/test:test_support", - "//cc/ipc", "//cc/paint", "//components/viz/common", "//components/viz/test:test_support", diff --git a/chromium/cc/DEPS b/chromium/cc/DEPS index fb06dd1e017..2e684073776 100644 --- a/chromium/cc/DEPS +++ b/chromium/cc/DEPS @@ -27,10 +27,10 @@ include_rules = [ "+third_party/khronos/GLES2/gl2ext.h", "+third_party/libyuv", "+third_party/skia/include", + "+third_party/skia/src/core/SkRemoteGlyphCache.h", "+ui/latency/latency_info.h", "+ui/gfx", "+ui/gl", - "-cc/blink", ] specific_include_rules = { diff --git a/chromium/cc/OWNERS b/chromium/cc/OWNERS index 169e4a1ea5f..5a453bed667 100644 --- a/chromium/cc/OWNERS +++ b/chromium/cc/OWNERS @@ -59,6 +59,9 @@ vmpstr@chromium.org fsamuel@chromium.org kylechar@chromium.org +# input, scrolling +bokan@chromium.org + # we miss you # jamesr@chromium.org # nduca@chromium.org diff --git a/chromium/cc/PRESUBMIT.py b/chromium/cc/PRESUBMIT.py index 3ddbde82ec0..3e27d70855f 100644 --- a/chromium/cc/PRESUBMIT.py +++ b/chromium/cc/PRESUBMIT.py @@ -275,25 +275,6 @@ def CheckForUseOfWrongClock(input_api, else: return [] -def CheckIpcUpdatedWithMojo(input_api, output_api): - """Make sure IPC is updated whenever Mojo serialization is updated""" - def match_ipc(affected_file): - match = re.match(r'.*_param_traits.*', affected_file.LocalPath()) - return match is not None - - def match_mojo(affected_file): - mojo_patterns = (r'.*_struct_traits.*', r'.*\.mojom$', r'.*\.typemap$') - matches = (re.match(pattern, affected_file.LocalPath()) - for pattern in mojo_patterns) - return any(matches) - - ipc_files = input_api.AffectedFiles(file_filter=match_ipc) - mojo_files = input_api.AffectedFiles(file_filter=match_mojo) - if mojo_files and not ipc_files: - return [output_api.PresubmitPromptOrNotify( - 'Make sure to update IPC ParamTraits along with mojo types.\n\n'),] - return [] - def CheckChangeOnUpload(input_api, output_api): results = [] results += CheckAsserts(input_api, output_api) @@ -305,7 +286,6 @@ def CheckChangeOnUpload(input_api, output_api): results += CheckNamespace(input_api, output_api) results += CheckForUseOfWrongClock(input_api, output_api) results += FindUselessIfdefs(input_api, output_api) - results += CheckIpcUpdatedWithMojo(input_api, output_api) return results def PostUploadHook(cl, change, output_api): diff --git a/chromium/cc/animation/animation.cc b/chromium/cc/animation/animation.cc index 8dd68bea444..57af2598821 100644 --- a/chromium/cc/animation/animation.cc +++ b/chromium/cc/animation/animation.cc @@ -243,7 +243,7 @@ void Animation::PushPropertiesTo(Animation* animation_impl) { void Animation::Tick(base::TimeTicks monotonic_time) { DCHECK(!monotonic_time.is_null()); for (auto& keyframe_effect : keyframe_effects_) - keyframe_effect->Tick(monotonic_time, nullptr); + keyframe_effect->Tick(monotonic_time); } void Animation::UpdateState(bool start_ready_animations, diff --git a/chromium/cc/animation/animation.h b/chromium/cc/animation/animation.h index 64ddcae8eb6..6ac050dfabe 100644 --- a/chromium/cc/animation/animation.h +++ b/chromium/cc/animation/animation.h @@ -90,7 +90,7 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { void AbortKeyframeModels(TargetProperty::Type target_property, bool needs_completion); - virtual void PushPropertiesTo(Animation* animation_impl); + void PushPropertiesTo(Animation* animation_impl); void UpdateState(bool start_ready_keyframe_models, AnimationEvents* events); virtual void Tick(base::TimeTicks monotonic_time); diff --git a/chromium/cc/animation/animation_curve.h b/chromium/cc/animation/animation_curve.h index 9865878afd8..34979f7b57c 100644 --- a/chromium/cc/animation/animation_curve.h +++ b/chromium/cc/animation/animation_curve.h @@ -13,10 +13,6 @@ #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/transform.h" -namespace gfx { -class BoxF; -} - namespace cc { class ColorAnimationCurve; @@ -81,12 +77,6 @@ class CC_ANIMATION_EXPORT TransformAnimationCurve : public AnimationCurve { virtual TransformOperations GetValue(base::TimeDelta t) const = 0; - // Sets |bounds| to be the bounding box for the region within which |box| - // will move during this animation. If this region cannot be computed, - // returns false. - virtual bool AnimatedBoundsForBox(const gfx::BoxF& box, - gfx::BoxF* bounds) const = 0; - // Returns true if this animation is a translation. virtual bool IsTranslation() const = 0; diff --git a/chromium/cc/animation/animation_host.cc b/chromium/cc/animation/animation_host.cc index 0b17d50a78e..cc1f51ad0f3 100644 --- a/chromium/cc/animation/animation_host.cc +++ b/chromium/cc/animation/animation_host.cc @@ -257,8 +257,6 @@ void AnimationHost::PushPropertiesToImplThread(AnimationHost* host_impl) { scroll_offset_animations_->PushPropertiesTo( host_impl->scroll_offset_animations_impl_.get()); host_impl->main_thread_animations_count_ = main_thread_animations_count_; - host_impl->main_thread_compositable_animations_count_ = - main_thread_compositable_animations_count_; host_impl->current_frame_had_raf_ = current_frame_had_raf_; host_impl->next_frame_has_pending_raf_ = next_frame_has_pending_raf_; } @@ -319,6 +317,7 @@ bool AnimationHost::TickAnimations(base::TimeTicks monotonic_time, bool did_animate = false; if (NeedsTickAnimations()) { + TRACE_EVENT_INSTANT0("cc", "NeedsTickAnimations", TRACE_EVENT_SCOPE_THREAD); AnimationsList ticking_animations_copy = ticking_animations_; for (auto& it : ticking_animations_copy) it->Tick(monotonic_time); @@ -654,7 +653,6 @@ size_t AnimationHost::CompositedAnimationsCount() const { void AnimationHost::SetAnimationCounts( size_t total_animations_count, - size_t main_thread_compositable_animations_count, bool current_frame_had_raf, bool next_frame_has_pending_raf) { // If an animation is being run on the compositor, it will have a ticking @@ -669,14 +667,6 @@ void AnimationHost::SetAnimationCounts( DCHECK_GE(main_thread_animations_count_, 0u); SetNeedsPushProperties(); } - if (main_thread_compositable_animations_count_ != - main_thread_compositable_animations_count) { - main_thread_compositable_animations_count_ = - main_thread_compositable_animations_count; - SetNeedsPushProperties(); - } - DCHECK_GE(main_thread_animations_count_, - main_thread_compositable_animations_count_); if (current_frame_had_raf != current_frame_had_raf_) { current_frame_had_raf_ = current_frame_had_raf; SetNeedsPushProperties(); @@ -691,10 +681,6 @@ size_t AnimationHost::MainThreadAnimationsCount() const { return main_thread_animations_count_; } -size_t AnimationHost::MainThreadCompositableAnimationsCount() const { - return main_thread_compositable_animations_count_; -} - bool AnimationHost::CurrentFrameHadRAF() const { return current_frame_had_raf_; } diff --git a/chromium/cc/animation/animation_host.h b/chromium/cc/animation/animation_host.h index 6a639b15e60..beae9903713 100644 --- a/chromium/cc/animation/animation_host.h +++ b/chromium/cc/animation/animation_host.h @@ -183,11 +183,9 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, size_t CompositedAnimationsCount() const override; size_t MainThreadAnimationsCount() const override; - size_t MainThreadCompositableAnimationsCount() const override; bool CurrentFrameHadRAF() const override; bool NextFrameHasPendingRAF() const override; void SetAnimationCounts(size_t total_animations_count, - size_t main_thread_compositable_animations_count, bool current_frame_had_raf, bool next_frame_has_pending_raf); @@ -229,7 +227,6 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, std::unique_ptr<LayerTreeMutator> mutator_; size_t main_thread_animations_count_ = 0; - size_t main_thread_compositable_animations_count_ = 0; bool current_frame_had_raf_ = false; bool next_frame_has_pending_raf_ = false; diff --git a/chromium/cc/animation/keyframe_effect.cc b/chromium/cc/animation/keyframe_effect.cc index 95ab3acab26..9b01eda5754 100644 --- a/chromium/cc/animation/keyframe_effect.cc +++ b/chromium/cc/animation/keyframe_effect.cc @@ -104,8 +104,7 @@ void KeyframeEffect::DetachElement() { element_id_ = ElementId(); } -void KeyframeEffect::Tick(base::TimeTicks monotonic_time, - const AnimationTimeProvider* tick_provider) { +void KeyframeEffect::Tick(base::TimeTicks monotonic_time) { DCHECK(has_bound_element_animations()); if (!element_animations_->has_element_in_any_list()) return; @@ -113,12 +112,8 @@ void KeyframeEffect::Tick(base::TimeTicks monotonic_time, if (needs_to_start_keyframe_models_) StartKeyframeModels(monotonic_time); - base::TimeTicks tick_time = monotonic_time; for (auto& keyframe_model : keyframe_models_) { - if (tick_provider) - tick_time = tick_provider->GetTimeForKeyframeModel(*keyframe_model); - - TickKeyframeModel(tick_time, keyframe_model.get(), + TickKeyframeModel(monotonic_time, keyframe_model.get(), element_animations_.get()); } @@ -225,6 +220,19 @@ void KeyframeEffect::UpdateTickingState(UpdateTickingType type) { } } +void KeyframeEffect::Pause(base::TimeDelta pause_offset) { + for (auto& keyframe_model : keyframe_models_) { + base::TimeTicks pause_time = keyframe_model->time_offset() + + keyframe_model->start_time() + pause_offset; + keyframe_model->SetRunState(KeyframeModel::PAUSED, pause_time); + } + + if (has_bound_element_animations()) { + animation_->SetNeedsCommit(); + SetNeedsPushProperties(); + } +} + void KeyframeEffect::AddKeyframeModel( std::unique_ptr<KeyframeModel> keyframe_model) { AnimationHost* animation_host = animation_->animation_host(); @@ -699,7 +707,7 @@ void KeyframeEffect::PushNewKeyframeModelsToImplThread( KeyframeModel::RunState initial_run_state = KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY; std::unique_ptr<KeyframeModel> to_add( - keyframe_model->CloneAndInitialize(initial_run_state)); + keyframe_model->CreateImplInstance(initial_run_state)); DCHECK(!to_add->needs_synchronized_start_time()); to_add->set_affects_active_elements(false); keyframe_effect_impl->AddKeyframeModel(std::move(to_add)); diff --git a/chromium/cc/animation/keyframe_effect.h b/chromium/cc/animation/keyframe_effect.h index 8db169e783b..4ee5176e517 100644 --- a/chromium/cc/animation/keyframe_effect.h +++ b/chromium/cc/animation/keyframe_effect.h @@ -41,12 +41,6 @@ typedef size_t KeyframeEffectId; // given target. class CC_ANIMATION_EXPORT KeyframeEffect { public: - class AnimationTimeProvider { - public: - virtual base::TimeTicks GetTimeForKeyframeModel( - const KeyframeModel&) const = 0; - }; - explicit KeyframeEffect(KeyframeEffectId id); ~KeyframeEffect(); @@ -87,8 +81,7 @@ class CC_ANIMATION_EXPORT KeyframeEffect { void AttachElement(ElementId element_id); void DetachElement(); - void Tick(base::TimeTicks monotonic_time, - const AnimationTimeProvider* tick_provider); + void Tick(base::TimeTicks monotonic_time); static void TickKeyframeModel(base::TimeTicks monotonic_time, KeyframeModel* keyframe_model, AnimationTarget* target); @@ -98,6 +91,8 @@ class CC_ANIMATION_EXPORT KeyframeEffect { void UpdateState(bool start_ready_keyframe_models, AnimationEvents* events); void UpdateTickingState(UpdateTickingType type); + void Pause(base::TimeDelta pause_offset); + void AddKeyframeModel(std::unique_ptr<KeyframeModel> keyframe_model); void PauseKeyframeModel(int keyframe_model_id, double time_offset); void RemoveKeyframeModel(int keyframe_model_id); diff --git a/chromium/cc/animation/keyframe_model.cc b/chromium/cc/animation/keyframe_model.cc index 3597a967501..d8495a62ff1 100644 --- a/chromium/cc/animation/keyframe_model.cc +++ b/chromium/cc/animation/keyframe_model.cc @@ -54,6 +54,28 @@ std::unique_ptr<KeyframeModel> KeyframeModel::Create( group_id, target_property_id)); } +std::unique_ptr<KeyframeModel> KeyframeModel::CreateImplInstance( + RunState initial_run_state) const { + // Should never clone a model that is the controlling instance as it ends up + // creating multiple controlling instances. + DCHECK(!is_controlling_instance_); + std::unique_ptr<KeyframeModel> to_return( + new KeyframeModel(curve_->Clone(), id_, group_, target_property_id_)); + to_return->run_state_ = initial_run_state; + to_return->iterations_ = iterations_; + to_return->iteration_start_ = iteration_start_; + to_return->start_time_ = start_time_; + to_return->pause_time_ = pause_time_; + to_return->total_paused_time_ = total_paused_time_; + to_return->time_offset_ = time_offset_; + to_return->direction_ = direction_; + to_return->playback_rate_ = playback_rate_; + to_return->fill_mode_ = fill_mode_; + DCHECK(!to_return->is_controlling_instance_); + to_return->is_controlling_instance_ = true; + return to_return; +} + KeyframeModel::KeyframeModel(std::unique_ptr<AnimationCurve> curve, int keyframe_model_id, int group_id, @@ -70,7 +92,6 @@ KeyframeModel::KeyframeModel(std::unique_ptr<AnimationCurve> curve, fill_mode_(FillMode::BOTH), needs_synchronized_start_time_(false), received_finished_event_(false), - suspended_(false), is_controlling_instance_(false), is_impl_only_(false), affects_active_elements_(true), @@ -83,9 +104,6 @@ KeyframeModel::~KeyframeModel() { void KeyframeModel::SetRunState(RunState run_state, base::TimeTicks monotonic_time) { - if (suspended_) - return; - char name_buffer[256]; base::snprintf(name_buffer, sizeof(name_buffer), "%s-%d-%d", s_curveTypeNames[curve_->Type()], target_property_id_, group_); @@ -122,16 +140,6 @@ void KeyframeModel::SetRunState(RunState run_state, TRACE_STR_COPY(name_buffer), "State", TRACE_STR_COPY(state_buffer)); } -void KeyframeModel::Suspend(base::TimeTicks monotonic_time) { - SetRunState(PAUSED, monotonic_time); - suspended_ = true; -} - -void KeyframeModel::Resume(base::TimeTicks monotonic_time) { - suspended_ = false; - SetRunState(RUNNING, monotonic_time); -} - bool KeyframeModel::IsFinishedAt(base::TimeTicks monotonic_time) const { if (is_finished()) return true; @@ -152,21 +160,6 @@ bool KeyframeModel::InEffect(base::TimeTicks monotonic_time) const { (fill_mode_ == FillMode::BOTH || fill_mode_ == FillMode::BACKWARDS); } -base::TimeTicks KeyframeModel::ConvertFromActiveTime( - base::TimeDelta active_time) const { - // When waiting on receiving a start time, then our global clock is 'stuck' at - // the initial state. - if ((run_state_ == STARTING && !has_set_start_time()) || - needs_synchronized_start_time()) - return base::TimeTicks(); - - // If we're paused, time is 'stuck' at the pause time. - if (run_state_ == PAUSED) - return pause_time_ - time_offset_; - - return active_time - time_offset_ + start_time_ + total_paused_time_; -} - base::TimeDelta KeyframeModel::ConvertToActiveTime( base::TimeTicks monotonic_time) const { // If we're just starting or we're waiting on receiving a start time, @@ -254,28 +247,6 @@ base::TimeDelta KeyframeModel::TrimTimeToCurrentIteration( return iteration_time; } -std::unique_ptr<KeyframeModel> KeyframeModel::CloneAndInitialize( - RunState initial_run_state) const { - // Should never clone a model that is the controlling instance as it ends up - // creating multiple controlling instances. - DCHECK(!is_controlling_instance_); - std::unique_ptr<KeyframeModel> to_return( - new KeyframeModel(curve_->Clone(), id_, group_, target_property_id_)); - to_return->run_state_ = initial_run_state; - to_return->iterations_ = iterations_; - to_return->iteration_start_ = iteration_start_; - to_return->start_time_ = start_time_; - to_return->pause_time_ = pause_time_; - to_return->total_paused_time_ = total_paused_time_; - to_return->time_offset_ = time_offset_; - to_return->direction_ = direction_; - to_return->playback_rate_ = playback_rate_; - to_return->fill_mode_ = fill_mode_; - DCHECK(!to_return->is_controlling_instance_); - to_return->is_controlling_instance_ = true; - return to_return; -} - void KeyframeModel::PushPropertiesTo(KeyframeModel* other) const { // Currently, we only push changes due to pausing and resuming KeyframeModels // on the main thread. diff --git a/chromium/cc/animation/keyframe_model.h b/chromium/cc/animation/keyframe_model.h index 517d8bed557..9d770995dd8 100644 --- a/chromium/cc/animation/keyframe_model.h +++ b/chromium/cc/animation/keyframe_model.h @@ -60,6 +60,9 @@ class CC_ANIMATION_EXPORT KeyframeModel { int group_id, int target_property_id); + std::unique_ptr<KeyframeModel> CreateImplInstance( + RunState initial_run_state) const; + virtual ~KeyframeModel(); int id() const { return id_; } @@ -92,9 +95,6 @@ class CC_ANIMATION_EXPORT KeyframeModel { time_offset_ = monotonic_time; } - void Suspend(base::TimeTicks monotonic_time); - void Resume(base::TimeTicks monotonic_time); - Direction direction() { return direction_; } void set_direction(Direction direction) { direction_ = direction; } @@ -140,11 +140,6 @@ class CC_ANIMATION_EXPORT KeyframeModel { base::TimeDelta TrimTimeToCurrentIteration( base::TimeTicks monotonic_time) const; - base::TimeTicks ConvertFromActiveTime(base::TimeDelta active_time) const; - - std::unique_ptr<KeyframeModel> CloneAndInitialize( - RunState initial_run_state) const; - void set_is_controlling_instance_for_test(bool is_controlling_instance) { is_controlling_instance_ = is_controlling_instance; } @@ -204,11 +199,6 @@ class CC_ANIMATION_EXPORT KeyframeModel { bool needs_synchronized_start_time_; bool received_finished_event_; - // When a keyframe model is suspended, it behaves as if it is paused and it - // also ignores all run state changes until it is resumed. This is used for - // testing purposes. - bool suspended_; - // These are used in TrimTimeToCurrentIteration to account for time // spent while paused. This is not included in AnimationState since it // there is absolutely no need for clients of this controller to know diff --git a/chromium/cc/animation/keyframe_model_unittest.cc b/chromium/cc/animation/keyframe_model_unittest.cc index ac13921648b..3757df9ee9f 100644 --- a/chromium/cc/animation/keyframe_model_unittest.cc +++ b/chromium/cc/animation/keyframe_model_unittest.cc @@ -488,51 +488,6 @@ TEST(KeyframeModelTest, TrimTimePauseResumeReverse) { .InSecondsF()); } -TEST(KeyframeModelTest, TrimTimeSuspendResume) { - std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); - keyframe_model->SetRunState(KeyframeModel::RUNNING, TicksFromSecondsF(0.0)); - EXPECT_EQ(0, - keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.0)) - .InSecondsF()); - EXPECT_EQ(0.5, - keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.5)) - .InSecondsF()); - keyframe_model->Suspend(TicksFromSecondsF(0.5)); - EXPECT_EQ( - 0.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.0)) - .InSecondsF()); - keyframe_model->Resume(TicksFromSecondsF(1024)); - EXPECT_EQ( - 0.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.0)) - .InSecondsF()); - EXPECT_EQ( - 1, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.5)) - .InSecondsF()); -} - -TEST(KeyframeModelTest, TrimTimeSuspendResumeReverse) { - std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); - keyframe_model->set_direction(KeyframeModel::Direction::REVERSE); - keyframe_model->SetRunState(KeyframeModel::RUNNING, TicksFromSecondsF(0.0)); - EXPECT_EQ(1.0, - keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.0)) - .InSecondsF()); - EXPECT_EQ(0.75, - keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.25)) - .InSecondsF()); - keyframe_model->Suspend(TicksFromSecondsF(0.75)); - EXPECT_EQ(0.25, keyframe_model - ->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.0)) - .InSecondsF()); - keyframe_model->Resume(TicksFromSecondsF(1024)); - EXPECT_EQ(0.25, keyframe_model - ->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.0)) - .InSecondsF()); - EXPECT_EQ( - 0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.25)) - .InSecondsF()); -} - TEST(KeyframeModelTest, TrimTimeZeroDuration) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(0, 0)); keyframe_model->SetRunState(KeyframeModel::RUNNING, TicksFromSecondsF(0.0)); @@ -716,17 +671,6 @@ TEST(KeyframeModelTest, IsFinishedNeedsSynchronizedStartTime) { EXPECT_TRUE(keyframe_model->is_finished()); } -TEST(KeyframeModelTest, RunStateChangesIgnoredWhileSuspended) { - std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); - keyframe_model->Suspend(TicksFromSecondsF(0)); - EXPECT_EQ(KeyframeModel::PAUSED, keyframe_model->run_state()); - keyframe_model->SetRunState(KeyframeModel::RUNNING, TicksFromSecondsF(0.0)); - EXPECT_EQ(KeyframeModel::PAUSED, keyframe_model->run_state()); - keyframe_model->Resume(TicksFromSecondsF(0)); - keyframe_model->SetRunState(KeyframeModel::RUNNING, TicksFromSecondsF(0.0)); - EXPECT_EQ(KeyframeModel::RUNNING, keyframe_model->run_state()); -} - TEST(KeyframeModelTest, TrimTimePlaybackNormal) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1, 1, 1)); EXPECT_EQ(0, diff --git a/chromium/cc/animation/keyframed_animation_curve.cc b/chromium/cc/animation/keyframed_animation_curve.cc index 89f088a8dc4..ed44328d053 100644 --- a/chromium/cc/animation/keyframed_animation_curve.cc +++ b/chromium/cc/animation/keyframed_animation_curve.cc @@ -381,28 +381,6 @@ TransformOperations KeyframedTransformAnimationCurve::GetValue( return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress); } -bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox( - const gfx::BoxF& box, - gfx::BoxF* bounds) const { - DCHECK_GE(keyframes_.size(), 2ul); - *bounds = gfx::BoxF(); - for (size_t i = 0; i < keyframes_.size() - 1; ++i) { - gfx::BoxF bounds_for_step; - float min_progress = 0.0; - float max_progress = 1.0; - if (keyframes_[i]->timing_function()) - keyframes_[i]->timing_function()->Range(&min_progress, &max_progress); - if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box, - keyframes_[i]->Value(), - min_progress, - max_progress, - &bounds_for_step)) - return false; - bounds->Union(bounds_for_step); - } - return true; -} - bool KeyframedTransformAnimationCurve::PreservesAxisAlignment() const { for (const auto& keyframe : keyframes_) { if (!keyframe->Value().PreservesAxisAlignment()) diff --git a/chromium/cc/animation/keyframed_animation_curve.h b/chromium/cc/animation/keyframed_animation_curve.h index 037805603d1..582a26c2f6c 100644 --- a/chromium/cc/animation/keyframed_animation_curve.h +++ b/chromium/cc/animation/keyframed_animation_curve.h @@ -238,8 +238,6 @@ class CC_ANIMATION_EXPORT KeyframedTransformAnimationCurve // TransformAnimationCurve implementation TransformOperations GetValue(base::TimeDelta t) const override; - bool AnimatedBoundsForBox(const gfx::BoxF& box, - gfx::BoxF* bounds) const override; bool PreservesAxisAlignment() const override; bool IsTranslation() const override; bool AnimationStartScale(bool forward_direction, diff --git a/chromium/cc/animation/keyframed_animation_curve_unittest.cc b/chromium/cc/animation/keyframed_animation_curve_unittest.cc index 7a13c743e4e..b71f127780f 100644 --- a/chromium/cc/animation/keyframed_animation_curve_unittest.cc +++ b/chromium/cc/animation/keyframed_animation_curve_unittest.cc @@ -658,32 +658,6 @@ TEST(KeyframedAnimationCurveTest, FramesTimingFunction) { } } -// Tests that animated bounds are computed as expected. -TEST(KeyframedAnimationCurveTest, AnimatedBounds) { - std::unique_ptr<KeyframedTransformAnimationCurve> curve( - KeyframedTransformAnimationCurve::Create()); - - TransformOperations operations1; - curve->AddKeyframe( - TransformKeyframe::Create(base::TimeDelta(), operations1, nullptr)); - operations1.AppendTranslate(2.0, 3.0, -1.0); - curve->AddKeyframe(TransformKeyframe::Create( - base::TimeDelta::FromSecondsD(0.5f), operations1, nullptr)); - TransformOperations operations2; - operations2.AppendTranslate(4.0, 1.0, 2.0); - curve->AddKeyframe(TransformKeyframe::Create( - base::TimeDelta::FromSecondsD(1.f), operations2, - CubicBezierTimingFunction::CreatePreset( - CubicBezierTimingFunction::EaseType::EASE))); - - gfx::BoxF box(2.f, 3.f, 4.f, 1.f, 3.f, 2.f); - gfx::BoxF bounds; - - EXPECT_TRUE(curve->AnimatedBoundsForBox(box, &bounds)); - EXPECT_EQ(gfx::BoxF(2.f, 3.f, 3.f, 5.f, 6.f, 5.f).ToString(), - bounds.ToString()); -} - // Tests that animations that are translations are correctly identified. TEST(KeyframedAnimationCurveTest, IsTranslation) { std::unique_ptr<KeyframedTransformAnimationCurve> curve( diff --git a/chromium/cc/animation/timing_function.cc b/chromium/cc/animation/timing_function.cc index e3df8deb03a..ad73588c6e4 100644 --- a/chromium/cc/animation/timing_function.cc +++ b/chromium/cc/animation/timing_function.cc @@ -65,11 +65,6 @@ float CubicBezierTimingFunction::Velocity(double x) const { return static_cast<float>(bezier_.Slope(x)); } -void CubicBezierTimingFunction::Range(float* min, float* max) const { - *min = static_cast<float>(bezier_.range_min()); - *max = static_cast<float>(bezier_.range_max()); -} - std::unique_ptr<TimingFunction> CubicBezierTimingFunction::Clone() const { return base::WrapUnique(new CubicBezierTimingFunction(*this)); } @@ -97,11 +92,6 @@ std::unique_ptr<TimingFunction> StepsTimingFunction::Clone() const { return base::WrapUnique(new StepsTimingFunction(*this)); } -void StepsTimingFunction::Range(float* min, float* max) const { - *min = 0.0f; - *max = 1.0f; -} - float StepsTimingFunction::Velocity(double x) const { return 0.0f; } @@ -150,11 +140,6 @@ std::unique_ptr<TimingFunction> FramesTimingFunction::Clone() const { return base::WrapUnique(new FramesTimingFunction(*this)); } -void FramesTimingFunction::Range(float* min, float* max) const { - *min = 0.0f; - *max = 1.0f; -} - float FramesTimingFunction::Velocity(double x) const { return 0.0f; } diff --git a/chromium/cc/animation/timing_function.h b/chromium/cc/animation/timing_function.h index 5ff8d3561bd..32bbf95fe56 100644 --- a/chromium/cc/animation/timing_function.h +++ b/chromium/cc/animation/timing_function.h @@ -24,8 +24,6 @@ class CC_ANIMATION_EXPORT TimingFunction { virtual Type GetType() const = 0; virtual float GetValue(double t) const = 0; virtual float Velocity(double time) const = 0; - // The smallest and largest values returned by GetValue for inputs in [0, 1]. - virtual void Range(float* min, float* max) const = 0; virtual std::unique_ptr<TimingFunction> Clone() const = 0; protected: @@ -50,7 +48,6 @@ class CC_ANIMATION_EXPORT CubicBezierTimingFunction : public TimingFunction { Type GetType() const override; float GetValue(double time) const override; float Velocity(double time) const override; - void Range(float* min, float* max) const override; std::unique_ptr<TimingFunction> Clone() const override; EaseType ease_type() const { return ease_type_; } @@ -83,7 +80,6 @@ class CC_ANIMATION_EXPORT StepsTimingFunction : public TimingFunction { Type GetType() const override; float GetValue(double t) const override; std::unique_ptr<TimingFunction> Clone() const override; - void Range(float* min, float* max) const override; float Velocity(double time) const override; int steps() const { return steps_; } @@ -110,7 +106,6 @@ class CC_ANIMATION_EXPORT FramesTimingFunction : public TimingFunction { Type GetType() const override; float GetValue(double t) const override; std::unique_ptr<TimingFunction> Clone() const override; - void Range(float* min, float* max) const override; float Velocity(double time) const override; int frames() const { return frames_; } diff --git a/chromium/cc/animation/worklet_animation.cc b/chromium/cc/animation/worklet_animation.cc index 5db8231c413..a905b94ce12 100644 --- a/chromium/cc/animation/worklet_animation.cc +++ b/chromium/cc/animation/worklet_animation.cc @@ -11,11 +11,13 @@ namespace cc { WorkletAnimation::WorkletAnimation( int id, const std::string& name, - std::unique_ptr<ScrollTimeline> scroll_timeline) + std::unique_ptr<ScrollTimeline> scroll_timeline, + bool is_controlling_instance) : SingleKeyframeEffectAnimation(id), name_(name), scroll_timeline_(std::move(scroll_timeline)), - last_current_time_(base::nullopt) {} + last_current_time_(base::nullopt), + is_impl_instance_(is_controlling_instance) {} WorkletAnimation::~WorkletAnimation() = default; @@ -24,7 +26,7 @@ scoped_refptr<WorkletAnimation> WorkletAnimation::Create( const std::string& name, std::unique_ptr<ScrollTimeline> scroll_timeline) { return WrapRefCounted( - new WorkletAnimation(id, name, std::move(scroll_timeline))); + new WorkletAnimation(id, name, std::move(scroll_timeline), false)); } scoped_refptr<Animation> WorkletAnimation::CreateImplInstance() const { @@ -33,7 +35,7 @@ scoped_refptr<Animation> WorkletAnimation::CreateImplInstance() const { impl_timeline = scroll_timeline_->CreateImplInstance(); return WrapRefCounted( - new WorkletAnimation(id(), name(), std::move(impl_timeline))); + new WorkletAnimation(id(), name(), std::move(impl_timeline), true)); } void WorkletAnimation::SetLocalTime(base::TimeDelta local_time) { @@ -42,7 +44,17 @@ void WorkletAnimation::SetLocalTime(base::TimeDelta local_time) { } void WorkletAnimation::Tick(base::TimeTicks monotonic_time) { - keyframe_effect()->Tick(monotonic_time, this); + // Do not tick worklet animations on main thread. This should be removed if we + // skip ticking all animations on main thread in http://crbug.com/762717. + if (!is_impl_instance_) + return; + // As the output of a WorkletAnimation is driven by a script-provided local + // time, we don't want the underlying effect to participate in the normal + // animations lifecycle. To avoid this we pause the underlying keyframe effect + // at the local time obtained from the user script - essentially turning each + // call to |WorkletAnimation::Tick| into a seek in the effect. + keyframe_effect()->Pause(local_time_); + keyframe_effect()->Tick(monotonic_time); } // TODO(crbug.com/780151): The current time returned should be an offset against @@ -66,18 +78,6 @@ bool WorkletAnimation::NeedsUpdate(base::TimeTicks monotonic_time, return needs_update; } -base::TimeTicks WorkletAnimation::GetTimeForKeyframeModel( - const KeyframeModel& keyframe_model) const { - // Animation local time is equivalent to animation active time. So we have to - // convert it from active time to monotonic time. - return keyframe_model.ConvertFromActiveTime(local_time_); -} - -void WorkletAnimation::PushPropertiesTo(Animation* animation_impl) { - SingleKeyframeEffectAnimation::PushPropertiesTo(animation_impl); - static_cast<WorkletAnimation*>(animation_impl)->SetLocalTime(local_time_); -} - bool WorkletAnimation::IsWorkletAnimation() const { return true; } diff --git a/chromium/cc/animation/worklet_animation.h b/chromium/cc/animation/worklet_animation.h index 27371100efc..cdde572fd28 100644 --- a/chromium/cc/animation/worklet_animation.h +++ b/chromium/cc/animation/worklet_animation.h @@ -19,12 +19,12 @@ class ScrollTimeline; // timing to be controlled by an animator instance that is running in a // AnimationWorkletGlobalScope. class CC_ANIMATION_EXPORT WorkletAnimation final - : public SingleKeyframeEffectAnimation, - KeyframeEffect::AnimationTimeProvider { + : public SingleKeyframeEffectAnimation { public: WorkletAnimation(int id, const std::string& name, - std::unique_ptr<ScrollTimeline> scroll_timeline); + std::unique_ptr<ScrollTimeline> scroll_timeline, + bool is_controlling_instance); static scoped_refptr<WorkletAnimation> Create( int id, const std::string& name, @@ -51,12 +51,6 @@ class CC_ANIMATION_EXPORT WorkletAnimation final bool NeedsUpdate(base::TimeTicks monotonic_time, const ScrollTree& scroll_tree); - // KeyframeEffect::AnimationTimeProvider: - base::TimeTicks GetTimeForKeyframeModel( - const KeyframeModel& keyframe_model) const override; - - void PushPropertiesTo(Animation* animation_impl) override; - private: ~WorkletAnimation() override; @@ -73,6 +67,8 @@ class CC_ANIMATION_EXPORT WorkletAnimation final base::TimeDelta local_time_; base::Optional<double> last_current_time_; + + bool is_impl_instance_; }; } // namespace cc diff --git a/chromium/cc/animation/worklet_animation_player_unittest.cc b/chromium/cc/animation/worklet_animation_player_unittest.cc deleted file mode 100644 index d77e0a7bb5d..00000000000 --- a/chromium/cc/animation/worklet_animation_player_unittest.cc +++ /dev/null @@ -1,135 +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. - -#include "cc/animation/worklet_animation_player.h" - -#include "cc/animation/scroll_timeline.h" -#include "cc/test/animation_test_common.h" -#include "cc/test/animation_timelines_test_common.h" -#include "cc/test/mock_layer_tree_mutator.h" -#include "cc/trees/property_tree.h" -#include "testing/gmock/include/gmock/gmock.h" - -using ::testing::Mock; -using ::testing::Return; -using ::testing::_; - -namespace cc { - -namespace { - -class WorkletAnimationPlayerTest : public AnimationTimelinesTest { - public: - WorkletAnimationPlayerTest() = default; - ~WorkletAnimationPlayerTest() override = default; - - int worklet_player_id_ = 11; -}; - -class MockScrollTimeline : public ScrollTimeline { - public: - MockScrollTimeline() - : ScrollTimeline(ElementId(), ScrollTimeline::Vertical, 0) {} - MOCK_CONST_METHOD1(CurrentTime, double(const ScrollTree&)); -}; - -TEST_F(WorkletAnimationPlayerTest, LocalTimeIsUsedWithAnimations) { - client_.RegisterElement(element_id_, ElementListType::ACTIVE); - client_impl_.RegisterElement(element_id_, ElementListType::PENDING); - client_impl_.RegisterElement(element_id_, ElementListType::ACTIVE); - - const float start_opacity = .7f; - const float end_opacity = .3f; - const double duration = 1.; - - const float expected_opacity = - start_opacity + (end_opacity - start_opacity) / 2; - - scoped_refptr<WorkletAnimationPlayer> worklet_player_ = - WorkletAnimationPlayer::Create(worklet_player_id_, "test_name", nullptr); - - worklet_player_->AttachElement(element_id_); - host_->AddAnimationTimeline(timeline_); - timeline_->AttachPlayer(worklet_player_); - - AddOpacityTransitionToPlayer(worklet_player_.get(), duration, start_opacity, - end_opacity, true); - - host_->PushPropertiesTo(host_impl_); - host_impl_->ActivateAnimations(); - - // TODO(majidvp): At the moment the player does not use the local time when - // it is starting. This is because KeyframeModel::ConvertToActiveTime always - // returns the time_offset when starting. We need to change this. - base::TimeTicks time; - time += base::TimeDelta::FromSecondsD(0.1); - TickAnimationsTransferEvents(time, 1u); - - base::TimeDelta local_time = base::TimeDelta::FromSecondsD(duration / 2); - worklet_player_->SetLocalTime(local_time); - - host_->PushPropertiesTo(host_impl_); - - TickAnimationsTransferEvents(time, 0u); - - client_.ExpectOpacityPropertyMutated(element_id_, ElementListType::ACTIVE, - expected_opacity); - - client_impl_.ExpectOpacityPropertyMutated( - element_id_, ElementListType::ACTIVE, expected_opacity); -} - -// Tests that verify interaction of AnimationHost with LayerTreeMutator. -// TODO(majidvp): Perhaps moves these to AnimationHostTest. -TEST_F(WorkletAnimationPlayerTest, - LayerTreeMutatorsIsMutatedWithCorrectInputState) { - MockLayerTreeMutator* mock_mutator = new MockLayerTreeMutator(); - host_impl_->SetLayerTreeMutator( - base::WrapUnique<LayerTreeMutator>(mock_mutator)); - - client_.RegisterElement(element_id_, ElementListType::ACTIVE); - client_impl_.RegisterElement(element_id_, ElementListType::PENDING); - client_impl_.RegisterElement(element_id_, ElementListType::ACTIVE); - - const float start_opacity = .7f; - const float end_opacity = .3f; - const double duration = 1.; - - scoped_refptr<WorkletAnimationPlayer> worklet_player_ = - WorkletAnimationPlayer::Create(worklet_player_id_, "test_name", nullptr); - - worklet_player_->AttachElement(element_id_); - host_->AddAnimationTimeline(timeline_); - timeline_->AttachPlayer(worklet_player_); - - AddOpacityTransitionToPlayer(worklet_player_.get(), duration, start_opacity, - end_opacity, true); - - host_->PushPropertiesTo(host_impl_); - host_impl_->ActivateAnimations(); - - EXPECT_CALL(*mock_mutator, MutateRef(_)); - - base::TimeTicks time; - time += base::TimeDelta::FromSecondsD(0.1); - TickAnimationsTransferEvents(time, 1u); - - Mock::VerifyAndClearExpectations(mock_mutator); -} - -TEST_F(WorkletAnimationPlayerTest, CurrentTimeCorrectlyUsesScrolltimeline) { - auto scroll_timeline = std::make_unique<MockScrollTimeline>(); - EXPECT_CALL(*scroll_timeline, CurrentTime(_)).WillOnce(Return(1234)); - scoped_refptr<WorkletAnimationPlayer> worklet_player = - WorkletAnimationPlayer::Create(worklet_player_id_, "test_name", - std::move(scroll_timeline)); - - ScrollTree scroll_tree; - EXPECT_EQ(1234, - worklet_player->CurrentTime(base::TimeTicks::Now(), scroll_tree)); -} - -} // namespace - -} // namespace cc diff --git a/chromium/cc/animation/worklet_animation_unittest.cc b/chromium/cc/animation/worklet_animation_unittest.cc index ef89d6fb11f..5e3020b75e9 100644 --- a/chromium/cc/animation/worklet_animation_unittest.cc +++ b/chromium/cc/animation/worklet_animation_unittest.cc @@ -36,9 +36,15 @@ class WorkletAnimationTest : public AnimationTimelinesTest { worklet_animation_->AttachElement(element_id_); host_->AddAnimationTimeline(timeline_); timeline_->AttachAnimation(worklet_animation_); + + host_->PushPropertiesTo(host_impl_); + timeline_impl_ = host_impl_->GetTimelineById(timeline_id_); + worklet_animation_impl_ = static_cast<WorkletAnimation*>( + timeline_impl_->GetAnimationById(worklet_animation_id_)); } scoped_refptr<WorkletAnimation> worklet_animation_; + scoped_refptr<WorkletAnimation> worklet_animation_impl_; int worklet_animation_id_ = 11; }; @@ -61,26 +67,18 @@ TEST_F(WorkletAnimationTest, LocalTimeIsUsedWithAnimations) { AddOpacityTransitionToAnimation(worklet_animation_.get(), duration, start_opacity, end_opacity, true); + // Push the opacity animation to the impl thread. host_->PushPropertiesTo(host_impl_); host_impl_->ActivateAnimations(); - // TODO(majidvp): At the moment the animation does not use the local time when - // it is starting. This is because KeyframeModel::ConvertToActiveTime always - // returns the time_offset when starting. We need to change this. - base::TimeTicks time; - time += base::TimeDelta::FromSecondsD(0.1); - TickAnimationsTransferEvents(time, 1u); - base::TimeDelta local_time = base::TimeDelta::FromSecondsD(duration / 2); - worklet_animation_->SetLocalTime(local_time); - - host_->PushPropertiesTo(host_impl_); - - TickAnimationsTransferEvents(time, 0u); + worklet_animation_impl_->SetLocalTime(local_time); - client_.ExpectOpacityPropertyMutated(element_id_, ElementListType::ACTIVE, - expected_opacity); + TickAnimationsTransferEvents(base::TimeTicks(), 0u); + TestLayer* layer = + client_.FindTestLayer(element_id_, ElementListType::ACTIVE); + EXPECT_FALSE(layer->is_property_mutated(TargetProperty::OPACITY)); client_impl_.ExpectOpacityPropertyMutated( element_id_, ElementListType::ACTIVE, expected_opacity); } @@ -109,7 +107,7 @@ TEST_F(WorkletAnimationTest, LayerTreeMutatorsIsMutatedWithCorrectInputState) { base::TimeTicks time; time += base::TimeDelta::FromSecondsD(0.1); - TickAnimationsTransferEvents(time, 1u); + TickAnimationsTransferEvents(time, 0u); Mock::VerifyAndClearExpectations(mock_mutator); } @@ -136,7 +134,7 @@ TEST_F(WorkletAnimationTest, LayerTreeMutatorsIsMutatedOnlyWhenInputChanges) { base::TimeTicks time; time += base::TimeDelta::FromSecondsD(0.1); - TickAnimationsTransferEvents(time, 1u); + TickAnimationsTransferEvents(time, 0u); // The time has not changed which means worklet animation input is the same. // Ticking animations again should not result in mutator being asked to diff --git a/chromium/cc/base/list_container.h b/chromium/cc/base/list_container.h index bafee7970ce..81235e1bc0a 100644 --- a/chromium/cc/base/list_container.h +++ b/chromium/cc/base/list_container.h @@ -146,22 +146,6 @@ class ListContainer { helper_.data_.swap(other.helper_.data_); } - // Appends a new item without copying. The original item will not be - // destructed and will be replaced with a new DerivedElementType. The - // DerivedElementType does not have to match the moved type as a full block - // of memory will be moved (up to MaxSizeForDerivedClass()). A pointer to - // the moved element is returned. - template <typename DerivedElementType> - DerivedElementType* AppendByMoving(DerivedElementType* item) { - size_t max_size_for_derived_class = helper_.MaxSizeForDerivedClass(); - void* new_item = helper_.Allocate(alignof(DerivedElementType), - max_size_for_derived_class); - memcpy(new_item, static_cast<void*>(item), max_size_for_derived_class); - // Construct a new element in-place so it can be destructed safely. - new (item) DerivedElementType; - return static_cast<DerivedElementType*>(new_item); - } - size_t size() const { return helper_.size(); } bool empty() const { return helper_.empty(); } size_t GetCapacityInBytes() const { return helper_.GetCapacityInBytes(); } diff --git a/chromium/cc/base/list_container_unittest.cc b/chromium/cc/base/list_container_unittest.cc index f0c5a24849f..e46be3bf875 100644 --- a/chromium/cc/base/list_container_unittest.cc +++ b/chromium/cc/base/list_container_unittest.cc @@ -8,7 +8,6 @@ #include <algorithm> #include <vector> -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -103,6 +102,7 @@ class SimpleDerivedElementConstructMagicNumberOne SimpleDerivedElementConstructMagicNumberOne() { set_value(kMagicNumberToUseForSimpleDerivedElementOne); } + ~SimpleDerivedElementConstructMagicNumberOne() override = default; }; class SimpleDerivedElementConstructMagicNumberTwo @@ -111,6 +111,7 @@ class SimpleDerivedElementConstructMagicNumberTwo SimpleDerivedElementConstructMagicNumberTwo() { set_value(kMagicNumberToUseForSimpleDerivedElementTwo); } + ~SimpleDerivedElementConstructMagicNumberTwo() override = default; }; class SimpleDerivedElementConstructMagicNumberThree @@ -119,12 +120,40 @@ class SimpleDerivedElementConstructMagicNumberThree SimpleDerivedElementConstructMagicNumberThree() { set_value(kMagicNumberToUseForSimpleDerivedElementThree); } + ~SimpleDerivedElementConstructMagicNumberThree() override = default; }; +// This class' instances are moved by ListContainer via memcpy(). This behavior +// is not supported by gmock's FunctionMocker, so this class must roll its own +// mocking code. class MockDerivedElement : public SimpleDerivedElementConstructMagicNumberOne { public: - ~MockDerivedElement() override { Destruct(); } - MOCK_METHOD0(Destruct, void()); + ~MockDerivedElement() override { + DestructorCalled(); + CheckDestructExpectation(); + } + + void SetExpectedDestructorCalls(size_t expected_calls) { + expected_destructor_calls_ = expected_calls; + has_expected_destructor_calls_ = true; + } + + private: + void DestructorCalled() { ++destructor_calls_; } + + void CheckDestructExpectation() { + if (!has_expected_destructor_calls_) + return; + EXPECT_EQ(expected_destructor_calls_, destructor_calls_) + << "element destructor called the wrong number of times"; + } + + // Not using base::Optional<size_t> here in order to get a precise destructor + // behavior. The tests below need the ability to catch multiple destructor + // calls, and base::Optional's destructor might make has_value() return false. + size_t expected_destructor_calls_; + bool has_expected_destructor_calls_ = false; + size_t destructor_calls_ = 0; }; class MockDerivedElementSubclass : public MockDerivedElement { @@ -164,7 +193,7 @@ TEST(ListContainerTest, DestructorCalled) { size_t size = 1; MockDerivedElement* de_1 = list.AllocateAndConstruct<MockDerivedElement>(); - EXPECT_CALL(*de_1, Destruct()); + de_1->SetExpectedDestructorCalls(1); EXPECT_EQ(size, list.size()); EXPECT_EQ(de_1, list.front()); } @@ -178,18 +207,10 @@ TEST(ListContainerTest, DestructorCalledOnceWhenClear) { EXPECT_EQ(size, list.size()); EXPECT_EQ(de_1, list.front()); - // Make sure destructor is called once during clear, and won't be called - // again. - testing::MockFunction<void()> separator; - { - testing::InSequence s; - EXPECT_CALL(*de_1, Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(*de_1, Destruct()).Times(0); - } + // Make sure destructor is called exactly once during clear. + de_1->SetExpectedDestructorCalls(1); list.clear(); - separator.Call(); } TEST(ListContainerTest, ClearDoesNotMalloc) { @@ -235,21 +256,12 @@ TEST(ListContainerTest, ReplaceExistingElement) { EXPECT_EQ(size, list.size()); EXPECT_EQ(de_1, list.front()); - // Make sure destructor is called once during clear, and won't be called - // again. - testing::MockFunction<void()> separator; - { - testing::InSequence s; - EXPECT_CALL(*de_1, Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(*de_1, Destruct()).Times(0); - } + // Make sure destructor is called exactly once during clear. + de_1->SetExpectedDestructorCalls(1); list.ReplaceExistingElement<MockDerivedElementSubclass>(list.begin()); EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, de_1->get_value()); - separator.Call(); - EXPECT_CALL(*de_1, Destruct()); list.clear(); } @@ -262,18 +274,10 @@ TEST(ListContainerTest, DestructorCalledOnceWhenErase) { EXPECT_EQ(size, list.size()); EXPECT_EQ(de_1, list.front()); - // Make sure destructor is called once during clear, and won't be called - // again. - testing::MockFunction<void()> separator; - { - testing::InSequence s; - EXPECT_CALL(*de_1, Destruct()); - EXPECT_CALL(separator, Call()); - EXPECT_CALL(*de_1, Destruct()).Times(0); - } + // Make sure destructor is called exactly once during clear. + de_1->SetExpectedDestructorCalls(1); list.EraseAndInvalidateAllPointers(list.begin()); - separator.Call(); } TEST(ListContainerTest, SimpleIndexAccessNonDerivedElement) { @@ -1021,158 +1025,6 @@ TEST(ListContainerTest, RemoveLastIteration) { check_equal(); // Empty. } -TEST(ListContainerTest, AppendByMovingSameList) { - ListContainer<SimpleDerivedElement> list( - kCurrentLargestDerivedElementAlign, kCurrentLargestDerivedElementSize, 0); - list.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberOne>(); - - list.AppendByMoving(list.front()); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, - list.back()->get_value()); - EXPECT_EQ(2u, list.size()); - - list.front()->set_value(kMagicNumberToUseForSimpleDerivedElementTwo); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, - list.front()->get_value()); - list.AppendByMoving(list.front()); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, - list.back()->get_value()); - EXPECT_EQ(3u, list.size()); -} - -TEST(ListContainerTest, AppendByMovingDoesNotDestruct) { - ListContainer<DerivedElement> list_1(kCurrentLargestDerivedElementAlign, - kCurrentLargestDerivedElementSize, 0); - ListContainer<DerivedElement> list_2(kCurrentLargestDerivedElementAlign, - kCurrentLargestDerivedElementSize, 0); - MockDerivedElement* mde_1 = list_1.AllocateAndConstruct<MockDerivedElement>(); - - // Make sure destructor isn't called during AppendByMoving. - list_2.AppendByMoving(mde_1); - EXPECT_CALL(*mde_1, Destruct()).Times(0); - testing::Mock::VerifyAndClearExpectations(mde_1); - mde_1 = static_cast<MockDerivedElement*>(list_2.back()); - EXPECT_CALL(*mde_1, Destruct()); -} - -TEST(ListContainerTest, AppendByMovingReturnsMovedPointer) { - ListContainer<SimpleDerivedElement> list_1( - kCurrentLargestDerivedElementAlign, kCurrentLargestDerivedElementSize, 0); - ListContainer<SimpleDerivedElement> list_2( - kCurrentLargestDerivedElementAlign, kCurrentLargestDerivedElementSize, 0); - SimpleDerivedElement* simple_element = - list_1.AllocateAndConstruct<SimpleDerivedElement>(); - - SimpleDerivedElement* moved_1 = list_2.AppendByMoving(simple_element); - EXPECT_EQ(list_2.back(), moved_1); - - SimpleDerivedElement* moved_2 = list_1.AppendByMoving(moved_1); - EXPECT_EQ(list_1.back(), moved_2); - EXPECT_NE(moved_1, moved_2); -} - -TEST(ListContainerTest, AppendByMovingReplacesSourceWithNewDerivedElement) { - ListContainer<SimpleDerivedElementConstructMagicNumberOne> list_1( - kCurrentLargestDerivedElementAlign, kCurrentLargestDerivedElementSize, 0); - ListContainer<SimpleDerivedElementConstructMagicNumberTwo> list_2( - kCurrentLargestDerivedElementAlign, kCurrentLargestDerivedElementSize, 0); - - list_1.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberOne>(); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, - list_1.front()->get_value()); - - list_2.AppendByMoving(list_1.front()); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, - list_1.front()->get_value()); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, - list_2.front()->get_value()); - - // Change the value of list_2.front() to ensure the value is actually moved. - list_2.back()->set_value(kMagicNumberToUseForSimpleDerivedElementThree); - - list_1.AppendByMoving(list_2.back()); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, - list_1.front()->get_value()); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementThree, - list_1.back()->get_value()); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, - list_2.back()->get_value()); - - // AppendByMoving replaces the source element with a new derived element so - // we do not expect sizes to shrink after AppendByMoving is called. - EXPECT_EQ(2u, list_1.size()); // One direct allocation, one AppendByMoving. - EXPECT_EQ(1u, list_2.size()); // One AppendByMoving. -} - -const size_t kLongCountForLongSimpleDerivedElement = 5; - -class LongSimpleDerivedElement : public SimpleDerivedElement { - public: - ~LongSimpleDerivedElement() override = default; - void SetAllValues(unsigned long value) { - for (size_t i = 0; i < kLongCountForLongSimpleDerivedElement; i++) - values[i] = value; - } - bool AreAllValuesEqualTo(size_t value) const { - for (size_t i = 1; i < kLongCountForLongSimpleDerivedElement; i++) { - if (values[i] != values[0]) - return false; - } - return true; - } - - private: - unsigned long values[kLongCountForLongSimpleDerivedElement]; -}; - -const unsigned long kMagicNumberToUseForLongSimpleDerivedElement = 2718ul; - -class LongSimpleDerivedElementConstructMagicNumber - : public LongSimpleDerivedElement { - public: - LongSimpleDerivedElementConstructMagicNumber() { - SetAllValues(kMagicNumberToUseForLongSimpleDerivedElement); - } -}; - -TEST(ListContainerTest, AppendByMovingLongAndSimpleDerivedElements) { - static_assert(sizeof(LongSimpleDerivedElement) > sizeof(SimpleDerivedElement), - "LongSimpleDerivedElement should be larger than " - "SimpleDerivedElement's size."); - static_assert(sizeof(LongSimpleDerivedElement) <= kLargestDerivedElementSize, - "LongSimpleDerivedElement should be smaller than the maximum " - "DerivedElement size."); - - ListContainer<SimpleDerivedElement> list( - kCurrentLargestDerivedElementAlign, kCurrentLargestDerivedElementSize, 0); - list.AllocateAndConstruct<LongSimpleDerivedElementConstructMagicNumber>(); - list.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberOne>(); - - EXPECT_TRUE( - static_cast<LongSimpleDerivedElement*>(list.front()) - ->AreAllValuesEqualTo(kMagicNumberToUseForLongSimpleDerivedElement)); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, - list.back()->get_value()); - - // Test that moving a simple derived element actually moves enough data so - // that the LongSimpleDerivedElement at this location is entirely moved. - SimpleDerivedElement* simple_element = list.back(); - list.AppendByMoving(list.front()); - EXPECT_TRUE( - static_cast<LongSimpleDerivedElement*>(list.back()) - ->AreAllValuesEqualTo(kMagicNumberToUseForLongSimpleDerivedElement)); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, - simple_element->get_value()); - - LongSimpleDerivedElement* long_element = - static_cast<LongSimpleDerivedElement*>(list.back()); - list.AppendByMoving(simple_element); - EXPECT_TRUE(long_element->AreAllValuesEqualTo( - kMagicNumberToUseForLongSimpleDerivedElement)); - EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, - list.back()->get_value()); -} - TEST(ListContainerTest, Swap) { ListContainer<SimpleDerivedElement> list_1( kCurrentLargestDerivedElementAlign, kCurrentLargestDerivedElementSize, 0); diff --git a/chromium/cc/base/switches.cc b/chromium/cc/base/switches.cc index b3688f98a20..8b70bc435c2 100644 --- a/chromium/cc/base/switches.cc +++ b/chromium/cc/base/switches.cc @@ -24,10 +24,8 @@ const char kDisableMainFrameBeforeActivation[] = const char kEnableMainFrameBeforeActivation[] = "enable-main-frame-before-activation"; -// Enables defering image decodes to the image decode service. -const char kEnableCheckerImaging[] = "enable-checker-imaging"; - -// Disabled defering image decodes to the image decode service. +// Disabled defering all image decodes to the image decode service, ignoring +// DecodingMode preferences specified on PaintImage. const char kDisableCheckerImaging[] = "disable-checker-imaging"; // Percentage of the browser controls need to be hidden before they will auto @@ -43,9 +41,6 @@ const char kBrowserControlsShowThreshold[] = "top-controls-show-threshold"; // complete, such as --slow-down-raster-scale-factor=25. const char kSlowDownRasterScaleFactor[] = "slow-down-raster-scale-factor"; -// Compress tile textures for GPUs supporting it. -const char kEnableTileCompression[] = "enable-tile-compression"; - // Checks damage early and aborts the frame if no damage, so that clients like // Android WebView don't invalidate unnecessarily. const char kCheckDamageEarly[] = "check-damage-early"; diff --git a/chromium/cc/base/switches.h b/chromium/cc/base/switches.h index adbea566bed..7234ee4024c 100644 --- a/chromium/cc/base/switches.h +++ b/chromium/cc/base/switches.h @@ -20,13 +20,11 @@ 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 kDisableCheckerImaging[]; 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[]; CC_BASE_EXPORT extern const char kCheckDamageEarly[]; // Switches for both the renderer and ui compositors. diff --git a/chromium/cc/blink/BUILD.gn b/chromium/cc/blink/BUILD.gn deleted file mode 100644 index 8b48a4097a7..00000000000 --- a/chromium/cc/blink/BUILD.gn +++ /dev/null @@ -1,75 +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. - -import("//cc/cc.gni") - -cc_component("blink") { - output_name = "cc_blink" - - sources = [ - "cc_blink_export.h", - "scrollbar_impl.cc", - "scrollbar_impl.h", - "web_compositor_support_impl.cc", - "web_compositor_support_impl.h", - "web_content_layer_impl.cc", - "web_content_layer_impl.h", - "web_display_item_list_impl.cc", - "web_display_item_list_impl.h", - "web_external_texture_layer_impl.cc", - "web_external_texture_layer_impl.h", - "web_image_layer_impl.cc", - "web_image_layer_impl.h", - "web_layer_impl.cc", - "web_layer_impl.h", - "web_layer_impl_fixed_bounds.cc", - "web_layer_impl_fixed_bounds.h", - "web_scrollbar_layer_impl.cc", - "web_scrollbar_layer_impl.h", - ] - - defines = [ "CC_BLINK_IMPLEMENTATION" ] - - public_deps = [ - "//skia", - ] - - deps = [ - "//base", - "//base/third_party/dynamic_annotations", - "//cc", - "//cc/paint", - "//gpu", - "//third_party/blink/public:blink", - "//ui/gfx", - "//ui/gfx/geometry", - ] -} - -cc_test("cc_blink_unittests") { - sources = [ - "web_display_item_list_impl_unittest.cc", - "web_layer_impl_fixed_bounds_unittest.cc", - - # Setup. - "test/cc_blink_test_suite.cc", - "test/cc_blink_test_suite.h", - "test/run_all_unittests.cc", - ] - - deps = [ - ":blink", - "//base/test:test_support", - "//base/third_party/dynamic_annotations", - "//cc", - "//cc:test_support", - "//cc/paint", - "//skia", - "//testing/gmock", - "//testing/gtest", - "//third_party/blink/public:blink", - "//ui/gfx:test_support", - "//ui/gfx/geometry", - ] -} diff --git a/chromium/cc/blink/DEPS b/chromium/cc/blink/DEPS deleted file mode 100644 index fc25dd99ad3..00000000000 --- a/chromium/cc/blink/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+third_party/blink/public/platform" -] diff --git a/chromium/cc/blink/OWNERS b/chromium/cc/blink/OWNERS deleted file mode 100644 index bcf87b10f97..00000000000 --- a/chromium/cc/blink/OWNERS +++ /dev/null @@ -1 +0,0 @@ -# COMPONENT: Blink>Compositing diff --git a/chromium/cc/blink/cc_blink_export.h b/chromium/cc/blink/cc_blink_export.h deleted file mode 100644 index 44ce527fc43..00000000000 --- a/chromium/cc/blink/cc_blink_export.h +++ /dev/null @@ -1,29 +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_BLINK_CC_BLINK_EXPORT_H_ -#define CC_BLINK_CC_BLINK_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(CC_BLINK_IMPLEMENTATION) -#define CC_BLINK_EXPORT __declspec(dllexport) -#else -#define CC_BLINK_EXPORT __declspec(dllimport) -#endif // defined(CC_BLINK_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(CC_BLINK_IMPLEMENTATION) -#define CC_BLINK_EXPORT __attribute__((visibility("default"))) -#else -#define CC_BLINK_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define CC_BLINK_EXPORT -#endif - -#endif // CC_BLINK_CC_BLINK_EXPORT_H_ diff --git a/chromium/cc/blink/scrollbar_impl.cc b/chromium/cc/blink/scrollbar_impl.cc deleted file mode 100644 index f92b4acb522..00000000000 --- a/chromium/cc/blink/scrollbar_impl.cc +++ /dev/null @@ -1,137 +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/blink/scrollbar_impl.h" - -#include "base/logging.h" -#include "third_party/blink/public/platform/web_scrollbar.h" -#include "third_party/blink/public/platform/web_scrollbar_theme_geometry.h" - -using blink::WebScrollbar; - -namespace cc_blink { - -ScrollbarImpl::ScrollbarImpl( - std::unique_ptr<WebScrollbar> scrollbar, - blink::WebScrollbarThemePainter painter, - std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry) - : scrollbar_(std::move(scrollbar)), - painter_(painter), - geometry_(std::move(geometry)) {} - -ScrollbarImpl::~ScrollbarImpl() = default; - -cc::ScrollbarOrientation ScrollbarImpl::Orientation() const { - if (scrollbar_->GetOrientation() == WebScrollbar::kHorizontal) - return cc::HORIZONTAL; - return cc::VERTICAL; -} - -bool ScrollbarImpl::IsLeftSideVerticalScrollbar() const { - return scrollbar_->IsLeftSideVerticalScrollbar(); -} - -bool ScrollbarImpl::HasThumb() const { - return geometry_->HasThumb(scrollbar_.get()); -} - -bool ScrollbarImpl::IsOverlay() const { - return scrollbar_->IsOverlay(); -} - -gfx::Point ScrollbarImpl::Location() const { - return scrollbar_->Location(); -} - -int ScrollbarImpl::ThumbThickness() const { - 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_->GetOrientation() == WebScrollbar::kHorizontal) - return thumb_rect.width(); - return thumb_rect.height(); -} - -gfx::Rect ScrollbarImpl::TrackRect() const { - return geometry_->TrackRect(scrollbar_.get()); -} - -float ScrollbarImpl::ThumbOpacity() const { - return painter_.ThumbOpacity(); -} - -bool ScrollbarImpl::NeedsPaintPart(cc::ScrollbarPart part) const { - if (part == cc::THUMB) - return painter_.ThumbNeedsRepaint(); - return painter_.TrackNeedsRepaint(); -} - -bool ScrollbarImpl::UsesNinePatchThumbResource() const { - return painter_.UsesNinePatchThumbResource(); -} - -gfx::Size ScrollbarImpl::NinePatchThumbCanvasSize() const { - return geometry_->NinePatchThumbCanvasSize(scrollbar_.get()); -} - -gfx::Rect ScrollbarImpl::NinePatchThumbAperture() const { - return geometry_->NinePatchThumbAperture(scrollbar_.get()); -} - -bool ScrollbarImpl::HasTickmarks() const { - return scrollbar_->HasTickmarks(); -} - -void ScrollbarImpl::PaintPart(cc::PaintCanvas* canvas, - cc::ScrollbarPart part, - const gfx::Rect& content_rect) { - if (part == cc::THUMB) { - painter_.PaintThumb(canvas, content_rect); - return; - } - - if (part == cc::TICKMARKS) { - painter_.PaintTickmarks(canvas, content_rect); - return; - } - - // The following is a simplification of ScrollbarThemeComposite::paint. - painter_.PaintScrollbarBackground(canvas, content_rect); - - if (geometry_->HasButtons(scrollbar_.get())) { - gfx::Rect 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); - - gfx::Rect 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); - } - - gfx::Rect track_paint_rect = geometry_->TrackRect(scrollbar_.get()); - painter_.PaintTrackBackground(canvas, track_paint_rect); - - bool thumb_present = geometry_->HasThumb(scrollbar_.get()); - if (thumb_present) { - painter_.PaintForwardTrackPart(canvas, track_paint_rect); - painter_.PaintBackTrackPart(canvas, track_paint_rect); - } - - painter_.PaintTickmarks(canvas, track_paint_rect); -} - -} // namespace cc_blink diff --git a/chromium/cc/blink/scrollbar_impl.h b/chromium/cc/blink/scrollbar_impl.h deleted file mode 100644 index 40157360fc8..00000000000 --- a/chromium/cc/blink/scrollbar_impl.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_BLINK_SCROLLBAR_IMPL_H_ -#define CC_BLINK_SCROLLBAR_IMPL_H_ - -#include <memory> - -#include "base/macros.h" -#include "cc/input/scrollbar.h" -#include "cc/paint/paint_canvas.h" -#include "third_party/blink/public/platform/web_scrollbar_theme_painter.h" - -namespace blink { -class WebScrollbar; -class WebScrollbarThemeGeometry; -} - -namespace cc_blink { - -class ScrollbarImpl : public cc::Scrollbar { - public: - ScrollbarImpl(std::unique_ptr<blink::WebScrollbar> scrollbar, - blink::WebScrollbarThemePainter painter, - std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry); - ~ScrollbarImpl() override; - - // cc::Scrollbar implementation. - cc::ScrollbarOrientation Orientation() const override; - bool IsLeftSideVerticalScrollbar() const override; - bool HasThumb() const override; - bool IsOverlay() const override; - gfx::Point Location() const override; - int ThumbThickness() const override; - int ThumbLength() const override; - gfx::Rect TrackRect() const override; - float ThumbOpacity() const override; - bool NeedsPaintPart(cc::ScrollbarPart part) const override; - bool HasTickmarks() const override; - void PaintPart(cc::PaintCanvas* canvas, - cc::ScrollbarPart part, - const gfx::Rect& content_rect) override; - - bool UsesNinePatchThumbResource() const override; - gfx::Size NinePatchThumbCanvasSize() const override; - gfx::Rect NinePatchThumbAperture() const override; - - private: - std::unique_ptr<blink::WebScrollbar> scrollbar_; - blink::WebScrollbarThemePainter painter_; - std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry_; - - DISALLOW_COPY_AND_ASSIGN(ScrollbarImpl); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_SCROLLBAR_IMPL_H_ diff --git a/chromium/cc/blink/web_blend_mode.h b/chromium/cc/blink/web_blend_mode.h deleted file mode 100644 index 998868c299e..00000000000 --- a/chromium/cc/blink/web_blend_mode.h +++ /dev/null @@ -1,107 +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_BLINK_WEB_BLEND_MODE_H_ -#define CC_BLINK_WEB_BLEND_MODE_H_ - -#include "third_party/blink/public/platform/web_blend_mode.h" -#include "third_party/skia/include/core/SkBlendMode.h" - -namespace cc_blink { - -inline SkBlendMode BlendModeToSkia(blink::WebBlendMode blend_mode) { - switch (blend_mode) { - case blink::WebBlendMode::kNormal: - return SkBlendMode::kSrcOver; - case blink::WebBlendMode::kMultiply: - return SkBlendMode::kMultiply; - case blink::WebBlendMode::kScreen: - return SkBlendMode::kScreen; - case blink::WebBlendMode::kOverlay: - return SkBlendMode::kOverlay; - case blink::WebBlendMode::kDarken: - return SkBlendMode::kDarken; - case blink::WebBlendMode::kLighten: - return SkBlendMode::kLighten; - case blink::WebBlendMode::kColorDodge: - return SkBlendMode::kColorDodge; - case blink::WebBlendMode::kColorBurn: - return SkBlendMode::kColorBurn; - case blink::WebBlendMode::kHardLight: - return SkBlendMode::kHardLight; - case blink::WebBlendMode::kSoftLight: - return SkBlendMode::kSoftLight; - case blink::WebBlendMode::kDifference: - return SkBlendMode::kDifference; - case blink::WebBlendMode::kExclusion: - return SkBlendMode::kExclusion; - case blink::WebBlendMode::kHue: - return SkBlendMode::kHue; - case blink::WebBlendMode::kSaturation: - return SkBlendMode::kSaturation; - case blink::WebBlendMode::kColor: - return SkBlendMode::kColor; - case blink::WebBlendMode::kLuminosity: - return SkBlendMode::kLuminosity; - } - return SkBlendMode::kSrcOver; -} - -inline blink::WebBlendMode BlendModeFromSkia(SkBlendMode blend_mode) { - switch (blend_mode) { - case SkBlendMode::kSrcOver: - return blink::WebBlendMode::kNormal; - case SkBlendMode::kMultiply: - return blink::WebBlendMode::kMultiply; - case SkBlendMode::kScreen: - return blink::WebBlendMode::kScreen; - case SkBlendMode::kOverlay: - return blink::WebBlendMode::kOverlay; - case SkBlendMode::kDarken: - return blink::WebBlendMode::kDarken; - case SkBlendMode::kLighten: - return blink::WebBlendMode::kLighten; - case SkBlendMode::kColorDodge: - return blink::WebBlendMode::kColorDodge; - case SkBlendMode::kColorBurn: - return blink::WebBlendMode::kColorBurn; - case SkBlendMode::kHardLight: - return blink::WebBlendMode::kHardLight; - case SkBlendMode::kSoftLight: - return blink::WebBlendMode::kSoftLight; - case SkBlendMode::kDifference: - return blink::WebBlendMode::kDifference; - case SkBlendMode::kExclusion: - return blink::WebBlendMode::kExclusion; - case SkBlendMode::kHue: - return blink::WebBlendMode::kHue; - case SkBlendMode::kSaturation: - return blink::WebBlendMode::kSaturation; - case SkBlendMode::kColor: - return blink::WebBlendMode::kColor; - case SkBlendMode::kLuminosity: - return blink::WebBlendMode::kLuminosity; - - // these value are SkBlendModes, but no blend modes. - case SkBlendMode::kClear: - case SkBlendMode::kSrc: - case SkBlendMode::kDst: - case SkBlendMode::kDstOver: - case SkBlendMode::kSrcIn: - case SkBlendMode::kDstIn: - case SkBlendMode::kSrcOut: - case SkBlendMode::kDstOut: - case SkBlendMode::kSrcATop: - case SkBlendMode::kDstATop: - case SkBlendMode::kXor: - case SkBlendMode::kPlus: - case SkBlendMode::kModulate: - NOTREACHED(); - } - return blink::WebBlendMode::kNormal; -} - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_BLEND_MODE_H_ diff --git a/chromium/cc/blink/web_compositor_support_impl.cc b/chromium/cc/blink/web_compositor_support_impl.cc deleted file mode 100644 index 04d038b181b..00000000000 --- a/chromium/cc/blink/web_compositor_support_impl.cc +++ /dev/null @@ -1,90 +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/blink/web_compositor_support_impl.h" - -#include <utility> - -#include "cc/blink/web_content_layer_impl.h" -#include "cc/blink/web_display_item_list_impl.h" -#include "cc/blink/web_external_texture_layer_impl.h" -#include "cc/blink/web_image_layer_impl.h" -#include "cc/blink/web_layer_impl.h" -#include "cc/blink/web_scrollbar_layer_impl.h" -#include "cc/layers/layer.h" - -using blink::WebContentLayer; -using blink::WebContentLayerClient; -using blink::WebDisplayItemList; -using blink::WebExternalTextureLayer; -using blink::WebImageLayer; -using blink::WebLayer; -using blink::WebScrollbar; -using blink::WebScrollbarLayer; -using blink::WebScrollbarThemeGeometry; -using blink::WebScrollbarThemePainter; - -namespace cc_blink { - -WebCompositorSupportImpl::WebCompositorSupportImpl() = default; - -WebCompositorSupportImpl::~WebCompositorSupportImpl() = default; - -std::unique_ptr<WebLayer> WebCompositorSupportImpl::CreateLayer() { - return std::make_unique<WebLayerImpl>(); -} - -std::unique_ptr<WebLayer> WebCompositorSupportImpl::CreateLayerFromCCLayer( - cc::Layer* layer) { - return std::make_unique<WebLayerImpl>(layer); -} - -std::unique_ptr<WebContentLayer> WebCompositorSupportImpl::CreateContentLayer( - WebContentLayerClient* client) { - return std::make_unique<WebContentLayerImpl>(client); -} - -std::unique_ptr<WebExternalTextureLayer> -WebCompositorSupportImpl::CreateExternalTextureLayer( - cc::TextureLayerClient* client) { - return std::make_unique<WebExternalTextureLayerImpl>(client); -} - -std::unique_ptr<blink::WebImageLayer> -WebCompositorSupportImpl::CreateImageLayer() { - return std::make_unique<WebImageLayerImpl>(); -} - -std::unique_ptr<WebScrollbarLayer> -WebCompositorSupportImpl::CreateScrollbarLayer( - std::unique_ptr<WebScrollbar> scrollbar, - WebScrollbarThemePainter painter, - std::unique_ptr<WebScrollbarThemeGeometry> geometry) { - return std::make_unique<WebScrollbarLayerImpl>(std::move(scrollbar), painter, - std::move(geometry), - /* is overlay */ false); -} - -std::unique_ptr<WebScrollbarLayer> -WebCompositorSupportImpl::CreateOverlayScrollbarLayer( - std::unique_ptr<WebScrollbar> scrollbar, - WebScrollbarThemePainter painter, - std::unique_ptr<WebScrollbarThemeGeometry> geometry) { - return std::make_unique<WebScrollbarLayerImpl>(std::move(scrollbar), painter, - std::move(geometry), - /* is overlay */ true); -} - -std::unique_ptr<WebScrollbarLayer> -WebCompositorSupportImpl::CreateSolidColorScrollbarLayer( - WebScrollbar::Orientation orientation, - int thumb_thickness, - int track_start, - bool is_left_side_vertical_scrollbar) { - return std::make_unique<WebScrollbarLayerImpl>( - orientation, thumb_thickness, track_start, - is_left_side_vertical_scrollbar); -} - -} // namespace cc_blink diff --git a/chromium/cc/blink/web_compositor_support_impl.h b/chromium/cc/blink/web_compositor_support_impl.h deleted file mode 100644 index 9a24211b9a2..00000000000 --- a/chromium/cc/blink/web_compositor_support_impl.h +++ /dev/null @@ -1,50 +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_BLINK_WEB_COMPOSITOR_SUPPORT_IMPL_H_ -#define CC_BLINK_WEB_COMPOSITOR_SUPPORT_IMPL_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "cc/blink/cc_blink_export.h" -#include "third_party/blink/public/platform/web_compositor_support.h" -#include "third_party/blink/public/platform/web_content_layer_client.h" -#include "third_party/blink/public/platform/web_layer.h" - -namespace cc_blink { - -class CC_BLINK_EXPORT WebCompositorSupportImpl - : public blink::WebCompositorSupport { - public: - 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( - blink::WebContentLayerClient* client) override; - 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::WebScrollbar> scrollbar, - blink::WebScrollbarThemePainter painter, - std::unique_ptr<blink::WebScrollbarThemeGeometry>) override; - 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( - blink::WebScrollbar::Orientation orientation, - int thumb_thickness, - int track_start, - bool is_left_side_vertical_scrollbar) override; - - private: - DISALLOW_COPY_AND_ASSIGN(WebCompositorSupportImpl); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_COMPOSITOR_SUPPORT_IMPL_H_ diff --git a/chromium/cc/blink/web_content_layer_impl.cc b/chromium/cc/blink/web_content_layer_impl.cc deleted file mode 100644 index 5dc2f9c2d81..00000000000 --- a/chromium/cc/blink/web_content_layer_impl.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/blink/web_content_layer_impl.h" - -#include <stddef.h> - -#include "base/command_line.h" -#include "cc/base/switches.h" -#include "cc/blink/web_display_item_list_impl.h" -#include "cc/layers/picture_layer.h" -#include "third_party/blink/public/platform/web_content_layer_client.h" -#include "third_party/blink/public/platform/web_float_point.h" -#include "third_party/blink/public/platform/web_float_rect.h" -#include "third_party/blink/public/platform/web_rect.h" -#include "third_party/blink/public/platform/web_size.h" -#include "third_party/skia/include/core/SkMatrix44.h" - -using cc::PictureLayer; - -namespace cc_blink { - -static blink::WebContentLayerClient::PaintingControlSetting -PaintingControlToWeb( - cc::ContentLayerClient::PaintingControlSetting painting_control) { - switch (painting_control) { - case cc::ContentLayerClient::PAINTING_BEHAVIOR_NORMAL: - return blink::WebContentLayerClient::kPaintDefaultBehavior; - case cc::ContentLayerClient::PAINTING_BEHAVIOR_NORMAL_FOR_TEST: - return blink::WebContentLayerClient::kPaintDefaultBehaviorForTest; - case cc::ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED: - return blink::WebContentLayerClient::kDisplayListConstructionDisabled; - case cc::ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED: - return blink::WebContentLayerClient::kDisplayListCachingDisabled; - case cc::ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED: - return blink::WebContentLayerClient::kDisplayListPaintingDisabled; - case cc::ContentLayerClient::SUBSEQUENCE_CACHING_DISABLED: - return blink::WebContentLayerClient::kSubsequenceCachingDisabled; - case cc::ContentLayerClient::PARTIAL_INVALIDATION: - return blink::WebContentLayerClient::kPartialInvalidation; - } - NOTREACHED(); - return blink::WebContentLayerClient::kPaintDefaultBehavior; -} - -WebContentLayerImpl::WebContentLayerImpl(blink::WebContentLayerClient* client) - : client_(client) { - layer_ = std::make_unique<WebLayerImpl>(PictureLayer::Create(this)); - layer_->layer()->SetIsDrawable(true); -} - -WebContentLayerImpl::~WebContentLayerImpl() { - static_cast<PictureLayer*>(layer_->layer())->ClearClient(); -} - -blink::WebLayer* WebContentLayerImpl::Layer() { - return layer_.get(); -} - -void WebContentLayerImpl::SetTransformedRasterizationAllowed(bool allowed) { - static_cast<PictureLayer*>(layer_->layer()) - ->SetTransformedRasterizationAllowed(allowed); -} - -bool WebContentLayerImpl::TransformedRasterizationAllowed() const { - return static_cast<PictureLayer*>(layer_->layer()) - ->transformed_rasterization_allowed(); -} - -gfx::Rect WebContentLayerImpl::PaintableRegion() { - return client_->PaintableRegion(); -} - -scoped_refptr<cc::DisplayItemList> -WebContentLayerImpl::PaintContentsToDisplayList( - cc::ContentLayerClient::PaintingControlSetting painting_control) { - auto display_list = base::MakeRefCounted<cc::DisplayItemList>(); - if (client_) { - WebDisplayItemListImpl list(display_list.get()); - client_->PaintContents(&list, PaintingControlToWeb(painting_control)); - } - display_list->Finalize(); - return display_list; -} - -bool WebContentLayerImpl::FillsBoundsCompletely() const { - return false; -} - -size_t WebContentLayerImpl::GetApproximateUnsharedMemoryUsage() const { - 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 deleted file mode 100644 index 6f82ec478e9..00000000000 --- a/chromium/cc/blink/web_content_layer_impl.h +++ /dev/null @@ -1,53 +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_BLINK_WEB_CONTENT_LAYER_IMPL_H_ -#define CC_BLINK_WEB_CONTENT_LAYER_IMPL_H_ - -#include <stddef.h> - -#include <memory> - -#include "base/macros.h" -#include "cc/blink/cc_blink_export.h" -#include "cc/blink/web_layer_impl.h" -#include "cc/layers/content_layer_client.h" -#include "third_party/blink/public/platform/web_content_layer.h" - -namespace blink { -class WebContentLayerClient; -} - -namespace cc_blink { - -class WebContentLayerImpl : public blink::WebContentLayer, - public cc::ContentLayerClient { - public: - CC_BLINK_EXPORT explicit WebContentLayerImpl(blink::WebContentLayerClient*); - - ~WebContentLayerImpl() override; - - // WebContentLayer implementation. - blink::WebLayer* Layer() override; - void SetTransformedRasterizationAllowed(bool) override; - bool TransformedRasterizationAllowed() const override; - - protected: - // ContentLayerClient implementation. - gfx::Rect PaintableRegion() override; - scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting painting_control) override; - bool FillsBoundsCompletely() const override; - size_t GetApproximateUnsharedMemoryUsage() const override; - - std::unique_ptr<WebLayerImpl> layer_; - blink::WebContentLayerClient* client_; - - private: - DISALLOW_COPY_AND_ASSIGN(WebContentLayerImpl); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_CONTENT_LAYER_IMPL_H_ diff --git a/chromium/cc/blink/web_display_item_list_impl.cc b/chromium/cc/blink/web_display_item_list_impl.cc deleted file mode 100644 index 5be83ce9a64..00000000000 --- a/chromium/cc/blink/web_display_item_list_impl.cc +++ /dev/null @@ -1,209 +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/blink/web_display_item_list_impl.h" - -#include <stddef.h> -#include <stdint.h> - -#include <vector> - -#include "cc/paint/paint_filter.h" -#include "cc/paint/paint_op_buffer.h" -#include "cc/paint/render_surface_filters.h" -#include "third_party/blink/public/platform/web_float_rect.h" -#include "third_party/blink/public/platform/web_rect.h" -#include "third_party/skia/include/core/SkColorFilter.h" -#include "third_party/skia/include/core/SkMatrix44.h" -#include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/geometry/safe_integer_conversions.h" -#include "ui/gfx/skia_util.h" -#include "ui/gfx/transform.h" - -namespace cc_blink { - -namespace { - -} // namespace - -WebDisplayItemListImpl::WebDisplayItemListImpl() - : display_item_list_(base::MakeRefCounted<cc::DisplayItemList>()) {} - -WebDisplayItemListImpl::WebDisplayItemListImpl( - cc::DisplayItemList* display_list) - : display_item_list_(display_list) { -} - -WebDisplayItemListImpl::~WebDisplayItemListImpl() = default; - -void WebDisplayItemListImpl::AppendDrawingItem( - const blink::WebRect& visual_rect, - sk_sp<const cc::PaintOpBuffer> record) { - display_item_list_->StartPaint(); - display_item_list_->push<cc::DrawRecordOp>(std::move(record)); - display_item_list_->EndPaintOfUnpaired(visual_rect); -} - -void WebDisplayItemListImpl::AppendClipItem( - const blink::WebRect& clip_rect, - const blink::WebVector<SkRRect>& rounded_clip_rects) { - bool antialias = true; - display_item_list_->StartPaint(); - display_item_list_->push<cc::SaveOp>(); - display_item_list_->push<cc::ClipRectOp>(gfx::RectToSkRect(clip_rect), - SkClipOp::kIntersect, antialias); - for (const SkRRect& rrect : rounded_clip_rects) { - if (rrect.isRect()) { - display_item_list_->push<cc::ClipRectOp>(rrect.rect(), - SkClipOp::kIntersect, antialias); - } else { - display_item_list_->push<cc::ClipRRectOp>(rrect, SkClipOp::kIntersect, - antialias); - } - } - display_item_list_->EndPaintOfPairedBegin(); -} - -void WebDisplayItemListImpl::AppendEndClipItem() { - AppendRestore(); -} - -void WebDisplayItemListImpl::AppendClipPathItem(const SkPath& clip_path, - bool antialias) { - display_item_list_->StartPaint(); - display_item_list_->push<cc::SaveOp>(); - display_item_list_->push<cc::ClipPathOp>(clip_path, SkClipOp::kIntersect, - antialias); - display_item_list_->EndPaintOfPairedBegin(); -} - -void WebDisplayItemListImpl::AppendEndClipPathItem() { - AppendRestore(); -} - -void WebDisplayItemListImpl::AppendFloatClipItem( - const blink::WebFloatRect& clip_rect) { - bool antialias = true; - display_item_list_->StartPaint(); - display_item_list_->push<cc::SaveOp>(); - display_item_list_->push<cc::ClipRectOp>(gfx::RectFToSkRect(clip_rect), - SkClipOp::kIntersect, antialias); - display_item_list_->EndPaintOfPairedBegin(); -} - -void WebDisplayItemListImpl::AppendEndFloatClipItem() { - AppendRestore(); -} - -void WebDisplayItemListImpl::AppendTransformItem(const SkMatrix44& matrix) { - display_item_list_->StartPaint(); - display_item_list_->push<cc::SaveOp>(); - if (!matrix.isIdentity()) - display_item_list_->push<cc::ConcatOp>(static_cast<SkMatrix>(matrix)); - display_item_list_->EndPaintOfPairedBegin(); -} - -void WebDisplayItemListImpl::AppendEndTransformItem() { - AppendRestore(); -} - -void WebDisplayItemListImpl::AppendCompositingItem( - float opacity, - SkBlendMode xfermode, - SkRect* bounds, - SkColorFilter* color_filter) { - DCHECK_GE(opacity, 0.f); - DCHECK_LE(opacity, 1.f); - - // TODO(ajuma): This should really be rounding instead of flooring the alpha - // value, but that breaks slimming paint reftests. - auto alpha = static_cast<uint8_t>(gfx::ToFlooredInt(255 * opacity)); - - if (xfermode == SkBlendMode::kSrcOver && !color_filter) { - display_item_list_->StartPaint(); - display_item_list_->push<cc::SaveLayerAlphaOp>(bounds, alpha, false); - if (bounds) { - display_item_list_->push<cc::ClipRectOp>(*bounds, SkClipOp::kIntersect, - false); - } - display_item_list_->EndPaintOfPairedBegin(); - return; - } - - cc::PaintFlags flags; - flags.setBlendMode(xfermode); - flags.setAlpha(alpha); - flags.setColorFilter(sk_ref_sp(color_filter)); - - display_item_list_->StartPaint(); - display_item_list_->push<cc::SaveLayerOp>(bounds, &flags); - if (bounds) { - display_item_list_->push<cc::ClipRectOp>(*bounds, SkClipOp::kIntersect, - false); - } - display_item_list_->EndPaintOfPairedBegin(); -} - -void WebDisplayItemListImpl::AppendEndCompositingItem() { - AppendRestore(); -} - -void WebDisplayItemListImpl::AppendFilterItem( - const cc::FilterOperations& filters, - const blink::WebFloatRect& filter_bounds, - const blink::WebFloatPoint& origin) { - display_item_list_->StartPaint(); - - // TODO(danakj): Skip the save+translate+restore if the origin is 0,0. This - // should be easier to do when this code is part of the blink DisplayItem - // which can keep related state. - display_item_list_->push<cc::SaveOp>(); - display_item_list_->push<cc::TranslateOp>(origin.x, origin.y); - - cc::PaintFlags flags; - flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter( - filters, gfx::SizeF(filter_bounds.width, filter_bounds.height))); - - SkRect layer_bounds = gfx::RectFToSkRect(filter_bounds); - layer_bounds.offset(-origin.x, -origin.y); - display_item_list_->push<cc::SaveLayerOp>(&layer_bounds, &flags); - display_item_list_->push<cc::TranslateOp>(-origin.x, -origin.y); - - display_item_list_->EndPaintOfPairedBegin( - gfx::ToEnclosingRect(filter_bounds)); -} - -void WebDisplayItemListImpl::AppendEndFilterItem() { - display_item_list_->StartPaint(); - display_item_list_->push<cc::RestoreOp>(); // For SaveLayerOp. - display_item_list_->push<cc::RestoreOp>(); // For SaveOp. - display_item_list_->EndPaintOfPairedEnd(); -} - -void WebDisplayItemListImpl::AppendScrollItem( - const blink::WebSize& scroll_offset, - ScrollContainerId) { - display_item_list_->StartPaint(); - display_item_list_->push<cc::SaveOp>(); - display_item_list_->push<cc::TranslateOp>( - static_cast<float>(-scroll_offset.width), - static_cast<float>(-scroll_offset.height)); - display_item_list_->EndPaintOfPairedBegin(); -} - -void WebDisplayItemListImpl::AppendEndScrollItem() { - AppendRestore(); -} - -void WebDisplayItemListImpl::AppendRestore() { - display_item_list_->StartPaint(); - display_item_list_->push<cc::RestoreOp>(); - display_item_list_->EndPaintOfPairedEnd(); -} - -cc::DisplayItemList* WebDisplayItemListImpl::GetCcDisplayItemList() { - return display_item_list_.get(); -} - -} // namespace cc_blink diff --git a/chromium/cc/blink/web_display_item_list_impl.h b/chromium/cc/blink/web_display_item_list_impl.h deleted file mode 100644 index 5db188c85c8..00000000000 --- a/chromium/cc/blink/web_display_item_list_impl.h +++ /dev/null @@ -1,79 +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_BLINK_WEB_DISPLAY_ITEM_LIST_IMPL_H_ -#define CC_BLINK_WEB_DISPLAY_ITEM_LIST_IMPL_H_ - -#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 "third_party/blink/public/platform/web_display_item_list.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/skia/include/core/SkBlendMode.h" -#include "ui/gfx/geometry/point_f.h" - -class SkColorFilter; -class SkMatrix44; -class SkPath; -class SkRRect; - -namespace blink { -struct WebFloatRect; -struct WebFloatPoint; -struct WebRect; -} - -namespace cc { -class FilterOperations; -class PaintOpBuffer; -} - -namespace cc_blink { - -class CC_BLINK_EXPORT WebDisplayItemListImpl - : public blink::WebDisplayItemList { - public: - WebDisplayItemListImpl(); - explicit WebDisplayItemListImpl(cc::DisplayItemList* display_list); - ~WebDisplayItemListImpl() override; - - // blink::WebDisplayItemList implementation. - void AppendDrawingItem(const blink::WebRect& visual_rect, - sk_sp<const cc::PaintOpBuffer> record) override; - 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, - SkBlendMode, - SkRect* bounds, - SkColorFilter*) override; - 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, - ScrollContainerId) override; - void AppendEndScrollItem() override; - cc::DisplayItemList* GetCcDisplayItemList() override; - - private: - void AppendRestore(); - - scoped_refptr<cc::DisplayItemList> display_item_list_; - - DISALLOW_COPY_AND_ASSIGN(WebDisplayItemListImpl); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_DISPLAY_ITEM_LIST_IMPL_H_ diff --git a/chromium/cc/blink/web_display_item_list_impl_unittest.cc b/chromium/cc/blink/web_display_item_list_impl_unittest.cc deleted file mode 100644 index f9efd761eed..00000000000 --- a/chromium/cc/blink/web_display_item_list_impl_unittest.cc +++ /dev/null @@ -1,91 +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. - -#include "cc/blink/web_display_item_list_impl.h" -#include "base/strings/stringprintf.h" -#include "cc/paint/display_item_list.h" -#include "cc/paint/paint_op_buffer.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/web_float_point.h" - -namespace cc_blink { -namespace { - -// SkCanvas::saveLayer(Alpha) allows for an optional bounds which is a hint -// for the backing size to use for the indirect buffer. It is not really -// a clip though, as Skia is allowed to use any size buffer it wants. -// Additionally, PaintOpBuffer can drop the bounds when folding -// save/draw/restore into a single draw-with-alpha. However, in some cases -// calling code (SVGMask) is drawing unclipped items which really need -// a clip to not pollute the rest of the painted content with their draw -// commands. Therefore, this tests that when providing bounds to -// AppendCompositingItem that a clip is inserted. -TEST(WebDisplayItemListImpl, ClipWhenCompositing) { - // Test with two different blend modes to differentiate the saveLayer vs - // saveLayerAlpha logic inside of AppendCompositingItem; - SkBlendMode blend_modes[] = {SkBlendMode::kSrc, SkBlendMode::kSrcOver}; - for (size_t i = 0; i < arraysize(blend_modes); ++i) { - static constexpr int size = 20; - static constexpr SkColor background_color = SK_ColorMAGENTA; - static constexpr SkColor clip_color = SK_ColorYELLOW; - - blink::WebRect full_bounds(0, 0, size, size); - blink::WebRect clip_bounds(5, 3, 13, 9); - SkRect sk_clip_bounds = SkRect::MakeXYWH( - clip_bounds.x, clip_bounds.y, clip_bounds.width, clip_bounds.height); - SkIRect clip_irect = sk_clip_bounds.roundOut(); - - auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(); - cc_blink::WebDisplayItemListImpl web_list(cc_list.get()); - - // drawColor(background color) - // saveLayer(should clip) - // drawColor(clip color) - // end - auto background_record = sk_make_sp<cc::PaintRecord>(); - background_record->push<cc::DrawColorOp>(background_color, - SkBlendMode::kSrcOver); - web_list.AppendDrawingItem(full_bounds, background_record); - web_list.AppendCompositingItem(1.f, blend_modes[i], &sk_clip_bounds, - nullptr); - auto clip_record = sk_make_sp<cc::PaintRecord>(); - clip_record->push<cc::DrawColorOp>(clip_color, SkBlendMode::kSrcOver); - web_list.AppendDrawingItem(full_bounds, clip_record); - web_list.AppendEndCompositingItem(); - cc_list->Finalize(); - - SkBitmap bitmap; - bitmap.allocPixels(SkImageInfo::MakeN32Premul(size, size)); - SkCanvas canvas(bitmap); - canvas.drawColor(SK_ColorGRAY); - - cc_list->Raster(&canvas); - uint8_t* pixels = static_cast<uint8_t*>(bitmap.getPixels()); - size_t row_bytes = size * 4; - for (size_t y = 0; y < size; ++y) { - size_t y_offset = y * row_bytes; - for (size_t x = 0; x < size; ++x) { - size_t x_offset = x * 4; - uint8_t* pixel = &pixels[y_offset + x_offset]; - SCOPED_TRACE( - base::StringPrintf("x(%zd) y(%zd) mode(%d)", x, y, blend_modes[i])); - - if (clip_irect.contains(x, y)) { - EXPECT_EQ(SkColorGetR(clip_color), pixel[SK_R32_SHIFT / 8]); - EXPECT_EQ(SkColorGetG(clip_color), pixel[SK_G32_SHIFT / 8]); - EXPECT_EQ(SkColorGetB(clip_color), pixel[SK_B32_SHIFT / 8]); - EXPECT_EQ(SkColorGetA(clip_color), pixel[SK_A32_SHIFT / 8]); - } else { - EXPECT_EQ(SkColorGetR(background_color), pixel[SK_R32_SHIFT / 8]); - EXPECT_EQ(SkColorGetG(background_color), pixel[SK_G32_SHIFT / 8]); - EXPECT_EQ(SkColorGetB(background_color), pixel[SK_B32_SHIFT / 8]); - EXPECT_EQ(SkColorGetA(background_color), pixel[SK_A32_SHIFT / 8]); - } - } - } - } -} - -} // namespace -} // namespace cc_blink diff --git a/chromium/cc/blink/web_external_texture_layer_impl.cc b/chromium/cc/blink/web_external_texture_layer_impl.cc deleted file mode 100644 index 64fbf26cbd4..00000000000 --- a/chromium/cc/blink/web_external_texture_layer_impl.cc +++ /dev/null @@ -1,65 +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/blink/web_external_texture_layer_impl.h" - -#include "cc/blink/web_layer_impl.h" -#include "cc/layers/texture_layer.h" - -using cc::TextureLayer; - -namespace cc_blink { - -WebExternalTextureLayerImpl::WebExternalTextureLayerImpl( - cc::TextureLayerClient* client) { - scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(client); - layer->SetIsDrawable(true); - layer_.reset(new WebLayerImpl(layer)); -} - -WebExternalTextureLayerImpl::~WebExternalTextureLayerImpl() { - static_cast<TextureLayer*>(layer_->layer())->ClearClient(); -} - -blink::WebLayer* WebExternalTextureLayerImpl::Layer() { - return layer_.get(); -} - -void WebExternalTextureLayerImpl::ClearTexture() { - TextureLayer* layer = static_cast<TextureLayer*>(layer_->layer()); - layer->ClearTexture(); -} - -void WebExternalTextureLayerImpl::SetOpaque(bool opaque) { - static_cast<TextureLayer*>(layer_->layer())->SetContentsOpaque(opaque); -} - -void WebExternalTextureLayerImpl::SetFlipped(bool flipped) { - static_cast<TextureLayer*>(layer_->layer())->SetFlipped(flipped); -} - -void WebExternalTextureLayerImpl::SetPremultipliedAlpha( - bool premultiplied_alpha) { - static_cast<TextureLayer*>(layer_->layer()) - ->SetPremultipliedAlpha(premultiplied_alpha); -} - -void WebExternalTextureLayerImpl::SetBlendBackgroundColor(bool blend) { - static_cast<TextureLayer*>(layer_->layer())->SetBlendBackgroundColor(blend); -} - -void WebExternalTextureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { - static_cast<TextureLayer*>(layer_->layer()) - ->SetNearestNeighbor(nearest_neighbor); -} - -void WebExternalTextureLayerImpl::SetUV( - const blink::WebFloatPoint left_top, - const blink::WebFloatPoint right_bottom) { - static_cast<TextureLayer*>(layer_->layer()) - ->SetUV(gfx::PointF(left_top.x, left_top.y), - gfx::PointF(right_bottom.x, right_bottom.y)); -} - -} // namespace cc_blink diff --git a/chromium/cc/blink/web_external_texture_layer_impl.h b/chromium/cc/blink/web_external_texture_layer_impl.h deleted file mode 100644 index 11ca63cf5b1..00000000000 --- a/chromium/cc/blink/web_external_texture_layer_impl.h +++ /dev/null @@ -1,45 +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_BLINK_WEB_EXTERNAL_TEXTURE_LAYER_IMPL_H_ -#define CC_BLINK_WEB_EXTERNAL_TEXTURE_LAYER_IMPL_H_ - -#include <memory> - -#include "base/macros.h" -#include "cc/blink/cc_blink_export.h" -#include "third_party/blink/public/platform/web_external_texture_layer.h" - -namespace cc { -class TextureLayerClient; -} - -namespace cc_blink { -class WebLayerImpl; - -class WebExternalTextureLayerImpl : public blink::WebExternalTextureLayer { - public: - CC_BLINK_EXPORT explicit WebExternalTextureLayerImpl(cc::TextureLayerClient*); - ~WebExternalTextureLayerImpl() override; - - // blink::WebExternalTextureLayer implementation. - blink::WebLayer* Layer() override; - void ClearTexture() override; - void SetOpaque(bool opaque) override; - void SetFlipped(bool flipped) override; - void SetPremultipliedAlpha(bool premultiplied) override; - void SetBlendBackgroundColor(bool blend) override; - void SetNearestNeighbor(bool nearest_neighbor) override; - void SetUV(const blink::WebFloatPoint left_top, - const blink::WebFloatPoint right_bottom) override; - - private: - std::unique_ptr<WebLayerImpl> layer_; - - DISALLOW_COPY_AND_ASSIGN(WebExternalTextureLayerImpl); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_EXTERNAL_TEXTURE_LAYER_IMPL_H_ diff --git a/chromium/cc/blink/web_image_layer_impl.cc b/chromium/cc/blink/web_image_layer_impl.cc deleted file mode 100644 index 403bb0cc49f..00000000000 --- a/chromium/cc/blink/web_image_layer_impl.cc +++ /dev/null @@ -1,40 +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/blink/web_image_layer_impl.h" - -#include "cc/blink/web_layer_impl.h" -#include "cc/blink/web_layer_impl_fixed_bounds.h" -#include "cc/layers/picture_image_layer.h" -#include "third_party/skia/include/core/SkImage.h" - -namespace cc_blink { - -WebImageLayerImpl::WebImageLayerImpl() { - layer_.reset(new WebLayerImplFixedBounds(cc::PictureImageLayer::Create())); -} - -WebImageLayerImpl::~WebImageLayerImpl() = default; - -blink::WebLayer* WebImageLayerImpl::Layer() { - return layer_.get(); -} - -void WebImageLayerImpl::SetImage(cc::PaintImage image, - const SkMatrix& matrix, - bool uses_width_as_height) { - gfx::Size size = uses_width_as_height - ? gfx::Size(image.height(), image.width()) - : gfx::Size(image.width(), image.height()); - static_cast<WebLayerImplFixedBounds*>(layer_.get())->SetFixedBounds(size); - static_cast<cc::PictureImageLayer*>(layer_->layer()) - ->SetImage(std::move(image), matrix, uses_width_as_height); -} - -void WebImageLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { - static_cast<cc::PictureImageLayer*>(layer_->layer()) - ->SetNearestNeighbor(nearest_neighbor); -} - -} // namespace cc_blink diff --git a/chromium/cc/blink/web_image_layer_impl.h b/chromium/cc/blink/web_image_layer_impl.h deleted file mode 100644 index 11b76dc95e7..00000000000 --- a/chromium/cc/blink/web_image_layer_impl.h +++ /dev/null @@ -1,39 +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_BLINK_WEB_IMAGE_LAYER_IMPL_H_ -#define CC_BLINK_WEB_IMAGE_LAYER_IMPL_H_ - -#include <memory> - -#include "base/macros.h" -#include "cc/blink/cc_blink_export.h" -#include "cc/paint/paint_image.h" -#include "third_party/blink/public/platform/web_image_layer.h" - -namespace cc_blink { - -class WebLayerImpl; - -class WebImageLayerImpl : public blink::WebImageLayer { - public: - CC_BLINK_EXPORT WebImageLayerImpl(); - ~WebImageLayerImpl() override; - - // blink::WebImageLayer implementation. - blink::WebLayer* Layer() override; - void SetImage(PaintImage image, - const SkMatrix& matrix, - bool uses_width_as_height) override; - void SetNearestNeighbor(bool nearest_neighbor) override; - - private: - std::unique_ptr<WebLayerImpl> layer_; - - DISALLOW_COPY_AND_ASSIGN(WebImageLayerImpl); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_IMAGE_LAYER_IMPL_H_ diff --git a/chromium/cc/blink/web_layer_impl.cc b/chromium/cc/blink/web_layer_impl.cc deleted file mode 100644 index b8cb7aeb9eb..00000000000 --- a/chromium/cc/blink/web_layer_impl.cc +++ /dev/null @@ -1,523 +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/blink/web_layer_impl.h" - -#include <stddef.h> -#include <stdint.h> - -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/containers/flat_map.h" -#include "base/strings/string_util.h" -#include "base/threading/thread_checker.h" -#include "base/trace_event/trace_event_impl.h" -#include "cc/base/region.h" -#include "cc/base/switches.h" -#include "cc/blink/web_blend_mode.h" -#include "cc/layers/layer.h" -#include "cc/layers/layer_position_constraint.h" -#include "cc/layers/touch_action_region.h" -#include "cc/trees/element_id.h" -#include "cc/trees/layer_tree_host.h" -#include "third_party/blink/public/platform/web_float_point.h" -#include "third_party/blink/public/platform/web_float_rect.h" -#include "third_party/blink/public/platform/web_layer_position_constraint.h" -#include "third_party/blink/public/platform/web_layer_scroll_client.h" -#include "third_party/blink/public/platform/web_layer_sticky_position_constraint.h" -#include "third_party/blink/public/platform/web_size.h" -#include "third_party/skia/include/core/SkMatrix44.h" -#include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/geometry/vector2d_conversions.h" - -using cc::Layer; -using blink::WebLayer; -using blink::WebFloatPoint; -using blink::WebVector; -using blink::WebRect; -using blink::WebSize; -using blink::WebColor; -using blink::WebOverscrollBehavior; - -namespace cc_blink { - -WebLayerImpl::WebLayerImpl() - : layer_(Layer::Create()), contents_opaque_is_fixed_(false) {} - -WebLayerImpl::WebLayerImpl(scoped_refptr<Layer> layer) - : layer_(layer), contents_opaque_is_fixed_(false) { -} - -WebLayerImpl::~WebLayerImpl() { - layer_->SetLayerClient(nullptr); -} - -int WebLayerImpl::Id() const { - return layer_->id(); -} - -DISABLE_CFI_PERF -void WebLayerImpl::InvalidateRect(const blink::WebRect& rect) { - layer_->SetNeedsDisplayRect(rect); -} - -void WebLayerImpl::Invalidate() { - layer_->SetNeedsDisplay(); -} - -void WebLayerImpl::AddChild(WebLayer* child) { - layer_->AddChild(static_cast<WebLayerImpl*>(child)->layer()); -} - -void WebLayerImpl::InsertChild(WebLayer* child, size_t index) { - layer_->InsertChild(static_cast<WebLayerImpl*>(child)->layer(), index); -} - -void WebLayerImpl::ReplaceChild(WebLayer* reference, WebLayer* new_layer) { - layer_->ReplaceChild(static_cast<WebLayerImpl*>(reference)->layer(), - static_cast<WebLayerImpl*>(new_layer)->layer()); -} - -void WebLayerImpl::RemoveFromParent() { - layer_->RemoveFromParent(); -} - -void WebLayerImpl::RemoveAllChildren() { - layer_->RemoveAllChildren(); -} - -void WebLayerImpl::SetBounds(const WebSize& size) { - layer_->SetBounds(size); -} - -WebSize WebLayerImpl::Bounds() const { - return layer_->bounds(); -} - -void WebLayerImpl::SetMasksToBounds(bool masks_to_bounds) { - layer_->SetMasksToBounds(masks_to_bounds); -} - -bool WebLayerImpl::MasksToBounds() const { - return layer_->masks_to_bounds(); -} - -void WebLayerImpl::SetMaskLayer(WebLayer* maskLayer) { - layer_->SetMaskLayer( - maskLayer ? static_cast<WebLayerImpl*>(maskLayer)->layer() : nullptr); -} - -void WebLayerImpl::SetOpacity(float opacity) { - layer_->SetOpacity(opacity); -} - -float WebLayerImpl::Opacity() const { - return layer_->opacity(); -} - -void WebLayerImpl::SetBlendMode(blink::WebBlendMode blend_mode) { - layer_->SetBlendMode(BlendModeToSkia(blend_mode)); -} - -blink::WebBlendMode WebLayerImpl::BlendMode() const { - return BlendModeFromSkia(layer_->blend_mode()); -} - -void WebLayerImpl::SetIsRootForIsolatedGroup(bool isolate) { - layer_->SetIsRootForIsolatedGroup(isolate); -} - -bool WebLayerImpl::IsRootForIsolatedGroup() { - return layer_->is_root_for_isolated_group(); -} - -void WebLayerImpl::SetHitTestableWithoutDrawsContent(bool should_hit_test) { - layer_->SetHitTestableWithoutDrawsContent(should_hit_test); -} - -void WebLayerImpl::SetOpaque(bool opaque) { - if (contents_opaque_is_fixed_) - return; - layer_->SetContentsOpaque(opaque); -} - -bool WebLayerImpl::Opaque() const { - return layer_->contents_opaque(); -} - -void WebLayerImpl::SetPosition(const WebFloatPoint& position) { - layer_->SetPosition(position); -} - -WebFloatPoint WebLayerImpl::GetPosition() const { - return layer_->position(); -} - -void WebLayerImpl::SetTransform(const SkMatrix44& matrix) { - gfx::Transform transform; - transform.matrix() = matrix; - layer_->SetTransform(transform); -} - -void WebLayerImpl::SetTransformOrigin(const blink::WebFloatPoint3D& point) { - gfx::Point3F gfx_point = point; - layer_->SetTransformOrigin(gfx_point); -} - -blink::WebFloatPoint3D WebLayerImpl::TransformOrigin() const { - return layer_->transform_origin(); -} - -SkMatrix44 WebLayerImpl::Transform() const { - return layer_->transform().matrix(); -} - -void WebLayerImpl::SetDrawsContent(bool draws_content) { - layer_->SetIsDrawable(draws_content); -} - -bool WebLayerImpl::DrawsContent() const { - return layer_->DrawsContent(); -} - -void WebLayerImpl::SetDoubleSided(bool double_sided) { - layer_->SetDoubleSided(double_sided); -} - -void WebLayerImpl::SetShouldFlattenTransform(bool flatten) { - layer_->SetShouldFlattenTransform(flatten); -} - -void WebLayerImpl::SetRenderingContext(int context) { - layer_->Set3dSortingContextId(context); -} - -void WebLayerImpl::SetUseParentBackfaceVisibility( - bool use_parent_backface_visibility) { - layer_->SetUseParentBackfaceVisibility(use_parent_backface_visibility); -} - -void WebLayerImpl::SetBackgroundColor(WebColor color) { - layer_->SetBackgroundColor(color); -} - -WebColor WebLayerImpl::BackgroundColor() const { - return layer_->background_color(); -} - -void WebLayerImpl::SetFilters(const cc::FilterOperations& filters) { - layer_->SetFilters(filters); -} - -void WebLayerImpl::SetFiltersOrigin(const blink::WebFloatPoint& origin) { - layer_->SetFiltersOrigin(origin); -} - -void WebLayerImpl::SetBackgroundFilters(const cc::FilterOperations& filters) { - layer_->SetBackgroundFilters(filters); -} - -bool WebLayerImpl::HasTickingAnimationForTesting() { - return layer_->HasTickingAnimationForTesting(); -} - -void WebLayerImpl::SetScrollable(const blink::WebSize& size) { - layer_->SetScrollable(size); -} - -void WebLayerImpl::SetScrollPosition(blink::WebFloatPoint position) { - layer_->SetScrollOffset(gfx::ScrollOffset(position.x, position.y)); -} - -blink::WebFloatPoint WebLayerImpl::ScrollPosition() const { - return blink::WebFloatPoint(layer_->scroll_offset().x(), - layer_->scroll_offset().y()); -} - -bool WebLayerImpl::Scrollable() const { - return layer_->scrollable(); -} - -blink::WebSize WebLayerImpl::ScrollContainerBoundsForTesting() const { - return layer_->scroll_container_bounds(); -} - -void WebLayerImpl::SetUserScrollable(bool horizontal, bool vertical) { - layer_->SetUserScrollable(horizontal, vertical); -} - -bool WebLayerImpl::UserScrollableHorizontal() const { - return layer_->user_scrollable_horizontal(); -} - -bool WebLayerImpl::UserScrollableVertical() const { - return layer_->user_scrollable_vertical(); -} - -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. - DCHECK(main_thread_scrolling_reasons); - DCHECK(cc::MainThreadScrollingReason::MainThreadCanSetScrollReasons( - main_thread_scrolling_reasons)); - layer_->AddMainThreadScrollingReasons(main_thread_scrolling_reasons); -} - -void WebLayerImpl::ClearMainThreadScrollingReasons( - uint32_t main_thread_scrolling_reasons_to_clear) { - layer_->ClearMainThreadScrollingReasons( - main_thread_scrolling_reasons_to_clear); -} - -uint32_t WebLayerImpl::MainThreadScrollingReasons() { - return layer_->main_thread_scrolling_reasons(); -} - -bool WebLayerImpl::ShouldScrollOnMainThread() const { - return layer_->should_scroll_on_main_thread(); -} - -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 { - size_t num_rects = 0; - for (gfx::Rect rect : layer_->non_fast_scrollable_region()) { - ALLOW_UNUSED_LOCAL(rect); - ++num_rects; - } - - WebVector<WebRect> result(num_rects); - size_t i = 0; - for (gfx::Rect rect : layer_->non_fast_scrollable_region()) { - result[i] = rect; - ++i; - } - return result; -} - -void WebLayerImpl::SetTouchEventHandlerRegion( - const WebVector<blink::WebTouchInfo>& touch_info) { - base::flat_map<blink::WebTouchAction, cc::Region> region_map; - for (size_t i = 0; i < touch_info.size(); ++i) - region_map[touch_info[i].touch_action].Union(touch_info[i].rect); - layer_->SetTouchActionRegion(cc::TouchActionRegion(region_map)); -} - -WebVector<WebRect> WebLayerImpl::TouchEventHandlerRegion() const { - size_t num_rects = 0; - for (gfx::Rect rect : layer_->touch_action_region().region()) { - ALLOW_UNUSED_LOCAL(rect); - ++num_rects; - } - - WebVector<WebRect> result(num_rects); - size_t i = 0; - for (gfx::Rect rect : layer_->touch_action_region().region()) { - result[i] = rect; - ++i; - } - return result; -} - -WebVector<WebRect> -WebLayerImpl::TouchEventHandlerRegionForTouchActionForTesting( - cc::TouchAction touch_action) const { - size_t num_rects = 0; - for (gfx::Rect rect : - layer_->touch_action_region().GetRegionForTouchAction(touch_action)) { - ALLOW_UNUSED_LOCAL(rect); - ++num_rects; - } - - WebVector<WebRect> result(num_rects); - size_t i = 0; - for (gfx::Rect rect : - layer_->touch_action_region().GetRegionForTouchAction(touch_action)) { - result[i] = rect; - ++i; - } - return result; -} - -void WebLayerImpl::SetIsContainerForFixedPositionLayers(bool enable) { - layer_->SetIsContainerForFixedPositionLayers(enable); -} - -bool WebLayerImpl::IsContainerForFixedPositionLayers() const { - return layer_->IsContainerForFixedPositionLayers(); -} - -void WebLayerImpl::SetIsResizedByBrowserControls(bool enable) { - layer_->SetIsResizedByBrowserControls(enable); -} - -static blink::WebLayerPositionConstraint ToWebLayerPositionConstraint( - const cc::LayerPositionConstraint& constraint) { - blink::WebLayerPositionConstraint web_constraint; - 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.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( - const blink::WebLayerPositionConstraint& constraint) { - layer_->SetPositionConstraint(ToLayerPositionConstraint(constraint)); -} - -blink::WebLayerPositionConstraint WebLayerImpl::PositionConstraint() const { - return ToWebLayerPositionConstraint(layer_->position_constraint()); -} - -static blink::WebLayerStickyPositionConstraint -ToWebLayerStickyPositionConstraint( - const cc::LayerStickyPositionConstraint& constraint) { - blink::WebLayerStickyPositionConstraint web_constraint; - 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.scroll_container_relative_sticky_box_rect = - constraint.scroll_container_relative_sticky_box_rect; - web_constraint.scroll_container_relative_containing_block_rect = - constraint.scroll_container_relative_containing_block_rect; - web_constraint.nearest_element_shifting_sticky_box = - constraint.nearest_element_shifting_sticky_box; - web_constraint.nearest_element_shifting_containing_block = - constraint.nearest_element_shifting_containing_block; - return web_constraint; -} -static cc::LayerStickyPositionConstraint ToStickyPositionConstraint( - const blink::WebLayerStickyPositionConstraint& web_constraint) { - cc::LayerStickyPositionConstraint constraint; - 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.scroll_container_relative_sticky_box_rect = - web_constraint.scroll_container_relative_sticky_box_rect; - constraint.scroll_container_relative_containing_block_rect = - web_constraint.scroll_container_relative_containing_block_rect; - constraint.nearest_element_shifting_sticky_box = - web_constraint.nearest_element_shifting_sticky_box; - constraint.nearest_element_shifting_containing_block = - web_constraint.nearest_element_shifting_containing_block; - return constraint; -} -void WebLayerImpl::SetStickyPositionConstraint( - const blink::WebLayerStickyPositionConstraint& constraint) { - layer_->SetStickyPositionConstraint(ToStickyPositionConstraint(constraint)); -} -blink::WebLayerStickyPositionConstraint WebLayerImpl::StickyPositionConstraint() - const { - return ToWebLayerStickyPositionConstraint( - layer_->sticky_position_constraint()); -} - -void WebLayerImpl::SetScrollClient(blink::WebLayerScrollClient* scroll_client) { - if (scroll_client) { - layer_->set_did_scroll_callback( - base::Bind(&blink::WebLayerScrollClient::DidScroll, - base::Unretained(scroll_client))); - } else { - layer_->set_did_scroll_callback( - base::Callback<void(const gfx::ScrollOffset&, const cc::ElementId&)>()); - } -} - -void WebLayerImpl::SetScrollOffsetFromImplSideForTesting( - const gfx::ScrollOffset& offset) { - layer_->SetScrollOffsetFromImplSide(offset); -} - -void WebLayerImpl::SetLayerClient(base::WeakPtr<cc::LayerClient> client) { - layer_->SetLayerClient(std::move(client)); -} - -const cc::Layer* WebLayerImpl::CcLayer() const { - return layer_.get(); -} - -cc::Layer* WebLayerImpl::CcLayer() { - return layer_.get(); -} - -void WebLayerImpl::SetElementId(const cc::ElementId& id) { - layer_->SetElementId(id); -} - -cc::ElementId WebLayerImpl::GetElementId() const { - return layer_->element_id(); -} - -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) { - cc::Layer* clip_parent = nullptr; - if (parent) - clip_parent = static_cast<WebLayerImpl*>(parent)->layer(); - layer_->SetClipParent(clip_parent); -} - -Layer* WebLayerImpl::layer() const { - return layer_.get(); -} - -void WebLayerImpl::SetContentsOpaqueIsFixed(bool fixed) { - contents_opaque_is_fixed_ = fixed; -} - -void WebLayerImpl::SetHasWillChangeTransformHint(bool has_will_change) { - layer_->SetHasWillChangeTransformHint(has_will_change); -} - -void WebLayerImpl::ShowScrollbars() { - layer_->ShowScrollbars(); -} - -void WebLayerImpl::SetOverscrollBehavior( - const blink::WebOverscrollBehavior& behavior) { - layer_->SetOverscrollBehavior(static_cast<cc::OverscrollBehavior>(behavior)); -} - -void WebLayerImpl::SetSnapContainerData( - base::Optional<cc::SnapContainerData> data) { - layer_->SetSnapContainerData(std::move(data)); -} - -} // namespace cc_blink diff --git a/chromium/cc/blink/web_layer_impl.h b/chromium/cc/blink/web_layer_impl.h deleted file mode 100644 index 9be421d303f..00000000000 --- a/chromium/cc/blink/web_layer_impl.h +++ /dev/null @@ -1,149 +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_BLINK_WEB_LAYER_IMPL_H_ -#define CC_BLINK_WEB_LAYER_IMPL_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <memory> -#include <string> -#include <utility> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "cc/blink/cc_blink_export.h" -#include "cc/layers/layer_client.h" -#include "third_party/blink/public/platform/web_color.h" -#include "third_party/blink/public/platform/web_double_point.h" -#include "third_party/blink/public/platform/web_float_point.h" -#include "third_party/blink/public/platform/web_float_size.h" -#include "third_party/blink/public/platform/web_layer.h" -#include "third_party/blink/public/platform/web_point.h" -#include "third_party/blink/public/platform/web_rect.h" -#include "third_party/blink/public/platform/web_size.h" -#include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/skia/include/core/SkMatrix44.h" - -namespace cc { -class FilterOperations; -class Layer; -} - -namespace cc_blink { - -class CC_BLINK_EXPORT WebLayerImpl : public blink::WebLayer { - public: - WebLayerImpl(); - explicit WebLayerImpl(scoped_refptr<cc::Layer>); - ~WebLayerImpl() override; - - cc::Layer* layer() const; - - // 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, - 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 SetContentsOpaqueIsFixed(bool fixed) override; - - void SetBlendMode(blink::WebBlendMode blend_mode) override; - blink::WebBlendMode BlendMode() const override; - void SetIsRootForIsolatedGroup(bool root) override; - bool IsRootForIsolatedGroup() override; - void SetHitTestableWithoutDrawsContent(bool should_hit_test) 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 SetScrollable(const blink::WebSize&) override; - blink::WebSize ScrollContainerBoundsForTesting() const override; - void SetScrollPosition(blink::WebFloatPoint position) override; - blink::WebFloatPoint ScrollPosition() const 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( - uint32_t main_thread_scrolling_reasons_to_clear) override; - 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( - const blink::WebVector<blink::WebTouchInfo>& touch_info) override; - blink::WebVector<blink::WebRect> TouchEventHandlerRegion() const override; - blink::WebVector<blink::WebRect> - TouchEventHandlerRegionForTouchActionForTesting( - cc::TouchAction) const override; - void SetIsContainerForFixedPositionLayers(bool is_container) override; - bool IsContainerForFixedPositionLayers() const override; - void SetIsResizedByBrowserControls(bool) override; - void SetPositionConstraint( - const blink::WebLayerPositionConstraint& constraint) override; - blink::WebLayerPositionConstraint PositionConstraint() const override; - void SetStickyPositionConstraint( - const blink::WebLayerStickyPositionConstraint& constraint) override; - blink::WebLayerStickyPositionConstraint StickyPositionConstraint() - const override; - void SetScrollClient(blink::WebLayerScrollClient* client) override; - void SetScrollOffsetFromImplSideForTesting(const gfx::ScrollOffset&) override; - void SetLayerClient(base::WeakPtr<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 SetHasWillChangeTransformHint(bool has_will_change) override; - void ShowScrollbars() override; - void SetOverscrollBehavior(const blink::WebOverscrollBehavior&) override; - void SetSnapContainerData(base::Optional<cc::SnapContainerData>) override; - - void SetScrollParent(blink::WebLayer* parent) override; - void SetClipParent(blink::WebLayer* parent) override; - - protected: - scoped_refptr<cc::Layer> layer_; - - bool contents_opaque_is_fixed_; - - private: - DISALLOW_COPY_AND_ASSIGN(WebLayerImpl); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_LAYER_IMPL_H_ diff --git a/chromium/cc/blink/web_layer_impl_fixed_bounds.cc b/chromium/cc/blink/web_layer_impl_fixed_bounds.cc deleted file mode 100644 index dc6b90993c4..00000000000 --- a/chromium/cc/blink/web_layer_impl_fixed_bounds.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/blink/web_layer_impl_fixed_bounds.h" - -#include "cc/layers/layer.h" -#include "third_party/blink/public/platform/web_float_point.h" -#include "third_party/blink/public/platform/web_size.h" -#include "third_party/skia/include/core/SkMatrix44.h" - -using cc::Layer; - -namespace cc_blink { - -WebLayerImplFixedBounds::WebLayerImplFixedBounds() = default; - -WebLayerImplFixedBounds::WebLayerImplFixedBounds(scoped_refptr<Layer> layer) - : WebLayerImpl(layer) { -} - -WebLayerImplFixedBounds::~WebLayerImplFixedBounds() = default; - -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(); -} - -void WebLayerImplFixedBounds::SetTransformOrigin( - const blink::WebFloatPoint3D& transform_origin) { - if (transform_origin != this->TransformOrigin()) { - layer_->SetTransformOrigin(transform_origin); - UpdateLayerBoundsAndTransform(); - } -} - -void WebLayerImplFixedBounds::SetBounds(const blink::WebSize& bounds) { - if (original_bounds_ != gfx::Size(bounds)) { - original_bounds_ = bounds; - UpdateLayerBoundsAndTransform(); - } -} - -blink::WebSize WebLayerImplFixedBounds::Bounds() const { - return original_bounds_; -} - -void WebLayerImplFixedBounds::SetTransform(const SkMatrix44& matrix) { - gfx::Transform transform; - transform.matrix() = matrix; - SetTransformInternal(transform); -} - -SkMatrix44 WebLayerImplFixedBounds::Transform() const { - return original_transform_.matrix(); -} - -void WebLayerImplFixedBounds::SetFixedBounds(gfx::Size fixed_bounds) { - if (fixed_bounds_ != fixed_bounds) { - fixed_bounds_ = fixed_bounds; - UpdateLayerBoundsAndTransform(); - } -} - -void WebLayerImplFixedBounds::SetTransformInternal( - const gfx::Transform& transform) { - if (original_transform_ != transform) { - original_transform_ = transform; - UpdateLayerBoundsAndTransform(); - } -} - -void WebLayerImplFixedBounds::UpdateLayerBoundsAndTransform() { - if (fixed_bounds_.IsEmpty() || original_bounds_.IsEmpty() || - 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) { - layer_->SetBounds(original_bounds_); - layer_->SetTransform(original_transform_); - return; - } - - layer_->SetBounds(fixed_bounds_); - - // Apply bounds scale (bounds/fixed_bounds) over original transform. - gfx::Transform transform_with_bounds_scale(original_transform_); - float bounds_scale_x = - static_cast<float>(original_bounds_.width()) / fixed_bounds_.width(); - float bounds_scale_y = - static_cast<float>(original_bounds_.height()) / fixed_bounds_.height(); - transform_with_bounds_scale.Scale(bounds_scale_x, bounds_scale_y); - layer_->SetTransform(transform_with_bounds_scale); -} - -} // namespace cc_blink diff --git a/chromium/cc/blink/web_layer_impl_fixed_bounds.h b/chromium/cc/blink/web_layer_impl_fixed_bounds.h deleted file mode 100644 index 949e47d5434..00000000000 --- a/chromium/cc/blink/web_layer_impl_fixed_bounds.h +++ /dev/null @@ -1,51 +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_BLINK_WEB_LAYER_IMPL_FIXED_BOUNDS_H_ -#define CC_BLINK_WEB_LAYER_IMPL_FIXED_BOUNDS_H_ - -#include "base/macros.h" -#include "cc/blink/web_layer_impl.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gfx/transform.h" - -namespace cc_blink { - -// A special implementation of WebLayerImpl for layers that its contents -// need to be automatically scaled when the bounds changes. The compositor -// can efficiently handle the bounds change of such layers if the bounds -// is fixed to a given value and the change of bounds are converted to -// transformation scales. -class CC_BLINK_EXPORT WebLayerImplFixedBounds : public WebLayerImpl { - public: - WebLayerImplFixedBounds(); - explicit WebLayerImplFixedBounds(scoped_refptr<cc::Layer> layer); - ~WebLayerImplFixedBounds() override; - - // WebLayerImpl overrides. - 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 SetFixedBounds(gfx::Size bounds); - - protected: - void SetTransformInternal(const gfx::Transform& transform); - void UpdateLayerBoundsAndTransform(); - - gfx::Transform original_transform_; - gfx::Size original_bounds_; - gfx::Size fixed_bounds_; - - private: - DISALLOW_COPY_AND_ASSIGN(WebLayerImplFixedBounds); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_LAYER_IMPL_FIXED_BOUNDS_H_ diff --git a/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc b/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc deleted file mode 100644 index 354326e36aa..00000000000 --- a/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc +++ /dev/null @@ -1,181 +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/blink/web_layer_impl_fixed_bounds.h" -#include <vector> -#include "cc/animation/animation_host.h" -#include "cc/layers/picture_image_layer.h" -#include "cc/test/fake_layer_tree_host.h" -#include "cc/test/geometry_test_utils.h" -#include "cc/test/test_task_graph_runner.h" -#include "cc/trees/layer_tree_host_common.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/web_float_point.h" -#include "third_party/blink/public/platform/web_size.h" -#include "third_party/skia/include/core/SkMatrix44.h" -#include "ui/gfx/geometry/point3_f.h" - -using blink::WebFloatPoint; -using blink::WebSize; - -namespace cc_blink { -namespace { - -TEST(WebLayerImplFixedBoundsTest, IdentityBounds) { - WebLayerImplFixedBounds layer; - layer.SetFixedBounds(gfx::Size(100, 100)); - 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()); -} - -gfx::Point3F TransformPoint(const gfx::Transform& transform, - const gfx::Point3F& point) { - gfx::Point3F result = point; - transform.TransformPoint(&result); - return result; -} - -void CheckBoundsScaleSimple(WebLayerImplFixedBounds* layer, - const WebSize& bounds, - const gfx::Size& fixed_bounds) { - layer->SetBounds(bounds); - layer->SetFixedBounds(fixed_bounds); - - EXPECT_EQ(bounds, layer->Bounds()); - EXPECT_EQ(fixed_bounds, layer->layer()->bounds()); - EXPECT_TRUE(layer->Transform().isIdentity()); - - // An arbitrary point to check the scale and transforms. - gfx::Point3F original_point(10, 20, 1); - gfx::Point3F scaled_point( - original_point.x() * bounds.width / fixed_bounds.width(), - original_point.y() * bounds.height / fixed_bounds.height(), - original_point.z()); - // Test if the bounds scale is correctly applied in transform. - EXPECT_POINT3F_EQ(scaled_point, TransformPoint(layer->layer()->transform(), - original_point)); -} - -TEST(WebLayerImplFixedBoundsTest, BoundsScaleSimple) { - WebLayerImplFixedBounds layer; - CheckBoundsScaleSimple(&layer, WebSize(100, 200), gfx::Size(150, 250)); - // Change fixed_bounds. - CheckBoundsScaleSimple(&layer, WebSize(100, 200), gfx::Size(75, 100)); - // Change bounds. - CheckBoundsScaleSimple(&layer, WebSize(300, 100), gfx::Size(75, 100)); -} - -void ExpectEqualLayerRectsInTarget(cc::Layer* layer1, cc::Layer* layer2) { - gfx::RectF layer1_rect_in_target(gfx::SizeF(layer1->bounds())); - layer1->ScreenSpaceTransform().TransformRect(&layer1_rect_in_target); - - gfx::RectF layer2_rect_in_target(gfx::SizeF(layer2->bounds())); - layer2->ScreenSpaceTransform().TransformRect(&layer2_rect_in_target); - - EXPECT_FLOAT_RECT_EQ(layer1_rect_in_target, layer2_rect_in_target); -} - -void CompareFixedBoundsLayerAndNormalLayer(const WebFloatPoint& anchor_point, - const gfx::Transform& transform) { - const gfx::Size kDeviceViewportSize(800, 600); - const float kDeviceScaleFactor = 2.f; - const float kPageScaleFactor = 1.5f; - - WebSize bounds(150, 200); - WebFloatPoint position(20, 30); - gfx::Size fixed_bounds(160, 70); - - WebLayerImplFixedBounds root_layer; - - WebLayerImplFixedBounds fixed_bounds_layer(cc::PictureImageLayer::Create()); - fixed_bounds_layer.SetBounds(bounds); - fixed_bounds_layer.SetFixedBounds(fixed_bounds); - fixed_bounds_layer.SetTransform(transform.matrix()); - fixed_bounds_layer.SetPosition(position); - root_layer.AddChild(&fixed_bounds_layer); - - WebLayerImpl normal_layer(cc::PictureImageLayer::Create()); - - 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); - - cc::FakeLayerTreeHostClient client; - cc::TestTaskGraphRunner task_graph_runner; - std::unique_ptr<cc::FakeLayerTreeHost> host = cc::FakeLayerTreeHost::Create( - &client, &task_graph_runner, animation_host.get()); - host->SetRootLayer(root_layer.layer()); - - { - cc::LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root_layer.layer(), kDeviceViewportSize); - inputs.device_scale_factor = kDeviceScaleFactor; - inputs.page_scale_factor = kPageScaleFactor; - inputs.page_scale_layer = root_layer.layer(), - cc::LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); - - ExpectEqualLayerRectsInTarget(normal_layer.layer(), - fixed_bounds_layer.layer()); - } - - // Change of fixed bounds should not affect the target geometries. - fixed_bounds_layer.SetFixedBounds( - gfx::Size(fixed_bounds.width() / 2, fixed_bounds.height() * 2)); - - { - cc::LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( - root_layer.layer(), kDeviceViewportSize); - inputs.device_scale_factor = kDeviceScaleFactor; - inputs.page_scale_factor = kPageScaleFactor; - inputs.page_scale_layer = root_layer.layer(), - cc::LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); - - ExpectEqualLayerRectsInTarget(normal_layer.layer(), - fixed_bounds_layer.layer()); - } -} - -// TODO(perkj): CompareToWebLayerImplSimple disabled on LSAN due to crbug/386080 -#if defined(LEAK_SANITIZER) -#define MAYBE_CompareToWebLayerImplSimple DISABLED_CompareToWebLayerImplSimple -#else -#define MAYBE_CompareToWebLayerImplSimple CompareToWebLayerImplSimple -#endif -// A black box test that ensures WebLayerImplFixedBounds won't change target -// geometries. Simple case: identity transforms and zero anchor point. -TEST(WebLayerImplFixedBoundsTest, MAYBE_CompareToWebLayerImplSimple) { - CompareFixedBoundsLayerAndNormalLayer(WebFloatPoint(0, 0), gfx::Transform()); -} - -// TODO(perkj): CompareToWebLayerImplComplex disabled on LSAN due to -// crbug/386080 -#if defined(LEAK_SANITIZER) -#define MAYBE_CompareToWebLayerImplComplex DISABLED_CompareToWebLayerImplComplex -#else -#define MAYBE_CompareToWebLayerImplComplex CompareToWebLayerImplComplex -#endif -// A black box test that ensures WebLayerImplFixedBounds won't change target -// geometries. Complex case: complex transforms and non-zero anchor point. -TEST(WebLayerImplFixedBoundsTest, MAYBE_CompareToWebLayerImplComplex) { - gfx::Transform transform; - // These are arbitrary values that should not affect the results. - transform.Translate3d(50, 60, 70); - transform.Scale3d(2, 3, 4); - transform.RotateAbout(gfx::Vector3dF(33, 44, 55), 99); - - CompareFixedBoundsLayerAndNormalLayer(WebFloatPoint(0, 0), transform); - - // With non-zero anchor point, WebLayerImplFixedBounds will fall back to - // WebLayerImpl. - CompareFixedBoundsLayerAndNormalLayer(WebFloatPoint(0.4f, 0.6f), transform); -} - -} // namespace -} // namespace cc_blink diff --git a/chromium/cc/blink/web_scrollbar_layer_impl.cc b/chromium/cc/blink/web_scrollbar_layer_impl.cc deleted file mode 100644 index f501002d486..00000000000 --- a/chromium/cc/blink/web_scrollbar_layer_impl.cc +++ /dev/null @@ -1,80 +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/blink/web_scrollbar_layer_impl.h" - -#include <utility> - -#include "cc/blink/scrollbar_impl.h" -#include "cc/blink/web_layer_impl.h" -#include "cc/layers/layer.h" -#include "cc/layers/painted_overlay_scrollbar_layer.h" -#include "cc/layers/painted_scrollbar_layer.h" -#include "cc/layers/scrollbar_layer_interface.h" -#include "cc/layers/solid_color_scrollbar_layer.h" -#include "cc/trees/element_id.h" - -using cc::PaintedOverlayScrollbarLayer; -using cc::PaintedScrollbarLayer; -using cc::SolidColorScrollbarLayer; - -namespace { - -cc::ScrollbarOrientation ConvertOrientation( - blink::WebScrollbar::Orientation orientation) { - return orientation == blink::WebScrollbar::kHorizontal ? cc::HORIZONTAL - : cc::VERTICAL; -} - -} // namespace - -namespace cc_blink { - -WebScrollbarLayerImpl::WebScrollbarLayerImpl( - std::unique_ptr<blink::WebScrollbar> scrollbar, - blink::WebScrollbarThemePainter painter, - std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry, - bool is_overlay) - : layer_(is_overlay - ? new WebLayerImpl(PaintedOverlayScrollbarLayer::Create( - std::make_unique<ScrollbarImpl>(std::move(scrollbar), - painter, - std::move(geometry)), - cc::ElementId())) - : new WebLayerImpl(PaintedScrollbarLayer::Create( - std::make_unique<ScrollbarImpl>(std::move(scrollbar), - painter, - std::move(geometry)), - cc::ElementId()))) {} - -WebScrollbarLayerImpl::WebScrollbarLayerImpl( - blink::WebScrollbar::Orientation orientation, - int thumb_thickness, - int track_start, - bool is_left_side_vertical_scrollbar) - : layer_(new WebLayerImpl( - SolidColorScrollbarLayer::Create(ConvertOrientation(orientation), - thumb_thickness, - track_start, - is_left_side_vertical_scrollbar, - cc::ElementId()))) {} - -WebScrollbarLayerImpl::~WebScrollbarLayerImpl() = default; - -blink::WebLayer* WebScrollbarLayerImpl::Layer() { - return layer_.get(); -} - -void WebScrollbarLayerImpl::SetScrollLayer(blink::WebLayer* layer) { - cc::Layer* scroll_layer = - layer ? static_cast<WebLayerImpl*>(layer)->layer() : nullptr; - layer_->layer()->ToScrollbarLayer()->SetScrollElementId( - scroll_layer ? scroll_layer->element_id() : cc::ElementId()); -} - -void WebScrollbarLayerImpl::SetElementId(const cc::ElementId& element_id) { - layer_->SetElementId(element_id); -} - -} // namespace cc_blink diff --git a/chromium/cc/blink/web_scrollbar_layer_impl.h b/chromium/cc/blink/web_scrollbar_layer_impl.h deleted file mode 100644 index c80c31df230..00000000000 --- a/chromium/cc/blink/web_scrollbar_layer_impl.h +++ /dev/null @@ -1,52 +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_BLINK_WEB_SCROLLBAR_LAYER_IMPL_H_ -#define CC_BLINK_WEB_SCROLLBAR_LAYER_IMPL_H_ - -#include <memory> - -#include "base/macros.h" -#include "cc/blink/cc_blink_export.h" -#include "third_party/blink/public/platform/web_scrollbar.h" -#include "third_party/blink/public/platform/web_scrollbar_layer.h" - -namespace blink { -class WebScrollbarThemeGeometry; -class WebScrollbarThemePainter; -} - -namespace cc_blink { - -class WebLayerImpl; - -class WebScrollbarLayerImpl : public blink::WebScrollbarLayer { - public: - CC_BLINK_EXPORT WebScrollbarLayerImpl( - std::unique_ptr<blink::WebScrollbar> scrollbar, - blink::WebScrollbarThemePainter painter, - std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry, - bool is_overlay); - CC_BLINK_EXPORT WebScrollbarLayerImpl( - blink::WebScrollbar::Orientation orientation, - int thumb_thickness, - int track_start, - bool is_left_side_vertical_scrollbar); - ~WebScrollbarLayerImpl() override; - - // blink::WebScrollbarLayer implementation. - blink::WebLayer* Layer() override; - void SetScrollLayer(blink::WebLayer* layer) override; - - void SetElementId(const cc::ElementId&) override; - - private: - std::unique_ptr<WebLayerImpl> layer_; - - DISALLOW_COPY_AND_ASSIGN(WebScrollbarLayerImpl); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_SCROLLBAR_LAYER_IMPL_H_ diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h index 312f103e941..51bc8f74b94 100644 --- a/chromium/cc/input/input_handler.h +++ b/chromium/cc/input/input_handler.h @@ -50,8 +50,10 @@ struct CC_EXPORT InputHandlerScrollResult { // property scroll-boundary-behavior. OverscrollBehavior overscroll_behavior; // The current offset of the currently scrolling node. It is in DIP or - // physical pixels depending on the use-zoom-for-dsf flag. - gfx::Vector2dF current_offset; + // physical pixels depending on the use-zoom-for-dsf flag. If the currently + // scrolling node is the viewport, this would be the sum of the scroll offsets + // of the inner and outer node, representing the visual scroll offset. + gfx::Vector2dF current_visual_offset; }; class CC_EXPORT InputHandlerClient { diff --git a/chromium/cc/input/main_thread_scrolling_reason.cc b/chromium/cc/input/main_thread_scrolling_reason.cc new file mode 100644 index 00000000000..6653ac98fde --- /dev/null +++ b/chromium/cc/input/main_thread_scrolling_reason.cc @@ -0,0 +1,78 @@ +// Copyright 2018 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/input/main_thread_scrolling_reason.h" + +#include "base/stl_util.h" +#include "base/trace_event/trace_event_argument.h" + +namespace cc { + +std::string MainThreadScrollingReason::AsText(uint32_t reasons) { + base::trace_event::TracedValue traced_value; + AddToTracedValue(reasons, traced_value); + std::string result = traced_value.ToString(); + // Remove '{main_thread_scrolling_reasons:[', ']}', and any '"' chars. + size_t array_start_pos = result.find('['); + size_t array_end_pos = result.find(']'); + result = + result.substr(array_start_pos + 1, array_end_pos - array_start_pos - 1); + base::Erase(result, '\"'); + return result; +} + +void MainThreadScrollingReason::AddToTracedValue( + uint32_t reasons, + base::trace_event::TracedValue& traced_value) { + traced_value.BeginArray("main_thread_scrolling_reasons"); + + if (reasons & kHasBackgroundAttachmentFixedObjects) + traced_value.AppendString("Has background-attachment:fixed"); + if (reasons & kHasNonLayerViewportConstrainedObjects) + traced_value.AppendString("Has non-layer viewport-constrained objects"); + if (reasons & kThreadedScrollingDisabled) + traced_value.AppendString("Threaded scrolling is disabled"); + if (reasons & kScrollbarScrolling) + traced_value.AppendString("Scrollbar scrolling"); + if (reasons & kPageOverlay) + traced_value.AppendString("Page overlay"); + if (reasons & kHandlingScrollFromMainThread) + traced_value.AppendString("Handling scroll from main thread"); + if (reasons & kCustomScrollbarScrolling) + traced_value.AppendString("Custom scrollbar scrolling"); + if (reasons & kHasOpacityAndLCDText) + traced_value.AppendString("Has opacity and LCD text"); + if (reasons & kHasTransformAndLCDText) + traced_value.AppendString("Has transform and LCD text"); + if (reasons & kBackgroundNotOpaqueInRectAndLCDText) + traced_value.AppendString("Background is not opaque in rect and LCD text"); + if (reasons & kHasBorderRadius) + traced_value.AppendString("Has border radius"); + if (reasons & kHasClipRelatedProperty) + traced_value.AppendString("Has clip related property"); + if (reasons & kHasBoxShadowFromNonRootLayer) + traced_value.AppendString("Has box shadow from non-root layer"); + if (reasons & kIsNotStackingContextAndLCDText) + traced_value.AppendString("Is not stacking context and LCD text"); + + // Transient scrolling reasons. + if (reasons & kNonFastScrollableRegion) + traced_value.AppendString("Non fast scrollable region"); + if (reasons & kFailedHitTest) + traced_value.AppendString("Failed hit test"); + if (reasons & kNoScrollingLayer) + traced_value.AppendString("No scrolling layer"); + if (reasons & kNotScrollable) + traced_value.AppendString("Not scrollable"); + if (reasons & kContinuingMainThreadScroll) + traced_value.AppendString("Continuing main thread scroll"); + if (reasons & kNonInvertibleTransform) + traced_value.AppendString("Non-invertible transform"); + if (reasons & kPageBasedScrolling) + traced_value.AppendString("Page-based scrolling"); + + traced_value.EndArray(); +} + +} // namespace cc diff --git a/chromium/cc/input/main_thread_scrolling_reason.h b/chromium/cc/input/main_thread_scrolling_reason.h index e7d88471aff..b926c75117d 100644 --- a/chromium/cc/input/main_thread_scrolling_reason.h +++ b/chromium/cc/input/main_thread_scrolling_reason.h @@ -5,17 +5,22 @@ #ifndef CC_INPUT_MAIN_THREAD_SCROLLING_REASON_H_ #define CC_INPUT_MAIN_THREAD_SCROLLING_REASON_H_ +#include <memory> #include <string> +#include "cc/cc_export.h" -#include "base/stl_util.h" -#include "base/trace_event/trace_event_argument.h" +namespace base { +namespace trace_event { +class TracedValue; +} +} // namespace base namespace cc { // Ensure this stays in sync with MainThreadScrollingReason in histograms.xml. // When adding a new MainThreadScrollingReason, make sure the corresponding // [MainThread/Compositor]CanSetScrollReasons function is also updated. -struct MainThreadScrollingReason { +struct CC_EXPORT MainThreadScrollingReason { enum : uint32_t { // Non-transient scrolling reasons. kNotScrollingOnMain = 0, @@ -96,72 +101,9 @@ struct MainThreadScrollingReason { return (reasons & kNonCompositedReasons) != 0; } - static std::string mainThreadScrollingReasonsAsText(uint32_t reasons) { - base::trace_event::TracedValue tracedValue; - mainThreadScrollingReasonsAsTracedValue(reasons, &tracedValue); - std::string result_in_array_foramt = tracedValue.ToString(); - // Remove '{main_thread_scrolling_reasons:[', ']}', and any '"' chars. - std::string result = - result_in_array_foramt.substr(34, result_in_array_foramt.length() - 36); - base::Erase(result, '\"'); - return result; - } - - static void mainThreadScrollingReasonsAsTracedValue( - uint32_t reasons, - base::trace_event::TracedValue* tracedValue) { - tracedValue->BeginArray("main_thread_scrolling_reasons"); - if (reasons & - MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects) - tracedValue->AppendString("Has background-attachment:fixed"); - if (reasons & - MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects) - tracedValue->AppendString("Has non-layer viewport-constrained objects"); - if (reasons & MainThreadScrollingReason::kThreadedScrollingDisabled) - tracedValue->AppendString("Threaded scrolling is disabled"); - if (reasons & MainThreadScrollingReason::kScrollbarScrolling) - tracedValue->AppendString("Scrollbar scrolling"); - if (reasons & MainThreadScrollingReason::kPageOverlay) - tracedValue->AppendString("Page overlay"); - if (reasons & MainThreadScrollingReason::kHandlingScrollFromMainThread) - tracedValue->AppendString("Handling scroll from main thread"); - if (reasons & MainThreadScrollingReason::kCustomScrollbarScrolling) - tracedValue->AppendString("Custom scrollbar scrolling"); - if (reasons & MainThreadScrollingReason::kHasOpacityAndLCDText) - tracedValue->AppendString("Has opacity and LCD text"); - if (reasons & MainThreadScrollingReason::kHasTransformAndLCDText) - tracedValue->AppendString("Has transform and LCD text"); - if (reasons & - MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText) { - tracedValue->AppendString( - "Background is not opaque in rect and LCD text"); - } - if (reasons & MainThreadScrollingReason::kHasBorderRadius) - tracedValue->AppendString("Has border radius"); - if (reasons & MainThreadScrollingReason::kHasClipRelatedProperty) - tracedValue->AppendString("Has clip related property"); - if (reasons & MainThreadScrollingReason::kHasBoxShadowFromNonRootLayer) - tracedValue->AppendString("Has box shadow from non-root layer"); - if (reasons & MainThreadScrollingReason::kIsNotStackingContextAndLCDText) - tracedValue->AppendString("Is not stacking context and LCD text"); - - // Transient scrolling reasons. - if (reasons & MainThreadScrollingReason::kNonFastScrollableRegion) - tracedValue->AppendString("Non fast scrollable region"); - if (reasons & MainThreadScrollingReason::kFailedHitTest) - tracedValue->AppendString("Failed hit test"); - if (reasons & MainThreadScrollingReason::kNoScrollingLayer) - tracedValue->AppendString("No scrolling layer"); - if (reasons & MainThreadScrollingReason::kNotScrollable) - tracedValue->AppendString("Not scrollable"); - if (reasons & MainThreadScrollingReason::kContinuingMainThreadScroll) - tracedValue->AppendString("Continuing main thread scroll"); - if (reasons & MainThreadScrollingReason::kNonInvertibleTransform) - tracedValue->AppendString("Non-invertible transform"); - if (reasons & MainThreadScrollingReason::kPageBasedScrolling) - tracedValue->AppendString("Page-based scrolling"); - tracedValue->EndArray(); - } + static std::string AsText(uint32_t reasons); + static void AddToTracedValue(uint32_t reasons, + base::trace_event::TracedValue&); }; } // namespace cc diff --git a/chromium/cc/input/main_thread_scrolling_reason_unittest.cc b/chromium/cc/input/main_thread_scrolling_reason_unittest.cc new file mode 100644 index 00000000000..ec49ff98001 --- /dev/null +++ b/chromium/cc/input/main_thread_scrolling_reason_unittest.cc @@ -0,0 +1,38 @@ +// Copyright 2018 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/input/main_thread_scrolling_reason.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { + +using MainThreadScrollingReasonTest = testing::Test; + +TEST_F(MainThreadScrollingReasonTest, AsText) { + EXPECT_EQ("", MainThreadScrollingReason::AsText(0)); + EXPECT_EQ( + "Has background-attachment:fixed," + "Has non-layer viewport-constrained objects," + "Threaded scrolling is disabled," + "Scrollbar scrolling,Page overlay," + "Handling scroll from main thread," + "Custom scrollbar scrolling," + "Has opacity and LCD text," + "Has transform and LCD text," + "Background is not opaque in rect and LCD text," + "Has border radius,Has clip related property," + "Has box shadow from non-root layer," + "Is not stacking context and LCD text," + "Non fast scrollable region," + "Failed hit test," + "No scrolling layer," + "Not scrollable," + "Continuing main thread scroll," + "Non-invertible transform," + "Page-based scrolling", + MainThreadScrollingReason::AsText(0xffffffffu)); +} + +} // namespace cc diff --git a/chromium/cc/input/scrollbar_animation_controller_unittest.cc b/chromium/cc/input/scrollbar_animation_controller_unittest.cc index 9749fc77148..e9f336ff695 100644 --- a/chromium/cc/input/scrollbar_animation_controller_unittest.cc +++ b/chromium/cc/input/scrollbar_animation_controller_unittest.cc @@ -35,7 +35,7 @@ class MockScrollbarAnimationControllerClient public: explicit MockScrollbarAnimationControllerClient(LayerTreeHostImpl* host_impl) : host_impl_(host_impl) {} - virtual ~MockScrollbarAnimationControllerClient() = default; + ~MockScrollbarAnimationControllerClient() override = default; void PostDelayedScrollbarAnimationTask(const base::Closure& start_fade, base::TimeDelta delay) override { diff --git a/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc b/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc index b883b1d0c17..08ba96d79b5 100644 --- a/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc +++ b/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc @@ -35,7 +35,7 @@ class MockSingleScrollbarAnimationControllerClient explicit MockSingleScrollbarAnimationControllerClient( LayerTreeHostImpl* host_impl) : host_impl_(host_impl) {} - virtual ~MockSingleScrollbarAnimationControllerClient() = default; + ~MockSingleScrollbarAnimationControllerClient() override = default; ScrollbarSet ScrollbarsFor(ElementId scroll_element_id) const override { return host_impl_->ScrollbarsFor(scroll_element_id); diff --git a/chromium/cc/input/snap_fling_controller.cc b/chromium/cc/input/snap_fling_controller.cc new file mode 100644 index 00000000000..4c8e485bcff --- /dev/null +++ b/chromium/cc/input/snap_fling_controller.cc @@ -0,0 +1,92 @@ +// Copyright 2018 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/input/snap_fling_controller.h" + +#include "cc/input/snap_fling_curve.h" + +namespace cc { + +SnapFlingController::SnapFlingController(SnapFlingClient* client) + : client_(client), state_(State::kIdle) {} + +SnapFlingController::~SnapFlingController() = default; + +bool SnapFlingController::FilterEventForSnap( + SnapFlingController::GestureScrollType gesture_scroll_type) { + switch (gesture_scroll_type) { + case GestureScrollType::kBegin: { + ClearSnapFling(); + return false; + } + // TODO(sunyunjia): Need to update the existing snap curve if the GSU is + // from a fling boosting event. + case GestureScrollType::kUpdate: + case GestureScrollType::kEnd: { + return state_ == State::kActive || state_ == State::kFinished; + } + } +} + +void SnapFlingController::ClearSnapFling() { + if (state_ == State::kActive) + client_->ScrollEndForSnapFling(); + + curve_.reset(); + state_ = State::kIdle; +} + +bool SnapFlingController::HandleGestureScrollUpdate( + const SnapFlingController::GestureScrollUpdateInfo& info) { + DCHECK(state_ != State::kActive && state_ != State::kFinished); + if (state_ != State::kIdle) + return false; + + if (!info.is_in_inertial_phase) + return false; + + gfx::Vector2dF ending_displacement = + SnapFlingCurve::EstimateDisplacement(info.delta); + + gfx::Vector2dF target_offset, start_offset; + if (!client_->GetSnapFlingInfo(ending_displacement, &start_offset, + &target_offset)) { + state_ = State::kIgnored; + return false; + } + + if (start_offset == target_offset) { + state_ = State::kFinished; + return true; + } + + curve_ = std::make_unique<SnapFlingCurve>(start_offset, target_offset, + info.event_time); + state_ = State::kActive; + Animate(info.event_time); + return true; +} + +void SnapFlingController::Animate(base::TimeTicks time) { + if (state_ != State::kActive) + return; + + if (curve_->IsFinished()) { + client_->ScrollEndForSnapFling(); + state_ = State::kFinished; + return; + } + gfx::Vector2dF snapped_delta = curve_->GetScrollDelta(time); + gfx::Vector2dF current_offset = client_->ScrollByForSnapFling(snapped_delta); + curve_->UpdateCurrentOffset(current_offset); + client_->RequestAnimationForSnapFling(); +} + +void SnapFlingController::SetCurveForTest( + std::unique_ptr<SnapFlingCurve> curve) { + curve_ = std::move(curve); + state_ = State::kActive; +} + +} // namespace cc diff --git a/chromium/cc/input/snap_fling_controller.h b/chromium/cc/input/snap_fling_controller.h new file mode 100644 index 00000000000..5199b23faa6 --- /dev/null +++ b/chromium/cc/input/snap_fling_controller.h @@ -0,0 +1,106 @@ +// Copyright 2018 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_INPUT_SNAP_FLING_CONTROLLER_H_ +#define CC_INPUT_SNAP_FLING_CONTROLLER_H_ + +#include <memory> + +#include "base/time/time.h" +#include "cc/cc_export.h" +#include "ui/gfx/geometry/vector2d_f.h" + +namespace cc { +namespace test { +class SnapFlingControllerTest; +} + +class SnapFlingCurve; + +// A client that provides information to the controller. It also executes the +// scroll operations and requests animation frames. All the inputs and outputs +// are in the same coordinate space. +class SnapFlingClient { + public: + virtual bool GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement, + gfx::Vector2dF* initial_offset, + gfx::Vector2dF* target_offset) const = 0; + virtual gfx::Vector2dF ScrollByForSnapFling(const gfx::Vector2dF& delta) = 0; + virtual void ScrollEndForSnapFling() = 0; + virtual void RequestAnimationForSnapFling() = 0; +}; + +// SnapFlingController ensures that an incoming fling event (or inertial-phase +// scroll event) would land on a snap position if there is a valid one nearby. +// It takes an input event, filters it if it conflicts with the current fling, +// or generates a curve if the SnapFlingClient finds a valid snap position. +// It also animates the curve by notifying the client to scroll when clock +// ticks. +class CC_EXPORT SnapFlingController { + public: + enum class GestureScrollType { kBegin, kUpdate, kEnd }; + + struct GestureScrollUpdateInfo { + gfx::Vector2dF delta; + bool is_in_inertial_phase; + base::TimeTicks event_time; + }; + + explicit SnapFlingController(SnapFlingClient* client); + + static std::unique_ptr<SnapFlingController> CreateForTests( + SnapFlingClient* client, + std::unique_ptr<SnapFlingCurve> curve); + + ~SnapFlingController(); + + // Returns true if the event should be consumed for snapping and should not be + // processed further. + bool FilterEventForSnap(GestureScrollType gesture_scroll_type); + + // Creates the snap fling curve from the first inertial GSU. Returns true if + // the event if a snap fling curve has been created and the event should not + // be processed further. + bool HandleGestureScrollUpdate(const GestureScrollUpdateInfo& info); + + // Notifies the snap fling controller to update or end the scroll animation. + void Animate(base::TimeTicks time); + + private: + friend class test::SnapFlingControllerTest; + + enum class State { + // We haven't received an inertial GSU in this scroll sequence. + kIdle, + // We have received an inertial GSU but decided not to snap for this scroll + // sequence. + kIgnored, + // We have received an inertial GSU and decided to snap and animate it for + // this scroll sequence. So subsequent GSUs and GSE in the scroll sequence + // are consumed for snapping. + kActive, + // The animation of the snap fling has finished for this scroll sequence. + // Subsequent GSUs and GSE in the scroll sequence are ignored. + kFinished, + }; + + SnapFlingController(SnapFlingClient* client, + std::unique_ptr<SnapFlingCurve> curve); + void ClearSnapFling(); + + // Sets the |curve_| to |curve| and the |state| to |kActive|. + void SetCurveForTest(std::unique_ptr<SnapFlingCurve> curve); + + void SetActiveStateForTest() { state_ = State::kActive; } + + SnapFlingClient* client_; + State state_ = State::kIdle; + std::unique_ptr<SnapFlingCurve> curve_; + + DISALLOW_COPY_AND_ASSIGN(SnapFlingController); +}; + +} // namespace cc + +#endif // CC_INPUT_SNAP_FLING_CONTROLLER_H_ diff --git a/chromium/cc/input/snap_fling_controller_unittest.cc b/chromium/cc/input/snap_fling_controller_unittest.cc new file mode 100644 index 00000000000..5deb03cb565 --- /dev/null +++ b/chromium/cc/input/snap_fling_controller_unittest.cc @@ -0,0 +1,157 @@ +// Copyright 2018 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/input/snap_fling_controller.h" + +#include "cc/input/snap_fling_curve.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace test { +namespace { + +class MockSnapFlingClient : public SnapFlingClient { + public: + MOCK_CONST_METHOD3(GetSnapFlingInfo, + bool(const gfx::Vector2dF& natural_displacement, + gfx::Vector2dF* initial_offset, + gfx::Vector2dF* target_offset)); + MOCK_METHOD0(ScrollEndForSnapFling, void()); + MOCK_METHOD0(RequestAnimationForSnapFling, void()); + MOCK_METHOD1(ScrollByForSnapFling, gfx::Vector2dF(const gfx::Vector2dF&)); +}; + +class MockSnapFlingCurve : public SnapFlingCurve { + public: + MockSnapFlingCurve() + : SnapFlingCurve(gfx::Vector2dF(), + gfx::Vector2dF(0, 100), + base::TimeTicks()) {} + MOCK_CONST_METHOD0(IsFinished, bool()); + MOCK_METHOD1(GetScrollDelta, gfx::Vector2dF(base::TimeTicks)); +}; + +} // namespace + +class SnapFlingControllerTest : public testing::Test { + public: + SnapFlingControllerTest() { + controller_ = std::make_unique<SnapFlingController>(&mock_client_); + } + void SetCurve(std::unique_ptr<SnapFlingCurve> curve) { + controller_->SetCurveForTest(std::move(curve)); + } + void SetActiveState() { controller_->SetActiveStateForTest(); } + + protected: + testing::StrictMock<MockSnapFlingClient> mock_client_; + std::unique_ptr<SnapFlingController> controller_; +}; + +TEST_F(SnapFlingControllerTest, DoesNotFilterGSBWhenIdle) { + EXPECT_FALSE(controller_->FilterEventForSnap( + SnapFlingController::GestureScrollType::kBegin)); +} + +TEST_F(SnapFlingControllerTest, FiltersGSUAndGSEDependingOnState) { + // Should not filter GSU and GSE if the fling is not active. + EXPECT_FALSE(controller_->FilterEventForSnap( + SnapFlingController::GestureScrollType::kUpdate)); + EXPECT_FALSE(controller_->FilterEventForSnap( + SnapFlingController::GestureScrollType::kEnd)); + + // Should filter GSU and GSE if the fling is active. + SetActiveState(); + EXPECT_TRUE(controller_->FilterEventForSnap( + SnapFlingController::GestureScrollType::kUpdate)); + EXPECT_TRUE(controller_->FilterEventForSnap( + SnapFlingController::GestureScrollType::kEnd)); +} + +TEST_F(SnapFlingControllerTest, CreatesAndAnimatesCurveOnFirstInertialGSU) { + SnapFlingController::GestureScrollUpdateInfo gsu; + gsu.delta = gfx::Vector2dF(0, -10); + gsu.is_in_inertial_phase = true; + + EXPECT_CALL(mock_client_, + GetSnapFlingInfo(testing::_, testing::_, testing::_)) + .WillOnce(DoAll(testing::SetArgPointee<1>(gfx::Vector2dF(0, 0)), + testing::SetArgPointee<2>(gfx::Vector2dF(0, 100)), + testing::Return(true))); + EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(1); + EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(1); + EXPECT_TRUE(controller_->HandleGestureScrollUpdate(gsu)); + testing::Mock::VerifyAndClearExpectations(&mock_client_); +} + +TEST_F(SnapFlingControllerTest, DoesNotHandleNonInertialGSU) { + SnapFlingController::GestureScrollUpdateInfo gsu; + gsu.delta = gfx::Vector2dF(0, -10); + gsu.is_in_inertial_phase = false; + + EXPECT_CALL(mock_client_, + GetSnapFlingInfo(testing::_, testing::_, testing::_)) + .Times(0); + EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0); + EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0); + EXPECT_FALSE(controller_->HandleGestureScrollUpdate(gsu)); + testing::Mock::VerifyAndClearExpectations(&mock_client_); +} + +TEST_F(SnapFlingControllerTest, AnimatesTheCurve) { + std::unique_ptr<MockSnapFlingCurve> mock_curve = + std::make_unique<MockSnapFlingCurve>(); + MockSnapFlingCurve* curve = mock_curve.get(); + SetCurve(std::move(mock_curve)); + + EXPECT_CALL(*curve, IsFinished()).WillOnce(testing::Return(false)); + EXPECT_CALL(*curve, GetScrollDelta(testing::_)) + .WillOnce(testing::Return(gfx::Vector2dF(100, 100))); + EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(1); + EXPECT_CALL(mock_client_, ScrollByForSnapFling(gfx::Vector2dF(100, 100))); + controller_->Animate(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); + testing::Mock::VerifyAndClearExpectations(&mock_client_); + testing::Mock::VerifyAndClearExpectations(curve); +} + +TEST_F(SnapFlingControllerTest, FinishesTheCurve) { + std::unique_ptr<MockSnapFlingCurve> mock_curve = + std::make_unique<MockSnapFlingCurve>(); + MockSnapFlingCurve* curve = mock_curve.get(); + SetCurve(std::move(mock_curve)); + EXPECT_CALL(*curve, IsFinished()).WillOnce(testing::Return(true)); + EXPECT_CALL(*curve, GetScrollDelta(testing::_)).Times(0); + EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0); + EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0); + EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(1); + controller_->Animate(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); + testing::Mock::VerifyAndClearExpectations(curve); + testing::Mock::VerifyAndClearExpectations(&mock_client_); + + EXPECT_CALL(*curve, IsFinished()).Times(0); + EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0); + EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0); + EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(0); + controller_->Animate(base::TimeTicks() + base::TimeDelta::FromSeconds(2)); + testing::Mock::VerifyAndClearExpectations(curve); + testing::Mock::VerifyAndClearExpectations(&mock_client_); +} + +TEST_F(SnapFlingControllerTest, GSBNotFilteredAndResetsStateWhenActive) { + SetActiveState(); + EXPECT_TRUE(controller_->FilterEventForSnap( + SnapFlingController::GestureScrollType::kUpdate)); + + EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(1); + EXPECT_FALSE(controller_->FilterEventForSnap( + SnapFlingController::GestureScrollType::kBegin)); + testing::Mock::VerifyAndClearExpectations(&mock_client_); + + EXPECT_FALSE(controller_->FilterEventForSnap( + SnapFlingController::GestureScrollType::kUpdate)); +} + +} // namespace test +} // namespace cc diff --git a/chromium/cc/input/snap_fling_curve.cc b/chromium/cc/input/snap_fling_curve.cc new file mode 100644 index 00000000000..645c9c5440a --- /dev/null +++ b/chromium/cc/input/snap_fling_curve.cc @@ -0,0 +1,119 @@ +// Copyright 2018 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/input/snap_fling_curve.h" + +#include <cmath> +#include "build/build_config.h" + +namespace cc { +namespace { + +#if defined(OS_ANDROID) +constexpr double kDistanceEstimatorScalar = 40; +// The delta to be scrolled in next frame is 0.9 of the delta in last frame. +constexpr double kRatio = 0.9; +#else +constexpr double kDistanceEstimatorScalar = 25; +// The delta to be scrolled in next frame is 0.92 of the delta in last frame. +constexpr double kRatio = 0.92; +#endif +constexpr double kMsPerFrame = 16; +constexpr base::TimeDelta kMaximumSnapDuration = + base::TimeDelta::FromSecondsD(5); + +double GetDistanceFromDisplacement(gfx::Vector2dF displacement) { + return std::hypot(displacement.x(), displacement.y()); +} + +double EstimateFramesFromDistance(double distance) { + // We approximate scroll deltas as a geometric sequence with the ratio kRatio, + // and the last scrolled delta should be less or equal than 1, yielding the + // total distance as (1 - kRatio^(-n)) / (1 - (1 / kRatio)). Solving this + // could get n as below, which is the total number of deltas in the sequence, + // and is also the total frames needed to finish the curve. + return std::ceil(-std::log(1 - distance * (1 - 1 / kRatio)) / + std::log(kRatio)); +} + +double CalculateFirstDelta(double distance, double frames) { + // distance = first_delta (1 - kRatio^(frames) / (1 - kRatio)). + // We can get the |first_delta| by solving the equation above. + return distance * (1 - kRatio) / (1 - std::pow(kRatio, frames)); +} + +} // namespace + +gfx::Vector2dF SnapFlingCurve::EstimateDisplacement( + const gfx::Vector2dF& first_delta) { + gfx::Vector2dF destination = first_delta; + destination.Scale(kDistanceEstimatorScalar); + return destination; +} + +SnapFlingCurve::SnapFlingCurve(const gfx::Vector2dF& start_offset, + const gfx::Vector2dF& target_offset, + base::TimeTicks first_gsu_time) + : start_offset_(start_offset), + total_displacement_(target_offset - start_offset), + total_distance_(GetDistanceFromDisplacement(total_displacement_)), + start_time_(first_gsu_time), + total_frames_(EstimateFramesFromDistance(total_distance_)), + first_delta_(CalculateFirstDelta(total_distance_, total_frames_)), + duration_(base::TimeDelta::FromMilliseconds(total_frames_ * kMsPerFrame)), + is_finished_(total_distance_ == 0) { + if (is_finished_) + return; + ratio_x_ = total_displacement_.x() / total_distance_; + ratio_y_ = total_displacement_.y() / total_distance_; +} + +SnapFlingCurve::~SnapFlingCurve() = default; + +double SnapFlingCurve::GetCurrentCurveDistance(base::TimeTicks time_stamp) { + double current_distance = GetDistanceFromDisplacement(current_displacement_); + base::TimeDelta current_time = time_stamp - start_time_; + + // Finishes the curve if the time elapsed is longer than |duration_|, or the + // remaining distance is less than 1. + if (current_time >= duration_ || current_distance >= total_distance_ - 1) { + return total_distance_; + } + + double current_frame = current_time.InMillisecondsF() / kMsPerFrame + 1; + double sum = + first_delta_ * (1 - std::pow(kRatio, current_frame)) / (1 - kRatio); + return sum <= total_distance_ ? sum : total_distance_; +} + +gfx::Vector2dF SnapFlingCurve::GetScrollDelta(base::TimeTicks time_stamp) { + if (is_finished_) + return gfx::Vector2dF(); + + // The the snap offset may never be reached due to clamping or other factors. + // To avoid a never ending snap curve, we force the curve to end if the time + // has passed a maximum Duration. + if (time_stamp - start_time_ > kMaximumSnapDuration) { + is_finished_ = true; + return total_displacement_ - current_displacement_; + } + + double new_distance = GetCurrentCurveDistance(time_stamp); + gfx::Vector2dF new_displacement(new_distance * ratio_x_, + new_distance * ratio_y_); + + return new_displacement - current_displacement_; +} + +void SnapFlingCurve::UpdateCurrentOffset(const gfx::Vector2dF& current_offset) { + current_displacement_ = current_offset - start_offset_; + if (current_displacement_ == total_displacement_) + is_finished_ = true; +} + +bool SnapFlingCurve::IsFinished() const { + return is_finished_; +} + +} // namespace cc diff --git a/chromium/cc/input/snap_fling_curve.h b/chromium/cc/input/snap_fling_curve.h new file mode 100644 index 00000000000..b5eaf62fa3d --- /dev/null +++ b/chromium/cc/input/snap_fling_curve.h @@ -0,0 +1,78 @@ +// Copyright 2018 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_INPUT_SNAP_FLING_CURVE_H_ +#define CC_INPUT_SNAP_FLING_CURVE_H_ + +#include "base/time/time.h" +#include "cc/cc_export.h" +#include "ui/gfx/geometry/rect_f.h" +#include "ui/gfx/geometry/vector2d_f.h" + +namespace cc { + +// The curve for the snap fling animation. The curve would generate a geometric +// sequence of deltas to be scrolled at each frame. +class CC_EXPORT SnapFlingCurve { + public: + // Creates the curve based on the start offset, target offset, and the first + // inertial GSU's time_stamp. + SnapFlingCurve(const gfx::Vector2dF& start_offset, + const gfx::Vector2dF& target_offset, + base::TimeTicks first_gsu_time); + + virtual ~SnapFlingCurve(); + + // Estimate the total distance that will be scrolled given the first GSU's + // delta + static gfx::Vector2dF EstimateDisplacement(const gfx::Vector2dF& first_delta); + + // Returns the delta that should be scrolled at |time|. + virtual gfx::Vector2dF GetScrollDelta(base::TimeTicks time); + + // Updates |current_displacement_|. This sync is necessary because the node + // might be scrolled by other calls and the scrolls might be clamped. + void UpdateCurrentOffset(const gfx::Vector2dF& current_offset); + + // Returns true if the scroll has arrived at the snap destination. + virtual bool IsFinished() const; + + base::TimeDelta duration() const { return duration_; } + + private: + // Returns the curve's current distance at |time_stamp|. + double GetCurrentCurveDistance(base::TimeTicks time_stamp); + + // The initial scroll offset of the scroller. + const gfx::Vector2dF start_offset_; + + // The total displacement to the snap position. + const gfx::Vector2dF total_displacement_; + // 1D representation of |total_displacement_|. + const double total_distance_; + + // The current displacement that has been scrolled. + gfx::Vector2dF current_displacement_; + + // The timestamp of the first GSU. + const base::TimeTicks start_time_; + + // The number of deltas in the curve's geometric sequence. + const double total_frames_; + // The first delta that defines the curve's geometric sequence. + const double first_delta_; + // The total milliseconds needed to finish the curve. + const base::TimeDelta duration_; + + bool is_finished_ = false; + + // |total_displacement_.x| / |total_distance_| + double ratio_x_; + // |total_displacement_.y| / |total_distance_| + double ratio_y_; +}; + +} // namespace cc + +#endif // CC_INPUT_SNAP_FLING_CURVE_H_ diff --git a/chromium/cc/input/snap_fling_curve_unittest.cc b/chromium/cc/input/snap_fling_curve_unittest.cc new file mode 100644 index 00000000000..028006f7670 --- /dev/null +++ b/chromium/cc/input/snap_fling_curve_unittest.cc @@ -0,0 +1,71 @@ +// Copyright 2018 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/input/snap_fling_curve.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace test { + +TEST(SnapFlingCurveTest, CurveInitialization) { + SnapFlingCurve active_curve(gfx::Vector2dF(100, 100), + gfx::Vector2dF(500, 500), base::TimeTicks()); + EXPECT_FALSE(active_curve.IsFinished()); + + SnapFlingCurve finished_curve(gfx::Vector2dF(100, 100), + gfx::Vector2dF(100, 100), base::TimeTicks()); + EXPECT_TRUE(finished_curve.IsFinished()); +} + +TEST(SnapFlingCurveTest, AdvanceHalfwayThrough) { + SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500), + base::TimeTicks()); + base::TimeDelta duration = curve.duration(); + gfx::Vector2dF delta1 = + curve.GetScrollDelta(base::TimeTicks() + duration / 2); + EXPECT_LT(0, delta1.x()); + EXPECT_LT(0, delta1.y()); + EXPECT_FALSE(curve.IsFinished()); + + // Repeated offset computations at the same timestamp before applying the + // scrolled delta should yield identical results. + gfx::Vector2dF delta2 = + curve.GetScrollDelta(base::TimeTicks() + duration / 2); + EXPECT_EQ(delta1, delta2); + EXPECT_FALSE(curve.IsFinished()); + + curve.UpdateCurrentOffset(gfx::Vector2dF(100, 100) + delta1); + EXPECT_FALSE(curve.IsFinished()); +} + +TEST(SnapFlingCurveTest, AdvanceFullyThroughOnlyFinishesAfterUpdate) { + SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500), + base::TimeTicks()); + gfx::Vector2dF delta = + curve.GetScrollDelta(base::TimeTicks() + curve.duration()); + EXPECT_EQ(gfx::Vector2dF(400, 400), delta); + EXPECT_FALSE(curve.IsFinished()); + + curve.UpdateCurrentOffset(gfx::Vector2dF(500, 500)); + EXPECT_TRUE(curve.IsFinished()); +} + +TEST(SnapFlingCurveTest, ReturnsZeroAfterFinished) { + SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500), + base::TimeTicks()); + curve.UpdateCurrentOffset(gfx::Vector2dF(500, 500)); + EXPECT_TRUE(curve.IsFinished()); + + gfx::Vector2dF delta = curve.GetScrollDelta(base::TimeTicks()); + EXPECT_EQ(gfx::Vector2dF(), delta); + EXPECT_TRUE(curve.IsFinished()); + + delta = curve.GetScrollDelta(base::TimeTicks() + curve.duration()); + EXPECT_EQ(gfx::Vector2dF(), delta); + EXPECT_TRUE(curve.IsFinished()); +} + +} // namespace test +} // namespace cc diff --git a/chromium/cc/ipc/BUILD.gn b/chromium/cc/ipc/BUILD.gn deleted file mode 100644 index 8692a3c6ac5..00000000000 --- a/chromium/cc/ipc/BUILD.gn +++ /dev/null @@ -1,40 +0,0 @@ -# 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. - -import("//build/config/ui.gni") -import("//cc/cc.gni") -import("//mojo/public/tools/bindings/mojom.gni") - -cc_component("ipc") { - output_name = "cc_ipc" - - defines = [ "CC_IPC_IMPLEMENTATION" ] - - sources = [ - "cc_ipc_export.h", - "cc_param_traits.cc", - "cc_param_traits.h", - "cc_param_traits_macros.h", - ] - - public_deps = [ - "//cc", - "//cc/paint", - "//components/viz/common", - "//skia", - ] - - deps = [ - "//base", - "//gpu/ipc/common", - "//ipc", - "//ui/gfx", - "//ui/gfx/ipc", - "//ui/gfx/ipc/buffer_types", - "//ui/gfx/ipc/color", - "//ui/gfx/ipc/geometry", - "//ui/gfx/ipc/skia", - "//ui/latency/ipc", - ] -} diff --git a/chromium/cc/ipc/DEPS b/chromium/cc/ipc/DEPS deleted file mode 100644 index a21ff764e82..00000000000 --- a/chromium/cc/ipc/DEPS +++ /dev/null @@ -1,10 +0,0 @@ -include_rules = [ - "+gpu/ipc/common", - "+mojo/common", - "+mojo/public", - "+skia/public", - "+ui/gfx/geometry/mojo", - "+ui/latency/ipc", - "+ui/latency/mojo", - "+services/viz/public", -] diff --git a/chromium/cc/ipc/OWNERS b/chromium/cc/ipc/OWNERS deleted file mode 100644 index 8b2d44fbeff..00000000000 --- a/chromium/cc/ipc/OWNERS +++ /dev/null @@ -1,11 +0,0 @@ -per-file *_param_traits*.*=set noparent -per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS - -per-file *_struct_traits*.*=set noparent -per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS - -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS - -per-file *.typemap=set noparent -per-file *.typemap=file://ipc/SECURITY_OWNERS diff --git a/chromium/cc/ipc/cc_ipc_export.h b/chromium/cc/ipc/cc_ipc_export.h deleted file mode 100644 index 4a3623e03d5..00000000000 --- a/chromium/cc/ipc/cc_ipc_export.h +++ /dev/null @@ -1,29 +0,0 @@ -// 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. - -#ifndef CC_IPC_CC_IPC_EXPORT_H_ -#define CC_IPC_CC_IPC_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(CC_IPC_IMPLEMENTATION) -#define CC_IPC_EXPORT __declspec(dllexport) -#else -#define CC_IPC_EXPORT __declspec(dllimport) -#endif // defined(CC_IPC_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(CC_IPC_IMPLEMENTATION) -#define CC_IPC_EXPORT __attribute__((visibility("default"))) -#else -#define CC_IPC_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define CC_IPC_EXPORT -#endif - -#endif // CC_IPC_CC_IPC_EXPORT_H_ diff --git a/chromium/cc/ipc/cc_param_traits.cc b/chromium/cc/ipc/cc_param_traits.cc deleted file mode 100644 index c66518e291d..00000000000 --- a/chromium/cc/ipc/cc_param_traits.cc +++ /dev/null @@ -1,1006 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/ipc/cc_param_traits.h" - -#include <stddef.h> -#include <utility> - -#include "base/numerics/safe_conversions.h" -#include "base/time/time.h" -#include "base/trace_event/trace_event.h" -#include "base/unguessable_token.h" -#include "cc/paint/filter_operations.h" -#include "cc/paint/paint_filter.h" -#include "cc/paint/paint_op_buffer.h" -#include "cc/paint/paint_op_reader.h" -#include "cc/paint/paint_op_writer.h" -#include "components/viz/common/quads/compositor_frame.h" -#include "components/viz/common/quads/debug_border_draw_quad.h" -#include "components/viz/common/quads/draw_quad.h" -#include "components/viz/common/quads/largest_draw_quad.h" -#include "components/viz/common/quads/render_pass_draw_quad.h" -#include "components/viz/common/quads/solid_color_draw_quad.h" -#include "components/viz/common/quads/surface_draw_quad.h" -#include "components/viz/common/quads/tile_draw_quad.h" -#include "components/viz/common/quads/yuv_video_draw_quad.h" -#include "components/viz/common/surfaces/surface_id.h" -#include "ui/gfx/ipc/geometry/gfx_param_traits.h" -#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h" - -namespace IPC { - -void ParamTraits<cc::FilterOperation>::Write(base::Pickle* m, - const param_type& p) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::FilterOperation::Write"); - WriteParam(m, p.type()); - switch (p.type()) { - case cc::FilterOperation::GRAYSCALE: - case cc::FilterOperation::SEPIA: - case cc::FilterOperation::SATURATE: - case cc::FilterOperation::HUE_ROTATE: - case cc::FilterOperation::INVERT: - case cc::FilterOperation::BRIGHTNESS: - case cc::FilterOperation::SATURATING_BRIGHTNESS: - case cc::FilterOperation::CONTRAST: - case cc::FilterOperation::OPACITY: - WriteParam(m, p.amount()); - break; - case cc::FilterOperation::BLUR: - WriteParam(m, p.amount()); - WriteParam(m, p.blur_tile_mode()); - break; - case cc::FilterOperation::DROP_SHADOW: - WriteParam(m, p.drop_shadow_offset()); - WriteParam(m, p.amount()); - WriteParam(m, p.drop_shadow_color()); - break; - case cc::FilterOperation::COLOR_MATRIX: - for (int i = 0; i < 20; ++i) - WriteParam(m, p.matrix()[i]); - break; - case cc::FilterOperation::ZOOM: - WriteParam(m, p.amount()); - WriteParam(m, p.zoom_inset()); - break; - case cc::FilterOperation::REFERENCE: - WriteParam(m, p.image_filter()); - break; - case cc::FilterOperation::ALPHA_THRESHOLD: - WriteParam(m, p.amount()); - WriteParam(m, p.outer_threshold()); - WriteParam(m, p.shape()); - break; - } -} - -bool ParamTraits<cc::FilterOperation>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::FilterOperation::Read"); - cc::FilterOperation::FilterType type; - float amount; - float outer_threshold; - gfx::Point drop_shadow_offset; - SkColor drop_shadow_color; - SkScalar matrix[20]; - cc::FilterOperation::ShapeRects shape; - int zoom_inset; - SkBlurImageFilter::TileMode tile_mode; - - if (!ReadParam(m, iter, &type)) - return false; - r->set_type(type); - - bool success = false; - switch (type) { - case cc::FilterOperation::GRAYSCALE: - case cc::FilterOperation::SEPIA: - case cc::FilterOperation::SATURATE: - case cc::FilterOperation::HUE_ROTATE: - case cc::FilterOperation::INVERT: - case cc::FilterOperation::BRIGHTNESS: - case cc::FilterOperation::SATURATING_BRIGHTNESS: - case cc::FilterOperation::CONTRAST: - case cc::FilterOperation::OPACITY: - if (ReadParam(m, iter, &amount)) { - r->set_amount(amount); - success = true; - } - break; - case cc::FilterOperation::BLUR: - if (ReadParam(m, iter, &amount) && ReadParam(m, iter, &tile_mode)) { - r->set_amount(amount); - r->set_blur_tile_mode(tile_mode); - success = true; - } - break; - case cc::FilterOperation::DROP_SHADOW: - if (ReadParam(m, iter, &drop_shadow_offset) && - ReadParam(m, iter, &amount) && - ReadParam(m, iter, &drop_shadow_color)) { - r->set_drop_shadow_offset(drop_shadow_offset); - r->set_amount(amount); - r->set_drop_shadow_color(drop_shadow_color); - success = true; - } - break; - case cc::FilterOperation::COLOR_MATRIX: { - int i; - for (i = 0; i < 20; ++i) { - if (!ReadParam(m, iter, &matrix[i])) - break; - } - if (i == 20) { - r->set_matrix(matrix); - success = true; - } - break; - } - case cc::FilterOperation::ZOOM: - if (ReadParam(m, iter, &amount) && ReadParam(m, iter, &zoom_inset) && - amount >= 0.f && zoom_inset >= 0) { - r->set_amount(amount); - r->set_zoom_inset(zoom_inset); - success = true; - } - break; - case cc::FilterOperation::REFERENCE: { - sk_sp<cc::PaintFilter> filter; - if (!ReadParam(m, iter, &filter)) { - success = false; - break; - } - r->set_image_filter(std::move(filter)); - success = true; - break; - } - case cc::FilterOperation::ALPHA_THRESHOLD: - if (ReadParam(m, iter, &amount) && ReadParam(m, iter, &outer_threshold) && - ReadParam(m, iter, &shape) && amount >= 0.f && - outer_threshold >= 0.f) { - r->set_amount(amount); - r->set_outer_threshold(amount); - r->set_shape(shape); - success = true; - } - break; - } - return success; -} - -void ParamTraits<cc::FilterOperation>::Log(const param_type& p, - std::string* l) { - l->append("("); - LogParam(static_cast<unsigned>(p.type()), l); - l->append(", "); - - switch (p.type()) { - case cc::FilterOperation::GRAYSCALE: - case cc::FilterOperation::SEPIA: - case cc::FilterOperation::SATURATE: - case cc::FilterOperation::HUE_ROTATE: - case cc::FilterOperation::INVERT: - case cc::FilterOperation::BRIGHTNESS: - case cc::FilterOperation::SATURATING_BRIGHTNESS: - case cc::FilterOperation::CONTRAST: - case cc::FilterOperation::OPACITY: - LogParam(p.amount(), l); - break; - case cc::FilterOperation::BLUR: - LogParam(p.amount(), l); - l->append(", "); - LogParam(static_cast<int>(p.blur_tile_mode()), l); - break; - case cc::FilterOperation::DROP_SHADOW: - LogParam(p.drop_shadow_offset(), l); - l->append(", "); - LogParam(p.amount(), l); - l->append(", "); - LogParam(p.drop_shadow_color(), l); - break; - case cc::FilterOperation::COLOR_MATRIX: - for (int i = 0; i < 20; ++i) { - if (i) - l->append(", "); - LogParam(p.matrix()[i], l); - } - break; - case cc::FilterOperation::ZOOM: - LogParam(p.amount(), l); - l->append(", "); - LogParam(p.zoom_inset(), l); - break; - case cc::FilterOperation::REFERENCE: - LogParam(p.image_filter(), l); - break; - case cc::FilterOperation::ALPHA_THRESHOLD: - LogParam(p.amount(), l); - l->append(", "); - LogParam(p.outer_threshold(), l); - l->append(", "); - LogParam(p.shape(), l); - break; - } - l->append(")"); -} - -void ParamTraits<cc::FilterOperations>::Write(base::Pickle* m, - const param_type& p) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::FilterOperations::Write"); - WriteParam(m, base::checked_cast<uint32_t>(p.size())); - for (std::size_t i = 0; i < p.size(); ++i) { - WriteParam(m, p.at(i)); - } -} - -bool ParamTraits<cc::FilterOperations>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::FilterOperations::Read"); - uint32_t count; - if (!ReadParam(m, iter, &count)) - return false; - - for (std::size_t i = 0; i < count; ++i) { - cc::FilterOperation op = cc::FilterOperation::CreateEmptyFilter(); - if (!ReadParam(m, iter, &op)) - return false; - r->Append(op); - } - return true; -} - -void ParamTraits<cc::FilterOperations>::Log(const param_type& p, - std::string* l) { - l->append("("); - for (std::size_t i = 0; i < p.size(); ++i) { - if (i) - l->append(", "); - LogParam(p.at(i), l); - } - l->append(")"); -} - -void ParamTraits<sk_sp<cc::PaintFilter>>::Write(base::Pickle* m, - const param_type& p) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::PaintFilter::Write"); - std::vector<uint8_t> memory; - memory.resize(cc::PaintOpWriter::HeaderBytes() + - cc::PaintFilter::GetFilterSize(p.get())); - cc::PaintOpWriter writer(memory.data(), memory.size(), nullptr, nullptr, - true /* enable_security_constraints */); - writer.Write(p.get()); - if (writer.size() == 0u) - m->WriteData(nullptr, 0); - else - m->WriteData(reinterpret_cast<const char*>(memory.data()), writer.size()); -} - -bool ParamTraits<sk_sp<cc::PaintFilter>>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::PaintFilter::Read"); - const char* data = nullptr; - int length = 0; - if (!iter->ReadData(&data, &length)) - return false; - - if (length <= 0) { - r->reset(); - return true; - } - - cc::PaintOpReader reader(data, length, nullptr, - true /* enable_security_constraints */); - sk_sp<cc::PaintFilter> filter; - reader.Read(&filter); - if (!filter) - return false; - - *r = std::move(filter); - return true; -} - -void ParamTraits<sk_sp<cc::PaintFilter>>::Log(const param_type& p, - std::string* l) { - l->append("("); - auto type = p ? p->type() : cc::PaintFilter::Type::kNullFilter; - LogParam(cc::PaintFilter::TypeToString(type), l); - l->append(")"); -} - -void ParamTraits<viz::RenderPass>::Write(base::Pickle* m, const param_type& p) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::RenderPass::Write"); - WriteParam(m, p.id); - WriteParam(m, p.output_rect); - WriteParam(m, p.damage_rect); - WriteParam(m, p.transform_to_root_target); - WriteParam(m, p.filters); - WriteParam(m, p.background_filters); - WriteParam(m, p.color_space); - WriteParam(m, p.has_transparent_background); - WriteParam(m, p.cache_render_pass); - WriteParam(m, p.has_damage_from_contributing_content); - WriteParam(m, p.generate_mipmap); - WriteParam(m, base::checked_cast<uint32_t>(p.quad_list.size())); - - auto shared_quad_state_iter = p.shared_quad_state_list.cbegin(); - auto last_shared_quad_state_iter = p.shared_quad_state_list.cend(); - for (auto* quad : p.quad_list) { - DCHECK(quad->rect.Contains(quad->visible_rect)) - << quad->material << " rect: " << quad->rect.ToString() - << " visible_rect: " << quad->visible_rect.ToString(); - - switch (quad->material) { - case viz::DrawQuad::DEBUG_BORDER: - WriteParam(m, *viz::DebugBorderDrawQuad::MaterialCast(quad)); - break; - case viz::DrawQuad::PICTURE_CONTENT: - NOTREACHED(); - break; - case viz::DrawQuad::TEXTURE_CONTENT: - WriteParam(m, *viz::TextureDrawQuad::MaterialCast(quad)); - break; - case viz::DrawQuad::RENDER_PASS: - WriteParam(m, *viz::RenderPassDrawQuad::MaterialCast(quad)); - break; - case viz::DrawQuad::SOLID_COLOR: - WriteParam(m, *viz::SolidColorDrawQuad::MaterialCast(quad)); - break; - case viz::DrawQuad::SURFACE_CONTENT: - WriteParam(m, *viz::SurfaceDrawQuad::MaterialCast(quad)); - break; - case viz::DrawQuad::TILED_CONTENT: - WriteParam(m, *viz::TileDrawQuad::MaterialCast(quad)); - break; - case viz::DrawQuad::STREAM_VIDEO_CONTENT: - WriteParam(m, *viz::StreamVideoDrawQuad::MaterialCast(quad)); - break; - case viz::DrawQuad::YUV_VIDEO_CONTENT: - WriteParam(m, *viz::YUVVideoDrawQuad::MaterialCast(quad)); - break; - case viz::DrawQuad::INVALID: - break; - } - - // Null shared quad states should not occur. - DCHECK(quad->shared_quad_state); - - // SharedQuadStates should appear in the order they are used by DrawQuads. - // Find the SharedQuadState for this DrawQuad. - while (shared_quad_state_iter != p.shared_quad_state_list.end() && - quad->shared_quad_state != *shared_quad_state_iter) { - ++shared_quad_state_iter; - } - - DCHECK(shared_quad_state_iter != p.shared_quad_state_list.end()); - - if (shared_quad_state_iter != last_shared_quad_state_iter) { - WriteParam(m, true); - WriteParam(m, **shared_quad_state_iter); - last_shared_quad_state_iter = shared_quad_state_iter; - } else { - WriteParam(m, false); - } - } -} - -static size_t ReserveSizeForRenderPassWrite(const viz::RenderPass& p) { - size_t to_reserve = sizeof(viz::RenderPass); - - // Whether the quad points to a new shared quad state for each quad. - to_reserve += p.quad_list.size() * sizeof(bool); - - // Shared quad state is only written when a quad contains a shared quad state - // that has not been written. - to_reserve += p.shared_quad_state_list.size() * sizeof(viz::SharedQuadState); - - // The largest quad type, verified by a unit test. - to_reserve += p.quad_list.size() * viz::LargestDrawQuadSize(); - - to_reserve += - sizeof(uint32_t) + p.filters.size() * sizeof(cc::FilterOperation); - to_reserve += sizeof(uint32_t) + - p.background_filters.size() * sizeof(cc::FilterOperation); - - return to_reserve; -} - -template <typename QuadType> -static viz::DrawQuad* ReadDrawQuad(const base::Pickle* m, - base::PickleIterator* iter, - viz::RenderPass* render_pass) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::ReadDrawQuad"); - QuadType* quad = render_pass->CreateAndAppendDrawQuad<QuadType>(); - if (!ReadParam(m, iter, quad)) - return nullptr; - return quad; -} - -bool ParamTraits<viz::RenderPass>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::RenderPass::Read"); - uint64_t id; - gfx::Rect output_rect; - gfx::Rect damage_rect; - gfx::Transform transform_to_root_target; - cc::FilterOperations filters; - cc::FilterOperations background_filters; - gfx::ColorSpace color_space; - bool has_transparent_background; - bool cache_render_pass; - bool has_damage_from_contributing_content; - bool generate_mipmap; - - uint32_t quad_list_size; - - if (!ReadParam(m, iter, &id) || !ReadParam(m, iter, &output_rect) || - !ReadParam(m, iter, &damage_rect) || - !ReadParam(m, iter, &transform_to_root_target) || - !ReadParam(m, iter, &filters) || - !ReadParam(m, iter, &background_filters) || - !ReadParam(m, iter, &color_space) || - !ReadParam(m, iter, &has_transparent_background) || - !ReadParam(m, iter, &cache_render_pass) || - !ReadParam(m, iter, &has_damage_from_contributing_content) || - !ReadParam(m, iter, &generate_mipmap) || - !ReadParam(m, iter, &quad_list_size)) - return false; - - p->SetAll(id, output_rect, damage_rect, transform_to_root_target, filters, - background_filters, color_space, has_transparent_background, - cache_render_pass, has_damage_from_contributing_content, - generate_mipmap); - - for (uint32_t i = 0; i < quad_list_size; ++i) { - viz::DrawQuad::Material material; - base::PickleIterator temp_iter = *iter; - if (!ReadParam(m, &temp_iter, &material)) - return false; - - viz::DrawQuad* draw_quad = nullptr; - switch (material) { - case viz::DrawQuad::DEBUG_BORDER: - draw_quad = ReadDrawQuad<viz::DebugBorderDrawQuad>(m, iter, p); - break; - case viz::DrawQuad::PICTURE_CONTENT: - NOTREACHED(); - return false; - case viz::DrawQuad::SURFACE_CONTENT: - draw_quad = ReadDrawQuad<viz::SurfaceDrawQuad>(m, iter, p); - break; - case viz::DrawQuad::TEXTURE_CONTENT: - draw_quad = ReadDrawQuad<viz::TextureDrawQuad>(m, iter, p); - break; - case viz::DrawQuad::RENDER_PASS: - draw_quad = ReadDrawQuad<viz::RenderPassDrawQuad>(m, iter, p); - break; - case viz::DrawQuad::SOLID_COLOR: - draw_quad = ReadDrawQuad<viz::SolidColorDrawQuad>(m, iter, p); - break; - case viz::DrawQuad::TILED_CONTENT: - draw_quad = ReadDrawQuad<viz::TileDrawQuad>(m, iter, p); - break; - case viz::DrawQuad::STREAM_VIDEO_CONTENT: - draw_quad = ReadDrawQuad<viz::StreamVideoDrawQuad>(m, iter, p); - break; - case viz::DrawQuad::YUV_VIDEO_CONTENT: - draw_quad = ReadDrawQuad<viz::YUVVideoDrawQuad>(m, iter, p); - break; - case viz::DrawQuad::INVALID: - break; - } - if (!draw_quad) - return false; - if (!draw_quad->rect.Contains(draw_quad->visible_rect)) { - LOG(ERROR) << "Quad with invalid visible rect " << draw_quad->material - << " rect: " << draw_quad->rect.ToString() - << " visible_rect: " << draw_quad->visible_rect.ToString(); - return false; - } - - bool has_new_shared_quad_state; - if (!ReadParam(m, iter, &has_new_shared_quad_state)) - return false; - - // If the quad has a new shared quad state, read it in. - if (has_new_shared_quad_state) { - viz::SharedQuadState* state = p->CreateAndAppendSharedQuadState(); - if (!ReadParam(m, iter, state)) - return false; - } - - draw_quad->shared_quad_state = p->shared_quad_state_list.back(); - } - - return true; -} - -void ParamTraits<viz::RenderPass>::Log(const param_type& p, std::string* l) { - l->append("RenderPass(("); - LogParam(p.id, l); - l->append("), "); - LogParam(p.output_rect, l); - l->append(", "); - LogParam(p.damage_rect, l); - l->append(", "); - LogParam(p.transform_to_root_target, l); - l->append(", "); - LogParam(p.filters, l); - l->append(", "); - LogParam(p.background_filters, l); - l->append(", "); - LogParam(p.color_space, l); - l->append(", "); - LogParam(p.has_transparent_background, l); - l->append(", "); - LogParam(p.cache_render_pass, l); - l->append(", "); - LogParam(p.has_damage_from_contributing_content, l); - l->append(", "); - - l->append("["); - for (auto* shared_quad_state : p.shared_quad_state_list) { - if (shared_quad_state != p.shared_quad_state_list.front()) - l->append(", "); - LogParam(*shared_quad_state, l); - } - l->append("], ["); - for (auto* quad : p.quad_list) { - if (quad != p.quad_list.front()) - l->append(", "); - switch (quad->material) { - case viz::DrawQuad::DEBUG_BORDER: - LogParam(*viz::DebugBorderDrawQuad::MaterialCast(quad), l); - break; - case viz::DrawQuad::PICTURE_CONTENT: - NOTREACHED(); - break; - case viz::DrawQuad::TEXTURE_CONTENT: - LogParam(*viz::TextureDrawQuad::MaterialCast(quad), l); - break; - case viz::DrawQuad::RENDER_PASS: - LogParam(*viz::RenderPassDrawQuad::MaterialCast(quad), l); - break; - case viz::DrawQuad::SOLID_COLOR: - LogParam(*viz::SolidColorDrawQuad::MaterialCast(quad), l); - break; - case viz::DrawQuad::SURFACE_CONTENT: - LogParam(*viz::SurfaceDrawQuad::MaterialCast(quad), l); - break; - case viz::DrawQuad::TILED_CONTENT: - LogParam(*viz::TileDrawQuad::MaterialCast(quad), l); - break; - case viz::DrawQuad::STREAM_VIDEO_CONTENT: - LogParam(*viz::StreamVideoDrawQuad::MaterialCast(quad), l); - break; - case viz::DrawQuad::YUV_VIDEO_CONTENT: - LogParam(*viz::YUVVideoDrawQuad::MaterialCast(quad), l); - break; - case viz::DrawQuad::INVALID: - break; - } - } - l->append("])"); -} - -void ParamTraits<viz::FrameDeadline>::Write(base::Pickle* m, - const param_type& p) { - WriteParam(m, p.frame_start_time()); - WriteParam(m, p.deadline_in_frames()); - WriteParam(m, p.frame_interval()); - WriteParam(m, p.use_default_lower_bound_deadline()); -} - -bool ParamTraits<viz::FrameDeadline>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - base::TimeTicks frame_start_time; - if (!ReadParam(m, iter, &frame_start_time)) - return false; - - uint32_t deadline_in_frames; - if (!ReadParam(m, iter, &deadline_in_frames)) - return false; - - base::TimeDelta frame_interval; - if (!ReadParam(m, iter, &frame_interval)) - return false; - - bool use_default_lower_bound_deadline; - if (!ReadParam(m, iter, &use_default_lower_bound_deadline)) - return false; - - *p = viz::FrameDeadline(frame_start_time, deadline_in_frames, frame_interval, - use_default_lower_bound_deadline); - return true; -} - -void ParamTraits<viz::FrameDeadline>::Log(const param_type& p, std::string* l) { - l->append("viz::FrameDeadline("); - LogParam(p.frame_start_time(), l); - l->append(", "); - LogParam(p.deadline_in_frames(), l); - l->append(", "); - LogParam(p.frame_interval(), l); - l->append(", "); - LogParam(p.use_default_lower_bound_deadline(), l); - l->append(")"); -} - -void ParamTraits<viz::FrameSinkId>::Write(base::Pickle* m, - const param_type& p) { - DCHECK(p.is_valid()); - WriteParam(m, p.client_id()); - WriteParam(m, p.sink_id()); -} - -bool ParamTraits<viz::FrameSinkId>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - uint32_t client_id; - if (!ReadParam(m, iter, &client_id)) - return false; - - uint32_t sink_id; - if (!ReadParam(m, iter, &sink_id)) - return false; - - *p = viz::FrameSinkId(client_id, sink_id); - return p->is_valid(); -} - -void ParamTraits<viz::FrameSinkId>::Log(const param_type& p, std::string* l) { - l->append("viz::FrameSinkId("); - LogParam(p.client_id(), l); - l->append(", "); - LogParam(p.sink_id(), l); - l->append(")"); -} - -void ParamTraits<viz::LocalSurfaceId>::Write(base::Pickle* m, - const param_type& p) { - DCHECK(p.is_valid()); - WriteParam(m, p.parent_sequence_number()); - WriteParam(m, p.child_sequence_number()); - WriteParam(m, p.embed_token()); -} - -bool ParamTraits<viz::LocalSurfaceId>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - uint32_t parent_sequence_number; - if (!ReadParam(m, iter, &parent_sequence_number)) - return false; - - uint32_t child_sequence_number; - if (!ReadParam(m, iter, &child_sequence_number)) - return false; - - base::UnguessableToken embed_token; - if (!ReadParam(m, iter, &embed_token)) - return false; - - *p = viz::LocalSurfaceId(parent_sequence_number, child_sequence_number, - embed_token); - return p->is_valid(); -} - -void ParamTraits<viz::LocalSurfaceId>::Log(const param_type& p, - std::string* l) { - l->append("viz::LocalSurfaceId("); - LogParam(p.parent_sequence_number(), l); - l->append(", "); - LogParam(p.child_sequence_number(), l); - l->append(", "); - LogParam(p.embed_token(), l); - l->append(")"); -} - -void ParamTraits<viz::SurfaceId>::Write(base::Pickle* m, const param_type& p) { - WriteParam(m, p.frame_sink_id()); - WriteParam(m, p.local_surface_id()); -} - -bool ParamTraits<viz::SurfaceId>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - viz::FrameSinkId frame_sink_id; - if (!ReadParam(m, iter, &frame_sink_id)) - return false; - - viz::LocalSurfaceId local_surface_id; - if (!ReadParam(m, iter, &local_surface_id)) - return false; - - *p = viz::SurfaceId(frame_sink_id, local_surface_id); - return true; -} - -void ParamTraits<viz::SurfaceId>::Log(const param_type& p, std::string* l) { - l->append("viz::SurfaceId("); - LogParam(p.frame_sink_id(), l); - l->append(", "); - LogParam(p.local_surface_id(), l); - l->append(")"); -} - -void ParamTraits<viz::SurfaceInfo>::Write(base::Pickle* m, - const param_type& p) { - WriteParam(m, p.id()); - WriteParam(m, p.device_scale_factor()); - WriteParam(m, p.size_in_pixels()); -} - -bool ParamTraits<viz::SurfaceInfo>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - viz::SurfaceId surface_id; - if (!ReadParam(m, iter, &surface_id)) - return false; - - float device_scale_factor; - if (!ReadParam(m, iter, &device_scale_factor)) - return false; - - gfx::Size size_in_pixels; - if (!ReadParam(m, iter, &size_in_pixels)) - return false; - - *p = viz::SurfaceInfo(surface_id, device_scale_factor, size_in_pixels); - return p->is_valid(); -} - -void ParamTraits<viz::SurfaceInfo>::Log(const param_type& p, std::string* l) { - l->append("viz::SurfaceInfo("); - LogParam(p.id(), l); - l->append(", "); - LogParam(p.device_scale_factor(), l); - l->append(", "); - LogParam(p.size_in_pixels(), l); - l->append(")"); -} - -void ParamTraits<viz::CompositorFrame>::Write(base::Pickle* m, - const param_type& p) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::CompositorFrame::Write"); - WriteParam(m, p.metadata); - size_t to_reserve = 0u; - to_reserve += p.resource_list.size() * sizeof(viz::TransferableResource); - for (const auto& pass : p.render_pass_list) { - to_reserve += sizeof(size_t) * 2; - to_reserve += ReserveSizeForRenderPassWrite(*pass); - } - m->Reserve(to_reserve); - - WriteParam(m, p.resource_list); - WriteParam(m, base::checked_cast<uint32_t>(p.render_pass_list.size())); - for (const auto& pass : p.render_pass_list) { - WriteParam(m, base::checked_cast<uint32_t>(pass->quad_list.size())); - WriteParam( - m, base::checked_cast<uint32_t>(pass->shared_quad_state_list.size())); - WriteParam(m, *pass); - } -} - -bool ParamTraits<viz::CompositorFrame>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::CompositorFrame::Read"); - if (!ReadParam(m, iter, &p->metadata)) - return false; - - const size_t kMaxRenderPasses = 10000; - const size_t kMaxSharedQuadStateListSize = 100000; - const size_t kMaxQuadListSize = 1000000; - - std::set<viz::RenderPassId> pass_id_set; - - uint32_t num_render_passes; - if (!ReadParam(m, iter, &p->resource_list) || - !ReadParam(m, iter, &num_render_passes) || num_render_passes == 0 || - num_render_passes > kMaxRenderPasses) - return false; - for (uint32_t i = 0; i < num_render_passes; ++i) { - uint32_t quad_list_size; - uint32_t shared_quad_state_list_size; - if (!ReadParam(m, iter, &quad_list_size) || - !ReadParam(m, iter, &shared_quad_state_list_size) || - quad_list_size > kMaxQuadListSize || - shared_quad_state_list_size > kMaxSharedQuadStateListSize) - return false; - std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create( - static_cast<size_t>(shared_quad_state_list_size), - static_cast<size_t>(quad_list_size)); - if (!ReadParam(m, iter, render_pass.get())) - return false; - // Validate that each viz::RenderPassDrawQuad points at a valid RenderPass - // earlier in the frame. - for (const auto* quad : render_pass->quad_list) { - if (quad->material != viz::DrawQuad::RENDER_PASS) - continue; - const viz::RenderPassDrawQuad* rpdq = - viz::RenderPassDrawQuad::MaterialCast(quad); - if (!pass_id_set.count(rpdq->render_pass_id)) - return false; - } - pass_id_set.insert(render_pass->id); - p->render_pass_list.push_back(std::move(render_pass)); - } - - if (p->render_pass_list.back()->output_rect.size().IsEmpty()) - return false; - - return true; -} - -void ParamTraits<viz::CompositorFrame>::Log(const param_type& p, - std::string* l) { - l->append("CompositorFrame("); - LogParam(p.metadata, l); - l->append(", "); - LogParam(p.resource_list, l); - l->append(", ["); - for (size_t i = 0; i < p.render_pass_list.size(); ++i) { - if (i) - l->append(", "); - LogParam(*p.render_pass_list[i], l); - } - l->append("])"); -} - -void ParamTraits<viz::DrawQuad::Resources>::Write(base::Pickle* m, - const param_type& p) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::DrawQuad::Resources::Write"); - DCHECK_LE(p.count, viz::DrawQuad::Resources::kMaxResourceIdCount); - WriteParam(m, p.count); - for (size_t i = 0; i < p.count; ++i) - WriteParam(m, p.ids[i]); -} - -bool ParamTraits<viz::DrawQuad::Resources>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), - "ParamTraits::DrawQuad::Resources::Read"); - if (!ReadParam(m, iter, &p->count)) - return false; - if (p->count > viz::DrawQuad::Resources::kMaxResourceIdCount) - return false; - for (size_t i = 0; i < p->count; ++i) { - if (!ReadParam(m, iter, &p->ids[i])) - return false; - } - return true; -} - -void ParamTraits<viz::DrawQuad::Resources>::Log(const param_type& p, - std::string* l) { - l->append("DrawQuad::Resources("); - LogParam(p.count, l); - l->append(", ["); - if (p.count > viz::DrawQuad::Resources::kMaxResourceIdCount) { - l->append("])"); - return; - } - - for (size_t i = 0; i < p.count; ++i) { - LogParam(p.ids[i], l); - if (i < (p.count - 1)) - l->append(", "); - } - l->append("])"); -} - -void ParamTraits<viz::YUVVideoDrawQuad>::Write(base::Pickle* m, - const param_type& p) { - ParamTraits<viz::DrawQuad>::Write(m, p); - WriteParam(m, p.ya_tex_coord_rect); - WriteParam(m, p.uv_tex_coord_rect); - WriteParam(m, p.ya_tex_size); - WriteParam(m, p.uv_tex_size); - WriteParam(m, p.video_color_space); - WriteParam(m, p.resource_offset); - WriteParam(m, p.resource_multiplier); - WriteParam(m, p.bits_per_channel); -} - -bool ParamTraits<viz::YUVVideoDrawQuad>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - return ParamTraits<viz::DrawQuad>::Read(m, iter, p) && - ReadParam(m, iter, &p->ya_tex_coord_rect) && - ReadParam(m, iter, &p->uv_tex_coord_rect) && - ReadParam(m, iter, &p->ya_tex_size) && - ReadParam(m, iter, &p->uv_tex_size) && - ReadParam(m, iter, &p->video_color_space) && - ReadParam(m, iter, &p->resource_offset) && - ReadParam(m, iter, &p->resource_multiplier) && - ReadParam(m, iter, &p->bits_per_channel) && - p->bits_per_channel >= viz::YUVVideoDrawQuad::kMinBitsPerChannel && - p->bits_per_channel <= viz::YUVVideoDrawQuad::kMaxBitsPerChannel; -} - -void ParamTraits<viz::YUVVideoDrawQuad>::Log(const param_type& p, - std::string* l) { - l->append("("); - ParamTraits<viz::DrawQuad>::Log(p, l); - l->append(", "); - LogParam(p.ya_tex_coord_rect, l); - l->append(", "); - LogParam(p.uv_tex_coord_rect, l); - l->append(", "); - LogParam(p.ya_tex_size, l); - l->append(", "); - LogParam(p.uv_tex_size, l); - l->append(", "); - LogParam(p.video_color_space, l); - l->append(", "); - LogParam(p.resource_offset, l); - l->append(", "); - LogParam(p.resource_multiplier, l); - l->append(", "); - LogParam(p.bits_per_channel, l); - l->append("])"); -} - -void ParamTraits<viz::BeginFrameAck>::Write(base::Pickle* m, - const param_type& p) { - m->WriteUInt64(p.sequence_number); - m->WriteUInt64(p.source_id); - // |has_damage| is implicit through IPC message name, so not transmitted. -} - -bool ParamTraits<viz::BeginFrameAck>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - return iter->ReadUInt64(&p->sequence_number) && - p->sequence_number >= viz::BeginFrameArgs::kStartingFrameNumber && - iter->ReadUInt64(&p->source_id); -} - -void ParamTraits<viz::BeginFrameAck>::Log(const param_type& p, std::string* l) { - l->append("("); - LogParam(p.sequence_number, l); - l->append(", "); - LogParam(p.source_id, l); - l->append(")"); -} - -} // namespace IPC - -// Generate param traits write methods. -#include "ipc/param_traits_write_macros.h" -namespace IPC { -#undef CC_IPC_CC_PARAM_TRAITS_MACROS_H_ -#include "cc/ipc/cc_param_traits_macros.h" -} // namespace IPC - -// Generate param traits read methods. -#include "ipc/param_traits_read_macros.h" -namespace IPC { -#undef CC_IPC_CC_PARAM_TRAITS_MACROS_H_ -#include "cc/ipc/cc_param_traits_macros.h" -} // namespace IPC - -// Generate param traits log methods. -#include "ipc/param_traits_log_macros.h" -namespace IPC { -#undef CC_IPC_CC_PARAM_TRAITS_MACROS_H_ -#include "cc/ipc/cc_param_traits_macros.h" -} // namespace IPC diff --git a/chromium/cc/ipc/cc_param_traits.h b/chromium/cc/ipc/cc_param_traits.h deleted file mode 100644 index bb575eb87f6..00000000000 --- a/chromium/cc/ipc/cc_param_traits.h +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 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. -// -// IPC Messages sent between compositor instances. - -#ifndef CC_IPC_CC_PARAM_TRAITS_H_ -#define CC_IPC_CC_PARAM_TRAITS_H_ - -#include "cc/ipc/cc_ipc_export.h" -#include "cc/ipc/cc_param_traits_macros.h" -#include "cc/paint/filter_operation.h" -#include "components/viz/common/quads/compositor_frame.h" -#include "components/viz/common/quads/draw_quad.h" -#include "components/viz/common/quads/frame_deadline.h" -#include "components/viz/common/quads/stream_video_draw_quad.h" -#include "components/viz/common/quads/texture_draw_quad.h" -#include "gpu/ipc/common/gpu_command_buffer_traits.h" -#include "ipc/ipc_message_macros.h" - -namespace cc { -class FilterOperations; -class PaintFilter; -} - -namespace IPC { - -template <> -struct ParamTraits<cc::FilterOperation> { - typedef cc::FilterOperation param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct ParamTraits<cc::FilterOperations> { - typedef cc::FilterOperations param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<sk_sp<cc::PaintFilter>> { - typedef sk_sp<cc::PaintFilter> param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::RenderPass> { - typedef viz::RenderPass param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::FrameDeadline> { - typedef viz::FrameDeadline param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::FrameSinkId> { - typedef viz::FrameSinkId param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::LocalSurfaceId> { - typedef viz::LocalSurfaceId param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::SurfaceId> { - typedef viz::SurfaceId param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::SurfaceInfo> { - typedef viz::SurfaceInfo param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::CompositorFrame> { - typedef viz::CompositorFrame param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::DrawQuad::Resources> { - typedef viz::DrawQuad::Resources param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::YUVVideoDrawQuad> { - typedef viz::YUVVideoDrawQuad param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct CC_IPC_EXPORT ParamTraits<viz::BeginFrameAck> { - typedef viz::BeginFrameAck param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p); - static void Log(const param_type& p, std::string* l); -}; - -} // namespace IPC - -#endif // CC_IPC_CC_PARAM_TRAITS_H_ diff --git a/chromium/cc/ipc/cc_param_traits_macros.h b/chromium/cc/ipc/cc_param_traits_macros.h deleted file mode 100644 index 1141b237a82..00000000000 --- a/chromium/cc/ipc/cc_param_traits_macros.h +++ /dev/null @@ -1,205 +0,0 @@ -// 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. - -#ifndef CC_IPC_CC_PARAM_TRAITS_MACROS_H_ -#define CC_IPC_CC_PARAM_TRAITS_MACROS_H_ - -#include "cc/paint/filter_operation.h" -#include "components/viz/common/frame_sinks/begin_frame_args.h" -#include "components/viz/common/quads/compositor_frame.h" -#include "components/viz/common/quads/debug_border_draw_quad.h" -#include "components/viz/common/quads/draw_quad.h" -#include "components/viz/common/quads/render_pass.h" -#include "components/viz/common/quads/render_pass_draw_quad.h" -#include "components/viz/common/quads/solid_color_draw_quad.h" -#include "components/viz/common/quads/stream_video_draw_quad.h" -#include "components/viz/common/quads/surface_draw_quad.h" -#include "components/viz/common/quads/texture_draw_quad.h" -#include "components/viz/common/quads/tile_draw_quad.h" -#include "components/viz/common/quads/yuv_video_draw_quad.h" -#include "components/viz/common/resources/resource_format.h" -#include "components/viz/common/resources/returned_resource.h" -#include "components/viz/common/resources/transferable_resource.h" -#include "components/viz/common/surfaces/surface_id.h" -#include "components/viz/common/surfaces/surface_info.h" -#include "ui/gfx/ipc/buffer_types/gfx_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 - -IPC_ENUM_TRAITS_MAX_VALUE(viz::DrawQuad::Material, viz::DrawQuad::MATERIAL_LAST) -IPC_ENUM_TRAITS_MAX_VALUE(cc::FilterOperation::FilterType, - cc::FilterOperation::FILTER_TYPE_LAST) -// TODO(wutao): This trait belongs with skia code. -IPC_ENUM_TRAITS_MAX_VALUE(SkBlurImageFilter::TileMode, - SkBlurImageFilter::kMax_TileMode) -IPC_ENUM_TRAITS_MAX_VALUE(viz::ResourceFormat, viz::RESOURCE_FORMAT_MAX) - -// TODO(fsamuel): This trait belongs with skia code. -IPC_ENUM_TRAITS_MAX_VALUE(SkBlendMode, SkBlendMode::kLastMode) - -IPC_STRUCT_TRAITS_BEGIN(viz::DrawQuad) - IPC_STRUCT_TRAITS_MEMBER(material) - IPC_STRUCT_TRAITS_MEMBER(rect) - IPC_STRUCT_TRAITS_MEMBER(visible_rect) - IPC_STRUCT_TRAITS_MEMBER(needs_blending) - IPC_STRUCT_TRAITS_MEMBER(resources) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::DebugBorderDrawQuad) - IPC_STRUCT_TRAITS_PARENT(viz::DrawQuad) - IPC_STRUCT_TRAITS_MEMBER(color) - IPC_STRUCT_TRAITS_MEMBER(width) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::RenderPassDrawQuad) - IPC_STRUCT_TRAITS_PARENT(viz::DrawQuad) - IPC_STRUCT_TRAITS_MEMBER(render_pass_id) - IPC_STRUCT_TRAITS_MEMBER(mask_uv_rect) - IPC_STRUCT_TRAITS_MEMBER(mask_texture_size) - IPC_STRUCT_TRAITS_MEMBER(filters_scale) - IPC_STRUCT_TRAITS_MEMBER(filters_origin) - IPC_STRUCT_TRAITS_MEMBER(tex_coord_rect) - IPC_STRUCT_TRAITS_MEMBER(force_anti_aliasing_off) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::SolidColorDrawQuad) - IPC_STRUCT_TRAITS_PARENT(viz::DrawQuad) - IPC_STRUCT_TRAITS_MEMBER(color) - IPC_STRUCT_TRAITS_MEMBER(force_anti_aliasing_off) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::StreamVideoDrawQuad) - IPC_STRUCT_TRAITS_PARENT(viz::DrawQuad) - IPC_STRUCT_TRAITS_MEMBER(overlay_resources) - IPC_STRUCT_TRAITS_MEMBER(matrix) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::StreamVideoDrawQuad::OverlayResources) - IPC_STRUCT_TRAITS_MEMBER(size_in_pixels) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::SurfaceDrawQuad) - IPC_STRUCT_TRAITS_PARENT(viz::DrawQuad) - IPC_STRUCT_TRAITS_MEMBER(primary_surface_id) - IPC_STRUCT_TRAITS_MEMBER(fallback_surface_id) - IPC_STRUCT_TRAITS_MEMBER(default_background_color) - IPC_STRUCT_TRAITS_MEMBER(stretch_content_to_fill_bounds) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::TextureDrawQuad) - IPC_STRUCT_TRAITS_PARENT(viz::DrawQuad) - IPC_STRUCT_TRAITS_MEMBER(overlay_resources) - IPC_STRUCT_TRAITS_MEMBER(premultiplied_alpha) - IPC_STRUCT_TRAITS_MEMBER(uv_top_left) - IPC_STRUCT_TRAITS_MEMBER(uv_bottom_right) - IPC_STRUCT_TRAITS_MEMBER(background_color) - IPC_STRUCT_TRAITS_MEMBER(vertex_opacity[0]) - IPC_STRUCT_TRAITS_MEMBER(vertex_opacity[1]) - IPC_STRUCT_TRAITS_MEMBER(vertex_opacity[2]) - IPC_STRUCT_TRAITS_MEMBER(vertex_opacity[3]) - IPC_STRUCT_TRAITS_MEMBER(y_flipped) - IPC_STRUCT_TRAITS_MEMBER(nearest_neighbor) - IPC_STRUCT_TRAITS_MEMBER(secure_output_only) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::TextureDrawQuad::OverlayResources) - IPC_STRUCT_TRAITS_MEMBER(size_in_pixels) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::TileDrawQuad) - IPC_STRUCT_TRAITS_PARENT(viz::DrawQuad) - IPC_STRUCT_TRAITS_MEMBER(tex_coord_rect) - IPC_STRUCT_TRAITS_MEMBER(texture_size) - IPC_STRUCT_TRAITS_MEMBER(swizzle_contents) - IPC_STRUCT_TRAITS_MEMBER(is_premultiplied) - IPC_STRUCT_TRAITS_MEMBER(nearest_neighbor) - IPC_STRUCT_TRAITS_MEMBER(force_anti_aliasing_off) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::SharedQuadState) - IPC_STRUCT_TRAITS_MEMBER(quad_to_target_transform) - IPC_STRUCT_TRAITS_MEMBER(quad_layer_rect) - IPC_STRUCT_TRAITS_MEMBER(visible_quad_layer_rect) - IPC_STRUCT_TRAITS_MEMBER(clip_rect) - IPC_STRUCT_TRAITS_MEMBER(is_clipped) - IPC_STRUCT_TRAITS_MEMBER(opacity) - IPC_STRUCT_TRAITS_MEMBER(blend_mode) - IPC_STRUCT_TRAITS_MEMBER(sorting_context_id) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::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) - IPC_STRUCT_TRAITS_MEMBER(read_lock_fences_enabled) - IPC_STRUCT_TRAITS_MEMBER(is_software) - IPC_STRUCT_TRAITS_MEMBER(shared_bitmap_sequence_number) - IPC_STRUCT_TRAITS_MEMBER(is_overlay_candidate) - IPC_STRUCT_TRAITS_MEMBER(color_space) -#if defined(OS_ANDROID) - IPC_STRUCT_TRAITS_MEMBER(is_backed_by_surface_texture) - IPC_STRUCT_TRAITS_MEMBER(wants_promotion_hint) -#endif -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::ReturnedResource) - IPC_STRUCT_TRAITS_MEMBER(id) - IPC_STRUCT_TRAITS_MEMBER(sync_token) - IPC_STRUCT_TRAITS_MEMBER(count) - IPC_STRUCT_TRAITS_MEMBER(lost) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::Selection<gfx::SelectionBound>) - IPC_STRUCT_TRAITS_MEMBER(start) - IPC_STRUCT_TRAITS_MEMBER(end) -IPC_STRUCT_TRAITS_END() - -IPC_ENUM_TRAITS_MAX_VALUE(viz::BeginFrameArgs::BeginFrameArgsType, - viz::BeginFrameArgs::BEGIN_FRAME_ARGS_TYPE_MAX - 1) - -IPC_STRUCT_TRAITS_BEGIN(viz::BeginFrameArgs) - IPC_STRUCT_TRAITS_MEMBER(frame_time) - IPC_STRUCT_TRAITS_MEMBER(deadline) - IPC_STRUCT_TRAITS_MEMBER(interval) - IPC_STRUCT_TRAITS_MEMBER(sequence_number) - IPC_STRUCT_TRAITS_MEMBER(source_id) - IPC_STRUCT_TRAITS_MEMBER(type) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(viz::CompositorFrameMetadata) - IPC_STRUCT_TRAITS_MEMBER(device_scale_factor) - IPC_STRUCT_TRAITS_MEMBER(root_scroll_offset) - IPC_STRUCT_TRAITS_MEMBER(page_scale_factor) - IPC_STRUCT_TRAITS_MEMBER(scrollable_viewport_size) - IPC_STRUCT_TRAITS_MEMBER(root_layer_size) - IPC_STRUCT_TRAITS_MEMBER(min_page_scale_factor) - IPC_STRUCT_TRAITS_MEMBER(max_page_scale_factor) - IPC_STRUCT_TRAITS_MEMBER(root_overflow_y_hidden) - IPC_STRUCT_TRAITS_MEMBER(may_contain_video) - IPC_STRUCT_TRAITS_MEMBER( - is_resourceless_software_draw_with_scroll_or_animation) - IPC_STRUCT_TRAITS_MEMBER(top_controls_height) - IPC_STRUCT_TRAITS_MEMBER(top_controls_shown_ratio) - IPC_STRUCT_TRAITS_MEMBER(bottom_controls_height) - IPC_STRUCT_TRAITS_MEMBER(bottom_controls_shown_ratio) - IPC_STRUCT_TRAITS_MEMBER(root_background_color) - IPC_STRUCT_TRAITS_MEMBER(selection) - IPC_STRUCT_TRAITS_MEMBER(latency_info) - IPC_STRUCT_TRAITS_MEMBER(referenced_surfaces) - IPC_STRUCT_TRAITS_MEMBER(deadline) - IPC_STRUCT_TRAITS_MEMBER(activation_dependencies) - 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_param_traits_unittest.cc b/chromium/cc/ipc/cc_param_traits_unittest.cc deleted file mode 100644 index 867bb9c39b0..00000000000 --- a/chromium/cc/ipc/cc_param_traits_unittest.cc +++ /dev/null @@ -1,665 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <string.h> -#include <algorithm> -#include <utility> - -#include "base/macros.h" -#include "build/build_config.h" -#include "cc/ipc/cc_param_traits.h" -#include "cc/resources/resource_provider.h" -#include "components/viz/common/quads/compositor_frame.h" -#include "components/viz/common/quads/frame_deadline.h" -#include "components/viz/common/quads/picture_draw_quad.h" -#include "components/viz/common/quads/render_pass_draw_quad.h" -#include "ipc/ipc_message.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_POSIX) -#include "base/file_descriptor_posix.h" -#endif - -using viz::CompositorFrame; -using cc::BlurPaintFilter; -using cc::FilterOperation; -using cc::FilterOperations; -using cc::ResourceProvider; -using gfx::Transform; -using viz::DebugBorderDrawQuad; -using viz::DrawQuad; -using viz::FrameDeadline; -using viz::PictureDrawQuad; -using viz::RenderPass; -using viz::RenderPassDrawQuad; -using viz::ResourceId; -using viz::SharedQuadState; -using viz::SolidColorDrawQuad; -using viz::StreamVideoDrawQuad; -using viz::SurfaceDrawQuad; -using viz::TextureDrawQuad; -using viz::TileDrawQuad; -using viz::TransferableResource; -using viz::YUVVideoDrawQuad; - -namespace content { -namespace { - -static constexpr viz::FrameSinkId kArbitraryFrameSinkId(1, 1); - -class CCParamTraitsTest : public testing::Test { - protected: - void Compare(const RenderPass* a, const RenderPass* b) { - EXPECT_EQ(a->id, b->id); - EXPECT_EQ(a->output_rect.ToString(), b->output_rect.ToString()); - EXPECT_EQ(a->damage_rect.ToString(), b->damage_rect.ToString()); - EXPECT_EQ(a->transform_to_root_target, b->transform_to_root_target); - EXPECT_EQ(a->filters.size(), b->filters.size()); - for (size_t i = 0; i < a->filters.size(); ++i) { - if (a->filters.at(i).type() != cc::FilterOperation::REFERENCE) { - EXPECT_EQ(a->filters.at(i), b->filters.at(i)); - } else { - EXPECT_EQ(b->filters.at(i).type(), cc::FilterOperation::REFERENCE); - EXPECT_EQ(a->filters.at(i).image_filter()->count_inputs(), - b->filters.at(i).image_filter()->count_inputs()); - } - } - EXPECT_EQ(a->background_filters.size(), b->background_filters.size()); - for (size_t i = 0; i < a->background_filters.size(); ++i) { - if (a->background_filters.at(i).type() != - cc::FilterOperation::REFERENCE) { - EXPECT_EQ(a->background_filters.at(i), b->background_filters.at(i)); - } else { - EXPECT_EQ(b->background_filters.at(i).type(), - cc::FilterOperation::REFERENCE); - EXPECT_EQ(a->background_filters.at(i).image_filter()->count_inputs(), - b->background_filters.at(i).image_filter()->count_inputs()); - } - } - EXPECT_EQ(a->color_space, b->color_space); - EXPECT_EQ(a->has_transparent_background, b->has_transparent_background); - } - - void Compare(const SharedQuadState* a, const SharedQuadState* b) { - EXPECT_EQ(a->quad_to_target_transform, b->quad_to_target_transform); - EXPECT_EQ(a->quad_layer_rect, b->quad_layer_rect); - EXPECT_EQ(a->visible_quad_layer_rect, b->visible_quad_layer_rect); - EXPECT_EQ(a->clip_rect, b->clip_rect); - EXPECT_EQ(a->is_clipped, b->is_clipped); - EXPECT_EQ(a->opacity, b->opacity); - EXPECT_EQ(a->blend_mode, b->blend_mode); - EXPECT_EQ(a->sorting_context_id, b->sorting_context_id); - } - - void Compare(const DrawQuad* a, const DrawQuad* b) { - ASSERT_NE(DrawQuad::INVALID, a->material); - ASSERT_EQ(a->material, b->material); - EXPECT_EQ(a->rect.ToString(), b->rect.ToString()); - EXPECT_EQ(a->visible_rect.ToString(), b->visible_rect.ToString()); - EXPECT_EQ(a->needs_blending, b->needs_blending); - - Compare(a->shared_quad_state, b->shared_quad_state); - - switch (a->material) { - case DrawQuad::DEBUG_BORDER: - Compare(DebugBorderDrawQuad::MaterialCast(a), - DebugBorderDrawQuad::MaterialCast(b)); - break; - case DrawQuad::PICTURE_CONTENT: - Compare(PictureDrawQuad::MaterialCast(a), - PictureDrawQuad::MaterialCast(b)); - break; - case DrawQuad::RENDER_PASS: - Compare(RenderPassDrawQuad::MaterialCast(a), - RenderPassDrawQuad::MaterialCast(b)); - break; - case DrawQuad::TEXTURE_CONTENT: - Compare(TextureDrawQuad::MaterialCast(a), - TextureDrawQuad::MaterialCast(b)); - break; - case DrawQuad::TILED_CONTENT: - Compare(TileDrawQuad::MaterialCast(a), TileDrawQuad::MaterialCast(b)); - break; - case DrawQuad::SOLID_COLOR: - Compare(SolidColorDrawQuad::MaterialCast(a), - SolidColorDrawQuad::MaterialCast(b)); - break; - case DrawQuad::STREAM_VIDEO_CONTENT: - Compare(StreamVideoDrawQuad::MaterialCast(a), - StreamVideoDrawQuad::MaterialCast(b)); - break; - case DrawQuad::SURFACE_CONTENT: - Compare(SurfaceDrawQuad::MaterialCast(a), - SurfaceDrawQuad::MaterialCast(b)); - break; - case DrawQuad::YUV_VIDEO_CONTENT: - Compare(YUVVideoDrawQuad::MaterialCast(a), - YUVVideoDrawQuad::MaterialCast(b)); - break; - case DrawQuad::INVALID: - break; - } - } - - void Compare(const DebugBorderDrawQuad* a, const DebugBorderDrawQuad* b) { - EXPECT_EQ(a->color, b->color); - EXPECT_EQ(a->width, b->width); - } - - void Compare(const RenderPassDrawQuad* a, const RenderPassDrawQuad* b) { - EXPECT_EQ(a->render_pass_id, b->render_pass_id); - EXPECT_EQ(a->mask_resource_id(), b->mask_resource_id()); - EXPECT_EQ(a->mask_uv_rect.ToString(), b->mask_uv_rect.ToString()); - EXPECT_EQ(a->mask_texture_size.ToString(), b->mask_texture_size.ToString()); - EXPECT_EQ(a->filters_scale, b->filters_scale); - EXPECT_EQ(a->filters_origin, b->filters_origin); - EXPECT_EQ(a->tex_coord_rect, b->tex_coord_rect); - EXPECT_EQ(a->force_anti_aliasing_off, b->force_anti_aliasing_off); - } - - void Compare(const SolidColorDrawQuad* a, const SolidColorDrawQuad* b) { - EXPECT_EQ(a->color, b->color); - EXPECT_EQ(a->force_anti_aliasing_off, b->force_anti_aliasing_off); - } - - void Compare(const StreamVideoDrawQuad* a, const StreamVideoDrawQuad* b) { - EXPECT_EQ(a->resource_id(), b->resource_id()); - EXPECT_EQ(a->resource_size_in_pixels(), b->resource_size_in_pixels()); - EXPECT_EQ(a->matrix, b->matrix); - } - - void Compare(const SurfaceDrawQuad* a, const SurfaceDrawQuad* b) { - EXPECT_EQ(a->primary_surface_id, b->primary_surface_id); - EXPECT_EQ(a->fallback_surface_id, b->fallback_surface_id); - EXPECT_EQ(a->default_background_color, b->default_background_color); - EXPECT_EQ(a->stretch_content_to_fill_bounds, - b->stretch_content_to_fill_bounds); - } - - void Compare(const TextureDrawQuad* a, const TextureDrawQuad* b) { - EXPECT_EQ(a->resource_id(), b->resource_id()); - EXPECT_EQ(a->resource_size_in_pixels(), b->resource_size_in_pixels()); - EXPECT_EQ(a->premultiplied_alpha, b->premultiplied_alpha); - EXPECT_EQ(a->uv_top_left, b->uv_top_left); - EXPECT_EQ(a->uv_bottom_right, b->uv_bottom_right); - EXPECT_EQ(a->background_color, b->background_color); - EXPECT_EQ(a->vertex_opacity[0], b->vertex_opacity[0]); - EXPECT_EQ(a->vertex_opacity[1], b->vertex_opacity[1]); - EXPECT_EQ(a->vertex_opacity[2], b->vertex_opacity[2]); - EXPECT_EQ(a->vertex_opacity[3], b->vertex_opacity[3]); - EXPECT_EQ(a->y_flipped, b->y_flipped); - EXPECT_EQ(a->nearest_neighbor, b->nearest_neighbor); - EXPECT_EQ(a->secure_output_only, b->secure_output_only); - } - - void Compare(const TileDrawQuad* a, const TileDrawQuad* b) { - EXPECT_EQ(a->resource_id(), b->resource_id()); - EXPECT_EQ(a->tex_coord_rect, b->tex_coord_rect); - EXPECT_EQ(a->texture_size, b->texture_size); - EXPECT_EQ(a->swizzle_contents, b->swizzle_contents); - EXPECT_EQ(a->nearest_neighbor, b->nearest_neighbor); - EXPECT_EQ(a->force_anti_aliasing_off, b->force_anti_aliasing_off); - } - - void Compare(const YUVVideoDrawQuad* a, const YUVVideoDrawQuad* b) { - EXPECT_EQ(a->ya_tex_coord_rect, b->ya_tex_coord_rect); - EXPECT_EQ(a->uv_tex_coord_rect, b->uv_tex_coord_rect); - EXPECT_EQ(a->ya_tex_size, b->ya_tex_size); - EXPECT_EQ(a->uv_tex_size, b->uv_tex_size); - EXPECT_EQ(a->y_plane_resource_id(), b->y_plane_resource_id()); - EXPECT_EQ(a->u_plane_resource_id(), b->u_plane_resource_id()); - EXPECT_EQ(a->v_plane_resource_id(), b->v_plane_resource_id()); - EXPECT_EQ(a->a_plane_resource_id(), b->a_plane_resource_id()); - EXPECT_EQ(a->video_color_space, b->video_color_space); - EXPECT_EQ(a->bits_per_channel, b->bits_per_channel); - EXPECT_EQ(a->require_overlay, b->require_overlay); - } - - void Compare(const TransferableResource& a, const TransferableResource& b) { - EXPECT_EQ(a.id, b.id); - EXPECT_EQ(a.format, b.format); - EXPECT_EQ(a.filter, b.filter); - EXPECT_EQ(a.size.ToString(), b.size.ToString()); - for (size_t i = 0; i < arraysize(a.mailbox_holder.mailbox.name); ++i) { - EXPECT_EQ(a.mailbox_holder.mailbox.name[i], - b.mailbox_holder.mailbox.name[i]); - } - EXPECT_EQ(a.mailbox_holder.texture_target, b.mailbox_holder.texture_target); - EXPECT_EQ(a.mailbox_holder.sync_token, b.mailbox_holder.sync_token); - EXPECT_EQ(a.is_overlay_candidate, b.is_overlay_candidate); -#if defined(OS_ANDROID) - EXPECT_EQ(a.is_backed_by_surface_texture, b.is_backed_by_surface_texture); - EXPECT_EQ(a.wants_promotion_hint, b.wants_promotion_hint); -#endif - } -}; - -TEST_F(CCParamTraitsTest, AllQuads) { - IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); - - Transform arbitrary_matrix1; - arbitrary_matrix1.Scale(3, 3); - arbitrary_matrix1.Translate(-5, 20); - arbitrary_matrix1.Rotate(15); - 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(40, 23, 11, 7); - gfx::Rect arbitrary_rect1_inside_rect2(44, 23, 4, 2); - gfx::Rect arbitrary_rect3(7, -53, 22, 19); - gfx::Rect arbitrary_rect2_inside_rect3(12, -51, 5, 12); - gfx::Size arbitrary_size1(15, 19); - gfx::Size arbitrary_size2(3, 99); - 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::PointF arbitrary_pointf1(31.4f, 15.9f); - gfx::PointF arbitrary_pointf2(26.5f, -35.8f); - 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; - int arbitrary_int = 13; - 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::CreateREC601(); - - int child_id = 30; - int root_id = 14; - - FilterOperations arbitrary_filters1; - arbitrary_filters1.Append( - FilterOperation::CreateGrayscaleFilter(arbitrary_float1)); - arbitrary_filters1.Append( - FilterOperation::CreateBlurFilter(arbitrary_float2)); - arbitrary_filters1.Append( - cc::FilterOperation::CreateReferenceFilter(sk_make_sp<BlurPaintFilter>( - arbitrary_sigma, arbitrary_sigma, - BlurPaintFilter::TileMode::kClampToBlack_TileMode, nullptr))); - - FilterOperations arbitrary_filters2; - arbitrary_filters2.Append( - FilterOperation::CreateBrightnessFilter(arbitrary_float2)); - - std::unique_ptr<RenderPass> child_pass_in = RenderPass::Create(); - child_pass_in->SetAll( - child_id, arbitrary_rect2, arbitrary_rect3, arbitrary_matrix2, - arbitrary_filters1, arbitrary_filters2, arbitrary_color_space, - arbitrary_bool2, arbitrary_bool3, arbitrary_bool4, arbitrary_bool5); - - std::unique_ptr<RenderPass> child_pass_cmp = RenderPass::Create(); - child_pass_cmp->SetAll( - child_id, arbitrary_rect2, arbitrary_rect3, arbitrary_matrix2, - arbitrary_filters1, arbitrary_filters2, arbitrary_color_space, - arbitrary_bool2, arbitrary_bool3, arbitrary_bool4, arbitrary_bool5); - - 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, arbitrary_bool2, arbitrary_bool3, - arbitrary_bool4); - - SharedQuadState* shared_state1_in = pass_in->CreateAndAppendSharedQuadState(); - shared_state1_in->SetAll(arbitrary_matrix1, arbitrary_rect1, arbitrary_rect1, - arbitrary_rect2, arbitrary_bool1, arbitrary_bool2, - arbitrary_float1, arbitrary_blend_mode1, - arbitrary_context_id1); - - std::unique_ptr<RenderPass> pass_cmp = RenderPass::Create(); - pass_cmp->SetAll(root_id, arbitrary_rect1, arbitrary_rect2, arbitrary_matrix1, - arbitrary_filters2, arbitrary_filters1, - arbitrary_color_space, arbitrary_bool1, arbitrary_bool2, - arbitrary_bool3, arbitrary_bool4); - - SharedQuadState* shared_state1_cmp = - pass_cmp->CreateAndAppendSharedQuadState(); - *shared_state1_cmp = *shared_state1_in; - - DebugBorderDrawQuad* debugborder_in = - pass_in->CreateAndAppendDrawQuad<DebugBorderDrawQuad>(); - debugborder_in->SetAll(shared_state1_in, arbitrary_rect3, - arbitrary_rect2_inside_rect3, arbitrary_bool1, - arbitrary_color, arbitrary_int); - pass_cmp->CopyFromAndAppendDrawQuad(debugborder_in); - - SharedQuadState* shared_state2_in = pass_in->CreateAndAppendSharedQuadState(); - shared_state2_in->SetAll(arbitrary_matrix2, arbitrary_rect2, arbitrary_rect2, - arbitrary_rect3, arbitrary_bool1, arbitrary_bool1, - arbitrary_float2, arbitrary_blend_mode2, - arbitrary_context_id2); - SharedQuadState* shared_state2_cmp = - pass_cmp->CreateAndAppendSharedQuadState(); - *shared_state2_cmp = *shared_state2_in; - - RenderPassDrawQuad* renderpass_in = - pass_in->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); - renderpass_in->SetAll(shared_state2_in, arbitrary_rect1, - arbitrary_rect1_inside_rect1, arbitrary_bool1, child_id, - arbitrary_resourceid2, arbitrary_rectf1, - arbitrary_size1, arbitrary_vector2df2, - arbitrary_pointf2, arbitrary_rectf1, arbitrary_bool2); - pass_cmp->CopyFromAndAppendRenderPassDrawQuad(renderpass_in, - renderpass_in->render_pass_id); - - SharedQuadState* shared_state3_in = pass_in->CreateAndAppendSharedQuadState(); - shared_state3_in->SetAll(arbitrary_matrix1, arbitrary_rect3, arbitrary_rect3, - arbitrary_rect1, arbitrary_bool1, arbitrary_bool2, - arbitrary_float3, arbitrary_blend_mode3, - arbitrary_context_id3); - SharedQuadState* shared_state3_cmp = - pass_cmp->CreateAndAppendSharedQuadState(); - *shared_state3_cmp = *shared_state3_in; - - auto* solidcolor_in = pass_in->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - solidcolor_in->SetAll(shared_state3_in, arbitrary_rect3, - arbitrary_rect2_inside_rect3, arbitrary_bool1, - arbitrary_color, arbitrary_bool2); - pass_cmp->CopyFromAndAppendDrawQuad(solidcolor_in); - - StreamVideoDrawQuad* streamvideo_in = - pass_in->CreateAndAppendDrawQuad<StreamVideoDrawQuad>(); - streamvideo_in->SetAll(shared_state3_in, arbitrary_rect2, - arbitrary_rect1_inside_rect2, arbitrary_bool1, - arbitrary_resourceid2, arbitrary_size1, - arbitrary_matrix1); - pass_cmp->CopyFromAndAppendDrawQuad(streamvideo_in); - - viz::SurfaceId arbitrary_surface_id( - kArbitraryFrameSinkId, - viz::LocalSurfaceId(3, base::UnguessableToken::Create())); - SurfaceDrawQuad* surface_in = - pass_in->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); - surface_in->SetAll(shared_state3_in, arbitrary_rect2, - arbitrary_rect1_inside_rect2, arbitrary_bool1, - arbitrary_surface_id, base::nullopt, SK_ColorWHITE, true); - pass_cmp->CopyFromAndAppendDrawQuad(surface_in); - - TextureDrawQuad* texture_in = - pass_in->CreateAndAppendDrawQuad<TextureDrawQuad>(); - texture_in->SetAll( - shared_state3_in, arbitrary_rect2, arbitrary_rect1_inside_rect2, - arbitrary_bool1, arbitrary_resourceid1, arbitrary_size1, arbitrary_bool2, - arbitrary_pointf1, arbitrary_pointf2, arbitrary_color, - arbitrary_float_array, arbitrary_bool4, arbitrary_bool5, arbitrary_bool6); - pass_cmp->CopyFromAndAppendDrawQuad(texture_in); - - TileDrawQuad* tile_in = pass_in->CreateAndAppendDrawQuad<TileDrawQuad>(); - tile_in->SetAll( - shared_state3_in, arbitrary_rect2, arbitrary_rect1_inside_rect2, - arbitrary_bool1, arbitrary_resourceid3, arbitrary_rectf1, arbitrary_size1, - arbitrary_bool2, arbitrary_bool3, arbitrary_bool4, arbitrary_bool5); - pass_cmp->CopyFromAndAppendDrawQuad(tile_in); - - YUVVideoDrawQuad* yuvvideo_in = - pass_in->CreateAndAppendDrawQuad<YUVVideoDrawQuad>(); - yuvvideo_in->SetAll( - shared_state3_in, arbitrary_rect1, arbitrary_rect1_inside_rect1, - arbitrary_bool1, arbitrary_rectf1, arbitrary_rectf2, arbitrary_size1, - arbitrary_size2, arbitrary_resourceid1, arbitrary_resourceid2, - arbitrary_resourceid3, arbitrary_resourceid4, arbitrary_color_space, - arbitrary_float1, arbitrary_float2, arbitrary_int, arbitrary_bool2); - pass_cmp->CopyFromAndAppendDrawQuad(yuvvideo_in); - - // Make sure the in and cmp RenderPasses match. - Compare(child_pass_cmp.get(), child_pass_in.get()); - ASSERT_EQ(0u, child_pass_in->shared_quad_state_list.size()); - ASSERT_EQ(0u, child_pass_in->quad_list.size()); - Compare(pass_cmp.get(), pass_in.get()); - ASSERT_EQ(3u, pass_in->shared_quad_state_list.size()); - ASSERT_EQ(8u, pass_in->quad_list.size()); - for (auto cmp_iterator = pass_cmp->shared_quad_state_list.cbegin(), - in_iterator = pass_in->shared_quad_state_list.cbegin(); - in_iterator != pass_in->shared_quad_state_list.cend(); - ++cmp_iterator, ++in_iterator) { - Compare(*cmp_iterator, *in_iterator); - } - for (auto in_iter = pass_in->quad_list.cbegin(), - cmp_iter = pass_cmp->quad_list.cbegin(); - in_iter != pass_in->quad_list.cend(); ++in_iter, ++cmp_iter) - Compare(*cmp_iter, *in_iter); - - for (size_t i = 1; i < pass_in->quad_list.size(); ++i) { - bool same_shared_quad_state_cmp = - pass_cmp->quad_list.ElementAt(i)->shared_quad_state == - pass_cmp->quad_list.ElementAt(i - 1)->shared_quad_state; - bool same_shared_quad_state_in = - pass_in->quad_list.ElementAt(i)->shared_quad_state == - pass_in->quad_list.ElementAt(i - 1)->shared_quad_state; - EXPECT_EQ(same_shared_quad_state_cmp, same_shared_quad_state_in); - } - - CompositorFrame frame_in; - frame_in.render_pass_list.push_back(std::move(child_pass_in)); - frame_in.render_pass_list.push_back(std::move(pass_in)); - frame_in.metadata.begin_frame_ack.sequence_number = - viz::BeginFrameArgs::kStartingFrameNumber; - const base::TimeTicks now = base::TimeTicks::Now(); - frame_in.metadata.deadline = - FrameDeadline(now, 4u, base::TimeDelta::FromMilliseconds(16), true); - - IPC::ParamTraits<CompositorFrame>::Write(&msg, frame_in); - - CompositorFrame frame_out; - base::PickleIterator iter(msg); - EXPECT_TRUE(IPC::ParamTraits<CompositorFrame>::Read(&msg, &iter, &frame_out)); - - EXPECT_EQ(FrameDeadline(now, 4u, base::TimeDelta::FromMilliseconds(16), true), - frame_out.metadata.deadline); - - // Make sure the out and cmp RenderPasses match. - std::unique_ptr<RenderPass> child_pass_out = - std::move(frame_out.render_pass_list[0]); - Compare(child_pass_cmp.get(), child_pass_out.get()); - ASSERT_EQ(0u, child_pass_out->shared_quad_state_list.size()); - ASSERT_EQ(0u, child_pass_out->quad_list.size()); - std::unique_ptr<RenderPass> pass_out = - std::move(frame_out.render_pass_list[1]); - Compare(pass_cmp.get(), pass_out.get()); - ASSERT_EQ(3u, pass_out->shared_quad_state_list.size()); - ASSERT_EQ(8u, pass_out->quad_list.size()); - for (auto cmp_iterator = pass_cmp->shared_quad_state_list.cbegin(), - out_iterator = pass_out->shared_quad_state_list.cbegin(); - out_iterator != pass_out->shared_quad_state_list.cend(); - ++cmp_iterator, ++out_iterator) { - Compare(*cmp_iterator, *out_iterator); - } - for (auto out_iter = pass_out->quad_list.cbegin(), - cmp_iter = pass_cmp->quad_list.cbegin(); - out_iter != pass_out->quad_list.cend(); ++out_iter, ++cmp_iter) - Compare(*cmp_iter, *out_iter); - - for (size_t i = 1; i < pass_out->quad_list.size(); ++i) { - bool same_shared_quad_state_cmp = - pass_cmp->quad_list.ElementAt(i)->shared_quad_state == - pass_cmp->quad_list.ElementAt(i - 1)->shared_quad_state; - bool same_shared_quad_state_out = - pass_out->quad_list.ElementAt(i)->shared_quad_state == - pass_out->quad_list.ElementAt(i - 1)->shared_quad_state; - EXPECT_EQ(same_shared_quad_state_cmp, same_shared_quad_state_out); - } -} - -TEST_F(CCParamTraitsTest, UnusedSharedQuadStates) { - std::unique_ptr<RenderPass> pass_in = RenderPass::Create(); - pass_in->SetAll(1, gfx::Rect(100, 100), gfx::Rect(), gfx::Transform(), - FilterOperations(), FilterOperations(), - gfx::ColorSpace::CreateSRGB(), false, false, false, false); - - // The first SharedQuadState is used. - SharedQuadState* shared_state1_in = pass_in->CreateAndAppendSharedQuadState(); - shared_state1_in->SetAll(gfx::Transform(), gfx::Rect(1, 1), gfx::Rect(), - gfx::Rect(), false, true, 1.f, SkBlendMode::kSrcOver, - 0); - - auto* quad1 = pass_in->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - quad1->SetAll(shared_state1_in, gfx::Rect(10, 10), gfx::Rect(10, 10), false, - SK_ColorRED, false); - - // The second and third SharedQuadStates are not used. - SharedQuadState* shared_state2_in = pass_in->CreateAndAppendSharedQuadState(); - shared_state2_in->SetAll(gfx::Transform(), gfx::Rect(2, 2), gfx::Rect(), - gfx::Rect(), false, true, 1.f, SkBlendMode::kSrcOver, - 0); - - SharedQuadState* shared_state3_in = pass_in->CreateAndAppendSharedQuadState(); - shared_state3_in->SetAll(gfx::Transform(), gfx::Rect(3, 3), gfx::Rect(), - gfx::Rect(), false, true, 1.f, SkBlendMode::kSrcOver, - 0); - - // The fourth SharedQuadState is used. - SharedQuadState* shared_state4_in = pass_in->CreateAndAppendSharedQuadState(); - shared_state4_in->SetAll(gfx::Transform(), gfx::Rect(4, 4), gfx::Rect(), - gfx::Rect(), false, true, 1.f, SkBlendMode::kSrcOver, - 0); - - auto* quad2 = pass_in->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - quad2->SetAll(shared_state4_in, gfx::Rect(10, 10), gfx::Rect(10, 10), false, - SK_ColorRED, false); - - // The fifth is not used again. - SharedQuadState* shared_state5_in = pass_in->CreateAndAppendSharedQuadState(); - shared_state5_in->SetAll(gfx::Transform(), gfx::Rect(5, 5), gfx::Rect(), - gfx::Rect(), false, true, 1.f, SkBlendMode::kSrcOver, - 0); - - // 5 SharedQuadStates go in. - ASSERT_EQ(5u, pass_in->shared_quad_state_list.size()); - ASSERT_EQ(2u, pass_in->quad_list.size()); - - CompositorFrame frame_in; - frame_in.render_pass_list.push_back(std::move(pass_in)); - frame_in.metadata.begin_frame_ack.sequence_number = - viz::BeginFrameArgs::kStartingFrameNumber; - - IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); - IPC::ParamTraits<CompositorFrame>::Write(&msg, frame_in); - - CompositorFrame frame_out; - base::PickleIterator iter(msg); - EXPECT_TRUE(IPC::ParamTraits<CompositorFrame>::Read(&msg, &iter, &frame_out)); - - std::unique_ptr<RenderPass> pass_out = - std::move(frame_out.render_pass_list[0]); - - // 2 SharedQuadStates come out. The first and fourth SharedQuadStates were - // used by quads, and so serialized. Others were not. - ASSERT_EQ(2u, pass_out->shared_quad_state_list.size()); - ASSERT_EQ(2u, pass_out->quad_list.size()); - - EXPECT_EQ(gfx::Rect(1, 1).ToString(), - pass_out->shared_quad_state_list.ElementAt(0) - ->quad_layer_rect.ToString()); - EXPECT_EQ(gfx::Rect(4, 4).ToString(), - pass_out->shared_quad_state_list.ElementAt(1) - ->quad_layer_rect.ToString()); -} - -TEST_F(CCParamTraitsTest, Resources) { - IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); - gpu::SyncToken arbitrary_token1(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x123), - 71234838); - arbitrary_token1.SetVerifyFlush(); - gpu::SyncToken arbitrary_token2(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x123), - 53589793); - arbitrary_token2.SetVerifyFlush(); - - GLbyte arbitrary_mailbox1[GL_MAILBOX_SIZE_CHROMIUM] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}; - - GLbyte arbitrary_mailbox2[GL_MAILBOX_SIZE_CHROMIUM] = { - 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 9, 7, 5, 3, 1, 2}; - - TransferableResource arbitrary_resource1; - arbitrary_resource1.id = 2178312; - arbitrary_resource1.format = viz::RGBA_8888; - arbitrary_resource1.filter = 53; - arbitrary_resource1.size = gfx::Size(37189, 123123); - arbitrary_resource1.mailbox_holder.mailbox.SetName(arbitrary_mailbox1); - arbitrary_resource1.mailbox_holder.texture_target = GL_TEXTURE_2D; - arbitrary_resource1.mailbox_holder.sync_token = arbitrary_token1; - arbitrary_resource1.is_overlay_candidate = true; -#if defined(OS_ANDROID) - arbitrary_resource1.is_backed_by_surface_texture = true; - arbitrary_resource1.wants_promotion_hint = true; -#endif - - TransferableResource arbitrary_resource2; - arbitrary_resource2.id = 789132; - arbitrary_resource2.format = viz::RGBA_4444; - arbitrary_resource2.filter = 47; - arbitrary_resource2.size = gfx::Size(89123, 23789); - arbitrary_resource2.mailbox_holder.mailbox.SetName(arbitrary_mailbox2); - arbitrary_resource2.mailbox_holder.texture_target = GL_TEXTURE_EXTERNAL_OES; - arbitrary_resource2.mailbox_holder.sync_token = arbitrary_token2; - arbitrary_resource2.is_overlay_candidate = false; -#if defined(OS_ANDROID) - arbitrary_resource2.is_backed_by_surface_texture = false; - arbitrary_resource2.wants_promotion_hint = false; -#endif - - std::unique_ptr<RenderPass> renderpass_in = RenderPass::Create(); - renderpass_in->SetNew(1u, gfx::Rect(0, 0, 5, 5), gfx::Rect(), - gfx::Transform()); - - CompositorFrame frame_in; - frame_in.resource_list.push_back(arbitrary_resource1); - frame_in.resource_list.push_back(arbitrary_resource2); - frame_in.render_pass_list.push_back(std::move(renderpass_in)); - frame_in.metadata.begin_frame_ack.sequence_number = - viz::BeginFrameArgs::kStartingFrameNumber; - - IPC::ParamTraits<CompositorFrame>::Write(&msg, frame_in); - - CompositorFrame frame_out; - base::PickleIterator iter(msg); - EXPECT_TRUE(IPC::ParamTraits<CompositorFrame>::Read(&msg, &iter, &frame_out)); - - ASSERT_EQ(2u, frame_out.resource_list.size()); - Compare(arbitrary_resource1, frame_out.resource_list[0]); - Compare(arbitrary_resource2, frame_out.resource_list[1]); -} - -TEST_F(CCParamTraitsTest, SurfaceInfo) { - IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); - const viz::SurfaceId kArbitrarySurfaceId( - kArbitraryFrameSinkId, - viz::LocalSurfaceId(3, base::UnguessableToken::Create())); - constexpr float kArbitraryDeviceScaleFactor = 0.9f; - const gfx::Size kArbitrarySize(65, 321); - const viz::SurfaceInfo surface_info_in( - kArbitrarySurfaceId, kArbitraryDeviceScaleFactor, kArbitrarySize); - IPC::ParamTraits<viz::SurfaceInfo>::Write(&msg, surface_info_in); - - viz::SurfaceInfo surface_info_out; - base::PickleIterator iter(msg); - EXPECT_TRUE( - IPC::ParamTraits<viz::SurfaceInfo>::Read(&msg, &iter, &surface_info_out)); - - ASSERT_EQ(surface_info_in, surface_info_out); -} - -} // namespace -} // namespace content diff --git a/chromium/cc/ipc/cc_serialization_perftest.cc b/chromium/cc/ipc/cc_serialization_perftest.cc deleted file mode 100644 index 7dc52dcff3f..00000000000 --- a/chromium/cc/ipc/cc_serialization_perftest.cc +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" -#include "cc/ipc/cc_param_traits.h" -#include "components/viz/common/quads/compositor_frame.h" -#include "components/viz/common/quads/picture_draw_quad.h" -#include "components/viz/test/compositor_frame_helpers.h" -#include "gpu/ipc/common/mailbox_holder_struct_traits.h" -#include "gpu/ipc/common/mailbox_struct_traits.h" -#include "gpu/ipc/common/sync_token_struct_traits.h" -#include "ipc/ipc_message.h" -#include "mojo/public/cpp/base/time_mojom_traits.h" -#include "mojo/public/cpp/bindings/message.h" -#include "services/viz/public/cpp/compositing/compositor_frame_metadata_struct_traits.h" -#include "services/viz/public/cpp/compositing/compositor_frame_struct_traits.h" -#include "services/viz/public/cpp/compositing/render_pass_struct_traits.h" -#include "services/viz/public/cpp/compositing/selection_struct_traits.h" -#include "services/viz/public/cpp/compositing/shared_quad_state_struct_traits.h" -#include "services/viz/public/cpp/compositing/surface_id_struct_traits.h" -#include "services/viz/public/interfaces/compositing/compositor_frame.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/perf/perf_test.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 { - -static const int kTimeLimitMillis = 2000; -static const int kNumWarmupRuns = 20; -static const int kTimeCheckInterval = 10; - -enum class UseSingleSharedQuadState { YES, NO }; - -class CCSerializationPerfTest : public testing::Test { - protected: - static void ReadMessage(const IPC::Message* msg, - viz::CompositorFrame* frame) { - base::PickleIterator iter(*msg); - bool success = - IPC::ParamTraits<viz::CompositorFrame>::Read(msg, &iter, frame); - CHECK(success); - } - - static void RunDeserializationTestParamTraits( - const std::string& test_name, - const viz::CompositorFrame& frame, - UseSingleSharedQuadState single_sqs) { - IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); - IPC::ParamTraits<viz::CompositorFrame>::Write(&msg, frame); - for (int i = 0; i < kNumWarmupRuns; ++i) { - viz::CompositorFrame compositor_frame; - ReadMessage(&msg, &compositor_frame); - } - - base::TimeTicks start = base::TimeTicks::Now(); - base::TimeTicks end = - start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis); - base::TimeTicks now = start; - base::TimeDelta min_time; - size_t count = 0; - while (start < end) { - for (int i = 0; i < kTimeCheckInterval; ++i) { - viz::CompositorFrame compositor_frame; - ReadMessage(&msg, &compositor_frame); - now = base::TimeTicks::Now(); - // We don't count iterations after the end time. - if (now < end) - ++count; - } - - if (now - start < min_time || min_time.is_zero()) - min_time = now - start; - start = now; - } - - perf_test::PrintResult( - "ParamTraits deserialization: min_frame_deserialization_time", - single_sqs == UseSingleSharedQuadState::YES - ? "_per_render_pass_shared_quad_state" - : "_per_quad_shared_quad_state", - test_name, min_time.InMillisecondsF() / kTimeCheckInterval * 1000, "us", - true); - perf_test::PrintResult("ParamTraits deserialization: num runs in 2 seconds", - single_sqs == UseSingleSharedQuadState::YES - ? "_per_render_pass_shared_quad_state" - : "_per_quad_shared_quad_state", - test_name, count, "runs/s", true); - } - - static void RunSerializationTestParamTraits( - const std::string& test_name, - const viz::CompositorFrame& frame, - UseSingleSharedQuadState single_sqs) { - for (int i = 0; i < kNumWarmupRuns; ++i) { - IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); - IPC::ParamTraits<viz::CompositorFrame>::Write(&msg, frame); - } - - base::TimeTicks start = base::TimeTicks::Now(); - base::TimeTicks end = - start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis); - base::TimeTicks now = start; - base::TimeDelta min_time; - size_t count = 0; - while (start < end) { - for (int i = 0; i < kTimeCheckInterval; ++i) { - IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); - IPC::ParamTraits<viz::CompositorFrame>::Write(&msg, frame); - now = base::TimeTicks::Now(); - // We don't count iterations after the end time. - if (now < end) - ++count; - } - - if (now - start < min_time || min_time.is_zero()) - min_time = now - start; - start = now; - } - - perf_test::PrintResult( - "ParamTraits serialization: min_frame_serialization_time", - single_sqs == UseSingleSharedQuadState::YES - ? "_per_render_pass_shared_quad_state" - : "_per_quad_shared_quad_state", - test_name, min_time.InMillisecondsF() / kTimeCheckInterval * 1000, "us", - true); - perf_test::PrintResult("ParamTraits serialization: num runs in 2 seconds", - single_sqs == UseSingleSharedQuadState::YES - ? "_per_render_pass_shared_quad_state" - : "_per_quad_shared_quad_state", - test_name, count, "runs/s", true); - } - - static void RunDeserializationTestStructTraits( - const std::string& test_name, - const viz::CompositorFrame& frame, - UseSingleSharedQuadState single_sqs) { - mojo::Message message = - viz::mojom::CompositorFrame::SerializeAsMessage(&frame); - for (int i = 0; i < kNumWarmupRuns; ++i) { - viz::CompositorFrame compositor_frame; - viz::mojom::CompositorFrame::Deserialize( - message.payload(), message.payload_num_bytes(), &compositor_frame); - } - - base::TimeTicks start = base::TimeTicks::Now(); - base::TimeTicks end = - start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis); - base::TimeTicks now = start; - base::TimeDelta min_time; - size_t count = 0; - while (start < end) { - for (int i = 0; i < kTimeCheckInterval; ++i) { - viz::CompositorFrame compositor_frame; - viz::mojom::CompositorFrame::Deserialize( - message.payload(), message.payload_num_bytes(), &compositor_frame); - now = base::TimeTicks::Now(); - // We don't count iterations after the end time. - if (now < end) - ++count; - } - - if (now - start < min_time || min_time.is_zero()) - min_time = now - start; - start = now; - } - - perf_test::PrintResult( - "StructTraits deserialization min_frame_deserialization_time", - single_sqs == UseSingleSharedQuadState::YES - ? "_per_render_pass_shared_quad_state" - : "_per_quad_shared_quad_state", - test_name, min_time.InMillisecondsF() / kTimeCheckInterval * 1000, "us", - true); - perf_test::PrintResult( - "StructTraits deserialization: num runs in 2 seconds", - single_sqs == UseSingleSharedQuadState::YES - ? "_per_render_pass_shared_quad_state" - : "_per_quad_shared_quad_state", - test_name, count, "runs/s", true); - } - - static void RunSerializationTestStructTraits( - const std::string& test_name, - const viz::CompositorFrame& frame, - UseSingleSharedQuadState single_sqs) { - for (int i = 0; i < kNumWarmupRuns; ++i) { - mojo::Message message = - viz::mojom::CompositorFrame::SerializeAsMessage(&frame); - } - - base::TimeTicks start = base::TimeTicks::Now(); - base::TimeTicks end = - start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis); - base::TimeTicks now = start; - base::TimeDelta min_time; - size_t count = 0; - while (start < end) { - for (int i = 0; i < kTimeCheckInterval; ++i) { - mojo::Message message = - viz::mojom::CompositorFrame::SerializeAsMessage(&frame); - now = base::TimeTicks::Now(); - // We don't count iterations after the end time. - if (now < end) - ++count; - } - - if (now - start < min_time || min_time.is_zero()) - min_time = now - start; - start = now; - } - - perf_test::PrintResult( - "StructTraits serialization min_frame_serialization_time", - single_sqs == UseSingleSharedQuadState::YES - ? "_per_render_pass_shared_quad_state" - : "_per_quad_shared_quad_state", - test_name, min_time.InMillisecondsF() / kTimeCheckInterval * 1000, "us", - true); - perf_test::PrintResult("StructTraits serialization: num runs in 2 seconds", - single_sqs == UseSingleSharedQuadState::YES - ? "_per_render_pass_shared_quad_state" - : "_per_quad_shared_quad_state", - test_name, count, "runs/s", true); - } - - static void RunComplexCompositorFrameTest(const std::string& test_name) { - viz::CompositorFrame frame; - frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true); - - std::vector<viz::TransferableResource>& resource_list = frame.resource_list; - for (uint32_t i = 0; i < 80; ++i) { - viz::TransferableResource arbitrary_resource; - resource_list.push_back(arbitrary_resource); - } - - auto& 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_rect2(40, 23, 11, 7); - gfx::Rect arbitrary_rect1_inside_rect2(44, 23, 4, 2); - gfx::Rect arbitrary_rect3(7, -53, 22, 19); - gfx::Rect arbitrary_rect2_inside_rect3(12, -51, 5, 12); - gfx::Size arbitrary_size1(15, 19); - gfx::Size arbitrary_size2(3, 99); - gfx::RectF arbitrary_rectf1(4.2f, -922.1f, 15.6f, 29.5f); - gfx::PointF arbitrary_pointf1(31.4f, 15.9f); - gfx::PointF arbitrary_pointf2(26.5f, -35.8f); - 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; - viz::ResourceId arbitrary_resourceid1 = 55; - viz::ResourceId arbitrary_resourceid2 = 47; - viz::ResourceId arbitrary_resourceid3 = 23; - viz::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(sk_make_sp<BlurPaintFilter>( - arbitrary_sigma, arbitrary_sigma, - BlurPaintFilter::TileMode::kClampToBlack_TileMode, nullptr))); - - FilterOperations arbitrary_filters2; - arbitrary_filters2.Append( - FilterOperation::CreateBrightnessFilter(arbitrary_float2)); - - std::unique_ptr<viz::RenderPass> pass_in = viz::RenderPass::Create(); - pass_in->SetAll(root_id, arbitrary_rect1, arbitrary_rect2, - arbitrary_matrix1, arbitrary_filters2, arbitrary_filters1, - arbitrary_color_space, arbitrary_bool1, arbitrary_bool1, - arbitrary_bool1, arbitrary_bool1); - - // Texture quads - for (uint32_t i = 0; i < 10; ++i) { - viz::SharedQuadState* shared_state1_in = - pass_in->CreateAndAppendSharedQuadState(); - shared_state1_in->SetAll( - arbitrary_matrix1, arbitrary_rect1, arbitrary_rect1, arbitrary_rect2, - arbitrary_bool1, arbitrary_bool1, arbitrary_float1, - arbitrary_blend_mode1, arbitrary_context_id1); - - auto* texture_in = - pass_in->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); - texture_in->SetAll(shared_state1_in, arbitrary_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); - - auto* texture_in2 = - pass_in->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); - texture_in2->SetAll(shared_state1_in, arbitrary_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); - - auto* texture_in3 = - pass_in->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); - texture_in3->SetAll(shared_state1_in, arbitrary_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); - - auto* texture_in4 = - pass_in->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); - texture_in4->SetAll(shared_state1_in, arbitrary_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) { - viz::SharedQuadState* shared_state2_in = - pass_in->CreateAndAppendSharedQuadState(); - shared_state2_in->SetAll( - arbitrary_matrix2, arbitrary_rect2, arbitrary_rect2, arbitrary_rect3, - arbitrary_bool1, arbitrary_bool1, arbitrary_float2, - arbitrary_blend_mode2, arbitrary_context_id2); - for (uint32_t j = 0; j < 6; ++j) { - auto* tile_in = pass_in->CreateAndAppendDrawQuad<viz::TileDrawQuad>(); - tile_in->SetAll(shared_state2_in, arbitrary_rect2, - arbitrary_rect1_inside_rect2, arbitrary_bool1, - arbitrary_resourceid3, arbitrary_rectf1, - arbitrary_size1, arbitrary_bool2, arbitrary_bool3, - arbitrary_bool4, arbitrary_bool5); - } - } - - // Solid color quads - for (uint32_t i = 0; i < 5; ++i) { - viz::SharedQuadState* shared_state3_in = - pass_in->CreateAndAppendSharedQuadState(); - shared_state3_in->SetAll( - arbitrary_matrix1, arbitrary_rect3, arbitrary_rect3, arbitrary_rect1, - arbitrary_bool1, arbitrary_bool1, arbitrary_float3, - arbitrary_blend_mode3, arbitrary_context_id3); - for (uint32_t j = 0; j < 5; ++j) { - auto* solidcolor_in = - pass_in->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>(); - solidcolor_in->SetAll(shared_state3_in, arbitrary_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, - UseSingleSharedQuadState single_sqs) { - viz::CompositorFrame frame = viz::MakeEmptyCompositorFrame(); - - for (uint32_t i = 0; i < num_passes; ++i) { - std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create(); - render_pass->SetNew(1, gfx::Rect(20, 20), gfx::Rect(), gfx::Transform()); - for (uint32_t j = 0; j < num_quads; ++j) { - if (j == 0 || single_sqs == UseSingleSharedQuadState::NO) - render_pass->CreateAndAppendSharedQuadState(); - const gfx::Rect bounds(100, 100, 100, 100); - const bool kForceAntiAliasingOff = true; - auto* quad = - render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>(); - quad->SetNew(render_pass->shared_quad_state_list.back(), bounds, bounds, - SK_ColorRED, kForceAntiAliasingOff); - } - frame.render_pass_list.push_back(std::move(render_pass)); - } - RunTest(test_name, std::move(frame), single_sqs); - } - - static void RunTest(const std::string& test_name, - viz::CompositorFrame frame, - UseSingleSharedQuadState single_sqs) { - RunSerializationTestStructTraits(test_name, frame, single_sqs); - RunDeserializationTestStructTraits(test_name, frame, single_sqs); - RunSerializationTestParamTraits(test_name, frame, single_sqs); - RunDeserializationTestParamTraits(test_name, frame, single_sqs); - } -}; - -// 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. - RunCompositorFrameTest("DelegatedFrame_ManyQuads_1_4000", 4000, 1, - UseSingleSharedQuadState::YES); - // Case 2: One shared quad state for each quad. - RunCompositorFrameTest("DelegatedFrame_ManyQuads_1_4000", 4000, 1, - UseSingleSharedQuadState::NO); -} - -// 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. - RunCompositorFrameTest("DelegatedFrame_ManyRenderPasses_5_100", 100, 5, - UseSingleSharedQuadState::YES); - // Case 2: One shared quad state for each quad. - RunCompositorFrameTest("DelegatedFrame_ManyRenderPasses_5_100", 100, 5, - UseSingleSharedQuadState::NO); -} - -// Test for compositor frames with 10 render pass and each with 500 quads. -TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyRenderPasses_10_500) { - // Case 1: One shared quad state for all quads in one render pass. - RunCompositorFrameTest("DelegatedFrame_ManyRenderPasses_10_500", 500, 10, - UseSingleSharedQuadState::YES); - // Case 2: One shared quad state for each quad. - RunCompositorFrameTest("DelegatedFrame_ManyRenderPasses_10_500", 500, 10, - UseSingleSharedQuadState::NO); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/layers/content_layer_client.h b/chromium/cc/layers/content_layer_client.h index c5d005f85a2..7f61a99ccef 100644 --- a/chromium/cc/layers/content_layer_client.h +++ b/chromium/cc/layers/content_layer_client.h @@ -34,8 +34,12 @@ class CC_EXPORT ContentLayerClient { // that is guaranteed valid only within this region. virtual gfx::Rect PaintableRegion() = 0; + // Paints the content area for the layer, typically dirty rects submitted + // to the layer itself, into a DisplayItemList that it returns. The + // PaintingControlSetting enum controls painting to isolate different + // components in performance tests. virtual scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting painting_status) = 0; + PaintingControlSetting painting_control) = 0; // If true the layer may skip clearing the background before rasterizing, // because it will cover any uncleared data with content. diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc index 8f2a21ea3fd..890f7ec426c 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.cc +++ b/chromium/cc/layers/heads_up_display_layer_impl.cc @@ -11,6 +11,7 @@ #include <vector> #include "base/numerics/safe_conversions.h" +#include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" @@ -28,6 +29,7 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/resources/bitmap_allocation.h" +#include "components/viz/common/resources/platform_color.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "skia/ext/platform_canvas.h" @@ -138,12 +140,12 @@ bool HeadsUpDisplayLayerImpl::WillDraw( if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) return false; + int max_texture_size = layer_tree_impl()->max_texture_size(); internal_contents_scale_ = GetIdealContentsScale(); internal_content_bounds_ = gfx::ScaleToCeiledSize(bounds(), internal_contents_scale_); internal_content_bounds_.SetToMin( - gfx::Size(resource_provider->max_texture_size(), - resource_provider->max_texture_size())); + gfx::Size(max_texture_size, max_texture_size)); return LayerImpl::WillDraw(draw_mode, resource_provider); } @@ -185,17 +187,10 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture( layer_tree_impl()->task_runner_provider()->HasImplThread() ? layer_tree_impl()->task_runner_provider()->ImplThreadTaskRunner() : layer_tree_impl()->task_runner_provider()->MainThreadTaskRunner(); - if (draw_mode == DRAW_MODE_HARDWARE) { - pool_ = std::make_unique<ResourcePool>( - resource_provider, std::move(task_runner), - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu, - layer_tree_impl()->settings().disallow_non_exact_resource_reuse); - } else { - pool_ = std::make_unique<ResourcePool>( - resource_provider, std::move(task_runner), - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kSoftware, - layer_tree_impl()->settings().disallow_non_exact_resource_reuse); - } + pool_ = std::make_unique<ResourcePool>( + resource_provider, layer_tree_frame_sink->context_provider(), + std::move(task_runner), ResourcePool::kDefaultExpirationDelay, + layer_tree_impl()->settings().disallow_non_exact_resource_reuse); } // Return ownership of the previous frame's resource to the pool, so we @@ -205,17 +200,20 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture( if (in_flight_resource_) pool_->ReleaseResource(std::move(in_flight_resource_)); - ResourcePool::InUsePoolResource pool_resource = pool_->AcquireResource( - internal_content_bounds_, resource_provider->best_render_buffer_format(), - gfx::ColorSpace()); - // Allocate a backing for the resource if needed, either for gpu or software // compositing. + ResourcePool::InUsePoolResource pool_resource; if (draw_mode == DRAW_MODE_HARDWARE) { viz::ContextProvider* context_provider = layer_tree_impl()->context_provider(); DCHECK(context_provider); + viz::ResourceFormat format = + viz::PlatformColor::BestSupportedRenderBufferFormat( + context_provider->ContextCapabilities()); + pool_resource = pool_->AcquireResource(internal_content_bounds_, format, + gfx::ColorSpace()); + if (!pool_resource.gpu_backing()) { auto backing = std::make_unique<HudGpuBacking>(); backing->compositor_context_provider = context_provider; @@ -245,6 +243,9 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture( } else { DCHECK_EQ(draw_mode, DRAW_MODE_SOFTWARE); + pool_resource = pool_->AcquireResource(internal_content_bounds_, + viz::RGBA_8888, gfx::ColorSpace()); + if (!pool_resource.software_backing()) { auto backing = std::make_unique<HudSoftwareBacking>(); backing->layer_tree_frame_sink = layer_tree_frame_sink; diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc index f8f478a6486..c5fb253d85e 100644 --- a/chromium/cc/layers/layer.cc +++ b/chromium/cc/layers/layer.cc @@ -65,7 +65,6 @@ Layer::Inputs::Inputs(int layer_id) has_will_change_transform_hint(false), trilinear_filtering(false), hide_layer_and_subtree(false), - client_rawptr(nullptr), overscroll_behavior(OverscrollBehavior::kOverscrollBehaviorTypeAuto) {} Layer::Inputs::~Inputs() = default; @@ -887,12 +886,15 @@ void Layer::AddMainThreadScrollingReasons( uint32_t main_thread_scrolling_reasons) { DCHECK(IsPropertyChangeAllowed()); DCHECK(main_thread_scrolling_reasons); + // Layer should only see non-transient scrolling reasons. Transient scrolling + // reasons are computed per hit test. + DCHECK(MainThreadScrollingReason::MainThreadCanSetScrollReasons( + main_thread_scrolling_reasons)); uint32_t new_reasons = inputs_.main_thread_scrolling_reasons | main_thread_scrolling_reasons; if (inputs_.main_thread_scrolling_reasons == new_reasons) return; inputs_.main_thread_scrolling_reasons = new_reasons; - didUpdateMainThreadScrollingReasons(); SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -906,7 +908,6 @@ void Layer::ClearMainThreadScrollingReasons( if (new_reasons == inputs_.main_thread_scrolling_reasons) return; inputs_.main_thread_scrolling_reasons = new_reasons; - didUpdateMainThreadScrollingReasons(); SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } @@ -1164,9 +1165,7 @@ void Layer::SetStickyPositionConstraint( void Layer::SetLayerClient(base::WeakPtr<LayerClient> client) { inputs_.client = std::move(client); - // Both binds the weak_ptr to the main thread and stores a rawptr for access - // during commit. - inputs_.client_rawptr = client.get(); + inputs_.debug_info = nullptr; } bool Layer::IsSnapped() { @@ -1185,14 +1184,7 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->SetBackgroundColor(inputs_.background_color); layer->SetSafeOpaqueBackgroundColor(safe_opaque_background_color_); layer->SetBounds(inputs_.bounds); - -#if defined(NDEBUG) - if (frame_viewer_instrumentation::IsTracingLayerTreeSnapshots()) - layer->SetDebugInfo(TakeDebugInfo()); -#else - layer->SetDebugInfo(TakeDebugInfo()); -#endif - + layer->SetDebugInfo(std::move(inputs_.debug_info)); layer->SetTransformTreeIndex(transform_tree_index()); layer->SetEffectTreeIndex(effect_tree_index()); layer->SetClipTreeIndex(clip_tree_index()); @@ -1321,24 +1313,10 @@ bool Layer::HasNonAAPaint() const { return false; } -std::unique_ptr<base::trace_event::ConvertableToTraceFormat> -Layer::TakeDebugInfo() { - // TakeDebugInfo is called from the compositor thread while the main thread is - // blocked so we use the raw client pointer as we can't check whether the - // reference is safe on the weak pointer. - // TODO(flackr): Remove client_rawptr and figure out if we can take the debug - // info from the main thread and store it on inputs before doing the commit or - // make a WeakPtr which understands the commit and allows checked access from - // the compositor thread. https://crbug.com/826455 - if (inputs_.client_rawptr) - return inputs_.client_rawptr->TakeDebugInfo(this); - else - return nullptr; -} - -void Layer::didUpdateMainThreadScrollingReasons() { +void Layer::UpdateDebugInfo() { + DCHECK(frame_viewer_instrumentation::IsTracingLayerTreeSnapshots()); if (inputs_.client) - inputs_.client->didUpdateMainThreadScrollingReasons(); + inputs_.debug_info = inputs_.client->TakeDebugInfo(this); } void Layer::SetSubtreePropertyChanged() { @@ -1357,7 +1335,7 @@ void Layer::SetMayContainVideo(bool yes) { void Layer::SetScrollbarsHiddenFromImplSide(bool hidden) { if (inputs_.client) - inputs_.client->didChangeScrollbarsHiddenIfOverlay(hidden); + inputs_.client->DidChangeScrollbarsHiddenIfOverlay(hidden); } // On<Property>Animated is called due to an ongoing accelerated animation. diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h index eca81a044cf..32f87b182cd 100644 --- a/chromium/cc/layers/layer.h +++ b/chromium/cc/layers/layer.h @@ -41,7 +41,7 @@ namespace base { namespace trace_event { -class ConvertableToTraceFormat; +class TracedValue; } } @@ -117,7 +117,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // A layer's bounds are in logical, non-page-scaled pixels (however, the // root layer's bounds are in physical pixels). void SetBounds(const gfx::Size& bounds); - gfx::Size bounds() const { return inputs_.bounds; } + const gfx::Size& bounds() const { return inputs_.bounds; } void SetOverscrollBehavior(const OverscrollBehavior& behavior); OverscrollBehavior overscroll_behavior() const { @@ -136,7 +136,13 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { Layer* mask_layer() { return inputs_.mask_layer.get(); } const Layer* mask_layer() const { return inputs_.mask_layer.get(); } + // Marks the |dirty_rect| as being changed, which will cause a commit and + // the compositor to submit a new frame with a damage rect that includes the + // layer's dirty area. virtual void SetNeedsDisplayRect(const gfx::Rect& dirty_rect); + // Marks the entire layer's bounds as being changed, which will cause a commit + // and the compositor to submit a new frame with a damage rect that includes + // the entire layer. void SetNeedsDisplay() { SetNeedsDisplayRect(gfx::Rect(bounds())); } virtual void SetOpacity(float opacity); @@ -166,8 +172,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { const FilterOperations& filters() const { return inputs_.filters; } // Background filters are filters applied to what is behind this layer, when - // they are viewed through non-opaque regions in this layer. They are used - // through the WebLayer interface, and are not exposed to HTML. + // they are viewed through non-opaque regions in this layer. void SetBackgroundFilters(const FilterOperations& filters); const FilterOperations& background_filters() const { return inputs_.background_filters; @@ -177,7 +182,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { bool contents_opaque() const { return inputs_.contents_opaque; } void SetPosition(const gfx::PointF& position); - gfx::PointF position() const { return inputs_.position; } + const gfx::PointF& position() const { return inputs_.position; } // A layer that is a container for fixed position layers cannot be both // scrollable and have a non-identity transform. @@ -204,7 +209,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { const gfx::Transform& transform() const { return inputs_.transform; } void SetTransformOrigin(const gfx::Point3F&); - gfx::Point3F transform_origin() const { return inputs_.transform_origin; } + const gfx::Point3F& transform_origin() const { + return inputs_.transform_origin; + } void SetScrollParent(Layer* parent); @@ -230,14 +237,18 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { void SetScrollOffset(const gfx::ScrollOffset& scroll_offset); - gfx::ScrollOffset scroll_offset() const { return inputs_.scroll_offset; } + const gfx::ScrollOffset& scroll_offset() const { + return inputs_.scroll_offset; + } + // Called internally during commit to update the layer with state from the + // compositor thread. Not to be called externally by users of this class. void SetScrollOffsetFromImplSide(const gfx::ScrollOffset& scroll_offset); // Marks this layer as being scrollable and needing an associated scroll node. // The scroll node's bounds and container_bounds will be kept in sync // with this layer. Once scrollable, a Layer cannot become un-scrollable. void SetScrollable(const gfx::Size& scroll_container_bounds); - gfx::Size scroll_container_bounds() const { + const gfx::Size& scroll_container_bounds() const { return inputs_.scroll_container_bounds; } bool scrollable() const { return inputs_.scrollable; } @@ -284,7 +295,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { return force_render_surface_for_testing_; } - gfx::ScrollOffset CurrentScrollOffset() const { + const gfx::ScrollOffset& CurrentScrollOffset() const { return inputs_.scroll_offset; } @@ -310,6 +321,11 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { virtual void SetLayerTreeHost(LayerTreeHost* host); + // When true the layer may contribute to the compositor's output. When false, + // it does not. This property does not apply to children of the layer, they + // may contribute while this layer does not. The layer itself will determine + // if it has content to contribute, but when false, this prevents it from + // doing so. void SetIsDrawable(bool is_drawable); void SetHideLayerAndSubtree(bool hide); @@ -320,6 +336,10 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { int NumDescendantsThatDrawContent() const; + // Is true if the layer will contribute content to the compositor's output. + // Will be false if SetIsDrawable(false) is called. But will also be false if + // the layer itself has no content to contribute, even though the layer was + // given SetIsDrawable(true). // This is only virtual for tests. // TODO(awoloszyn): Remove this once we no longer need it for tests virtual bool DrawsContent() const; @@ -331,11 +351,10 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { virtual bool HasSlowPaths() const; virtual bool HasNonAAPaint() const; - virtual std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - TakeDebugInfo(); - virtual void didUpdateMainThreadScrollingReasons(); + void UpdateDebugInfo(); void SetLayerClient(base::WeakPtr<LayerClient> client); + LayerClient* GetLayerClientForTesting() const { return inputs_.client.get(); } virtual bool IsSnapped(); @@ -628,9 +647,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // The following elements can not and are not serialized. base::WeakPtr<LayerClient> client; - // During commit, the main thread is blocked on the compositor thread, so - // we use the raw pointer to the LayerClient. - LayerClient* client_rawptr; + std::unique_ptr<base::trace_event::TracedValue> debug_info; base::Callback<void(const gfx::ScrollOffset&, const ElementId&)> did_scroll_callback; diff --git a/chromium/cc/layers/layer_client.h b/chromium/cc/layers/layer_client.h index 10ded49b5a5..c7bb4862c2f 100644 --- a/chromium/cc/layers/layer_client.h +++ b/chromium/cc/layers/layer_client.h @@ -11,7 +11,7 @@ namespace base { namespace trace_event { -class ConvertableToTraceFormat; +class TracedValue; } } @@ -28,10 +28,10 @@ class CC_EXPORT LayerClient { // // A pointer to the layer is provided for the convenience of layer clients // which service multiple layers. - virtual std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - TakeDebugInfo(Layer* layer) = 0; - virtual void didUpdateMainThreadScrollingReasons() = 0; - virtual void didChangeScrollbarsHiddenIfOverlay(bool) = 0; + virtual std::unique_ptr<base::trace_event::TracedValue> TakeDebugInfo( + Layer* layer) = 0; + + virtual void DidChangeScrollbarsHiddenIfOverlay(bool) = 0; protected: virtual ~LayerClient() {} diff --git a/chromium/cc/layers/layer_impl.cc b/chromium/cc/layers/layer_impl.cc index 89b4bdf6a80..2eee6d48f5a 100644 --- a/chromium/cc/layers/layer_impl.cc +++ b/chromium/cc/layers/layer_impl.cc @@ -114,7 +114,7 @@ ElementListType LayerImpl::GetElementTypeForAnimation() const { } void LayerImpl::SetDebugInfo( - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> debug_info) { + std::unique_ptr<base::trace_event::TracedValue> debug_info) { owned_debug_info_ = std::move(debug_info); debug_info_ = owned_debug_info_.get(); SetNeedsPushProperties(); @@ -408,6 +408,9 @@ std::unique_ptr<base::DictionaryValue> LayerImpl::LayerAsJson() { result->SetBoolean("Is3dSorted", Is3dSorted()); result->SetDouble("OPACITY", Opacity()); result->SetBoolean("ContentsOpaque", contents_opaque_); + result->SetString( + "mainThreadScrollingReasons", + MainThreadScrollingReason::AsText(main_thread_scrolling_reasons_)); if (scrollable()) result->SetBoolean("Scrollable", true); @@ -764,25 +767,11 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->SetBoolean("trilinear_filtering", trilinear_filtering()); - if (debug_info_) { - std::string str; - debug_info_->AppendAsTraceFormat(&str); - base::JSONReader json_reader; - std::unique_ptr<base::Value> debug_info_value(json_reader.ReadToValue(str)); - - if (debug_info_value->is_dict()) { - base::DictionaryValue* dictionary_value = nullptr; - bool converted_to_dictionary = - debug_info_value->GetAsDictionary(&dictionary_value); - DCHECK(converted_to_dictionary); - for (base::DictionaryValue::Iterator it(*dictionary_value); !it.IsAtEnd(); - it.Advance()) { - state->SetValue(it.key().data(), it.value().CreateDeepCopy()); - } - } else { - NOTREACHED(); - } - } + MainThreadScrollingReason::AddToTracedValue(main_thread_scrolling_reasons_, + *state); + + if (debug_info_) + state->SetValue("debug_info", *debug_info_); } size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; } diff --git a/chromium/cc/layers/layer_impl.h b/chromium/cc/layers/layer_impl.h index 6eb7daabac1..d130a695d45 100644 --- a/chromium/cc/layers/layer_impl.h +++ b/chromium/cc/layers/layer_impl.h @@ -45,7 +45,6 @@ namespace base { namespace trace_event { -class ConvertableToTraceFormat; class TracedValue; } class DictionaryValue; @@ -388,8 +387,7 @@ class CC_EXPORT LayerImpl { virtual void RunMicroBenchmark(MicroBenchmarkImpl* benchmark); - void SetDebugInfo( - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> debug_info); + void SetDebugInfo(std::unique_ptr<base::trace_event::TracedValue> debug_info); void set_contributes_to_drawn_render_surface(bool is_member) { contributes_to_drawn_render_surface_ = is_member; @@ -564,9 +562,8 @@ class CC_EXPORT LayerImpl { DrawProperties draw_properties_; PerformanceProperties<LayerImpl> performance_properties_; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - owned_debug_info_; - base::trace_event::ConvertableToTraceFormat* debug_info_; + std::unique_ptr<base::trace_event::TracedValue> owned_debug_info_; + base::trace_event::TracedValue* debug_info_; bool has_will_change_transform_hint_ : 1; bool trilinear_filtering_ : 1; diff --git a/chromium/cc/layers/layer_unittest.cc b/chromium/cc/layers/layer_unittest.cc index 3c898c8c12d..594552cc344 100644 --- a/chromium/cc/layers/layer_unittest.cc +++ b/chromium/cc/layers/layer_unittest.cc @@ -65,6 +65,20 @@ using ::testing::_; grand_child->layer_tree_host()->LayerNeedsPushPropertiesForTesting( \ grand_child.get())); +#define EXECUTE_AND_VERIFY_SUBTREE_NOT_CHANGED(code_to_test) \ + code_to_test; \ + root->layer_tree_host()->BuildPropertyTreesForTesting(); \ + EXPECT_FALSE(root->subtree_property_changed()); \ + EXPECT_FALSE(root->layer_tree_host()->LayerNeedsPushPropertiesForTesting( \ + root.get())); \ + EXPECT_FALSE(child->subtree_property_changed()); \ + EXPECT_FALSE(child->layer_tree_host()->LayerNeedsPushPropertiesForTesting( \ + child.get())); \ + EXPECT_FALSE(grand_child->subtree_property_changed()); \ + EXPECT_FALSE( \ + grand_child->layer_tree_host()->LayerNeedsPushPropertiesForTesting( \ + grand_child.get())); + #define EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(code_to_test) \ code_to_test; \ EXPECT_FALSE(root->subtree_property_changed()); \ @@ -848,23 +862,24 @@ TEST_F(LayerTest, TestSettingMainThreadScrollingReason) { EXPECT_FALSE(test_layer->NeedsDisplayForTesting()); uint32_t reasons = 0, reasons_to_clear = 0, reasons_after_clearing = 0; - reasons |= MainThreadScrollingReason::kNonFastScrollableRegion; - reasons |= MainThreadScrollingReason::kContinuingMainThreadScroll; + reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; + reasons |= MainThreadScrollingReason::kHandlingScrollFromMainThread; reasons |= MainThreadScrollingReason::kScrollbarScrolling; - reasons_to_clear |= MainThreadScrollingReason::kContinuingMainThreadScroll; - reasons_to_clear |= MainThreadScrollingReason::kThreadedScrollingDisabled; + reasons_to_clear |= MainThreadScrollingReason::kHandlingScrollFromMainThread; + reasons_to_clear |= MainThreadScrollingReason::kCustomScrollbarScrolling; - reasons_after_clearing |= MainThreadScrollingReason::kNonFastScrollableRegion; + reasons_after_clearing |= + MainThreadScrollingReason::kThreadedScrollingDisabled; reasons_after_clearing |= MainThreadScrollingReason::kScrollbarScrolling; // Check that the reasons are added correctly. EXPECT_SET_NEEDS_COMMIT( 1, test_layer->AddMainThreadScrollingReasons( - MainThreadScrollingReason::kNonFastScrollableRegion)); + MainThreadScrollingReason::kThreadedScrollingDisabled)); EXPECT_SET_NEEDS_COMMIT( 1, test_layer->AddMainThreadScrollingReasons( - MainThreadScrollingReason::kContinuingMainThreadScroll)); + MainThreadScrollingReason::kHandlingScrollFromMainThread)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->AddMainThreadScrollingReasons( MainThreadScrollingReason::kScrollbarScrolling)); @@ -878,8 +893,8 @@ TEST_F(LayerTest, TestSettingMainThreadScrollingReason) { // Check that clearing non-set reasons doesn't set needs commit. reasons_to_clear = 0; - reasons_to_clear |= MainThreadScrollingReason::kThreadedScrollingDisabled; - reasons_to_clear |= MainThreadScrollingReason::kNoScrollingLayer; + reasons_to_clear |= MainThreadScrollingReason::kCustomScrollbarScrolling; + reasons_to_clear |= MainThreadScrollingReason::kPageOverlay; EXPECT_SET_NEEDS_COMMIT( 0, test_layer->ClearMainThreadScrollingReasons(reasons_to_clear)); EXPECT_EQ(reasons_after_clearing, @@ -888,7 +903,7 @@ TEST_F(LayerTest, TestSettingMainThreadScrollingReason) { // Check that adding an existing condition doesn't set needs commit. EXPECT_SET_NEEDS_COMMIT( 0, test_layer->AddMainThreadScrollingReasons( - MainThreadScrollingReason::kNonFastScrollableRegion)); + MainThreadScrollingReason::kThreadedScrollingDisabled)); } TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) { @@ -921,7 +936,7 @@ TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) { gfx::ScrollOffset(10, 10))); EXPECT_SET_NEEDS_COMMIT( 1, test_layer->AddMainThreadScrollingReasons( - MainThreadScrollingReason::kNonFastScrollableRegion)); + MainThreadScrollingReason::kThreadedScrollingDisabled)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetNonFastScrollableRegion( Region(gfx::Rect(1, 1, 2, 2)))); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTransform( diff --git a/chromium/cc/layers/nine_patch_layer_impl.h b/chromium/cc/layers/nine_patch_layer_impl.h index 9e5c9d65580..4841059fcaf 100644 --- a/chromium/cc/layers/nine_patch_layer_impl.h +++ b/chromium/cc/layers/nine_patch_layer_impl.h @@ -13,7 +13,6 @@ #include "cc/layers/layer_impl.h" #include "cc/layers/nine_patch_generator.h" #include "cc/layers/ui_resource_layer_impl.h" -#include "cc/resources/resource_provider.h" #include "cc/resources/ui_resource_client.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" diff --git a/chromium/cc/layers/nine_patch_layer_unittest.cc b/chromium/cc/layers/nine_patch_layer_unittest.cc index db3dc399a33..969de99e8cf 100644 --- a/chromium/cc/layers/nine_patch_layer_unittest.cc +++ b/chromium/cc/layers/nine_patch_layer_unittest.cc @@ -5,7 +5,6 @@ #include "cc/layers/nine_patch_layer.h" #include "cc/animation/animation_host.h" -#include "cc/resources/resource_provider.h" #include "cc/resources/scoped_ui_resource.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc index e52dfccf2c4..4dc5f16985f 100644 --- a/chromium/cc/layers/picture_layer_impl.cc +++ b/chromium/cc/layers/picture_layer_impl.cc @@ -771,6 +771,10 @@ void PictureLayerImpl::UpdateRasterSource( // We could do this after doing UpdateTiles, which would avoid doing this for // tilings that are going to disappear on the pending tree (if scale changed). // But that would also be more complicated, so we just do it here for now. + // + // TODO(crbug.com/843787): If the LayerTreeFrameSink is lost, and we activate, + // this ends up running with the old LayerTreeFrameSink, or possibly with a + // null LayerTreeFrameSink, which can give incorrect results or maybe crash. if (pending_set) { tilings_->UpdateTilingsToCurrentRasterSourceForActivation( raster_source_, pending_set, invalidation_, MinimumContentsScale(), @@ -932,8 +936,7 @@ bool PictureLayerImpl::ShouldAnimate(PaintImage::Id paint_image_id) const { gfx::Size PictureLayerImpl::CalculateTileSize( const gfx::Size& content_bounds) const { - int max_texture_size = - layer_tree_impl()->resource_provider()->max_texture_size(); + int max_texture_size = layer_tree_impl()->max_texture_size(); if (mask_type_ == Layer::LayerMaskType::SINGLE_TEXTURE_MASK) { // Masks are not tiled, so if we can't cover the whole mask with one tile, @@ -1452,10 +1455,10 @@ float PictureLayerImpl::MaximumContentsScale() const { // have tilings that would become larger than the max_texture_size since they // use a single tile for the entire tiling. Other layers can have tilings such // that dimension * scale does not overflow. - float max_dimension = static_cast<float>( - mask_type_ == Layer::LayerMaskType::SINGLE_TEXTURE_MASK - ? layer_tree_impl()->resource_provider()->max_texture_size() - : std::numeric_limits<int>::max()); + float max_dimension = + static_cast<float>(mask_type_ == Layer::LayerMaskType::SINGLE_TEXTURE_MASK + ? layer_tree_impl()->max_texture_size() + : std::numeric_limits<int>::max()); float max_scale_width = max_dimension / bounds().width(); float max_scale_height = max_dimension / bounds().height(); float max_scale = std::min(max_scale_width, max_scale_height); diff --git a/chromium/cc/layers/picture_layer_impl.h b/chromium/cc/layers/picture_layer_impl.h index d0348102464..6f850859e72 100644 --- a/chromium/cc/layers/picture_layer_impl.h +++ b/chromium/cc/layers/picture_layer_impl.h @@ -163,11 +163,20 @@ class CC_EXPORT PictureLayerImpl scoped_refptr<RasterSource> raster_source_; Region invalidation_; + // Ideal scales are calcuated from the transforms applied to the layer. They + // represent the best known scale from the layer to the final output. + // Page scale is from user pinch/zoom. float ideal_page_scale_; + // Device scale is from screen dpi, and it comes from device scale facter. float ideal_device_scale_; + // Source scale comes from javascript css scale. float ideal_source_scale_; + // Contents scale = device scale * page scale * source scale. float ideal_contents_scale_; + // Raster scales are set from ideal scales. They are scales we choose to + // raster at. They may not match the ideal scales at times to avoid raster for + // performance reasons. float raster_page_scale_; float raster_device_scale_; float raster_source_scale_; diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc index 38e0a3ac30a..90f76f90953 100644 --- a/chromium/cc/layers/picture_layer_impl_unittest.cc +++ b/chromium/cc/layers/picture_layer_impl_unittest.cc @@ -1258,7 +1258,7 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) { EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size()); // Resize larger than the max texture size. - int max_texture_size = host_impl()->resource_provider()->max_texture_size(); + int max_texture_size = host_impl()->max_texture_size(); gfx::Size huge_bounds(max_texture_size + 1, 10); scoped_refptr<FakeRasterSource> huge_raster_source = FakeRasterSource::CreateFilled(huge_bounds); @@ -1451,10 +1451,10 @@ TEST_F(PictureLayerImplTest, ClampTilesToMaxTileSize) { ResetTilingsAndRasterScales(); // Change the max texture size on the output surface context. - std::unique_ptr<viz::TestWebGraphicsContext3D> context = - viz::TestWebGraphicsContext3D::Create(); - context->set_max_texture_size(140); - ResetLayerTreeFrameSink(FakeLayerTreeFrameSink::Create3d(std::move(context))); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + gl_owned->set_max_texture_size(140); + ResetLayerTreeFrameSink( + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned))); SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 0.f, false); @@ -1486,10 +1486,10 @@ TEST_F(PictureLayerImplTest, ClampSingleTileToToMaxTileSize) { ResetTilingsAndRasterScales(); // Change the max texture size on the output surface context. - std::unique_ptr<viz::TestWebGraphicsContext3D> context = - viz::TestWebGraphicsContext3D::Create(); - context->set_max_texture_size(140); - ResetLayerTreeFrameSink(FakeLayerTreeFrameSink::Create3d(std::move(context))); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + gl_owned->set_max_texture_size(140); + ResetLayerTreeFrameSink( + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned))); SetupDrawPropertiesAndUpdateTiles(active_layer(), 1.f, 1.f, 1.f, 1.f, 0.f, false); diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc index c0614fcfbf2..02caf7cb7e7 100644 --- a/chromium/cc/layers/render_surface_impl.cc +++ b/chromium/cc/layers/render_surface_impl.cc @@ -26,6 +26,7 @@ #include "components/viz/common/quads/render_pass_draw_quad.h" #include "components/viz/common/quads/shared_quad_state.h" #include "components/viz/common/quads/solid_color_draw_quad.h" +#include "components/viz/common/quads/tile_draw_quad.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/transform.h" @@ -267,8 +268,8 @@ void RenderSurfaceImpl::CalculateContentRectFromAccumulatedContentRect( // use accumulated content rect, and then try to clip it. gfx::Rect surface_content_rect = CalculateClippedAccumulatedContentRect(); - // The RenderSurfaceImpl backing texture cannot exceed the maximum - // supported texture size. + // The RenderSurfaceImpl backing texture cannot exceed the maximum supported + // texture size. surface_content_rect.set_width( std::min(surface_content_rect.width(), max_texture_size)); surface_content_rect.set_height( @@ -384,9 +385,9 @@ std::unique_ptr<viz::RenderPass> RenderSurfaceImpl::CreateRenderPass() { void RenderSurfaceImpl::AppendQuads(DrawMode draw_mode, viz::RenderPass* render_pass, AppendQuadsData* append_quads_data) { - gfx::Rect visible_layer_rect = + gfx::Rect unoccluded_content_rect = occlusion_in_content_space().GetUnoccludedContentRect(content_rect()); - if (visible_layer_rect.IsEmpty()) + if (unoccluded_content_rect.IsEmpty()) return; const PropertyTrees* property_trees = layer_tree_impl_->property_trees(); @@ -406,7 +407,7 @@ void RenderSurfaceImpl::AppendQuads(DrawMode draw_mode, auto* debug_border_quad = render_pass->CreateAndAppendDrawQuad<viz::DebugBorderDrawQuad>(); debug_border_quad->SetNew(shared_quad_state, content_rect(), - visible_layer_rect, GetDebugBorderColor(), + unoccluded_content_rect, GetDebugBorderColor(), GetDebugBorderWidth()); } @@ -429,7 +430,7 @@ void RenderSurfaceImpl::AppendQuads(DrawMode draw_mode, "mask_layer_gpu_memory_usage", mask_layer->GPUMemoryUsageInBytes()); if (mask_layer->mask_type() == Layer::LayerMaskType::MULTI_TEXTURE_MASK) { - TileMaskLayer(render_pass, shared_quad_state, visible_layer_rect); + TileMaskLayer(render_pass, shared_quad_state, unoccluded_content_rect); return; } gfx::SizeF mask_uv_size; @@ -448,21 +449,25 @@ void RenderSurfaceImpl::AppendQuads(DrawMode draw_mode, gfx::RectF tex_coord_rect(gfx::Rect(content_rect().size())); auto* quad = render_pass->CreateAndAppendDrawQuad<viz::RenderPassDrawQuad>(); - quad->SetNew(shared_quad_state, content_rect(), visible_layer_rect, id(), + quad->SetNew(shared_quad_state, content_rect(), unoccluded_content_rect, id(), mask_resource_id, mask_uv_rect, mask_texture_size, surface_contents_scale, FiltersOrigin(), tex_coord_rect, !layer_tree_impl_->settings().enable_edge_anti_aliasing); } -void RenderSurfaceImpl::TileMaskLayer(viz::RenderPass* render_pass, - viz::SharedQuadState* shared_quad_state, - const gfx::Rect& visible_layer_rect) { +void RenderSurfaceImpl::TileMaskLayer( + viz::RenderPass* render_pass, + viz::SharedQuadState* shared_quad_state, + const gfx::Rect& unoccluded_content_rect) { DCHECK(MaskLayer()); DCHECK(Filters().IsEmpty()); LayerImpl* mask_layer = MaskLayer(); gfx::Vector2dF owning_layer_to_surface_contents_scale = OwningEffectNode()->surface_contents_scale; + + // Use the picture layer's AppendQuads logic to generate TileDrawQuads. These + // DrawQuads are used to generate tiled RenderPassDrawQuad for the mask. std::unique_ptr<viz::RenderPass> temp_render_pass = viz::RenderPass::Create(); AppendQuadsData temp_append_quads_data; mask_layer->AppendQuads(temp_render_pass.get(), &temp_append_quads_data); @@ -470,92 +475,158 @@ void RenderSurfaceImpl::TileMaskLayer(viz::RenderPass* render_pass, auto* temp_quad = temp_render_pass->quad_list.front(); if (!temp_quad) return; - gfx::Transform mask_quad_to_surface_contents = + + // There are two spaces we are dealing with here: + // 1. quad space: This is the space where the draw quads generated by the + // PictureLayerImpl's logic are in. In other words, this is the space where + // the |temp_quad|'s rect is in. + // 2. surface space: This is the contents space of |this| render surface. + // Since |mask_layer|'s target is the render surface it's masking, the surface + // space is also the target space for the quads generated by + // PictureLayerImpl's logic. + + gfx::Transform quad_space_to_surface_space_transform = 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_rect = - gfx::ScaleToEnclosingRect(shared_quad_state->quad_layer_rect, - 1.f / mask_quad_to_surface_contents_scale.x(), - 1.f / mask_quad_to_surface_contents_scale.y()); + // This transform should be a 2d scale + offset, so would be invertible. + gfx::Transform surface_space_to_quad_space_transform; + bool invertible = quad_space_to_surface_space_transform.GetInverse( + &surface_space_to_quad_space_transform); + DCHECK(invertible) << "RenderSurfaceImpl::TileMaskLayer created quads with " + "non-invertible transform."; + + // While converting from the TileDrawQuads to RenderPassDrawQuads, we keep the + // quad rects in the same space, and modify every other rect that is not in + // quad space accordingly. + + // The |shared_quad_state| being passed in is generated with |this| render + // surface's draw properties. It holds a transform from the surface contents + // space to the surface target space. We want to change the origin space to + // match the |mask_layer|'s quad space, so we must include the transform from + // the quad space to the surface contents space. Then the transform is from + // the |mask_layer|'s quad space to our target space. + shared_quad_state->quad_to_target_transform.PreconcatTransform( + quad_space_to_surface_space_transform); + + // Next, we need to modify the rects on |shared_quad_state| that are in + // surface's "quad space" (surface space) to quad space. + shared_quad_state->quad_layer_rect = MathUtil::ProjectEnclosingClippedRect( + surface_space_to_quad_space_transform, + shared_quad_state->quad_layer_rect); shared_quad_state->visible_quad_layer_rect = - gfx::ScaleToEnclosingRect(shared_quad_state->visible_quad_layer_rect, - 1.f / mask_quad_to_surface_contents_scale.x(), - 1.f / mask_quad_to_surface_contents_scale.y()); - gfx::Rect content_rect_in_coverage_space = gfx::ScaleToEnclosingRect( - 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::ScaleToEnclosingRect( - visible_layer_rect, 1.f / mask_quad_to_surface_contents_scale.x(), - 1.f / mask_quad_to_surface_contents_scale.y()); - + MathUtil::ProjectEnclosingClippedRect( + surface_space_to_quad_space_transform, + shared_quad_state->visible_quad_layer_rect); + + // The |shared_quad_state|'s |quad_layer_rect| and |visible_quad_layer_rect| + // is set from content_rect(). content_rect() defines the size of the source + // texture to be masked. PictureLayerImpl's generated |quad_layer_rect| and + // |visible_quad_layer_rect| is from the mask layer's |bounds| and + // |visible_layer_rect|. These rect defines the size of the mask texture. The + // intersection of the two rects is the rect we can draw. + shared_quad_state->quad_layer_rect.Intersect( + temp_quad->shared_quad_state->quad_layer_rect); + shared_quad_state->visible_quad_layer_rect.Intersect( + temp_quad->shared_quad_state->visible_quad_layer_rect); + + // Cache content_rect() and |unoccluded_content_rect| in quad space. + gfx::Rect content_rect_in_quad_space = MathUtil::MapEnclosingClippedRect( + surface_space_to_quad_space_transform, content_rect()); + gfx::Rect unoccluded_content_rect_in_quad_space = + MathUtil::MapEnclosingClippedRect(surface_space_to_quad_space_transform, + unoccluded_content_rect); + + // Generate RenderPassDrawQuads based on the temporary quads created by + // |mask_layer|. for (auto* temp_quad : temp_render_pass->quad_list) { - gfx::Rect quad_rect = temp_quad->rect; - if (!quad_rect.Intersects(content_rect_in_coverage_space)) + gfx::Rect temp_quad_rect = temp_quad->rect; + // If the |temp_quad_rect| is entirely outside render surface's + // content_rect(), ignore the quad. + if (!temp_quad_rect.Intersects(content_rect_in_quad_space)) continue; - gfx::Rect render_quad_rect = - gfx::IntersectRects(quad_rect, content_rect_in_coverage_space); - gfx::Rect quad_visible_rect_in_coverage_space = gfx::IntersectRects( - render_quad_rect, visible_layer_rect_in_coverage_space); - if (quad_visible_rect_in_coverage_space.IsEmpty()) + // We only care about the quads that are inside the content_rect(). + gfx::Rect quad_rect = + gfx::IntersectRects(temp_quad_rect, content_rect_in_quad_space); + + gfx::Rect visible_quad_rect = + gfx::IntersectRects(quad_rect, unoccluded_content_rect_in_quad_space); + if (visible_quad_rect.IsEmpty()) continue; - 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()); + // |tex_coord_rect| is non-normalized sub-rect of the render surface's + // texture that is being masked. Its origin is (0,0) and it is in surface + // space. For example the |tex_coord_rect| for the entire texture would be + // (0,0 content_rect.width X content_rect.height). + + // In order to calculate the |tex_coord_rect|, we calculate what quad's rect + // would be masking in the surface contents space, then remove the offset. + gfx::RectF tex_coord_rect = MathUtil::MapClippedRect( + quad_space_to_surface_space_transform, gfx::RectF(quad_rect)); + tex_coord_rect.Offset(-content_rect().OffsetFromOrigin()); switch (temp_quad->material) { case viz::DrawQuad::TILED_CONTENT: { DCHECK_EQ(1U, temp_quad->resources.count); - gfx::Size mask_texture_size = - static_cast<viz::ContentDrawQuadBase*>(temp_quad)->texture_size; + // When the |temp_quad| is actually a texture, we need to calculate + // |mask_uv_rect|. The |mask_uv_rect| is the normalized sub-rect for + // applying the mask's texture. To get |mask_uv_rect|, we need the newly + // calculated |quad_rect| in the texture's space, then normalized by the + // texture's size. + + // We are applying the |temp_quad|'s texture as a mask, so we start with + // the |tex_coord_rect| of the |temp_quad|. gfx::RectF temp_tex_coord_rect = - static_cast<viz::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); + viz::TileDrawQuad::MaterialCast(temp_quad)->tex_coord_rect; + + // The |quad_rect| is in the same space as |temp_quad_rect|. Calculate + // the scale transform between the texture space and the quad space. + float scale_x = temp_tex_coord_rect.width() / temp_quad_rect.width(); + float scale_y = temp_tex_coord_rect.height() / temp_quad_rect.height(); + // Start by setting up the correct size of mask_uv_rect in texture + // space. + gfx::RectF mask_uv_rect(quad_rect.width() * scale_x, + quad_rect.height() * scale_y); + + // Now figure out what is the correct offset. Start with the original + // temp_tex_coord_rect's offset. + mask_uv_rect.Offset(temp_tex_coord_rect.OffsetFromOrigin()); + // Next figure out what offset to apply by checking the difference in + // offset between |temp_quad_rect| and |quad_rect| which is + // intersected by the content_rect(). + gfx::Vector2dF offset(quad_rect.OffsetFromOrigin()); + offset -= temp_quad_rect.OffsetFromOrigin(); + // Convert the difference in offset into texture space. + offset.Scale(scale_x, scale_y); + mask_uv_rect.Offset(offset); + + // |mask_uv_rect| is normalized to [0..1] by the |mask_texture_size|. + gfx::Size mask_texture_size = + viz::TileDrawQuad::MaterialCast(temp_quad)->texture_size; + mask_uv_rect.Scale(1.f / mask_texture_size.width(), + 1.f / mask_texture_size.height()); auto* quad = render_pass->CreateAndAppendDrawQuad<viz::RenderPassDrawQuad>(); - quad->SetNew(shared_quad_state, render_quad_rect, - quad_visible_rect_in_coverage_space, id(), + quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, id(), 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, + FiltersOrigin(), tex_coord_rect, !layer_tree_impl_->settings().enable_edge_anti_aliasing); } break; case viz::DrawQuad::SOLID_COLOR: { - if (!static_cast<viz::SolidColorDrawQuad*>(temp_quad)->color) + SkColor temp_color = + viz::SolidColorDrawQuad::MaterialCast(temp_quad)->color; + if (!temp_color) continue; SkAlpha solid = SK_AlphaOPAQUE; - DCHECK_EQ(SkColorGetA( - static_cast<viz::SolidColorDrawQuad*>(temp_quad)->color), - solid); + DCHECK_EQ(SkColorGetA(temp_color), solid); auto* quad = render_pass->CreateAndAppendDrawQuad<viz::RenderPassDrawQuad>(); - quad->SetNew(shared_quad_state, render_quad_rect, - quad_visible_rect_in_coverage_space, id(), 0, gfx::RectF(), - gfx::Size(), owning_layer_to_surface_contents_scale, - FiltersOrigin(), quad_rect_in_non_normalized_texture_space, + quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, id(), 0, + gfx::RectF(), gfx::Size(), + owning_layer_to_surface_contents_scale, FiltersOrigin(), + tex_coord_rect, !layer_tree_impl_->settings().enable_edge_anti_aliasing); } break; case viz::DrawQuad::DEBUG_BORDER: diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h index 00b05df4860..8e7c143087f 100644 --- a/chromium/cc/layers/render_surface_impl.h +++ b/chromium/cc/layers/render_surface_impl.h @@ -189,7 +189,7 @@ class CC_EXPORT RenderSurfaceImpl { const gfx::Transform& target_to_surface); void TileMaskLayer(viz::RenderPass* render_pass, viz::SharedQuadState* shared_quad_state, - const gfx::Rect& visible_layer_rect); + const gfx::Rect& unoccluded_content_rect); LayerTreeImpl* layer_tree_impl_; uint64_t stable_id_; diff --git a/chromium/cc/layers/render_surface_impl_unittest.cc b/chromium/cc/layers/render_surface_impl_unittest.cc index 0690231faea..8fb231d5a30 100644 --- a/chromium/cc/layers/render_surface_impl_unittest.cc +++ b/chromium/cc/layers/render_surface_impl_unittest.cc @@ -153,8 +153,11 @@ TEST(RenderSurfaceLayerImplTest, viz::RenderPassDrawQuad::MaterialCast(render_pass->quad_list.front()); EXPECT_EQ(gfx::Transform(), quad->shared_quad_state->quad_to_target_transform); + // With tiled mask layer, we only generate mask quads for visible rect. In + // this case |quad_layer_rect| is not fully covered, but + // |visible_quad_layer_rect| is fully covered. LayerTestCommon::VerifyQuadsExactlyCoverRect( - render_pass->quad_list, quad->shared_quad_state->quad_layer_rect); + render_pass->quad_list, quad->shared_quad_state->visible_quad_layer_rect); } } // namespace diff --git a/chromium/cc/layers/render_surface_unittest.cc b/chromium/cc/layers/render_surface_unittest.cc index 714ddd49916..14f74ecc27e 100644 --- a/chromium/cc/layers/render_surface_unittest.cc +++ b/chromium/cc/layers/render_surface_unittest.cc @@ -245,6 +245,8 @@ TEST(RenderSurfaceTest, SanityCheckSurfaceDropsOccludedRenderPassDrawQuads) { std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink = FakeLayerTreeFrameSink::Create3d(); FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner); + // Set a big enough viewport to show the entire render pass. + host_impl.SetViewportSize(gfx::Size(1000, 1000)); std::unique_ptr<LayerImpl> root_layer = LayerImpl::Create(host_impl.active_tree(), 1); @@ -312,6 +314,8 @@ TEST(RenderSurfaceTest, SanityCheckSurfaceIgnoreMaskLayerOcclusion) { std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink = FakeLayerTreeFrameSink::Create3d(); FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner); + // Set a big enough viewport to show the entire render pass. + host_impl.SetViewportSize(gfx::Size(1000, 1000)); std::unique_ptr<LayerImpl> root_layer = LayerImpl::Create(host_impl.active_tree(), 1); diff --git a/chromium/cc/layers/scrollbar_layer_unittest.cc b/chromium/cc/layers/scrollbar_layer_unittest.cc index 94935c08f07..131182ac2d0 100644 --- a/chromium/cc/layers/scrollbar_layer_unittest.cc +++ b/chromium/cc/layers/scrollbar_layer_unittest.cc @@ -1351,7 +1351,7 @@ class ScaledScrollbarLayerTestResourceCreation : public ScrollbarLayerTest { layer_tree_host_->SetViewportSizeAndScale( layer_tree_host_->device_viewport_size(), test_scale, - layer_tree_host_->local_surface_id()); + layer_tree_host_->local_surface_id_from_parent()); scrollbar_layer->Update(); @@ -1417,7 +1417,7 @@ class ScaledScrollbarLayerTestScaledRasterization : public ScrollbarLayerTest { layer_tree_host_->SetViewportSizeAndScale( layer_tree_host_->device_viewport_size(), test_scale, - layer_tree_host_->local_surface_id()); + layer_tree_host_->local_surface_id_from_parent()); scrollbar_layer->Update(); diff --git a/chromium/cc/layers/solid_color_layer_impl_unittest.cc b/chromium/cc/layers/solid_color_layer_impl_unittest.cc index 395533bae64..5f0a8e8a419 100644 --- a/chromium/cc/layers/solid_color_layer_impl_unittest.cc +++ b/chromium/cc/layers/solid_color_layer_impl_unittest.cc @@ -188,7 +188,7 @@ TEST(SolidColorLayerImplTest, VerifyNeedsBlending) { LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); EXPECT_FALSE(layer->contents_opaque()); - layer->SetBackgroundColor(SkColorSetARGBInline(255, 10, 20, 30)); + layer->SetBackgroundColor(SkColorSetARGB(255, 10, 20, 30)); EXPECT_TRUE(layer->contents_opaque()); { DebugScopedSetImplThread scoped_impl_thread(host->GetTaskRunnerProvider()); @@ -215,7 +215,7 @@ TEST(SolidColorLayerImplTest, VerifyNeedsBlending) { } EXPECT_TRUE(layer->contents_opaque()); - layer->SetBackgroundColor(SkColorSetARGBInline(254, 10, 20, 30)); + layer->SetBackgroundColor(SkColorSetARGB(254, 10, 20, 30)); EXPECT_FALSE(layer->contents_opaque()); { DebugScopedSetImplThread scoped_impl_thread(host->GetTaskRunnerProvider()); diff --git a/chromium/cc/layers/surface_layer.cc b/chromium/cc/layers/surface_layer.cc index 8a123ca8587..6124fe42fbf 100644 --- a/chromium/cc/layers/surface_layer.cc +++ b/chromium/cc/layers/surface_layer.cc @@ -59,10 +59,10 @@ void SurfaceLayer::SetStretchContentToFillBounds( SetNeedsPushProperties(); } -void SurfaceLayer::SetHitTestable(bool hit_testable) { - if (hit_testable_ == hit_testable) +void SurfaceLayer::SetSurfaceHitTestable(bool surface_hit_testable) { + if (surface_hit_testable_ == surface_hit_testable) return; - hit_testable_ = hit_testable; + surface_hit_testable_ = surface_hit_testable; SetNeedsPushProperties(); } @@ -100,7 +100,7 @@ void SurfaceLayer::PushPropertiesTo(LayerImpl* layer) { deadline_in_frames_ = 0u; layer_impl->SetFallbackSurfaceId(fallback_surface_id_); layer_impl->SetStretchContentToFillBounds(stretch_content_to_fill_bounds_); - layer_impl->SetHitTestable(hit_testable_); + layer_impl->SetSurfaceHitTestable(surface_hit_testable_); } } // namespace cc diff --git a/chromium/cc/layers/surface_layer.h b/chromium/cc/layers/surface_layer.h index 3ed0b9ad140..87c5a26dfe2 100644 --- a/chromium/cc/layers/surface_layer.h +++ b/chromium/cc/layers/surface_layer.h @@ -32,8 +32,8 @@ class CC_EXPORT SurfaceLayer : public Layer { return stretch_content_to_fill_bounds_; } - void SetHitTestable(bool hit_testable); - bool hit_testable() const { return hit_testable_; } + void SetSurfaceHitTestable(bool surface_hit_testable); + bool surface_hit_testable() const { return surface_hit_testable_; } // Layer overrides. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; @@ -64,7 +64,14 @@ class CC_EXPORT SurfaceLayer : public Layer { base::Optional<uint32_t> deadline_in_frames_ = 0u; bool stretch_content_to_fill_bounds_ = false; - bool hit_testable_ = false; + + // Whether or not the surface should submit hit test data when submitting + // compositor frame. The bit represents that the surface layer may be + // associated with an out-of-process iframe and viz hit testing needs to know + // the hit test information of that iframe. This bit is different from a layer + // being hit testable in the renderer, a hit testable surface layer may not + // be surface hit testable (e.g., a surface layer created by video). + bool surface_hit_testable_ = false; DISALLOW_COPY_AND_ASSIGN(SurfaceLayer); }; diff --git a/chromium/cc/layers/surface_layer_impl.cc b/chromium/cc/layers/surface_layer_impl.cc index d90e233bfd3..def5281514d 100644 --- a/chromium/cc/layers/surface_layer_impl.cc +++ b/chromium/cc/layers/surface_layer_impl.cc @@ -54,11 +54,11 @@ void SurfaceLayerImpl::SetStretchContentToFillBounds(bool stretch_content) { NoteLayerPropertyChanged(); } -void SurfaceLayerImpl::SetHitTestable(bool hit_testable) { - if (hit_testable_ == hit_testable) +void SurfaceLayerImpl::SetSurfaceHitTestable(bool surface_hit_testable) { + if (surface_hit_testable_ == surface_hit_testable) return; - hit_testable_ = hit_testable; + surface_hit_testable_ = surface_hit_testable; NoteLayerPropertyChanged(); } @@ -71,7 +71,7 @@ void SurfaceLayerImpl::PushPropertiesTo(LayerImpl* layer) { deadline_in_frames_ = 0u; layer_impl->SetFallbackSurfaceId(fallback_surface_id_); layer_impl->SetStretchContentToFillBounds(stretch_content_to_fill_bounds_); - layer_impl->SetHitTestable(hit_testable_); + layer_impl->SetSurfaceHitTestable(surface_hit_testable_); } void SurfaceLayerImpl::AppendQuads(viz::RenderPass* render_pass, diff --git a/chromium/cc/layers/surface_layer_impl.h b/chromium/cc/layers/surface_layer_impl.h index d51dd6ad9a6..ce243205514 100644 --- a/chromium/cc/layers/surface_layer_impl.h +++ b/chromium/cc/layers/surface_layer_impl.h @@ -50,8 +50,8 @@ class CC_EXPORT SurfaceLayerImpl : public LayerImpl { return stretch_content_to_fill_bounds_; } - void SetHitTestable(bool hit_testable); - bool hit_testable() const { return hit_testable_; } + void SetSurfaceHitTestable(bool surface_hit_testable); + bool surface_hit_testable() const { return surface_hit_testable_; } // LayerImpl overrides. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; @@ -79,7 +79,7 @@ class CC_EXPORT SurfaceLayerImpl : public LayerImpl { base::Optional<uint32_t> deadline_in_frames_; bool stretch_content_to_fill_bounds_ = false; - bool hit_testable_ = false; + bool surface_hit_testable_ = false; DISALLOW_COPY_AND_ASSIGN(SurfaceLayerImpl); }; diff --git a/chromium/cc/layers/texture_layer.cc b/chromium/cc/layers/texture_layer.cc index 0e55c54f17f..359cbf8955d 100644 --- a/chromium/cc/layers/texture_layer.cc +++ b/chromium/cc/layers/texture_layer.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/location.h" +#include "base/sequenced_task_runner.h" #include "base/synchronization/lock.h" #include "base/trace_event/trace_event.h" #include "cc/base/simple_enclosed_region.h" @@ -273,20 +274,40 @@ TextureLayer::TransferableResourceHolder::MainThreadReference:: TextureLayer::TransferableResourceHolder::MainThreadReference:: ~MainThreadReference() { +#if DCHECK_IS_ON() + { + base::AutoLock hold(holder_->posted_internal_derefs_lock_); + ++holder_->posted_internal_derefs_; + } +#endif holder_->InternalRelease(); } TextureLayer::TransferableResourceHolder::TransferableResourceHolder( const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback) - : internal_references_(0), - resource_(resource), + : resource_(resource), release_callback_(std::move(release_callback)), - sync_token_(resource.mailbox_holder.sync_token), - is_lost_(false) {} + sync_token_(resource.mailbox_holder.sync_token) {} TextureLayer::TransferableResourceHolder::~TransferableResourceHolder() { - DCHECK_EQ(0u, internal_references_); +#if DCHECK_IS_ON() + { + // If the MessageLoop is destroyed while a posted deref is waiting to run, + // this object will be destroyed with an internal_references_ still present. + // So we must also include the outstanding posted derefences. + base::AutoLock hold(posted_internal_derefs_lock_); + DCHECK_EQ(internal_references_, posted_internal_derefs_); + } +#endif + if (release_callback_) { + // We land here if the dereferences are posted but not run and the + // MessageLoop is destroyed, destroying those tasks and this object with it. + // We run the ReleaseCallback in that case assuming the MessageLoop is being + // destroyed on the main thread. + DCHECK(main_thread_checker_.CalledOnValidThread()); + release_callback_->Run(sync_token_, is_lost_); + } } std::unique_ptr<TextureLayer::TransferableResourceHolder::MainThreadReference> @@ -310,7 +331,7 @@ TextureLayer::TransferableResourceHolder::GetCallbackForImplThread( scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner) { // We can't call GetCallbackForImplThread if we released the main thread // reference. - DCHECK_GT(internal_references_, 0u); + DCHECK_GT(internal_references_, 0); InternalAddRef(); return viz::SingleReleaseCallback::Create( base::Bind(&TransferableResourceHolder::ReturnAndReleaseOnImplThread, @@ -323,6 +344,12 @@ void TextureLayer::TransferableResourceHolder::InternalAddRef() { void TextureLayer::TransferableResourceHolder::InternalRelease() { DCHECK(main_thread_checker_.CalledOnValidThread()); +#if DCHECK_IS_ON() + { + base::AutoLock hold(posted_internal_derefs_lock_); + --posted_internal_derefs_; + } +#endif if (!--internal_references_) { release_callback_->Run(sync_token_, is_lost_); resource_ = viz::TransferableResource(); @@ -335,6 +362,12 @@ void TextureLayer::TransferableResourceHolder::ReturnAndReleaseOnImplThread( const gpu::SyncToken& sync_token, bool is_lost) { Return(sync_token, is_lost); +#if DCHECK_IS_ON() + { + base::AutoLock hold(posted_internal_derefs_lock_); + ++posted_internal_derefs_; + } +#endif main_thread_task_runner->PostTask( FROM_HERE, base::Bind(&TransferableResourceHolder::InternalRelease, this)); diff --git a/chromium/cc/layers/texture_layer.h b/chromium/cc/layers/texture_layer.h index af32a87c81e..c8c77755b53 100644 --- a/chromium/cc/layers/texture_layer.h +++ b/chromium/cc/layers/texture_layer.h @@ -84,7 +84,13 @@ class CC_EXPORT TextureLayer : public Layer, SharedBitmapIdRegistrar { // These members are only accessed on the main thread, or on the impl thread // during commit where the main thread is blocked. - unsigned internal_references_; + int internal_references_ = 0; +#if DCHECK_IS_ON() + // The number of derefs posted from the impl thread, and a lock for + // accessing it. + base::Lock posted_internal_derefs_lock_; + int posted_internal_derefs_ = 0; +#endif viz::TransferableResource resource_; std::unique_ptr<viz::SingleReleaseCallback> release_callback_; @@ -94,7 +100,7 @@ class CC_EXPORT TextureLayer : public Layer, SharedBitmapIdRegistrar { // ReturnAndReleaseOnImplThread() defines their values. base::Lock arguments_lock_; gpu::SyncToken sync_token_; - bool is_lost_; + bool is_lost_ = false; base::ThreadChecker main_thread_checker_; DISALLOW_COPY_AND_ASSIGN(TransferableResourceHolder); }; diff --git a/chromium/cc/layers/texture_layer_unittest.cc b/chromium/cc/layers/texture_layer_unittest.cc index 24463ef1a26..08919e42ed9 100644 --- a/chromium/cc/layers/texture_layer_unittest.cc +++ b/chromium/cc/layers/texture_layer_unittest.cc @@ -15,6 +15,7 @@ #include "base/location.h" #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" @@ -105,7 +106,7 @@ class MockReleaseCallback { const gpu::SyncToken& sync_token, bool lost_resource)); MOCK_METHOD3(Release2, - void(viz::SharedBitmap* shared_bitmap, + void(const viz::SharedBitmapId& shared_bitmap_id, const gpu::SyncToken& sync_token, bool lost_resource)); }; @@ -133,14 +134,12 @@ struct CommonResourceObjects { resource2_ = viz::TransferableResource::MakeGL( mailbox_name2_, GL_LINEAR, arbitrary_target2, sync_token2_); gfx::Size size(128, 128); - shared_bitmap_ = manager->AllocateSharedBitmap(size, viz::RGBA_8888); - DCHECK(shared_bitmap_); + shared_bitmap_id_ = viz::SharedBitmap::GenerateId(); release_callback3_ = base::Bind(&MockReleaseCallback::Release2, - base::Unretained(&mock_callback_), shared_bitmap_.get()); - resource3_ = viz::TransferableResource::MakeSoftware( - shared_bitmap_->id(), shared_bitmap_->sequence_number(), size, - viz::RGBA_8888); + base::Unretained(&mock_callback_), shared_bitmap_id_); + resource3_ = viz::TransferableResource::MakeSoftware(shared_bitmap_id_, + size, viz::RGBA_8888); } using RepeatingReleaseCallback = @@ -155,7 +154,7 @@ struct CommonResourceObjects { RepeatingReleaseCallback release_callback3_; gpu::SyncToken sync_token1_; gpu::SyncToken sync_token2_; - std::unique_ptr<viz::SharedBitmap> shared_bitmap_; + viz::SharedBitmapId shared_bitmap_id_; viz::TransferableResource resource1_; viz::TransferableResource resource2_; viz::TransferableResource resource3_; @@ -281,7 +280,7 @@ TEST_F(TextureLayerWithResourceTest, ReplaceMailboxOnMainThreadBeforeCommit) { EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); EXPECT_CALL(test_data_.mock_callback_, - Release2(test_data_.shared_bitmap_.get(), _, false)) + Release2(test_data_.shared_bitmap_id_, _, false)) .Times(1); test_layer->ClearTexture(); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); @@ -505,9 +504,8 @@ class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { !layer_tree_host()->GetSettings().single_thread_proxy_scheduler; return std::make_unique<viz::TestLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), - shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings, - ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync, - refresh_rate); + gpu_memory_buffer_manager(), renderer_settings, ImplThreadTaskRunner(), + synchronous_composite, disable_display_vsync, refresh_rate); } void AdvanceTestCase() { @@ -782,9 +780,8 @@ TEST_F(TextureLayerImplWithResourceTest, TestWillDraw) { test_data_.mock_callback_, Release(test_data_.mailbox_name1_, test_data_.sync_token1_, false)) .Times(AnyNumber()); - EXPECT_CALL( - test_data_.mock_callback_, - Release2(test_data_.shared_bitmap_.get(), gpu::SyncToken(), false)) + EXPECT_CALL(test_data_.mock_callback_, + Release2(test_data_.shared_bitmap_id_, gpu::SyncToken(), false)) .Times(AnyNumber()); // Hardware mode. { @@ -1401,9 +1398,9 @@ class SoftwareTextureLayerTest : public LayerTreeTest { !HasImplThread() && !layer_tree_host()->GetSettings().single_thread_proxy_scheduler; auto sink = std::make_unique<viz::TestLayerTreeFrameSink>( - nullptr, nullptr, shared_bitmap_manager(), gpu_memory_buffer_manager(), - renderer_settings, ImplThreadTaskRunner(), synchronous_composite, - disable_display_vsync, refresh_rate); + nullptr, nullptr, gpu_memory_buffer_manager(), renderer_settings, + ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync, + refresh_rate); frame_sink_ = sink.get(); num_frame_sinks_created_++; return sink; @@ -1450,7 +1447,7 @@ class SoftwareTextureLayerSwitchTreesTest : public SoftwareTextureLayerTest { // Give the TextureLayer a resource so it contributes to the frame. It // doesn't need to register the SharedBitmapId otherwise. texture_layer_->SetTransferableResource( - viz::TransferableResource::MakeSoftware(id_, 0, gfx::Size(1, 1), + viz::TransferableResource::MakeSoftware(id_, gfx::Size(1, 1), viz::RGBA_8888), viz::SingleReleaseCallback::Create( base::BindOnce([](const gpu::SyncToken&, bool) {}))); @@ -1558,7 +1555,7 @@ class SoftwareTextureLayerMultipleRegisterTest // Give the TextureLayer a resource so it contributes to the frame. It // doesn't need to register the SharedBitmapId otherwise. texture_layer_->SetTransferableResource( - viz::TransferableResource::MakeSoftware(id1_, 0, gfx::Size(1, 1), + viz::TransferableResource::MakeSoftware(id1_, gfx::Size(1, 1), viz::RGBA_8888), viz::SingleReleaseCallback::Create( base::BindOnce([](const gpu::SyncToken&, bool) {}))); @@ -1660,7 +1657,7 @@ class SoftwareTextureLayerRegisterUnregisterTest // Give the TextureLayer a resource so it contributes to the frame. It // doesn't need to register the SharedBitmapId otherwise. texture_layer_->SetTransferableResource( - viz::TransferableResource::MakeSoftware(id1_, 0, gfx::Size(1, 1), + viz::TransferableResource::MakeSoftware(id1_, gfx::Size(1, 1), viz::RGBA_8888), viz::SingleReleaseCallback::Create( base::BindOnce([](const gpu::SyncToken&, bool) {}))); @@ -1725,6 +1722,18 @@ class SoftwareTextureLayerLoseFrameSinkTest : public SoftwareTextureLayerTest { } void DidCommitAndDrawFrame() override { + // We run the next step in a clean stack, so that we don't cause side + // effects that will interfere with this current stack unwinding. + // Specifically, removing the LayerTreeFrameSink destroys the Display + // and the BeginFrameSource, but they can be on the stack (see + // https://crbug.com/829484). + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&SoftwareTextureLayerLoseFrameSinkTest::NextStep, + base::Unretained(this))); + } + + void NextStep() { step_ = layer_tree_host()->SourceFrameNumber(); switch (step_) { case 1: @@ -1736,7 +1745,7 @@ class SoftwareTextureLayerLoseFrameSinkTest : public SoftwareTextureLayerTest { // Give the TextureLayer a resource so it contributes to the frame. It // doesn't need to register the SharedBitmapId otherwise. texture_layer_->SetTransferableResource( - viz::TransferableResource::MakeSoftware(id_, 0, gfx::Size(1, 1), + viz::TransferableResource::MakeSoftware(id_, gfx::Size(1, 1), viz::RGBA_8888), viz::SingleReleaseCallback::Create( base::BindOnce([](const gpu::SyncToken&, bool) {}))); @@ -1756,7 +1765,7 @@ class SoftwareTextureLayerLoseFrameSinkTest : public SoftwareTextureLayerTest { // VizDisplayCompositor. texture_layer_->ClearClient(); texture_layer_->SetTransferableResource( - viz::TransferableResource::MakeSoftware(id_, 0, gfx::Size(1, 1), + viz::TransferableResource::MakeSoftware(id_, gfx::Size(1, 1), viz::RGBA_8888), viz::SingleReleaseCallback::Create( base::BindOnce([](const gpu::SyncToken&, bool) {}))); @@ -1807,8 +1816,7 @@ class SoftwareTextureLayerLoseFrameSinkTest : public SoftwareTextureLayerTest { void* first_frame_sink_; }; -// TODO(crbug.com/829923): Flaky with a heap-use-after-free. -// SINGLE_AND_MULTI_THREAD_TEST_F(SoftwareTextureLayerLoseFrameSinkTest); +SINGLE_AND_MULTI_THREAD_TEST_F(SoftwareTextureLayerLoseFrameSinkTest); class SoftwareTextureLayerUnregisterRegisterTest : public SoftwareTextureLayerTest { @@ -1847,7 +1855,7 @@ class SoftwareTextureLayerUnregisterRegisterTest // Give the TextureLayer a resource so it contributes to the frame. It // doesn't need to register the SharedBitmapId otherwise. texture_layer_->SetTransferableResource( - viz::TransferableResource::MakeSoftware(id_, 0, gfx::Size(1, 1), + viz::TransferableResource::MakeSoftware(id_, gfx::Size(1, 1), viz::RGBA_8888), viz::SingleReleaseCallback::Create( base::BindOnce([](const gpu::SyncToken&, bool) {}))); diff --git a/chromium/cc/layers/ui_resource_layer_impl.h b/chromium/cc/layers/ui_resource_layer_impl.h index 8660ab7a913..ed37db2cfd1 100644 --- a/chromium/cc/layers/ui_resource_layer_impl.h +++ b/chromium/cc/layers/ui_resource_layer_impl.h @@ -11,7 +11,6 @@ #include "base/memory/ptr_util.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" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -21,6 +20,7 @@ class DictionaryValue; } namespace cc { +class LayerTreeResourceProvider; class CC_EXPORT UIResourceLayerImpl : public LayerImpl { public: diff --git a/chromium/cc/layers/ui_resource_layer_unittest.cc b/chromium/cc/layers/ui_resource_layer_unittest.cc index 87a21390da3..e4e21aabf65 100644 --- a/chromium/cc/layers/ui_resource_layer_unittest.cc +++ b/chromium/cc/layers/ui_resource_layer_unittest.cc @@ -6,7 +6,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/animation_host.h" -#include "cc/resources/resource_provider.h" #include "cc/resources/scoped_ui_resource.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/geometry_test_utils.h" diff --git a/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc b/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc index 19481d3929e..32627b820e6 100644 --- a/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc +++ b/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc @@ -41,7 +41,7 @@ class VideoFrameProviderClientImplTest : public testing::Test, DebugSetImplThreadAndMainThreadBlocked(impl_.task_runner_provider()); } - ~VideoFrameProviderClientImplTest() { + ~VideoFrameProviderClientImplTest() override { if (!client_impl_->Stopped()) { client_impl_->Stop(); DCHECK(client_impl_->Stopped()); diff --git a/chromium/cc/layers/video_layer_impl.cc b/chromium/cc/layers/video_layer_impl.cc index d431a96572c..4e2843f2ca3 100644 --- a/chromium/cc/layers/video_layer_impl.cc +++ b/chromium/cc/layers/video_layer_impl.cc @@ -10,7 +10,8 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "cc/layers/video_frame_provider_client_impl.h" -#include "cc/resources/resource_provider.h" +#include "cc/resources/layer_tree_resource_provider.h" +#include "cc/trees/layer_tree_frame_sink.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/occlusion.h" #include "cc/trees/task_runner_provider.h" @@ -107,7 +108,9 @@ bool VideoLayerImpl::WillDraw(DrawMode draw_mode, layer_tree_impl()->layer_tree_frame_sink(), layer_tree_impl()->resource_provider(), settings.use_stream_video_draw_quad, - settings.resource_settings.use_gpu_memory_buffer_resources); + settings.resource_settings.use_gpu_memory_buffer_resources, + settings.resource_settings.use_r16_texture, + layer_tree_impl()->max_texture_size()); } updater_->ObtainFrameResources(frame_); return true; diff --git a/chromium/cc/layers/viewport.cc b/chromium/cc/layers/viewport.cc index d19c08cdd93..fe4371883bb 100644 --- a/chromium/cc/layers/viewport.cc +++ b/chromium/cc/layers/viewport.cc @@ -150,7 +150,6 @@ gfx::Vector2dF Viewport::ScrollAnimated(const gfx::Vector2dF& delta, will_animate = host_impl_->ScrollAnimationCreate(outer_node, outer_delta, delayed_by); } - if (will_animate) { // Consume entire scroll delta as long as we are starting an animation. return delta; diff --git a/chromium/cc/layers/viewport.h b/chromium/cc/layers/viewport.h index d5733643139..0d8f3afaddf 100644 --- a/chromium/cc/layers/viewport.h +++ b/chromium/cc/layers/viewport.h @@ -62,6 +62,8 @@ class CC_EXPORT Viewport { gfx::Vector2dF ScrollAnimated(const gfx::Vector2dF& delta, base::TimeDelta delayed_by); + gfx::ScrollOffset TotalScrollOffset() const; + void PinchUpdate(float magnify_delta, const gfx::Point& anchor); void PinchEnd(const gfx::Point& anchor, bool snap_to_min); @@ -84,7 +86,6 @@ class CC_EXPORT Viewport { gfx::Vector2dF ScrollBrowserControls(const gfx::Vector2dF& delta); gfx::ScrollOffset MaxTotalScrollOffset() const; - gfx::ScrollOffset TotalScrollOffset() const; LayerImpl* InnerScrollLayer() const; LayerImpl* OuterScrollLayer() const; diff --git a/chromium/cc/output/overlay_candidate.cc b/chromium/cc/output/overlay_candidate.cc deleted file mode 100644 index 829cacd0516..00000000000 --- a/chromium/cc/output/overlay_candidate.cc +++ /dev/null @@ -1,395 +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/output/overlay_candidate.h" - -#include <algorithm> -#include <limits> -#include "base/logging.h" -#include "cc/base/math_util.h" -#include "cc/resources/display_resource_provider.h" -#include "components/viz/common/quads/solid_color_draw_quad.h" -#include "components/viz/common/quads/stream_video_draw_quad.h" -#include "components/viz/common/quads/texture_draw_quad.h" -#include "components/viz/common/quads/tile_draw_quad.h" -#include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/geometry/vector3d_f.h" - -namespace cc { - -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) { - if (std::abs(vec.z()) > kEpsilon) - return NONE; - const bool x_zero = (std::abs(vec.x()) <= kEpsilon); - const bool y_zero = (std::abs(vec.y()) <= kEpsilon); - if (x_zero && !y_zero) - return (vec.y() > 0) ? AXIS_POS_Y : AXIS_NEG_Y; - else if (y_zero && !x_zero) - return (vec.x() > 0) ? AXIS_POS_X : AXIS_NEG_X; - else - return NONE; -} - -gfx::OverlayTransform GetOverlayTransform(const gfx::Transform& quad_transform, - bool y_flipped) { - if (!quad_transform.Preserves2dAxisAlignment()) { - return gfx::OVERLAY_TRANSFORM_INVALID; - } - - gfx::Vector3dF x_axis = MathUtil::GetXAxis(quad_transform); - gfx::Vector3dF y_axis = MathUtil::GetYAxis(quad_transform); - if (y_flipped) { - y_axis.Scale(-1); - } - - Axis x_to = VectorToAxis(x_axis); - Axis y_to = VectorToAxis(y_axis); - - if (x_to == AXIS_POS_X && y_to == AXIS_POS_Y) - return gfx::OVERLAY_TRANSFORM_NONE; - else if (x_to == AXIS_NEG_X && y_to == AXIS_POS_Y) - return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL; - else if (x_to == AXIS_POS_X && y_to == AXIS_NEG_Y) - return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL; - else if (x_to == AXIS_NEG_Y && y_to == AXIS_POS_X) - return gfx::OVERLAY_TRANSFORM_ROTATE_270; - else if (x_to == AXIS_NEG_X && y_to == AXIS_NEG_Y) - return gfx::OVERLAY_TRANSFORM_ROTATE_180; - else if (x_to == AXIS_POS_Y && y_to == AXIS_NEG_X) - return gfx::OVERLAY_TRANSFORM_ROTATE_90; - else - return gfx::OVERLAY_TRANSFORM_INVALID; -} - -// Apply transform |delta| to |in| and return the resulting transform, -// or OVERLAY_TRANSFORM_INVALID. -gfx::OverlayTransform ComposeTransforms(gfx::OverlayTransform delta, - gfx::OverlayTransform in) { - // There are 8 different possible transforms. We can characterize these - // by looking at where the origin moves and the direction the horizontal goes. - // (TL=top-left, BR=bottom-right, H=horizontal, V=vertical). - // NONE: TL, H - // FLIP_VERTICAL: BL, H - // FLIP_HORIZONTAL: TR, H - // ROTATE_90: TR, V - // ROTATE_180: BR, H - // ROTATE_270: BL, V - // Missing transforms: TL, V & BR, V - // Basic combinations: - // Flip X & Y -> Rotate 180 (TL,H -> TR,H -> BR,H or TL,H -> BL,H -> BR,H) - // Flip X or Y + Rotate 180 -> other flip (eg, TL,H -> TR,H -> BL,H) - // Rotate + Rotate simply adds values. - // Rotate 90/270 + flip is invalid because we can only have verticals with - // the origin in TR or BL. - if (delta == gfx::OVERLAY_TRANSFORM_NONE) - return in; - switch (in) { - case gfx::OVERLAY_TRANSFORM_NONE: - return delta; - case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL: - switch (delta) { - case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL: - return gfx::OVERLAY_TRANSFORM_NONE; - case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL: - return gfx::OVERLAY_TRANSFORM_ROTATE_180; - case gfx::OVERLAY_TRANSFORM_ROTATE_180: - return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL; - default: - return gfx::OVERLAY_TRANSFORM_INVALID; - } - break; - case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL: - switch (delta) { - case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL: - return gfx::OVERLAY_TRANSFORM_NONE; - case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL: - return gfx::OVERLAY_TRANSFORM_ROTATE_180; - case gfx::OVERLAY_TRANSFORM_ROTATE_90: - case gfx::OVERLAY_TRANSFORM_ROTATE_180: - return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL; - case gfx::OVERLAY_TRANSFORM_ROTATE_270: - default: - return gfx::OVERLAY_TRANSFORM_INVALID; - } - break; - case gfx::OVERLAY_TRANSFORM_ROTATE_90: - switch (delta) { - case gfx::OVERLAY_TRANSFORM_ROTATE_90: - return gfx::OVERLAY_TRANSFORM_ROTATE_180; - case gfx::OVERLAY_TRANSFORM_ROTATE_180: - return gfx::OVERLAY_TRANSFORM_ROTATE_270; - case gfx::OVERLAY_TRANSFORM_ROTATE_270: - return gfx::OVERLAY_TRANSFORM_NONE; - default: - return gfx::OVERLAY_TRANSFORM_INVALID; - } - break; - case gfx::OVERLAY_TRANSFORM_ROTATE_180: - switch (delta) { - case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL: - return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL; - case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL: - return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL; - case gfx::OVERLAY_TRANSFORM_ROTATE_90: - return gfx::OVERLAY_TRANSFORM_ROTATE_270; - case gfx::OVERLAY_TRANSFORM_ROTATE_180: - return gfx::OVERLAY_TRANSFORM_NONE; - case gfx::OVERLAY_TRANSFORM_ROTATE_270: - return gfx::OVERLAY_TRANSFORM_ROTATE_90; - default: - return gfx::OVERLAY_TRANSFORM_INVALID; - } - break; - case gfx::OVERLAY_TRANSFORM_ROTATE_270: - switch (delta) { - case gfx::OVERLAY_TRANSFORM_ROTATE_90: - return gfx::OVERLAY_TRANSFORM_NONE; - case gfx::OVERLAY_TRANSFORM_ROTATE_180: - return gfx::OVERLAY_TRANSFORM_ROTATE_90; - case gfx::OVERLAY_TRANSFORM_ROTATE_270: - return gfx::OVERLAY_TRANSFORM_ROTATE_180; - default: - return gfx::OVERLAY_TRANSFORM_INVALID; - } - break; - default: - return gfx::OVERLAY_TRANSFORM_INVALID; - } -} - -} // namespace - -OverlayCandidate::OverlayCandidate() - : transform(gfx::OVERLAY_TRANSFORM_NONE), - 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) - is_backed_by_surface_texture(false), - is_promotable_hint(false), -#endif - plane_z_order(0), - is_unoccluded(false), - overlay_handled(false) { -} - -OverlayCandidate::OverlayCandidate(const OverlayCandidate& other) = default; - -OverlayCandidate::~OverlayCandidate() = default; - -// static -bool OverlayCandidate::FromDrawQuad(DisplayResourceProvider* resource_provider, - const SkMatrix44& output_color_matrix, - const viz::DrawQuad* quad, - OverlayCandidate* candidate) { - // It is currently not possible to set a color conversion matrix on an HW - // overlay plane. - // TODO(dcastagna): Remove this check once crbug.com/792757 is resolved. - if (!output_color_matrix.isIdentity()) - return false; - - // 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; - - switch (quad->material) { - case viz::DrawQuad::TEXTURE_CONTENT: - return FromTextureQuad(resource_provider, - viz::TextureDrawQuad::MaterialCast(quad), - candidate); - case viz::DrawQuad::TILED_CONTENT: - return FromTileQuad(resource_provider, - viz::TileDrawQuad::MaterialCast(quad), candidate); - case viz::DrawQuad::STREAM_VIDEO_CONTENT: - return FromStreamVideoQuad(resource_provider, - viz::StreamVideoDrawQuad::MaterialCast(quad), - candidate); - default: - break; - } - - return false; -} - -// static -bool OverlayCandidate::IsInvisibleQuad(const viz::DrawQuad* quad) { - float opacity = quad->shared_quad_state->opacity; - if (opacity < std::numeric_limits<float>::epsilon()) - return true; - if (quad->material == viz::DrawQuad::SOLID_COLOR) { - SkColor color = viz::SolidColorDrawQuad::MaterialCast(quad)->color; - float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; - return quad->ShouldDrawWithBlending() && - alpha < std::numeric_limits<float>::epsilon(); - } - return false; -} - -// static -bool OverlayCandidate::IsOccluded(const OverlayCandidate& candidate, - viz::QuadList::ConstIterator quad_list_begin, - viz::QuadList::ConstIterator quad_list_end) { - // Check that no visible quad overlaps the candidate. - for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end; - ++overlap_iter) { - gfx::RectF overlap_rect = MathUtil::MapClippedRect( - overlap_iter->shared_quad_state->quad_to_target_transform, - gfx::RectF(overlap_iter->rect)); - if (candidate.display_rect.Intersects(overlap_rect) && - !OverlayCandidate::IsInvisibleQuad(*overlap_iter)) - return true; - } - return false; -} - -// static -bool OverlayCandidate::FromDrawQuadResource( - DisplayResourceProvider* resource_provider, - const viz::DrawQuad* quad, - viz::ResourceId resource_id, - bool y_flipped, - OverlayCandidate* candidate) { - if (!resource_provider->IsOverlayCandidate(resource_id)) - return false; - - candidate->format = resource_provider->GetBufferFormat(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, y_flipped); - if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID) - return false; - - auto& transform = quad->shared_quad_state->quad_to_target_transform; - candidate->display_rect = gfx::RectF(quad->rect); - transform.TransformRect(&candidate->display_rect); - - candidate->clip_rect = quad->shared_quad_state->clip_rect; - candidate->is_clipped = quad->shared_quad_state->is_clipped; - candidate->is_opaque = !quad->ShouldDrawWithBlending(); - - candidate->resource_id = resource_id; - candidate->transform = overlay_transform; - - return true; -} - -// static -bool OverlayCandidate::FromTextureQuad( - DisplayResourceProvider* resource_provider, - const viz::TextureDrawQuad* quad, - OverlayCandidate* candidate) { - if (quad->background_color != SK_ColorTRANSPARENT) - return false; - if (!FromDrawQuadResource(resource_provider, quad, quad->resource_id(), - quad->y_flipped, candidate)) { - return false; - } - candidate->resource_size_in_pixels = quad->resource_size_in_pixels(); - candidate->uv_rect = BoundingRect(quad->uv_top_left, quad->uv_bottom_right); - return true; -} - -// static -bool OverlayCandidate::FromTileQuad(DisplayResourceProvider* resource_provider, - const viz::TileDrawQuad* quad, - OverlayCandidate* candidate) { - if (!FromDrawQuadResource(resource_provider, quad, quad->resource_id(), false, - candidate)) { - return false; - } - candidate->resource_size_in_pixels = quad->texture_size; - candidate->uv_rect = quad->tex_coord_rect; - return true; -} - -// static -bool OverlayCandidate::FromStreamVideoQuad( - DisplayResourceProvider* resource_provider, - const viz::StreamVideoDrawQuad* quad, - OverlayCandidate* candidate) { - if (!FromDrawQuadResource(resource_provider, quad, quad->resource_id(), false, - candidate)) { - return false; - } - if (!quad->matrix.IsScaleOrTranslation()) { - // We cannot handle anything other than scaling & translation for texture - // coordinates yet. - return false; - } - candidate->resource_id = quad->resource_id(); - candidate->resource_size_in_pixels = quad->resource_size_in_pixels(); -#if defined(OS_ANDROID) - candidate->is_backed_by_surface_texture = - resource_provider->IsBackedBySurfaceTexture(quad->resource_id()); -#endif - - gfx::Point3F uv0 = gfx::Point3F(0, 0, 0); - gfx::Point3F uv1 = gfx::Point3F(1, 1, 0); - quad->matrix.TransformPoint(&uv0); - quad->matrix.TransformPoint(&uv1); - gfx::Vector3dF delta = uv1 - uv0; - if (delta.x() < 0) { - candidate->transform = ComposeTransforms( - gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL, candidate->transform); - float x0 = uv0.x(); - uv0.set_x(uv1.x()); - uv1.set_x(x0); - delta.set_x(-delta.x()); - } - - if (delta.y() < 0) { - // In this situation, uv0y < uv1y. Since we overlay inverted, a request - // to invert the source texture means we can just output the texture - // normally and it will be correct. - candidate->uv_rect = gfx::RectF(uv0.x(), uv1.y(), delta.x(), -delta.y()); - } else { - candidate->transform = ComposeTransforms( - gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL, candidate->transform); - candidate->uv_rect = gfx::RectF(uv0.x(), uv0.y(), delta.x(), delta.y()); - } - return true; -} - -OverlayCandidateList::OverlayCandidateList() = default; - -OverlayCandidateList::OverlayCandidateList(const OverlayCandidateList& other) = - default; - -OverlayCandidateList::OverlayCandidateList(OverlayCandidateList&& other) = - default; - -OverlayCandidateList::~OverlayCandidateList() = default; - -OverlayCandidateList& OverlayCandidateList::operator=( - const OverlayCandidateList& other) = default; - -OverlayCandidateList& OverlayCandidateList::operator=( - OverlayCandidateList&& other) = default; - -void OverlayCandidateList::AddPromotionHint(const OverlayCandidate& candidate) { - promotion_hint_info_map_[candidate.resource_id] = candidate.display_rect; -} - -} // namespace cc diff --git a/chromium/cc/output/overlay_candidate.h b/chromium/cc/output/overlay_candidate.h deleted file mode 100644 index f304951e83a..00000000000 --- a/chromium/cc/output/overlay_candidate.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_OUTPUT_OVERLAY_CANDIDATE_H_ -#define CC_OUTPUT_OVERLAY_CANDIDATE_H_ - -#include <map> -#include <vector> - -#include "cc/cc_export.h" -#include "components/viz/common/quads/render_pass.h" -#include "components/viz/common/resources/resource_id.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" -#include "ui/gfx/overlay_transform.h" -#include "ui/gfx/transform.h" - -namespace gfx { -class Rect; -} - -namespace viz { -class StreamVideoDrawQuad; -class TextureDrawQuad; -class TileDrawQuad; -} // namespace viz - -namespace cc { -class DisplayResourceProvider; - -class CC_EXPORT OverlayCandidate { - public: - // Returns true and fills in |candidate| if |draw_quad| is of a known quad - // type and contains an overlayable resource. - static bool FromDrawQuad(DisplayResourceProvider* resource_provider, - const SkMatrix44& output_color_matrix, - const viz::DrawQuad* quad, - OverlayCandidate* candidate); - // Returns true if |quad| will not block quads underneath from becoming - // an overlay. - static bool IsInvisibleQuad(const viz::DrawQuad* quad); - - // Returns true if any any of the quads in the list given by |quad_list_begin| - // and |quad_list_end| are visible and on top of |candidate|. - static bool IsOccluded(const OverlayCandidate& candidate, - viz::QuadList::ConstIterator quad_list_begin, - viz::QuadList::ConstIterator quad_list_end); - - OverlayCandidate(); - OverlayCandidate(const OverlayCandidate& other); - ~OverlayCandidate(); - - // Transformation to apply to layer during composition. - gfx::OverlayTransform transform; - // 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 - // to integer coordinates if setting |overlay_handled| to true. - gfx::RectF display_rect; - // Crop within the buffer to be placed inside |display_rect|. - gfx::RectF uv_rect; - // Clip rect in the target content space after composition. - 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; - // Texture resource to present in an overlay. - unsigned resource_id; - -#if defined(OS_ANDROID) - // For candidates from StreamVideoDrawQuads, this records whether the quad is - // marked as being backed by a SurfaceTexture or not. If so, it's not really - // promotable to an overlay. - bool is_backed_by_surface_texture; - - // Filled in by the OverlayCandidateValidator to indicate whether this is a - // promotable candidate or not. - bool is_promotable_hint; -#endif - - // Stacking order of the overlay plane relative to the main surface, - // which is 0. Signed to allow for "underlays". - int plane_z_order; - // True if the overlay does not have any visible quads on top of it. Set by - // the strategy so the OverlayProcessor can consider subtracting damage caused - // by underlay quads. - bool is_unoccluded; - - // To be modified by the implementer if this candidate can go into - // an overlay. - bool overlay_handled; - - private: - static bool FromDrawQuadResource(DisplayResourceProvider* resource_provider, - const viz::DrawQuad* quad, - viz::ResourceId resource_id, - bool y_flipped, - OverlayCandidate* candidate); - static bool FromTextureQuad(DisplayResourceProvider* resource_provider, - const viz::TextureDrawQuad* quad, - OverlayCandidate* candidate); - static bool FromTileQuad(DisplayResourceProvider* resource_provider, - const viz::TileDrawQuad* quad, - OverlayCandidate* candidate); - static bool FromStreamVideoQuad(DisplayResourceProvider* resource_provider, - const viz::StreamVideoDrawQuad* quad, - OverlayCandidate* candidate); -}; - -class CC_EXPORT OverlayCandidateList : public std::vector<OverlayCandidate> { - public: - OverlayCandidateList(); - OverlayCandidateList(const OverlayCandidateList&); - OverlayCandidateList(OverlayCandidateList&&); - ~OverlayCandidateList(); - - OverlayCandidateList& operator=(const OverlayCandidateList&); - OverlayCandidateList& operator=(OverlayCandidateList&&); - - // [id] == candidate's |display_rect| for all promotable resources. - using PromotionHintInfoMap = std::map<viz::ResourceId, gfx::RectF>; - - // For android, this provides a set of resources that could be promoted to - // overlay, if one backs them with a SurfaceView. - PromotionHintInfoMap promotion_hint_info_map_; - - // Helper to insert |candidate| into |promotion_hint_info_|. - void AddPromotionHint(const OverlayCandidate& candidate); -}; - -} // namespace cc - -#endif // CC_OUTPUT_OVERLAY_CANDIDATE_H_ diff --git a/chromium/cc/paint/BUILD.gn b/chromium/cc/paint/BUILD.gn index 535acba1472..92306d62373 100644 --- a/chromium/cc/paint/BUILD.gn +++ b/chromium/cc/paint/BUILD.gn @@ -67,6 +67,8 @@ cc_component("paint") { "paint_typeface.h", "paint_typeface_transfer_cache_entry.cc", "paint_typeface_transfer_cache_entry.h", + "path_transfer_cache_entry.cc", + "path_transfer_cache_entry.h", "raw_memory_transfer_cache_entry.cc", "raw_memory_transfer_cache_entry.h", "record_paint_canvas.cc", @@ -75,6 +77,8 @@ cc_component("paint") { "render_surface_filters.h", "scoped_raster_flags.cc", "scoped_raster_flags.h", + "shader_transfer_cache_entry.cc", + "shader_transfer_cache_entry.h", "skia_paint_canvas.cc", "skia_paint_canvas.h", "skia_paint_image_generator.cc", @@ -120,6 +124,7 @@ fuzzer_test("paint_op_buffer_fuzzer") { "//cc:test_support", "//cc/paint", "//components/viz/test:test_support", + "//gpu/command_buffer/service:gles2", ] } diff --git a/chromium/cc/paint/DEPS b/chromium/cc/paint/DEPS index 3761569771d..7c3f35427c6 100644 --- a/chromium/cc/paint/DEPS +++ b/chromium/cc/paint/DEPS @@ -1,6 +1,7 @@ specific_include_rules = { "paint_op_buffer_fuzzer.cc": [ "+components/viz/test", + "+gpu/command_buffer", ], "transfer_cache_fuzzer.cc": [ "+components/viz/test", diff --git a/chromium/cc/paint/display_item_list.h b/chromium/cc/paint/display_item_list.h index 0ade2b179f3..feb8e5407b7 100644 --- a/chromium/cc/paint/display_item_list.h +++ b/chromium/cc/paint/display_item_list.h @@ -9,6 +9,7 @@ #include <memory> #include <utility> +#include <vector> #include "base/gtest_prod_util.h" #include "base/macros.h" @@ -28,6 +29,7 @@ class SkCanvas; namespace gpu { namespace raster { +class RasterImplementation; class RasterImplementationGLES; } // namespace raster } // namespace gpu @@ -192,6 +194,7 @@ class CC_PAINT_EXPORT DisplayItemList private: FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithNoOps); FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithOps); + friend gpu::raster::RasterImplementation; friend gpu::raster::RasterImplementationGLES; ~DisplayItemList(); diff --git a/chromium/cc/paint/image_transfer_cache_entry.cc b/chromium/cc/paint/image_transfer_cache_entry.cc index c0f6d025f2c..493a9840a18 100644 --- a/chromium/cc/paint/image_transfer_cache_entry.cc +++ b/chromium/cc/paint/image_transfer_cache_entry.cc @@ -59,7 +59,11 @@ uint32_t ClientImageTransferCacheEntry::Id() const { bool ClientImageTransferCacheEntry::Serialize(base::span<uint8_t> data) const { DCHECK_GE(data.size(), SerializedSize()); - PaintOpWriter writer(data.data(), data.size(), nullptr, nullptr); + // We don't need to populate the SerializeOptions here since the writer is + // only used for serializing primitives. + PaintOp::SerializeOptions options(nullptr, nullptr, nullptr, nullptr, nullptr, + false, SkMatrix::I()); + PaintOpWriter writer(data.data(), data.size(), options); writer.Write(pixmap_->colorType()); writer.Write(pixmap_->width()); writer.Write(pixmap_->height()); @@ -90,7 +94,10 @@ size_t ServiceImageTransferCacheEntry::CachedSize() const { bool ServiceImageTransferCacheEntry::Deserialize( GrContext* context, base::span<const uint8_t> data) { - PaintOpReader reader(data.data(), data.size(), nullptr); + // We don't need to populate the DeSerializeOptions here since the reader is + // only used for de-serializing primitives. + PaintOp::DeserializeOptions options(nullptr, nullptr); + PaintOpReader reader(data.data(), data.size(), options); SkColorType color_type; reader.Read(&color_type); uint32_t width; diff --git a/chromium/cc/paint/image_transfer_cache_entry.h b/chromium/cc/paint/image_transfer_cache_entry.h index fd3937d0926..3e709cafd64 100644 --- a/chromium/cc/paint/image_transfer_cache_entry.h +++ b/chromium/cc/paint/image_transfer_cache_entry.h @@ -56,9 +56,6 @@ class CC_PAINT_EXPORT ServiceImageTransferCacheEntry size_t CachedSize() const final; bool Deserialize(GrContext* context, base::span<const uint8_t> data) final; - void set_image_for_testing(sk_sp<SkImage> image) { - image_ = std::move(image); - } const sk_sp<SkImage>& image() { return image_; } private: diff --git a/chromium/cc/paint/oop_pixeltest.cc b/chromium/cc/paint/oop_pixeltest.cc index 6850d6f9ad9..cb3168a7783 100644 --- a/chromium/cc/paint/oop_pixeltest.cc +++ b/chromium/cc/paint/oop_pixeltest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <tuple> #include <vector> #include "base/command_line.h" @@ -10,7 +11,9 @@ #include "cc/base/region.h" #include "cc/layers/recording_source.h" #include "cc/paint/display_item_list.h" +#include "cc/paint/paint_filter.h" #include "cc/paint/paint_image_builder.h" +#include "cc/paint/paint_text_blob_builder.h" #include "cc/raster/playback_image_provider.h" #include "cc/raster/raster_source.h" #include "cc/test/pixel_test_utils.h" @@ -50,25 +53,25 @@ scoped_refptr<DisplayItemList> MakeNoopDisplayItemList() { class OopPixelTest : public testing::Test { public: void SetUp() override { - // Add an OOP rasterization command line flag so that we set - // |chromium_raster_transport| features flag. - // TODO(vmpstr): Is there a better way to do this? - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableOOPRasterization)) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableOOPRasterization); - } - - context_provider_ = - base::MakeRefCounted<TestInProcessContextProvider>(nullptr, true); - int max_texture_size = - context_provider_->ContextCapabilities().max_texture_size; + raster_context_provider_ = + base::MakeRefCounted<TestInProcessContextProvider>( + /*enable_oop_rasterization=*/true); + const int raster_max_texture_size = + raster_context_provider_->ContextCapabilities().max_texture_size; oop_image_cache_.reset(new GpuImageDecodeCache( - context_provider_.get(), true, kRGBA_8888_SkColorType, kWorkingSetSize, - max_texture_size)); + raster_context_provider_.get(), true, kRGBA_8888_SkColorType, + kWorkingSetSize, raster_max_texture_size)); + + gles2_context_provider_ = + base::MakeRefCounted<TestInProcessContextProvider>( + /*enable_oop_rasterization=*/false); + const int gles2_max_texture_size = + raster_context_provider_->ContextCapabilities().max_texture_size; gpu_image_cache_.reset(new GpuImageDecodeCache( - context_provider_.get(), false, kRGBA_8888_SkColorType, kWorkingSetSize, - max_texture_size)); + gles2_context_provider_.get(), false, kRGBA_8888_SkColorType, + kWorkingSetSize, gles2_max_texture_size)); + + ASSERT_EQ(raster_max_texture_size, gles2_max_texture_size); } class RasterOptions { @@ -107,24 +110,25 @@ class OopPixelTest : public testing::Test { SkBitmap Raster(scoped_refptr<DisplayItemList> display_item_list, const RasterOptions& options) { TestInProcessContextProvider::ScopedRasterContextLock lock( - context_provider_.get()); + raster_context_provider_.get()); PlaybackImageProvider image_provider(oop_image_cache_.get(), options.color_space, PlaybackImageProvider::Settings()); - gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); + gpu::gles2::GLES2Interface* gl = gles2_context_provider_->ContextGL(); int width = options.resource_size.width(); int height = options.resource_size.height(); // Create and allocate a texture on the raster interface. GLuint raster_texture_id; - auto* raster_implementation = context_provider_->RasterInterface(); + + auto* raster_implementation = raster_context_provider_->RasterInterface(); raster_texture_id = raster_implementation->CreateTexture( false, gfx::BufferUsage::GPU_READ, viz::ResourceFormat::RGBA_8888); raster_implementation->TexStorage2D(raster_texture_id, 1, width, height); raster_implementation->TexParameteri(raster_texture_id, - GL_TEXTURE_MIN_FILTER, GL_LINEAR); + GL_TEXTURE_MIN_FILTER, GL_NEAREST); EXPECT_EQ(raster_implementation->GetError(), static_cast<unsigned>(GL_NO_ERROR)); @@ -211,8 +215,8 @@ class OopPixelTest : public testing::Test { scoped_refptr<DisplayItemList> display_item_list, const RasterOptions& options) { TestInProcessContextProvider::ScopedRasterContextLock lock( - context_provider_.get()); - context_provider_->GrContext()->resetContext(); + gles2_context_provider_.get()); + gles2_context_provider_->GrContext()->resetContext(); // Generate bitmap via the "in process" raster path. This verifies // that the preamble setup in RasterSource::PlaybackToCanvas matches @@ -244,8 +248,8 @@ class OopPixelTest : public testing::Test { } SkImageInfo image_info = SkImageInfo::MakeN32Premul( options.resource_size.width(), options.resource_size.height()); - auto surface = SkSurface::MakeRenderTarget(context_provider_->GrContext(), - SkBudgeted::kYes, image_info); + auto surface = SkSurface::MakeRenderTarget( + gles2_context_provider_->GrContext(), SkBudgeted::kYes, image_info); SkCanvas* canvas = surface->getCanvas(); if (options.preclear) canvas->drawColor(options.preclear_color); @@ -259,7 +263,7 @@ class OopPixelTest : public testing::Test { options.full_raster_rect, options.playback_rect, raster_transform, settings); surface->prepareForExternalIO(); - EXPECT_EQ(context_provider_->ContextGL()->GetError(), + EXPECT_EQ(gles2_context_provider_->ContextGL()->GetError(), static_cast<unsigned>(GL_NO_ERROR)); SkBitmap bitmap; @@ -269,7 +273,7 @@ class OopPixelTest : public testing::Test { bitmap.allocPixels(info, options.resource_size.width() * 4); bool success = surface->readPixels(bitmap, 0, 0); CHECK(success); - EXPECT_EQ(context_provider_->ContextGL()->GetError(), + EXPECT_EQ(gles2_context_provider_->ContextGL()->GetError(), static_cast<unsigned>(GL_NO_ERROR)); return bitmap; } @@ -293,7 +297,8 @@ class OopPixelTest : public testing::Test { protected: enum { kWorkingSetSize = 64 * 1024 * 1024 }; - scoped_refptr<TestInProcessContextProvider> context_provider_; + scoped_refptr<TestInProcessContextProvider> raster_context_provider_; + scoped_refptr<TestInProcessContextProvider> gles2_context_provider_; std::unique_ptr<GpuImageDecodeCache> gpu_image_cache_; std::unique_ptr<GpuImageDecodeCache> oop_image_cache_; gl::DisableNullDrawGLBindings enable_pixel_output_; @@ -305,9 +310,11 @@ class OopImagePixelTest : public OopPixelTest, public ::testing::WithParamInterface<bool> { public: bool UseTooLargeImage() { return GetParam(); } + SkFilterQuality FilterQuality() { return kNone_SkFilterQuality; } + gfx::Size GetImageSize() { const int kMaxSize = 20000; - DCHECK_GT(kMaxSize, context_provider_->GrContext()->maxTextureSize()); + DCHECK_GT(kMaxSize, gles2_context_provider_->GrContext()->maxTextureSize()); return UseTooLargeImage() ? gfx::Size(10, kMaxSize) : gfx::Size(10, 10); } }; @@ -401,6 +408,9 @@ TEST_F(OopPixelTest, DrawRect) { } TEST_P(OopImagePixelTest, DrawImage) { + SCOPED_TRACE(base::StringPrintf("UseTooLargeImage: %d, FilterQuality: %d\n", + UseTooLargeImage(), FilterQuality())); + gfx::Rect rect(10, 10); gfx::Size image_size = GetImageSize(); @@ -423,7 +433,9 @@ TEST_P(OopImagePixelTest, DrawImage) { auto display_item_list = base::MakeRefCounted<DisplayItemList>(); display_item_list->StartPaint(); - display_item_list->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr); + PaintFlags flags; + flags.setFilterQuality(FilterQuality()); + display_item_list->push<DrawImageOp>(paint_image, 0.f, 0.f, &flags); display_item_list->EndPaintOfUnpaired(rect); display_item_list->Finalize(); @@ -434,7 +446,136 @@ TEST_P(OopImagePixelTest, DrawImage) { EXPECT_EQ(actual.getColor(0, 0), SK_ColorMAGENTA); } +TEST_P(OopImagePixelTest, DrawImageScaled) { + SCOPED_TRACE(base::StringPrintf("UseTooLargeImage: %d, FilterQuality: %d\n", + UseTooLargeImage(), FilterQuality())); + + gfx::Rect rect(10, 10); + gfx::Size image_size = GetImageSize(); + + SkBitmap bitmap; + bitmap.allocPixelsFlags( + SkImageInfo::MakeN32Premul(image_size.width(), image_size.height()), + SkBitmap::kZeroPixels_AllocFlag); + + SkCanvas canvas(bitmap); + canvas.drawColor(SK_ColorMAGENTA); + SkPaint green; + green.setColor(SK_ColorGREEN); + canvas.drawRect(SkRect::MakeXYWH(1, 2, 3, 4), green); + + sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); + auto builder = PaintImageBuilder::WithDefault().set_image(image, 0).set_id( + PaintImage::GetNextId()); + auto paint_image = builder.TakePaintImage(); + + auto display_item_list = base::MakeRefCounted<DisplayItemList>(); + display_item_list->StartPaint(); + display_item_list->push<ScaleOp>(0.5f, 0.5f); + PaintFlags flags; + flags.setFilterQuality(FilterQuality()); + display_item_list->push<DrawImageOp>(paint_image, 0.f, 0.f, &flags); + display_item_list->EndPaintOfUnpaired(rect); + display_item_list->Finalize(); + + auto actual = Raster(display_item_list, rect.size()); + auto expected = RasterExpectedBitmap(display_item_list, rect.size()); + ExpectEquals(actual, expected); +} + +TEST_P(OopImagePixelTest, DrawImageShaderScaled) { + SCOPED_TRACE(base::StringPrintf("UseTooLargeImage: %d, FilterQuality: %d\n", + UseTooLargeImage(), FilterQuality())); + + gfx::Rect rect(10, 10); + gfx::Size image_size = GetImageSize(); + + SkBitmap bitmap; + bitmap.allocPixelsFlags( + SkImageInfo::MakeN32Premul(image_size.width(), image_size.height()), + SkBitmap::kZeroPixels_AllocFlag); + + SkCanvas canvas(bitmap); + canvas.drawColor(SK_ColorMAGENTA); + SkPaint green; + green.setColor(SK_ColorGREEN); + canvas.drawRect(SkRect::MakeXYWH(1, 2, 3, 4), green); + + sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); + auto builder = PaintImageBuilder::WithDefault().set_image(image, 0).set_id( + PaintImage::GetNextId()); + auto paint_image = builder.TakePaintImage(); + auto paint_image_shader = + PaintShader::MakeImage(paint_image, SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode, nullptr); + + auto display_item_list = base::MakeRefCounted<DisplayItemList>(); + display_item_list->StartPaint(); + display_item_list->push<ScaleOp>(0.5f, 0.5f); + PaintFlags flags; + flags.setShader(paint_image_shader); + flags.setFilterQuality(FilterQuality()); + display_item_list->push<DrawRectOp>(gfx::RectToSkRect(rect), flags); + display_item_list->EndPaintOfUnpaired(rect); + display_item_list->Finalize(); + + auto actual = Raster(display_item_list, rect.size()); + auto expected = RasterExpectedBitmap(display_item_list, rect.size()); + ExpectEquals(actual, expected); +} + +TEST_P(OopImagePixelTest, DrawRecordShaderWithImageScaled) { + SCOPED_TRACE(base::StringPrintf("UseTooLargeImage: %d, FilterQuality: %d\n", + UseTooLargeImage(), FilterQuality())); + + gfx::Rect rect(10, 10); + gfx::Size image_size = GetImageSize(); + + SkBitmap bitmap; + bitmap.allocPixelsFlags( + SkImageInfo::MakeN32Premul(image_size.width(), image_size.height()), + SkBitmap::kZeroPixels_AllocFlag); + + SkCanvas canvas(bitmap); + canvas.drawColor(SK_ColorMAGENTA); + SkPaint green; + green.setColor(SK_ColorGREEN); + canvas.drawRect(SkRect::MakeXYWH(1, 2, 3, 4), green); + + sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); + auto builder = PaintImageBuilder::WithDefault().set_image(image, 0).set_id( + PaintImage::GetNextId()); + auto paint_image = builder.TakePaintImage(); + auto paint_record = sk_make_sp<PaintOpBuffer>(); + PaintFlags flags; + flags.setFilterQuality(FilterQuality()); + paint_record->push<DrawImageOp>(paint_image, 0.f, 0.f, &flags); + auto paint_record_shader = PaintShader::MakePaintRecord( + paint_record, gfx::RectToSkRect(rect), SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode, nullptr); + // Set the shader has animated images so gpu also goes through cc's image + // upload stack, instead of using skia. + paint_record_shader->set_has_animated_images(true); + + auto display_item_list = base::MakeRefCounted<DisplayItemList>(); + display_item_list->StartPaint(); + display_item_list->push<ScaleOp>(0.5f, 0.5f); + PaintFlags raster_flags; + raster_flags.setShader(paint_record_shader); + raster_flags.setFilterQuality(FilterQuality()); + display_item_list->push<DrawRectOp>(gfx::RectToSkRect(rect), raster_flags); + display_item_list->EndPaintOfUnpaired(rect); + display_item_list->Finalize(); + + auto actual = Raster(display_item_list, rect.size()); + auto expected = RasterExpectedBitmap(display_item_list, rect.size()); + ExpectEquals(actual, expected); +} + TEST_P(OopImagePixelTest, DrawImageWithTargetColorSpace) { + SCOPED_TRACE(base::StringPrintf("UseTooLargeImage: %d, FilterQuality: %d\n", + UseTooLargeImage(), FilterQuality())); + gfx::Rect rect(10, 10); gfx::Size image_size = GetImageSize(); @@ -457,7 +598,9 @@ TEST_P(OopImagePixelTest, DrawImageWithTargetColorSpace) { auto display_item_list = base::MakeRefCounted<DisplayItemList>(); display_item_list->StartPaint(); - display_item_list->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr); + PaintFlags flags; + flags.setFilterQuality(FilterQuality()); + display_item_list->push<DrawImageOp>(paint_image, 0.f, 0.f, &flags); display_item_list->EndPaintOfUnpaired(rect); display_item_list->Finalize(); @@ -473,6 +616,9 @@ TEST_P(OopImagePixelTest, DrawImageWithTargetColorSpace) { } TEST_P(OopImagePixelTest, DrawImageWithSourceColorSpace) { + SCOPED_TRACE(base::StringPrintf("UseTooLargeImage: %d, FilterQuality: %d\n", + UseTooLargeImage(), FilterQuality())); + gfx::Rect rect(10, 10); gfx::Size image_size = GetImageSize(); @@ -498,7 +644,9 @@ TEST_P(OopImagePixelTest, DrawImageWithSourceColorSpace) { auto display_item_list = base::MakeRefCounted<DisplayItemList>(); display_item_list->StartPaint(); - display_item_list->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr); + PaintFlags flags; + flags.setFilterQuality(FilterQuality()); + display_item_list->push<DrawImageOp>(paint_image, 0.f, 0.f, &flags); display_item_list->EndPaintOfUnpaired(rect); display_item_list->Finalize(); @@ -513,6 +661,9 @@ TEST_P(OopImagePixelTest, DrawImageWithSourceColorSpace) { } TEST_P(OopImagePixelTest, DrawImageWithSourceAndTargetColorSpace) { + SCOPED_TRACE(base::StringPrintf("UseTooLargeImage: %d, FilterQuality: %d\n", + UseTooLargeImage(), FilterQuality())); + gfx::Rect rect(10, 10); gfx::Size image_size = GetImageSize(); @@ -538,7 +689,9 @@ TEST_P(OopImagePixelTest, DrawImageWithSourceAndTargetColorSpace) { auto display_item_list = base::MakeRefCounted<DisplayItemList>(); display_item_list->StartPaint(); - display_item_list->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr); + PaintFlags flags; + flags.setFilterQuality(FilterQuality()); + display_item_list->push<DrawImageOp>(paint_image, 0.f, 0.f, &flags); display_item_list->EndPaintOfUnpaired(rect); display_item_list->Finalize(); @@ -1047,7 +1200,112 @@ TEST_F(OopPixelTest, DrawRectColorSpace) { ExpectEquals(actual, expected); } -INSTANTIATE_TEST_CASE_P(P, OopImagePixelTest, ::testing::Values(false, true)); +scoped_refptr<PaintTextBlob> buildTextBlob() { + SkFontStyle style; + PaintTypeface typeface = + PaintTypeface::FromFamilyNameAndFontStyle("monospace", style); + + PaintFont font; + font.SetTypeface(typeface); + font.SetTextEncoding(SkPaint::kGlyphID_TextEncoding); + font.SetHinting(SkPaint::kNormal_Hinting); + font.SetTextSize(10u); + + PaintTextBlobBuilder builder; + SkRect bounds = SkRect::MakeWH(100, 100); + const int glyphCount = 10; + const auto& runBuffer = builder.AllocRunPosH(font, glyphCount, 0, &bounds); + for (int i = 0; i < glyphCount; i++) { + runBuffer.glyphs[i] = static_cast<SkGlyphID>(i); + runBuffer.pos[i] = SkIntToScalar(i); + } + return builder.TakeTextBlob(); +} + +TEST_F(OopPixelTest, DrawTextBlob) { + RasterOptions options; + options.resource_size = gfx::Size(100, 100); + options.content_size = options.resource_size; + options.full_raster_rect = gfx::Rect(options.content_size); + options.playback_rect = options.full_raster_rect; + options.color_space = gfx::ColorSpace::CreateSRGB(); + + auto display_item_list = base::MakeRefCounted<DisplayItemList>(); + display_item_list->StartPaint(); + PaintFlags flags; + flags.setStyle(PaintFlags::kFill_Style); + flags.setColor(SK_ColorGREEN); + display_item_list->push<DrawTextBlobOp>(buildTextBlob(), 0u, 0u, flags); + display_item_list->EndPaintOfUnpaired(options.full_raster_rect); + display_item_list->Finalize(); + + auto actual = Raster(display_item_list, options); + auto expected = RasterExpectedBitmap(display_item_list, options); + ExpectEquals(actual, expected); +} + +TEST_F(OopPixelTest, DrawRecordShaderWithTextScaled) { + RasterOptions options; + options.resource_size = gfx::Size(100, 100); + options.content_size = options.resource_size; + options.full_raster_rect = gfx::Rect(options.content_size); + options.playback_rect = options.full_raster_rect; + options.color_space = gfx::ColorSpace::CreateSRGB(); + + auto paint_record = sk_make_sp<PaintOpBuffer>(); + PaintFlags flags; + flags.setStyle(PaintFlags::kFill_Style); + flags.setColor(SK_ColorGREEN); + paint_record->push<DrawTextBlobOp>(buildTextBlob(), 0u, 0u, flags); + auto paint_record_shader = PaintShader::MakePaintRecord( + paint_record, SkRect::MakeWH(25, 25), SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode, nullptr); + + auto display_item_list = base::MakeRefCounted<DisplayItemList>(); + display_item_list->StartPaint(); + display_item_list->push<ScaleOp>(2.f, 2.f); + PaintFlags shader_flags; + shader_flags.setShader(paint_record_shader); + display_item_list->push<DrawRectOp>(SkRect::MakeWH(50, 50), shader_flags); + display_item_list->EndPaintOfUnpaired(options.full_raster_rect); + display_item_list->Finalize(); + + auto actual = Raster(display_item_list, options); + auto expected = RasterExpectedBitmap(display_item_list, options); + ExpectEquals(actual, expected); +} + +TEST_F(OopPixelTest, DrawRecordFilterWithTextScaled) { + RasterOptions options; + options.resource_size = gfx::Size(100, 100); + options.content_size = options.resource_size; + options.full_raster_rect = gfx::Rect(options.content_size); + options.playback_rect = options.full_raster_rect; + options.color_space = gfx::ColorSpace::CreateSRGB(); + + auto paint_record = sk_make_sp<PaintOpBuffer>(); + PaintFlags flags; + flags.setStyle(PaintFlags::kFill_Style); + flags.setColor(SK_ColorGREEN); + paint_record->push<DrawTextBlobOp>(buildTextBlob(), 0u, 0u, flags); + auto paint_record_filter = + sk_make_sp<RecordPaintFilter>(paint_record, SkRect::MakeWH(100, 100)); + + auto display_item_list = base::MakeRefCounted<DisplayItemList>(); + display_item_list->StartPaint(); + display_item_list->push<ScaleOp>(2.f, 2.f); + PaintFlags shader_flags; + shader_flags.setImageFilter(paint_record_filter); + display_item_list->push<DrawRectOp>(SkRect::MakeWH(50, 50), shader_flags); + display_item_list->EndPaintOfUnpaired(options.full_raster_rect); + display_item_list->Finalize(); + + auto actual = Raster(display_item_list, options); + auto expected = RasterExpectedBitmap(display_item_list, options); + ExpectEquals(actual, expected); +} + +INSTANTIATE_TEST_CASE_P(P, OopImagePixelTest, ::testing::Bool()); } // namespace } // namespace cc diff --git a/chromium/cc/paint/paint_filter.cc b/chromium/cc/paint/paint_filter.cc index 947973cb130..f410b273562 100644 --- a/chromium/cc/paint/paint_filter.cc +++ b/chromium/cc/paint/paint_filter.cc @@ -980,8 +980,7 @@ PaintFlagsPaintFilter::PaintFlagsPaintFilter(PaintFlags flags, : PaintFilter(kType, crop_rect, flags.HasDiscardableImages()), flags_(std::move(flags)) { if (image_provider) { - raster_flags_.emplace(&flags_, image_provider, SkMatrix::I(), 255u, - true /* create_skia_shaders */); + raster_flags_.emplace(&flags_, image_provider, SkMatrix::I(), 255u); } cached_sk_filter_ = SkPaintImageFilter::Make( raster_flags_ ? raster_flags_->flags()->ToSkPaint() : flags_.ToSkPaint(), diff --git a/chromium/cc/paint/paint_image.cc b/chromium/cc/paint/paint_image.cc index 414e5988442..805520f8b37 100644 --- a/chromium/cc/paint/paint_image.cc +++ b/chromium/cc/paint/paint_image.cc @@ -15,8 +15,8 @@ namespace cc { namespace { -base::AtomicSequenceNumber g_next_id_; -base::AtomicSequenceNumber g_next_content_id_; +base::AtomicSequenceNumber g_next_image_id; +base::AtomicSequenceNumber g_next_image_content_id; } // namespace const PaintImage::Id PaintImage::kNonLazyStableId = -1; @@ -74,12 +74,12 @@ PaintImage::DecodingMode PaintImage::GetConservative(DecodingMode one, // static PaintImage::Id PaintImage::GetNextId() { - return g_next_id_.GetNext(); + return g_next_image_id.GetNext(); } // static PaintImage::ContentId PaintImage::GetNextContentId() { - return g_next_content_id_.GetNext(); + return g_next_image_content_id.GetNext(); } const sk_sp<SkImage>& PaintImage::GetSkImage() const { diff --git a/chromium/cc/paint/paint_op_buffer.cc b/chromium/cc/paint/paint_op_buffer.cc index 446fc6e1ec6..45ae2526f15 100644 --- a/chromium/cc/paint/paint_op_buffer.cc +++ b/chromium/cc/paint/paint_op_buffer.cc @@ -26,6 +26,23 @@ DrawImage CreateDrawImage(const PaintImage& image, flags ? flags->getFilterQuality() : kLow_SkFilterQuality, matrix); } + +bool IsScaleAdjustmentIdentity(const SkSize& scale_adjustment) { + return std::abs(scale_adjustment.width() - 1.f) < FLT_EPSILON && + std::abs(scale_adjustment.height() - 1.f) < FLT_EPSILON; +} + +SkRect AdjustSrcRectForScale(SkRect original, SkSize scale_adjustment) { + if (IsScaleAdjustmentIdentity(scale_adjustment)) + return original; + + float x_scale = scale_adjustment.width(); + float y_scale = scale_adjustment.height(); + return SkRect::MakeXYWH(original.x() * x_scale, original.y() * y_scale, + original.width() * x_scale, + original.height() * y_scale); +} + } // namespace #define TYPES(M) \ @@ -297,25 +314,37 @@ PlaybackParams::PlaybackParams(ImageProvider* image_provider, PlaybackParams::~PlaybackParams() {} -PaintOp::SerializeOptions::SerializeOptions() = default; +PlaybackParams::PlaybackParams(const PlaybackParams& other) = default; +PlaybackParams& PlaybackParams::operator=(const PlaybackParams& other) = + default; PaintOp::SerializeOptions::SerializeOptions( ImageProvider* image_provider, TransferCacheSerializeHelper* transfer_cache, SkCanvas* canvas, + SkStrikeServer* strike_server, + SkColorSpace* color_space, + bool can_use_lcd_text, const SkMatrix& original_ctm) - : transfer_cache(transfer_cache), + : image_provider(image_provider), + transfer_cache(transfer_cache), canvas(canvas), - image_provider(image_provider), + strike_server(strike_server), + color_space(color_space), + can_use_lcd_text(can_use_lcd_text), original_ctm(original_ctm) {} +PaintOp::DeserializeOptions::DeserializeOptions( + TransferCacheDeserializeHelper* transfer_cache, + SkStrikeClient* strike_client) + : transfer_cache(transfer_cache), strike_client(strike_client) {} + size_t AnnotateOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { auto* op = static_cast<const AnnotateOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); helper.Write(op->annotation_type); helper.Write(op->rect); helper.Write(op->data); @@ -327,8 +356,7 @@ size_t ClipPathOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const ClipPathOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); helper.Write(op->path); helper.Write(op->op); helper.Write(op->antialias); @@ -375,8 +403,7 @@ size_t DrawDRRectOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawDRRectOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; @@ -391,15 +418,20 @@ size_t DrawImageOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawImageOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; helper.Write(*serialized_flags); + + SkSize scale_adjustment = SkSize::Make(1.f, 1.f); helper.Write(CreateDrawImage(op->image, serialized_flags, - options.canvas->getTotalMatrix())); + options.canvas->getTotalMatrix()), + &scale_adjustment); helper.AlignMemory(alignof(SkScalar)); + helper.Write(scale_adjustment.width()); + helper.Write(scale_adjustment.height()); + helper.Write(op->left); helper.Write(op->top); return helper.size(); @@ -410,14 +442,22 @@ size_t DrawImageRectOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawImageRectOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; helper.Write(*serialized_flags); + + // Note that we don't request subsets here since the GpuImageCache has no + // optimizations for using subsets. + SkSize scale_adjustment = SkSize::Make(1.f, 1.f); helper.Write(CreateDrawImage(op->image, serialized_flags, - options.canvas->getTotalMatrix())); + options.canvas->getTotalMatrix()), + &scale_adjustment); + helper.AlignMemory(alignof(SkScalar)); + helper.Write(scale_adjustment.width()); + helper.Write(scale_adjustment.height()); + helper.Write(op->src); helper.Write(op->dst); helper.Write(op->constraint); @@ -429,8 +469,7 @@ size_t DrawIRectOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawIRectOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; @@ -444,8 +483,7 @@ size_t DrawLineOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawLineOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; @@ -463,8 +501,7 @@ size_t DrawOvalOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawOvalOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; @@ -478,8 +515,7 @@ size_t DrawPathOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawPathOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; @@ -503,8 +539,7 @@ size_t DrawRectOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawRectOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; @@ -518,8 +553,7 @@ size_t DrawRRectOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawRRectOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; @@ -533,8 +567,7 @@ size_t DrawTextBlobOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const DrawTextBlobOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; @@ -579,8 +612,7 @@ size_t SaveLayerOp::Serialize(const PaintOp* base_op, size_t size, const SerializeOptions& options) { auto* op = static_cast<const SaveLayerOp*>(base_op); - PaintOpWriter helper(memory, size, options.transfer_cache, - options.image_provider); + PaintOpWriter helper(memory, size, options); const auto* serialized_flags = options.flags_to_serialize; if (!serialized_flags) serialized_flags = &op->flags; @@ -654,7 +686,7 @@ PaintOp* AnnotateOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(AnnotateOp)); AnnotateOp* op = new (output) AnnotateOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->annotation_type); helper.Read(&op->rect); helper.Read(&op->data); @@ -675,7 +707,7 @@ PaintOp* ClipPathOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(ClipPathOp)); ClipPathOp* op = new (output) ClipPathOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->path); helper.Read(&op->op); helper.Read(&op->antialias); @@ -746,7 +778,7 @@ PaintOp* DrawDRRectOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawDRRectOp)); DrawDRRectOp* op = new (output) DrawDRRectOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); helper.Read(&op->outer); helper.Read(&op->inner); @@ -766,10 +798,14 @@ PaintOp* DrawImageOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawImageOp)); DrawImageOp* op = new (output) DrawImageOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); + helper.Read(&op->image); helper.AlignMemory(alignof(SkScalar)); + helper.Read(&op->scale_adjustment.fWidth); + helper.Read(&op->scale_adjustment.fHeight); + helper.Read(&op->left); helper.Read(&op->top); if (!helper.valid() || !op->IsValid()) { @@ -788,9 +824,14 @@ PaintOp* DrawImageRectOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawImageRectOp)); DrawImageRectOp* op = new (output) DrawImageRectOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); + helper.Read(&op->image); + helper.AlignMemory(alignof(SkScalar)); + helper.Read(&op->scale_adjustment.fWidth); + helper.Read(&op->scale_adjustment.fHeight); + helper.Read(&op->src); helper.Read(&op->dst); helper.Read(&op->constraint); @@ -810,7 +851,7 @@ PaintOp* DrawIRectOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawIRectOp)); DrawIRectOp* op = new (output) DrawIRectOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); helper.Read(&op->rect); if (!helper.valid() || !op->IsValid()) { @@ -829,7 +870,7 @@ PaintOp* DrawLineOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawLineOp)); DrawLineOp* op = new (output) DrawLineOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); helper.AlignMemory(alignof(SkScalar)); helper.Read(&op->x0); @@ -852,7 +893,7 @@ PaintOp* DrawOvalOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawOvalOp)); DrawOvalOp* op = new (output) DrawOvalOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); helper.Read(&op->oval); if (!helper.valid() || !op->IsValid()) { @@ -871,7 +912,7 @@ PaintOp* DrawPathOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawPathOp)); DrawPathOp* op = new (output) DrawPathOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); helper.Read(&op->path); if (!helper.valid() || !op->IsValid()) { @@ -900,7 +941,7 @@ PaintOp* DrawRectOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawRectOp)); DrawRectOp* op = new (output) DrawRectOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); helper.Read(&op->rect); if (!helper.valid() || !op->IsValid()) { @@ -919,7 +960,7 @@ PaintOp* DrawRRectOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawRRectOp)); DrawRRectOp* op = new (output) DrawRRectOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); helper.Read(&op->rrect); if (!helper.valid() || !op->IsValid()) { @@ -938,7 +979,7 @@ PaintOp* DrawTextBlobOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(DrawTextBlobOp)); DrawTextBlobOp* op = new (output) DrawTextBlobOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); helper.AlignMemory(alignof(SkScalar)); helper.Read(&op->x); @@ -996,7 +1037,7 @@ PaintOp* SaveLayerOp::Deserialize(const volatile void* input, DCHECK_GE(output_size, sizeof(SaveLayerOp)); SaveLayerOp* op = new (output) SaveLayerOp; - PaintOpReader helper(input, input_size, options.transfer_cache); + PaintOpReader helper(input, input_size, options); helper.Read(&op->flags); helper.Read(&op->bounds); if (!helper.valid() || !op->IsValid()) { @@ -1119,6 +1160,12 @@ void DrawImageOp::RasterWithFlags(const DrawImageOp* op, SkPaint paint = flags ? flags->ToSkPaint() : SkPaint(); if (!params.image_provider) { + const bool needs_scale = !IsScaleAdjustmentIdentity(op->scale_adjustment); + SkAutoCanvasRestore save_restore(canvas, needs_scale); + if (needs_scale) { + canvas->scale(1.f / op->scale_adjustment.width(), + 1.f / op->scale_adjustment.height()); + } canvas->drawImage(op->image.GetSkImage().get(), op->left, op->top, &paint); return; } @@ -1137,17 +1184,18 @@ void DrawImageOp::RasterWithFlags(const DrawImageOp* op, DCHECK_EQ(0, static_cast<int>(decoded_image.src_rect_offset().width())); DCHECK_EQ(0, static_cast<int>(decoded_image.src_rect_offset().height())); - bool need_scale = !decoded_image.is_scale_adjustment_identity(); - if (need_scale) { - canvas->save(); - canvas->scale(1.f / (decoded_image.scale_adjustment().width()), - 1.f / (decoded_image.scale_adjustment().height())); - } - - paint.setFilterQuality(decoded_image.filter_quality()); - canvas->drawImage(decoded_image.image().get(), op->left, op->top, &paint); - if (need_scale) - canvas->restore(); + SkSize scale_adjustment = SkSize::Make( + op->scale_adjustment.width() * decoded_image.scale_adjustment().width(), + op->scale_adjustment.height() * + decoded_image.scale_adjustment().height()); + const bool needs_scale = !IsScaleAdjustmentIdentity(scale_adjustment); + SkAutoCanvasRestore save_restore(canvas, needs_scale); + if (needs_scale) { + canvas->scale(1.f / scale_adjustment.width(), + 1.f / scale_adjustment.height()); + } + paint.setFilterQuality(decoded_image.filter_quality()); + canvas->drawImage(decoded_image.image().get(), op->left, op->top, &paint); } void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op, @@ -1160,7 +1208,8 @@ void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op, SkPaint paint = flags ? flags->ToSkPaint() : SkPaint(); if (!params.image_provider) { - canvas->drawImageRect(op->image.GetSkImage().get(), op->src, op->dst, + SkRect adjusted_src = AdjustSrcRectForScale(op->src, op->scale_adjustment); + canvas->drawImageRect(op->image.GetSkImage().get(), adjusted_src, op->dst, &paint, skconstraint); return; } @@ -1183,20 +1232,17 @@ void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op, const auto& decoded_image = scoped_decoded_draw_image.decoded_image(); DCHECK(decoded_image.image()); + SkSize scale_adjustment = SkSize::Make( + op->scale_adjustment.width() * decoded_image.scale_adjustment().width(), + op->scale_adjustment.height() * + decoded_image.scale_adjustment().height()); SkRect adjusted_src = op->src.makeOffset(decoded_image.src_rect_offset().width(), decoded_image.src_rect_offset().height()); - if (!decoded_image.is_scale_adjustment_identity()) { - float x_scale = decoded_image.scale_adjustment().width(); - float y_scale = decoded_image.scale_adjustment().height(); - adjusted_src = SkRect::MakeXYWH( - adjusted_src.x() * x_scale, adjusted_src.y() * y_scale, - adjusted_src.width() * x_scale, adjusted_src.height() * y_scale); - } - - paint.setFilterQuality(decoded_image.filter_quality()); - canvas->drawImageRect(decoded_image.image().get(), adjusted_src, op->dst, - &paint, skconstraint); + adjusted_src = AdjustSrcRectForScale(adjusted_src, scale_adjustment); + paint.setFilterQuality(decoded_image.filter_quality()); + canvas->drawImageRect(decoded_image.image().get(), adjusted_src, op->dst, + &paint, skconstraint); } void DrawIRectOp::RasterWithFlags(const DrawIRectOp* op, @@ -1522,6 +1568,9 @@ bool DrawImageOp::AreEqual(const PaintOp* base_left, return false; if (!AreEqualEvenIfNaN(left->top, right->top)) return false; + + // scale_adjustment intentionally omitted because it is added during + // serialization based on raster scale. return true; } @@ -1538,6 +1587,9 @@ bool DrawImageRectOp::AreEqual(const PaintOp* base_left, return false; if (!AreSkRectsEqual(left->dst, right->dst)) return false; + + // scale_adjustment intentionally omitted because it is added during + // serialization based on raster scale. return true; } @@ -2278,10 +2330,9 @@ void PaintOpBuffer::Playback(SkCanvas* canvas, if (op->IsPaintOpWithFlags()) { const auto* flags_op = static_cast<const PaintOpWithFlags*>(op); - const bool create_skia_shaders = true; const ScopedRasterFlags scoped_flags( &flags_op->flags, new_params.image_provider, canvas->getTotalMatrix(), - iter.alpha(), create_skia_shaders); + iter.alpha()); if (const auto* raster_flags = scoped_flags.flags()) flags_op->RasterWithFlags(canvas, raster_flags, new_params); } else { diff --git a/chromium/cc/paint/paint_op_buffer.h b/chromium/cc/paint/paint_op_buffer.h index 2228e487e9a..f803f0f27bb 100644 --- a/chromium/cc/paint/paint_op_buffer.h +++ b/chromium/cc/paint/paint_op_buffer.h @@ -28,6 +28,11 @@ #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/core/SkTextBlob.h" +#include "ui/gfx/color_space.h" + +class SkColorSpace; +class SkStrikeClient; +class SkStrikeServer; // PaintOpBuffer is a reimplementation of SkLiteDL. // See: third_party/skia/src/core/SkLiteDL.h. @@ -105,8 +110,11 @@ struct CC_PAINT_EXPORT PlaybackParams { DidDrawOpCallback did_draw_op_callback = DidDrawOpCallback()); ~PlaybackParams(); + PlaybackParams(const PlaybackParams& other); + PlaybackParams& operator=(const PlaybackParams& other); + ImageProvider* image_provider; - const SkMatrix original_ctm; + SkMatrix original_ctm; CustomDataRasterCallback custom_callback; DidDrawOpCallback did_draw_op_callback; }; @@ -132,26 +140,35 @@ class CC_PAINT_EXPORT PaintOp { bool operator!=(const PaintOp& other) const { return !(*this == other); } struct CC_PAINT_EXPORT SerializeOptions { - SerializeOptions(); SerializeOptions(ImageProvider* image_provider, TransferCacheSerializeHelper* transfer_cache, SkCanvas* canvas, + SkStrikeServer* strike_server, + SkColorSpace* color_space, + bool can_use_lcd_text, const SkMatrix& original_ctm); // Required. + ImageProvider* image_provider = nullptr; TransferCacheSerializeHelper* transfer_cache = nullptr; SkCanvas* canvas = nullptr; + SkStrikeServer* strike_server = nullptr; + SkColorSpace* color_space = nullptr; + bool can_use_lcd_text = false; // Optional. - ImageProvider* image_provider = nullptr; SkMatrix original_ctm = SkMatrix::I(); // The flags to use when serializing this op. This can be used to override // the flags serialized with the op. Valid only for PaintOpWithFlags. const PaintFlags* flags_to_serialize = nullptr; }; - struct DeserializeOptions { + struct CC_PAINT_EXPORT DeserializeOptions { + DeserializeOptions(TransferCacheDeserializeHelper* transfer_cache, + SkStrikeClient* strike_client); TransferCacheDeserializeHelper* transfer_cache = nullptr; + uint32_t raster_color_space_id = gfx::ColorSpace::kInvalidId; + SkStrikeClient* strike_client = nullptr; }; // Indicates how PaintImages are serialized. @@ -457,7 +474,10 @@ class CC_PAINT_EXPORT DrawImageOp final : public PaintOpWithFlags { const PaintFlags* flags, SkCanvas* canvas, const PlaybackParams& params); - bool IsValid() const { return flags.IsValid(); } + bool IsValid() const { + return flags.IsValid() && SkScalarIsFinite(scale_adjustment.width()) && + SkScalarIsFinite(scale_adjustment.height()); + } static bool AreEqual(const PaintOp* left, const PaintOp* right); bool HasDiscardableImages() const; bool HasNonAAPaint() const { return false; } @@ -469,6 +489,10 @@ class CC_PAINT_EXPORT DrawImageOp final : public PaintOpWithFlags { private: DrawImageOp(); + + // Scale that has already been applied to the decoded image during + // serialization. Used with OOP raster. + SkSize scale_adjustment = SkSize::Make(1.f, 1.f); }; class CC_PAINT_EXPORT DrawImageRectOp final : public PaintOpWithFlags { @@ -486,7 +510,9 @@ class CC_PAINT_EXPORT DrawImageRectOp final : public PaintOpWithFlags { SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { - return flags.IsValid() && src.isFinite() && dst.isFinite(); + return flags.IsValid() && src.isFinite() && dst.isFinite() && + SkScalarIsFinite(scale_adjustment.width()) && + SkScalarIsFinite(scale_adjustment.height()); } static bool AreEqual(const PaintOp* left, const PaintOp* right); bool HasDiscardableImages() const; @@ -499,6 +525,10 @@ class CC_PAINT_EXPORT DrawImageRectOp final : public PaintOpWithFlags { private: DrawImageRectOp(); + + // Scale that has already been applied to the decoded image during + // serialization. Used with OOP raster. + SkSize scale_adjustment = SkSize::Make(1.f, 1.f); }; class CC_PAINT_EXPORT DrawIRectOp final : public PaintOpWithFlags { diff --git a/chromium/cc/paint/paint_op_buffer_eq_fuzzer.cc b/chromium/cc/paint/paint_op_buffer_eq_fuzzer.cc index d773388df43..553136dd883 100644 --- a/chromium/cc/paint/paint_op_buffer_eq_fuzzer.cc +++ b/chromium/cc/paint/paint_op_buffer_eq_fuzzer.cc @@ -7,7 +7,7 @@ #include "cc/paint/paint_op_buffer.h" #include "cc/test/paint_op_helper.h" -#include "cc/test/transfer_cache_test_helper.h" +#include "cc/test/test_options_provider.h" #include "third_party/skia/include/utils/SkNoDrawCanvas.h" // paint_op_buffer_eq_fuzzer deserializes and reserializes paint ops to @@ -36,14 +36,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { const size_t kMaxSerializedSize = 1000000; - // TODO(enne): add an image provider here once deserializing supports that. SkNoDrawCanvas canvas(100, 100); - cc::TransferCacheTestHelper transfer_cache_helper; - cc::PaintOp::SerializeOptions serialize_options; - serialize_options.transfer_cache = &transfer_cache_helper; - serialize_options.canvas = &canvas; - cc::PaintOp::DeserializeOptions deserialize_options; - deserialize_options.transfer_cache = &transfer_cache_helper; + cc::TestOptionsProvider test_options_provider; // Need 4 bytes to be able to read the type/skip. if (size < 4) @@ -63,7 +57,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { size_t bytes_read1 = 0; cc::PaintOp* deserialized_op1 = cc::PaintOp::Deserialize( data, size, deserialized1.get(), sizeof(cc::LargestPaintOp), &bytes_read1, - deserialize_options); + test_options_provider.deserialize_options()); // Failed to deserialize, so abort. if (!deserialized_op1) @@ -94,8 +88,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { static_cast<char*>(base::AlignedAlloc(serialized_size, cc::PaintOpBuffer::PaintOpAlign))); memset(serialized2.get(), 0, serialized_size); - size_t written_bytes2 = deserialized_op1->Serialize( - serialized2.get(), serialized_size, serialize_options); + size_t written_bytes2 = + deserialized_op1->Serialize(serialized2.get(), serialized_size, + test_options_provider.serialize_options()); CHECK_LE(written_bytes2, serialized_size); std::unique_ptr<char, base::AlignedFreeDeleter> deserialized2( @@ -104,7 +99,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { size_t bytes_read2 = 0; cc::PaintOp* deserialized_op2 = cc::PaintOp::Deserialize( data, size, deserialized2.get(), sizeof(cc::LargestPaintOp), &bytes_read2, - deserialize_options); + test_options_provider.deserialize_options()); CHECK(deserialized_op2); CHECK_EQ(bytes_read1, bytes_read2); @@ -112,8 +107,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { static_cast<char*>( base::AlignedAlloc(written_bytes2, cc::PaintOpBuffer::PaintOpAlign))); memset(serialized3.get(), 0, written_bytes2); - size_t written_bytes3 = deserialized_op2->Serialize( - serialized3.get(), written_bytes2, serialize_options); + size_t written_bytes3 = + deserialized_op2->Serialize(serialized3.get(), written_bytes2, + test_options_provider.serialize_options()); CHECK_EQ(written_bytes2, written_bytes3); CHECK(*deserialized_op1 == *deserialized_op2) diff --git a/chromium/cc/paint/paint_op_buffer_fuzzer.cc b/chromium/cc/paint/paint_op_buffer_fuzzer.cc index ec34033f9e9..dfbbf34c49e 100644 --- a/chromium/cc/paint/paint_op_buffer_fuzzer.cc +++ b/chromium/cc/paint/paint_op_buffer_fuzzer.cc @@ -5,18 +5,77 @@ #include <stddef.h> #include <stdint.h> +#include "base/command_line.h" #include "cc/paint/paint_op_buffer.h" #include "cc/test/transfer_cache_test_helper.h" #include "components/viz/test/test_context_provider.h" +#include "gpu/command_buffer/common/buffer.h" +#include "gpu/command_buffer/service/service_font_manager.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrContext.h" +struct Environment { + Environment() { + // Disable noisy logging as per "libFuzzer in Chrome" documentation: + // testing/libfuzzer/getting_started.md#Disable-noisy-error-message-logging. + logging::SetMinLogLevel(logging::LOG_FATAL); + } +}; + +class FontSupport : public gpu::ServiceFontManager::Client { + public: + FontSupport() = default; + ~FontSupport() override = default; + + // gpu::ServiceFontManager::Client implementation. + scoped_refptr<gpu::Buffer> GetShmBuffer(uint32_t shm_id) override { + auto it = buffers_.find(shm_id); + if (it != buffers_.end()) + return it->second; + return CreateBuffer(shm_id); + } + + private: + scoped_refptr<gpu::Buffer> CreateBuffer(uint32_t shm_id) { + std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + static const size_t kBufferSize = 2048u; + shared_memory->CreateAndMapAnonymous(kBufferSize); + auto buffer = + gpu::MakeBufferFromSharedMemory(std::move(shared_memory), kBufferSize); + buffers_[shm_id] = buffer; + return buffer; + } + + base::flat_map<uint32_t, scoped_refptr<gpu::Buffer>> buffers_; +}; + // Deserialize an arbitrary number of cc::PaintOps and raster them // using gpu raster into an SkCanvas. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size <= sizeof(size_t)) + return 0; + + static Environment* env = new Environment(); + ALLOW_UNUSED_LOCAL(env); + base::CommandLine::Init(0, nullptr); const size_t kMaxSerializedSize = 1000000; const size_t kRasterDimension = 32; + // Partition the data to use some bytes for populating the font cache. + size_t bytes_for_fonts = data[0]; + if (bytes_for_fonts > size) + bytes_for_fonts = size / 2; + + FontSupport font_support; + gpu::ServiceFontManager font_manager(&font_support); + std::vector<SkDiscardableHandleId> locked_handles; + if (bytes_for_fonts > 0u) { + font_manager.Deserialize(reinterpret_cast<const char*>(data), + bytes_for_fonts, &locked_handles); + data += bytes_for_fonts; + size -= bytes_for_fonts; + } + SkImageInfo image_info = SkImageInfo::MakeN32( kRasterDimension, kRasterDimension, kOpaque_SkAlphaType); scoped_refptr<viz::TestContextProvider> context_provider = @@ -28,8 +87,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { cc::PlaybackParams params(nullptr, canvas->getTotalMatrix()); cc::TransferCacheTestHelper transfer_cache_helper; - cc::PaintOp::DeserializeOptions deserialize_options; - deserialize_options.transfer_cache = &transfer_cache_helper; + cc::PaintOp::DeserializeOptions deserialize_options( + &transfer_cache_helper, font_manager.strike_client()); // Need 4 bytes to be able to read the type/skip. while (size >= 4) { @@ -58,5 +117,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { size -= bytes_read; data += bytes_read; } + + font_manager.Unlock(locked_handles); return 0; } diff --git a/chromium/cc/paint/paint_op_buffer_serializer.cc b/chromium/cc/paint/paint_op_buffer_serializer.cc index 4dc024e0fb3..869d7c5403b 100644 --- a/chromium/cc/paint/paint_op_buffer_serializer.cc +++ b/chromium/cc/paint/paint_op_buffer_serializer.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "cc/paint/scoped_raster_flags.h" +#include "third_party/skia/include/core/SkColorSpaceXformCanvas.h" #include "ui/gfx/skia_util.h" namespace cc { @@ -24,17 +25,52 @@ class ScopedFlagsOverride { PaintOp::SerializeOptions* options_; }; +// Copied from LayerTreeResourceProvider. +SkSurfaceProps ComputeSurfaceProps(bool can_use_lcd_text) { + uint32_t flags = 0; + // Use unknown pixel geometry to disable LCD text. + SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry); + if (can_use_lcd_text) { + // LegacyFontHost will get LCD text and skia figures out what type to use. + surface_props = + SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType); + } + return surface_props; +} + +PlaybackParams MakeParams(const SkCanvas* canvas) { + // We don't use an ImageProvider here since the ops are played onto a no-draw + // canvas for state tracking and don't need decoded images. + return PlaybackParams(nullptr, canvas->getTotalMatrix()); +} + +// Use half of the max int as the extent for the SkNoDrawCanvas. The correct +// clip is applied to the canvas during serialization. +const int kMaxExtent = std::numeric_limits<int>::max() >> 1; + } // namespace PaintOpBufferSerializer::PaintOpBufferSerializer( SerializeCallback serialize_cb, ImageProvider* image_provider, - TransferCacheSerializeHelper* transfer_cache) + TransferCacheSerializeHelper* transfer_cache, + SkStrikeServer* strike_server, + SkColorSpace* color_space, + bool can_use_lcd_text) : serialize_cb_(std::move(serialize_cb)), - canvas_(100, 100), image_provider_(image_provider), - transfer_cache_(transfer_cache) { + transfer_cache_(transfer_cache), + strike_server_(strike_server), + color_space_(color_space), + can_use_lcd_text_(can_use_lcd_text), + text_blob_canvas_(kMaxExtent, + kMaxExtent, + SkMatrix::I(), + ComputeSurfaceProps(can_use_lcd_text), + strike_server) { DCHECK(serialize_cb_); + canvas_ = SkCreateColorSpaceXformCanvas(&text_blob_canvas_, + sk_ref_sp<SkColorSpace>(color_space)); } PaintOpBufferSerializer::~PaintOpBufferSerializer() = default; @@ -42,19 +78,18 @@ PaintOpBufferSerializer::~PaintOpBufferSerializer() = default; void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer, const std::vector<size_t>* offsets, const Preamble& preamble) { - canvas_.resetCanvas(preamble.full_raster_rect.width(), - preamble.full_raster_rect.height()); - DCHECK(canvas_.getTotalMatrix().isIdentity()); + DCHECK(canvas_->getTotalMatrix().isIdentity()); static const int kInitialSaveCount = 1; - DCHECK_EQ(kInitialSaveCount, canvas_.getSaveCount()); + DCHECK_EQ(kInitialSaveCount, canvas_->getSaveCount()); // These SerializeOptions and PlaybackParams use the initial (identity) canvas // matrix, as they are only used for serializing the preamble and the initial // save / final restore. SerializeBuffer will create its own SerializeOptions // and PlaybackParams based on the post-preamble canvas. - PaintOp::SerializeOptions options(image_provider_, transfer_cache_, &canvas_, - canvas_.getTotalMatrix()); - PlaybackParams params(image_provider_, canvas_.getTotalMatrix()); + PaintOp::SerializeOptions options( + image_provider_, transfer_cache_, canvas_.get(), strike_server_, + color_space_, can_use_lcd_text_, canvas_->getTotalMatrix()); + PlaybackParams params = MakeParams(canvas_.get()); Save(options, params); SerializePreamble(preamble, options, params); @@ -63,27 +98,22 @@ void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer, } void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer) { - // Use half of the max int as the extent for the SkNoDrawCanvas. - static const int extent = std::numeric_limits<int>::max() >> 1; - // Reset the canvas to the maximum extents of our playback rect, ensuring this - // rect will not reject images. - canvas_.resetCanvas(extent, extent); - DCHECK(canvas_.getTotalMatrix().isIdentity()); + DCHECK(canvas_->getTotalMatrix().isIdentity()); SerializeBuffer(buffer, nullptr); } -void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer, - const gfx::Rect& playback_rect, - const gfx::SizeF& post_scale) { - // Reset the canvas to the maximum extents of our playback rect, ensuring this - // rect will not reject images. - canvas_.resetCanvas(playback_rect.width(), playback_rect.height()); - DCHECK(canvas_.getTotalMatrix().isIdentity()); +void PaintOpBufferSerializer::Serialize( + const PaintOpBuffer* buffer, + const gfx::Rect& playback_rect, + const gfx::SizeF& post_scale, + const SkMatrix& post_matrix_for_analysis) { + DCHECK(canvas_->getTotalMatrix().isIdentity()); - PaintOp::SerializeOptions options(image_provider_, transfer_cache_, &canvas_, - canvas_.getTotalMatrix()); - PlaybackParams params(image_provider_, canvas_.getTotalMatrix()); + PaintOp::SerializeOptions options( + image_provider_, transfer_cache_, canvas_.get(), strike_server_, + color_space_, can_use_lcd_text_, canvas_->getTotalMatrix()); + PlaybackParams params = MakeParams(canvas_.get()); // TODO(khushalsagar): remove this clip rect if it's not needed. if (!playback_rect.IsEmpty()) { @@ -97,6 +127,7 @@ void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer, SerializeOp(&scale_op, options, params); } + canvas_->concat(post_matrix_for_analysis); SerializeBuffer(buffer, nullptr); } @@ -199,9 +230,10 @@ void PaintOpBufferSerializer::SerializeBuffer( const PaintOpBuffer* buffer, const std::vector<size_t>* offsets) { DCHECK(buffer); - PaintOp::SerializeOptions options(image_provider_, transfer_cache_, &canvas_, - canvas_.getTotalMatrix()); - PlaybackParams params(image_provider_, canvas_.getTotalMatrix()); + PaintOp::SerializeOptions options( + image_provider_, transfer_cache_, canvas_.get(), strike_server_, + color_space_, can_use_lcd_text_, canvas_->getTotalMatrix()); + PlaybackParams params = MakeParams(canvas_.get()); for (PaintOpBuffer::PlaybackFoldingIterator iter(buffer, offsets); iter; ++iter) { @@ -210,7 +242,7 @@ void PaintOpBufferSerializer::SerializeBuffer( // Skip ops outside the current clip if they have images. This saves // performing an unnecessary expensive decode. const bool skip_op = PaintOp::OpHasDiscardableImages(op) && - PaintOp::QuickRejectDraw(op, &canvas_); + PaintOp::QuickRejectDraw(op, canvas_.get()); if (skip_op) continue; @@ -228,7 +260,7 @@ void PaintOpBufferSerializer::SerializeBuffer( continue; } - int save_count = canvas_.getSaveCount(); + int save_count = canvas_->getSaveCount(); Save(options, params); SerializeBuffer(static_cast<const DrawRecordOp*>(op)->record.get(), nullptr); @@ -241,13 +273,10 @@ bool PaintOpBufferSerializer::SerializeOpWithFlags( PaintOp::SerializeOptions* options, const PlaybackParams& params, uint8_t alpha) { - // We don't need the skia backing for decoded shaders during serialization, - // since those are created on the service side where the record is rasterized. - const bool create_skia_shaders = false; - + // We use a null |image_provider| here because images are decoded during + // serialization. const ScopedRasterFlags scoped_flags( - &flags_op->flags, options->image_provider, - options->canvas->getTotalMatrix(), alpha, create_skia_shaders); + &flags_op->flags, nullptr, options->canvas->getTotalMatrix(), alpha); const PaintFlags* flags_to_serialize = scoped_flags.flags(); if (!flags_to_serialize) return true; @@ -272,11 +301,11 @@ bool PaintOpBufferSerializer::SerializeOp( DCHECK_GE(bytes, 4u); DCHECK_EQ(bytes % PaintOpBuffer::PaintOpAlign, 0u); - // Only pass state-changing operations to the canvas. - if (!op->IsDrawOp()) { - // Note that we don't need to use overridden flags during raster here since - // the override must not affect any state being tracked by this canvas. - op->Raster(&canvas_, params); + if (op->IsPaintOpWithFlags() && options.flags_to_serialize) { + static_cast<const PaintOpWithFlags*>(op)->RasterWithFlags( + canvas_.get(), options.flags_to_serialize, params); + } else { + op->Raster(canvas_.get(), params); } return true; } @@ -292,7 +321,7 @@ void PaintOpBufferSerializer::RestoreToCount( const PaintOp::SerializeOptions& options, const PlaybackParams& params) { RestoreOp restore_op; - while (canvas_.getSaveCount() > count) { + while (canvas_->getSaveCount() > count) { if (!SerializeOp(&restore_op, options, params)) return; } @@ -302,12 +331,18 @@ SimpleBufferSerializer::SimpleBufferSerializer( void* memory, size_t size, ImageProvider* image_provider, - TransferCacheSerializeHelper* transfer_cache) + TransferCacheSerializeHelper* transfer_cache, + SkStrikeServer* strike_server, + SkColorSpace* color_space, + bool can_use_lcd_text) : PaintOpBufferSerializer( base::Bind(&SimpleBufferSerializer::SerializeToMemory, base::Unretained(this)), image_provider, - transfer_cache), + transfer_cache, + strike_server, + color_space, + can_use_lcd_text), memory_(memory), total_(size) {} diff --git a/chromium/cc/paint/paint_op_buffer_serializer.h b/chromium/cc/paint/paint_op_buffer_serializer.h index af793efde7c..9f4f21cfa2d 100644 --- a/chromium/cc/paint/paint_op_buffer_serializer.h +++ b/chromium/cc/paint/paint_op_buffer_serializer.h @@ -7,7 +7,7 @@ #include "cc/paint/paint_op_buffer.h" -#include "third_party/skia/include/utils/SkNoDrawCanvas.h" +#include "third_party/skia/src/core/SkRemoteGlyphCache.h" #include "ui/gfx/geometry/rect_f.h" namespace cc { @@ -20,7 +20,10 @@ class CC_PAINT_EXPORT PaintOpBufferSerializer { PaintOpBufferSerializer(SerializeCallback serialize_cb, ImageProvider* image_provider, - TransferCacheSerializeHelper* transfer_cache); + TransferCacheSerializeHelper* transfer_cache, + SkStrikeServer* strike_server, + SkColorSpace* color_space, + bool can_use_lcd_text); virtual ~PaintOpBufferSerializer(); struct Preamble { @@ -59,9 +62,14 @@ class CC_PAINT_EXPORT PaintOpBufferSerializer { // generally be used for internal PaintOpBuffers in PaintShaders that have // a scale and a tiling, but don't want the clearing or other complicated // logic of the top level Serialize. + // post_matrix_for_analysis adds a scale that is not added to the serialized + // buffer, but used in analysis. This is required for cases that don't modify + // the record during serialization, but need to send resources based on the + // raster scale (mainly PaintRecord backed PaintFilters). void Serialize(const PaintOpBuffer* buffer, const gfx::Rect& playback_rect, - const gfx::SizeF& post_scale); + const gfx::SizeF& post_scale, + const SkMatrix& post_matrix_for_analysis); bool valid() const { return valid_; } @@ -85,9 +93,14 @@ class CC_PAINT_EXPORT PaintOpBufferSerializer { const PlaybackParams& params); SerializeCallback serialize_cb_; - SkNoDrawCanvas canvas_; ImageProvider* image_provider_; TransferCacheSerializeHelper* transfer_cache_; + SkStrikeServer* strike_server_; + SkColorSpace* color_space_; + bool can_use_lcd_text_; + + SkTextBlobCacheDiffCanvas text_blob_canvas_; + std::unique_ptr<SkCanvas> canvas_; bool valid_ = true; }; @@ -97,7 +110,10 @@ class CC_PAINT_EXPORT SimpleBufferSerializer : public PaintOpBufferSerializer { SimpleBufferSerializer(void* memory, size_t size, ImageProvider* image_provider, - TransferCacheSerializeHelper* transfer_cache); + TransferCacheSerializeHelper* transfer_cache, + SkStrikeServer* strike_server, + SkColorSpace* color_space, + bool can_use_lcd_text); ~SimpleBufferSerializer() override; size_t written() const { return written_; } diff --git a/chromium/cc/paint/paint_op_buffer_unittest.cc b/chromium/cc/paint/paint_op_buffer_unittest.cc index 7ab3a8c6ad7..b7b1d1e37fb 100644 --- a/chromium/cc/paint/paint_op_buffer_unittest.cc +++ b/chromium/cc/paint/paint_op_buffer_unittest.cc @@ -12,9 +12,11 @@ #include "cc/paint/paint_op_buffer_serializer.h" #include "cc/paint/paint_op_reader.h" #include "cc/paint/paint_op_writer.h" +#include "cc/paint/shader_transfer_cache_entry.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/paint_op_helper.h" #include "cc/test/skia_common.h" +#include "cc/test/test_options_provider.h" #include "cc/test/test_skcanvas.h" #include "cc/test/transfer_cache_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" @@ -23,6 +25,7 @@ #include "third_party/skia/include/effects/SkDashPathEffect.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" #include "third_party/skia/include/effects/SkOffsetImageFilter.h" +#include "third_party/skia/src/core/SkRemoteGlyphCache.h" using testing::_; using testing::Property; @@ -73,71 +76,6 @@ class PaintOpSerializationTestUtils { } }; -class TestOptionsProvider : public ImageProvider, - public TransferCacheTestHelper { - public: - TestOptionsProvider() { - serialize_options_.canvas = &canvas_; - serialize_options_.image_provider = this; - serialize_options_.transfer_cache = this; - deserialize_options_.transfer_cache = this; - } - ~TestOptionsProvider() override = default; - - const PaintOp::SerializeOptions& serialize_options() const { - return serialize_options_; - } - PaintOp::SerializeOptions& mutable_serialize_options() { - return serialize_options_; - } - const PaintOp::DeserializeOptions deserialize_options() const { - return deserialize_options_; - } - PaintOp::DeserializeOptions mutable_deserialize_options() { - return deserialize_options_; - } - ImageProvider* image_provider() { return this; } - TransferCacheTestHelper* transfer_cache_helper() { return this; } - - const std::vector<DrawImage>& decoded_images() const { - return decoded_images_; - } - - private: - ScopedDecodedDrawImage GetDecodedDrawImage( - const DrawImage& draw_image) override { - decoded_images_.push_back(draw_image); - auto& entry = entry_map_[++transfer_cache_entry_id_]; - SkBitmap bitmap; - const auto& paint_image = draw_image.paint_image(); - bitmap.allocPixelsFlags( - SkImageInfo::MakeN32Premul(paint_image.width(), paint_image.height()), - SkBitmap::kZeroPixels_AllocFlag); - sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); - entry.set_image_for_testing(image); - return ScopedDecodedDrawImage(DecodedDrawImage( - transfer_cache_entry_id_, SkSize::MakeEmpty(), SkSize::Make(1u, 1u), - draw_image.filter_quality(), true)); - } - - ServiceTransferCacheEntry* GetEntryInternal(TransferCacheEntryType entry_type, - uint32_t entry_id) override { - if (entry_type != TransferCacheEntryType::kImage) - return TransferCacheTestHelper::GetEntryInternal(entry_type, entry_id); - auto it = entry_map_.find(entry_id); - CHECK(it != entry_map_.end()); - return &it->second; - } - - uint32_t transfer_cache_entry_id_ = 0u; - base::flat_map<uint32_t, ServiceImageTransferCacheEntry> entry_map_; - - testing::StrictMock<MockCanvas> canvas_; - PaintOp::SerializeOptions serialize_options_; - PaintOp::DeserializeOptions deserialize_options_; - std::vector<DrawImage> decoded_images_; -}; - TEST(PaintOpBufferTest, Empty) { PaintOpBuffer buffer; EXPECT_EQ(buffer.size(), 0u); @@ -1196,12 +1134,9 @@ std::vector<PaintFlags> test_flags = { }; std::vector<SkColor> test_colors = { - SkColorSetARGBInline(0, 0, 0, 0), - SkColorSetARGBInline(255, 255, 255, 255), - SkColorSetARGBInline(0, 255, 10, 255), - SkColorSetARGBInline(255, 0, 20, 255), - SkColorSetARGBInline(30, 255, 0, 255), - SkColorSetARGBInline(255, 40, 0, 0), + SkColorSetARGB(0, 0, 0, 0), SkColorSetARGB(255, 255, 255, 255), + SkColorSetARGB(0, 255, 10, 255), SkColorSetARGB(255, 0, 20, 255), + SkColorSetARGB(30, 255, 0, 255), SkColorSetARGB(255, 40, 0, 0), }; std::vector<std::string> test_strings = { @@ -1334,12 +1269,12 @@ class DeserializerIterator { public: DeserializerIterator(const void* input, size_t input_size, - TransferCacheDeserializeHelper* transfer_cache) + const PaintOp::DeserializeOptions& options) : DeserializerIterator(input, static_cast<const char*>(input), input_size, input_size, - transfer_cache) {} + options) {} DeserializerIterator(DeserializerIterator&&) = default; DeserializerIterator& operator=(DeserializerIterator&&) = default; @@ -1348,13 +1283,12 @@ class DeserializerIterator { DeserializerIterator begin() { return DeserializerIterator(input_, static_cast<const char*>(input_), - input_size_, input_size_, - options_.transfer_cache); + input_size_, input_size_, options_); } DeserializerIterator end() { return DeserializerIterator(input_, static_cast<const char*>(input_) + input_size_, - input_size_, 0, options_.transfer_cache); + input_size_, 0, options_); } bool operator!=(const DeserializerIterator& other) { return input_ != other.input_ || current_ != other.current_ || @@ -1382,12 +1316,12 @@ class DeserializerIterator { const char* current, size_t input_size, size_t remaining, - TransferCacheDeserializeHelper* transfer_cache) + const PaintOp::DeserializeOptions& options) : input_(input), current_(current), input_size_(input_size), - remaining_(remaining) { - options_.transfer_cache = transfer_cache; + remaining_(remaining), + options_(options) { data_.reset(static_cast<char*>(base::AlignedAlloc( sizeof(LargestPaintOp), PaintOpBuffer::PaintOpAlign))); DeserializeCurrentOp(); @@ -1784,9 +1718,12 @@ TEST_P(PaintOpSerializationTest, SmokeTest) { PaintOpBuffer::Iterator iter(&buffer_); size_t i = 0; - for (auto* base_written : DeserializerIterator( - output_.get(), serializer.TotalBytesWritten(), - serializer.options_provider()->transfer_cache_helper())) { + PaintOp::DeserializeOptions deserialize_options( + serializer.options_provider()->transfer_cache_helper(), + serializer.options_provider()->strike_client()); + for (auto* base_written : + DeserializerIterator(output_.get(), serializer.TotalBytesWritten(), + deserialize_options)) { SCOPED_TRACE(base::StringPrintf( "%s #%zu", PaintOpTypeToString(GetParamType()).c_str(), i)); ASSERT_EQ(!*iter, !base_written); @@ -1991,10 +1928,12 @@ TEST(PaintOpSerializationTest, CompleteBufferSerialization) { static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, PaintOpBuffer::PaintOpAlign))); TestOptionsProvider options_provider; - SimpleBufferSerializer serializer(memory.get(), - PaintOpBuffer::kInitialBufferSize, - options_provider.image_provider(), - options_provider.transfer_cache_helper()); + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), + options_provider.transfer_cache_helper(), + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); serializer.Serialize(&buffer, nullptr, preamble); ASSERT_NE(serializer.written(), 0u); @@ -2066,10 +2005,12 @@ TEST(PaintOpSerializationTest, Preamble) { static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, PaintOpBuffer::PaintOpAlign))); TestOptionsProvider options_provider; - SimpleBufferSerializer serializer(memory.get(), - PaintOpBuffer::kInitialBufferSize, - options_provider.image_provider(), - options_provider.transfer_cache_helper()); + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), + options_provider.transfer_cache_helper(), + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); serializer.Serialize(&buffer, nullptr, preamble); ASSERT_NE(serializer.written(), 0u); @@ -2164,10 +2105,12 @@ TEST(PaintOpSerializationTest, SerializesNestedRecords) { static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, PaintOpBuffer::PaintOpAlign))); TestOptionsProvider options_provider; - SimpleBufferSerializer serializer(memory.get(), - PaintOpBuffer::kInitialBufferSize, - options_provider.image_provider(), - options_provider.transfer_cache_helper()); + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), + options_provider.transfer_cache_helper(), + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); PaintOpBufferSerializer::Preamble preamble; serializer.Serialize(&buffer, nullptr, preamble); ASSERT_NE(serializer.written(), 0u); @@ -2236,10 +2179,12 @@ TEST(PaintOpBufferTest, ClipsImagesDuringSerialization) { static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, PaintOpBuffer::PaintOpAlign))); TestOptionsProvider options_provider; - SimpleBufferSerializer serializer(memory.get(), - PaintOpBuffer::kInitialBufferSize, - options_provider.image_provider(), - options_provider.transfer_cache_helper()); + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), + options_provider.transfer_cache_helper(), + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); PaintOpBufferSerializer::Preamble preamble; preamble.playback_rect = test_case.clip_rect; preamble.full_raster_rect = gfx::Rect(0, 0, test_case.clip_rect.right(), @@ -2297,10 +2242,12 @@ TEST(PaintOpBufferSerializationTest, AlphaFoldingDuringSerialization) { static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, PaintOpBuffer::PaintOpAlign))); TestOptionsProvider options_provider; - SimpleBufferSerializer serializer(memory.get(), - PaintOpBuffer::kInitialBufferSize, - options_provider.image_provider(), - options_provider.transfer_cache_helper()); + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), + options_provider.transfer_cache_helper(), + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); serializer.Serialize(&buffer, nullptr, preamble); ASSERT_NE(serializer.written(), 0u); @@ -2892,6 +2839,68 @@ TEST(PaintOpBufferTest, ReplacesImagesFromProvider) { buffer.Playback(&canvas, PlaybackParams(&image_provider)); } +TEST(PaintOpBufferTest, ReplacesImagesFromProviderOOP) { + PaintOpBuffer buffer; + SkSize expected_scale = SkSize::Make(0.2f, 0.5f); + + SkRect rect = SkRect::MakeWH(10, 10); + PaintFlags flags; + flags.setFilterQuality(kLow_SkFilterQuality); + PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10)); + buffer.push<ScaleOp>(expected_scale.width(), expected_scale.height()); + buffer.push<DrawImageOp>(paint_image, 0.0f, 0.0f, &flags); + buffer.push<DrawImageRectOp>( + paint_image, rect, rect, &flags, + PaintCanvas::SrcRectConstraint::kFast_SrcRectConstraint); + flags.setShader( + PaintShader::MakeImage(paint_image, SkShader::TileMode::kRepeat_TileMode, + SkShader::TileMode::kRepeat_TileMode, nullptr)); + buffer.push<DrawOvalOp>(SkRect::MakeWH(10, 10), flags); + + std::unique_ptr<char, base::AlignedFreeDeleter> memory( + static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, + PaintOpBuffer::PaintOpAlign))); + TestOptionsProvider options_provider; + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), + options_provider.transfer_cache_helper(), + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); + serializer.Serialize(&buffer); + ASSERT_NE(serializer.written(), 0u); + + auto deserialized_buffer = + PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(), + options_provider.deserialize_options()); + ASSERT_TRUE(deserialized_buffer); + + for (auto* op : PaintOpBuffer::Iterator(deserialized_buffer.get())) { + testing::NiceMock<MockCanvas> canvas; + PlaybackParams params(nullptr); + testing::Sequence s; + + if (op->GetType() == PaintOpType::DrawImage) { + // Save/scale/image/restore from DrawImageop. + EXPECT_CALL(canvas, willSave()).InSequence(s); + EXPECT_CALL(canvas, didConcat(MatchesInvScale(expected_scale))); + EXPECT_CALL(canvas, onDrawImage(NonLazyImage(), 0.0f, 0.0f, _)); + EXPECT_CALL(canvas, willRestore()).InSequence(s); + op->Raster(&canvas, params); + } else if (op->GetType() == PaintOpType::DrawImageRect) { + EXPECT_CALL(canvas, onDrawImageRect(NonLazyImage(), + MatchesRect(rect, expected_scale), + SkRect::MakeWH(10, 10), _, + SkCanvas::kFast_SrcRectConstraint)); + op->Raster(&canvas, params); + } else if (op->GetType() == PaintOpType::DrawOval) { + EXPECT_CALL(canvas, onDrawOval(SkRect::MakeWH(10, 10), + MatchesShader(flags, expected_scale))); + op->Raster(&canvas, params); + } + } +} + class PaintFilterSerializationTest : public ::testing::TestWithParam<bool> {}; INSTANTIATE_TEST_CASE_P(PaintFilterSerializationTests, @@ -2966,15 +2975,22 @@ TEST_P(PaintFilterSerializationTest, Basic) { buffer_size += PaintOpWriter::HeaderBytes(); memory.resize(buffer_size); - PaintOpWriter writer(memory.data(), memory.size(), - options_provider.transfer_cache_helper(), - options_provider.image_provider(), GetParam()); + PaintOp::SerializeOptions serialize_options( + options_provider.image_provider(), + options_provider.transfer_cache_helper(), nullptr, + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text(), SkMatrix::I()); + PaintOpWriter writer(memory.data(), memory.size(), serialize_options, + GetParam()); writer.Write(filter.get()); ASSERT_GT(writer.size(), 0u) << PaintFilter::TypeToString(filter->type()); sk_sp<PaintFilter> deserialized_filter; - PaintOpReader reader(memory.data(), writer.size(), - options_provider.transfer_cache_helper(), GetParam()); + PaintOp::DeserializeOptions deserialize_options( + options_provider.transfer_cache_helper(), + options_provider.strike_client()); + PaintOpReader reader(memory.data(), writer.size(), deserialize_options, + GetParam()); reader.Read(&deserialized_filter); ASSERT_TRUE(deserialized_filter); EXPECT_TRUE(*filter == *deserialized_filter); @@ -2996,10 +3012,12 @@ TEST(PaintOpBufferTest, PaintRecordShaderSerialization) { PaintOpBuffer buffer; buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 2, 3, 4), flags); - SimpleBufferSerializer serializer(memory.get(), - PaintOpBuffer::kInitialBufferSize, - options_provider.image_provider(), - options_provider.transfer_cache_helper()); + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), + options_provider.transfer_cache_helper(), + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); serializer.Serialize(&buffer); ASSERT_TRUE(serializer.valid()); ASSERT_GT(serializer.written(), 0u); @@ -3080,12 +3098,21 @@ TEST(PaintOpBufferTest, SecurityConstrainedImageSerialization) { std::unique_ptr<char, base::AlignedFreeDeleter> memory( static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, PaintOpBuffer::PaintOpAlign))); - PaintOpWriter writer(memory.get(), PaintOpBuffer::kInitialBufferSize, nullptr, - nullptr, enable_security_constraints); + TestOptionsProvider options_provider; + PaintOp::SerializeOptions serialize_options( + options_provider.image_provider(), + options_provider.transfer_cache_helper(), nullptr, + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text(), SkMatrix::I()); + PaintOpWriter writer(memory.get(), PaintOpBuffer::kInitialBufferSize, + serialize_options, enable_security_constraints); writer.Write(filter.get()); sk_sp<PaintFilter> out_filter; - PaintOpReader reader(memory.get(), writer.size(), nullptr, + PaintOp::DeserializeOptions deserialize_options( + options_provider.transfer_cache_helper(), + options_provider.strike_client()); + PaintOpReader reader(memory.get(), writer.size(), deserialize_options, enable_security_constraints); reader.Read(&out_filter); EXPECT_TRUE(*filter == *out_filter); @@ -3111,10 +3138,12 @@ TEST(PaintOpBufferTest, RecordShadersSerializeScaledImages) { static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, PaintOpBuffer::PaintOpAlign))); TestOptionsProvider options_provider; - SimpleBufferSerializer serializer(memory.get(), - PaintOpBuffer::kInitialBufferSize, - options_provider.image_provider(), - options_provider.transfer_cache_helper()); + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), + options_provider.transfer_cache_helper(), + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); serializer.Serialize(buffer.get()); ASSERT_EQ(options_provider.decoded_images().size(), 1u); @@ -3123,6 +3152,176 @@ TEST(PaintOpBufferTest, RecordShadersSerializeScaledImages) { EXPECT_EQ(scale.height(), 0.8f); } +TEST(PaintOpBufferTest, RecordShadersCached) { + auto record_buffer = sk_make_sp<PaintOpBuffer>(); + record_buffer->push<DrawImageOp>( + CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f, nullptr); + auto shader = PaintShader::MakePaintRecord( + record_buffer, SkRect::MakeWH(10.f, 10.f), + SkShader::TileMode::kRepeat_TileMode, + SkShader::TileMode::kRepeat_TileMode, nullptr); + shader->set_has_animated_images(false); + auto shader_id = shader->paint_record_shader_id(); + TestOptionsProvider options_provider; + auto* transfer_cache = options_provider.transfer_cache_helper(); + + // Generate serialized |memory|. + std::unique_ptr<char, base::AlignedFreeDeleter> memory( + static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, + PaintOpBuffer::PaintOpAlign))); + size_t memory_written = 0; + { + auto buffer = sk_make_sp<PaintOpBuffer>(); + PaintFlags flags; + flags.setShader(shader); + buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags); + + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), transfer_cache, + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); + serializer.Serialize(buffer.get()); + memory_written = serializer.written(); + } + + // Generate serialized |memory_scaled|, which is the same pob, but with + // a scale factor. + std::unique_ptr<char, base::AlignedFreeDeleter> memory_scaled( + static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, + PaintOpBuffer::PaintOpAlign))); + size_t memory_scaled_written = 0; + { + auto buffer = sk_make_sp<PaintOpBuffer>(); + PaintFlags flags; + flags.setShader(shader); + // This buffer has an additional scale op. + buffer->push<ScaleOp>(2.0f, 3.7f); + buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags); + + SimpleBufferSerializer serializer( + memory_scaled.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), transfer_cache, + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); + serializer.Serialize(buffer.get()); + memory_scaled_written = serializer.written(); + } + + // Hold onto records so PaintShader pointer comparisons are valid. + sk_sp<PaintRecord> records[5]; + const SkShader* last_shader = nullptr; + PaintOp::DeserializeOptions deserialize_options( + transfer_cache, options_provider.strike_client()); + + // Several deserialization test cases: + // (0) deserialize once, verify cached is the same as deserialized version + // (1) deserialize again, verify shader gets reused + // (2) change color space, verify shader is new + // (3) change scale, verify shader is new + // (4) sanity check, same new scale + same new colorspace, shader is reused. + for (size_t i = 0; i < 5; ++i) { + if (i < 2) { + // arbitrary color space ids + deserialize_options.raster_color_space_id = 23; + } else { + deserialize_options.raster_color_space_id = 34; + } + + if (i < 3) { + records[i] = PaintOpBuffer::MakeFromMemory(memory.get(), memory_written, + deserialize_options); + } else { + records[i] = PaintOpBuffer::MakeFromMemory( + memory_scaled.get(), memory_scaled_written, deserialize_options); + } + + auto* entry = + transfer_cache->GetEntryAs<ServiceShaderTransferCacheEntry>(shader_id); + ASSERT_TRUE(entry); + EXPECT_EQ(entry->raster_color_space_id(), + deserialize_options.raster_color_space_id); + if (i < 3) + EXPECT_EQ(records[i]->size(), 1u); + else + EXPECT_EQ(records[i]->size(), 2u); + + for (auto* base_op : PaintOpBuffer::Iterator(records[i].get())) { + if (base_op->GetType() != PaintOpType::DrawRect) + continue; + auto* op = static_cast<const DrawRectOp*>(base_op); + + // In every case, the shader in the op should get cached for future + // use. + auto* op_skshader = op->flags.getShader()->GetSkShader().get(); + EXPECT_EQ(op_skshader, entry->shader()->GetSkShader().get()); + switch (i) { + case 0: + // Nothing to check. + break; + case 1: + EXPECT_EQ(op_skshader, last_shader); + break; + case 2: + EXPECT_NE(op_skshader, last_shader); + break; + case 3: + EXPECT_NE(op_skshader, last_shader); + break; + case 4: + EXPECT_EQ(op_skshader, last_shader); + break; + } + last_shader = op_skshader; + } + } +} + +TEST(PaintOpBufferTest, RecordShadersCachedSize) { + auto record_buffer = sk_make_sp<PaintOpBuffer>(); + size_t estimated_image_size = 30 * 30 * 4; + auto image = CreateBitmapImage(gfx::Size(30, 30)); + record_buffer->push<DrawImageOp>(image, 0.f, 0.f, nullptr); + auto shader = PaintShader::MakePaintRecord( + record_buffer, SkRect::MakeWH(10.f, 10.f), + SkShader::TileMode::kRepeat_TileMode, + SkShader::TileMode::kRepeat_TileMode, nullptr); + shader->set_has_animated_images(false); + auto shader_id = shader->paint_record_shader_id(); + TestOptionsProvider options_provider; + auto* transfer_cache = options_provider.transfer_cache_helper(); + + // Generate serialized |memory|. + std::unique_ptr<char, base::AlignedFreeDeleter> memory( + static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, + PaintOpBuffer::PaintOpAlign))); + auto buffer = sk_make_sp<PaintOpBuffer>(); + PaintFlags flags; + flags.setShader(shader); + buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags); + + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), transfer_cache, + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); + serializer.Serialize(buffer.get()); + + PaintOp::DeserializeOptions deserialize_options( + transfer_cache, options_provider.strike_client()); + auto record = PaintOpBuffer::MakeFromMemory( + memory.get(), serializer.written(), deserialize_options); + auto* shader_entry = + transfer_cache->GetEntryAs<ServiceShaderTransferCacheEntry>(shader_id); + ASSERT_TRUE(shader_entry); + + // The size of the shader in the cache should be bigger than both the record + // and the image. Exact numbers not used here to not overfit this test. + size_t shader_size = shader_entry->CachedSize(); + EXPECT_GT(estimated_image_size, serializer.written()); + EXPECT_GT(shader_size, estimated_image_size); +} + TEST(PaintOpBufferTest, TotalOpCount) { auto record_buffer = sk_make_sp<PaintOpBuffer>(); auto sub_record_buffer = sk_make_sp<PaintOpBuffer>(); diff --git a/chromium/cc/paint/paint_op_perftest.cc b/chromium/cc/paint/paint_op_perftest.cc index ee9f92f5eb7..dfefd8a8afa 100644 --- a/chromium/cc/paint/paint_op_perftest.cc +++ b/chromium/cc/paint/paint_op_perftest.cc @@ -9,7 +9,7 @@ #include "cc/base/lap_timer.h" #include "cc/paint/paint_op_buffer.h" #include "cc/paint/paint_op_buffer_serializer.h" -#include "cc/test/transfer_cache_test_helper.h" +#include "cc/test/test_options_provider.h" #include "testing/perf/perf_test.h" #include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" @@ -40,11 +40,7 @@ class PaintOpPerfTest : public testing::Test { PaintOpBuffer::PaintOpAlign))) {} void RunTest(const std::string& name, const PaintOpBuffer& buffer) { - TransferCacheTestHelper helper; - PaintOp::SerializeOptions serialize_options; - serialize_options.transfer_cache = &helper; - PaintOp::DeserializeOptions deserialize_options; - deserialize_options.transfer_cache = &helper; + TestOptionsProvider test_options_provider; size_t bytes_written = 0u; PaintOpBufferSerializer::Preamble preamble; @@ -53,7 +49,11 @@ class PaintOpPerfTest : public testing::Test { do { SimpleBufferSerializer serializer( serialized_data_.get(), kMaxSerializedBufferBytes, - serialize_options.image_provider, serialize_options.transfer_cache); + test_options_provider.image_provider(), + test_options_provider.transfer_cache_helper(), + test_options_provider.strike_server(), + test_options_provider.color_space(), + test_options_provider.can_use_lcd_text()); serializer.Serialize(&buffer, nullptr, preamble); bytes_written = serializer.written(); timer_.NextLap(); @@ -66,6 +66,7 @@ class PaintOpPerfTest : public testing::Test { size_t bytes_read = 0; timer_.Reset(); + test_options_provider.PushFonts(); do { size_t remaining_read_bytes = bytes_written; @@ -74,7 +75,8 @@ class PaintOpPerfTest : public testing::Test { while (true) { PaintOp* deserialized_op = PaintOp::Deserialize( to_read, remaining_read_bytes, deserialized_data_.get(), - sizeof(LargestPaintOp), &bytes_read, deserialize_options); + sizeof(LargestPaintOp), &bytes_read, + test_options_provider.deserialize_options()); deserialized_op->DestroyThis(); DCHECK_GE(remaining_read_bytes, bytes_read); diff --git a/chromium/cc/paint/paint_op_reader.cc b/chromium/cc/paint/paint_op_reader.cc index 2e7dbe089d9..e9c885c465d 100644 --- a/chromium/cc/paint/paint_op_reader.cc +++ b/chromium/cc/paint/paint_op_reader.cc @@ -14,11 +14,14 @@ #include "cc/paint/paint_op_buffer.h" #include "cc/paint/paint_shader.h" #include "cc/paint/paint_typeface_transfer_cache_entry.h" +#include "cc/paint/path_transfer_cache_entry.h" +#include "cc/paint/shader_transfer_cache_entry.h" #include "cc/paint/transfer_cache_deserialize_helper.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkSerialProcs.h" #include "third_party/skia/include/core/SkTextBlob.h" +#include "third_party/skia/src/core/SkRemoteGlyphCache.h" namespace cc { namespace { @@ -29,33 +32,6 @@ const size_t kMaxMergeFilterCount = 10000; const size_t kMaxKernelSize = 1000; const size_t kMaxRegionByteSize = 10 * 1024; -struct TypefacesCatalog { - TransferCacheDeserializeHelper* transfer_cache; - bool had_null = false; -}; - -sk_sp<SkTypeface> ResolveTypeface(const void* data, size_t length, void* ctx) { - TypefacesCatalog* catalog = static_cast<TypefacesCatalog*>(ctx); - if (length != 4) { - catalog->had_null = true; - return nullptr; - } - - uint32_t id; - memcpy(&id, data, length); - auto* entry = catalog->transfer_cache - ->GetEntryAs<ServicePaintTypefaceTransferCacheEntry>(id); - // TODO(vmpstr): The !entry->typeface() check is here because not all - // typefaces are supported right now. Instead of making the reader invalid - // during the typeface deserialization, which results in an invalid op, - // instead just make the textblob be null by setting |had_null| to true. - if (!entry || !entry->typeface()) { - catalog->had_null = true; - return nullptr; - } - return entry->typeface().ToSkTypeface(); -} - bool IsValidPaintShaderType(PaintShader::Type type) { return static_cast<uint8_t>(type) < static_cast<uint8_t>(PaintShader::Type::kShaderCount); @@ -71,6 +47,24 @@ bool IsValidPaintShaderScalingBehavior(PaintShader::ScalingBehavior behavior) { behavior == PaintShader::ScalingBehavior::kFixedScale; } +struct TypefaceCtx { + explicit TypefaceCtx(SkStrikeClient* client) : client(client) {} + bool invalid_typeface = false; + SkStrikeClient* client = nullptr; +}; + +sk_sp<SkTypeface> DeserializeTypeface(const void* data, + size_t length, + void* ctx) { + auto* typeface_ctx = static_cast<TypefaceCtx*>(ctx); + auto tf = typeface_ctx->client->deserializeTypeface(data, length); + if (tf) + return tf; + + typeface_ctx->invalid_typeface = true; + return nullptr; +} + } // namespace // static @@ -213,21 +207,18 @@ void PaintOpReader::Read(SkRRect* rect) { } void PaintOpReader::Read(SkPath* path) { - AlignMemory(4); + uint32_t transfer_cache_entry_id; + ReadSimple(&transfer_cache_entry_id); if (!valid_) return; - - // This is assumed safe from TOCTOU violations as the SkPath deserializing - // function uses an SkRBuffer which reads each piece of memory once much - // like PaintOpReader does. Additionally, paths are later validated in - // PaintOpBuffer. - size_t read_bytes = - path->readFromMemory(const_cast<const char*>(memory_), remaining_bytes_); - if (!read_bytes) - SetInvalid(); - - memory_ += read_bytes; - remaining_bytes_ -= read_bytes; + auto* entry = + options_.transfer_cache->GetEntryAs<ServicePathTransferCacheEntry>( + transfer_cache_entry_id); + if (entry) { + *path = entry->path(); + } else { + valid_ = false; + } } void PaintOpReader::Read(PaintFlags* flags) { @@ -238,10 +229,9 @@ void PaintOpReader::Read(PaintFlags* flags) { ReadSimple(&flags->blend_mode_); ReadSimple(&flags->bitfields_uint_); - // TODO(enne): ReadTypeface, http://crbug.com/737629 - // Flattenables must be read at 4-byte boundary, which should be the case // here. + AlignMemory(4); ReadFlattenable(&flags->path_effect_); AlignMemory(4); ReadFlattenable(&flags->mask_filter_); @@ -335,8 +325,9 @@ void PaintOpReader::Read(PaintImage* image) { if (transfer_cache_entry_id == kInvalidImageTransferCacheEntryId) return; - if (auto* entry = transfer_cache_->GetEntryAs<ServiceImageTransferCacheEntry>( - transfer_cache_entry_id)) { + if (auto* entry = + options_.transfer_cache->GetEntryAs<ServiceImageTransferCacheEntry>( + transfer_cache_entry_id)) { *image = PaintImageBuilder::WithDefault() .set_id(PaintImage::GetNextId()) .set_image(entry->image(), PaintImage::kNonLazyStableId) @@ -399,22 +390,18 @@ void PaintOpReader::Read(scoped_refptr<PaintTextBlob>* paint_blob) { if (!valid_) return; - TypefacesCatalog catalog; - catalog.transfer_cache = transfer_cache_; - + DCHECK(options_.strike_client); SkDeserialProcs procs; - procs.fTypefaceProc = &ResolveTypeface; - procs.fTypefaceCtx = &catalog; + TypefaceCtx typeface_ctx(options_.strike_client); + procs.fTypefaceProc = &DeserializeTypeface; + procs.fTypefaceCtx = &typeface_ctx; sk_sp<SkTextBlob> blob = SkTextBlob::Deserialize( const_cast<const char*>(memory_), data_bytes, procs); - // TODO(vmpstr): If we couldn't serialize |blob|, we should make |paint_blob| - // nullptr. However, this causes GL errors right now, because not all - // typefaces are serialized. Fix this once we serialize everything. For now - // the behavior is that the |paint_blob| op exists and is valid, but - // internally it has a nullptr SkTextBlob which skia ignores. - // See also: TODO in paint_op_buffer_eq_fuzzer. - if (catalog.had_null) - blob = nullptr; + if (typeface_ctx.invalid_typeface) { + SetInvalid(); + return; + } + *paint_blob = base::MakeRefCounted<PaintTextBlob>( std::move(blob), std::vector<PaintTypeface>()); memory_ += data_bytes; @@ -464,8 +451,18 @@ void PaintOpReader::Read(sk_sp<PaintShader>* shader) { Read(&ref.image_); bool has_record = false; ReadSimple(&has_record); - if (has_record) - Read(&ref.record_); + uint32_t shader_id = PaintShader::kInvalidRecordShaderId; + size_t shader_size = 0; + if (has_record) { + Read(&shader_id); + + // Track dependent transfer cache entries to make cached shader size + // more realistic. + size_t pre_size = options_.transfer_cache->GetTotalEntrySizes(); + size_t record_size = Read(&ref.record_); + size_t post_size = options_.transfer_cache->GetTotalEntrySizes(); + shader_size = post_size - pre_size + record_size; + } decltype(ref.colors_)::size_type colors_size = 0; ReadSimple(&colors_size); @@ -503,9 +500,40 @@ void PaintOpReader::Read(sk_sp<PaintShader>* shader) { SetInvalid(); return; } - // TODO(vmpstr): We should have a PaintShader id and cache these shaders - // instead of creating every time we deserialize. - (*shader)->CreateSkShader(); + + if (shader_id == PaintShader::kInvalidRecordShaderId) { + // Paint record shaders must have ids. + if (shader_type == PaintShader::Type::kPaintRecord) { + SetInvalid(); + return; + } + (*shader)->CreateSkShader(); + return; + } + + // Record shaders have shader ids. Attempt to use cached versions of + // these so that Skia can cache based on SkPictureShader::fUniqueId. + // These shaders are always serialized (and assumed to not be large + // records). Handling this edge case in this roundabout way prevents + // transfer cache entries from needing to depend on other transfer cache + // entries. + auto* entry = + options_.transfer_cache->GetEntryAs<ServiceShaderTransferCacheEntry>( + shader_id); + // Only consider entries that use the same scale and color space. + // This limits the service side transfer cache to only having one entry + // per shader but this will hit the common case of enabling Skia reuse. + if (entry && entry->shader()->tile_ == ref.tile_ && + entry->raster_color_space_id() == options_.raster_color_space_id) { + DCHECK(!ref.cached_shader_); + ref.cached_shader_ = entry->shader()->GetSkShader(); + } else { + ref.CreateSkShader(); + std::unique_ptr<ServiceShaderTransferCacheEntry> entry( + new ServiceShaderTransferCacheEntry( + *shader, options_.raster_color_space_id, shader_size)); + options_.transfer_cache->CreateLocalEntry(shader_id, std::move(entry)); + } } void PaintOpReader::Read(SkMatrix* matrix) { @@ -1164,7 +1192,7 @@ void PaintOpReader::ReadLightingSpotPaintFilter( base::OptionalOrNullptr(crop_rect))); } -void PaintOpReader::Read(sk_sp<PaintRecord>* record) { +size_t PaintOpReader::Read(sk_sp<PaintRecord>* record) { size_t size_bytes = 0; ReadSimple(&size_bytes); AlignMemory(PaintOpBuffer::PaintOpAlign); @@ -1174,27 +1202,25 @@ void PaintOpReader::Read(sk_sp<PaintRecord>* record) { // enabled. if (size_bytes != 0) { SetInvalid(); - return; + return 0; } *record = sk_make_sp<PaintOpBuffer>(); - return; + return 0; } if (size_bytes > remaining_bytes_) SetInvalid(); if (!valid_) - return; + return 0; - PaintOp::DeserializeOptions options; - options.transfer_cache = transfer_cache_; - - *record = PaintOpBuffer::MakeFromMemory(memory_, size_bytes, options); + *record = PaintOpBuffer::MakeFromMemory(memory_, size_bytes, options_); if (!*record) { SetInvalid(); - return; + return 0; } memory_ += size_bytes; remaining_bytes_ -= size_bytes; + return size_bytes; } void PaintOpReader::Read(SkRegion* region) { diff --git a/chromium/cc/paint/paint_op_reader.h b/chromium/cc/paint/paint_op_reader.h index 5fc268af0ec..c8455fe8448 100644 --- a/chromium/cc/paint/paint_op_reader.h +++ b/chromium/cc/paint/paint_op_reader.h @@ -18,17 +18,18 @@ class PaintShader; // PaintOpReader takes garbage |memory| and clobbers it with successive // read functions. -class TransferCacheDeserializeHelper; class CC_PAINT_EXPORT PaintOpReader { public: + // The DeserializeOptions passed to the reader must set all fields if it can + // be used to for deserializing images, paint records or text blobs. PaintOpReader(const volatile void* memory, size_t size, - TransferCacheDeserializeHelper* transfer_cache, + const PaintOp::DeserializeOptions& options, bool enable_security_constraints = false) : memory_(static_cast<const volatile char*>(memory) + PaintOpWriter::HeaderBytes()), remaining_bytes_(size - PaintOpWriter::HeaderBytes()), - transfer_cache_(transfer_cache), + options_(options), enable_security_constraints_(enable_security_constraints) { if (size < PaintOpWriter::HeaderBytes()) valid_ = false; @@ -184,13 +185,15 @@ class CC_PAINT_EXPORT PaintOpReader { sk_sp<PaintFilter>* filter, const base::Optional<PaintFilter::CropRect>& crop_rect); - void Read(sk_sp<PaintRecord>* record); + // Returns the size of the read record, 0 if error. + size_t Read(sk_sp<PaintRecord>* record); + void Read(SkRegion* region); const volatile char* memory_ = nullptr; size_t remaining_bytes_ = 0u; bool valid_ = true; - TransferCacheDeserializeHelper* transfer_cache_; + const PaintOp::DeserializeOptions& options_; // Indicates that the data was serialized with the following constraints: // 1) PaintRecords and SkDrawLoopers are ignored. diff --git a/chromium/cc/paint/paint_op_writer.cc b/chromium/cc/paint/paint_op_writer.cc index 697a9ea4647..00338a6ba2f 100644 --- a/chromium/cc/paint/paint_op_writer.cc +++ b/chromium/cc/paint/paint_op_writer.cc @@ -11,9 +11,11 @@ #include "cc/paint/paint_op_buffer_serializer.h" #include "cc/paint/paint_shader.h" #include "cc/paint/paint_typeface_transfer_cache_entry.h" +#include "cc/paint/path_transfer_cache_entry.h" #include "cc/paint/transfer_cache_serialize_helper.h" #include "third_party/skia/include/core/SkSerialProcs.h" #include "third_party/skia/include/core/SkTextBlob.h" +#include "third_party/skia/src/core/SkRemoteGlyphCache.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/skia_util.h" @@ -21,18 +23,16 @@ namespace cc { namespace { const size_t kSkiaAlignment = 4u; -sk_sp<SkData> TypefaceCataloger(SkTypeface* typeface, void* ctx) { - static_cast<TransferCacheSerializeHelper*>(ctx)->AssertLocked( - TransferCacheEntryType::kPaintTypeface, typeface->uniqueID()); - - uint32_t id = typeface->uniqueID(); - return SkData::MakeWithCopy(&id, sizeof(uint32_t)); -} - size_t RoundDownToAlignment(size_t bytes, size_t alignment) { return bytes - (bytes & (alignment - 1)); } +SkIRect MakeSrcRect(const PaintImage& image) { + if (!image) + return SkIRect::MakeEmpty(); + return SkIRect::MakeWH(image.width(), image.height()); +} + } // namespace // static @@ -77,14 +77,12 @@ size_t PaintOpWriter::GetRecordSize(const PaintRecord* record) { PaintOpWriter::PaintOpWriter(void* memory, size_t size, - TransferCacheSerializeHelper* transfer_cache, - ImageProvider* image_provider, + const PaintOp::SerializeOptions& options, bool enable_security_constraints) : memory_(static_cast<char*>(memory) + HeaderBytes()), size_(size), remaining_bytes_(size - HeaderBytes()), - transfer_cache_(transfer_cache), - image_provider_(image_provider), + options_(options), enable_security_constraints_(enable_security_constraints) { // Leave space for header of type/skip. DCHECK_GE(size, HeaderBytes()); @@ -169,16 +167,14 @@ void PaintOpWriter::Write(const SkRRect& rect) { } void PaintOpWriter::Write(const SkPath& path) { - AlignMemory(4); - size_t bytes = path.writeToMemory(nullptr); - EnsureBytes(bytes); - if (!valid_) - return; - - size_t bytes_written = path.writeToMemory(memory_); - DCHECK_LE(bytes_written, bytes); - memory_ += bytes; - remaining_bytes_ -= bytes; + auto id = path.getGenerationID(); + auto locked = + options_.transfer_cache->LockEntry(TransferCacheEntryType::kPath, id); + if (!locked) { + options_.transfer_cache->CreateEntry(ClientPathTransferCacheEntry(path)); + options_.transfer_cache->AssertLocked(TransferCacheEntryType::kPath, id); + } + Write(id); } void PaintOpWriter::Write(const PaintFlags& flags) { @@ -189,10 +185,9 @@ void PaintOpWriter::Write(const PaintFlags& flags) { WriteSimple(flags.blend_mode_); WriteSimple(flags.bitfields_uint_); - // TODO(enne): WriteTypeface, http://crbug.com/737629 - // Flattenables must be written starting at a 4 byte boundary, which should be // the case here. + AlignMemory(4); WriteFlattenable(flags.path_effect_.get()); AlignMemory(4); WriteFlattenable(flags.mask_filter_.get()); @@ -206,13 +201,26 @@ void PaintOpWriter::Write(const PaintFlags& flags) { WriteFlattenable(flags.draw_looper_.get()); Write(flags.image_filter_.get()); - Write(flags.shader_.get()); + Write(flags.shader_.get(), flags.getFilterQuality()); } -void PaintOpWriter::Write(const DrawImage& image) { +void PaintOpWriter::Write(const DrawImage& draw_image, + SkSize* scale_adjustment) { + // We never ask for subsets during serialization. + const PaintImage& paint_image = draw_image.paint_image(); + DCHECK_EQ(paint_image.width(), draw_image.src_rect().width()); + DCHECK_EQ(paint_image.height(), draw_image.src_rect().height()); + + // Empty image. + if (!draw_image.paint_image()) { + Write(static_cast<uint8_t>(PaintOp::SerializedImageType::kNoImage)); + return; + } + + // Security constrained serialization inlines the image bitmap. if (enable_security_constraints_) { SkBitmap bm; - if (!image.paint_image().GetSkImage()->asLegacyBitmap(&bm)) { + if (!draw_image.paint_image().GetSkImage()->asLegacyBitmap(&bm)) { Write(static_cast<uint8_t>(PaintOp::SerializedImageType::kNoImage)); return; } @@ -228,17 +236,24 @@ void PaintOpWriter::Write(const DrawImage& image) { return; } - Write( - static_cast<uint8_t>(PaintOp::SerializedImageType::kTransferCacheEntry)); - auto decoded_image = image_provider_->GetDecodedDrawImage(image); + // Default mode uses the transfer cache. + auto decoded_image = options_.image_provider->GetDecodedDrawImage(draw_image); DCHECK(!decoded_image.decoded_image().image()) << "Use transfer cache for image serialization"; + const DecodedDrawImage& decoded_draw_image = decoded_image.decoded_image(); + DCHECK(decoded_draw_image.src_rect_offset().isEmpty()) + << "We shouldn't ask for image subsets"; - base::Optional<uint32_t> id = - decoded_image.decoded_image().transfer_cache_entry_id(); - + base::Optional<uint32_t> id = decoded_draw_image.transfer_cache_entry_id(); + *scale_adjustment = decoded_draw_image.scale_adjustment(); // In the case of a decode failure, id may not be set. Send an invalid ID. - Write(id ? *id : kInvalidImageTransferCacheEntryId); + WriteImage(id ? *id : kInvalidImageTransferCacheEntryId); +} + +void PaintOpWriter::WriteImage(uint32_t transfer_cache_entry_id) { + Write( + static_cast<uint8_t>(PaintOp::SerializedImageType::kTransferCacheEntry)); + Write(transfer_cache_entry_id); } void PaintOpWriter::Write(const sk_sp<SkData>& data) { @@ -272,9 +287,12 @@ void PaintOpWriter::Write(const SkColorSpace* color_space) { remaining_bytes_ -= written; } -void PaintOpWriter::Write(const sk_sp<SkTextBlob>& blob) { - DCHECK(blob); +void PaintOpWriter::Write(const scoped_refptr<PaintTextBlob>& paint_blob) { + DCHECK(paint_blob); + if (!valid_) + return; + const auto& blob = paint_blob->ToSkTextBlob(); size_t size_offset = sizeof(size_t); EnsureBytes(size_offset); if (!valid_) @@ -283,9 +301,15 @@ void PaintOpWriter::Write(const sk_sp<SkTextBlob>& blob) { char* size_memory = memory_; memory_ += size_offset; remaining_bytes_ -= size_offset; + + auto encodeTypeface = [](SkTypeface* tf, void* ctx) -> sk_sp<SkData> { + return static_cast<SkStrikeServer*>(ctx)->serializeTypeface(tf); + }; + DCHECK(options_.strike_server); SkSerialProcs procs; - procs.fTypefaceProc = &TypefaceCataloger; - procs.fTypefaceCtx = transfer_cache_; + procs.fTypefaceProc = encodeTypeface; + procs.fTypefaceCtx = options_.strike_server; + size_t bytes_written = blob->serialize( procs, memory_, RoundDownToAlignment(remaining_bytes_, kSkiaAlignment)); if (bytes_written == 0u) { @@ -297,25 +321,41 @@ void PaintOpWriter::Write(const sk_sp<SkTextBlob>& blob) { remaining_bytes_ -= bytes_written; } -void PaintOpWriter::Write(const scoped_refptr<PaintTextBlob>& blob) { - if (!valid_) - return; +sk_sp<PaintShader> PaintOpWriter::TransformShaderIfNecessary( + const PaintShader* original, + SkFilterQuality quality, + uint32_t* paint_image_transfer_cache_entry_id, + gfx::SizeF* paint_record_post_scale) { + DCHECK(!enable_security_constraints_); + + const auto type = original->shader_type(); + const auto& ctm = options_.canvas->getTotalMatrix(); - for (auto& typeface : blob->typefaces()) { - auto locked = transfer_cache_->LockEntry( - TransferCacheEntryType::kPaintTypeface, typeface.sk_id()); - if (locked) - continue; - transfer_cache_->CreateEntry( - ClientPaintTypefaceTransferCacheEntry(typeface)); - transfer_cache_->AssertLocked(TransferCacheEntryType::kPaintTypeface, - typeface.sk_id()); + if (type == PaintShader::Type::kImage) { + return original->CreateDecodedImage(ctm, quality, options_.image_provider, + paint_image_transfer_cache_entry_id, + &quality); } - Write(blob->ToSkTextBlob()); + if (type == PaintShader::Type::kPaintRecord) { + return original->CreateScaledPaintRecord(ctm, paint_record_post_scale); + } + + return sk_ref_sp<PaintShader>(original); } -void PaintOpWriter::Write(const PaintShader* shader) { +void PaintOpWriter::Write(const PaintShader* shader, SkFilterQuality quality) { + sk_sp<PaintShader> transformed_shader; + uint32_t paint_image_transfer_cache_id = kInvalidImageTransferCacheEntryId; + gfx::SizeF paint_record_post_scale(1.f, 1.f); + + if (!enable_security_constraints_ && shader) { + transformed_shader = TransformShaderIfNecessary( + shader, quality, &paint_image_transfer_cache_id, + &paint_record_post_scale); + shader = transformed_shader.get(); + } + if (!shader) { WriteSimple(false); return; @@ -345,21 +385,31 @@ void PaintOpWriter::Write(const PaintShader* shader) { WriteSimple(shader->end_point_); WriteSimple(shader->start_degrees_); WriteSimple(shader->end_degrees_); - Write(shader->image_); + + if (enable_security_constraints_) { + DrawImage draw_image(shader->image_, MakeSrcRect(shader->image_), quality, + SkMatrix::I()); + SkSize scale_adjustment = SkSize::Make(1.f, 1.f); + Write(draw_image, &scale_adjustment); + DCHECK_EQ(scale_adjustment.width(), 1.f); + DCHECK_EQ(scale_adjustment.height(), 1.f); + } else { + WriteImage(paint_image_transfer_cache_id); + } + if (shader->record_) { Write(true); - base::Optional<gfx::Rect> playback_rect; - base::Optional<gfx::SizeF> post_scale; - if (shader->tile_scale()) { - playback_rect.emplace( - gfx::ToEnclosingRect(gfx::SkRectToRectF(shader->tile()))); - post_scale.emplace(*shader->tile_scale()); - } - Write(shader->record_.get(), std::move(playback_rect), - std::move(post_scale)); + DCHECK_NE(shader->id_, PaintShader::kInvalidRecordShaderId); + Write(shader->id_); + const gfx::Rect playback_rect( + gfx::ToEnclosingRect(gfx::SkRectToRectF(shader->tile()))); + Write(shader->record_.get(), playback_rect, paint_record_post_scale, + SkMatrix::I()); } else { + DCHECK_EQ(shader->id_, PaintShader::kInvalidRecordShaderId); Write(false); } + WriteSimple(shader->colors_.size()); WriteData(shader->colors_.size() * sizeof(SkColor), shader->colors_.data()); @@ -583,7 +633,11 @@ void PaintOpWriter::Write(const ImagePaintFilter& filter) { filter.image(), SkIRect::MakeWH(filter.image().width(), filter.image().height()), filter.filter_quality(), SkMatrix::I()); - Write(draw_image); + SkSize scale_adjustment = SkSize::Make(1.f, 1.f); + Write(draw_image, &scale_adjustment); + DCHECK_EQ(scale_adjustment.width(), 1.f); + DCHECK_EQ(scale_adjustment.height(), 1.f); + Write(filter.src_rect()); Write(filter.dst_rect()); Write(filter.filter_quality()); @@ -591,7 +645,8 @@ void PaintOpWriter::Write(const ImagePaintFilter& filter) { void PaintOpWriter::Write(const RecordPaintFilter& filter) { WriteSimple(filter.record_bounds()); - Write(filter.record().get()); + Write(filter.record().get(), gfx::Rect(), gfx::SizeF(1.f, 1.f), + options_.canvas ? options_.canvas->getTotalMatrix() : SkMatrix::I()); } void PaintOpWriter::Write(const MergePaintFilter& filter) { @@ -672,9 +727,9 @@ void PaintOpWriter::Write(const LightingSpotPaintFilter& filter) { } void PaintOpWriter::Write(const PaintRecord* record, - base::Optional<gfx::Rect> playback_rect, - base::Optional<gfx::SizeF> post_scale) { - DCHECK_EQ(playback_rect.has_value(), post_scale.has_value()); + const gfx::Rect& playback_rect, + const gfx::SizeF& post_scale, + const SkMatrix& post_matrix_for_analysis) { // We need to record how many bytes we will serialize, but we don't know this // information until we do the serialization. So, skip the amount needed // before writing. @@ -697,13 +752,12 @@ void PaintOpWriter::Write(const PaintRecord* record, return; } - SimpleBufferSerializer serializer(memory_, remaining_bytes_, image_provider_, - transfer_cache_); - if (playback_rect) { - serializer.Serialize(record, *playback_rect, *post_scale); - } else { - serializer.Serialize(record); - } + SimpleBufferSerializer serializer( + memory_, remaining_bytes_, options_.image_provider, + options_.transfer_cache, options_.strike_server, options_.color_space, + options_.can_use_lcd_text); + serializer.Serialize(record, playback_rect, post_scale, + post_matrix_for_analysis); if (!serializer.valid()) { valid_ = false; @@ -725,20 +779,6 @@ void PaintOpWriter::Write(const PaintRecord* record, remaining_bytes_ -= serializer.written(); } -void PaintOpWriter::Write(const PaintImage& image) { - if (!image) { - Write(static_cast<uint8_t>(PaintOp::SerializedImageType::kNoImage)); - return; - } - // Note that the filter quality doesn't matter here, since it's not - // serialized. It's only used to determine the decoded draw image that we will - // get. However, since we're requesting a full-sized image decode, the filter - // quality is essentially ignored. - DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()), - kLow_SkFilterQuality, SkMatrix::I()); - Write(draw_image); -} - void PaintOpWriter::Write(const SkRegion& region) { size_t bytes_required = region.writeToMemory(nullptr); std::unique_ptr<char[]> data(new char[bytes_required]); diff --git a/chromium/cc/paint/paint_op_writer.h b/chromium/cc/paint/paint_op_writer.h index 685ff92c857..ecca69ced59 100644 --- a/chromium/cc/paint/paint_op_writer.h +++ b/chromium/cc/paint/paint_op_writer.h @@ -19,16 +19,15 @@ class SkRRect; namespace cc { class DrawImage; -class ImageProvider; class PaintShader; -class TransferCacheSerializeHelper; class CC_PAINT_EXPORT PaintOpWriter { public: + // The SerializeOptions passed to the writer must set the required fields + // if it can be used for serializing images, paint records or text blobs. PaintOpWriter(void* memory, size_t size, - TransferCacheSerializeHelper* transfer_cache, - ImageProvider* image_provider, + const PaintOp::SerializeOptions& options, bool enable_security_constraints = false); ~PaintOpWriter(); @@ -58,10 +57,9 @@ class CC_PAINT_EXPORT PaintOpWriter { void Write(const SkPath& path); void Write(const PaintFlags& flags); - void Write(const DrawImage& image); void Write(const sk_sp<SkData>& data); void Write(const SkColorSpace* data); - void Write(const PaintShader* shader); + void Write(const PaintShader* shader, SkFilterQuality quality); void Write(const PaintFilter* filter); void Write(const scoped_refptr<PaintTextBlob>& blob); void Write(SkColorType color_type); @@ -92,13 +90,23 @@ class CC_PAINT_EXPORT PaintOpWriter { static_assert(sizeof(T) == 0, "Attempted to call a non-existent sk_sp override."); } + template <typename T> + void Write(const T*) { + static_assert(sizeof(T) == 0, + "Attempted to call a non-existent T* override."); + } + + // Serializes the given |draw_image|. + // |scale_adjustment| is set to the scale applied to the serialized image. + // |quality| is set to the quality that should be used when rasterizing this + // image. + void Write(const DrawImage& draw_image, SkSize* scale_adjustment); private: template <typename T> void WriteSimple(const T& val); void WriteFlattenable(const SkFlattenable* val); - void Write(const sk_sp<SkTextBlob>& blob); // The main entry point is Write(const PaintFilter* filter) which casts the // filter and calls one of the following functions. @@ -126,18 +134,23 @@ class CC_PAINT_EXPORT PaintOpWriter { void Write(const LightingSpotPaintFilter& filter); void Write(const PaintRecord* record, - base::Optional<gfx::Rect> playback_rect = base::nullopt, - base::Optional<gfx::SizeF> post_scale = base::nullopt); - void Write(const PaintImage& image); + const gfx::Rect& playback_rect, + const gfx::SizeF& post_scale, + const SkMatrix& post_matrix_for_analysis); void Write(const SkRegion& region); + void WriteImage(uint32_t transfer_cache_entry_id); void EnsureBytes(size_t required_bytes); + sk_sp<PaintShader> TransformShaderIfNecessary( + const PaintShader* original, + SkFilterQuality quality, + uint32_t* paint_image_transfer_cache_entry_id, + gfx::SizeF* paint_record_post_scale); char* memory_ = nullptr; size_t size_ = 0u; size_t remaining_bytes_ = 0u; - TransferCacheSerializeHelper* transfer_cache_; - ImageProvider* image_provider_; + const PaintOp::SerializeOptions& options_; bool valid_ = true; // Indicates that the following security constraints must be applied during diff --git a/chromium/cc/paint/paint_shader.cc b/chromium/cc/paint/paint_shader.cc index 6baee9fe6d3..f06e539ddd9 100644 --- a/chromium/cc/paint/paint_shader.cc +++ b/chromium/cc/paint/paint_shader.cc @@ -4,6 +4,8 @@ #include "cc/paint/paint_shader.h" +#include "base/atomic_sequence_num.h" +#include "cc/paint/paint_image_builder.h" #include "cc/paint/paint_op_writer.h" #include "cc/paint/paint_record.h" #include "third_party/skia/include/core/SkPictureRecorder.h" @@ -11,6 +13,7 @@ namespace cc { namespace { +base::AtomicSequenceNumber g_next_shader_id; sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record, const SkRect& bounds, @@ -24,8 +27,27 @@ sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record, return recorder.finishRecordingAsPicture(); } +bool CompareMatrices(const SkMatrix& a, + const SkMatrix& b, + bool ignore_scaling_differences) { + if (!ignore_scaling_differences) + return PaintOp::AreSkMatricesEqual(a, b); + + SkSize scale; + SkMatrix a_without_scale; + SkMatrix b_without_scale; + if (a.decomposeScale(&scale, &a_without_scale) != + b.decomposeScale(&scale, &b_without_scale)) { + return false; + } + + return PaintOp::AreSkMatricesEqual(a_without_scale, b_without_scale); +} + } // namespace +const PaintShader::RecordShaderId PaintShader::kInvalidRecordShaderId = -1; + sk_sp<PaintShader> PaintShader::MakeColor(SkColor color) { sk_sp<PaintShader> shader(new PaintShader(Type::kColor)); @@ -151,6 +173,7 @@ sk_sp<PaintShader> PaintShader::MakePaintRecord( sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord)); shader->record_ = std::move(record); + shader->id_ = g_next_shader_id.GetNext(); shader->tile_ = tile; shader->scaling_behavior_ = scaling_behavior; shader->SetMatrixAndTiling(local_matrix, tx, ty); @@ -175,6 +198,7 @@ size_t PaintShader::GetSerializedSize(const PaintShader* shader) { sizeof(shader->end_degrees_) + PaintOpWriter::GetImageSize(shader->image_) + PaintOpWriter::GetImageSize(shader->image_) + bool_size + + sizeof(shader->id_) + PaintOpWriter::GetRecordSize(shader->record_.get()) + sizeof(shader->colors_.size()) + shader->colors_.size() * sizeof(SkColor) + @@ -235,9 +259,9 @@ bool PaintShader::GetRasterizationTileRect(const SkMatrix& ctm, return true; } -sk_sp<PaintShader> PaintShader::CreateDecodedPaintRecord( +sk_sp<PaintShader> PaintShader::CreateScaledPaintRecord( const SkMatrix& ctm, - ImageProvider* image_provider) const { + gfx::SizeF* raster_scale) const { DCHECK_EQ(shader_type_, Type::kPaintRecord); // For creating a decoded PaintRecord shader, we need to do the following: @@ -258,6 +282,7 @@ sk_sp<PaintShader> PaintShader::CreateDecodedPaintRecord( sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord)); shader->record_ = record_; + shader->id_ = id_; shader->tile_ = tile_rect; // Use a fixed scale since we have already scaled the tile rect and fixed the // raster scale. @@ -265,21 +290,73 @@ sk_sp<PaintShader> PaintShader::CreateDecodedPaintRecord( shader->tx_ = tx_; shader->ty_ = ty_; - shader->tile_scale_ = + *raster_scale = gfx::SizeF(SkIntToScalar(tile_rect.width()) / tile_.width(), SkIntToScalar(tile_rect.height()) / tile_.height()); shader->local_matrix_ = GetLocalMatrix(); - shader->local_matrix_->preScale(1 / shader->tile_scale_->width(), - 1 / shader->tile_scale_->height()); + shader->local_matrix_->preScale(1 / raster_scale->width(), + 1 / raster_scale->height()); return shader; } +sk_sp<PaintShader> PaintShader::CreateDecodedImage( + const SkMatrix& ctm, + SkFilterQuality quality, + ImageProvider* image_provider, + uint32_t* transfer_cache_entry_id, + SkFilterQuality* raster_quality) const { + DCHECK_EQ(shader_type_, Type::kImage); + if (!image_) + return nullptr; + + SkMatrix total_image_matrix = GetLocalMatrix(); + total_image_matrix.preConcat(ctm); + SkRect src_rect = SkRect::MakeIWH(image_.width(), image_.height()); + SkIRect int_src_rect; + src_rect.roundOut(&int_src_rect); + DrawImage draw_image(image_, int_src_rect, quality, total_image_matrix); + auto decoded_draw_image = image_provider->GetDecodedDrawImage(draw_image); + if (!decoded_draw_image) + return nullptr; + + auto decoded_image = decoded_draw_image.decoded_image(); + SkMatrix final_matrix = GetLocalMatrix(); + bool need_scale = !decoded_image.is_scale_adjustment_identity(); + if (need_scale) { + final_matrix.preScale(1.f / decoded_image.scale_adjustment().width(), + 1.f / decoded_image.scale_adjustment().height()); + } + + PaintImage decoded_paint_image; + if (decoded_image.transfer_cache_entry_id()) { + decoded_paint_image = image_; + *transfer_cache_entry_id = *decoded_image.transfer_cache_entry_id(); + } else { + DCHECK(decoded_image.image()); + + sk_sp<SkImage> sk_image = + sk_ref_sp<SkImage>(const_cast<SkImage*>(decoded_image.image().get())); + decoded_paint_image = + PaintImageBuilder::WithDefault() + .set_id(image_.stable_id()) + .set_image(std::move(sk_image), image_.content_id()) + .TakePaintImage(); + } + + // TODO(khushalsagar): Remove filter quality from DecodedDrawImage. All we + // want to do is cap the filter quality used, but Gpu and Sw cache have + // different behaviour. D: + *raster_quality = decoded_image.filter_quality(); + return PaintShader::MakeImage(decoded_paint_image, tx_, ty_, &final_matrix); +} + sk_sp<SkShader> PaintShader::GetSkShader() const { return cached_shader_; } -void PaintShader::CreateSkShader(ImageProvider* image_provider) { +void PaintShader::CreateSkShader(const gfx::SizeF* raster_scale, + ImageProvider* image_provider) { DCHECK(!cached_shader_); switch (shader_type_) { @@ -325,7 +402,7 @@ void PaintShader::CreateSkShader(ImageProvider* image_provider) { case Type::kPaintRecord: { // Create a recording at the desired scale if this record has images which // have been decoded before raster. - auto picture = ToSkPicture(record_, tile_, tile_scale(), image_provider); + auto picture = ToSkPicture(record_, tile_, raster_scale, image_provider); switch (scaling_behavior_) { // For raster scale, we create a picture shader directly. @@ -426,16 +503,20 @@ bool PaintShader::operator==(const PaintShader& other) const { if (shader_type_ != other.shader_type_) return false; + // Record and image shaders are scaled during serialization. + const bool ignore_scaling_differences = + shader_type_ == PaintShader::Type::kPaintRecord || + shader_type_ == PaintShader::Type::kImage; + // Variables that all shaders use. - if (local_matrix_) { - if (!other.local_matrix_.has_value()) - return false; - if (!PaintOp::AreSkMatricesEqual(*local_matrix_, *other.local_matrix_)) - return false; - } else { - if (other.local_matrix_.has_value()) - return false; + const SkMatrix& local_matrix = local_matrix_ ? *local_matrix_ : SkMatrix::I(); + const SkMatrix& other_local_matrix = + other.local_matrix_ ? *other.local_matrix_ : SkMatrix::I(); + if (!CompareMatrices(local_matrix, other_local_matrix, + ignore_scaling_differences)) { + return false; } + if (fallback_color_ != other.fallback_color_) return false; if (flags_ != other.flags_) @@ -444,7 +525,9 @@ bool PaintShader::operator==(const PaintShader& other) const { return false; if (ty_ != other.ty_) return false; - if (scaling_behavior_ != other.scaling_behavior_) + + if (!ignore_scaling_differences && + scaling_behavior_ != other.scaling_behavior_) return false; // Variables that only some shaders use. @@ -487,10 +570,8 @@ bool PaintShader::operator==(const PaintShader& other) const { // aren't the same. if (!record_ != !other.record_) return false; - if (record_ && *record_ != *other.record_) - return false; - if (!PaintOp::AreSkRectsEqual(tile_, other.tile_)) - return false; + // tile_ and record_ intentionally omitted since they are modified on the + // serialized shader based on the ctm. break; case Type::kShaderCount: break; diff --git a/chromium/cc/paint/paint_shader.h b/chromium/cc/paint/paint_shader.h index 6c197b7919d..6c2e963fb40 100644 --- a/chromium/cc/paint/paint_shader.h +++ b/chromium/cc/paint/paint_shader.h @@ -16,6 +16,7 @@ #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/core/SkShader.h" +#include "ui/gfx/color_space.h" #include "ui/gfx/geometry/size_f.h" namespace cc { @@ -36,6 +37,9 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { kShaderCount }; + using RecordShaderId = uint32_t; + static const RecordShaderId kInvalidRecordShaderId; + // Scaling behavior dictates how a PaintRecord shader will behave. Use // RasterAtScale to create a picture shader. Use FixedScale to create an image // shader that is backed by the paint record. @@ -148,6 +152,11 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { bool operator==(const PaintShader& other) const; bool operator!=(const PaintShader& other) const { return !(*this == other); } + RecordShaderId paint_record_shader_id() const { + DCHECK(id_ == kInvalidRecordShaderId || shader_type_ == Type::kPaintRecord); + return id_; + } + private: friend class PaintFlags; friend class PaintOpReader; @@ -156,15 +165,34 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { friend class ScopedRasterFlags; FRIEND_TEST_ALL_PREFIXES(PaintShaderTest, DecodePaintRecord); FRIEND_TEST_ALL_PREFIXES(PaintOpBufferTest, PaintRecordShaderSerialization); + FRIEND_TEST_ALL_PREFIXES(PaintOpBufferTest, RecordShadersCached); explicit PaintShader(Type type); sk_sp<SkShader> GetSkShader() const; - void CreateSkShader(ImageProvider* image_provider = nullptr); - - sk_sp<PaintShader> CreateDecodedPaintRecord( - const SkMatrix& ctm, - ImageProvider* image_provider) const; + void CreateSkShader(const gfx::SizeF* raster_scale = nullptr, + ImageProvider* image_provider = nullptr); + + // Creates a PaintShader to be rasterized at the given ctm. |raster_scale| is + // set to the scale at which the record should be rasterized when the shader + // is used. + // Note that this does not create a skia backing for the shader. + // Valid only for PaintRecord backed shaders. + sk_sp<PaintShader> CreateScaledPaintRecord(const SkMatrix& ctm, + gfx::SizeF* raster_scale) const; + + // Creates a PaintShader with images from |image_provider| to be rasterized + // at the given ctm. + // |transfer_cache_entry_id| is set to the transfer cache id for the image, if + // the decode is backed by the transfer cache. + // |raster_quality| is set to the filter quality the shader should be + // rasterized with. + // Valid only for PaintImage backed shaders. + sk_sp<PaintShader> CreateDecodedImage(const SkMatrix& ctm, + SkFilterQuality requested_quality, + ImageProvider* image_provider, + uint32_t* transfer_cache_entry_id, + SkFilterQuality* raster_quality) const; void SetColorsAndPositions(const SkColor* colors, const SkScalar* positions, @@ -196,6 +224,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { PaintImage image_; sk_sp<PaintRecord> record_; + RecordShaderId id_ = kInvalidRecordShaderId; // For decoded PaintRecord shaders, specifies the scale at which the record // will be rasterized. diff --git a/chromium/cc/paint/path_transfer_cache_entry.cc b/chromium/cc/paint/path_transfer_cache_entry.cc new file mode 100644 index 00000000000..c1490109c05 --- /dev/null +++ b/chromium/cc/paint/path_transfer_cache_entry.cc @@ -0,0 +1,54 @@ +// Copyright 2018 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/path_transfer_cache_entry.h" + +namespace cc { + +ClientPathTransferCacheEntry::ClientPathTransferCacheEntry(const SkPath& path) + : path_(path) { + size_ = path_.writeToMemory(nullptr); +} + +ClientPathTransferCacheEntry::~ClientPathTransferCacheEntry() = default; + +uint32_t ClientPathTransferCacheEntry::Id() const { + return path_.getGenerationID(); +} + +size_t ClientPathTransferCacheEntry::SerializedSize() const { + return size_; +} + +bool ClientPathTransferCacheEntry::Serialize(base::span<uint8_t> data) const { + DCHECK_EQ(data.size(), size_); + + size_t bytes_written = path_.writeToMemory(data.data()); + CHECK_LE(bytes_written, size_); + return true; +} + +ServicePathTransferCacheEntry::ServicePathTransferCacheEntry() = default; + +ServicePathTransferCacheEntry::~ServicePathTransferCacheEntry() = default; + +size_t ServicePathTransferCacheEntry::CachedSize() const { + return size_; +} + +bool ServicePathTransferCacheEntry::Deserialize( + GrContext* context, + base::span<const uint8_t> data) { + size_t read_bytes = path_.readFromMemory(data.data(), data.size()); + // Invalid path. + if (read_bytes == 0) + return false; + if (read_bytes > data.size()) + return false; + size_ = read_bytes; + + return true; +} + +} // namespace cc diff --git a/chromium/cc/paint/path_transfer_cache_entry.h b/chromium/cc/paint/path_transfer_cache_entry.h new file mode 100644 index 00000000000..b1282e3c11f --- /dev/null +++ b/chromium/cc/paint/path_transfer_cache_entry.h @@ -0,0 +1,46 @@ +// 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_PATH_TRANSFER_CACHE_ENTRY_H_ +#define CC_PAINT_PATH_TRANSFER_CACHE_ENTRY_H_ + +#include "base/containers/span.h" +#include "cc/paint/paint_export.h" +#include "cc/paint/transfer_cache_entry.h" +#include "third_party/skia/include/core/SkPath.h" + +namespace cc { + +class CC_PAINT_EXPORT ClientPathTransferCacheEntry + : public ClientTransferCacheEntryBase<TransferCacheEntryType::kPath> { + public: + explicit ClientPathTransferCacheEntry(const SkPath& path); + ~ClientPathTransferCacheEntry() final; + uint32_t Id() const final; + size_t SerializedSize() const final; + bool Serialize(base::span<uint8_t> data) const final; + + private: + SkPath path_; + size_t size_ = 0u; +}; + +class CC_PAINT_EXPORT ServicePathTransferCacheEntry + : public ServiceTransferCacheEntryBase<TransferCacheEntryType::kPath> { + public: + ServicePathTransferCacheEntry(); + ~ServicePathTransferCacheEntry() final; + size_t CachedSize() const final; + bool Deserialize(GrContext* context, base::span<const uint8_t> data) final; + + const SkPath& path() const { return path_; } + + private: + SkPath path_; + size_t size_ = 0; +}; + +} // namespace cc + +#endif // CC_PAINT_PATH_TRANSFER_CACHE_ENTRY_H_ diff --git a/chromium/cc/paint/scoped_raster_flags.cc b/chromium/cc/paint/scoped_raster_flags.cc index b54f137e1dc..cee4465a8c6 100644 --- a/chromium/cc/paint/scoped_raster_flags.cc +++ b/chromium/cc/paint/scoped_raster_flags.cc @@ -5,6 +5,7 @@ #include "cc/paint/scoped_raster_flags.h" #include "cc/paint/image_provider.h" +#include "cc/paint/image_transfer_cache_entry.h" #include "cc/paint/paint_filter.h" #include "cc/paint/paint_image_builder.h" @@ -12,20 +13,16 @@ namespace cc { ScopedRasterFlags::ScopedRasterFlags(const PaintFlags* flags, ImageProvider* image_provider, const SkMatrix& ctm, - uint8_t alpha, - bool create_skia_shader) + uint8_t alpha) : original_flags_(flags) { - if (flags->HasDiscardableImages() && image_provider) { - // TODO(khushalsagar): The decoding of images in PaintFlags here is a bit of - // a mess. We decode image shaders at the correct scale but ignore that - // during serialization and just use the original image. + if (image_provider) { decode_stashing_image_provider_.emplace(image_provider); // We skip the op if any images fail to decode. DecodeImageShader(ctm); if (decode_failed_) return; - DecodeRecordShader(ctm, create_skia_shader); + DecodeRecordShader(ctm); if (decode_failed_) return; DecodeFilter(); @@ -48,79 +45,40 @@ void ScopedRasterFlags::DecodeImageShader(const SkMatrix& ctm) { flags()->getShader()->shader_type() != PaintShader::Type::kImage) return; - const PaintImage& paint_image = flags()->getShader()->paint_image(); - SkMatrix matrix = flags()->getShader()->GetLocalMatrix(); + uint32_t transfer_cache_entry_id = kInvalidImageTransferCacheEntryId; + SkFilterQuality raster_quality = flags()->getFilterQuality(); + auto decoded_shader = flags()->getShader()->CreateDecodedImage( + ctm, flags()->getFilterQuality(), &*decode_stashing_image_provider_, + &transfer_cache_entry_id, &raster_quality); + DCHECK_EQ(transfer_cache_entry_id, kInvalidImageTransferCacheEntryId); - SkMatrix total_image_matrix = matrix; - total_image_matrix.preConcat(ctm); - SkRect src_rect = SkRect::MakeIWH(paint_image.width(), paint_image.height()); - SkIRect int_src_rect; - src_rect.roundOut(&int_src_rect); - DrawImage draw_image(paint_image, int_src_rect, flags()->getFilterQuality(), - total_image_matrix); - auto decoded_draw_image = - decode_stashing_image_provider_->GetDecodedDrawImage(draw_image); - - if (!decoded_draw_image) { + if (!decoded_shader) { decode_failed_ = true; return; } - const auto& decoded_image = decoded_draw_image.decoded_image(); - // If this image is backed by a transfer cache entry id, then it's suitable - // for serialization. We don't need to do anything here, because the image - // provider (accessed via PaintOpWriter) will get the decode and serialize the - // transfer cache id. - // Note that if we replace this with the decoded paint image, the - // serialization will fail, because a transfer cache backed image cannot on - // its own construct an SkImage which is needed to create an underlying - // SkShader. - if (decoded_image.transfer_cache_entry_id()) { - DCHECK(!decoded_image.image()); - return; - } - DCHECK(decoded_image.image()); - - bool need_scale = !decoded_image.is_scale_adjustment_identity(); - if (need_scale) { - matrix.preScale(1.f / decoded_image.scale_adjustment().width(), - 1.f / decoded_image.scale_adjustment().height()); - } - - sk_sp<SkImage> sk_image = - sk_ref_sp<SkImage>(const_cast<SkImage*>(decoded_image.image().get())); - PaintImage decoded_paint_image = - PaintImageBuilder::WithDefault() - .set_id(paint_image.stable_id()) - .set_image(std::move(sk_image), PaintImage::kNonLazyStableId) - .TakePaintImage(); - MutableFlags()->setFilterQuality(decoded_image.filter_quality()); - MutableFlags()->setShader( - PaintShader::MakeImage(decoded_paint_image, flags()->getShader()->tx(), - flags()->getShader()->ty(), &matrix)); + MutableFlags()->setFilterQuality(raster_quality); + MutableFlags()->setShader(decoded_shader); } -void ScopedRasterFlags::DecodeRecordShader(const SkMatrix& ctm, - bool create_skia_shader) { +void ScopedRasterFlags::DecodeRecordShader(const SkMatrix& ctm) { if (!flags()->HasShader() || flags()->getShader()->shader_type() != PaintShader::Type::kPaintRecord) return; - // TODO(khushalsagar): For OOP, we have to decode everything during - // serialization. This will force us to use original sized decodes. + // Only replace shaders with animated images. Creating transient shaders for + // replacing decodes during raster results in cache misses in skia's picture + // shader cache, which results in re-rasterizing the picture for every draw. if (flags()->getShader()->image_analysis_state() != - ImageAnalysisState::kAnimatedImages) - return; - - auto decoded_shader = flags()->getShader()->CreateDecodedPaintRecord( - ctm, &*decode_stashing_image_provider_); - if (!decoded_shader) { - decode_failed_ = true; + ImageAnalysisState::kAnimatedImages) { return; } - if (create_skia_shader) - decoded_shader->CreateSkShader(&*decode_stashing_image_provider_); + gfx::SizeF raster_scale(1.f, 1.f); + auto decoded_shader = + flags()->getShader()->CreateScaledPaintRecord(ctm, &raster_scale); + decoded_shader->CreateSkShader(&raster_scale, + &*decode_stashing_image_provider_); MutableFlags()->setShader(std::move(decoded_shader)); } diff --git a/chromium/cc/paint/scoped_raster_flags.h b/chromium/cc/paint/scoped_raster_flags.h index 5407b5e2655..91a6b871105 100644 --- a/chromium/cc/paint/scoped_raster_flags.h +++ b/chromium/cc/paint/scoped_raster_flags.h @@ -21,8 +21,7 @@ class CC_PAINT_EXPORT ScopedRasterFlags { ScopedRasterFlags(const PaintFlags* flags, ImageProvider* image_provider, const SkMatrix& ctm, - uint8_t alpha, - bool create_skia_shaders); + uint8_t alpha); ~ScopedRasterFlags(); // The usage of these flags should not extend beyond the lifetime of this @@ -36,7 +35,7 @@ class CC_PAINT_EXPORT ScopedRasterFlags { private: void DecodeImageShader(const SkMatrix& ctm); - void DecodeRecordShader(const SkMatrix& ctm, bool create_skia_shader); + void DecodeRecordShader(const SkMatrix& ctm); void DecodeFilter(); void AdjustStrokeIfNeeded(const SkMatrix& ctm); diff --git a/chromium/cc/paint/scoped_raster_flags_unittest.cc b/chromium/cc/paint/scoped_raster_flags_unittest.cc index b0ac2654d1d..801d6cfa933 100644 --- a/chromium/cc/paint/scoped_raster_flags_unittest.cc +++ b/chromium/cc/paint/scoped_raster_flags_unittest.cc @@ -60,7 +60,7 @@ TEST(ScopedRasterFlagsTest, KeepsDecodesAlive) { PaintFlags flags; flags.setShader(record_shader); { - ScopedRasterFlags scoped_flags(&flags, &provider, SkMatrix::I(), 255, true); + ScopedRasterFlags scoped_flags(&flags, &provider, SkMatrix::I(), 255); ASSERT_TRUE(scoped_flags.flags()); EXPECT_NE(scoped_flags.flags(), &flags); SkPaint paint = scoped_flags.flags()->ToSkPaint(); @@ -77,7 +77,7 @@ TEST(ScopedRasterFlagsTest, NoImageProvider) { CreateDiscardablePaintImage(gfx::Size(10, 10)), SkShader::TileMode::kClamp_TileMode, SkShader::TileMode::kClamp_TileMode, &SkMatrix::I())); - ScopedRasterFlags scoped_flags(&flags, nullptr, SkMatrix::I(), 10, true); + ScopedRasterFlags scoped_flags(&flags, nullptr, SkMatrix::I(), 10); EXPECT_NE(scoped_flags.flags(), &flags); EXPECT_EQ(scoped_flags.flags()->getAlpha(), SkMulDiv255Round(255, 10)); } @@ -108,7 +108,7 @@ TEST(ScopedRasterFlagsTest, ThinAliasedStroke) { }; for (const auto& test : tests) { - ScopedRasterFlags scoped_flags(&flags, nullptr, test.ctm, test.alpha, true); + ScopedRasterFlags scoped_flags(&flags, nullptr, test.ctm, test.alpha); ASSERT_TRUE(scoped_flags.flags()); EXPECT_EQ(scoped_flags.flags() == &flags, test.expect_same_flags); diff --git a/chromium/cc/paint/shader_transfer_cache_entry.cc b/chromium/cc/paint/shader_transfer_cache_entry.cc new file mode 100644 index 00000000000..5e66f1b6b95 --- /dev/null +++ b/chromium/cc/paint/shader_transfer_cache_entry.cc @@ -0,0 +1,31 @@ +// Copyright 2018 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/shader_transfer_cache_entry.h" + +namespace cc { + +ServiceShaderTransferCacheEntry::ServiceShaderTransferCacheEntry( + sk_sp<PaintShader> shader, + uint32_t raster_color_space_id, + size_t size) + : shader_(std::move(shader)), + raster_color_space_id_(raster_color_space_id), + size_(size) {} + +ServiceShaderTransferCacheEntry::~ServiceShaderTransferCacheEntry() = default; + +size_t ServiceShaderTransferCacheEntry::CachedSize() const { + return size_; +} + +bool ServiceShaderTransferCacheEntry::Deserialize( + GrContext* context, + base::span<const uint8_t> data) { + // These entries must be created directly via CreateLocalEntry. + NOTREACHED(); + return false; +} + +} // namespace cc diff --git a/chromium/cc/paint/shader_transfer_cache_entry.h b/chromium/cc/paint/shader_transfer_cache_entry.h new file mode 100644 index 00000000000..fcb6abb7572 --- /dev/null +++ b/chromium/cc/paint/shader_transfer_cache_entry.h @@ -0,0 +1,46 @@ +// Copyright 2018 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_SHADER_TRANSFER_CACHE_ENTRY_H_ +#define CC_PAINT_SHADER_TRANSFER_CACHE_ENTRY_H_ + +#include "base/containers/span.h" +#include "cc/paint/paint_export.h" +#include "cc/paint/paint_shader.h" +#include "cc/paint/transfer_cache_entry.h" + +namespace cc { + +// There is only a service transfer cache entry here. The reason shaders +// are cached at all are to reuse internal Skia caches for SkPictureShaders. +// However, the major reason not to transfer from the client is that it +// avoids the design change to make it possible for transfer cache entries +// to depend on transfer cache entries. This adds a number of wrinkles +// (during serialization, deserialization, scheduling). The assumption +// is that most picture shaders are small (e.g. a few ops to draw a tiled +// image) and that the design complication for this edge case isn't worth +// it. + +class CC_PAINT_EXPORT ServiceShaderTransferCacheEntry + : public ServiceTransferCacheEntryBase<TransferCacheEntryType::kShader> { + public: + explicit ServiceShaderTransferCacheEntry(sk_sp<PaintShader> shader, + uint32_t raster_color_space_id, + size_t size); + ~ServiceShaderTransferCacheEntry() final; + size_t CachedSize() const final; + bool Deserialize(GrContext* context, base::span<const uint8_t> data) final; + + sk_sp<PaintShader> shader() const { return shader_; } + uint32_t raster_color_space_id() const { return raster_color_space_id_; } + + private: + sk_sp<PaintShader> shader_; + uint32_t raster_color_space_id_; + size_t size_ = 0; +}; + +} // namespace cc + +#endif // CC_PAINT_SHADER_TRANSFER_CACHE_ENTRY_H_ diff --git a/chromium/cc/paint/skia_paint_canvas.cc b/chromium/cc/paint/skia_paint_canvas.cc index 83128d5c3a6..b5963ca9d05 100644 --- a/chromium/cc/paint/skia_paint_canvas.cc +++ b/chromium/cc/paint/skia_paint_canvas.cc @@ -16,8 +16,6 @@ namespace cc { -const bool SkiaPaintCanvas::kCreateSkiaShaders = true; - SkiaPaintCanvas::ContextFlushes::ContextFlushes() : enable(false), max_draws_before_flush(-1) {} @@ -171,8 +169,7 @@ void SkiaPaintCanvas::drawLine(SkScalar x0, SkScalar y1, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -183,8 +180,7 @@ void SkiaPaintCanvas::drawLine(SkScalar x0, void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -195,8 +191,7 @@ void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { void SkiaPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -207,8 +202,7 @@ void SkiaPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) { void SkiaPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -219,8 +213,7 @@ void SkiaPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) { void SkiaPaintCanvas::drawRRect(const SkRRect& rrect, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -233,8 +226,7 @@ void SkiaPaintCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -248,8 +240,7 @@ void SkiaPaintCanvas::drawRoundRect(const SkRect& rect, SkScalar ry, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -260,8 +251,7 @@ void SkiaPaintCanvas::drawRoundRect(const SkRect& rect, void SkiaPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -277,7 +267,7 @@ void SkiaPaintCanvas::drawImage(const PaintImage& image, base::Optional<ScopedRasterFlags> scoped_flags; if (flags) { scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(), - 255u, kCreateSkiaShaders); + 255u); if (!scoped_flags->flags()) return; } @@ -297,7 +287,7 @@ void SkiaPaintCanvas::drawImageRect(const PaintImage& image, base::Optional<ScopedRasterFlags> scoped_flags; if (flags) { scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(), - 255u, kCreateSkiaShaders); + 255u); if (!scoped_flags->flags()) return; } @@ -316,8 +306,7 @@ void SkiaPaintCanvas::drawBitmap(const SkBitmap& bitmap, const PaintFlags* flags) { if (flags) { ScopedRasterFlags raster_flags(flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -333,8 +322,7 @@ void SkiaPaintCanvas::drawTextBlob(scoped_refptr<PaintTextBlob> blob, SkScalar y, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + canvas_->getTotalMatrix(), 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); diff --git a/chromium/cc/paint/skia_paint_canvas.h b/chromium/cc/paint/skia_paint_canvas.h index d5f39f657e4..c9e1936733e 100644 --- a/chromium/cc/paint/skia_paint_canvas.h +++ b/chromium/cc/paint/skia_paint_canvas.h @@ -142,9 +142,6 @@ class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas { PlaybackParams::CustomDataRasterCallback custom_raster_callback); private: - // We always need skia shaders since the ops will be played on an SkCanvas. - static const bool kCreateSkiaShaders; - void WrapCanvasInColorSpaceXformCanvas( sk_sp<SkColorSpace> target_color_space); void FlushAfterDrawIfNeeded(); diff --git a/chromium/cc/paint/skia_paint_image_generator.cc b/chromium/cc/paint/skia_paint_image_generator.cc index 40b30df340f..d7b6c1a7e62 100644 --- a/chromium/cc/paint/skia_paint_image_generator.cc +++ b/chromium/cc/paint/skia_paint_image_generator.cc @@ -17,8 +17,8 @@ SkiaPaintImageGenerator::SkiaPaintImageGenerator( SkiaPaintImageGenerator::~SkiaPaintImageGenerator() = default; -SkData* SkiaPaintImageGenerator::onRefEncodedData() { - return paint_image_generator_->GetEncodedData().release(); +sk_sp<SkData> SkiaPaintImageGenerator::onRefEncodedData() { + return paint_image_generator_->GetEncodedData(); } bool SkiaPaintImageGenerator::onGetPixels(const SkImageInfo& info, diff --git a/chromium/cc/paint/skia_paint_image_generator.h b/chromium/cc/paint/skia_paint_image_generator.h index 97da522e806..859faf52298 100644 --- a/chromium/cc/paint/skia_paint_image_generator.h +++ b/chromium/cc/paint/skia_paint_image_generator.h @@ -18,7 +18,7 @@ class CC_PAINT_EXPORT SkiaPaintImageGenerator final : public SkImageGenerator { size_t frame_index); ~SkiaPaintImageGenerator() override; - SkData* onRefEncodedData() override; + sk_sp<SkData> onRefEncodedData() override; bool onGetPixels(const SkImageInfo&, void* pixels, size_t row_bytes, diff --git a/chromium/cc/paint/solid_color_analyzer.cc b/chromium/cc/paint/solid_color_analyzer.cc index 4e59ffde676..1863cfb3778 100644 --- a/chromium/cc/paint/solid_color_analyzer.cc +++ b/chromium/cc/paint/solid_color_analyzer.cc @@ -263,17 +263,20 @@ base::Optional<SkColor> SolidColorAnalyzer::DetermineIfSolidColor( break; } - // The rest of the ops should only affect our state canvas. + // Don't affect the canvas, so ignore. case PaintOpType::Annotate: - case PaintOpType::Concat: case PaintOpType::CustomData: + case PaintOpType::Noop: + break; + + // The rest of the ops should only affect our state canvas. + case PaintOpType::Concat: case PaintOpType::Scale: case PaintOpType::SetMatrix: case PaintOpType::Restore: case PaintOpType::Rotate: case PaintOpType::Save: case PaintOpType::Translate: - case PaintOpType::Noop: op->Raster(&canvas, params); break; } diff --git a/chromium/cc/paint/transfer_cache_deserialize_helper.h b/chromium/cc/paint/transfer_cache_deserialize_helper.h index 48d4c6f04b9..530b4795de9 100644 --- a/chromium/cc/paint/transfer_cache_deserialize_helper.h +++ b/chromium/cc/paint/transfer_cache_deserialize_helper.h @@ -32,16 +32,28 @@ class CC_PAINT_EXPORT TransferCacheDeserializeHelper { if (entry == nullptr) { return nullptr; } + + total_size_ += entry->CachedSize(); + // The service side entry is created using T::kType, so the class created is // guaranteed to make the entry type. DCHECK_EQ(entry->Type(), entry_type); return static_cast<T*>(entry); } + // Creates an entry directly. If an entry exists, it will be clobbered. + virtual void CreateLocalEntry( + uint32_t id, + std::unique_ptr<ServiceTransferCacheEntry> entry) = 0; + + size_t GetTotalEntrySizes() const { return total_size_; } + private: virtual ServiceTransferCacheEntry* GetEntryInternal( TransferCacheEntryType entry_type, uint32_t entry_id) = 0; + + size_t total_size_ = 0; }; }; // namespace cc diff --git a/chromium/cc/paint/transfer_cache_entry.cc b/chromium/cc/paint/transfer_cache_entry.cc index 46252c1850d..eb51292b2aa 100644 --- a/chromium/cc/paint/transfer_cache_entry.cc +++ b/chromium/cc/paint/transfer_cache_entry.cc @@ -10,7 +10,9 @@ #include "cc/paint/color_space_transfer_cache_entry.h" #include "cc/paint/image_transfer_cache_entry.h" #include "cc/paint/paint_typeface_transfer_cache_entry.h" +#include "cc/paint/path_transfer_cache_entry.h" #include "cc/paint/raw_memory_transfer_cache_entry.h" +#include "cc/paint/shader_transfer_cache_entry.h" namespace cc { @@ -25,6 +27,12 @@ std::unique_ptr<ServiceTransferCacheEntry> ServiceTransferCacheEntry::Create( return std::make_unique<ServicePaintTypefaceTransferCacheEntry>(); case TransferCacheEntryType::kColorSpace: return std::make_unique<ServiceColorSpaceTransferCacheEntry>(); + case TransferCacheEntryType::kPath: + return std::make_unique<ServicePathTransferCacheEntry>(); + case TransferCacheEntryType::kShader: + // ServiceShaderTransferCache is only created via CreateLocalEntry + // and is never serialized/deserialized. + return nullptr; } return nullptr; diff --git a/chromium/cc/paint/transfer_cache_entry.h b/chromium/cc/paint/transfer_cache_entry.h index 9ecde14aedc..474bd970344 100644 --- a/chromium/cc/paint/transfer_cache_entry.h +++ b/chromium/cc/paint/transfer_cache_entry.h @@ -24,8 +24,10 @@ enum class TransferCacheEntryType : uint32_t { kImage, kPaintTypeface, kColorSpace, + kPath, + kShader, // Add new entries above this line, make sure to update kLast. - kLast = kColorSpace, + kLast = kShader, }; // An interface used on the client to serialize a transfer cache entry diff --git a/chromium/cc/paint/transfer_cache_unittest.cc b/chromium/cc/paint/transfer_cache_unittest.cc index 4c1ea2875e8..d8fb589c35d 100644 --- a/chromium/cc/paint/transfer_cache_unittest.cc +++ b/chromium/cc/paint/transfer_cache_unittest.cc @@ -14,12 +14,12 @@ #include "gpu/command_buffer/client/client_transfer_cache.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_implementation.h" -#include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/client/raster_interface.h" #include "gpu/command_buffer/client/shared_memory_limits.h" #include "gpu/command_buffer/common/context_creation_attribs.h" #include "gpu/command_buffer/service/service_transfer_cache.h" #include "gpu/config/gpu_switches.h" -#include "gpu/ipc/gl_in_process_context.h" +#include "gpu/ipc/raster_in_process_context.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkImage.h" #include "ui/gl/gl_implementation.h" @@ -29,10 +29,9 @@ namespace { class TransferCacheTest : public testing::Test { public: - TransferCacheTest() - : testing::Test(), test_client_entry_(std::vector<uint8_t>(100)) {} + TransferCacheTest() : test_client_entry_(std::vector<uint8_t>(100)) {} + void SetUp() override { - bool is_offscreen = true; gpu::ContextCreationAttribs attribs; attribs.alpha_size = -1; attribs.depth_size = 24; @@ -43,21 +42,15 @@ class TransferCacheTest : public testing::Test { attribs.bind_generates_resource = false; // Enable OOP rasterization. attribs.enable_oop_rasterization = true; + attribs.enable_raster_interface = true; + attribs.enable_gles2_interface = false; - // Add an OOP rasterization command line flag so that we set - // |chromium_raster_transport| features flag. - // TODO(vmpstr): Is there a better way to do this? - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableOOPRasterization)) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableOOPRasterization); - } - - context_ = gpu::GLInProcessContext::CreateWithoutInit(); + context_ = std::make_unique<gpu::RasterInProcessContext>(); auto result = context_->Initialize( - nullptr, nullptr, is_offscreen, gpu::kNullSurfaceHandle, nullptr, - attribs, gpu::SharedMemoryLimits(), &gpu_memory_buffer_manager_, - &image_factory_, nullptr, base::ThreadTaskRunnerHandle::Get()); + /*service=*/nullptr, attribs, gpu::SharedMemoryLimits(), + &gpu_memory_buffer_manager_, &image_factory_, + /*gpu_channel_manager_delegate=*/nullptr, + base::ThreadTaskRunnerHandle::Get()); ASSERT_EQ(result, gpu::ContextResult::kSuccess); ASSERT_TRUE(context_->GetCapabilities().supports_oop_raster); @@ -69,12 +62,10 @@ class TransferCacheTest : public testing::Test { return context_->GetTransferCacheForTest(); } - gpu::gles2::GLES2Implementation* Gl() { - return context_->GetImplementation(); - } + gpu::raster::RasterInterface* ri() { return context_->GetImplementation(); } gpu::ContextSupport* ContextSupport() { - return context_->GetImplementation(); + return context_->GetContextSupport(); } const ClientRawMemoryTransferCacheEntry& test_client_entry() const { @@ -93,20 +84,19 @@ class TransferCacheTest : public testing::Test { private: viz::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; TestImageFactory image_factory_; - std::unique_ptr<gpu::GLInProcessContext> context_; + std::unique_ptr<gpu::RasterInProcessContext> context_; gl::DisableNullDrawGLBindings enable_pixel_output_; ClientRawMemoryTransferCacheEntry test_client_entry_; }; TEST_F(TransferCacheTest, Basic) { auto* service_cache = ServiceTransferCache(); - auto* gl = Gl(); auto* context_support = ContextSupport(); // Create an entry. const auto& entry = test_client_entry(); CreateEntry(entry); - gl->Finish(); + ri()->Finish(); // Validate service-side state. EXPECT_NE(nullptr, service_cache->GetEntry(entry.Type(), entry.Id())); @@ -114,7 +104,7 @@ TEST_F(TransferCacheTest, Basic) { // Unlock on client side and flush to service. context_support->UnlockTransferCacheEntries( {{entry.UnsafeType(), entry.Id()}}); - gl->Finish(); + ri()->Finish(); // Re-lock on client side and validate state. No need to flush as lock is // local. @@ -123,19 +113,18 @@ TEST_F(TransferCacheTest, Basic) { // Delete on client side, flush, and validate that deletion reaches service. context_support->DeleteTransferCacheEntry(entry.UnsafeType(), entry.Id()); - gl->Finish(); + ri()->Finish(); EXPECT_EQ(nullptr, service_cache->GetEntry(entry.Type(), entry.Id())); } TEST_F(TransferCacheTest, Eviction) { auto* service_cache = ServiceTransferCache(); - auto* gl = Gl(); auto* context_support = ContextSupport(); const auto& entry = test_client_entry(); // Create an entry. CreateEntry(entry); - gl->Finish(); + ri()->Finish(); // Validate service-side state. EXPECT_NE(nullptr, service_cache->GetEntry(entry.Type(), entry.Id())); @@ -143,7 +132,7 @@ TEST_F(TransferCacheTest, Eviction) { // Unlock on client side and flush to service. context_support->UnlockTransferCacheEntries( {{entry.UnsafeType(), entry.Id()}}); - gl->Finish(); + ri()->Finish(); // Evict on the service side. service_cache->SetCacheSizeLimitForTesting(0); @@ -156,7 +145,6 @@ TEST_F(TransferCacheTest, Eviction) { TEST_F(TransferCacheTest, RawMemoryTransfer) { auto* service_cache = ServiceTransferCache(); - auto* gl = Gl(); // Create an entry with some initialized data. std::vector<uint8_t> data; @@ -168,7 +156,7 @@ TEST_F(TransferCacheTest, RawMemoryTransfer) { // Add the entry to the transfer cache ClientRawMemoryTransferCacheEntry client_entry(data); CreateEntry(client_entry); - gl->Finish(); + ri()->Finish(); // Validate service-side data matches. ServiceTransferCacheEntry* service_entry = @@ -186,7 +174,6 @@ TEST_F(TransferCacheTest, ImageMemoryTransfer) { #endif auto* service_cache = ServiceTransferCache(); - auto* gl = Gl(); // Create a 10x10 image. SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); @@ -200,7 +187,7 @@ TEST_F(TransferCacheTest, ImageMemoryTransfer) { // Add the entry to the transfer cache ClientImageTransferCacheEntry client_entry(&pixmap, nullptr); CreateEntry(client_entry); - gl->Finish(); + ri()->Finish(); // Validate service-side data matches. ServiceTransferCacheEntry* service_entry = diff --git a/chromium/cc/raster/bitmap_raster_buffer_provider.cc b/chromium/cc/raster/bitmap_raster_buffer_provider.cc index ae5744092af..c801facce0e 100644 --- a/chromium/cc/raster/bitmap_raster_buffer_provider.cc +++ b/chromium/cc/raster/bitmap_raster_buffer_provider.cc @@ -14,7 +14,6 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/raster/raster_source.h" -#include "cc/resources/resource.h" #include "cc/trees/layer_tree_frame_sink.h" #include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/resources/platform_color.h" @@ -70,7 +69,7 @@ class BitmapRasterBufferImpl : public RasterBuffer { RasterBufferProvider::PlaybackToMemory( pixels_, viz::RGBA_8888, resource_size_, stride, raster_source, raster_full_rect, playback_rect, transform, color_space_, - playback_settings); + /*gpu_compositing=*/false, playback_settings); } private: @@ -124,19 +123,18 @@ BitmapRasterBufferProvider::AcquireBufferForRaster( void BitmapRasterBufferProvider::Flush() {} -viz::ResourceFormat BitmapRasterBufferProvider::GetResourceFormat( - bool must_support_alpha) const { +viz::ResourceFormat BitmapRasterBufferProvider::GetResourceFormat() const { return viz::RGBA_8888; } -bool BitmapRasterBufferProvider::IsResourceSwizzleRequired( - bool must_support_alpha) const { - // GetResourceFormat() returns a constant so use it directly. - return ResourceFormatRequiresSwizzle(viz::RGBA_8888); +bool BitmapRasterBufferProvider::IsResourceSwizzleRequired() const { + // This value only used by gpu compositing. Software compositing resources + // are all in the native skia byte ordering, and the display compositor will + // do its drawing in the same order. + return false; } -bool BitmapRasterBufferProvider::IsResourcePremultiplied( - bool must_support_alpha) const { +bool BitmapRasterBufferProvider::IsResourcePremultiplied() const { return true; } diff --git a/chromium/cc/raster/bitmap_raster_buffer_provider.h b/chromium/cc/raster/bitmap_raster_buffer_provider.h index 1f33b863b5b..5174176fd11 100644 --- a/chromium/cc/raster/bitmap_raster_buffer_provider.h +++ b/chromium/cc/raster/bitmap_raster_buffer_provider.h @@ -32,9 +32,9 @@ class CC_EXPORT BitmapRasterBufferProvider : public RasterBufferProvider { uint64_t resource_content_id, uint64_t previous_content_id) override; void Flush() override; - viz::ResourceFormat GetResourceFormat(bool must_support_alpha) const override; - bool IsResourceSwizzleRequired(bool must_support_alpha) const override; - bool IsResourcePremultiplied(bool must_support_alpha) const override; + viz::ResourceFormat GetResourceFormat() const override; + bool IsResourceSwizzleRequired() const override; + bool IsResourcePremultiplied() const override; bool CanPartialRasterIntoProvidedResource() const override; bool IsResourceReadyToDraw( const ResourcePool::InUsePoolResource& resource) const override; diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.cc b/chromium/cc/raster/gpu_raster_buffer_provider.cc index ba2abde1adc..f449095504c 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.cc +++ b/chromium/cc/raster/gpu_raster_buffer_provider.cc @@ -17,7 +17,7 @@ #include "cc/paint/paint_recorder.h" #include "cc/raster/raster_source.h" #include "cc/raster/scoped_gpu_raster.h" -#include "cc/resources/resource.h" +#include "cc/resources/layer_tree_resource_provider.h" #include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/gpu/raster_context_provider.h" #include "components/viz/common/gpu/texture_allocation.h" @@ -27,7 +27,6 @@ #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/raster_interface.h" #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" -#include "skia/ext/texture_handle.h" #include "third_party/skia/include/core/SkMultiPictureDraw.h" #include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/core/SkSurface.h" @@ -85,12 +84,17 @@ class ScopedSkSurfaceForUnpremultiplyAndDither { if (!surface_) return; - GrBackendObject handle = - surface_->getTextureHandle(SkSurface::kFlushRead_BackendHandleAccess); - const GrGLTextureInfo* info = - skia::GrBackendObjectToGrGLTextureInfo(handle); + GrBackendTexture backend_texture = + surface_->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess); + if (!backend_texture.isValid()) { + return; + } + GrGLTextureInfo info; + if (!backend_texture.getGLTextureInfo(&info)) { + return; + } context_provider_->ContextGL()->UnpremultiplyAndDitherCopyCHROMIUM( - info->fID, texture_id_, offset_.x(), offset_.y(), size_.width(), + info.fID, texture_id_, offset_.x(), offset_.y(), size_.width(), size_.height()); } @@ -134,11 +138,11 @@ static void RasterizeSourceOOP( // TODO(enne): Use the |texture_target|? GpuMemoryBuffer backed textures don't // use GL_TEXTURE_2D. - ri->BeginRasterCHROMIUM( - texture_id, raster_source->background_color(), msaa_sample_count, - playback_settings.use_lcd_text, - viz::ResourceFormatToClosestSkColorType(resource_format), - playback_settings.raster_color_space); + ri->BeginRasterCHROMIUM(texture_id, raster_source->background_color(), + msaa_sample_count, playback_settings.use_lcd_text, + viz::ResourceFormatToClosestSkColorType( + /*gpu_compositing=*/true, resource_format), + playback_settings.raster_color_space); float recording_to_raster_scale = transform.scale() / raster_source->recording_scale_factor(); gfx::Size content_size = raster_source->GetContentSize(transform.scale()); @@ -336,19 +340,17 @@ void GpuRasterBufferProvider::RasterBufferImpl::Playback( GpuRasterBufferProvider::GpuRasterBufferProvider( viz::ContextProvider* compositor_context_provider, viz::RasterContextProvider* worker_context_provider, - LayerTreeResourceProvider* resource_provider, bool use_gpu_memory_buffer_resources, int gpu_rasterization_msaa_sample_count, - viz::ResourceFormat preferred_tile_format, + viz::ResourceFormat tile_format, const gfx::Size& max_tile_size, bool unpremultiply_and_dither_low_bit_depth_tiles, bool enable_oop_rasterization) : compositor_context_provider_(compositor_context_provider), worker_context_provider_(worker_context_provider), - resource_provider_(resource_provider), use_gpu_memory_buffer_resources_(use_gpu_memory_buffer_resources), msaa_sample_count_(gpu_rasterization_msaa_sample_count), - preferred_tile_format_(preferred_tile_format), + tile_format_(tile_format), max_tile_size_(max_tile_size), unpremultiply_and_dither_low_bit_depth_tiles_( unpremultiply_and_dither_low_bit_depth_tiles), @@ -399,28 +401,17 @@ void GpuRasterBufferProvider::Flush() { compositor_context_provider_->ContextSupport()->FlushPendingWork(); } -viz::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(); +viz::ResourceFormat GpuRasterBufferProvider::GetResourceFormat() const { + return tile_format_; } -bool GpuRasterBufferProvider::IsResourceSwizzleRequired( - bool must_support_alpha) const { +bool GpuRasterBufferProvider::IsResourceSwizzleRequired() const { // This doesn't require a swizzle because we rasterize to the correct format. return false; } -bool GpuRasterBufferProvider::IsResourcePremultiplied( - bool must_support_alpha) const { - return !ShouldUnpremultiplyAndDitherResource( - GetResourceFormat(must_support_alpha)); +bool GpuRasterBufferProvider::IsResourcePremultiplied() const { + return !ShouldUnpremultiplyAndDitherResource(GetResourceFormat()); } bool GpuRasterBufferProvider::CanPartialRasterIntoProvidedResource() const { diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.h b/chromium/cc/raster/gpu_raster_buffer_provider.h index c019d77fa07..67881acd682 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.h +++ b/chromium/cc/raster/gpu_raster_buffer_provider.h @@ -9,7 +9,6 @@ #include "base/macros.h" #include "cc/raster/raster_buffer_provider.h" -#include "cc/resources/layer_tree_resource_provider.h" #include "gpu/command_buffer/common/sync_token.h" namespace viz { @@ -23,10 +22,9 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { public: GpuRasterBufferProvider(viz::ContextProvider* compositor_context_provider, viz::RasterContextProvider* worker_context_provider, - LayerTreeResourceProvider* resource_provider, bool use_gpu_memory_buffer_resources, int gpu_rasterization_msaa_sample_count, - viz::ResourceFormat preferred_tile_format, + viz::ResourceFormat tile_format, const gfx::Size& max_tile_size, bool unpremultiply_and_dither_low_bit_depth_tiles, bool enable_oop_rasterization); @@ -38,9 +36,9 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { uint64_t resource_content_id, uint64_t previous_content_id) override; void Flush() override; - viz::ResourceFormat GetResourceFormat(bool must_support_alpha) const override; - bool IsResourceSwizzleRequired(bool must_support_alpha) const override; - bool IsResourcePremultiplied(bool must_support_alpha) const override; + viz::ResourceFormat GetResourceFormat() const override; + bool IsResourceSwizzleRequired() const override; + bool IsResourcePremultiplied() const override; bool CanPartialRasterIntoProvidedResource() const override; bool IsResourceReadyToDraw( const ResourcePool::InUsePoolResource& resource) const override; @@ -114,10 +112,9 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { viz::ContextProvider* const compositor_context_provider_; viz::RasterContextProvider* const worker_context_provider_; - LayerTreeResourceProvider* const resource_provider_; const bool use_gpu_memory_buffer_resources_; const int msaa_sample_count_; - const viz::ResourceFormat preferred_tile_format_; + const viz::ResourceFormat tile_format_; const gfx::Size max_tile_size_; const bool unpremultiply_and_dither_low_bit_depth_tiles_; const bool enable_oop_rasterization_; diff --git a/chromium/cc/raster/one_copy_raster_buffer_provider.cc b/chromium/cc/raster/one_copy_raster_buffer_provider.cc index fdf03d5db1d..90f94f65055 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.cc @@ -74,7 +74,7 @@ class OneCopyRasterBufferProvider::OneCopyGpuBacking OneCopyRasterBufferProvider::RasterBufferImpl::RasterBufferImpl( OneCopyRasterBufferProvider* client, - LayerTreeResourceProvider* resource_provider, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, const ResourcePool::InUsePoolResource& in_use_resource, OneCopyGpuBacking* backing, uint64_t previous_content_id) @@ -127,15 +127,15 @@ OneCopyRasterBufferProvider::OneCopyRasterBufferProvider( scoped_refptr<base::SequencedTaskRunner> task_runner, viz::ContextProvider* compositor_context_provider, viz::RasterContextProvider* worker_context_provider, - LayerTreeResourceProvider* resource_provider, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, int max_copy_texture_chromium_size, bool use_partial_raster, bool use_gpu_memory_buffer_resources, int max_staging_buffer_usage_in_bytes, - viz::ResourceFormat preferred_tile_format) + viz::ResourceFormat tile_format) : compositor_context_provider_(compositor_context_provider), worker_context_provider_(worker_context_provider), - resource_provider_(resource_provider), + gpu_memory_buffer_manager_(gpu_memory_buffer_manager), max_bytes_per_copy_operation_( max_copy_texture_chromium_size ? std::min(kMaxBytesPerCopyOperation, @@ -144,10 +144,9 @@ OneCopyRasterBufferProvider::OneCopyRasterBufferProvider( use_partial_raster_(use_partial_raster), use_gpu_memory_buffer_resources_(use_gpu_memory_buffer_resources), bytes_scheduled_since_last_flush_(0), - preferred_tile_format_(preferred_tile_format), + tile_format_(tile_format), staging_pool_(std::move(task_runner), worker_context_provider, - resource_provider, use_partial_raster, max_staging_buffer_usage_in_bytes) { DCHECK(compositor_context_provider); @@ -188,8 +187,8 @@ OneCopyRasterBufferProvider::AcquireBufferForRaster( static_cast<OneCopyGpuBacking*>(resource.gpu_backing()); // TODO(danakj): If resource_content_id != 0, we only need to copy/upload // the dirty rect. - return std::make_unique<RasterBufferImpl>(this, resource_provider_, resource, - backing, previous_content_id); + return std::make_unique<RasterBufferImpl>( + this, gpu_memory_buffer_manager_, resource, backing, previous_content_id); } void OneCopyRasterBufferProvider::Flush() { @@ -201,24 +200,15 @@ void OneCopyRasterBufferProvider::Flush() { compositor_context_provider_->ContextSupport()->FlushPendingWork(); } -viz::ResourceFormat OneCopyRasterBufferProvider::GetResourceFormat( - bool must_support_alpha) const { - if (resource_provider_->IsTextureFormatSupported(preferred_tile_format_) && - (DoesResourceFormatSupportAlpha(preferred_tile_format_) || - !must_support_alpha)) { - return preferred_tile_format_; - } - - return resource_provider_->best_texture_format(); +viz::ResourceFormat OneCopyRasterBufferProvider::GetResourceFormat() const { + return tile_format_; } -bool OneCopyRasterBufferProvider::IsResourceSwizzleRequired( - bool must_support_alpha) const { - return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); +bool OneCopyRasterBufferProvider::IsResourceSwizzleRequired() const { + return !viz::PlatformColor::SameComponentOrder(GetResourceFormat()); } -bool OneCopyRasterBufferProvider::IsResourcePremultiplied( - bool must_support_alpha) const { +bool OneCopyRasterBufferProvider::IsResourcePremultiplied() const { // TODO(ericrk): Handle unpremultiply/dither in one-copy case as well. // https://crbug.com/789153 return true; @@ -323,7 +313,7 @@ void OneCopyRasterBufferProvider::PlaybackToStagingBuffer( // must allocate a buffer with BufferUsage CPU_READ_WRITE_PERSISTENT. if (!staging_buffer->gpu_memory_buffer) { staging_buffer->gpu_memory_buffer = - resource_provider_->gpu_memory_buffer_manager()->CreateGpuMemoryBuffer( + gpu_memory_buffer_manager_->CreateGpuMemoryBuffer( staging_buffer->size, BufferFormat(format), StagingBufferUsage(), gpu::kNullSurfaceHandle); } @@ -364,7 +354,7 @@ void OneCopyRasterBufferProvider::PlaybackToStagingBuffer( RasterBufferProvider::PlaybackToMemory( buffer->memory(0), format, staging_buffer->size, buffer->stride(0), raster_source, raster_full_rect, playback_rect, transform, - dst_color_space, playback_settings); + dst_color_space, /*gpu_compositing=*/true, playback_settings); buffer->Unmap(); staging_buffer->content_id = new_content_id; } @@ -438,7 +428,7 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread( // TODO(vmiura): Need a way to ensure we don't hold onto bindings? // ri->BindTexture(image_target, 0); - if (resource_provider_->use_sync_query()) { + if (worker_context_provider_->ContextCapabilities().sync_query) { if (!staging_buffer->query_id) ri->GenQueriesEXT(1, &staging_buffer->query_id); @@ -485,7 +475,7 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread( } } - if (resource_provider_->use_sync_query()) { + if (worker_context_provider_->ContextCapabilities().sync_query) { #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) ri->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); #else diff --git a/chromium/cc/raster/one_copy_raster_buffer_provider.h b/chromium/cc/raster/one_copy_raster_buffer_provider.h index 7e1fac1bab7..3c823596cba 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.h +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.h @@ -8,11 +8,16 @@ #include <stdint.h> #include "base/macros.h" +#include "base/sequenced_task_runner.h" #include "cc/raster/raster_buffer_provider.h" #include "cc/raster/staging_buffer_pool.h" #include "cc/resources/layer_tree_resource_provider.h" #include "gpu/command_buffer/common/sync_token.h" +namespace gpu { +class GpuMemoryBufferManager; +} + namespace viz { class ContextProvider; class RasterContextProvider; @@ -28,12 +33,12 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { scoped_refptr<base::SequencedTaskRunner> task_runner, viz::ContextProvider* compositor_context_provider, viz::RasterContextProvider* worker_context_provider, - LayerTreeResourceProvider* resource_provider, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, int max_copy_texture_chromium_size, bool use_partial_raster, bool use_gpu_memory_buffer_resources, int max_staging_buffer_usage_in_bytes, - viz::ResourceFormat preferred_tile_format); + viz::ResourceFormat tile_format); ~OneCopyRasterBufferProvider() override; // Overridden from RasterBufferProvider: @@ -42,9 +47,9 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { uint64_t resource_content_id, uint64_t previous_content_id) override; void Flush() override; - viz::ResourceFormat GetResourceFormat(bool must_support_alpha) const override; - bool IsResourceSwizzleRequired(bool must_support_alpha) const override; - bool IsResourcePremultiplied(bool must_support_alpha) const override; + viz::ResourceFormat GetResourceFormat() const override; + bool IsResourceSwizzleRequired() const override; + bool IsResourcePremultiplied() const override; bool CanPartialRasterIntoProvidedResource() const override; bool IsResourceReadyToDraw( const ResourcePool::InUsePoolResource& resource) const override; @@ -78,7 +83,7 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { class RasterBufferImpl : public RasterBuffer { public: RasterBufferImpl(OneCopyRasterBufferProvider* client, - LayerTreeResourceProvider* resource_provider, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, const ResourcePool::InUsePoolResource& in_use_resource, OneCopyGpuBacking* backing, uint64_t previous_content_id); @@ -142,7 +147,7 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { viz::ContextProvider* const compositor_context_provider_; viz::RasterContextProvider* const worker_context_provider_; - LayerTreeResourceProvider* const resource_provider_; + gpu::GpuMemoryBufferManager* const gpu_memory_buffer_manager_; const int max_bytes_per_copy_operation_; const bool use_partial_raster_; const bool use_gpu_memory_buffer_resources_; @@ -150,7 +155,7 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { // Context lock must be acquired when accessing this member. int bytes_scheduled_since_last_flush_; - const viz::ResourceFormat preferred_tile_format_; + const viz::ResourceFormat tile_format_; StagingBufferPool staging_pool_; DISALLOW_COPY_AND_ASSIGN(OneCopyRasterBufferProvider); diff --git a/chromium/cc/raster/raster_buffer_provider.cc b/chromium/cc/raster/raster_buffer_provider.cc index 1cef94610f9..873a432e0ef 100644 --- a/chromium/cc/raster/raster_buffer_provider.cc +++ b/chromium/cc/raster/raster_buffer_provider.cc @@ -57,6 +57,7 @@ void RasterBufferProvider::PlaybackToMemory( const gfx::Rect& canvas_playback_rect, const gfx::AxisTransform2d& transform, const gfx::ColorSpace& target_color_space, + bool gpu_compositing, const RasterSource::PlaybackSettings& playback_settings) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "RasterBufferProvider::PlaybackToMemory"); @@ -97,8 +98,7 @@ void RasterBufferProvider::PlaybackToMemory( playback_settings); return; } - case viz::RGBA_4444: - case viz::ETC1: { + case viz::RGBA_4444: { 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 @@ -122,13 +122,14 @@ void RasterBufferProvider::PlaybackToMemory( } else { TRACE_EVENT0("cc", "RasterBufferProvider::PlaybackToMemory::ConvertRGBA4444"); - SkImageInfo dst_info = - info.makeColorType(ResourceFormatToClosestSkColorType(format)); + SkImageInfo dst_info = info.makeColorType( + ResourceFormatToClosestSkColorType(gpu_compositing, format)); bool rv = surface->readPixels(dst_info, memory, stride, 0, 0); DCHECK(rv); } return; } + case viz::ETC1: case viz::ALPHA_8: case viz::LUMINANCE_8: case viz::RGB_565: @@ -142,27 +143,4 @@ void RasterBufferProvider::PlaybackToMemory( NOTREACHED(); } -bool RasterBufferProvider::ResourceFormatRequiresSwizzle( - viz::ResourceFormat format) { - switch (format) { - case viz::RGBA_8888: - case viz::BGRA_8888: - // Initialize resource using the preferred viz::PlatformColor component - // order and swizzle in the shader instead of in software. - return !viz::PlatformColor::SameComponentOrder(format); - case viz::RGBA_4444: - case viz::ETC1: - case viz::ALPHA_8: - case viz::LUMINANCE_8: - case viz::RGB_565: - case viz::RED_8: - case viz::LUMINANCE_F16: - case viz::RGBA_F16: - case viz::R16_EXT: - return false; - } - NOTREACHED(); - return false; -} - } // namespace cc diff --git a/chromium/cc/raster/raster_buffer_provider.h b/chromium/cc/raster/raster_buffer_provider.h index 12b7e0d80da..3e2b1aaeb50 100644 --- a/chromium/cc/raster/raster_buffer_provider.h +++ b/chromium/cc/raster/raster_buffer_provider.h @@ -12,7 +12,6 @@ #include "cc/raster/task_graph_runner.h" #include "cc/raster/tile_task.h" #include "cc/resources/resource_pool.h" -#include "cc/resources/resource_provider.h" #include "components/viz/common/resources/resource_format.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -31,6 +30,9 @@ class CC_EXPORT RasterBufferProvider { // that will cover the resulting |memory|. The |canvas_playback_rect| can be a // smaller contained rect inside the |canvas_bitmap_rect| if the |memory| is // already partially complete, and only the subrect needs to be played back. + // Set |gpu_compositing| to true if the compositor is using gpu, as we respect + // the format more accurately, vs in software compositing where the format is + // a placeholder for the skia native format. static void PlaybackToMemory( void* memory, viz::ResourceFormat format, @@ -41,6 +43,7 @@ class CC_EXPORT RasterBufferProvider { const gfx::Rect& canvas_playback_rect, const gfx::AxisTransform2d& transform, const gfx::ColorSpace& target_color_space, + bool gpu_compositing, const RasterSource::PlaybackSettings& playback_settings); // Acquire raster buffer. @@ -56,14 +59,13 @@ class CC_EXPORT RasterBufferProvider { virtual void Flush() = 0; // Returns the format to use for the tiles. - virtual viz::ResourceFormat GetResourceFormat( - bool must_support_alpha) const = 0; + virtual viz::ResourceFormat GetResourceFormat() const = 0; // Determine if the resource requires swizzling. - virtual bool IsResourceSwizzleRequired(bool must_support_alpha) const = 0; + virtual bool IsResourceSwizzleRequired() const = 0; // Determines if the resource is premultiplied. - virtual bool IsResourcePremultiplied(bool must_support_alpha) const = 0; + virtual bool IsResourcePremultiplied() const = 0; // Determine if the RasterBufferProvider can handle partial raster into // the Resource provided in AcquireBufferForRaster. @@ -86,10 +88,6 @@ class CC_EXPORT RasterBufferProvider { // Shutdown for doing cleanup. virtual void Shutdown() = 0; - - protected: - // Check if resource format matches output format. - static bool ResourceFormatRequiresSwizzle(viz::ResourceFormat format); }; } // namespace cc diff --git a/chromium/cc/raster/raster_buffer_provider_perftest.cc b/chromium/cc/raster/raster_buffer_provider_perftest.cc index 4d96efeb552..a91d3bef29d 100644 --- a/chromium/cc/raster/raster_buffer_provider_perftest.cc +++ b/chromium/cc/raster/raster_buffer_provider_perftest.cc @@ -16,8 +16,8 @@ #include "cc/raster/raster_buffer_provider.h" #include "cc/raster/synchronous_task_graph_runner.h" #include "cc/raster/zero_copy_raster_buffer_provider.h" +#include "cc/resources/layer_tree_resource_provider.h" #include "cc/resources/resource_pool.h" -#include "cc/resources/resource_provider.h" #include "cc/test/fake_layer_tree_frame_sink.h" #include "cc/test/fake_resource_provider.h" #include "cc/tiles/tile_task_manager.h" @@ -87,7 +87,7 @@ class PerfContextProvider capabilities_.sync_query = true; raster_context_ = std::make_unique<gpu::raster::RasterImplementationGLES>( - context_gl_.get(), &support_, capabilities_); + context_gl_.get(), nullptr, capabilities_); } // viz::ContextProvider implementation. @@ -350,51 +350,34 @@ class RasterBufferProviderPerfTest Create3dResourceProvider(); raster_buffer_provider_ = std::make_unique<ZeroCopyRasterBufferProvider>( - resource_provider_.get(), &gpu_memory_buffer_manager_, - compositor_context_provider_.get(), - viz::PlatformColor::BestTextureFormat()); - resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), task_runner_, - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu, - false); + &gpu_memory_buffer_manager_, compositor_context_provider_.get(), + viz::RGBA_8888); break; case RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY: Create3dResourceProvider(); raster_buffer_provider_ = std::make_unique<OneCopyRasterBufferProvider>( task_runner_.get(), compositor_context_provider_.get(), - worker_context_provider_.get(), resource_provider_.get(), + worker_context_provider_.get(), &gpu_memory_buffer_manager_, std::numeric_limits<int>::max(), false, false, - std::numeric_limits<int>::max(), - viz::PlatformColor::BestTextureFormat()); - resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), task_runner_, - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu, - false); + std::numeric_limits<int>::max(), viz::RGBA_8888); break; case RASTER_BUFFER_PROVIDER_TYPE_GPU: Create3dResourceProvider(); raster_buffer_provider_ = std::make_unique<GpuRasterBufferProvider>( compositor_context_provider_.get(), worker_context_provider_.get(), - resource_provider_.get(), false, 0, - viz::PlatformColor::BestTextureFormat(), gfx::Size(), true, false); - resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), task_runner_, - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu, - false); + false, 0, viz::RGBA_8888, gfx::Size(), true, false); break; case RASTER_BUFFER_PROVIDER_TYPE_BITMAP: CreateSoftwareResourceProvider(); raster_buffer_provider_ = std::make_unique<BitmapRasterBufferProvider>( layer_tree_frame_sink_.get()); - resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), task_runner_, - ResourcePool::kDefaultExpirationDelay, - ResourcePool::Mode::kSoftware, false); break; } - DCHECK(raster_buffer_provider_); + resource_pool_ = std::make_unique<ResourcePool>( + resource_provider_.get(), compositor_context_provider_.get(), + task_runner_, ResourcePool::kDefaultExpirationDelay, false); tile_task_manager_ = TileTaskManagerImpl::Create(task_graph_runner_.get()); } void TearDown() override { @@ -519,14 +502,13 @@ class RasterBufferProviderPerfTest private: void Create3dResourceProvider() { resource_provider_ = FakeResourceProvider::CreateLayerTreeResourceProvider( - compositor_context_provider_.get(), nullptr, - &gpu_memory_buffer_manager_); + compositor_context_provider_.get()); } void CreateSoftwareResourceProvider() { layer_tree_frame_sink_ = FakeLayerTreeFrameSink::CreateSoftware(); - resource_provider_ = FakeResourceProvider::CreateLayerTreeResourceProvider( - nullptr, layer_tree_frame_sink_->shared_bitmap_manager(), nullptr); + resource_provider_ = + FakeResourceProvider::CreateLayerTreeResourceProvider(nullptr); } std::string TestModifierString() const { @@ -590,10 +572,10 @@ class RasterBufferProviderCommonPerfTest // Overridden from testing::Test: void SetUp() override { resource_provider_ = FakeResourceProvider::CreateLayerTreeResourceProvider( - compositor_context_provider_.get(), nullptr); + compositor_context_provider_.get()); resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), task_runner_, - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu, false); + resource_provider_.get(), compositor_context_provider_.get(), + task_runner_, ResourcePool::kDefaultExpirationDelay, false); } void RunBuildTileTaskGraphTest(const std::string& test_name, diff --git a/chromium/cc/raster/raster_buffer_provider_unittest.cc b/chromium/cc/raster/raster_buffer_provider_unittest.cc index 4bc78099834..c50e739199c 100644 --- a/chromium/cc/raster/raster_buffer_provider_unittest.cc +++ b/chromium/cc/raster/raster_buffer_provider_unittest.cc @@ -14,7 +14,6 @@ #include "base/cancelable_callback.h" #include "base/location.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -25,8 +24,8 @@ #include "cc/raster/one_copy_raster_buffer_provider.h" #include "cc/raster/synchronous_task_graph_runner.h" #include "cc/raster/zero_copy_raster_buffer_provider.h" +#include "cc/resources/layer_tree_resource_provider.h" #include "cc/resources/resource_pool.h" -#include "cc/resources/resource_provider.h" #include "cc/test/fake_layer_tree_frame_sink.h" #include "cc/test/fake_raster_source.h" #include "cc/test/fake_resource_provider.h" @@ -34,7 +33,6 @@ #include "components/viz/common/resources/platform_color.h" #include "components/viz/test/test_context_provider.h" #include "components/viz/test/test_gpu_memory_buffer_manager.h" -#include "components/viz/test/test_shared_bitmap_manager.h" #include "components/viz/test/test_web_graphics_context_3d.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/raster_interface.h" @@ -158,46 +156,35 @@ class RasterBufferProviderTest Create3dResourceProvider(); raster_buffer_provider_ = std::make_unique<ZeroCopyRasterBufferProvider>( - resource_provider_.get(), &gpu_memory_buffer_manager_, - context_provider_.get(), - viz::PlatformColor::BestTextureFormat()); - pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), base::ThreadTaskRunnerHandle::Get(), - base::TimeDelta(), ResourcePool::Mode::kGpu, true); + &gpu_memory_buffer_manager_, context_provider_.get(), + viz::RGBA_8888); break; case RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY: Create3dResourceProvider(); raster_buffer_provider_ = std::make_unique<OneCopyRasterBufferProvider>( base::ThreadTaskRunnerHandle::Get().get(), context_provider_.get(), - worker_context_provider_.get(), resource_provider_.get(), + worker_context_provider_.get(), &gpu_memory_buffer_manager_, kMaxBytesPerCopyOperation, false, false, kMaxStagingBuffers, - viz::PlatformColor::BestTextureFormat()); - pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), base::ThreadTaskRunnerHandle::Get(), - base::TimeDelta(), ResourcePool::Mode::kGpu, true); + viz::RGBA_8888); break; case RASTER_BUFFER_PROVIDER_TYPE_GPU: Create3dResourceProvider(); raster_buffer_provider_ = std::make_unique<GpuRasterBufferProvider>( - context_provider_.get(), worker_context_provider_.get(), - resource_provider_.get(), false, 0, - viz::PlatformColor::BestTextureFormat(), gfx::Size(), true, false); - pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), base::ThreadTaskRunnerHandle::Get(), - base::TimeDelta(), ResourcePool::Mode::kGpu, true); + context_provider_.get(), worker_context_provider_.get(), false, 0, + viz::RGBA_8888, gfx::Size(), true, false); break; case RASTER_BUFFER_PROVIDER_TYPE_BITMAP: CreateSoftwareResourceProvider(); raster_buffer_provider_ = std::make_unique<BitmapRasterBufferProvider>( layer_tree_frame_sink_.get()); - pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), base::ThreadTaskRunnerHandle::Get(), - base::TimeDelta(), ResourcePool::Mode::kSoftware, true); break; } DCHECK(raster_buffer_provider_); + pool_ = std::make_unique<ResourcePool>( + resource_provider_.get(), context_provider_.get(), + base::ThreadTaskRunnerHandle::Get(), base::TimeDelta(), true); tile_task_manager_ = TileTaskManagerImpl::Create(&task_graph_runner_); } @@ -305,22 +292,20 @@ class RasterBufferProviderTest private: void Create3dResourceProvider() { - context_provider_ = viz::TestContextProvider::Create(); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + gl_owned->set_support_sync_query(true); + context_provider_ = viz::TestContextProvider::Create(std::move(gl_owned)); context_provider_->BindToCurrentThread(); worker_context_provider_ = viz::TestContextProvider::CreateWorker(); - viz::TestWebGraphicsContext3D* context3d = - context_provider_->TestContext3d(); - context3d->set_support_sync_query(true); layer_tree_frame_sink_ = FakeLayerTreeFrameSink::Create3d(); resource_provider_ = FakeResourceProvider::CreateLayerTreeResourceProvider( - context_provider_.get(), &shared_bitmap_manager_, - &gpu_memory_buffer_manager_); + context_provider_.get()); } void CreateSoftwareResourceProvider() { layer_tree_frame_sink_ = FakeLayerTreeFrameSink::CreateSoftware(); - resource_provider_ = FakeResourceProvider::CreateLayerTreeResourceProvider( - nullptr, &shared_bitmap_manager_, &gpu_memory_buffer_manager_); + resource_provider_ = + FakeResourceProvider::CreateLayerTreeResourceProvider(nullptr); } void OnTimeout() { @@ -337,7 +322,6 @@ class RasterBufferProviderTest std::unique_ptr<TileTaskManager> tile_task_manager_; std::unique_ptr<RasterBufferProvider> raster_buffer_provider_; viz::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; - viz::TestSharedBitmapManager shared_bitmap_manager_; SynchronousTaskGraphRunner task_graph_runner_; base::CancelableClosure timeout_; UniqueNotifier all_tile_tasks_finished_; diff --git a/chromium/cc/raster/staging_buffer_pool.cc b/chromium/cc/raster/staging_buffer_pool.cc index 37c39fc4102..0ac04f79693 100644 --- a/chromium/cc/raster/staging_buffer_pool.cc +++ b/chromium/cc/raster/staging_buffer_pool.cc @@ -14,6 +14,8 @@ #include "components/viz/common/gpu/raster_context_provider.h" #include "components/viz/common/resources/resource_sizes.h" #include "gpu/command_buffer/client/raster_interface.h" +#include "third_party/khronos/GLES2/gl2.h" +#include "third_party/khronos/GLES2/gl2ext.h" #include "ui/gfx/gpu_memory_buffer.h" using base::trace_event::MemoryAllocatorDump; @@ -129,12 +131,10 @@ void StagingBuffer::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, StagingBufferPool::StagingBufferPool( scoped_refptr<base::SequencedTaskRunner> task_runner, viz::RasterContextProvider* worker_context_provider, - LayerTreeResourceProvider* resource_provider, bool use_partial_raster, int max_staging_buffer_usage_in_bytes) : task_runner_(std::move(task_runner)), worker_context_provider_(worker_context_provider), - resource_provider_(resource_provider), use_partial_raster_(use_partial_raster), max_staging_buffer_usage_in_bytes_(max_staging_buffer_usage_in_bytes), staging_buffer_usage_in_bytes_(0), @@ -260,7 +260,7 @@ std::unique_ptr<StagingBuffer> StagingBufferPool::AcquireStagingBuffer( DCHECK(ri); // Check if any busy buffers have become available. - if (resource_provider_->use_sync_query()) { + if (worker_context_provider_->ContextCapabilities().sync_query) { while (!busy_buffers_.empty()) { if (!CheckForQueryResult(ri, busy_buffers_.front()->query_id)) break; @@ -278,7 +278,7 @@ std::unique_ptr<StagingBuffer> StagingBufferPool::AcquireStagingBuffer( if (busy_buffers_.empty()) break; - if (resource_provider_->use_sync_query()) { + if (worker_context_provider_->ContextCapabilities().sync_query) { WaitForQueryResult(ri, busy_buffers_.front()->query_id); MarkStagingBufferAsFree(busy_buffers_.front().get()); free_buffers_.push_back(PopFront(&busy_buffers_)); diff --git a/chromium/cc/raster/staging_buffer_pool.h b/chromium/cc/raster/staging_buffer_pool.h index 559657f8aaa..460a3bbe843 100644 --- a/chromium/cc/raster/staging_buffer_pool.h +++ b/chromium/cc/raster/staging_buffer_pool.h @@ -14,12 +14,19 @@ #include "base/macros.h" #include "base/memory/memory_coordinator_client.h" #include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" #include "base/synchronization/lock.h" #include "base/time/time.h" #include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/trace_event.h" -#include "cc/resources/layer_tree_resource_provider.h" +#include "cc/cc_export.h" +#include "components/viz/common/resources/resource_format.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/gpu_memory_buffer.h" +namespace gfx { +class GpuMemoryBuffer; +} namespace gpu { namespace raster { class RasterInterface; @@ -59,7 +66,6 @@ class CC_EXPORT StagingBufferPool StagingBufferPool(scoped_refptr<base::SequencedTaskRunner> task_runner, viz::RasterContextProvider* worker_context_provider, - LayerTreeResourceProvider* resource_provider, bool use_partial_raster, int max_staging_buffer_usage_in_bytes); void Shutdown(); @@ -96,7 +102,6 @@ class CC_EXPORT StagingBufferPool scoped_refptr<base::SequencedTaskRunner> task_runner_; viz::RasterContextProvider* const worker_context_provider_; - LayerTreeResourceProvider* const resource_provider_; const bool use_partial_raster_; mutable base::Lock lock_; diff --git a/chromium/cc/raster/staging_buffer_pool_unittest.cc b/chromium/cc/raster/staging_buffer_pool_unittest.cc index 51e3f7c56fa..7c7c79aec61 100644 --- a/chromium/cc/raster/staging_buffer_pool_unittest.cc +++ b/chromium/cc/raster/staging_buffer_pool_unittest.cc @@ -16,14 +16,13 @@ namespace cc { TEST(StagingBufferPoolTest, ShutdownImmediatelyAfterCreation) { auto context_provider = viz::TestContextProvider::CreateWorker(); - LayerTreeResourceProvider* resource_provider = nullptr; bool use_partial_raster = false; int max_staging_buffer_usage_in_bytes = 1024; auto task_runner = base::ThreadTaskRunnerHandle::Get(); // Create a StagingBufferPool and immediately shut it down. auto pool = std::make_unique<StagingBufferPool>( - task_runner.get(), context_provider.get(), resource_provider, - use_partial_raster, max_staging_buffer_usage_in_bytes); + task_runner.get(), context_provider.get(), use_partial_raster, + max_staging_buffer_usage_in_bytes); pool->Shutdown(); // Flush the message loop. auto flush_message_loop = [] { diff --git a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc index 9cefe8af99b..fd2bb2118c8 100644 --- a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc @@ -183,7 +183,8 @@ class ZeroCopyRasterBufferImpl : public RasterBuffer { RasterBufferProvider::PlaybackToMemory( gpu_memory_buffer_->memory(0), resource_format_, resource_size_, gpu_memory_buffer_->stride(0), raster_source, raster_full_rect, - raster_full_rect, transform, resource_color_space_, playback_settings); + raster_full_rect, transform, resource_color_space_, + /*gpu_compositing=*/true, playback_settings); gpu_memory_buffer_->Unmap(); } @@ -204,14 +205,12 @@ class ZeroCopyRasterBufferImpl : public RasterBuffer { } // namespace ZeroCopyRasterBufferProvider::ZeroCopyRasterBufferProvider( - LayerTreeResourceProvider* resource_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, viz::ContextProvider* compositor_context_provider, - viz::ResourceFormat preferred_tile_format) - : resource_provider_(resource_provider), - gpu_memory_buffer_manager_(gpu_memory_buffer_manager), + viz::ResourceFormat tile_format) + : gpu_memory_buffer_manager_(gpu_memory_buffer_manager), compositor_context_provider_(compositor_context_provider), - preferred_tile_format_(preferred_tile_format) {} + tile_format_(tile_format) {} ZeroCopyRasterBufferProvider::~ZeroCopyRasterBufferProvider() = default; @@ -235,24 +234,15 @@ ZeroCopyRasterBufferProvider::AcquireBufferForRaster( void ZeroCopyRasterBufferProvider::Flush() {} -viz::ResourceFormat ZeroCopyRasterBufferProvider::GetResourceFormat( - bool must_support_alpha) const { - if (resource_provider_->IsTextureFormatSupported(preferred_tile_format_)) { - if (!must_support_alpha) - return preferred_tile_format_; - if (DoesResourceFormatSupportAlpha(preferred_tile_format_)) - return preferred_tile_format_; - } - return resource_provider_->best_texture_format(); +viz::ResourceFormat ZeroCopyRasterBufferProvider::GetResourceFormat() const { + return tile_format_; } -bool ZeroCopyRasterBufferProvider::IsResourceSwizzleRequired( - bool must_support_alpha) const { - return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); +bool ZeroCopyRasterBufferProvider::IsResourceSwizzleRequired() const { + return !viz::PlatformColor::SameComponentOrder(GetResourceFormat()); } -bool ZeroCopyRasterBufferProvider::IsResourcePremultiplied( - bool must_support_alpha) const { +bool ZeroCopyRasterBufferProvider::IsResourcePremultiplied() const { return true; } diff --git a/chromium/cc/raster/zero_copy_raster_buffer_provider.h b/chromium/cc/raster/zero_copy_raster_buffer_provider.h index d7a118e2988..68f78bfb2c7 100644 --- a/chromium/cc/raster/zero_copy_raster_buffer_provider.h +++ b/chromium/cc/raster/zero_copy_raster_buffer_provider.h @@ -23,15 +23,13 @@ class GpuMemoryBufferManager; } namespace cc { -class LayerTreeResourceProvider; class CC_EXPORT ZeroCopyRasterBufferProvider : public RasterBufferProvider { public: ZeroCopyRasterBufferProvider( - LayerTreeResourceProvider* resource_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, viz::ContextProvider* compositor_context_provider, - viz::ResourceFormat preferred_tile_format); + viz::ResourceFormat tile_format); ~ZeroCopyRasterBufferProvider() override; // Overridden from RasterBufferProvider: @@ -40,9 +38,9 @@ class CC_EXPORT ZeroCopyRasterBufferProvider : public RasterBufferProvider { uint64_t resource_content_id, uint64_t previous_content_id) override; void Flush() override; - viz::ResourceFormat GetResourceFormat(bool must_support_alpha) const override; - bool IsResourceSwizzleRequired(bool must_support_alpha) const override; - bool IsResourcePremultiplied(bool must_support_alpha) const override; + viz::ResourceFormat GetResourceFormat() const override; + bool IsResourceSwizzleRequired() const override; + bool IsResourcePremultiplied() const override; bool CanPartialRasterIntoProvidedResource() const override; bool IsResourceReadyToDraw( const ResourcePool::InUsePoolResource& resource) const override; @@ -56,10 +54,9 @@ class CC_EXPORT ZeroCopyRasterBufferProvider : public RasterBufferProvider { std::unique_ptr<base::trace_event::ConvertableToTraceFormat> StateAsValue() const; - LayerTreeResourceProvider* resource_provider_; gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; viz::ContextProvider* compositor_context_provider_; - viz::ResourceFormat preferred_tile_format_; + viz::ResourceFormat tile_format_; DISALLOW_COPY_AND_ASSIGN(ZeroCopyRasterBufferProvider); }; diff --git a/chromium/cc/resources/display_resource_provider.cc b/chromium/cc/resources/display_resource_provider.cc deleted file mode 100644 index c48d3ff6768..00000000000 --- a/chromium/cc/resources/display_resource_provider.cc +++ /dev/null @@ -1,829 +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. - -#include "cc/resources/display_resource_provider.h" - -#include "base/trace_event/trace_event.h" -#include "components/viz/common/gpu/context_provider.h" -#include "components/viz/common/resources/resource_format_utils.h" -#include "components/viz/common/resources/shared_bitmap_manager.h" -#include "gpu/command_buffer/client/gles2_interface.h" -#include "third_party/skia/include/gpu/GrBackendSurface.h" - -using gpu::gles2::GLES2Interface; - -namespace cc { - -static GLint GetActiveTextureUnit(GLES2Interface* gl) { - GLint active_unit = 0; - gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit); - return active_unit; -} - -class ScopedSetActiveTexture { - public: - ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit) - : gl_(gl), unit_(unit) { - DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_)); - - if (unit_ != GL_TEXTURE0) - gl_->ActiveTexture(unit_); - } - - ~ScopedSetActiveTexture() { - // Active unit being GL_TEXTURE0 is effectively the ground state. - if (unit_ != GL_TEXTURE0) - gl_->ActiveTexture(GL_TEXTURE0); - } - - private: - GLES2Interface* gl_; - GLenum unit_; -}; - -namespace { -// The resource id in DisplayResourceProvider starts from 2 to avoid -// conflicts with id from LayerTreeResourceProvider. -const unsigned int kDisplayInitialResourceId = 2; -} // namespace - -DisplayResourceProvider::DisplayResourceProvider( - viz::ContextProvider* compositor_context_provider, - viz::SharedBitmapManager* shared_bitmap_manager) - : ResourceProvider(compositor_context_provider), - next_id_(kDisplayInitialResourceId), - shared_bitmap_manager_(shared_bitmap_manager) {} - -DisplayResourceProvider::~DisplayResourceProvider() { - while (!children_.empty()) - DestroyChildInternal(children_.begin(), FOR_SHUTDOWN); - - GLES2Interface* gl = ContextGL(); - if (gl) - gl->Finish(); -} - -#if defined(OS_ANDROID) -void DisplayResourceProvider::SendPromotionHints( - const OverlayCandidateList::PromotionHintInfoMap& promotion_hints) { - GLES2Interface* gl = ContextGL(); - if (!gl) - return; - - for (const auto& id : wants_promotion_hints_set_) { - const ResourceMap::iterator it = resources_.find(id); - if (it == resources_.end()) - continue; - - if (it->second.marked_for_deletion) - continue; - - const viz::internal::Resource* resource = LockForRead(id); - // TODO(ericrk): We should never fail LockForRead, but we appear to be - // doing so on Android in rare cases. Handle this gracefully until a better - // solution can be found. https://crbug.com/811858 - if (!resource) - return; - - DCHECK(resource->wants_promotion_hint); - - // Insist that this is backed by a GPU texture. - if (resource->is_gpu_resource_type()) { - DCHECK(resource->gl_id); - auto iter = promotion_hints.find(id); - bool promotable = iter != promotion_hints.end(); - gl->OverlayPromotionHintCHROMIUM(resource->gl_id, promotable, - promotable ? iter->second.x() : 0, - promotable ? iter->second.y() : 0, - promotable ? iter->second.width() : 0, - promotable ? iter->second.height() : 0); - } - UnlockForRead(id); - } -} - -void DisplayResourceProvider::DeletePromotionHint(ResourceMap::iterator it, - DeleteStyle style) { - viz::internal::Resource* resource = &it->second; - // If this resource was interested in promotion hints, then remove it from - // the set of resources that we'll notify. - if (resource->wants_promotion_hint) - wants_promotion_hints_set_.erase(it->first); -} - -bool DisplayResourceProvider::IsBackedBySurfaceTexture(viz::ResourceId id) { - viz::internal::Resource* resource = GetResource(id); - return resource->is_backed_by_surface_texture; -} - -bool DisplayResourceProvider::WantsPromotionHintForTesting(viz::ResourceId id) { - return wants_promotion_hints_set_.count(id) > 0; -} - -size_t DisplayResourceProvider::CountPromotionHintRequestsForTesting() { - return wants_promotion_hints_set_.size(); -} - -#endif -bool DisplayResourceProvider::IsOverlayCandidate(viz::ResourceId id) { - viz::internal::Resource* resource = TryGetResource(id); - // TODO(ericrk): We should never fail TryGetResource, but we appear to - // be doing so on Android in rare cases. Handle this gracefully until a - // better solution can be found. https://crbug.com/811858 - return resource && resource->is_overlay_candidate; -} - -viz::ResourceType DisplayResourceProvider::GetResourceType(viz::ResourceId id) { - return GetResource(id)->type; -} - -gfx::BufferFormat DisplayResourceProvider::GetBufferFormat(viz::ResourceId id) { - viz::internal::Resource* resource = GetResource(id); - return resource->buffer_format; -} - -void DisplayResourceProvider::WaitSyncToken(viz::ResourceId id) { - viz::internal::Resource* resource = TryGetResource(id); - // TODO(ericrk): We should never fail TryGetResource, but we appear to - // be doing so on Android in rare cases. Handle this gracefully until a - // better solution can be found. https://crbug.com/811858 - if (!resource) - return; - WaitSyncTokenInternal(resource); -#if defined(OS_ANDROID) - // Now that the resource is synced, we may send it a promotion hint. We could - // sync all |wants_promotion_hint| resources elsewhere, and send 'no' to all - // resources that weren't used. However, there's no real advantage. - if (resource->wants_promotion_hint) - wants_promotion_hints_set_.insert(id); -#endif // OS_ANDROID -} - -DisplayResourceProvider::ScopedBatchReturnResources::ScopedBatchReturnResources( - DisplayResourceProvider* resource_provider) - : resource_provider_(resource_provider) { - resource_provider_->SetBatchReturnResources(true); -} - -DisplayResourceProvider::ScopedBatchReturnResources:: - ~ScopedBatchReturnResources() { - resource_provider_->SetBatchReturnResources(false); -} - -void DisplayResourceProvider::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(); - } -} - -DisplayResourceProvider::Child::Child() - : marked_for_deletion(false), needs_sync_tokens(true) {} - -DisplayResourceProvider::Child::Child(const Child& other) = default; - -DisplayResourceProvider::Child::~Child() = default; - -int DisplayResourceProvider::CreateChild( - const ReturnCallback& return_callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - Child child_info; - child_info.return_callback = return_callback; - - int child = next_child_++; - children_[child] = child_info; - return child; -} - -void DisplayResourceProvider::SetChildNeedsSyncTokens(int child_id, - bool needs) { - ChildMap::iterator it = children_.find(child_id); - DCHECK(it != children_.end()); - it->second.needs_sync_tokens = needs; -} - -void DisplayResourceProvider::DestroyChild(int child_id) { - ChildMap::iterator it = children_.find(child_id); - DCHECK(it != children_.end()); - DestroyChildInternal(it, NORMAL); -} - -void DisplayResourceProvider::DestroyChildInternal(ChildMap::iterator it, - DeleteStyle style) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - Child& child = it->second; - DCHECK(style == FOR_SHUTDOWN || !child.marked_for_deletion); - - ResourceIdArray resources_for_child; - - for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin(); - child_it != child.child_to_parent_map.end(); ++child_it) { - viz::ResourceId id = child_it->second; - resources_for_child.push_back(id); - } - - child.marked_for_deletion = true; - - DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child); -} - -void DisplayResourceProvider::DeleteAndReturnUnusedResourcesToChild( - ChildMap::iterator child_it, - DeleteStyle style, - const ResourceIdArray& unused) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(child_it != children_.end()); - Child* child_info = &child_it->second; - - if (unused.empty() && !child_info->marked_for_deletion) - return; - - std::vector<viz::ReturnedResource> to_return; - to_return.reserve(unused.size()); - std::vector<viz::ReturnedResource*> need_synchronization_resources; - std::vector<GLbyte*> unverified_sync_tokens; - std::vector<size_t> to_return_indices_unverified; - - GLES2Interface* gl = ContextGL(); - - for (viz::ResourceId local_id : unused) { - ResourceMap::iterator it = resources_.find(local_id); - CHECK(it != resources_.end()); - viz::internal::Resource& resource = it->second; - - // TODO(xing.xu): remove locked_for_write. - DCHECK(!resource.locked_for_write); - - viz::ResourceId child_id = resource.id_in_child; - DCHECK(child_info->child_to_parent_map.count(child_id)); - - bool is_lost = resource.lost || - (resource.is_gpu_resource_type() && lost_context_provider_); - if (resource.exported_count > 0 || resource.lock_for_read_count > 0 || - resource.locked_for_external_use) { - if (style != FOR_SHUTDOWN) { - // Defer this resource deletion. - resource.marked_for_deletion = true; - continue; - } - // We can't postpone the deletion, so we'll have to lose it. - is_lost = true; - } else if (!ReadLockFenceHasPassed(&resource)) { - // TODO(dcastagna): see if it's possible to use this logic for - // the branch above too, where the resource is locked or still exported. - if (style != FOR_SHUTDOWN && !child_info->marked_for_deletion) { - // Defer this resource deletion. - resource.marked_for_deletion = true; - continue; - } - // We can't postpone the deletion, so we'll have to lose it. - is_lost = true; - } - - if (resource.is_gpu_resource_type() && - resource.filter != resource.original_filter) { - DCHECK(resource.target); - DCHECK(resource.gl_id); - DCHECK(gl); - gl->BindTexture(resource.target, resource.gl_id); - gl->TexParameteri(resource.target, GL_TEXTURE_MIN_FILTER, - resource.original_filter); - gl->TexParameteri(resource.target, GL_TEXTURE_MAG_FILTER, - resource.original_filter); - resource.SetLocallyUsed(); - } - - viz::ReturnedResource returned; - returned.id = child_id; - returned.sync_token = resource.sync_token(); - returned.count = resource.imported_count; - returned.lost = is_lost; - to_return.push_back(returned); - - if (resource.is_gpu_resource_type() && child_info->needs_sync_tokens) { - if (resource.needs_sync_token()) { - need_synchronization_resources.push_back(&to_return.back()); - } else if (returned.sync_token.HasData() && - !returned.sync_token.verified_flush()) { - // Before returning any sync tokens, they must be verified. Store an - // index into |to_return| instead of a pointer as vectors may realloc - // and move their data. - to_return_indices_unverified.push_back(to_return.size() - 1); - } - } - - child_info->child_to_parent_map.erase(child_id); - resource.imported_count = 0; -#if defined(OS_ANDROID) - DeletePromotionHint(it, style); -#endif - DeleteResourceInternal(it, style); - } - - for (size_t i : to_return_indices_unverified) - unverified_sync_tokens.push_back(to_return[i].sync_token.GetData()); - - gpu::SyncToken new_sync_token; - if (!need_synchronization_resources.empty()) { - DCHECK(child_info->needs_sync_tokens); - DCHECK(gl); - gl->GenUnverifiedSyncTokenCHROMIUM(new_sync_token.GetData()); - unverified_sync_tokens.push_back(new_sync_token.GetData()); - } - - if (!unverified_sync_tokens.empty()) { - DCHECK(child_info->needs_sync_tokens); - DCHECK(gl); - gl->VerifySyncTokensCHROMIUM(unverified_sync_tokens.data(), - unverified_sync_tokens.size()); - } - - // Set sync token after verification. - for (viz::ReturnedResource* returned : need_synchronization_resources) - returned->sync_token = new_sync_token; - - if (!to_return.empty()) - child_info->return_callback.Run(to_return); - - if (child_info->marked_for_deletion && - child_info->child_to_parent_map.empty()) { - children_.erase(child_it); - } -} - -void DisplayResourceProvider::ReceiveFromChild( - int child, - const std::vector<viz::TransferableResource>& resources) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - GLES2Interface* gl = ContextGL(); - Child& child_info = children_.find(child)->second; - DCHECK(!child_info.marked_for_deletion); - for (std::vector<viz::TransferableResource>::const_iterator it = - resources.begin(); - it != resources.end(); ++it) { - ResourceIdMap::iterator resource_in_map_it = - child_info.child_to_parent_map.find(it->id); - if (resource_in_map_it != child_info.child_to_parent_map.end()) { - viz::internal::Resource* resource = - GetResource(resource_in_map_it->second); - resource->marked_for_deletion = false; - resource->imported_count++; - continue; - } - - if ((!it->is_software && !gl) || - (it->is_software && !shared_bitmap_manager_)) { - TRACE_EVENT0( - "cc", "DisplayResourceProvider::ReceiveFromChild dropping invalid"); - std::vector<viz::ReturnedResource> to_return; - to_return.push_back(it->ToReturnedResource()); - child_info.return_callback.Run(to_return); - continue; - } - - viz::ResourceId local_id = next_id_++; - viz::internal::Resource* resource = nullptr; - if (it->is_software) { - DCHECK(IsBitmapFormatSupported(it->format)); - resource = InsertResource( - local_id, - viz::internal::Resource(it->size, viz::internal::Resource::DELEGATED, - viz::ResourceTextureHint::kDefault, - viz::ResourceType::kBitmap, it->format, - it->color_space)); - resource->has_shared_bitmap_id = true; - resource->shared_bitmap_id = it->mailbox_holder.mailbox; - } else { - resource = InsertResource( - local_id, - viz::internal::Resource(it->size, viz::internal::Resource::DELEGATED, - viz::ResourceTextureHint::kDefault, - viz::ResourceType::kTexture, it->format, - it->color_space)); - resource->target = it->mailbox_holder.texture_target; - resource->filter = it->filter; - resource->original_filter = it->filter; - resource->min_filter = it->filter; - resource->buffer_format = it->buffer_format; - resource->mailbox = it->mailbox_holder.mailbox; - resource->UpdateSyncToken(it->mailbox_holder.sync_token); - resource->read_lock_fences_enabled = it->read_lock_fences_enabled; - resource->is_overlay_candidate = it->is_overlay_candidate; -#if defined(OS_ANDROID) - resource->is_backed_by_surface_texture = it->is_backed_by_surface_texture; - resource->wants_promotion_hint = it->wants_promotion_hint; -#endif - } - resource->child_id = child; - // Don't allocate a texture for a child. - resource->allocated = true; - resource->imported_count = 1; - resource->id_in_child = it->id; - child_info.child_to_parent_map[it->id] = local_id; - } -} - -void DisplayResourceProvider::DeclareUsedResourcesFromChild( - int child, - const viz::ResourceIdSet& resources_from_child) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - ChildMap::iterator child_it = children_.find(child); - DCHECK(child_it != children_.end()); - Child& child_info = child_it->second; - DCHECK(!child_info.marked_for_deletion); - - ResourceIdArray unused; - for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin(); - it != child_info.child_to_parent_map.end(); ++it) { - viz::ResourceId local_id = it->second; - bool resource_is_in_use = resources_from_child.count(it->first) > 0; - if (!resource_is_in_use) - unused.push_back(local_id); - } - DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused); -} - -const ResourceProvider::ResourceIdMap& -DisplayResourceProvider::GetChildToParentMap(int child) const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - ChildMap::const_iterator it = children_.find(child); - DCHECK(it != children_.end()); - DCHECK(!it->second.marked_for_deletion); - return it->second.child_to_parent_map; -} - -GLenum DisplayResourceProvider::BindForSampling(viz::ResourceId resource_id, - GLenum unit, - GLenum filter) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - GLES2Interface* gl = ContextGL(); - ResourceMap::iterator it = resources_.find(resource_id); - // TODO(ericrk): We should never fail to find resource_id, but we appear to - // be doing so on Android in rare cases. Handle this gracefully until a - // better solution can be found. https://crbug.com/811858 - if (it == resources_.end()) - return GL_TEXTURE_2D; - - viz::internal::Resource* resource = &it->second; - DCHECK(resource->lock_for_read_count); - // TODO(xing.xu): remove locked_for_write. - DCHECK(!resource->locked_for_write); - - ScopedSetActiveTexture scoped_active_tex(gl, unit); - GLenum target = resource->target; - gl->BindTexture(target, resource->gl_id); - GLenum min_filter = filter; - if (filter == GL_LINEAR) { - switch (resource->mipmap_state) { - case viz::internal::Resource::INVALID: - break; - case viz::internal::Resource::GENERATE: - DCHECK(compositor_context_provider_); - DCHECK( - compositor_context_provider_->ContextCapabilities().texture_npot); - gl->GenerateMipmap(target); - resource->mipmap_state = viz::internal::Resource::VALID; - FALLTHROUGH; - case viz::internal::Resource::VALID: - min_filter = GL_LINEAR_MIPMAP_LINEAR; - break; - } - } - if (min_filter != resource->min_filter) { - gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filter); - resource->min_filter = min_filter; - } - if (filter != resource->filter) { - gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); - resource->filter = filter; - } - - return target; -} - -bool DisplayResourceProvider::InUse(viz::ResourceId id) { - viz::internal::Resource* resource = GetResource(id); - return resource->lock_for_read_count > 0 || resource->lost || - resource->locked_for_external_use; -} - -DisplayResourceProvider::ScopedReadLockGL::ScopedReadLockGL( - DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id) - : resource_provider_(resource_provider), resource_id_(resource_id) { - const viz::internal::Resource* resource = - resource_provider->LockForRead(resource_id); - // TODO(ericrk): We should never fail LockForRead, but we appear to be - // doing so on Android in rare cases. Handle this gracefully until a better - // solution can be found. https://crbug.com/811858 - if (!resource) - return; - - texture_id_ = resource->gl_id; - target_ = resource->target; - size_ = resource->size; - color_space_ = resource->color_space; -} - -const viz::internal::Resource* DisplayResourceProvider::LockForRead( - viz::ResourceId id) { - // TODO(ericrk): We should never fail TryGetResource, but we appear to be - // doing so on Android in rare cases. Handle this gracefully until a better - // solution can be found. https://crbug.com/811858 - viz::internal::Resource* resource = TryGetResource(id); - if (!resource) - return nullptr; - - // TODO(xing.xu): remove locked_for_write. - DCHECK(!resource->locked_for_write) - << "locked for write: " << resource->locked_for_write; - DCHECK_EQ(resource->exported_count, 0); - // Uninitialized! Call SetPixels or LockForWrite first. - DCHECK(resource->allocated); - - // Mailbox sync_tokens must be processed by a call to WaitSyncToken() prior to - // calling LockForRead(). - DCHECK_NE(viz::internal::Resource::NEEDS_WAIT, - resource->synchronization_state()); - - if (resource->is_gpu_resource_type() && !resource->gl_id) { - DCHECK(resource->origin != viz::internal::Resource::INTERNAL); - DCHECK(!resource->mailbox.IsZero()); - - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - resource->gl_id = - gl->CreateAndConsumeTextureCHROMIUM(resource->mailbox.name); - resource->SetLocallyUsed(); - } - - if (!resource->pixels && resource->has_shared_bitmap_id && - shared_bitmap_manager_) { - std::unique_ptr<viz::SharedBitmap> bitmap = - shared_bitmap_manager_->GetSharedBitmapFromId( - resource->size, resource->format, resource->shared_bitmap_id); - if (bitmap) { - resource->SetSharedBitmap(bitmap.get()); - resource->owned_shared_bitmap = std::move(bitmap); - } - } - - resource->lock_for_read_count++; - if (resource->read_lock_fences_enabled) { - if (current_read_lock_fence_.get()) - current_read_lock_fence_->Set(); - resource->read_lock_fence = current_read_lock_fence_; - } - - return resource; -} - -void DisplayResourceProvider::UnlockForRead(viz::ResourceId id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - ResourceMap::iterator it = resources_.find(id); - // TODO(ericrk): We should never fail to find id, but we appear to be - // doing so on Android in rare cases. Handle this gracefully until a better - // solution can be found. https://crbug.com/811858 - if (it == resources_.end()) - return; - - viz::internal::Resource* resource = &it->second; - DCHECK_GT(resource->lock_for_read_count, 0); - DCHECK_EQ(resource->exported_count, 0); - resource->lock_for_read_count--; - TryReleaseResource(it); -} - -viz::ResourceMetadata DisplayResourceProvider::LockForExternalUse( - viz::ResourceId id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - ResourceMap::iterator it = resources_.find(id); - DCHECK(it != resources_.end()); - - viz::internal::Resource* resource = &it->second; - viz::ResourceMetadata metadata; - // TODO(xing.xu): remove locked_for_write. - DCHECK(!resource->locked_for_write) - << "locked for write: " << resource->locked_for_write; - DCHECK_EQ(resource->exported_count, 0); - // Uninitialized! Call SetPixels or LockForWrite first. - DCHECK(resource->allocated); - // Make sure there is no outstanding LockForExternalUse without calling - // UnlockForExternalUse. - DCHECK(!resource->locked_for_external_use); - // TODO(penghuang): support software resource. - DCHECK(resource->is_gpu_resource_type()); - - metadata.mailbox = resource->mailbox; - metadata.backend_format = GrBackendFormat::MakeGL( - TextureStorageFormat(resource->format), resource->target); - metadata.size = resource->size; - metadata.mip_mapped = GrMipMapped::kNo; - metadata.origin = kTopLeft_GrSurfaceOrigin; - metadata.color_type = ResourceFormatToClosestSkColorType(resource->format); - metadata.alpha_type = kPremul_SkAlphaType; - metadata.color_space = nullptr; - metadata.sync_token = resource->sync_token(); - - resource->locked_for_external_use = true; - return metadata; -} - -void DisplayResourceProvider::UnlockForExternalUse( - viz::ResourceId id, - const gpu::SyncToken& sync_token) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - ResourceMap::iterator it = resources_.find(id); - DCHECK(it != resources_.end()); - DCHECK(sync_token.verified_flush()); - - viz::internal::Resource* resource = &it->second; - DCHECK(resource->locked_for_external_use); - // TODO(penghuang): support software resource. - DCHECK(resource->is_gpu_resource_type()); - - // Update the resource sync token to |sync_token|. When the next frame is - // being composited, the DeclareUsedResourcesFromChild() will be called with - // resources belong to every child for the next frame. If the resource is not - // used by the next frame, the resource will be returned to a child which - // owns it with the |sync_token|. The child is responsible for issuing a - // WaitSyncToken GL command with the |sync_token| before reusing it. - resource->UpdateSyncToken(sync_token); - resource->locked_for_external_use = false; - - TryReleaseResource(it); -} - -void DisplayResourceProvider::TryReleaseResource(ResourceMap::iterator it) { - viz::ResourceId id = it->first; - viz::internal::Resource* resource = &it->second; - if (resource->marked_for_deletion && !resource->lock_for_read_count && - !resource->locked_for_external_use) { - if (!resource->child_id) { - // The resource belongs to this ResourceProvider, so it can be destroyed. -#if defined(OS_ANDROID) - DeletePromotionHint(it, NORMAL); -#endif - DeleteResourceInternal(it, NORMAL); - } else { - 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); - } - } - } -} - -bool DisplayResourceProvider::ReadLockFenceHasPassed( - const viz::internal::Resource* resource) { - return !resource->read_lock_fence || resource->read_lock_fence->HasPassed(); -} - -DisplayResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() { - resource_provider_->UnlockForRead(resource_id_); -} - -DisplayResourceProvider::ScopedSamplerGL::ScopedSamplerGL( - DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id, - GLenum filter) - : resource_lock_(resource_provider, resource_id), - unit_(GL_TEXTURE0), - target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {} - -DisplayResourceProvider::ScopedSamplerGL::ScopedSamplerGL( - DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id, - GLenum unit, - GLenum filter) - : resource_lock_(resource_provider, resource_id), - unit_(unit), - target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {} - -DisplayResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() = default; - -DisplayResourceProvider::ScopedReadLockSkImage::ScopedReadLockSkImage( - DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id) - : resource_provider_(resource_provider), resource_id_(resource_id) { - const viz::internal::Resource* resource = - resource_provider->LockForRead(resource_id); - DCHECK(resource); - if (resource_provider_->resource_sk_image_.find(resource_id) != - resource_provider_->resource_sk_image_.end()) { - // Use cached sk_image. - sk_image_ = - resource_provider_->resource_sk_image_.find(resource_id)->second; - } else if (resource->gl_id) { - GrGLTextureInfo texture_info; - texture_info.fID = resource->gl_id; - texture_info.fTarget = resource->target; - texture_info.fFormat = TextureStorageFormat(resource->format); - GrBackendTexture backend_texture(resource->size.width(), - resource->size.height(), GrMipMapped::kNo, - texture_info); - sk_image_ = SkImage::MakeFromTexture( - resource_provider->compositor_context_provider_->GrContext(), - backend_texture, kTopLeft_GrSurfaceOrigin, - ResourceFormatToClosestSkColorType(resource->format), - kPremul_SkAlphaType, nullptr); - } else if (resource->pixels) { - SkBitmap sk_bitmap; - resource_provider->PopulateSkBitmapWithResource(&sk_bitmap, resource); - sk_bitmap.setImmutable(); - sk_image_ = SkImage::MakeFromBitmap(sk_bitmap); - } else { - // During render process shutdown, ~RenderMessageFilter which calls - // ~HostSharedBitmapClient (which deletes shared bitmaps from child) - // can race with OnBeginFrameDeadline which draws a frame. - // In these cases, shared bitmaps (and this read lock) won't be valid. - // Renderers need to silently handle locks failing until this race - // is fixed. DCHECK that this is the only case where there are no pixels. - DCHECK(!resource->shared_bitmap_id.IsZero()); - } -} - -DisplayResourceProvider::ScopedReadLockSkImage::~ScopedReadLockSkImage() { - resource_provider_->UnlockForRead(resource_id_); -} - -DisplayResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware( - DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id) - : resource_provider_(resource_provider), resource_id_(resource_id) { - const viz::internal::Resource* resource = - resource_provider->LockForRead(resource_id); - DCHECK(resource); - resource_provider->PopulateSkBitmapWithResource(&sk_bitmap_, resource); -} - -DisplayResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() { - resource_provider_->UnlockForRead(resource_id_); -} - -DisplayResourceProvider::LockSetForExternalUse::LockSetForExternalUse( - DisplayResourceProvider* resource_provider) - : resource_provider_(resource_provider) {} - -DisplayResourceProvider::LockSetForExternalUse::~LockSetForExternalUse() { - DCHECK(resources_.empty()); -} - -viz::ResourceMetadata -DisplayResourceProvider::LockSetForExternalUse::LockResource( - viz::ResourceId id) { - DCHECK(std::find(resources_.begin(), resources_.end(), id) == - resources_.end()); - resources_.push_back(id); - return resource_provider_->LockForExternalUse(id); -} - -void DisplayResourceProvider::LockSetForExternalUse::UnlockResources( - const gpu::SyncToken& sync_token) { - for (const auto& id : resources_) - resource_provider_->UnlockForExternalUse(id, sync_token); - resources_.clear(); -} - -DisplayResourceProvider::SynchronousFence::SynchronousFence( - gpu::gles2::GLES2Interface* gl) - : gl_(gl), has_synchronized_(true) {} - -DisplayResourceProvider::SynchronousFence::~SynchronousFence() = default; - -void DisplayResourceProvider::SynchronousFence::Set() { - has_synchronized_ = false; -} - -bool DisplayResourceProvider::SynchronousFence::HasPassed() { - if (!has_synchronized_) { - has_synchronized_ = true; - Synchronize(); - } - return true; -} - -void DisplayResourceProvider::SynchronousFence::Wait() { - HasPassed(); -} - -void DisplayResourceProvider::SynchronousFence::Synchronize() { - TRACE_EVENT0("cc", "DisplayResourceProvider::SynchronousFence::Synchronize"); - gl_->Finish(); -} - -} // namespace cc diff --git a/chromium/cc/resources/display_resource_provider.h b/chromium/cc/resources/display_resource_provider.h deleted file mode 100644 index 5c6baef797e..00000000000 --- a/chromium/cc/resources/display_resource_provider.h +++ /dev/null @@ -1,315 +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_RESOURCES_DISPLAY_RESOURCE_PROVIDER_H_ -#define CC_RESOURCES_DISPLAY_RESOURCE_PROVIDER_H_ - -#include "build/build_config.h" -#include "cc/output/overlay_candidate.h" -#include "cc/resources/resource_provider.h" -#include "components/viz/common/resources/resource_fence.h" -#include "components/viz/common/resources/resource_metadata.h" - -namespace viz { -class SharedBitmapManager; -} // namespace viz - -namespace cc { - -// This class is not thread-safe and can only be called from the thread it was -// created on. -class CC_EXPORT DisplayResourceProvider : public ResourceProvider { - public: - DisplayResourceProvider(viz::ContextProvider* compositor_context_provider, - viz::SharedBitmapManager* shared_bitmap_manager); - ~DisplayResourceProvider() override; - -#if defined(OS_ANDROID) - // Send an overlay promotion hint to all resources that requested it via - // |wants_promotion_hints_set_|. |promotable_hints| contains all the - // resources that should be told that they're promotable. Others will be told - // that they're not promotable right now. - void SendPromotionHints( - const OverlayCandidateList::PromotionHintInfoMap& promotion_hints); - - // Indicates if this resource is backed by an Android SurfaceTexture, and thus - // can't really be promoted to an overlay. - bool IsBackedBySurfaceTexture(viz::ResourceId id); - - // Indicates if this resource wants to receive promotion hints. - bool WantsPromotionHintForTesting(viz::ResourceId id); - - // Return the number of resources that request promotion hints. - size_t CountPromotionHintRequestsForTesting(); -#endif - - viz::ResourceType GetResourceType(viz::ResourceId id); - - // Return the format of the underlying buffer that can be used for scanout. - gfx::BufferFormat GetBufferFormat(viz::ResourceId id); - - // Indicates if this resource may be used for a hardware overlay plane. - bool IsOverlayCandidate(viz::ResourceId id); - - void WaitSyncToken(viz::ResourceId id); - - // Checks whether a resource is in use. - bool InUse(viz::ResourceId id); - - // The following lock classes are part of the DisplayResourceProvider API and - // are needed to read the resource contents. The user must ensure that they - // only use GL locks on GL resources, etc, and this is enforced by assertions. - class CC_EXPORT ScopedReadLockGL { - public: - ScopedReadLockGL(DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id); - ~ScopedReadLockGL(); - - GLuint texture_id() const { return texture_id_; } - GLenum target() const { return target_; } - const gfx::Size& size() const { return size_; } - const gfx::ColorSpace& color_space() const { return color_space_; } - - private: - DisplayResourceProvider* const resource_provider_; - const viz::ResourceId resource_id_; - - GLuint texture_id_ = 0; - GLenum target_ = GL_TEXTURE_2D; - gfx::Size size_; - gfx::ColorSpace color_space_; - - DISALLOW_COPY_AND_ASSIGN(ScopedReadLockGL); - }; - - class CC_EXPORT ScopedSamplerGL { - public: - ScopedSamplerGL(DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id, - GLenum filter); - ScopedSamplerGL(DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id, - GLenum unit, - GLenum filter); - ~ScopedSamplerGL(); - - GLuint texture_id() const { return resource_lock_.texture_id(); } - GLenum target() const { return target_; } - const gfx::ColorSpace& color_space() const { - return resource_lock_.color_space(); - } - - private: - const ScopedReadLockGL resource_lock_; - const GLenum unit_; - const GLenum target_; - - DISALLOW_COPY_AND_ASSIGN(ScopedSamplerGL); - }; - - class CC_EXPORT ScopedReadLockSkImage { - public: - ScopedReadLockSkImage(DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id); - ~ScopedReadLockSkImage(); - - const SkImage* sk_image() const { return sk_image_.get(); } - - bool valid() const { return !!sk_image_; } - - private: - DisplayResourceProvider* const resource_provider_; - const viz::ResourceId resource_id_; - sk_sp<SkImage> sk_image_; - - DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSkImage); - }; - - class CC_EXPORT ScopedReadLockSoftware { - public: - ScopedReadLockSoftware(DisplayResourceProvider* resource_provider, - viz::ResourceId resource_id); - ~ScopedReadLockSoftware(); - - const SkBitmap* sk_bitmap() const { - DCHECK(valid()); - return &sk_bitmap_; - } - - bool valid() const { return !!sk_bitmap_.getPixels(); } - - private: - DisplayResourceProvider* const resource_provider_; - const viz::ResourceId resource_id_; - SkBitmap sk_bitmap_; - - DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSoftware); - }; - - // Maintains set of lock for external use. - class CC_EXPORT LockSetForExternalUse { - public: - explicit LockSetForExternalUse(DisplayResourceProvider* resource_provider); - ~LockSetForExternalUse(); - - // Lock a resource for external use. - viz::ResourceMetadata LockResource(viz::ResourceId resource_id); - - // Unlock all locked resources with a |sync_token|. - // See UnlockForExternalUse for the detail. All resources must be unlocked - // before destroying this class. - void UnlockResources(const gpu::SyncToken& sync_token); - - private: - DisplayResourceProvider* const resource_provider_; - std::vector<viz::ResourceId> resources_; - - DISALLOW_COPY_AND_ASSIGN(LockSetForExternalUse); - }; - - // 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( - DisplayResourceProvider* resource_provider); - ~ScopedBatchReturnResources(); - - private: - DisplayResourceProvider* const resource_provider_; - - DISALLOW_COPY_AND_ASSIGN(ScopedBatchReturnResources); - }; - - class CC_EXPORT SynchronousFence : public viz::ResourceFence { - public: - explicit SynchronousFence(gpu::gles2::GLES2Interface* gl); - - // viz::ResourceFence implementation. - void Set() override; - bool HasPassed() override; - void Wait() override; - - // Returns true if fence has been set but not yet synchornized. - bool has_synchronized() const { return has_synchronized_; } - - private: - ~SynchronousFence() override; - - void Synchronize(); - - gpu::gles2::GLES2Interface* gl_; - bool has_synchronized_; - - DISALLOW_COPY_AND_ASSIGN(SynchronousFence); - }; - - // Sets the current read fence. If a resource is locked for read - // and has read fences enabled, the resource will not allow writes - // until this fence has passed. - void SetReadLockFence(viz::ResourceFence* fence) { - current_read_lock_fence_ = fence; - } - - // Creates accounting for a child. Returns a child ID. - int CreateChild(const ReturnCallback& return_callback); - - // Destroys accounting for the child, deleting all accounted resources. - void DestroyChild(int child); - - // Sets whether resources need sync points set on them when returned to this - // child. Defaults to true. - void SetChildNeedsSyncTokens(int child, bool needs_sync_tokens); - - // Gets the child->parent resource ID map. - const ResourceIdMap& GetChildToParentMap(int child) const; - - // Receives resources from a child, moving them from mailboxes. ResourceIds - // passed are in the child namespace, and will be translated to the parent - // namespace, added to the child->parent map. - // This adds the resources to the working set in the ResourceProvider without - // declaring which resources are in use. Use DeclareUsedResourcesFromChild - // after calling this method to do that. All calls to ReceiveFromChild should - // be followed by a DeclareUsedResourcesFromChild. - // NOTE: if the sync_token is set on any viz::TransferableResource, this will - // wait on it. - void ReceiveFromChild( - int child, - const std::vector<viz::TransferableResource>& transferable_resources); - - // Once a set of resources have been received, they may or may not be used. - // This declares what set of resources are currently in use from the child, - // releasing any other resources back to the child. - void DeclareUsedResourcesFromChild( - int child, - const viz::ResourceIdSet& resources_from_child); - - private: - const viz::internal::Resource* LockForRead(viz::ResourceId id); - void UnlockForRead(viz::ResourceId id); - - // Lock a resource for external use. - viz::ResourceMetadata LockForExternalUse(viz::ResourceId id); - - // Unlock a resource which locked by LockForExternalUse. - // The |sync_token| should be waited on before reusing the resouce's backing - // to ensure that any external use of it is completed. This |sync_token| - // should have been verified. - void UnlockForExternalUse(viz::ResourceId id, - const gpu::SyncToken& sync_token); - - void TryReleaseResource(ResourceMap::iterator it); - // Binds the given GL resource to a texture target for sampling using the - // specified filter for both minification and magnification. Returns the - // texture target used. The resource must be locked for reading. - GLenum BindForSampling(viz::ResourceId resource_id, - GLenum unit, - GLenum filter); - bool ReadLockFenceHasPassed(const viz::internal::Resource* resource); -#if defined(OS_ANDROID) - void DeletePromotionHint(ResourceMap::iterator it, DeleteStyle style); -#endif - - struct Child { - Child(); - Child(const Child& other); - ~Child(); - - ResourceIdMap child_to_parent_map; - ReturnCallback return_callback; - bool marked_for_deletion; - bool needs_sync_tokens; - }; - using ChildMap = std::unordered_map<int, Child>; - - void DeleteAndReturnUnusedResourcesToChild(ChildMap::iterator child_it, - DeleteStyle style, - const ResourceIdArray& unused); - void DestroyChildInternal(ChildMap::iterator it, DeleteStyle style); - - void SetBatchReturnResources(bool aggregate); - - scoped_refptr<viz::ResourceFence> current_read_lock_fence_; - ChildMap children_; - // Used as child id when creating a child. - int next_child_ = 1; - base::flat_map<viz::ResourceId, sk_sp<SkImage>> resource_sk_image_; - viz::ResourceId next_id_; - viz::SharedBitmapManager* shared_bitmap_manager_; - // 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::small_map<std::map<int, ResourceIdArray>> batched_returning_resources_; -#if defined(OS_ANDROID) - // Set of ResourceIds that would like to be notified about promotion hints. - viz::ResourceIdSet wants_promotion_hints_set_; -#endif - - DISALLOW_COPY_AND_ASSIGN(DisplayResourceProvider); -}; - -} // namespace cc - -#endif // CC_RESOURCES_DISPLAY_RESOURCE_PROVIDER_H_ diff --git a/chromium/cc/resources/display_resource_provider_unittest.cc b/chromium/cc/resources/display_resource_provider_unittest.cc deleted file mode 100644 index b8e3e5647bd..00000000000 --- a/chromium/cc/resources/display_resource_provider_unittest.cc +++ /dev/null @@ -1,548 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/resources/display_resource_provider.h" -#include "cc/resources/layer_tree_resource_provider.h" - -#include <stddef.h> -#include <stdint.h> - -#include <algorithm> -#include <map> -#include <memory> -#include <set> -#include <unordered_map> -#include <vector> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "cc/test/render_pass_test_utils.h" -#include "cc/test/resource_provider_test_utils.h" -#include "components/viz/common/resources/resource_format_utils.h" -#include "components/viz/common/resources/returned_resource.h" -#include "components/viz/common/resources/shared_bitmap_manager.h" -#include "components/viz/common/resources/single_release_callback.h" -#include "components/viz/test/test_context_provider.h" -#include "components/viz/test/test_gpu_memory_buffer_manager.h" -#include "components/viz/test/test_shared_bitmap_manager.h" -#include "components/viz/test/test_texture.h" -#include "components/viz/test/test_web_graphics_context_3d.h" -#include "gpu/GLES2/gl2extchromium.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/gpu_memory_buffer.h" - -namespace cc { -namespace { - -static const bool kUseGpuMemoryBufferResources = false; - -MATCHER_P(MatchesSyncToken, sync_token, "") { - gpu::SyncToken other; - memcpy(&other, arg, sizeof(other)); - return other == sync_token; -} - -static void ReleaseSharedBitmapCallback( - std::unique_ptr<viz::SharedBitmap> shared_bitmap, - bool* release_called, - gpu::SyncToken* release_sync_token, - bool* lost_resource_result, - const gpu::SyncToken& sync_token, - bool lost_resource) { - *release_called = true; - *release_sync_token = sync_token; - *lost_resource_result = lost_resource; -} - -static std::unique_ptr<viz::SharedBitmap> CreateAndFillSharedBitmap( - viz::SharedBitmapManager* manager, - const gfx::Size& size, - viz::ResourceFormat format, - uint32_t value) { - std::unique_ptr<viz::SharedBitmap> shared_bitmap = - manager->AllocateSharedBitmap(size, format); - CHECK(shared_bitmap); - uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_bitmap->pixels()); - CHECK(pixels); - std::fill_n(pixels, size.GetArea(), value); - return shared_bitmap; -} - -static viz::ResourceSettings CreateResourceSettings() { - viz::ResourceSettings resource_settings; - resource_settings.use_gpu_memory_buffer_resources = - kUseGpuMemoryBufferResources; - return resource_settings; -} - -// Shared data between multiple ResourceProviderContext. This contains mailbox -// contents as well as information about sync points. -class ContextSharedData { - public: - static std::unique_ptr<ContextSharedData> Create() { - return base::WrapUnique(new ContextSharedData()); - } - - uint32_t InsertFenceSync() { return next_fence_sync_++; } - - void GenMailbox(GLbyte* mailbox) { - memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM); - memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_)); - ++next_mailbox_; - } - - void ProduceTexture(const GLbyte* mailbox_name, - const gpu::SyncToken& sync_token, - scoped_refptr<viz::TestTexture> texture) { - uint32_t sync_point = static_cast<uint32_t>(sync_token.release_count()); - - unsigned mailbox = 0; - memcpy(&mailbox, mailbox_name, sizeof(mailbox)); - ASSERT_TRUE(mailbox && mailbox < next_mailbox_); - textures_[mailbox] = texture; - ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point); - sync_point_for_mailbox_[mailbox] = sync_point; - } - - scoped_refptr<viz::TestTexture> ConsumeTexture( - const GLbyte* mailbox_name, - const gpu::SyncToken& sync_token) { - unsigned mailbox = 0; - memcpy(&mailbox, mailbox_name, sizeof(mailbox)); - DCHECK(mailbox && mailbox < next_mailbox_); - - // If the latest sync point the context has waited on is before the sync - // point for when the mailbox was set, pretend we never saw that - // ProduceTexture. - if (sync_point_for_mailbox_[mailbox] > sync_token.release_count()) { - NOTREACHED(); - return scoped_refptr<viz::TestTexture>(); - } - return textures_[mailbox]; - } - - private: - ContextSharedData() : next_fence_sync_(1), next_mailbox_(1) {} - - uint64_t next_fence_sync_; - unsigned next_mailbox_; - using TextureMap = - std::unordered_map<unsigned, scoped_refptr<viz::TestTexture>>; - TextureMap textures_; - std::unordered_map<unsigned, uint32_t> sync_point_for_mailbox_; -}; - -class ResourceProviderContext : public viz::TestWebGraphicsContext3D { - public: - static std::unique_ptr<ResourceProviderContext> Create( - ContextSharedData* shared_data) { - return base::WrapUnique(new ResourceProviderContext(shared_data)); - } - - void genSyncToken(GLbyte* sync_token) override { - uint64_t fence_sync = shared_data_->InsertFenceSync(); - gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x123), - fence_sync); - sync_token_data.SetVerifyFlush(); - // Commit the ProduceTextureDirectCHROMIUM calls at this point, so that - // they're associated with the sync point. - for (const std::unique_ptr<PendingProduceTexture>& pending_texture : - pending_produce_textures_) { - shared_data_->ProduceTexture(pending_texture->mailbox, sync_token_data, - pending_texture->texture); - } - pending_produce_textures_.clear(); - memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); - } - - void waitSyncToken(const GLbyte* sync_token) override { - gpu::SyncToken sync_token_data; - if (sync_token) - memcpy(&sync_token_data, sync_token, sizeof(sync_token_data)); - - if (sync_token_data.release_count() > - last_waited_sync_token_.release_count()) { - last_waited_sync_token_ = sync_token_data; - } - } - - const gpu::SyncToken& last_waited_sync_token() const { - return last_waited_sync_token_; - } - - void texStorage2DEXT(GLenum target, - GLint levels, - GLuint internalformat, - GLint width, - GLint height) override { - CheckTextureIsBound(target); - ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); - ASSERT_EQ(1, levels); - GLenum format = GL_RGBA; - switch (internalformat) { - case GL_RGBA8_OES: - break; - case GL_BGRA8_EXT: - format = GL_BGRA_EXT; - break; - default: - NOTREACHED(); - } - AllocateTexture(gfx::Size(width, height), format); - } - - void texImage2D(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void* pixels) override { - CheckTextureIsBound(target); - ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); - ASSERT_FALSE(level); - ASSERT_EQ(internalformat, format); - ASSERT_FALSE(border); - ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); - AllocateTexture(gfx::Size(width, height), format); - if (pixels) - SetPixels(0, 0, width, height, pixels); - } - - void texSubImage2D(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void* pixels) override { - CheckTextureIsBound(target); - ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); - ASSERT_FALSE(level); - ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); - { - base::AutoLock lock_for_texture_access(namespace_->lock); - ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format); - } - ASSERT_TRUE(pixels); - SetPixels(xoffset, yoffset, width, height, pixels); - } - - void genMailboxCHROMIUM(GLbyte* mailbox) override { - return shared_data_->GenMailbox(mailbox); - } - - void produceTextureDirectCHROMIUM(GLuint texture, - const GLbyte* mailbox) override { - // Delay moving the texture into the mailbox until the next - // sync token, so that it is not visible to other contexts that - // haven't waited on that sync point. - std::unique_ptr<PendingProduceTexture> pending(new PendingProduceTexture); - memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox)); - base::AutoLock lock_for_texture_access(namespace_->lock); - pending->texture = UnboundTexture(texture); - pending_produce_textures_.push_back(std::move(pending)); - } - - GLuint createAndConsumeTextureCHROMIUM(const GLbyte* mailbox) override { - GLuint texture_id = createTexture(); - base::AutoLock lock_for_texture_access(namespace_->lock); - scoped_refptr<viz::TestTexture> texture = - shared_data_->ConsumeTexture(mailbox, last_waited_sync_token_); - namespace_->textures.Replace(texture_id, texture); - return texture_id; - } - - void GetPixels(const gfx::Size& size, - viz::ResourceFormat format, - uint8_t* pixels) { - CheckTextureIsBound(GL_TEXTURE_2D); - base::AutoLock lock_for_texture_access(namespace_->lock); - scoped_refptr<viz::TestTexture> texture = BoundTexture(GL_TEXTURE_2D); - ASSERT_EQ(texture->size, size); - ASSERT_EQ(texture->format, format); - memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format)); - } - - protected: - explicit ResourceProviderContext(ContextSharedData* shared_data) - : shared_data_(shared_data) {} - - private: - void AllocateTexture(const gfx::Size& size, GLenum format) { - CheckTextureIsBound(GL_TEXTURE_2D); - viz::ResourceFormat texture_format = viz::RGBA_8888; - switch (format) { - case GL_RGBA: - texture_format = viz::RGBA_8888; - break; - case GL_BGRA_EXT: - texture_format = viz::BGRA_8888; - break; - } - base::AutoLock lock_for_texture_access(namespace_->lock); - BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format); - } - - void SetPixels(int xoffset, - int yoffset, - int width, - int height, - const void* pixels) { - CheckTextureIsBound(GL_TEXTURE_2D); - base::AutoLock lock_for_texture_access(namespace_->lock); - scoped_refptr<viz::TestTexture> texture = BoundTexture(GL_TEXTURE_2D); - ASSERT_TRUE(texture->data.get()); - ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width()); - ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height()); - ASSERT_TRUE(pixels); - size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format); - size_t out_pitch = - TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format); - uint8_t* dest = texture->data.get() + yoffset * out_pitch + - TextureSizeBytes(gfx::Size(xoffset, 1), texture->format); - const uint8_t* src = static_cast<const uint8_t*>(pixels); - for (int i = 0; i < height; ++i) { - memcpy(dest, src, in_pitch); - dest += out_pitch; - src += in_pitch; - } - } - - struct PendingProduceTexture { - GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; - scoped_refptr<viz::TestTexture> texture; - }; - ContextSharedData* shared_data_; - gpu::SyncToken last_waited_sync_token_; - std::vector<std::unique_ptr<PendingProduceTexture>> pending_produce_textures_; -}; - -class DisplayResourceProviderTest : public testing::TestWithParam<bool> { - public: - explicit DisplayResourceProviderTest(bool child_needs_sync_token) - : use_gpu_(GetParam()), - child_needs_sync_token_(child_needs_sync_token), - shared_data_(ContextSharedData::Create()) { - if (use_gpu_) { - auto context3d(ResourceProviderContext::Create(shared_data_.get())); - context3d_ = context3d.get(); - context_provider_ = - viz::TestContextProvider::Create(std::move(context3d)); - context_provider_->UnboundTestContext3d() - ->set_support_texture_format_bgra8888(true); - context_provider_->BindToCurrentThread(); - - auto child_context_owned = - ResourceProviderContext::Create(shared_data_.get()); - child_context_ = child_context_owned.get(); - child_context_provider_ = - viz::TestContextProvider::Create(std::move(child_context_owned)); - child_context_provider_->UnboundTestContext3d() - ->set_support_texture_format_bgra8888(true); - child_context_provider_->BindToCurrentThread(); - gpu_memory_buffer_manager_ = - std::make_unique<viz::TestGpuMemoryBufferManager>(); - child_gpu_memory_buffer_manager_ = - gpu_memory_buffer_manager_->CreateClientGpuMemoryBufferManager(); - } else { - shared_bitmap_manager_ = std::make_unique<viz::TestSharedBitmapManager>(); - } - - resource_provider_ = std::make_unique<DisplayResourceProvider>( - context_provider_.get(), shared_bitmap_manager_.get()); - - MakeChildResourceProvider(); - } - - DisplayResourceProviderTest() : DisplayResourceProviderTest(true) {} - - bool use_gpu() const { return use_gpu_; } - - void MakeChildResourceProvider() { - child_resource_provider_ = std::make_unique<LayerTreeResourceProvider>( - child_context_provider_.get(), shared_bitmap_manager_.get(), - child_gpu_memory_buffer_manager_.get(), child_needs_sync_token_, - CreateResourceSettings()); - } - - static void CollectResources( - std::vector<viz::ReturnedResource>* array, - const std::vector<viz::ReturnedResource>& returned) { - array->insert(array->end(), returned.begin(), returned.end()); - } - - static ReturnCallback GetReturnCallback( - std::vector<viz::ReturnedResource>* array) { - return base::BindRepeating(&DisplayResourceProviderTest::CollectResources, - array); - } - - static void SetResourceFilter(DisplayResourceProvider* resource_provider, - viz::ResourceId id, - GLenum filter) { - DisplayResourceProvider::ScopedSamplerGL sampler(resource_provider, id, - GL_TEXTURE_2D, filter); - } - - ResourceProviderContext* context() { return context3d_; } - - viz::ResourceId CreateChildMailbox(gpu::SyncToken* release_sync_token, - bool* lost_resource, - bool* release_called, - gpu::SyncToken* sync_token, - viz::ResourceFormat format) { - if (use_gpu()) { - unsigned texture = child_context_->createTexture(); - gpu::Mailbox gpu_mailbox; - child_context_->genMailboxCHROMIUM(gpu_mailbox.name); - child_context_->produceTextureDirectCHROMIUM(texture, gpu_mailbox.name); - child_context_->genSyncToken(sync_token->GetData()); - EXPECT_TRUE(sync_token->HasData()); - - std::unique_ptr<viz::SharedBitmap> shared_bitmap; - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::BindRepeating( - ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), - release_called, release_sync_token, lost_resource)); - viz::TransferableResource gl_resource = viz::TransferableResource::MakeGL( - gpu_mailbox, GL_LINEAR, GL_TEXTURE_2D, *sync_token); - gl_resource.format = format; - return child_resource_provider_->ImportResource(gl_resource, - std::move(callback)); - } else { - gfx::Size size(64, 64); - std::unique_ptr<viz::SharedBitmap> shared_bitmap( - CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, format, - 0)); - - viz::SharedBitmap* shared_bitmap_ptr = shared_bitmap.get(); - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::BindRepeating( - ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), - release_called, release_sync_token, lost_resource)); - return child_resource_provider_->ImportResource( - viz::TransferableResource::MakeSoftware( - shared_bitmap_ptr->id(), shared_bitmap_ptr->sequence_number(), - size, format), - std::move(callback)); - } - } - - viz::ResourceId MakeGpuResourceAndSendToDisplay( - char c, - GLuint filter, - GLuint target, - const gpu::SyncToken& sync_token, - DisplayResourceProvider* resource_provider) { - ReturnCallback return_callback = base::DoNothing(); - - int child = resource_provider->CreateChild(return_callback); - - gpu::Mailbox gpu_mailbox; - gpu_mailbox.name[0] = c; - gpu_mailbox.name[1] = 0; - auto resource = viz::TransferableResource::MakeGL(gpu_mailbox, GL_LINEAR, - target, sync_token); - resource.id = 11; - resource_provider->ReceiveFromChild(child, {resource}); - auto& map = resource_provider->GetChildToParentMap(child); - return map.find(resource.id)->second; - } - - protected: - const bool use_gpu_; - const bool child_needs_sync_token_; - const std::unique_ptr<ContextSharedData> shared_data_; - ResourceProviderContext* context3d_ = nullptr; - ResourceProviderContext* child_context_ = nullptr; - scoped_refptr<viz::TestContextProvider> context_provider_; - scoped_refptr<viz::TestContextProvider> child_context_provider_; - std::unique_ptr<viz::TestGpuMemoryBufferManager> gpu_memory_buffer_manager_; - std::unique_ptr<DisplayResourceProvider> resource_provider_; - std::unique_ptr<viz::TestGpuMemoryBufferManager> - child_gpu_memory_buffer_manager_; - std::unique_ptr<LayerTreeResourceProvider> child_resource_provider_; - std::unique_ptr<viz::TestSharedBitmapManager> shared_bitmap_manager_; -}; - -INSTANTIATE_TEST_CASE_P(DisplayResourceProviderTests, - DisplayResourceProviderTest, - ::testing::Values(false, true)); - -TEST_P(DisplayResourceProviderTest, LockForExternalUse) { - // TODO(penghuang): consider supporting SW mode. - if (!use_gpu()) - return; - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - uint8_t data1[4] = {1, 2, 3, 4}; - child_resource_provider_->CopyToResource(id1, data1, size); - std::vector<viz::ReturnedResource> 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; - resource_ids_to_transfer.push_back(id1); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(1u, list.size()); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - - resource_provider_->ReceiveFromChild(child_id, list); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - - unsigned parent_id = resource_map[list.front().id]; - - DisplayResourceProvider::LockSetForExternalUse lock_set( - resource_provider_.get()); - - viz::ResourceMetadata metadata = lock_set.LockResource(parent_id); - ASSERT_EQ(size, metadata.size); - ASSERT_FALSE(metadata.mailbox.IsZero()); - ASSERT_TRUE(metadata.sync_token.HasData()); - - resource_provider_->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - // The resource should not be returned due to the external use lock. - EXPECT_EQ(0u, returned_to_child.size()); - - gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x234), - 0x456); - sync_token.SetVerifyFlush(); - lock_set.UnlockResources(sync_token); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - // The resource should be returned after the lock is released. - EXPECT_EQ(1u, returned_to_child.size()); - EXPECT_EQ(sync_token, returned_to_child[0].sync_token); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - child_resource_provider_->DeleteResource(id1); - EXPECT_EQ(0u, child_resource_provider_->num_resources()); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/resources/layer_tree_resource_provider.cc b/chromium/cc/resources/layer_tree_resource_provider.cc index 44720a3ffcb..df7c76ca592 100644 --- a/chromium/cc/resources/layer_tree_resource_provider.cc +++ b/chromium/cc/resources/layer_tree_resource_provider.cc @@ -8,73 +8,20 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "components/viz/common/gpu/context_provider.h" -#include "components/viz/common/resources/platform_color.h" #include "components/viz/common/resources/resource_format_utils.h" #include "components/viz/common/resources/resource_sizes.h" -#include "components/viz/common/resources/shared_bitmap_manager.h" +#include "components/viz/common/resources/returned_resource.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" -#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "gpu/command_buffer/client/raster_interface.h" #include "gpu/command_buffer/common/capabilities.h" -#include "gpu/command_buffer/common/gpu_memory_buffer_support.h" #include "third_party/skia/include/core/SkCanvas.h" using gpu::gles2::GLES2Interface; namespace cc { -LayerTreeResourceProvider::Settings::Settings( - viz::ContextProvider* compositor_context_provider, - bool delegated_sync_points_required, - const viz::ResourceSettings& resource_settings) - : yuv_highbit_resource_format(resource_settings.high_bit_for_testing - ? viz::R16_EXT - : viz::LUMINANCE_8), - use_gpu_memory_buffer_resources( - resource_settings.use_gpu_memory_buffer_resources), - delegated_sync_points_required(delegated_sync_points_required) { - if (!compositor_context_provider) { - // Pick an arbitrary limit here similar to what hardware might. - max_texture_size = 16 * 1024; - best_texture_format = viz::RGBA_8888; - return; - } - - const auto& caps = compositor_context_provider->ContextCapabilities(); - use_texture_storage = caps.texture_storage; - use_texture_format_bgra = caps.texture_format_bgra8888; - use_texture_usage_hint = caps.texture_usage; - use_texture_npot = caps.texture_npot; - use_sync_query = caps.sync_query; - use_texture_storage_image = caps.texture_storage_image; - - if (caps.disable_one_component_textures) { - yuv_resource_format = yuv_highbit_resource_format = viz::RGBA_8888; - } else { - yuv_resource_format = caps.texture_rg ? viz::RED_8 : viz::LUMINANCE_8; - if (resource_settings.use_r16_texture && caps.texture_norm16) - yuv_highbit_resource_format = viz::R16_EXT; - else if (caps.texture_half_float_linear) - yuv_highbit_resource_format = viz::LUMINANCE_F16; - } - - GLES2Interface* gl = compositor_context_provider->ContextGL(); - gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); - - best_texture_format = - viz::PlatformColor::BestSupportedTextureFormat(use_texture_format_bgra); - best_render_buffer_format = viz::PlatformColor::BestSupportedTextureFormat( - caps.render_buffer_format_bgra8888); -} - -namespace { -// The resource id in LayerTreeResourceProvider starts from 1 to avoid -// conflicts with id from DisplayResourceProvider. -const unsigned int kLayerTreeInitialResourceId = 1; -} // namespace - struct LayerTreeResourceProvider::ImportedResource { viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; @@ -105,17 +52,10 @@ struct LayerTreeResourceProvider::ImportedResource { LayerTreeResourceProvider::LayerTreeResourceProvider( viz::ContextProvider* compositor_context_provider, - viz::SharedBitmapManager* shared_bitmap_manager, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - bool delegated_sync_points_required, - const viz::ResourceSettings& resource_settings) - : ResourceProvider(compositor_context_provider), - settings_(compositor_context_provider, - delegated_sync_points_required, - resource_settings), - shared_bitmap_manager_(shared_bitmap_manager), - gpu_memory_buffer_manager_(gpu_memory_buffer_manager), - next_id_(kLayerTreeInitialResourceId) { + bool delegated_sync_points_required) + : delegated_sync_points_required_(delegated_sync_points_required), + compositor_context_provider_(compositor_context_provider) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } LayerTreeResourceProvider::~LayerTreeResourceProvider() { @@ -126,9 +66,6 @@ LayerTreeResourceProvider::~LayerTreeResourceProvider() { bool is_lost = imported.exported_count || imported.returned_lost; imported.release_callback->Run(imported.returned_sync_token, is_lost); } - GLES2Interface* gl = ContextGL(); - if (gl) - gl->Finish(); } gpu::SyncToken LayerTreeResourceProvider::GenerateSyncTokenHelper( @@ -151,64 +88,27 @@ gpu::SyncToken LayerTreeResourceProvider::GenerateSyncTokenHelper( return sync_token; } -gpu::SyncToken LayerTreeResourceProvider::GetSyncTokenForResources( - const ResourceIdArray& resource_ids) { - gpu::SyncToken latest_sync_token; - for (viz::ResourceId id : resource_ids) { - const gpu::SyncToken& sync_token = GetResource(id)->sync_token(); - if (sync_token.release_count() > latest_sync_token.release_count()) - latest_sync_token = sync_token; - } - return latest_sync_token; -} - -gfx::ColorSpace LayerTreeResourceProvider::GetResourceColorSpaceForRaster( - const viz::internal::Resource* resource) const { - return resource->color_space; -} - void LayerTreeResourceProvider::PrepareSendToParent( - const ResourceIdArray& export_ids, - std::vector<viz::TransferableResource>* list) { + const std::vector<viz::ResourceId>& export_ids, + std::vector<viz::TransferableResource>* list, + viz::ContextProvider* context_provider) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - GLES2Interface* gl = ContextGL(); // This function goes through the array multiple times, store the resources // as pointers so we don't have to look up the resource id multiple times. // Make sure the maps do not change while these vectors are alive or they // will become invalid. - std::vector<std::pair<viz::internal::Resource*, viz::ResourceId>> resources; std::vector<ImportedResource*> imports; - resources.reserve(export_ids.size()); imports.reserve(export_ids.size()); for (const viz::ResourceId id : export_ids) { auto it = imported_resources_.find(id); - if (it != imported_resources_.end()) - imports.push_back(&it->second); - else - resources.push_back({GetResource(id), id}); + DCHECK(it != imported_resources_.end()); + imports.push_back(&it->second); } - DCHECK_EQ(resources.size() + imports.size(), export_ids.size()); // Lazily create any mailboxes and verify all unverified sync tokens. std::vector<GLbyte*> unverified_sync_tokens; - std::vector<viz::internal::Resource*> need_synchronization_resources; - for (auto& pair : resources) { - viz::internal::Resource* resource = pair.first; - if (!resource->is_gpu_resource_type()) - continue; - - CreateMailbox(resource); - - if (settings_.delegated_sync_points_required) { - if (resource->needs_sync_token()) { - need_synchronization_resources.push_back(resource); - } else if (!resource->sync_token().verified_flush()) { - unverified_sync_tokens.push_back(resource->GetSyncTokenData()); - } - } - } - if (settings_.delegated_sync_points_required) { + if (delegated_sync_points_required_) { for (ImportedResource* imported : imports) { if (!imported->resource.is_software && !imported->resource.mailbox_holder.sync_token.verified_flush()) { @@ -218,49 +118,13 @@ void LayerTreeResourceProvider::PrepareSendToParent( } } - // Insert sync point to synchronize the mailbox creation or bound textures. - gpu::SyncToken new_sync_token; - if (!need_synchronization_resources.empty()) { - DCHECK(settings_.delegated_sync_points_required); - DCHECK(gl); - gl->GenUnverifiedSyncTokenCHROMIUM(new_sync_token.GetData()); - unverified_sync_tokens.push_back(new_sync_token.GetData()); - } - - if (compositor_context_provider_) - compositor_context_provider_->ContextSupport()->FlushPendingWork(); - if (!unverified_sync_tokens.empty()) { - DCHECK(settings_.delegated_sync_points_required); - DCHECK(gl); - gl->VerifySyncTokensCHROMIUM(unverified_sync_tokens.data(), - unverified_sync_tokens.size()); - } - - // Set sync token after verification. - for (viz::internal::Resource* resource : need_synchronization_resources) { - DCHECK(resource->is_gpu_resource_type()); - resource->UpdateSyncToken(new_sync_token); - resource->SetSynchronized(); + DCHECK(delegated_sync_points_required_); + DCHECK(context_provider); + context_provider->ContextGL()->VerifySyncTokensCHROMIUM( + unverified_sync_tokens.data(), unverified_sync_tokens.size()); } - // Transfer Resources. - for (size_t i = 0; i < resources.size(); ++i) { - viz::internal::Resource* source = resources[i].first; - const viz::ResourceId id = resources[i].second; - - DCHECK(!settings_.delegated_sync_points_required || - !source->needs_sync_token()); - DCHECK(!settings_.delegated_sync_points_required || - viz::internal::Resource::LOCALLY_USED != - source->synchronization_state()); - - viz::TransferableResource resource; - TransferResource(source, id, &resource); - - source->exported_count++; - list->push_back(std::move(resource)); - } for (ImportedResource* imported : imports) { list->push_back(imported->resource); imported->exported_count++; @@ -270,177 +134,31 @@ void LayerTreeResourceProvider::PrepareSendToParent( void LayerTreeResourceProvider::ReceiveReturnsFromParent( const std::vector<viz::ReturnedResource>& resources) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - GLES2Interface* gl = ContextGL(); for (const viz::ReturnedResource& returned : resources) { viz::ResourceId local_id = returned.id; auto import_it = imported_resources_.find(local_id); - if (import_it != imported_resources_.end()) { - ImportedResource& imported = import_it->second; - - DCHECK_GE(imported.exported_count, returned.count); - imported.exported_count -= returned.count; - imported.returned_lost |= returned.lost; - - if (imported.exported_count) - continue; - - if (returned.sync_token.HasData()) { - DCHECK(!imported.resource.is_software); - imported.returned_sync_token = returned.sync_token; - } - - if (imported.marked_for_deletion) { - imported.release_callback->Run(imported.returned_sync_token, - imported.returned_lost); - imported_resources_.erase(import_it); - } - - continue; - } - - auto map_iterator = resources_.find(local_id); - DCHECK(map_iterator != resources_.end()); - // Resource was already lost (e.g. it belonged to a child that was - // destroyed). - // TODO(danakj): Remove this. There is no "child" here anymore, and - // lost resources are still in the map until exported_count == 0. - if (map_iterator == resources_.end()) - continue; + DCHECK(import_it != imported_resources_.end()); + ImportedResource& imported = import_it->second; - viz::internal::Resource* resource = &map_iterator->second; + DCHECK_GE(imported.exported_count, returned.count); + imported.exported_count -= returned.count; + imported.returned_lost |= returned.lost; - DCHECK_GE(resource->exported_count, returned.count); - resource->exported_count -= returned.count; - resource->lost |= returned.lost; - if (resource->exported_count) + if (imported.exported_count) continue; if (returned.sync_token.HasData()) { - DCHECK(!resource->has_shared_bitmap_id); - if (resource->origin == viz::internal::Resource::INTERNAL) { - DCHECK(resource->gl_id); - gl->WaitSyncTokenCHROMIUM(returned.sync_token.GetConstData()); - resource->SetSynchronized(); - } else { - DCHECK(!resource->gl_id); - resource->UpdateSyncToken(returned.sync_token); - } + DCHECK(!imported.resource.is_software); + imported.returned_sync_token = returned.sync_token; } - if (!resource->marked_for_deletion) - continue; - - // The resource belongs to this LayerTreeResourceProvider, so it can be - // destroyed. - DeleteResourceInternal(map_iterator, NORMAL); - } -} - -viz::ResourceId LayerTreeResourceProvider::CreateGpuTextureResource( - const gfx::Size& size, - viz::ResourceTextureHint hint, - viz::ResourceFormat format, - const gfx::ColorSpace& color_space) { - DCHECK(compositor_context_provider_); - DCHECK(!size.IsEmpty()); - DCHECK_LE(size.width(), settings_.max_texture_size); - DCHECK_LE(size.height(), settings_.max_texture_size); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(IsTextureFormatSupported(format)); - - bool use_overlay = settings_.use_gpu_memory_buffer_resources || - (hint & viz::ResourceTextureHint::kOverlay); - DCHECK(!use_overlay || !(hint & viz::ResourceTextureHint::kMipmap)); - - viz::ResourceId id = next_id_++; - viz::internal::Resource* resource = - InsertResource(id, viz::internal::Resource( - size, viz::internal::Resource::INTERNAL, hint, - viz::ResourceType::kTexture, format, color_space)); - if (use_overlay && settings_.use_texture_storage_image && - viz::IsGpuMemoryBufferFormatSupported(format)) { - resource->usage = gfx::BufferUsage::SCANOUT; - resource->target = GetImageTextureTarget( - compositor_context_provider_->ContextCapabilities(), resource->usage, - format); - resource->buffer_format = BufferFormat(format); - resource->is_overlay_candidate = true; - } - return id; -} - -viz::ResourceId LayerTreeResourceProvider::CreateGpuMemoryBufferResource( - const gfx::Size& size, - viz::ResourceTextureHint hint, - viz::ResourceFormat format, - gfx::BufferUsage usage, - const gfx::ColorSpace& color_space) { - DCHECK(compositor_context_provider_); - DCHECK(!size.IsEmpty()); - DCHECK(compositor_context_provider_); - DCHECK_LE(size.width(), settings_.max_texture_size); - DCHECK_LE(size.height(), settings_.max_texture_size); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - viz::ResourceId id = next_id_++; - viz::internal::Resource* resource = InsertResource( - id, viz::internal::Resource(size, viz::internal::Resource::INTERNAL, hint, - viz::ResourceType::kGpuMemoryBuffer, format, - color_space)); - resource->target = GetImageTextureTarget( - compositor_context_provider_->ContextCapabilities(), usage, format); - resource->buffer_format = BufferFormat(format); - resource->usage = usage; - resource->is_overlay_candidate = true; - // GpuMemoryBuffer provides direct access to the memory used by the GPU. Read - // lock fences are required to ensure that we're not trying to map a buffer - // that is currently in-use by the GPU. - resource->read_lock_fences_enabled = true; - return id; -} - -viz::ResourceId LayerTreeResourceProvider::CreateBitmapResource( - const gfx::Size& size, - const gfx::ColorSpace& color_space, - viz::ResourceFormat format) { - DCHECK(!compositor_context_provider_); - DCHECK(!size.IsEmpty()); - DCHECK(viz::IsBitmapFormatSupported(format)); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - // TODO(danakj): Allocate this outside ResourceProvider. - std::unique_ptr<viz::SharedBitmap> bitmap = - shared_bitmap_manager_->AllocateSharedBitmap(size, format); - DCHECK(bitmap); - DCHECK(bitmap->pixels()); - - viz::ResourceId id = next_id_++; - viz::internal::Resource* resource = InsertResource( - id, - viz::internal::Resource(size, viz::internal::Resource::INTERNAL, - viz::ResourceTextureHint::kDefault, - viz::ResourceType::kBitmap, format, color_space)); - resource->SetSharedBitmap(bitmap.get()); - resource->owned_shared_bitmap = std::move(bitmap); - return id; -} - -void LayerTreeResourceProvider::DeleteResource(viz::ResourceId id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - ResourceMap::iterator it = resources_.find(id); - CHECK(it != resources_.end()); - viz::internal::Resource* resource = &it->second; - DCHECK(!resource->marked_for_deletion); - DCHECK_EQ(resource->imported_count, 0); - DCHECK(!resource->locked_for_write); - - if (resource->exported_count > 0) { - resource->marked_for_deletion = true; - return; - } else { - DeleteResourceInternal(it, NORMAL); + if (imported.marked_for_deletion) { + imported.release_callback->Run(imported.returned_sync_token, + imported.returned_lost); + imported_resources_.erase(import_it); + } } } @@ -468,223 +186,6 @@ void LayerTreeResourceProvider::RemoveImportedResource(viz::ResourceId id) { } } -void LayerTreeResourceProvider::CopyToResource(viz::ResourceId id, - const uint8_t* image, - const gfx::Size& image_size) { - viz::internal::Resource* resource = GetResource(id); - DCHECK(!resource->locked_for_write); - DCHECK_EQ(resource->origin, viz::internal::Resource::INTERNAL); - DCHECK_NE(resource->synchronization_state(), - viz::internal::Resource::NEEDS_WAIT); - DCHECK_EQ(resource->exported_count, 0); - - DCHECK_EQ(image_size.width(), resource->size.width()); - DCHECK_EQ(image_size.height(), resource->size.height()); - - if (resource->type == viz::ResourceType::kBitmap) { - DCHECK_EQ(viz::ResourceType::kBitmap, resource->type); - DCHECK(resource->allocated); - DCHECK_EQ(viz::RGBA_8888, resource->format); - SkImageInfo source_info = - SkImageInfo::MakeN32Premul(image_size.width(), image_size.height()); - size_t image_stride = image_size.width() * 4; - - ScopedWriteLockSoftware lock(this, id); - SkCanvas dest(lock.sk_bitmap()); - dest.writePixels(source_info, image, image_stride, 0, 0); - } else { - // No sync token needed because the lock will set synchronization state to - // LOCALLY_USED and a sync token will be generated in PrepareSendToParent. - ScopedWriteLockGL lock(this, id); - GLuint texture_id = lock.GetTexture(); - DCHECK(texture_id); - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - gl->BindTexture(resource->target, texture_id); - if (resource->format == viz::ETC1) { - DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); - int image_bytes = - viz::ResourceSizes::CheckedSizeInBytes<int>(image_size, viz::ETC1); - gl->CompressedTexImage2D(resource->target, 0, GLInternalFormat(viz::ETC1), - image_size.width(), image_size.height(), 0, - image_bytes, image); - lock.set_allocated(); - } else { - gl->TexSubImage2D(resource->target, 0, 0, 0, image_size.width(), - image_size.height(), GLDataFormat(resource->format), - GLDataType(resource->format), image); - } - } - DCHECK(resource->allocated); -} - -void LayerTreeResourceProvider::CreateForTesting(viz::ResourceId id) { - CreateTexture(GetResource(id)); -} - -void LayerTreeResourceProvider::CreateTexture( - viz::internal::Resource* resource) { - if (!resource->is_gpu_resource_type()) - return; - - if (resource->gl_id) - return; - - DCHECK_EQ(resource->origin, viz::internal::Resource::INTERNAL); - DCHECK(resource->mailbox.IsZero()); - - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - - // Create and set texture properties. Allocation of the texture backing is - // delayed until needed. - gl->GenTextures(1, &resource->gl_id); - gl->BindTexture(resource->target, resource->gl_id); - gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER, - resource->original_filter); - gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER, - resource->original_filter); - gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (settings_.use_texture_usage_hint && - (resource->hint & viz::ResourceTextureHint::kFramebuffer)) { - gl->TexParameteri(resource->target, GL_TEXTURE_USAGE_ANGLE, - GL_FRAMEBUFFER_ATTACHMENT_ANGLE); - } -} - -void LayerTreeResourceProvider::CreateMailbox( - viz::internal::Resource* resource) { - if (!resource->is_gpu_resource_type()) - return; - - if (!resource->mailbox.IsZero()) - return; - - CreateTexture(resource); - - DCHECK(resource->gl_id); - DCHECK_EQ(resource->origin, viz::internal::Resource::INTERNAL); - - gpu::gles2::GLES2Interface* gl = ContextGL(); - DCHECK(gl); - gl->GenMailboxCHROMIUM(resource->mailbox.name); - gl->ProduceTextureDirectCHROMIUM(resource->gl_id, resource->mailbox.name); - resource->SetLocallyUsed(); -} - -void LayerTreeResourceProvider::CreateAndBindImage( - viz::internal::Resource* resource) { - DCHECK(resource->gpu_memory_buffer); -#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) - // TODO(reveman): This avoids a performance problem on ARM ChromeOS - // devices. This only works with shared memory backed buffers. - // https://crbug.com/580166 - DCHECK_EQ(resource->gpu_memory_buffer->GetHandle().type, - gfx::SHARED_MEMORY_BUFFER); -#endif - CreateTexture(resource); - - gpu::gles2::GLES2Interface* gl = ContextGL(); - DCHECK(gl); - - gl->BindTexture(resource->target, resource->gl_id); - - if (!resource->image_id) { - resource->image_id = gl->CreateImageCHROMIUM( - resource->gpu_memory_buffer->AsClientBuffer(), resource->size.width(), - resource->size.height(), GLInternalFormat(resource->format)); - - DCHECK(resource->image_id || - gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR); - - gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id); - } else { - gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->image_id); - gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id); - } -} - -void LayerTreeResourceProvider::AllocateForTesting(viz::ResourceId id) { - viz::internal::Resource* resource = GetResource(id); - if (!resource->allocated) { - // Software and external resources are marked allocated on creation. - DCHECK(resource->is_gpu_resource_type()); - DCHECK_EQ(resource->origin, viz::internal::Resource::INTERNAL); - ScopedWriteLockGL resource_lock(this, id); - resource_lock.GetTexture(); // Allocates texture. - } -} - -void LayerTreeResourceProvider::TransferResource( - viz::internal::Resource* source, - viz::ResourceId id, - viz::TransferableResource* resource) { - DCHECK(!source->locked_for_write); - DCHECK(source->allocated); - resource->id = id; - resource->format = source->format; - resource->buffer_format = source->buffer_format; - resource->filter = source->filter; - resource->size = source->size; - resource->read_lock_fences_enabled = source->read_lock_fences_enabled; - resource->is_overlay_candidate = source->is_overlay_candidate; - resource->color_space = source->color_space; - - if (source->type == viz::ResourceType::kBitmap) { - DCHECK(source->shared_bitmap); - resource->mailbox_holder.mailbox = source->shared_bitmap_id; - resource->is_software = true; - resource->shared_bitmap_sequence_number = - source->shared_bitmap->sequence_number(); - } else { - DCHECK(!source->mailbox.IsZero()); - // This is either an external resource, or a compositor resource that we - // already exported. Make sure to forward the sync point that we were given. - resource->mailbox_holder.mailbox = source->mailbox; - resource->mailbox_holder.texture_target = source->target; - resource->mailbox_holder.sync_token = source->sync_token(); - } -} - -bool LayerTreeResourceProvider::CanLockForWrite(viz::ResourceId id) { - viz::internal::Resource* resource = GetResource(id); - return !resource->locked_for_write && !resource->exported_count && - resource->origin == viz::internal::Resource::INTERNAL && - !resource->lost; -} - -viz::internal::Resource* LayerTreeResourceProvider::LockForWrite( - viz::ResourceId id) { - DCHECK(CanLockForWrite(id)); - viz::internal::Resource* resource = GetResource(id); - WaitSyncTokenInternal(resource); - resource->SetLocallyUsed(); - resource->locked_for_write = true; - resource->mipmap_state = viz::internal::Resource::INVALID; - return resource; -} - -void LayerTreeResourceProvider::UnlockForWrite( - viz::internal::Resource* resource) { - DCHECK(resource->locked_for_write); - DCHECK_EQ(resource->exported_count, 0); - DCHECK(resource->origin == viz::internal::Resource::INTERNAL); - resource->locked_for_write = false; -} - -void LayerTreeResourceProvider::FlushPendingDeletions() const { - if (auto* gl = ContextGL()) - gl->ShallowFlushCHROMIUM(); -} - -GLenum LayerTreeResourceProvider::GetImageTextureTarget( - const gpu::Capabilities& caps, - gfx::BufferUsage usage, - viz::ResourceFormat format) const { - return gpu::GetBufferTextureTarget(usage, BufferFormat(format), caps); -} - bool LayerTreeResourceProvider::IsTextureFormatSupported( viz::ResourceFormat format) const { gpu::Capabilities caps; @@ -749,239 +250,6 @@ bool LayerTreeResourceProvider::IsRenderBufferFormatSupported( return false; } -viz::ResourceFormat LayerTreeResourceProvider::YuvResourceFormat( - int bits) const { - if (bits > 8) { - return settings_.yuv_highbit_resource_format; - } else { - return settings_.yuv_resource_format; - } -} - -bool LayerTreeResourceProvider::IsLost(viz::ResourceId id) { - viz::internal::Resource* resource = GetResource(id); - return resource->lost; -} - -void LayerTreeResourceProvider::LoseResourceForTesting(viz::ResourceId id) { - auto it = imported_resources_.find(id); - if (it != imported_resources_.end()) { - ImportedResource& imported = it->second; - imported.returned_lost = true; - return; - } - - viz::internal::Resource* resource = GetResource(id); - DCHECK(resource); - resource->lost = true; -} - -void LayerTreeResourceProvider::EnableReadLockFencesForTesting( - viz::ResourceId id) { - viz::internal::Resource* resource = GetResource(id); - DCHECK(resource); - resource->read_lock_fences_enabled = true; -} - -LayerTreeResourceProvider::ScopedWriteLockGpu::ScopedWriteLockGpu( - LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id) - : resource_provider_(resource_provider), resource_id_(resource_id) { - viz::internal::Resource* resource = - resource_provider->LockForWrite(resource_id); - DCHECK_EQ(resource->type, viz::ResourceType::kTexture); - resource_provider->CreateTexture(resource); - size_ = resource->size; - usage_ = resource->usage; - format_ = resource->format; - color_space_ = resource_provider_->GetResourceColorSpaceForRaster(resource); - texture_id_ = resource->gl_id; - target_ = resource->target; - hint_ = resource->hint; - mailbox_ = resource->mailbox; - is_overlay_ = resource->is_overlay_candidate; - allocated_ = resource->allocated; -} - -LayerTreeResourceProvider::ScopedWriteLockGpu::~ScopedWriteLockGpu() { - viz::internal::Resource* resource = - resource_provider_->GetResource(resource_id_); - DCHECK(resource->locked_for_write); - resource->allocated = allocated_; - resource->mailbox = mailbox_; - // Don't set empty sync token otherwise resource will be marked synchronized. - if (has_sync_token_) - resource->UpdateSyncToken(sync_token_); - if (synchronized_) - resource->SetSynchronized(); - if (generate_mipmap_) - resource->SetGenerateMipmap(); - resource_provider_->UnlockForWrite(resource); -} - -SkColorType LayerTreeResourceProvider::ScopedWriteLockGpu::ColorType() const { - return ResourceFormatToClosestSkColorType(format_); -} - -void LayerTreeResourceProvider::ScopedWriteLockGpu::CreateMailbox() { - if (!mailbox_.IsZero()) - return; - gpu::gles2::GLES2Interface* gl = resource_provider_->ContextGL(); - DCHECK(gl); - gl->GenMailboxCHROMIUM(mailbox_.name); - gl->ProduceTextureDirectCHROMIUM(texture_id_, mailbox_.name); -} - -LayerTreeResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL( - LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id) - : ScopedWriteLockGpu(resource_provider, resource_id) {} - -LayerTreeResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {} - -GLuint LayerTreeResourceProvider::ScopedWriteLockGL::GetTexture() { - LazyAllocate(resource_provider_->ContextGL(), texture_id_); - return texture_id_; -} - -void LayerTreeResourceProvider::ScopedWriteLockGL::LazyAllocate( - gpu::gles2::GLES2Interface* gl, - GLuint texture_id) { - // ETC1 resources cannot be preallocated. - if (format_ == viz::ETC1) - return; - - if (allocated_) - return; - allocated_ = true; - - const Settings& settings = resource_provider_->settings_; - - gl->BindTexture(target_, texture_id); - - if (is_overlay_) { - DCHECK(settings.use_texture_storage_image); - gl->TexStorage2DImageCHROMIUM(target_, viz::TextureStorageFormat(format_), - GL_SCANOUT_CHROMIUM, size_.width(), - size_.height()); - if (color_space_.IsValid()) { - gl->SetColorSpaceMetadataCHROMIUM( - texture_id, reinterpret_cast<GLColorSpace>(&color_space_)); - } - } else if (settings.use_texture_storage) { - GLint levels = 1; - if (settings.use_texture_npot && - (hint_ & viz::ResourceTextureHint::kMipmap)) { - levels += base::bits::Log2Floor(std::max(size_.width(), size_.height())); - } - gl->TexStorage2DEXT(target_, levels, viz::TextureStorageFormat(format_), - size_.width(), size_.height()); - } else { - gl->TexImage2D(target_, 0, GLInternalFormat(format_), size_.width(), - size_.height(), 0, GLDataFormat(format_), - GLDataType(format_), nullptr); - } -} - -LayerTreeResourceProvider::ScopedWriteLockRaster::ScopedWriteLockRaster( - LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id) - : ScopedWriteLockGpu(resource_provider, resource_id) {} - -LayerTreeResourceProvider::ScopedWriteLockRaster::~ScopedWriteLockRaster() {} - -GLuint LayerTreeResourceProvider::ScopedWriteLockRaster::ConsumeTexture( - gpu::raster::RasterInterface* ri) { - DCHECK(ri); - DCHECK(!mailbox_.IsZero()); - - GLuint texture_id = - ri->CreateAndConsumeTexture(is_overlay_, usage_, format_, mailbox_.name); - DCHECK(texture_id); - - LazyAllocate(ri, texture_id); - - return texture_id; -} - -void LayerTreeResourceProvider::ScopedWriteLockRaster::LazyAllocate( - gpu::raster::RasterInterface* ri, - GLuint texture_id) { - // ETC1 resources cannot be preallocated. - if (format_ == viz::ETC1) - return; - - if (allocated_) - return; - allocated_ = true; - - ri->TexStorage2D(texture_id, 1, size_.width(), size_.height()); - if (is_overlay_ && color_space_.IsValid()) { - ri->SetColorSpaceMetadata(texture_id, - reinterpret_cast<GLColorSpace>(&color_space_)); - } -} - -LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer :: - ScopedWriteLockGpuMemoryBuffer(LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id) - : resource_provider_(resource_provider), resource_id_(resource_id) { - viz::internal::Resource* resource = - resource_provider->LockForWrite(resource_id); - DCHECK_EQ(resource->type, viz::ResourceType::kGpuMemoryBuffer); - size_ = resource->size; - format_ = resource->format; - usage_ = resource->usage; - color_space_ = resource_provider->GetResourceColorSpaceForRaster(resource); - gpu_memory_buffer_ = std::move(resource->gpu_memory_buffer); -} - -LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer:: - ~ScopedWriteLockGpuMemoryBuffer() { - viz::internal::Resource* resource = - resource_provider_->GetResource(resource_id_); - // Avoid crashing in release builds if GpuMemoryBuffer allocation fails. - // http://crbug.com/554541 - if (gpu_memory_buffer_) { - resource->gpu_memory_buffer = std::move(gpu_memory_buffer_); - resource->allocated = true; - resource_provider_->CreateAndBindImage(resource); - } - resource_provider_->UnlockForWrite(resource); -} - -gfx::GpuMemoryBuffer* LayerTreeResourceProvider:: - ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() { - if (!gpu_memory_buffer_) { - gpu_memory_buffer_ = - resource_provider_->gpu_memory_buffer_manager()->CreateGpuMemoryBuffer( - size_, BufferFormat(format_), usage_, gpu::kNullSurfaceHandle); - // Avoid crashing in release builds if GpuMemoryBuffer allocation fails. - // http://crbug.com/554541 - if (gpu_memory_buffer_ && color_space_.IsValid()) - gpu_memory_buffer_->SetColorSpace(color_space_); - } - return gpu_memory_buffer_.get(); -} - -LayerTreeResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware( - LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id) - : resource_provider_(resource_provider), resource_id_(resource_id) { - viz::internal::Resource* resource = - resource_provider->LockForWrite(resource_id); - resource_provider->PopulateSkBitmapWithResource(&sk_bitmap_, resource); - color_space_ = resource_provider->GetResourceColorSpaceForRaster(resource); - DCHECK(valid()); -} - -LayerTreeResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { - viz::internal::Resource* resource = - resource_provider_->GetResource(resource_id_); - resource->SetSynchronized(); - resource_provider_->UnlockForWrite(resource); -} - LayerTreeResourceProvider::ScopedSkSurface::ScopedSkSurface( GrContext* gr_context, GLuint texture_id, @@ -997,9 +265,12 @@ LayerTreeResourceProvider::ScopedSkSurface::ScopedSkSurface( GrBackendTexture backend_texture(size.width(), size.height(), GrMipMapped::kNo, texture_info); SkSurfaceProps surface_props = ComputeSurfaceProps(can_use_lcd_text); + // This type is used only for gpu raster, which implies gpu compositing. + bool gpu_compositing = true; surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget( gr_context, backend_texture, kTopLeft_GrSurfaceOrigin, msaa_sample_count, - ResourceFormatToClosestSkColorType(format), nullptr, &surface_props); + ResourceFormatToClosestSkColorType(gpu_compositing, format), nullptr, + &surface_props); } LayerTreeResourceProvider::ScopedSkSurface::~ScopedSkSurface() { @@ -1023,30 +294,14 @@ SkSurfaceProps LayerTreeResourceProvider::ScopedSkSurface::ComputeSurfaceProps( void LayerTreeResourceProvider::ValidateResource(viz::ResourceId id) const { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(id); - DCHECK(resources_.find(id) != resources_.end() || - imported_resources_.find(id) != imported_resources_.end()); + DCHECK(imported_resources_.find(id) != imported_resources_.end()); } bool LayerTreeResourceProvider::InUseByConsumer(viz::ResourceId id) { auto it = imported_resources_.find(id); - if (it != imported_resources_.end()) { - ImportedResource& imported = it->second; - return imported.exported_count > 0 || imported.returned_lost; - } - - viz::internal::Resource* resource = GetResource(id); - return resource->exported_count > 0 || resource->lost; -} - -bool LayerTreeResourceProvider::OnMemoryDump( - const base::trace_event::MemoryDumpArgs& args, - base::trace_event::ProcessMemoryDump* pmd) { - // Imported resources should be tracked in the client where they - // originated, as this code has only a name to refer to them and - // is not keeping them alive. - - // Non-imported resources are tracked in the base class. - return ResourceProvider::OnMemoryDump(args, pmd); + DCHECK(it != imported_resources_.end()); + ImportedResource& imported = it->second; + return imported.exported_count > 0 || imported.returned_lost; } } // namespace cc diff --git a/chromium/cc/resources/layer_tree_resource_provider.h b/chromium/cc/resources/layer_tree_resource_provider.h index 07a85f50a70..b046ea9d33c 100644 --- a/chromium/cc/resources/layer_tree_resource_provider.h +++ b/chromium/cc/resources/layer_tree_resource_provider.h @@ -5,53 +5,56 @@ #ifndef CC_RESOURCES_LAYER_TREE_RESOURCE_PROVIDER_H_ #define CC_RESOURCES_LAYER_TREE_RESOURCE_PROVIDER_H_ -#include "cc/resources/resource_provider.h" +#include <vector> + +#include "base/threading/thread_checker.h" +#include "cc/cc_export.h" #include "components/viz/common/display/renderer_settings.h" +#include "components/viz/common/resources/release_callback.h" +#include "components/viz/common/resources/resource_id.h" #include "components/viz/common/resources/resource_settings.h" +#include "components/viz/common/resources/single_release_callback.h" +#include "components/viz/common/resources/transferable_resource.h" +#include "third_party/khronos/GLES2/gl2.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrContext.h" -namespace viz { -class SharedBitmapManager; -} // namespace viz - namespace gpu { -struct Capabilities; -class GpuMemoryBufferManager; +namespace gles2 { +class GLES2Interface; +} namespace raster { class RasterInterface; } } // namespace gpu +namespace viz { +class ContextProvider; +} // namespace viz + namespace cc { // This class is not thread-safe and can only be called from the thread it was // created on (in practice, the impl thread). -class CC_EXPORT LayerTreeResourceProvider : public ResourceProvider { +class CC_EXPORT LayerTreeResourceProvider { public: - LayerTreeResourceProvider( - viz::ContextProvider* compositor_context_provider, - viz::SharedBitmapManager* shared_bitmap_manager, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - bool delegated_sync_points_required, - const viz::ResourceSettings& resource_settings); - ~LayerTreeResourceProvider() override; + LayerTreeResourceProvider(viz::ContextProvider* compositor_context_provider, + bool delegated_sync_points_required); + ~LayerTreeResourceProvider(); static gpu::SyncToken GenerateSyncTokenHelper(gpu::gles2::GLES2Interface* gl); static gpu::SyncToken GenerateSyncTokenHelper( gpu::raster::RasterInterface* ri); - // Gets the most recent sync token from the indicated resources. - gpu::SyncToken GetSyncTokenForResources(const ResourceIdArray& resource_ids); - // Prepares resources to be transfered to the parent, moving them to // mailboxes and serializing meta-data into TransferableResources. // Resources are not removed from the ResourceProvider, but are marked as // "in use". void PrepareSendToParent( - const ResourceIdArray& resource_ids, - std::vector<viz::TransferableResource>* transferable_resources); + const std::vector<viz::ResourceId>& resource_ids, + std::vector<viz::TransferableResource>* transferable_resources, + viz::ContextProvider* context_provider); // Receives resources from the parent, moving them from mailboxes. ResourceIds // passed are in the child namespace. @@ -60,22 +63,6 @@ class CC_EXPORT LayerTreeResourceProvider : public ResourceProvider { void ReceiveReturnsFromParent( const std::vector<viz::ReturnedResource>& transferable_resources); - viz::ResourceId CreateGpuTextureResource(const gfx::Size& size, - viz::ResourceTextureHint hint, - viz::ResourceFormat format, - const gfx::ColorSpace& color_space); - viz::ResourceId CreateGpuMemoryBufferResource( - const gfx::Size& size, - viz::ResourceTextureHint hint, - viz::ResourceFormat format, - gfx::BufferUsage usage, - const gfx::ColorSpace& color_space); - viz::ResourceId CreateBitmapResource(const gfx::Size& size, - const gfx::ColorSpace& color_space, - viz::ResourceFormat format); - - void DeleteResource(viz::ResourceId id); - // Receives a resource from an external client that can be used in compositor // frames, via the returned ResourceId. viz::ResourceId ImportResource(const viz::TransferableResource&, @@ -83,18 +70,6 @@ class CC_EXPORT LayerTreeResourceProvider : public ResourceProvider { // Removes an imported resource, which will call the ReleaseCallback given // originally, once the resource is no longer in use by any compositor frame. void RemoveImportedResource(viz::ResourceId); - // Update pixels from image, copying source_rect (in image) to dest_offset (in - // the resource). - void CopyToResource(viz::ResourceId id, - const uint8_t* image, - const gfx::Size& image_size); - - // For tests only! This prevents detecting uninitialized reads. - // Use SetPixels or LockForWrite to allocate implicitly. - void AllocateForTesting(viz::ResourceId id); - - // For tests only! - void CreateForTesting(viz::ResourceId id); // Verify that the ResourceId is valid and is known to this class, for debug // checks. @@ -103,182 +78,13 @@ class CC_EXPORT LayerTreeResourceProvider : public ResourceProvider { // Checks whether a resource is in use by a consumer. bool InUseByConsumer(viz::ResourceId id); - // Indicates if we can currently lock this resource for write. - bool CanLockForWrite(viz::ResourceId id); - - // In the case of GPU resources, we may need to flush the GL context to ensure - // that texture deletions are seen in a timely fashion. This function should - // be called after texture deletions that may happen during an idle state. - void FlushPendingDeletions() const; - - GLenum GetImageTextureTarget(const gpu::Capabilities& caps, - gfx::BufferUsage usage, - viz::ResourceFormat format) const; - bool IsTextureFormatSupported(viz::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(viz::ResourceFormat format) const; - bool use_sync_query() const { return settings_.use_sync_query; } - - int max_texture_size() const { return settings_.max_texture_size; } - - // Use this format for making resources that will be rastered and uploaded to - // from software bitmaps. - viz::ResourceFormat best_texture_format() const { - return settings_.best_texture_format; - } - // Use this format for making resources that will be rastered to on the Gpu. - viz::ResourceFormat best_render_buffer_format() const { - return settings_.best_render_buffer_format; - } - - viz::ResourceFormat YuvResourceFormat(int bits) const; - - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() { - return gpu_memory_buffer_manager_; - } - - bool IsLost(viz::ResourceId id); - - void LoseResourceForTesting(viz::ResourceId id); - void EnableReadLockFencesForTesting(viz::ResourceId id); - - // The following lock classes are part of the ResourceProvider API and are - // needed to read and write the resource contents. The user must ensure - // that they only use GL locks on GL resources, etc, and this is enforced - // by assertions. - class CC_EXPORT ScopedWriteLockGpu { - public: - ScopedWriteLockGpu(LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id); - ~ScopedWriteLockGpu(); - - GLenum target() const { return target_; } - viz::ResourceFormat format() const { return format_; } - const gfx::Size& size() const { return size_; } - const gfx::ColorSpace& color_space_for_raster() const { - return color_space_; - } - - SkColorType ColorType() const; - - void set_allocated() { allocated_ = true; } - - void set_sync_token(const gpu::SyncToken& sync_token) { - sync_token_ = sync_token; - has_sync_token_ = true; - } - - void set_synchronized() { synchronized_ = true; } - - void set_generate_mipmap() { generate_mipmap_ = true; } - - // Creates mailbox on compositor context that can be consumed on another - // context. - void CreateMailbox(); - - protected: - LayerTreeResourceProvider* const resource_provider_; - const viz::ResourceId resource_id_; - - // The following are copied from the resource. - gfx::Size size_; - gfx::BufferUsage usage_; - viz::ResourceFormat format_; - gfx::ColorSpace color_space_; - GLuint texture_id_; - GLenum target_; - viz::ResourceTextureHint hint_; - gpu::Mailbox mailbox_; - bool is_overlay_; - bool allocated_; - - // Set by the user. - gpu::SyncToken sync_token_; - bool has_sync_token_ = false; - bool synchronized_ = false; - bool generate_mipmap_ = false; - - private: - DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpu); - }; - - class CC_EXPORT ScopedWriteLockGL : public ScopedWriteLockGpu { - public: - ScopedWriteLockGL(LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id); - ~ScopedWriteLockGL(); - - // Returns texture id on compositor context, allocating if necessary. - GLuint GetTexture(); - - private: - void LazyAllocate(gpu::gles2::GLES2Interface* gl, GLuint texture_id); - - DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL); - }; - - class CC_EXPORT ScopedWriteLockRaster : public ScopedWriteLockGpu { - public: - ScopedWriteLockRaster(LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id); - ~ScopedWriteLockRaster(); - - // Creates a texture id, allocating if necessary, on the given context. The - // texture id must be deleted by the caller. - GLuint ConsumeTexture(gpu::raster::RasterInterface* ri); - - private: - void LazyAllocate(gpu::raster::RasterInterface* gl, GLuint texture_id); - - DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockRaster); - }; - - class CC_EXPORT ScopedWriteLockGpuMemoryBuffer { - public: - ScopedWriteLockGpuMemoryBuffer(LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id); - ~ScopedWriteLockGpuMemoryBuffer(); - gfx::GpuMemoryBuffer* GetGpuMemoryBuffer(); - const gfx::ColorSpace& color_space_for_raster() const { - return color_space_; - } - - private: - LayerTreeResourceProvider* const resource_provider_; - const viz::ResourceId resource_id_; - - gfx::Size size_; - viz::ResourceFormat format_; - gfx::BufferUsage usage_; - gfx::ColorSpace color_space_; - std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; - - DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpuMemoryBuffer); - }; - - class CC_EXPORT ScopedWriteLockSoftware { - public: - ScopedWriteLockSoftware(LayerTreeResourceProvider* resource_provider, - viz::ResourceId resource_id); - ~ScopedWriteLockSoftware(); - - SkBitmap& sk_bitmap() { return sk_bitmap_; } - bool valid() const { return !!sk_bitmap_.getPixels(); } - const gfx::ColorSpace& color_space_for_raster() const { - return color_space_; - } - - private: - LayerTreeResourceProvider* const resource_provider_; - const viz::ResourceId resource_id_; - gfx::ColorSpace color_space_; - SkBitmap sk_bitmap_; - DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockSoftware); - }; + bool IsSoftware() const { return !compositor_context_provider_; } class CC_EXPORT ScopedSkSurface { public: @@ -301,52 +107,17 @@ class CC_EXPORT LayerTreeResourceProvider : public ResourceProvider { DISALLOW_COPY_AND_ASSIGN(ScopedSkSurface); }; - protected: - viz::internal::Resource* LockForWrite(viz::ResourceId id); - void UnlockForWrite(viz::internal::Resource* resource); - void CreateMailbox(viz::internal::Resource* resource); - private: - // Holds const settings for the ResourceProvider. Never changed after init. - struct Settings { - Settings(viz::ContextProvider* compositor_context_provider, - bool delegated_sync_points_needed, - const viz::ResourceSettings& resource_settings); - - int max_texture_size = 0; - bool use_texture_storage = false; - bool use_texture_format_bgra = false; - bool use_texture_usage_hint = false; - bool use_texture_npot = false; - bool use_sync_query = false; - bool use_texture_storage_image = false; - viz::ResourceType default_resource_type = viz::ResourceType::kTexture; - viz::ResourceFormat yuv_resource_format = viz::LUMINANCE_8; - viz::ResourceFormat yuv_highbit_resource_format = viz::LUMINANCE_8; - viz::ResourceFormat best_texture_format = viz::RGBA_8888; - viz::ResourceFormat best_render_buffer_format = viz::RGBA_8888; - bool use_gpu_memory_buffer_resources = false; - bool delegated_sync_points_required = false; - } const settings_; - - // base::trace_event::MemoryDumpProvider implementation. - bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, - base::trace_event::ProcessMemoryDump* pmd) override; - - gfx::ColorSpace GetResourceColorSpaceForRaster( - const viz::internal::Resource* resource) const; + struct ImportedResource; - void CreateTexture(viz::internal::Resource* resource); - void CreateAndBindImage(viz::internal::Resource* resource); - void TransferResource(viz::internal::Resource* source, - viz::ResourceId id, - viz::TransferableResource* resource); + THREAD_CHECKER(thread_checker_); + const bool delegated_sync_points_required_; + viz::ContextProvider* const compositor_context_provider_; - viz::SharedBitmapManager* shared_bitmap_manager_; - struct ImportedResource; base::flat_map<viz::ResourceId, ImportedResource> imported_resources_; - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; - viz::ResourceId next_id_; + // The ResourceIds in LayerTreeResourceProvider start from 1 to avoid + // conflicts with id from viz::DisplayResourceProvider. + viz::ResourceId next_id_ = 1; DISALLOW_COPY_AND_ASSIGN(LayerTreeResourceProvider); }; diff --git a/chromium/cc/resources/layer_tree_resource_provider_unittest.cc b/chromium/cc/resources/layer_tree_resource_provider_unittest.cc index b0a47f2a805..e78f363d6b8 100644 --- a/chromium/cc/resources/layer_tree_resource_provider_unittest.cc +++ b/chromium/cc/resources/layer_tree_resource_provider_unittest.cc @@ -7,10 +7,10 @@ #include <memory> #include "base/bind.h" +#include "base/bind_helpers.h" +#include "components/viz/common/resources/returned_resource.h" #include "components/viz/common/resources/single_release_callback.h" #include "components/viz/test/test_context_provider.h" -#include "components/viz/test/test_gpu_memory_buffer_manager.h" -#include "components/viz/test/test_shared_bitmap_manager.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -27,10 +27,7 @@ class LayerTreeResourceProviderTest : public testing::TestWithParam<bool> { bound_(context_provider_->BindToCurrentThread()), provider_(std::make_unique<LayerTreeResourceProvider>( use_gpu_ ? context_provider_.get() : nullptr, - &shared_bitmap_manager_, - &gpu_memory_buffer_manager_, - delegated_sync_points_required_, - resource_settings_)) { + delegated_sync_points_required_)) { DCHECK_EQ(bound_, gpu::ContextResult::kSuccess); } @@ -59,8 +56,6 @@ class LayerTreeResourceProviderTest : public testing::TestWithParam<bool> { r.mailbox_holder.sync_token = SyncTokenFromUInt(sync_token_value); r.mailbox_holder.texture_target = 6; } - if (!gpu) - r.shared_bitmap_sequence_number = sync_token_value; return r; } @@ -68,15 +63,17 @@ class LayerTreeResourceProviderTest : public testing::TestWithParam<bool> { bool use_gpu() const { return use_gpu_; } LayerTreeResourceProvider& provider() const { return *provider_; } + viz::ContextProvider* context_provider() const { + return context_provider_.get(); + } + + void DestroyProvider() { provider_.reset(); } private: bool use_gpu_; scoped_refptr<viz::TestContextProvider> context_provider_; gpu::ContextResult bound_; - viz::TestSharedBitmapManager shared_bitmap_manager_; - viz::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; bool delegated_sync_points_required_ = true; - viz::ResourceSettings resource_settings_; std::unique_ptr<LayerTreeResourceProvider> provider_; }; @@ -93,7 +90,7 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceReleased) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); viz::ResourceId id = provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( &MockReleaseCallback::Released, base::Unretained(&release)))); // The local id is different. EXPECT_NE(id, tran.id); @@ -108,14 +105,15 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceReleased) { TEST_P(LayerTreeResourceProviderTest, TransferableResourceSendToParent) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); + tran.buffer_format = gfx::BufferFormat::RGBX_8888; viz::ResourceId id = provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( &MockReleaseCallback::Released, base::Unretained(&release)))); // Export the resource. std::vector<viz::ResourceId> to_send = {id}; std::vector<viz::TransferableResource> exported; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); ASSERT_EQ(exported.size(), 1u); // Exported resource matches except for the id which was mapped @@ -132,8 +130,7 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceSendToParent) { EXPECT_EQ(exported[0].mailbox_holder.sync_token, verified_sync_token); EXPECT_EQ(exported[0].mailbox_holder.texture_target, tran.mailbox_holder.texture_target); - EXPECT_EQ(exported[0].shared_bitmap_sequence_number, - tran.shared_bitmap_sequence_number); + EXPECT_EQ(exported[0].buffer_format, tran.buffer_format); // Exported resources are not released when removed, until the export returns. EXPECT_CALL(release, Released(_, _)).Times(0); @@ -153,18 +150,83 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceSendToParent) { provider().ReceiveReturnsFromParent(returned); } +TEST_P(LayerTreeResourceProviderTest, TransferableResourceSendTwoToParent) { + viz::TransferableResource tran[] = { + MakeTransferableResource(use_gpu(), 'a', 15), + MakeTransferableResource(use_gpu(), 'b', 16)}; + viz::ResourceId id1 = provider().ImportResource( + tran[0], viz::SingleReleaseCallback::Create(base::DoNothing())); + viz::ResourceId id2 = provider().ImportResource( + tran[1], viz::SingleReleaseCallback::Create(base::DoNothing())); + + // Export the resource. + std::vector<viz::ResourceId> to_send = {id1, id2}; + std::vector<viz::TransferableResource> exported; + provider().PrepareSendToParent(to_send, &exported, context_provider()); + ASSERT_EQ(exported.size(), 2u); + + // Exported resource matches except for the id which was mapped + // to the local ResourceProvider, and the sync token should be + // verified if it's a gpu resource. + for (int i = 0; i < 2; ++i) { + gpu::SyncToken verified_sync_token = tran[i].mailbox_holder.sync_token; + if (!tran[i].is_software) + verified_sync_token.SetVerifyFlush(); + EXPECT_EQ(exported[i].id, to_send[i]); + EXPECT_EQ(exported[i].is_software, tran[i].is_software); + EXPECT_EQ(exported[i].filter, tran[i].filter); + EXPECT_EQ(exported[i].size, tran[i].size); + EXPECT_EQ(exported[i].mailbox_holder.mailbox, + tran[i].mailbox_holder.mailbox); + EXPECT_EQ(exported[i].mailbox_holder.sync_token, verified_sync_token); + EXPECT_EQ(exported[i].mailbox_holder.texture_target, + tran[i].mailbox_holder.texture_target); + EXPECT_EQ(exported[i].buffer_format, tran[i].buffer_format); + } +} + +TEST_P(LayerTreeResourceProviderTest, + TransferableResourceSendToParentTwoTimes) { + viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); + viz::ResourceId id = provider().ImportResource( + tran, viz::SingleReleaseCallback::Create(base::DoNothing())); + + // Export the resource. + std::vector<viz::ResourceId> to_send = {id}; + std::vector<viz::TransferableResource> exported; + provider().PrepareSendToParent(to_send, &exported, context_provider()); + ASSERT_EQ(exported.size(), 1u); + EXPECT_EQ(exported[0].id, id); + + // Return the resource, with a sync token if using gpu. + std::vector<viz::ReturnedResource> returned; + returned.push_back({}); + returned.back().id = exported[0].id; + if (use_gpu()) + returned.back().sync_token = SyncTokenFromUInt(31); + returned.back().count = 1; + returned.back().lost = false; + provider().ReceiveReturnsFromParent(returned); + + // Then export again, it still sends. + exported.clear(); + provider().PrepareSendToParent(to_send, &exported, context_provider()); + ASSERT_EQ(exported.size(), 1u); + EXPECT_EQ(exported[0].id, id); +} + TEST_P(LayerTreeResourceProviderTest, TransferableResourceLostOnShutdownIfExported) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); viz::ResourceId id = provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( &MockReleaseCallback::Released, base::Unretained(&release)))); // Export the resource. std::vector<viz::ResourceId> to_send = {id}; std::vector<viz::TransferableResource> exported; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); EXPECT_CALL(release, Released(_, true)); Shutdown(); @@ -174,13 +236,13 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceRemovedAfterReturn) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); viz::ResourceId id = provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( &MockReleaseCallback::Released, base::Unretained(&release)))); // Export the resource. std::vector<viz::ResourceId> to_send = {id}; std::vector<viz::TransferableResource> exported; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); // Return the resource. This does not release the resource back to // the client. @@ -204,13 +266,13 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceExportedTwice) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); viz::ResourceId id = provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( &MockReleaseCallback::Released, base::Unretained(&release)))); // Export the resource once. std::vector<viz::ResourceId> to_send = {id}; std::vector<viz::TransferableResource> exported; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); // Exported resources are not released when removed, until all exports are // returned. @@ -219,7 +281,7 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceExportedTwice) { // Export the resource twice. exported = {}; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); // Return the resource the first time. std::vector<viz::ReturnedResource> returned; @@ -243,13 +305,13 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceReturnedTwiceAtOnce) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); viz::ResourceId id = provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( &MockReleaseCallback::Released, base::Unretained(&release)))); // Export the resource once. std::vector<viz::ResourceId> to_send = {id}; std::vector<viz::TransferableResource> exported; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); // Exported resources are not released when removed, until all exports are // returned. @@ -258,7 +320,7 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceReturnedTwiceAtOnce) { // Export the resource twice. exported = {}; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); // Return both exports at once. std::vector<viz::ReturnedResource> returned; @@ -278,13 +340,13 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceLostOnReturn) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); viz::ResourceId id = provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( &MockReleaseCallback::Released, base::Unretained(&release)))); // Export the resource once. std::vector<viz::ResourceId> to_send = {id}; std::vector<viz::TransferableResource> exported; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); // Exported resources are not released when removed, until all exports are // returned. @@ -293,7 +355,7 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceLostOnReturn) { // Export the resource twice. exported = {}; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); // Return the resource the first time, not lost. std::vector<viz::ReturnedResource> returned; @@ -303,7 +365,8 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceLostOnReturn) { returned.back().lost = false; provider().ReceiveReturnsFromParent(returned); - // Return a second time, as lost. The ReturnCallback should report it lost. + // Return a second time, as lost. The viz::ReturnCallback should report it + // lost. returned.back().lost = true; EXPECT_CALL(release, Released(_, true)); provider().ReceiveReturnsFromParent(returned); @@ -313,13 +376,13 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceLostOnFirstReturn) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); viz::ResourceId id = provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( &MockReleaseCallback::Released, base::Unretained(&release)))); // Export the resource once. std::vector<viz::ResourceId> to_send = {id}; std::vector<viz::TransferableResource> exported; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); // Exported resources are not released when removed, until all exports are // returned. @@ -328,7 +391,7 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceLostOnFirstReturn) { // Export the resource twice. exported = {}; - provider().PrepareSendToParent(to_send, &exported); + provider().PrepareSendToParent(to_send, &exported, context_provider()); // Return the resource the first time, marked as lost. std::vector<viz::ReturnedResource> returned; @@ -344,92 +407,149 @@ TEST_P(LayerTreeResourceProviderTest, TransferableResourceLostOnFirstReturn) { provider().ReceiveReturnsFromParent(returned); } -TEST_P(LayerTreeResourceProviderTest, - NormalPlusTransferableResourceSendToParent) { +TEST_P(LayerTreeResourceProviderTest, ReturnedSyncTokensArePassedToClient) { + // SyncTokens are gpu-only. + if (!use_gpu()) + return; + + MockReleaseCallback release; + + GLuint texture; + context_provider()->ContextGL()->GenTextures(1, &texture); + context_provider()->ContextGL()->BindTexture(GL_TEXTURE_2D, texture); + gpu::Mailbox mailbox; + context_provider()->ContextGL()->GenMailboxCHROMIUM(mailbox.name); + context_provider()->ContextGL()->ProduceTextureDirectCHROMIUM(texture, + mailbox.name); + gpu::SyncToken sync_token; + context_provider()->ContextGL()->GenSyncTokenCHROMIUM(sync_token.GetData()); + + auto tran = viz::TransferableResource::MakeGL(mailbox, GL_LINEAR, + GL_TEXTURE_2D, sync_token); + viz::ResourceId resource = provider().ImportResource( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( + &MockReleaseCallback::Released, base::Unretained(&release)))); + + EXPECT_TRUE(tran.mailbox_holder.sync_token.HasData()); + // All the logic below assumes that the sync token releases are all positive. + EXPECT_LT(0u, tran.mailbox_holder.sync_token.release_count()); + + // Transfer the resource, expect the sync points to be consistent. + std::vector<viz::TransferableResource> list; + provider().PrepareSendToParent({resource}, &list, context_provider()); + ASSERT_EQ(1u, list.size()); + EXPECT_LE(sync_token.release_count(), + list[0].mailbox_holder.sync_token.release_count()); + EXPECT_EQ(0, memcmp(mailbox.name, list[0].mailbox_holder.mailbox.name, + sizeof(mailbox.name))); + + // Make a new texture id from the mailbox. + context_provider()->ContextGL()->WaitSyncTokenCHROMIUM( + list[0].mailbox_holder.sync_token.GetConstData()); + unsigned other_texture = + context_provider()->ContextGL()->CreateAndConsumeTextureCHROMIUM( + mailbox.name); + // Then delete it and make a new SyncToken. + context_provider()->ContextGL()->DeleteTextures(1, &other_texture); + context_provider()->ContextGL()->GenSyncTokenCHROMIUM( + list[0].mailbox_holder.sync_token.GetData()); + EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); + + // Receive the resource, then delete it, expect the SyncTokens to be + // consistent. + provider().ReceiveReturnsFromParent( + viz::TransferableResource::ReturnResources(list)); + + gpu::SyncToken returned_sync_token; + EXPECT_CALL(release, Released(_, false)) + .WillOnce(testing::SaveArg<0>(&returned_sync_token)); + provider().RemoveImportedResource(resource); + EXPECT_GE(returned_sync_token.release_count(), + list[0].mailbox_holder.sync_token.release_count()); +} + +TEST_P(LayerTreeResourceProviderTest, LostResourcesAreReturnedLost) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); + viz::ResourceId resource = provider().ImportResource( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( + &MockReleaseCallback::Released, base::Unretained(&release)))); + + // Transfer the resource to the parent. + std::vector<viz::TransferableResource> list; + provider().PrepareSendToParent({resource}, &list, context_provider()); + EXPECT_EQ(1u, list.size()); - viz::ResourceId tran_id = provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( + // Receive it back marked lost. + std::vector<viz::ReturnedResource> returned_to_child; + returned_to_child.push_back(list[0].ToReturnedResource()); + returned_to_child.back().lost = true; + provider().ReceiveReturnsFromParent(returned_to_child); + + // Delete the resource in the child. Expect the resource to be lost. + EXPECT_CALL(release, Released(_, true)); + provider().RemoveImportedResource(resource); +} + +TEST_P(LayerTreeResourceProviderTest, ShutdownPreservesLostState) { + MockReleaseCallback release; + viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); + viz::ResourceId resource = provider().ImportResource( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( &MockReleaseCallback::Released, base::Unretained(&release)))); - viz::ResourceId norm_id; - if (use_gpu()) { - norm_id = provider().CreateGpuTextureResource( - gfx::Size(3, 4), viz::ResourceTextureHint::kDefault, viz::RGBA_8888, - gfx::ColorSpace()); - } else { - norm_id = provider().CreateBitmapResource( - gfx::Size(3, 4), gfx::ColorSpace(), viz::RGBA_8888); - } - provider().AllocateForTesting(norm_id); - // Export the resources. - std::vector<viz::ResourceId> to_send = {tran_id, norm_id}; - std::vector<viz::TransferableResource> exported; - provider().PrepareSendToParent(to_send, &exported); - ASSERT_EQ(exported.size(), 2u); + // Transfer the resource to the parent. + std::vector<viz::TransferableResource> list; + provider().PrepareSendToParent({resource}, &list, context_provider()); + EXPECT_EQ(1u, list.size()); - // They're both exported (normal resources come first). - EXPECT_EQ(exported[0].id, norm_id); - EXPECT_EQ(exported[1].id, tran_id); - viz::TransferableResource exported_norm = exported[0]; - viz::TransferableResource exported_tran = exported[1]; - - // Exported normal Resource matches what it should. - EXPECT_EQ(exported_norm.id, norm_id); - EXPECT_EQ(exported_norm.is_software, tran.is_software); - EXPECT_NE(exported_norm.filter, 0u); - EXPECT_EQ(exported_norm.size, gfx::Size(3, 4)); - EXPECT_NE(exported_norm.mailbox_holder.mailbox, gpu::Mailbox()); - if (use_gpu()) { - EXPECT_NE(exported_norm.mailbox_holder.sync_token, gpu::SyncToken()); - EXPECT_NE(exported_norm.mailbox_holder.texture_target, 0u); - EXPECT_EQ(exported_norm.shared_bitmap_sequence_number, 0u); - } else { - EXPECT_EQ(exported_norm.mailbox_holder.sync_token, gpu::SyncToken()); - EXPECT_EQ(exported_norm.mailbox_holder.texture_target, 0u); - EXPECT_NE(exported_norm.shared_bitmap_sequence_number, 0u); - } + // Receive it back marked lost. + std::vector<viz::ReturnedResource> returned_to_child; + returned_to_child.push_back(list[0].ToReturnedResource()); + returned_to_child.back().lost = true; + provider().ReceiveReturnsFromParent(returned_to_child); - // Exported TransferableResource matches except for the id which was mapped - // to the local ResourceProvider, and the sync token should be - // verified if it's a gpu resource. - gpu::SyncToken verified_sync_token = tran.mailbox_holder.sync_token; - if (!tran.is_software) - verified_sync_token.SetVerifyFlush(); - EXPECT_EQ(exported_tran.id, tran_id); - EXPECT_EQ(exported_tran.is_software, tran.is_software); - EXPECT_EQ(exported_tran.filter, tran.filter); - EXPECT_EQ(exported_tran.size, tran.size); - EXPECT_EQ(exported_tran.mailbox_holder.mailbox, tran.mailbox_holder.mailbox); - EXPECT_EQ(exported_tran.mailbox_holder.sync_token, verified_sync_token); - EXPECT_EQ(exported_tran.mailbox_holder.texture_target, - tran.mailbox_holder.texture_target); - EXPECT_EQ(exported_tran.shared_bitmap_sequence_number, - tran.shared_bitmap_sequence_number); + // Shutdown, and expect the resource to be lost.. + EXPECT_CALL(release, Released(_, true)); + DestroyProvider(); +} - // Return both resources, with sync tokens if using gpu. - std::vector<viz::ReturnedResource> returned; - returned.push_back({}); - returned.back().id = exported_norm.id; - if (use_gpu()) - returned.back().sync_token = SyncTokenFromUInt(31); - returned.back().count = 1; - returned.back().lost = false; +TEST_P(LayerTreeResourceProviderTest, ShutdownLosesExportedResources) { + MockReleaseCallback release; + viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); + viz::ResourceId resource = provider().ImportResource( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( + &MockReleaseCallback::Released, base::Unretained(&release)))); - returned.push_back({}); - returned.back().id = exported_tran.id; - if (use_gpu()) - returned.back().sync_token = SyncTokenFromUInt(82); - returned.back().count = 1; - returned.back().lost = false; + // Transfer the resource to the parent. + std::vector<viz::TransferableResource> list; + provider().PrepareSendToParent({resource}, &list, context_provider()); + EXPECT_EQ(1u, list.size()); - provider().ReceiveReturnsFromParent(returned); + // Destroy the LayerTreeResourceProvider, the resource is returned lost. + EXPECT_CALL(release, Released(_, true)); + DestroyProvider(); +} + +TEST_P(LayerTreeResourceProviderTest, ShutdownDoesNotLoseUnexportedResources) { + MockReleaseCallback release; + viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); + viz::ResourceId resource = provider().ImportResource( + tran, viz::SingleReleaseCallback::Create(base::BindOnce( + &MockReleaseCallback::Released, base::Unretained(&release)))); + + // Transfer the resource to the parent. + std::vector<viz::TransferableResource> list; + provider().PrepareSendToParent({resource}, &list, context_provider()); + EXPECT_EQ(1u, list.size()); + + // Receive it back. + provider().ReceiveReturnsFromParent( + viz::TransferableResource::ReturnResources(list)); - // The sync token for the TransferableResource is given to the - // ReleaseCallback. - EXPECT_CALL(release, Released(returned[1].sync_token, false)); - provider().RemoveImportedResource(tran_id); + // Destroy the LayerTreeResourceProvider, the resource is not lost. + EXPECT_CALL(release, Released(_, false)); + DestroyProvider(); } } // namespace diff --git a/chromium/cc/resources/resource.h b/chromium/cc/resources/resource.h deleted file mode 100644 index f35fa0bf19b..00000000000 --- a/chromium/cc/resources/resource.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_RESOURCE_H_ -#define CC_RESOURCES_RESOURCE_H_ - -#include "base/macros.h" -#include "cc/cc_export.h" -#include "components/viz/common/resources/resource_format.h" -#include "components/viz/common/resources/resource_id.h" -#include "ui/gfx/color_space.h" -#include "ui/gfx/geometry/size.h" - -namespace cc { - -class CC_EXPORT Resource { - public: - Resource() : id_(0), format_(viz::RGBA_8888) {} - Resource(unsigned id, - const gfx::Size& size, - viz::ResourceFormat format, - const gfx::ColorSpace& color_space) - : id_(id), size_(size), format_(format), color_space_(color_space) {} - - viz::ResourceId id() const { return id_; } - const gfx::Size& size() const { return size_; } - viz::ResourceFormat format() const { return format_; } - const gfx::ColorSpace& color_space() const { return color_space_; } - - protected: - void set_id(viz::ResourceId id) { id_ = id; } - void set_dimensions(const gfx::Size& size, viz::ResourceFormat format) { - size_ = size; - format_ = format; - } - void set_color_space(const gfx::ColorSpace& color_space) { - color_space_ = color_space; - } - - private: - viz::ResourceId id_; - gfx::Size size_; - viz::ResourceFormat format_; - gfx::ColorSpace color_space_; - - DISALLOW_COPY_AND_ASSIGN(Resource); -}; - -} // namespace cc - -#endif // CC_RESOURCES_RESOURCE_H_ diff --git a/chromium/cc/resources/resource_pool.cc b/chromium/cc/resources/resource_pool.cc index 659d5743972..a6d8b841c92 100644 --- a/chromium/cc/resources/resource_pool.cc +++ b/chromium/cc/resources/resource_pool.cc @@ -14,13 +14,16 @@ #include "base/format_macros.h" #include "base/memory/memory_coordinator_client_registry.h" #include "base/memory/shared_memory_handle.h" +#include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "build/build_config.h" #include "cc/base/container_util.h" #include "cc/resources/layer_tree_resource_provider.h" +#include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/resources/resource_sizes.h" +#include "gpu/command_buffer/client/gles2_interface.h" using base::trace_event::MemoryAllocatorDump; using base::trace_event::MemoryDumpLevelOfDetail; @@ -65,12 +68,12 @@ constexpr base::TimeDelta ResourcePool::kDefaultExpirationDelay; ResourcePool::ResourcePool( LayerTreeResourceProvider* resource_provider, + viz::ContextProvider* context_provider, scoped_refptr<base::SingleThreadTaskRunner> task_runner, const base::TimeDelta& expiration_delay, - Mode resource_mode, bool disallow_non_exact_reuse) : resource_provider_(resource_provider), - using_gpu_resources_(resource_mode == Mode::kGpu), + context_provider_(context_provider), task_runner_(std::move(task_runner)), resource_expiration_delay_(expiration_delay), disallow_non_exact_reuse_(disallow_non_exact_reuse), @@ -160,7 +163,7 @@ ResourcePool::InUsePoolResource ResourcePool::AcquireResource( PoolResource* resource = ReuseResource(size, format, color_space); if (!resource) resource = CreateResource(size, format, color_space); - return InUsePoolResource(resource, using_gpu_resources_); + return InUsePoolResource(resource, !!context_provider_); } // Iterate over all three resource lists (unused, in-use, and busy), updating @@ -241,7 +244,7 @@ ResourcePool::TryAcquireResourceForPartialRaster( // These will be updated when raster completes successfully. resource->set_invalidated_rect(gfx::Rect()); resource->set_content_id(0); - return InUsePoolResource(resource, using_gpu_resources_); + return InUsePoolResource(resource, !!context_provider_); } return InUsePoolResource(); @@ -275,7 +278,7 @@ void ResourcePool::OnResourceReleased(size_t unique_id, } resource->set_resource_id(0); - if (using_gpu_resources_) + if (context_provider_) resource->gpu_backing()->returned_sync_token = sync_token; DidFinishUsingResource(std::move(*busy_it)); busy_resources_.erase(busy_it); @@ -300,10 +303,7 @@ void ResourcePool::PrepareForExport(const InUsePoolResource& resource) { } else { transferable = viz::TransferableResource::MakeSoftware( resource.resource_->software_backing()->shared_bitmap_id, - // Not needed since this software resource's SharedBitmapId was - // notified to the display compositor through the CompositorFrameSink. - /*sequence_number=*/0, resource.resource_->size(), - resource.resource_->format()); + resource.resource_->size(), resource.resource_->format()); } transferable.format = resource.resource_->format(); transferable.buffer_format = viz::BufferFormat(transferable.format); @@ -486,7 +486,8 @@ void ResourcePool::EvictExpiredResources() { // If nothing is evictable, we have deleted one (and possibly more) // resources without any new activity. Flush to ensure these deletions are // processed. - resource_provider_->FlushPendingDeletions(); + if (context_provider_) + context_provider_->ContextGL()->ShallowFlushCHROMIUM(); return; } @@ -522,8 +523,8 @@ base::TimeTicks ResourcePool::GetUsageTimeForLRUResource() const { bool ResourcePool::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) { if (args.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND) { - std::string dump_name = base::StringPrintf( - "cc/tile_memory/provider_%d", resource_provider_->tracing_id()); + std::string dump_name = + base::StringPrintf("cc/tile_memory/provider_%d", tracing_id_); MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name); dump->AddScalar(MemoryAllocatorDump::kNameSize, MemoryAllocatorDump::kUnitsBytes, diff --git a/chromium/cc/resources/resource_pool.h b/chromium/cc/resources/resource_pool.h index b55cf829297..e401582bc6d 100644 --- a/chromium/cc/resources/resource_pool.h +++ b/chromium/cc/resources/resource_pool.h @@ -20,11 +20,12 @@ #include "base/trace_event/memory_dump_provider.h" #include "base/unguessable_token.h" #include "cc/cc_export.h" -#include "cc/resources/resource.h" #include "components/viz/common/quads/shared_bitmap.h" #include "components/viz/common/resources/resource_format.h" +#include "components/viz/common/resources/resource_id.h" #include "gpu/command_buffer/common/sync_token.h" #include "third_party/khronos/GLES2/gl2.h" +#include "ui/gfx/color_space.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/gpu_memory_buffer.h" @@ -32,6 +33,10 @@ namespace base { class SingleThreadTaskRunner; } +namespace viz { +class ContextProvider; +} + namespace cc { class LayerTreeResourceProvider; @@ -161,14 +166,13 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider, PoolResource* resource_ = nullptr; }; - enum class Mode { kGpu, kSoftware }; - - // This takes a hint for if the pool will be holding gpu or software - // resources, which is used for consistency checking. + // When holding gpu resources, the |context_provider| should be non-null, + // and when holding software resources, it should be null. It is used for + // consistency checking as well as for correctness. ResourcePool(LayerTreeResourceProvider* resource_provider, + viz::ContextProvider* context_provider, scoped_refptr<base::SingleThreadTaskRunner> task_runner, const base::TimeDelta& expiration_delay, - Mode resource_mode, bool disallow_non_exact_reuse); ~ResourcePool() override; @@ -343,8 +347,8 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider, bool HasEvictableResources() const; base::TimeTicks GetUsageTimeForLRUResource() const; - LayerTreeResourceProvider* const resource_provider_ = nullptr; - const bool using_gpu_resources_ = false; + LayerTreeResourceProvider* const resource_provider_; + viz::ContextProvider* const context_provider_; const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; const base::TimeDelta resource_expiration_delay_; const bool disallow_non_exact_reuse_ = false; diff --git a/chromium/cc/resources/resource_pool_unittest.cc b/chromium/cc/resources/resource_pool_unittest.cc index cf233dc40b4..509a5a27421 100644 --- a/chromium/cc/resources/resource_pool_unittest.cc +++ b/chromium/cc/resources/resource_pool_unittest.cc @@ -23,11 +23,11 @@ class ResourcePoolTest : public testing::Test { context_provider_ = viz::TestContextProvider::Create(); context_provider_->BindToCurrentThread(); resource_provider_ = FakeResourceProvider::CreateLayerTreeResourceProvider( - context_provider_.get(), nullptr); + context_provider_.get()); task_runner_ = base::ThreadTaskRunnerHandle::Get(); resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), task_runner_, - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu, false); + resource_provider_.get(), context_provider_.get(), task_runner_, + ResourcePool::kDefaultExpirationDelay, false); } protected: @@ -163,7 +163,15 @@ TEST_F(ResourcePoolTest, LostResource) { SetBackingOnResource(resource); resource_pool_->PrepareForExport(resource); - resource_provider_->LoseResourceForTesting(resource.resource_id_for_export()); + std::vector<viz::ResourceId> export_ids = {resource.resource_id_for_export()}; + std::vector<viz::TransferableResource> transferable_resources; + resource_provider_->PrepareSendToParent(export_ids, &transferable_resources, + context_provider_.get()); + auto returned_resources = + viz::TransferableResource::ReturnResources(transferable_resources); + ASSERT_EQ(1u, returned_resources.size()); + returned_resources[0].lost = true; + resource_provider_->ReceiveReturnsFromParent(returned_resources); EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting()); resource_pool_->ReleaseResource(std::move(resource)); @@ -174,8 +182,8 @@ TEST_F(ResourcePoolTest, BusyResourcesNotFreed) { // Set a quick resource expiration delay so that this test doesn't take long // to run. resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), task_runner_, - base::TimeDelta::FromMilliseconds(10), ResourcePool::Mode::kGpu, false); + resource_provider_.get(), context_provider_.get(), task_runner_, + base::TimeDelta::FromMilliseconds(10), false); // Limits high enough to not be hit by this test. size_t bytes_limit = 10 * 1024 * 1024; @@ -196,7 +204,7 @@ TEST_F(ResourcePoolTest, BusyResourcesNotFreed) { std::vector<viz::TransferableResource> transfers; resource_provider_->PrepareSendToParent({resource.resource_id_for_export()}, - &transfers); + &transfers, context_provider_.get()); resource_pool_->ReleaseResource(std::move(resource)); EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting()); @@ -221,8 +229,8 @@ TEST_F(ResourcePoolTest, UnusedResourcesEventuallyFreed) { // Set a quick resource expiration delay so that this test doesn't take long // to run. resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), task_runner_, - base::TimeDelta::FromMilliseconds(100), ResourcePool::Mode::kGpu, false); + resource_provider_.get(), context_provider_.get(), task_runner_, + base::TimeDelta::FromMilliseconds(100), false); // Limits high enough to not be hit by this test. size_t bytes_limit = 10 * 1024 * 1024; @@ -245,7 +253,7 @@ TEST_F(ResourcePoolTest, UnusedResourcesEventuallyFreed) { resource_pool_->PrepareForExport(resource); std::vector<viz::TransferableResource> transfers; resource_provider_->PrepareSendToParent({resource.resource_id_for_export()}, - &transfers); + &transfers, context_provider_.get()); resource_pool_->ReleaseResource(std::move(resource)); EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting()); @@ -467,7 +475,7 @@ TEST_F(ResourcePoolTest, PurgedMemory) { // released. std::vector<viz::TransferableResource> transfers; resource_provider_->PrepareSendToParent({resource.resource_id_for_export()}, - &transfers); + &transfers, context_provider_.get()); // Release the resource making it busy. resource_pool_->OnMemoryStateChange(base::MemoryState::NORMAL); @@ -523,7 +531,7 @@ TEST_F(ResourcePoolTest, MemoryStateSuspended) { // released. std::vector<viz::TransferableResource> transfers; resource_provider_->PrepareSendToParent({resource.resource_id_for_export()}, - &transfers); + &transfers, context_provider_.get()); // Release the resource making it busy. resource_pool_->OnMemoryStateChange(base::MemoryState::NORMAL); @@ -586,7 +594,8 @@ TEST_F(ResourcePoolTest, InvalidateResources) { // once released. std::vector<viz::TransferableResource> transfers; resource_provider_->PrepareSendToParent( - {busy_resource.resource_id_for_export()}, &transfers); + {busy_resource.resource_id_for_export()}, &transfers, + context_provider_.get()); // Release the resource making it busy. resource_pool_->ReleaseResource(std::move(busy_resource)); @@ -622,8 +631,8 @@ TEST_F(ResourcePoolTest, ExactRequestsRespected) { gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB(); resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), task_runner_, - base::TimeDelta::FromMilliseconds(100), ResourcePool::Mode::kGpu, true); + resource_provider_.get(), context_provider_.get(), task_runner_, + base::TimeDelta::FromMilliseconds(100), true); // Create unused resource with size 100x100. CheckAndReturnResource(resource_pool_->AcquireResource(gfx::Size(100, 100), @@ -679,7 +688,7 @@ TEST_F(ResourcePoolTest, MetadataSentToDisplayCompositor) { std::vector<viz::TransferableResource> transfer; resource_provider_->PrepareSendToParent({resource.resource_id_for_export()}, - &transfer); + &transfer, context_provider_.get()); // The verified_flush flag will be set by the ResourceProvider when it exports // the resource. diff --git a/chromium/cc/resources/resource_provider.cc b/chromium/cc/resources/resource_provider.cc deleted file mode 100644 index fcc3b6158e7..00000000000 --- a/chromium/cc/resources/resource_provider.cc +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/resources/resource_provider.h" - -#include <stddef.h> -#include <stdint.h> - -#include <algorithm> -#include <limits> -#include <unordered_map> - -#include "base/atomic_sequence_num.h" -#include "base/macros.h" -#include "base/metrics/histogram.h" -#include "base/numerics/safe_math.h" -#include "base/stl_util.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/trace_event.h" -#include "build/build_config.h" -#include "components/viz/common/gpu/context_provider.h" -#include "components/viz/common/resources/resource_sizes.h" -#include "components/viz/common/resources/returned_resource.h" -#include "components/viz/common/resources/transferable_resource.h" -#include "gpu/command_buffer/client/context_support.h" -#include "gpu/command_buffer/client/gles2_interface.h" -#include "gpu/command_buffer/common/gpu_memory_buffer_support.h" -#include "skia/ext/texture_handle.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/vector2d.h" -#include "ui/gfx/icc_profile.h" -#include "ui/gl/trace_util.h" - -using gpu::gles2::GLES2Interface; - -namespace cc { - -namespace { - -// Generates process-unique IDs to use for tracing a ResourceProvider's -// resources. -base::AtomicSequenceNumber g_next_resource_provider_tracing_id; - -} // namespace - -ResourceProvider::ResourceProvider( - viz::ContextProvider* compositor_context_provider) - : compositor_context_provider_(compositor_context_provider), - lost_context_provider_(false), - tracing_id_(g_next_resource_provider_tracing_id.GetNext()) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). - // Don't register a dump provider in these cases. - // TODO(ericrk): Get this working in Android Webview. crbug.com/517156 - if (base::ThreadTaskRunnerHandle::IsSet()) { - base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - this, "cc::ResourceProvider", base::ThreadTaskRunnerHandle::Get()); - } - - if (!compositor_context_provider) - return; -} - -ResourceProvider::~ResourceProvider() { - base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( - this); - - while (!resources_.empty()) - DeleteResourceInternal(resources_.begin(), FOR_SHUTDOWN); - - if (!compositor_context_provider_) - return; - -#if DCHECK_IS_ON() - // Check that all GL resources has been deleted. - for (const auto& pair : resources_) - DCHECK(!pair.second.is_gpu_resource_type()); -#endif // DCHECK_IS_ON() -} - -void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it, - DeleteStyle style) { - TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal"); - viz::internal::Resource* resource = &it->second; - DCHECK(resource->exported_count == 0 || style != NORMAL); - - // Exported resources are lost on shutdown. - bool exported_resource_lost = - style == FOR_SHUTDOWN && resource->exported_count > 0; - // GPU resources are lost when context is lost. - bool gpu_resource_lost = - resource->is_gpu_resource_type() && lost_context_provider_; - bool lost_resource = - resource->lost || exported_resource_lost || gpu_resource_lost; - - // Wait on sync token before deleting resources we own. - if (!lost_resource && resource->origin == viz::internal::Resource::INTERNAL) - WaitSyncTokenInternal(resource); - - if (resource->image_id) { - DCHECK_EQ(resource->origin, viz::internal::Resource::INTERNAL); - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - gl->DestroyImageCHROMIUM(resource->image_id); - } - - if (resource->gl_id) { - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - gl->DeleteTextures(1, &resource->gl_id); - resource->gl_id = 0; - } - - if (resource->owned_shared_bitmap) { - DCHECK_EQ(viz::ResourceType::kBitmap, resource->type); - resource->shared_bitmap = nullptr; - resource->pixels = nullptr; - resource->owned_shared_bitmap = nullptr; - } - - if (resource->gpu_memory_buffer) { - DCHECK_EQ(viz::ResourceType::kGpuMemoryBuffer, resource->type); - resource->gpu_memory_buffer = nullptr; - } - - resources_.erase(it); -} - -GLenum ResourceProvider::GetResourceTextureTarget(viz::ResourceId id) { - return GetResource(id)->target; -} - -viz::internal::Resource* ResourceProvider::InsertResource( - viz::ResourceId id, - viz::internal::Resource resource) { - std::pair<ResourceMap::iterator, bool> result = - resources_.insert(ResourceMap::value_type(id, std::move(resource))); - DCHECK(result.second); - return &result.first->second; -} - -viz::internal::Resource* ResourceProvider::GetResource(viz::ResourceId id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(id); - ResourceMap::iterator it = resources_.find(id); - DCHECK(it != resources_.end()); - return &it->second; -} - -viz::internal::Resource* ResourceProvider::TryGetResource(viz::ResourceId id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!id) - return nullptr; - ResourceMap::iterator it = resources_.find(id); - if (it == resources_.end()) - return nullptr; - return &it->second; -} - -void ResourceProvider::PopulateSkBitmapWithResource( - SkBitmap* sk_bitmap, - const viz::internal::Resource* resource) { - DCHECK(IsBitmapFormatSupported(resource->format)); - SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(), - resource->size.height()); - bool pixels_installed = - sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes()); - DCHECK(pixels_installed); -} - -void ResourceProvider::WaitSyncTokenInternal( - viz::internal::Resource* resource) { - DCHECK(resource); - if (!resource->ShouldWaitSyncToken()) - return; - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - // In the case of context lost, this sync token may be empty (see comment in - // the UpdateSyncToken() function). The WaitSyncTokenCHROMIUM() function - // handles empty sync tokens properly so just wait anyways and update the - // state the synchronized. - gl->WaitSyncTokenCHROMIUM(resource->sync_token().GetConstData()); - resource->SetSynchronized(); -} - -GLES2Interface* ResourceProvider::ContextGL() const { - viz::ContextProvider* context_provider = compositor_context_provider_; - return context_provider ? context_provider->ContextGL() : nullptr; -} - -bool ResourceProvider::OnMemoryDump( - const base::trace_event::MemoryDumpArgs& args, - base::trace_event::ProcessMemoryDump* pmd) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - const uint64_t tracing_process_id = - base::trace_event::MemoryDumpManager::GetInstance() - ->GetTracingProcessId(); - - for (const auto& resource_entry : resources_) { - const auto& resource = resource_entry.second; - - bool backing_memory_allocated = false; - switch (resource.type) { - case viz::ResourceType::kGpuMemoryBuffer: - backing_memory_allocated = !!resource.gpu_memory_buffer; - break; - case viz::ResourceType::kTexture: - backing_memory_allocated = !!resource.gl_id; - break; - case viz::ResourceType::kBitmap: - backing_memory_allocated = !!resource.shared_bitmap; - break; - } - - if (!backing_memory_allocated) { - // Don't log unallocated resources - they have no backing memory. - continue; - } - - // ResourceIds are not process-unique, so log with the ResourceProvider's - // unique id. - std::string dump_name = - base::StringPrintf("cc/resource_memory/provider_%d/resource_%d", - tracing_id_, resource_entry.first); - base::trace_event::MemoryAllocatorDump* dump = - pmd->CreateAllocatorDump(dump_name); - - // Texture resources may not come with a size, in which case don't report - // one. - if (!resource.size.IsEmpty()) { - uint64_t total_bytes = - viz::ResourceSizes::UncheckedSizeInBytesAligned<size_t>( - resource.size, resource.format); - dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - static_cast<uint64_t>(total_bytes)); - } - - // Resources may be shared across processes and require a shared GUID to - // prevent double counting the memory. - base::trace_event::MemoryAllocatorDumpGuid guid; - base::UnguessableToken shared_memory_guid; - switch (resource.type) { - case viz::ResourceType::kGpuMemoryBuffer: - // GpuMemoryBuffers may be backed by shared memory, and in that case we - // use the guid from there to attribute for the global shared memory - // dumps. Otherwise, they may be backed by native structures, and we - // fall back to that with GetGUIDForTracing. - shared_memory_guid = - resource.gpu_memory_buffer->GetHandle().handle.GetGUID(); - if (shared_memory_guid.is_empty()) { - guid = - resource.gpu_memory_buffer->GetGUIDForTracing(tracing_process_id); - } - break; - case viz::ResourceType::kTexture: - DCHECK(resource.gl_id); - guid = gl::GetGLTextureClientGUIDForTracing( - compositor_context_provider_->ContextSupport() - ->ShareGroupTracingGUID(), - resource.gl_id); - break; - case viz::ResourceType::kBitmap: - // If the resource comes from out of process, it will have this id, - // which we prefer. Otherwise, we fall back to the SharedBitmapGUID - // which can be generated for in-process bitmaps. - shared_memory_guid = resource.shared_bitmap->GetCrossProcessGUID(); - if (shared_memory_guid.is_empty()) - guid = viz::GetSharedBitmapGUIDForTracing(resource.shared_bitmap_id); - break; - } - - DCHECK(!shared_memory_guid.is_empty() || !guid.empty()); - - const int kImportanceForInteral = 2; - const int kImportanceForExternal = 1; - int importance = resource.origin == viz::internal::Resource::INTERNAL - ? kImportanceForInteral - : kImportanceForExternal; - if (!shared_memory_guid.is_empty()) { - pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid, - importance); - } else { - pmd->CreateSharedGlobalAllocatorDump(guid); - pmd->AddOwnershipEdge(dump->guid(), guid, importance); - } - } - - return true; -} - -} // namespace cc diff --git a/chromium/cc/resources/resource_provider.h b/chromium/cc/resources/resource_provider.h deleted file mode 100644 index 31e46d23620..00000000000 --- a/chromium/cc/resources/resource_provider.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_RESOURCE_PROVIDER_H_ -#define CC_RESOURCES_RESOURCE_PROVIDER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <memory> -#include <set> -#include <string> -#include <unordered_map> -#include <unordered_set> -#include <utility> -#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/cc_export.h" -#include "cc/resources/return_callback.h" -#include "components/viz/common/resources/release_callback.h" -#include "components/viz/common/resources/resource.h" -#include "components/viz/common/resources/resource_id.h" -#include "components/viz/common/resources/single_release_callback.h" -#include "components/viz/common/resources/transferable_resource.h" -#include "gpu/command_buffer/common/mailbox.h" -#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/geometry/size.h" - -namespace gpu { -namespace gles2 { -class GLES2Interface; -} -} - -namespace viz { -class ContextProvider; -} // namespace viz - -namespace cc { - -// This class provides abstractions for allocating and transferring resources -// between modules/threads/processes. It abstracts away GL textures vs -// GpuMemoryBuffers vs software bitmaps behind a single ResourceId so that -// code in common can hold onto ResourceIds, as long as the code using them -// knows the correct type. -// -// The resource's underlying type is accessed through Read and Write locks that -// help to safeguard correct usage with DCHECKs. All resources held in -// ResourceProvider are immutable - they can not change format or size once -// they are created, only their contents. -// -// This class is not thread-safe and can only be called from the thread it was -// created on (in practice, the impl thread). -class CC_EXPORT ResourceProvider - : public base::trace_event::MemoryDumpProvider { - public: - using ResourceIdArray = std::vector<viz::ResourceId>; - using ResourceIdMap = std::unordered_map<viz::ResourceId, viz::ResourceId>; - - explicit ResourceProvider(viz::ContextProvider* compositor_context_provider); - ~ResourceProvider() override; - - bool IsSoftware() const { return !compositor_context_provider_; } - - void DidLoseContextProvider() { lost_context_provider_ = true; } - - size_t num_resources() const { return resources_.size(); } - - GLenum GetResourceTextureTarget(viz::ResourceId id); - - // base::trace_event::MemoryDumpProvider implementation. - bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, - base::trace_event::ProcessMemoryDump* pmd) override; - - int tracing_id() const { return tracing_id_; } - - protected: - using ResourceMap = - std::unordered_map<viz::ResourceId, viz::internal::Resource>; - - viz::internal::Resource* InsertResource(viz::ResourceId id, - viz::internal::Resource resource); - viz::internal::Resource* GetResource(viz::ResourceId id); - - // TODO(ericrk): TryGetResource is part of a temporary workaround for cases - // where resources which should be available are missing. This version may - // return nullptr if a resource is not found. https://crbug.com/811858 - viz::internal::Resource* TryGetResource(viz::ResourceId id); - - void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap, - const viz::internal::Resource* resource); - - enum DeleteStyle { - NORMAL, - FOR_SHUTDOWN, - }; - - void DeleteResourceInternal(ResourceMap::iterator it, DeleteStyle style); - - void WaitSyncTokenInternal(viz::internal::Resource* resource); - - // Returns null if we do not have a viz::ContextProvider. - gpu::gles2::GLES2Interface* ContextGL() const; - - ResourceMap resources_; - - viz::ContextProvider* compositor_context_provider_; - - bool lost_context_provider_; - - THREAD_CHECKER(thread_checker_); - - private: - // A process-unique ID used for disambiguating memory dumps from different - // resource providers. - int tracing_id_; - - DISALLOW_COPY_AND_ASSIGN(ResourceProvider); -}; - -} // namespace cc - -#endif // CC_RESOURCES_RESOURCE_PROVIDER_H_ diff --git a/chromium/cc/resources/resource_provider_unittest.cc b/chromium/cc/resources/resource_provider_unittest.cc deleted file mode 100644 index b569bcdd8a7..00000000000 --- a/chromium/cc/resources/resource_provider_unittest.cc +++ /dev/null @@ -1,3709 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/resources/display_resource_provider.h" -#include "cc/resources/layer_tree_resource_provider.h" - -#include <stddef.h> -#include <stdint.h> - -#include <algorithm> -#include <map> -#include <memory> -#include <set> -#include <unordered_map> -#include <vector> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "cc/test/render_pass_test_utils.h" -#include "cc/test/resource_provider_test_utils.h" -#include "components/viz/common/resources/resource_format_utils.h" -#include "components/viz/common/resources/returned_resource.h" -#include "components/viz/common/resources/shared_bitmap_manager.h" -#include "components/viz/common/resources/single_release_callback.h" -#include "components/viz/test/test_context_provider.h" -#include "components/viz/test/test_gpu_memory_buffer_manager.h" -#include "components/viz/test/test_shared_bitmap_manager.h" -#include "components/viz/test/test_texture.h" -#include "components/viz/test/test_web_graphics_context_3d.h" -#include "gpu/GLES2/gl2extchromium.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/gpu_memory_buffer.h" - -using testing::InSequence; -using testing::Mock; -using testing::NiceMock; -using testing::Return; -using testing::StrictMock; -using testing::_; -using testing::AnyNumber; - -namespace cc { -namespace { - -static const bool kUseGpuMemoryBufferResources = false; -static const bool kDelegatedSyncPointsRequired = true; - -MATCHER_P(MatchesSyncToken, sync_token, "") { - gpu::SyncToken other; - memcpy(&other, arg, sizeof(other)); - return other == sync_token; -} - -static void ReleaseCallback(gpu::SyncToken* release_sync_token, - bool* release_lost_resource, - const gpu::SyncToken& sync_token, - bool lost_resource) { - *release_sync_token = sync_token; - *release_lost_resource = lost_resource; -} - -static void ReleaseSharedBitmapCallback( - std::unique_ptr<viz::SharedBitmap> shared_bitmap, - bool* release_called, - gpu::SyncToken* release_sync_token, - bool* lost_resource_result, - const gpu::SyncToken& sync_token, - bool lost_resource) { - *release_called = true; - *release_sync_token = sync_token; - *lost_resource_result = lost_resource; -} - -static std::unique_ptr<viz::SharedBitmap> CreateAndFillSharedBitmap( - viz::SharedBitmapManager* manager, - const gfx::Size& size, - viz::ResourceFormat format, - uint32_t value) { - std::unique_ptr<viz::SharedBitmap> shared_bitmap = - manager->AllocateSharedBitmap(size, format); - CHECK(shared_bitmap); - uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_bitmap->pixels()); - CHECK(pixels); - std::fill_n(pixels, size.GetArea(), value); - return shared_bitmap; -} - -static viz::ResourceSettings CreateResourceSettings() { - viz::ResourceSettings resource_settings; - resource_settings.use_gpu_memory_buffer_resources = - kUseGpuMemoryBufferResources; - return resource_settings; -} - -class TextureStateTrackingContext : public viz::TestWebGraphicsContext3D { - public: - MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture)); - MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param)); - MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token)); - MOCK_METHOD2(produceTextureDirectCHROMIUM, - void(GLuint texture, const GLbyte* mailbox)); - MOCK_METHOD1(createAndConsumeTextureCHROMIUM, - unsigned(const GLbyte* mailbox)); - - // Force all textures to be consecutive numbers starting at "1", - // so we easily can test for them. - GLuint NextTextureId() override { - base::AutoLock lock(namespace_->lock); - return namespace_->next_texture_id++; - } - - void RetireTextureId(GLuint) override {} - - void genSyncToken(GLbyte* sync_token) override { - gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x123), - next_fence_sync_++); - sync_token_data.SetVerifyFlush(); - memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); - } - - GLuint64 GetNextFenceSync() const { return next_fence_sync_; } - - GLuint64 next_fence_sync_ = 1; -}; - -// Shared data between multiple ResourceProviderContext. This contains mailbox -// contents as well as information about sync points. -class ContextSharedData { - public: - static std::unique_ptr<ContextSharedData> Create() { - return base::WrapUnique(new ContextSharedData()); - } - - uint32_t InsertFenceSync() { return next_fence_sync_++; } - - void GenMailbox(GLbyte* mailbox) { - memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM); - memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_)); - ++next_mailbox_; - } - - void ProduceTexture(const GLbyte* mailbox_name, - const gpu::SyncToken& sync_token, - scoped_refptr<viz::TestTexture> texture) { - uint32_t sync_point = static_cast<uint32_t>(sync_token.release_count()); - - unsigned mailbox = 0; - memcpy(&mailbox, mailbox_name, sizeof(mailbox)); - ASSERT_TRUE(mailbox && mailbox < next_mailbox_); - textures_[mailbox] = texture; - ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point); - sync_point_for_mailbox_[mailbox] = sync_point; - } - - scoped_refptr<viz::TestTexture> ConsumeTexture( - const GLbyte* mailbox_name, - const gpu::SyncToken& sync_token) { - unsigned mailbox = 0; - memcpy(&mailbox, mailbox_name, sizeof(mailbox)); - DCHECK(mailbox && mailbox < next_mailbox_); - - // If the latest sync point the context has waited on is before the sync - // point for when the mailbox was set, pretend we never saw that - // ProduceTexture. - if (sync_point_for_mailbox_[mailbox] > sync_token.release_count()) { - NOTREACHED(); - return scoped_refptr<viz::TestTexture>(); - } - return textures_[mailbox]; - } - - private: - ContextSharedData() : next_fence_sync_(1), next_mailbox_(1) {} - - uint64_t next_fence_sync_; - unsigned next_mailbox_; - using TextureMap = - std::unordered_map<unsigned, scoped_refptr<viz::TestTexture>>; - TextureMap textures_; - std::unordered_map<unsigned, uint32_t> sync_point_for_mailbox_; -}; - -class ResourceProviderContext : public viz::TestWebGraphicsContext3D { - public: - static std::unique_ptr<ResourceProviderContext> Create( - ContextSharedData* shared_data) { - return base::WrapUnique(new ResourceProviderContext(shared_data)); - } - - void genSyncToken(GLbyte* sync_token) override { - uint64_t fence_sync = shared_data_->InsertFenceSync(); - gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x123), - fence_sync); - sync_token_data.SetVerifyFlush(); - // Commit the ProduceTextureDirectCHROMIUM calls at this point, so that - // they're associated with the sync point. - for (const std::unique_ptr<PendingProduceTexture>& pending_texture : - pending_produce_textures_) { - shared_data_->ProduceTexture(pending_texture->mailbox, sync_token_data, - pending_texture->texture); - } - pending_produce_textures_.clear(); - memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); - } - - void waitSyncToken(const GLbyte* sync_token) override { - gpu::SyncToken sync_token_data; - if (sync_token) - memcpy(&sync_token_data, sync_token, sizeof(sync_token_data)); - - if (sync_token_data.release_count() > - last_waited_sync_token_.release_count()) { - last_waited_sync_token_ = sync_token_data; - } - } - - const gpu::SyncToken& last_waited_sync_token() const { - return last_waited_sync_token_; - } - - void texStorage2DEXT(GLenum target, - GLint levels, - GLuint internalformat, - GLint width, - GLint height) override { - CheckTextureIsBound(target); - ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); - ASSERT_EQ(1, levels); - GLenum format = GL_RGBA; - switch (internalformat) { - case GL_RGBA8_OES: - break; - case GL_BGRA8_EXT: - format = GL_BGRA_EXT; - break; - default: - NOTREACHED(); - } - AllocateTexture(gfx::Size(width, height), format); - } - - void texImage2D(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void* pixels) override { - CheckTextureIsBound(target); - ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); - ASSERT_FALSE(level); - ASSERT_EQ(internalformat, format); - ASSERT_FALSE(border); - ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); - AllocateTexture(gfx::Size(width, height), format); - if (pixels) - SetPixels(0, 0, width, height, pixels); - } - - void texSubImage2D(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void* pixels) override { - CheckTextureIsBound(target); - ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); - ASSERT_FALSE(level); - ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); - { - base::AutoLock lock_for_texture_access(namespace_->lock); - ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format); - } - ASSERT_TRUE(pixels); - SetPixels(xoffset, yoffset, width, height, pixels); - } - - void genMailboxCHROMIUM(GLbyte* mailbox) override { - return shared_data_->GenMailbox(mailbox); - } - - void produceTextureDirectCHROMIUM(GLuint texture, - const GLbyte* mailbox) override { - // Delay moving the texture into the mailbox until the next - // sync token, so that it is not visible to other contexts that - // haven't waited on that sync point. - std::unique_ptr<PendingProduceTexture> pending(new PendingProduceTexture); - memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox)); - base::AutoLock lock_for_texture_access(namespace_->lock); - pending->texture = UnboundTexture(texture); - pending_produce_textures_.push_back(std::move(pending)); - } - - GLuint createAndConsumeTextureCHROMIUM(const GLbyte* mailbox) override { - GLuint texture_id = createTexture(); - base::AutoLock lock_for_texture_access(namespace_->lock); - scoped_refptr<viz::TestTexture> texture = - shared_data_->ConsumeTexture(mailbox, last_waited_sync_token_); - namespace_->textures.Replace(texture_id, texture); - return texture_id; - } - - void GetPixels(const gfx::Size& size, - viz::ResourceFormat format, - uint8_t* pixels) { - CheckTextureIsBound(GL_TEXTURE_2D); - base::AutoLock lock_for_texture_access(namespace_->lock); - scoped_refptr<viz::TestTexture> texture = BoundTexture(GL_TEXTURE_2D); - ASSERT_EQ(texture->size, size); - ASSERT_EQ(texture->format, format); - memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format)); - } - - protected: - explicit ResourceProviderContext(ContextSharedData* shared_data) - : shared_data_(shared_data) {} - - private: - void AllocateTexture(const gfx::Size& size, GLenum format) { - CheckTextureIsBound(GL_TEXTURE_2D); - viz::ResourceFormat texture_format = viz::RGBA_8888; - switch (format) { - case GL_RGBA: - texture_format = viz::RGBA_8888; - break; - case GL_BGRA_EXT: - texture_format = viz::BGRA_8888; - break; - } - base::AutoLock lock_for_texture_access(namespace_->lock); - BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format); - } - - void SetPixels(int xoffset, - int yoffset, - int width, - int height, - const void* pixels) { - CheckTextureIsBound(GL_TEXTURE_2D); - base::AutoLock lock_for_texture_access(namespace_->lock); - scoped_refptr<viz::TestTexture> texture = BoundTexture(GL_TEXTURE_2D); - ASSERT_TRUE(texture->data.get()); - ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width()); - ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height()); - ASSERT_TRUE(pixels); - size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format); - size_t out_pitch = - TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format); - uint8_t* dest = texture->data.get() + yoffset * out_pitch + - TextureSizeBytes(gfx::Size(xoffset, 1), texture->format); - const uint8_t* src = static_cast<const uint8_t*>(pixels); - for (int i = 0; i < height; ++i) { - memcpy(dest, src, in_pitch); - dest += out_pitch; - src += in_pitch; - } - } - - struct PendingProduceTexture { - GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; - scoped_refptr<viz::TestTexture> texture; - }; - ContextSharedData* shared_data_; - gpu::SyncToken last_waited_sync_token_; - std::vector<std::unique_ptr<PendingProduceTexture>> pending_produce_textures_; -}; - -void GetResourcePixels(DisplayResourceProvider* resource_provider, - ResourceProviderContext* context, - viz::ResourceId id, - const gfx::Size& size, - viz::ResourceFormat format, - uint8_t* pixels) { - resource_provider->WaitSyncToken(id); - if (resource_provider->IsSoftware()) { - DisplayResourceProvider::ScopedReadLockSoftware lock_software( - resource_provider, id); - memcpy(pixels, lock_software.sk_bitmap()->getPixels(), - lock_software.sk_bitmap()->computeByteSize()); - } else { - DisplayResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id); - ASSERT_NE(0U, lock_gl.texture_id()); - context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id()); - context->GetPixels(size, format, pixels); - } -} - -class ResourceProviderTest : public testing::TestWithParam<bool> { - public: - explicit ResourceProviderTest(bool child_needs_sync_token) - : use_gpu_(GetParam()), - child_needs_sync_token_(child_needs_sync_token), - shared_data_(ContextSharedData::Create()) { - if (use_gpu_) { - auto context3d(ResourceProviderContext::Create(shared_data_.get())); - context3d_ = context3d.get(); - context_provider_ = - viz::TestContextProvider::Create(std::move(context3d)); - context_provider_->UnboundTestContext3d() - ->set_support_texture_format_bgra8888(true); - context_provider_->BindToCurrentThread(); - - auto child_context_owned = - ResourceProviderContext::Create(shared_data_.get()); - child_context_ = child_context_owned.get(); - child_context_provider_ = - viz::TestContextProvider::Create(std::move(child_context_owned)); - child_context_provider_->UnboundTestContext3d() - ->set_support_texture_format_bgra8888(true); - child_context_provider_->BindToCurrentThread(); - gpu_memory_buffer_manager_ = - std::make_unique<viz::TestGpuMemoryBufferManager>(); - child_gpu_memory_buffer_manager_ = - gpu_memory_buffer_manager_->CreateClientGpuMemoryBufferManager(); - } else { - shared_bitmap_manager_ = std::make_unique<viz::TestSharedBitmapManager>(); - } - - resource_provider_ = std::make_unique<DisplayResourceProvider>( - context_provider_.get(), shared_bitmap_manager_.get()); - - MakeChildResourceProvider(); - } - - ResourceProviderTest() : ResourceProviderTest(true) {} - - bool use_gpu() const { return use_gpu_; } - - void MakeChildResourceProvider() { - child_resource_provider_ = std::make_unique<LayerTreeResourceProvider>( - child_context_provider_.get(), shared_bitmap_manager_.get(), - child_gpu_memory_buffer_manager_.get(), child_needs_sync_token_, - CreateResourceSettings()); - } - - static void CollectResources( - std::vector<viz::ReturnedResource>* array, - const std::vector<viz::ReturnedResource>& returned) { - array->insert(array->end(), returned.begin(), returned.end()); - } - - static ReturnCallback GetReturnCallback( - std::vector<viz::ReturnedResource>* array) { - return base::Bind(&ResourceProviderTest::CollectResources, array); - } - - static void SetResourceFilter(DisplayResourceProvider* resource_provider, - viz::ResourceId id, - GLenum filter) { - DisplayResourceProvider::ScopedSamplerGL sampler(resource_provider, id, - GL_TEXTURE_2D, filter); - } - - ResourceProviderContext* context() { return context3d_; } - - viz::ResourceId CreateChildMailbox(gpu::SyncToken* release_sync_token, - bool* lost_resource, - bool* release_called, - gpu::SyncToken* sync_token, - viz::ResourceFormat format) { - if (use_gpu()) { - unsigned texture = child_context_->createTexture(); - gpu::Mailbox gpu_mailbox; - child_context_->genMailboxCHROMIUM(gpu_mailbox.name); - child_context_->produceTextureDirectCHROMIUM(texture, gpu_mailbox.name); - child_context_->genSyncToken(sync_token->GetData()); - EXPECT_TRUE(sync_token->HasData()); - - std::unique_ptr<viz::SharedBitmap> shared_bitmap; - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::Bind( - ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), - release_called, release_sync_token, lost_resource)); - viz::TransferableResource gl_resource = viz::TransferableResource::MakeGL( - gpu_mailbox, GL_LINEAR, GL_TEXTURE_2D, *sync_token); - gl_resource.format = format; - return child_resource_provider_->ImportResource(gl_resource, - std::move(callback)); - } else { - gfx::Size size(64, 64); - std::unique_ptr<viz::SharedBitmap> shared_bitmap( - CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, format, - 0)); - - viz::SharedBitmap* shared_bitmap_ptr = shared_bitmap.get(); - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::Bind( - ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), - release_called, release_sync_token, lost_resource)); - return child_resource_provider_->ImportResource( - viz::TransferableResource::MakeSoftware( - shared_bitmap_ptr->id(), shared_bitmap_ptr->sequence_number(), - size, format), - std::move(callback)); - } - } - - viz::ResourceId MakeGpuResourceAndSendToDisplay( - char c, - GLuint filter, - GLuint target, - const gpu::SyncToken& sync_token, - DisplayResourceProvider* resource_provider) { - ReturnCallback return_callback = base::DoNothing(); - - int child = resource_provider->CreateChild(return_callback); - - gpu::Mailbox gpu_mailbox; - gpu_mailbox.name[0] = c; - gpu_mailbox.name[1] = 0; - auto resource = viz::TransferableResource::MakeGL(gpu_mailbox, GL_LINEAR, - target, sync_token); - resource.id = 11; - resource_provider->ReceiveFromChild(child, {resource}); - auto& map = resource_provider->GetChildToParentMap(child); - return map.find(resource.id)->second; - } - - protected: - const bool use_gpu_; - const bool child_needs_sync_token_; - const std::unique_ptr<ContextSharedData> shared_data_; - ResourceProviderContext* context3d_ = nullptr; - ResourceProviderContext* child_context_ = nullptr; - scoped_refptr<viz::TestContextProvider> context_provider_; - scoped_refptr<viz::TestContextProvider> child_context_provider_; - std::unique_ptr<viz::TestGpuMemoryBufferManager> gpu_memory_buffer_manager_; - std::unique_ptr<DisplayResourceProvider> resource_provider_; - std::unique_ptr<viz::TestGpuMemoryBufferManager> - child_gpu_memory_buffer_manager_; - std::unique_ptr<LayerTreeResourceProvider> child_resource_provider_; - std::unique_ptr<viz::TestSharedBitmapManager> shared_bitmap_manager_; -}; - -TEST_P(ResourceProviderTest, Basic) { - DCHECK_EQ(resource_provider_->IsSoftware(), !use_gpu()); - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - viz::ResourceId id; - if (!use_gpu()) { - id = child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace(), - format); - } else { - id = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - } - EXPECT_EQ(1, static_cast<int>(child_resource_provider_->num_resources())); - if (use_gpu()) - EXPECT_EQ(0u, context()->NumTextures()); - - uint8_t data[4] = {1, 2, 3, 4}; - child_resource_provider_->CopyToResource(id, data, size); - if (use_gpu()) - EXPECT_EQ(1u, context()->NumTextures()); - - // Give the resource to the parent to read its pixels. - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = - resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent({id}, &list); - resource_provider_->ReceiveFromChild(child_id, list); - auto id_map = resource_provider_->GetChildToParentMap(child_id); - - uint8_t result[4] = {0}; - GetResourcePixels(resource_provider_.get(), context(), id_map[id], size, - format, result); - EXPECT_EQ(0, memcmp(data, result, pixel_size)); - - // Give it back to the child. - resource_provider_->DeclareUsedResourcesFromChild(child_id, {}); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - - child_resource_provider_->DeleteResource(id); - EXPECT_EQ(0, static_cast<int>(child_resource_provider_->num_resources())); - if (use_gpu()) - EXPECT_EQ(0u, context()->NumTextures()); -} - -TEST_P(ResourceProviderTest, SimpleUpload) { - gfx::Size size(2, 2); - viz::ResourceFormat format = viz::RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(16U, pixel_size); - - viz::ResourceId id1; - viz::ResourceId id2; - if (use_gpu()) { - id1 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - id2 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - - } else { - id1 = child_resource_provider_->CreateBitmapResource( - size, gfx::ColorSpace(), format); - id2 = child_resource_provider_->CreateBitmapResource( - size, gfx::ColorSpace(), format); - } - - uint8_t image[16] = {0}; - child_resource_provider_->CopyToResource(id1, image, size); - - for (uint8_t i = 0; i < pixel_size; ++i) - image[i] = i; - child_resource_provider_->CopyToResource(id2, image, size); - - // Return the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - SendResourceAndGetChildToParentMap({id1, id2}, resource_provider_.get(), - child_resource_provider_.get()); - viz::ResourceId mapped_id1 = resource_map[id1]; - viz::ResourceId mapped_id2 = resource_map[id2]; - - { - uint8_t result[16] = {0}; - uint8_t expected[16] = {0}; - GetResourcePixels(resource_provider_.get(), context(), mapped_id1, size, - format, result); - EXPECT_EQ(0, memcmp(expected, result, pixel_size)); - } - - { - uint8_t result[16] = {0}; - uint8_t expected[16] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - GetResourcePixels(resource_provider_.get(), context(), mapped_id2, size, - format, result); - EXPECT_EQ(0, memcmp(expected, result, pixel_size)); - } -} - -TEST_P(ResourceProviderTest, TransferGLResources) { - if (!use_gpu()) - return; - gfx::Size size(1, 1); - // Use some non-default format to detect when defaults aren't changed - // correctly. - viz::ResourceFormat format = viz::BGRA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - gfx::ColorSpace color_space1 = gfx::ColorSpace::CreateSRGB(); - viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, color_space1); - uint8_t data1[4] = { 1, 2, 3, 4 }; - child_resource_provider_->CopyToResource(id1, data1, size); - - viz::ResourceId id2 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - uint8_t data2[4] = { 5, 5, 5, 5 }; - child_resource_provider_->CopyToResource(id2, data2, size); - - viz::ResourceId id3 = child_resource_provider_->CreateGpuMemoryBufferResource( - size, viz::ResourceTextureHint::kDefault, format, - gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace()); - { - LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( - child_resource_provider_.get(), id3); - EXPECT_TRUE(lock.GetGpuMemoryBuffer()); - } - - std::vector<viz::ReturnedResource> 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; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - resource_ids_to_transfer.push_back(id3); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(3u, list.size()); - EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); - EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); - EXPECT_EQ(list[0].mailbox_holder.sync_token, - list[1].mailbox_holder.sync_token); - EXPECT_TRUE(list[2].mailbox_holder.sync_token.HasData()); - EXPECT_EQ(list[0].mailbox_holder.sync_token, - list[2].mailbox_holder.sync_token); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[0].mailbox_holder.texture_target); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[1].mailbox_holder.texture_target); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[2].mailbox_holder.texture_target); - EXPECT_EQ(list[0].buffer_format, gfx::BufferFormat::RGBA_8888); - EXPECT_EQ(list[1].buffer_format, gfx::BufferFormat::RGBA_8888); - EXPECT_EQ(list[2].buffer_format, gfx::BufferFormat::BGRA_8888); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); - resource_provider_->ReceiveFromChild(child_id, list); - EXPECT_NE(list[0].mailbox_holder.sync_token, - context3d_->last_waited_sync_token()); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - { - viz::ResourceId mapped_resource_id = resource_map[list[0].id]; - resource_provider_->WaitSyncToken(mapped_resource_id); - DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), - mapped_resource_id); - } - EXPECT_EQ(list[0].mailbox_holder.sync_token, - context3d_->last_waited_sync_token()); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id1); - resource_ids_to_receive.insert(id2); - resource_ids_to_receive.insert(id3); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - - EXPECT_EQ(3u, resource_provider_->num_resources()); - viz::ResourceId mapped_id1 = resource_map[id1]; - viz::ResourceId mapped_id2 = resource_map[id2]; - viz::ResourceId mapped_id3 = resource_map[id3]; - EXPECT_NE(0u, mapped_id1); - EXPECT_NE(0u, mapped_id2); - EXPECT_NE(0u, mapped_id3); - EXPECT_FALSE(resource_provider_->InUse(mapped_id1)); - EXPECT_FALSE(resource_provider_->InUse(mapped_id2)); - EXPECT_FALSE(resource_provider_->InUse(mapped_id3)); - - uint8_t result[4] = { 0 }; - GetResourcePixels( - resource_provider_.get(), context(), mapped_id1, size, format, result); - EXPECT_EQ(0, memcmp(data1, result, pixel_size)); - - GetResourcePixels( - resource_provider_.get(), context(), mapped_id2, size, format, result); - EXPECT_EQ(0, memcmp(data2, result, pixel_size)); - - EXPECT_FALSE(resource_provider_->IsOverlayCandidate(mapped_id1)); - EXPECT_FALSE(resource_provider_->IsOverlayCandidate(mapped_id2)); - EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id3)); - - { - resource_provider_->WaitSyncToken(mapped_id1); - DisplayResourceProvider::ScopedReadLockGL lock1(resource_provider_.get(), - mapped_id1); - EXPECT_TRUE(lock1.color_space() == color_space1); - } - - { - // Check that transfering again the same resource from the child to the - // parent works. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - resource_ids_to_transfer.push_back(id3); - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - EXPECT_EQ(3u, list.size()); - EXPECT_EQ(id1, list[0].id); - EXPECT_EQ(id2, list[1].id); - EXPECT_EQ(id3, list[2].id); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[0].mailbox_holder.texture_target); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[1].mailbox_holder.texture_target); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[2].mailbox_holder.texture_target); - EXPECT_EQ(list[0].buffer_format, gfx::BufferFormat::RGBA_8888); - EXPECT_EQ(list[1].buffer_format, gfx::BufferFormat::RGBA_8888); - EXPECT_EQ(list[2].buffer_format, gfx::BufferFormat::BGRA_8888); - std::vector<viz::ReturnedResource> returned = - viz::TransferableResource::ReturnResources(list); - child_resource_provider_->ReceiveReturnsFromParent(returned); - // ids were exported twice, we returned them only once, they should still - // be in-use. - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); - } - { - EXPECT_EQ(0u, returned_to_child.size()); - - // Transfer resources back from the parent to the child. Set no resources as - // being in use. - viz::ResourceIdSet no_resources; - resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - - ASSERT_EQ(3u, returned_to_child.size()); - EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); - EXPECT_TRUE(returned_to_child[1].sync_token.HasData()); - EXPECT_TRUE(returned_to_child[2].sync_token.HasData()); - EXPECT_FALSE(returned_to_child[0].lost); - EXPECT_FALSE(returned_to_child[1].lost); - EXPECT_FALSE(returned_to_child[2].lost); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - returned_to_child.clear(); - } - EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2)); - EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3)); - - { - // ScopedWriteLockGL will wait for the sync token, which is convenient since - // |child_resource_provider_| doesn't expose that. - LayerTreeResourceProvider::ScopedWriteLockGL lock( - child_resource_provider_.get(), id1); - ASSERT_NE(0U, lock.GetTexture()); - } - // Ensure copying to resource doesn't fail. - child_resource_provider_->CopyToResource(id2, data2, size); - { - // ScopedWriteLockGL will wait for the sync token. - LayerTreeResourceProvider::ScopedWriteLockGL lock( - child_resource_provider_.get(), id2); - ASSERT_NE(0U, lock.GetTexture()); - } - { - // Transfer resources to the parent again. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - resource_ids_to_transfer.push_back(id3); - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(3u, list.size()); - EXPECT_EQ(id1, list[0].id); - EXPECT_EQ(id2, list[1].id); - EXPECT_EQ(id3, list[2].id); - EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); - EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); - EXPECT_TRUE(list[2].mailbox_holder.sync_token.HasData()); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[0].mailbox_holder.texture_target); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[1].mailbox_holder.texture_target); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[2].mailbox_holder.texture_target); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); - resource_provider_->ReceiveFromChild(child_id, list); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id1); - resource_ids_to_receive.insert(id2); - resource_ids_to_receive.insert(id3); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - } - - EXPECT_EQ(0u, returned_to_child.size()); - - EXPECT_EQ(3u, resource_provider_->num_resources()); - resource_provider_->DestroyChild(child_id); - EXPECT_EQ(0u, resource_provider_->num_resources()); - - ASSERT_EQ(3u, returned_to_child.size()); - EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); - EXPECT_TRUE(returned_to_child[1].sync_token.HasData()); - EXPECT_TRUE(returned_to_child[2].sync_token.HasData()); - EXPECT_FALSE(returned_to_child[0].lost); - EXPECT_FALSE(returned_to_child[1].lost); - EXPECT_FALSE(returned_to_child[2].lost); -} - -#if defined(OS_ANDROID) -TEST_P(ResourceProviderTest, OverlayPromotionHint) { - if (!use_gpu()) - return; - - GLuint external_texture_id = child_context_->createExternalTexture(); - - gpu::Mailbox external_mailbox; - child_context_->genMailboxCHROMIUM(external_mailbox.name); - child_context_->produceTextureDirectCHROMIUM(external_texture_id, - external_mailbox.name); - gpu::SyncToken external_sync_token; - child_context_->genSyncToken(external_sync_token.GetData()); - EXPECT_TRUE(external_sync_token.HasData()); - - viz::TransferableResource id1_transfer = - viz::TransferableResource::MakeGLOverlay( - external_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, - external_sync_token, gfx::Size(1, 1), true); - id1_transfer.wants_promotion_hint = true; - id1_transfer.is_backed_by_surface_texture = true; - viz::ResourceId id1 = child_resource_provider_->ImportResource( - id1_transfer, viz::SingleReleaseCallback::Create(base::DoNothing())); - - viz::TransferableResource id2_transfer = - viz::TransferableResource::MakeGLOverlay( - external_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, - external_sync_token, gfx::Size(1, 1), true); - id2_transfer.wants_promotion_hint = false; - id2_transfer.is_backed_by_surface_texture = false; - viz::ResourceId id2 = child_resource_provider_->ImportResource( - id2_transfer, viz::SingleReleaseCallback::Create(base::DoNothing())); - - std::vector<viz::ReturnedResource> 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; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(2u, list.size()); - resource_provider_->ReceiveFromChild(child_id, list); - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - viz::ResourceId mapped_id1 = resource_map[list[0].id]; - viz::ResourceId mapped_id2 = resource_map[list[1].id]; - - // The promotion hints should not be recorded until after we wait. This is - // because we can't notify them until they're synchronized, and we choose to - // ignore unwaited resources rather than send them a "no" hint. If they end - // up in the request set before we wait, then the attempt to notify them wil; - // DCHECK when we try to lock them for reading in SendPromotionHints. - EXPECT_EQ(0u, resource_provider_->CountPromotionHintRequestsForTesting()); - { - resource_provider_->WaitSyncToken(mapped_id1); - DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), - mapped_id1); - } - EXPECT_EQ(1u, resource_provider_->CountPromotionHintRequestsForTesting()); - - EXPECT_EQ(list[0].mailbox_holder.sync_token, - context3d_->last_waited_sync_token()); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id1); - resource_ids_to_receive.insert(id2); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - - EXPECT_EQ(2u, resource_provider_->num_resources()); - - EXPECT_NE(0u, mapped_id1); - EXPECT_NE(0u, mapped_id2); - - // Make sure that the request for a promotion hint was noticed. - EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id1)); - EXPECT_TRUE(resource_provider_->IsBackedBySurfaceTexture(mapped_id1)); - EXPECT_TRUE(resource_provider_->WantsPromotionHintForTesting(mapped_id1)); - - EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id2)); - EXPECT_FALSE(resource_provider_->IsBackedBySurfaceTexture(mapped_id2)); - EXPECT_FALSE(resource_provider_->WantsPromotionHintForTesting(mapped_id2)); - - // ResourceProvider maintains a set of promotion hint requests that should be - // cleared when resources are deleted. - resource_provider_->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - EXPECT_EQ(2u, returned_to_child.size()); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - - EXPECT_EQ(0u, resource_provider_->CountPromotionHintRequestsForTesting()); - - resource_provider_->DestroyChild(child_id); -} -#endif - -TEST_P(ResourceProviderTest, TransferGLResources_NoSyncToken) { - if (!use_gpu()) - return; - - bool need_sync_tokens = false; - auto no_token_resource_provider = std::make_unique<LayerTreeResourceProvider>( - child_context_provider_.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), need_sync_tokens, - CreateResourceSettings()); - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - viz::ResourceId id1 = no_token_resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - uint8_t data1[4] = {1, 2, 3, 4}; - no_token_resource_provider->CopyToResource(id1, data1, size); - - viz::ResourceId id2 = - no_token_resource_provider->CreateGpuMemoryBufferResource( - size, viz::ResourceTextureHint::kDefault, format, - gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace()); - { - // Ensure locking the memory buffer doesn't create an unnecessary sync - // point. - LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( - no_token_resource_provider.get(), id2); - EXPECT_TRUE(lock.GetGpuMemoryBuffer()); - } - - GLuint external_texture_id = child_context_->createExternalTexture(); - - // A sync point is specified directly and should be used. - gpu::Mailbox external_mailbox; - child_context_->genMailboxCHROMIUM(external_mailbox.name); - child_context_->produceTextureDirectCHROMIUM(external_texture_id, - external_mailbox.name); - gpu::SyncToken external_sync_token; - child_context_->genSyncToken(external_sync_token.GetData()); - EXPECT_TRUE(external_sync_token.HasData()); - viz::ResourceId id3 = no_token_resource_provider->ImportResource( - viz::TransferableResource::MakeGL(external_mailbox, GL_LINEAR, - GL_TEXTURE_EXTERNAL_OES, - external_sync_token), - viz::SingleReleaseCallback::Create(base::DoNothing())); - - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = - resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - resource_provider_->SetChildNeedsSyncTokens(child_id, false); - { - // Transfer some resources to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - resource_ids_to_transfer.push_back(id3); - std::vector<viz::TransferableResource> list; - no_token_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(3u, list.size()); - // Standard resources shouldn't require creating and sending a sync point. - EXPECT_FALSE(list[0].mailbox_holder.sync_token.HasData()); - EXPECT_FALSE(list[1].mailbox_holder.sync_token.HasData()); - // A given sync point should be passed through. - EXPECT_EQ(external_sync_token, list[2].mailbox_holder.sync_token); - resource_provider_->ReceiveFromChild(child_id, list); - - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id1); - resource_ids_to_receive.insert(id2); - resource_ids_to_receive.insert(id3); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - } - - { - EXPECT_EQ(0u, returned_to_child.size()); - - // Transfer resources back from the parent to the child. Set no resources as - // being in use. - viz::ResourceIdSet no_resources; - resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - - ASSERT_EQ(3u, returned_to_child.size()); - std::map<viz::ResourceId, gpu::SyncToken> returned_sync_tokens; - for (const auto& returned : returned_to_child) - returned_sync_tokens[returned.id] = returned.sync_token; - - ASSERT_TRUE(returned_sync_tokens.find(id1) != returned_sync_tokens.end()); - // No new sync point should be created transferring back. - ASSERT_TRUE(returned_sync_tokens.find(id1) != returned_sync_tokens.end()); - EXPECT_FALSE(returned_sync_tokens[id1].HasData()); - ASSERT_TRUE(returned_sync_tokens.find(id2) != returned_sync_tokens.end()); - EXPECT_FALSE(returned_sync_tokens[id2].HasData()); - // Original sync point given should be returned. - ASSERT_TRUE(returned_sync_tokens.find(id3) != returned_sync_tokens.end()); - EXPECT_EQ(external_sync_token, returned_sync_tokens[id3]); - EXPECT_FALSE(returned_to_child[0].lost); - EXPECT_FALSE(returned_to_child[1].lost); - EXPECT_FALSE(returned_to_child[2].lost); - no_token_resource_provider->ReceiveReturnsFromParent(returned_to_child); - returned_to_child.clear(); - } - - resource_provider_->DestroyChild(child_id); -} - -// Test that SetBatchReturnResources batching works. -TEST_P(ResourceProviderTest, SetBatchPreventsReturn) { - if (!use_gpu()) - return; - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - uint8_t data1[4] = {1, 2, 3, 4}; - std::vector<viz::ReturnedResource> 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; - viz::ResourceId ids[2]; - for (size_t i = 0; i < arraysize(ids); i++) { - ids[i] = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - child_resource_provider_->CopyToResource(ids[i], data1, size); - resource_ids_to_transfer.push_back(ids[i]); - } - - std::vector<viz::TransferableResource> 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); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - - std::vector<std::unique_ptr<DisplayResourceProvider::ScopedReadLockGL>> - read_locks; - for (auto& resource_id : list) { - unsigned int mapped_resource_id = resource_map[resource_id.id]; - resource_provider_->WaitSyncToken(mapped_resource_id); - read_locks.push_back( - std::make_unique<DisplayResourceProvider::ScopedReadLockGL>( - resource_provider_.get(), mapped_resource_id)); - } - - resource_provider_->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - std::unique_ptr<DisplayResourceProvider::ScopedBatchReturnResources> - returner = - std::make_unique<DisplayResourceProvider::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 (!use_gpu()) - return; - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - uint8_t data1[4] = {1, 2, 3, 4}; - child_resource_provider_->CopyToResource(id1, data1, size); - - std::vector<viz::ReturnedResource> 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; - resource_ids_to_transfer.push_back(id1); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(1u, list.size()); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - - resource_provider_->ReceiveFromChild(child_id, list); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - viz::ResourceId mapped_resource_id = resource_map[list[0].id]; - resource_provider_->WaitSyncToken(mapped_resource_id); - DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), - mapped_resource_id); - - resource_provider_->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - EXPECT_EQ(0u, returned_to_child.size()); - } - - EXPECT_EQ(1u, returned_to_child.size()); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - - // No need to wait for the sync token here -- it will be returned to the - // client on delete. - EXPECT_EQ(1u, child_resource_provider_->num_resources()); - child_resource_provider_->DeleteResource(id1); - EXPECT_EQ(0u, child_resource_provider_->num_resources()); - - resource_provider_->DestroyChild(child_id); -} - -class TestFence : public viz::ResourceFence { - public: - TestFence() = default; - - // viz::ResourceFence implementation. - void Set() override {} - bool HasPassed() override { return passed; } - void Wait() override {} - - bool passed = false; - - private: - ~TestFence() override = default; -}; - -TEST_P(ResourceProviderTest, ReadLockFenceStopsReturnToChildOrDelete) { - if (!use_gpu()) - return; - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - uint8_t data1[4] = {1, 2, 3, 4}; - child_resource_provider_->CopyToResource(id1, data1, size); - child_resource_provider_->EnableReadLockFencesForTesting(id1); - std::vector<viz::ReturnedResource> 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; - resource_ids_to_transfer.push_back(id1); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(1u, list.size()); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(list[0].read_lock_fences_enabled); - - resource_provider_->ReceiveFromChild(child_id, list); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - - scoped_refptr<TestFence> fence(new TestFence); - resource_provider_->SetReadLockFence(fence.get()); - { - unsigned parent_id = resource_map[list.front().id]; - resource_provider_->WaitSyncToken(parent_id); - DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), - parent_id); - } - resource_provider_->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - EXPECT_EQ(0u, returned_to_child.size()); - - resource_provider_->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - EXPECT_EQ(0u, returned_to_child.size()); - fence->passed = true; - - resource_provider_->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - EXPECT_EQ(1u, returned_to_child.size()); - - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - child_resource_provider_->DeleteResource(id1); - EXPECT_EQ(0u, child_resource_provider_->num_resources()); -} - -TEST_P(ResourceProviderTest, ReadLockFenceDestroyChild) { - if (!use_gpu()) - return; - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - uint8_t data[4] = {1, 2, 3, 4}; - child_resource_provider_->CopyToResource(id1, data, size); - child_resource_provider_->EnableReadLockFencesForTesting(id1); - - viz::ResourceId id2 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - child_resource_provider_->CopyToResource(id2, data, size); - - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = - resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - - // Transfer resources to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(2u, list.size()); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - - resource_provider_->ReceiveFromChild(child_id, list); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - - scoped_refptr<TestFence> fence(new TestFence); - resource_provider_->SetReadLockFence(fence.get()); - { - for (size_t i = 0; i < list.size(); i++) { - unsigned parent_id = resource_map[list[i].id]; - resource_provider_->WaitSyncToken(parent_id); - DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), - parent_id); - } - } - EXPECT_EQ(0u, returned_to_child.size()); - - EXPECT_EQ(2u, resource_provider_->num_resources()); - - resource_provider_->DestroyChild(child_id); - - EXPECT_EQ(0u, resource_provider_->num_resources()); - EXPECT_EQ(2u, returned_to_child.size()); - - // id1 should be lost and id2 should not. - EXPECT_EQ(returned_to_child[0].lost, returned_to_child[0].id == id1); - EXPECT_EQ(returned_to_child[1].lost, returned_to_child[1].id == id1); - - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - child_resource_provider_->DeleteResource(id1); - child_resource_provider_->DeleteResource(id2); - EXPECT_EQ(0u, child_resource_provider_->num_resources()); -} - -TEST_P(ResourceProviderTest, ReadLockFenceContextLost) { - if (!use_gpu()) - return; - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - uint8_t data[4] = {1, 2, 3, 4}; - child_resource_provider_->CopyToResource(id1, data, size); - child_resource_provider_->EnableReadLockFencesForTesting(id1); - - viz::ResourceId id2 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - child_resource_provider_->CopyToResource(id2, data, size); - - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = - resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - - // Transfer resources to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(2u, list.size()); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - - resource_provider_->ReceiveFromChild(child_id, list); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - - scoped_refptr<TestFence> fence(new TestFence); - resource_provider_->SetReadLockFence(fence.get()); - { - for (size_t i = 0; i < list.size(); i++) { - unsigned parent_id = resource_map[list[i].id]; - resource_provider_->WaitSyncToken(parent_id); - DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), - parent_id); - } - } - EXPECT_EQ(0u, returned_to_child.size()); - - EXPECT_EQ(2u, resource_provider_->num_resources()); - resource_provider_->DidLoseContextProvider(); - resource_provider_ = nullptr; - - EXPECT_EQ(2u, returned_to_child.size()); - - EXPECT_TRUE(returned_to_child[0].lost); - EXPECT_TRUE(returned_to_child[1].lost); -} - -TEST_P(ResourceProviderTest, TransferSoftwareResources) { - if (use_gpu()) - return; - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - viz::ResourceId id1 = child_resource_provider_->CreateBitmapResource( - size, gfx::ColorSpace(), format); - uint8_t data1[4] = { 1, 2, 3, 4 }; - child_resource_provider_->CopyToResource(id1, data1, size); - - viz::ResourceId id2 = child_resource_provider_->CreateBitmapResource( - size, gfx::ColorSpace(), format); - uint8_t data2[4] = { 5, 5, 5, 5 }; - child_resource_provider_->CopyToResource(id2, data2, size); - - std::vector<viz::ReturnedResource> 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; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(2u, list.size()); - EXPECT_FALSE(list[0].mailbox_holder.sync_token.HasData()); - EXPECT_FALSE(list[1].mailbox_holder.sync_token.HasData()); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - resource_provider_->ReceiveFromChild(child_id, list); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id1); - resource_ids_to_receive.insert(id2); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - } - - EXPECT_EQ(2u, resource_provider_->num_resources()); - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - viz::ResourceId mapped_id1 = resource_map[id1]; - viz::ResourceId mapped_id2 = resource_map[id2]; - EXPECT_NE(0u, mapped_id1); - EXPECT_NE(0u, mapped_id2); - EXPECT_FALSE(resource_provider_->InUse(mapped_id1)); - EXPECT_FALSE(resource_provider_->InUse(mapped_id2)); - - uint8_t result[4] = { 0 }; - GetResourcePixels( - resource_provider_.get(), context(), mapped_id1, size, format, result); - EXPECT_EQ(0, memcmp(data1, result, pixel_size)); - - GetResourcePixels( - resource_provider_.get(), context(), mapped_id2, size, format, result); - EXPECT_EQ(0, memcmp(data2, result, pixel_size)); - - { - // Check that transfering again the same resource from the child to the - // parent works. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - EXPECT_EQ(2u, list.size()); - EXPECT_EQ(id1, list[0].id); - EXPECT_EQ(id2, list[1].id); - std::vector<viz::ReturnedResource> returned = - viz::TransferableResource::ReturnResources(list); - child_resource_provider_->ReceiveReturnsFromParent(returned); - // ids were exported twice, we returned them only once, they should still - // be in-use. - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - } - { - EXPECT_EQ(0u, returned_to_child.size()); - - // Transfer resources back from the parent to the child. Set no resources as - // being in use. - viz::ResourceIdSet no_resources; - resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - - ASSERT_EQ(2u, returned_to_child.size()); - EXPECT_FALSE(returned_to_child[0].sync_token.HasData()); - EXPECT_FALSE(returned_to_child[1].sync_token.HasData()); - std::set<viz::ResourceId> expected_ids; - expected_ids.insert(id1); - expected_ids.insert(id2); - std::set<viz::ResourceId> returned_ids; - for (unsigned i = 0; i < returned_to_child.size(); i++) - returned_ids.insert(returned_to_child[i].id); - EXPECT_EQ(expected_ids, returned_ids); - EXPECT_FALSE(returned_to_child[0].lost); - EXPECT_FALSE(returned_to_child[1].lost); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - returned_to_child.clear(); - } - EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2)); - - { - LayerTreeResourceProvider::ScopedWriteLockSoftware lock( - child_resource_provider_.get(), id1); - const SkBitmap sk_bitmap = lock.sk_bitmap(); - EXPECT_EQ(sk_bitmap.width(), size.width()); - EXPECT_EQ(sk_bitmap.height(), size.height()); - EXPECT_EQ(0, memcmp(data1, sk_bitmap.getPixels(), pixel_size)); - } - { - LayerTreeResourceProvider::ScopedWriteLockSoftware lock( - child_resource_provider_.get(), id2); - const SkBitmap sk_bitmap = lock.sk_bitmap(); - EXPECT_EQ(sk_bitmap.width(), size.width()); - EXPECT_EQ(sk_bitmap.height(), size.height()); - EXPECT_EQ(0, memcmp(data2, sk_bitmap.getPixels(), pixel_size)); - } - { - // Transfer resources to the parent again. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(2u, list.size()); - EXPECT_EQ(id1, list[0].id); - EXPECT_EQ(id2, list[1].id); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - resource_provider_->ReceiveFromChild(child_id, list); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id1); - resource_ids_to_receive.insert(id2); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - } - - EXPECT_EQ(0u, returned_to_child.size()); - - EXPECT_EQ(2u, resource_provider_->num_resources()); - resource_provider_->DestroyChild(child_id); - EXPECT_EQ(0u, resource_provider_->num_resources()); - - ASSERT_EQ(2u, returned_to_child.size()); - EXPECT_FALSE(returned_to_child[0].sync_token.HasData()); - EXPECT_FALSE(returned_to_child[1].sync_token.HasData()); - std::set<viz::ResourceId> expected_ids; - expected_ids.insert(id1); - expected_ids.insert(id2); - std::set<viz::ResourceId> returned_ids; - for (unsigned i = 0; i < returned_to_child.size(); i++) - returned_ids.insert(returned_to_child[i].id); - EXPECT_EQ(expected_ids, returned_ids); - EXPECT_FALSE(returned_to_child[0].lost); - EXPECT_FALSE(returned_to_child[1].lost); -} - -TEST_P(ResourceProviderTest, TransferGLToSoftware) { - if (use_gpu()) - return; - - scoped_refptr<viz::TestContextProvider> child_context_provider = - viz::TestContextProvider::Create( - ResourceProviderContext::Create(shared_data_.get())); - child_context_provider->BindToCurrentThread(); - - auto child_resource_provider(std::make_unique<LayerTreeResourceProvider>( - child_context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - viz::ResourceId id1 = child_resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, viz::RGBA_8888, - gfx::ColorSpace()); - uint8_t data1[4] = { 1, 2, 3, 4 }; - child_resource_provider->CopyToResource(id1, data1, size); - - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = - resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - { - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id1); - - std::vector<viz::TransferableResource> list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(1u, list.size()); - EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), - list[0].mailbox_holder.texture_target); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1)); - resource_provider_->ReceiveFromChild(child_id, list); - } - - EXPECT_EQ(0u, resource_provider_->num_resources()); - ASSERT_EQ(1u, returned_to_child.size()); - EXPECT_EQ(returned_to_child[0].id, id1); - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - viz::ResourceId mapped_id1 = resource_map[id1]; - EXPECT_EQ(0u, mapped_id1); - - resource_provider_->DestroyChild(child_id); - EXPECT_EQ(0u, resource_provider_->num_resources()); - - ASSERT_EQ(1u, returned_to_child.size()); - EXPECT_FALSE(returned_to_child[0].lost); -} - -TEST_P(ResourceProviderTest, TransferInvalidSoftware) { - if (use_gpu()) - return; - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - viz::ResourceId id1 = child_resource_provider_->CreateBitmapResource( - size, gfx::ColorSpace(), format); - uint8_t data1[4] = { 1, 2, 3, 4 }; - child_resource_provider_->CopyToResource(id1, data1, size); - - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = - resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - { - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id1); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(1u, list.size()); - // Make invalid. - list[0].mailbox_holder.mailbox.name[1] ^= 0xff; - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - resource_provider_->ReceiveFromChild(child_id, list); - } - - EXPECT_EQ(1u, resource_provider_->num_resources()); - EXPECT_EQ(0u, returned_to_child.size()); - - ResourceProvider::ResourceIdMap resource_map = - resource_provider_->GetChildToParentMap(child_id); - viz::ResourceId mapped_id1 = resource_map[id1]; - EXPECT_NE(0u, mapped_id1); - { - DisplayResourceProvider::ScopedReadLockSoftware lock( - resource_provider_.get(), mapped_id1); - EXPECT_FALSE(lock.valid()); - } - - resource_provider_->DestroyChild(child_id); - EXPECT_EQ(0u, resource_provider_->num_resources()); - - ASSERT_EQ(1u, returned_to_child.size()); - EXPECT_FALSE(returned_to_child[0].lost); -} - -TEST_P(ResourceProviderTest, DeleteExportedResources) { - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - viz::ResourceId id1; - viz::ResourceId id2; - if (use_gpu()) { - id1 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - id2 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - } else { - id1 = child_resource_provider_->CreateBitmapResource( - size, gfx::ColorSpace(), format); - id2 = child_resource_provider_->CreateBitmapResource( - size, gfx::ColorSpace(), format); - } - - uint8_t data1[4] = { 1, 2, 3, 4 }; - child_resource_provider_->CopyToResource(id1, data1, size); - uint8_t data2[4] = {5, 5, 5, 5}; - child_resource_provider_->CopyToResource(id2, data2, size); - - std::vector<viz::ReturnedResource> 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; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(2u, list.size()); - if (use_gpu()) { - EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); - EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); - } - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - resource_provider_->ReceiveFromChild(child_id, list); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id1); - resource_ids_to_receive.insert(id2); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - - std::vector<viz::ReturnedResource> returned = - viz::TransferableResource::ReturnResources(list); - child_resource_provider_->ReceiveReturnsFromParent(returned); - EXPECT_EQ(0u, returned_to_child.size()); - EXPECT_EQ(2u, resource_provider_->num_resources()); - - // Return the resources from the parent, it should be returned at this - // point. - viz::ResourceIdSet no_resources; - resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - EXPECT_EQ(2u, returned_to_child.size()); - EXPECT_EQ(0u, resource_provider_->num_resources()); - } -} - -TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - viz::ResourceId id1; - viz::ResourceId id2; - if (use_gpu()) { - id1 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - id2 = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - } else { - id1 = child_resource_provider_->CreateBitmapResource( - size, gfx::ColorSpace(), format); - id2 = child_resource_provider_->CreateBitmapResource( - size, gfx::ColorSpace(), format); - } - - uint8_t data1[4] = {1, 2, 3, 4}; - child_resource_provider_->CopyToResource(id1, data1, size); - uint8_t data2[4] = {5, 5, 5, 5}; - child_resource_provider_->CopyToResource(id2, data2, size); - - std::vector<viz::ReturnedResource> 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; - resource_ids_to_transfer.push_back(id1); - resource_ids_to_transfer.push_back(id2); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(2u, list.size()); - if (use_gpu()) { - EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); - EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); - } - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - resource_provider_->ReceiveFromChild(child_id, list); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id1); - resource_ids_to_receive.insert(id2); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - - EXPECT_EQ(0u, returned_to_child.size()); - EXPECT_EQ(2u, resource_provider_->num_resources()); - // Destroy the child, the resources should be returned. - resource_provider_->DestroyChild(child_id); - EXPECT_EQ(2u, returned_to_child.size()); - EXPECT_EQ(0u, resource_provider_->num_resources()); - } -} - -TEST_P(ResourceProviderTest, DeleteTransferredResources) { - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - viz::ResourceId id; - if (use_gpu()) { - id = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - } else { - id = child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace(), - format); - } - - uint8_t data[4] = { 1, 2, 3, 4 }; - child_resource_provider_->CopyToResource(id, data, size); - - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = - resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - { - // Transfer some resource to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id); - - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(1u, list.size()); - if (use_gpu()) - EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id)); - resource_provider_->ReceiveFromChild(child_id, list); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - } - - // Delete textures in the child, while they are transfered. - child_resource_provider_->DeleteResource(id); - EXPECT_EQ(1u, child_resource_provider_->num_resources()); - { - EXPECT_EQ(0u, returned_to_child.size()); - - // Transfer resources back from the parent to the child. Set no resources as - // being in use. - viz::ResourceIdSet no_resources; - resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - - ASSERT_EQ(1u, returned_to_child.size()); - if (use_gpu()) - EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - EXPECT_EQ(0u, child_resource_provider_->num_resources()); - } -} - -class ResourceProviderTestTextureFilters : public ResourceProviderTest { - public: - static void RunTest(GLenum child_filter, GLenum parent_filter) { - auto child_context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* child_context = child_context_owned.get(); - - auto child_context_provider = - viz::TestContextProvider::Create(std::move(child_context_owned)); - child_context_provider->BindToCurrentThread(); - auto shared_bitmap_manager = - std::make_unique<viz::TestSharedBitmapManager>(); - - viz::ResourceSettings resource_settings = CreateResourceSettings(); - auto child_resource_provider(std::make_unique<LayerTreeResourceProvider>( - child_context_provider.get(), shared_bitmap_manager.get(), nullptr, - kDelegatedSyncPointsRequired, resource_settings)); - - auto parent_context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* parent_context = parent_context_owned.get(); - - auto parent_context_provider = - viz::TestContextProvider::Create(std::move(parent_context_owned)); - parent_context_provider->BindToCurrentThread(); - - auto parent_resource_provider(std::make_unique<DisplayResourceProvider>( - parent_context_provider.get(), shared_bitmap_manager.get())); - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - int child_texture_id = 1; - int parent_texture_id = 2; - - size_t pixel_size = TextureSizeBytes(size, format); - ASSERT_EQ(4U, pixel_size); - - viz::ResourceId id = child_resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - - // The new texture is created with GL_LINEAR. - EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)) - .Times(2); // Once to create and once to allocate. - EXPECT_CALL(*child_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - EXPECT_CALL(*child_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - EXPECT_CALL( - *child_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - EXPECT_CALL( - *child_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - child_resource_provider->AllocateForTesting(id); - Mock::VerifyAndClearExpectations(child_context); - - uint8_t data[4] = { 1, 2, 3, 4 }; - - EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)); - child_resource_provider->CopyToResource(id, data, size); - Mock::VerifyAndClearExpectations(child_context); - - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = parent_resource_provider->CreateChild( - GetReturnCallback(&returned_to_child)); - - // Transfer some resource to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id); - std::vector<viz::TransferableResource> list; - - EXPECT_CALL(*child_context, produceTextureDirectCHROMIUM(_, _)); - - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); - Mock::VerifyAndClearExpectations(child_context); - - ASSERT_EQ(1u, list.size()); - EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter); - - EXPECT_CALL(*parent_context, createAndConsumeTextureCHROMIUM(_)) - .WillOnce(Return(parent_texture_id)); - - parent_resource_provider->ReceiveFromChild(child_id, list); - ResourceProvider::ResourceIdMap resource_map = - parent_resource_provider->GetChildToParentMap(child_id); - viz::ResourceId mapped_id = resource_map[id]; - EXPECT_NE(0u, mapped_id); - - { - parent_resource_provider->WaitSyncToken(mapped_id); - DisplayResourceProvider::ScopedReadLockGL lock( - parent_resource_provider.get(), mapped_id); - } - Mock::VerifyAndClearExpectations(parent_context); - - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id); - parent_resource_provider->DeclareUsedResourcesFromChild( - child_id, resource_ids_to_receive); - Mock::VerifyAndClearExpectations(parent_context); - - // The texture is set to |parent_filter| in the parent. - EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id)); - EXPECT_CALL( - *parent_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter)); - EXPECT_CALL( - *parent_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter)); - SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter); - Mock::VerifyAndClearExpectations(parent_context); - - // The texture should be reset to |child_filter| in the parent when it is - // returned, since that is how it was received. - EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id)); - EXPECT_CALL(*parent_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - EXPECT_CALL(*parent_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - - { - EXPECT_EQ(0u, returned_to_child.size()); - - // Transfer resources back from the parent to the child. Set no resources - // as being in use. - viz::ResourceIdSet no_resources; - parent_resource_provider->DeclareUsedResourcesFromChild(child_id, - no_resources); - Mock::VerifyAndClearExpectations(parent_context); - - ASSERT_EQ(1u, returned_to_child.size()); - child_resource_provider->ReceiveReturnsFromParent(returned_to_child); - } - } -}; - -TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) { - if (!use_gpu()) - return; - ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST); -} - -TEST_P(ResourceProviderTest, TransferMailboxResources) { - // Other mailbox transfers tested elsewhere. - if (!use_gpu()) - return; - unsigned texture = context()->createTexture(); - context()->bindTexture(GL_TEXTURE_2D, texture); - uint8_t data[4] = { 1, 2, 3, 4 }; - context()->texImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data); - gpu::Mailbox mailbox; - context()->genMailboxCHROMIUM(mailbox.name); - context()->produceTextureDirectCHROMIUM(texture, mailbox.name); - gpu::SyncToken sync_token; - context()->genSyncToken(sync_token.GetData()); - EXPECT_TRUE(sync_token.HasData()); - - // All the logic below assumes that the sync token releases are all positive. - EXPECT_LT(0u, sync_token.release_count()); - - gpu::SyncToken release_sync_token; - bool lost_resource = false; - viz::ReleaseCallback callback = - base::Bind(ReleaseCallback, &release_sync_token, &lost_resource); - viz::ResourceId resource = child_resource_provider_->ImportResource( - viz::TransferableResource::MakeGL(mailbox, GL_LINEAR, GL_TEXTURE_2D, - sync_token), - viz::SingleReleaseCallback::Create(std::move(callback))); - EXPECT_EQ(1u, context()->NumTextures()); - EXPECT_FALSE(release_sync_token.HasData()); - { - // Transfer the resource, expect the sync points to be consistent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(resource); - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(1u, list.size()); - EXPECT_LE(sync_token.release_count(), - list[0].mailbox_holder.sync_token.release_count()); - EXPECT_EQ(0, - memcmp(mailbox.name, - list[0].mailbox_holder.mailbox.name, - sizeof(mailbox.name))); - EXPECT_FALSE(release_sync_token.HasData()); - - context()->waitSyncToken(list[0].mailbox_holder.sync_token.GetConstData()); - unsigned other_texture = - context()->createAndConsumeTextureCHROMIUM(mailbox.name); - uint8_t test_data[4] = { 0 }; - context()->GetPixels(gfx::Size(1, 1), viz::RGBA_8888, test_data); - EXPECT_EQ(0, memcmp(data, test_data, sizeof(data))); - - context()->produceTextureDirectCHROMIUM(other_texture, mailbox.name); - context()->deleteTexture(other_texture); - context()->genSyncToken(list[0].mailbox_holder.sync_token.GetData()); - EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); - - // Receive the resource, then delete it, expect the sync points to be - // consistent. - std::vector<viz::ReturnedResource> returned = - viz::TransferableResource::ReturnResources(list); - child_resource_provider_->ReceiveReturnsFromParent(returned); - EXPECT_EQ(1u, context()->NumTextures()); - EXPECT_FALSE(release_sync_token.HasData()); - - child_resource_provider_->RemoveImportedResource(resource); - EXPECT_LE(list[0].mailbox_holder.sync_token.release_count(), - release_sync_token.release_count()); - EXPECT_FALSE(lost_resource); - } - - // We're going to do the same thing as above, but testing the case where we - // delete the resource before we receive it back. - sync_token = release_sync_token; - EXPECT_LT(0u, sync_token.release_count()); - release_sync_token.Clear(); - callback = base::Bind(ReleaseCallback, &release_sync_token, &lost_resource); - resource = child_resource_provider_->ImportResource( - viz::TransferableResource::MakeGL(mailbox, GL_LINEAR, GL_TEXTURE_2D, - sync_token), - viz::SingleReleaseCallback::Create(std::move(callback))); - EXPECT_EQ(1u, context()->NumTextures()); - EXPECT_FALSE(release_sync_token.HasData()); - { - // Transfer the resource, expect the sync points to be consistent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(resource); - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - ASSERT_EQ(1u, list.size()); - EXPECT_LE(sync_token.release_count(), - list[0].mailbox_holder.sync_token.release_count()); - EXPECT_EQ(0, - memcmp(mailbox.name, - list[0].mailbox_holder.mailbox.name, - sizeof(mailbox.name))); - EXPECT_FALSE(release_sync_token.HasData()); - - context()->waitSyncToken(list[0].mailbox_holder.sync_token.GetConstData()); - unsigned other_texture = - context()->createAndConsumeTextureCHROMIUM(mailbox.name); - uint8_t test_data[4] = { 0 }; - context()->GetPixels(gfx::Size(1, 1), viz::RGBA_8888, test_data); - EXPECT_EQ(0, memcmp(data, test_data, sizeof(data))); - - context()->produceTextureDirectCHROMIUM(other_texture, mailbox.name); - context()->deleteTexture(other_texture); - context()->genSyncToken(list[0].mailbox_holder.sync_token.GetData()); - EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); - - // Delete the resource, which shouldn't do anything. - child_resource_provider_->RemoveImportedResource(resource); - EXPECT_EQ(1u, context()->NumTextures()); - EXPECT_FALSE(release_sync_token.HasData()); - - // Then receive the resource which should release the mailbox, expect the - // sync points to be consistent. - std::vector<viz::ReturnedResource> returned = - viz::TransferableResource::ReturnResources(list); - child_resource_provider_->ReceiveReturnsFromParent(returned); - EXPECT_LE(list[0].mailbox_holder.sync_token.release_count(), - release_sync_token.release_count()); - EXPECT_FALSE(lost_resource); - } - - context()->waitSyncToken(release_sync_token.GetConstData()); - texture = context()->createAndConsumeTextureCHROMIUM(mailbox.name); - context()->deleteTexture(texture); -} - -TEST_P(ResourceProviderTest, LostResourceInParent) { - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - viz::ResourceId id; - if (use_gpu()) { - id = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - } else { - id = child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace(), - format); - } - - child_resource_provider_->AllocateForTesting(id); - // Expect a GL resource to be lost. - bool should_lose_resource = use_gpu(); - - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = - resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - { - // Transfer the resource to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id); - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - EXPECT_EQ(1u, list.size()); - - resource_provider_->ReceiveFromChild(child_id, list); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(id); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - } - - // Lose the output surface in the parent. - resource_provider_->DidLoseContextProvider(); - - { - EXPECT_EQ(0u, returned_to_child.size()); - - // Transfer resources back from the parent to the child. Set no resources as - // being in use. - viz::ResourceIdSet no_resources; - resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - - // Expect a GL resource to be lost. - ASSERT_EQ(1u, returned_to_child.size()); - EXPECT_EQ(should_lose_resource, returned_to_child[0].lost); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - returned_to_child.clear(); - } - - // A GL resource should be lost. - EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(id)); - - // Lost resources stay in use in the parent forever. - EXPECT_EQ(should_lose_resource, - child_resource_provider_->InUseByConsumer(id)); -} - - -TEST_P(ResourceProviderTest, LostMailboxInParent) { - gpu::SyncToken release_sync_token; - bool lost_resource = false; - bool release_called = false; - gpu::SyncToken sync_token; - viz::ResourceId resource = - CreateChildMailbox(&release_sync_token, &lost_resource, &release_called, - &sync_token, viz::RGBA_8888); - - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = - resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); - { - // Transfer the resource to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(resource); - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - EXPECT_EQ(1u, list.size()); - - resource_provider_->ReceiveFromChild(child_id, list); - viz::ResourceIdSet resource_ids_to_receive; - resource_ids_to_receive.insert(resource); - resource_provider_->DeclareUsedResourcesFromChild(child_id, - resource_ids_to_receive); - } - - // Lose the output surface in the parent. - resource_provider_->DidLoseContextProvider(); - - { - EXPECT_EQ(0u, returned_to_child.size()); - - // Transfer resources back from the parent to the child. Set no resources as - // being in use. - viz::ResourceIdSet no_resources; - resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - - ASSERT_EQ(1u, returned_to_child.size()); - // Losing an output surface only loses hardware resources. - EXPECT_EQ(returned_to_child[0].lost, use_gpu()); - child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); - returned_to_child.clear(); - } - - // Delete the resource in the child. Expect the resource to be lost if it's - // a GL texture. - child_resource_provider_->RemoveImportedResource(resource); - EXPECT_EQ(lost_resource, use_gpu()); -} - -TEST_P(ResourceProviderTest, Shutdown) { - enum Cases { - // If not exported, the resource is returned not lost, and doesn't need a - // sync token. - kShutdownWithoutExport = 0, - // If exported and not returned, the resource is lost, and doesn't need/have - // a sync token to give. - kShutdownAfterExport, - // If exported and returned, the resource is not lost. - kShutdownAfterExportAndReturn, - // If returned as lost, then the resource must report lost on shutdown too. - kShutdownAfterExportAndReturnWithLostResource, - // If the context is lost, it doesn't affect imported resources as they are - // just weak references. - kShutdownAfterContextLossWithoutExport, - // If the context is lost, it doesn't affect imported resources as they are - // just weak references. - kShutdownAfterContextLossAfterExportAndReturn, - kNumCases, - }; - - for (int i = 0; i < kNumCases; ++i) { - auto c = static_cast<Cases>(i); - SCOPED_TRACE(c); - - gpu::SyncToken release_sync_token; - bool lost_resource = false; - bool release_called = false; - gpu::SyncToken sync_token; - viz::ResourceId id = - CreateChildMailbox(&release_sync_token, &lost_resource, &release_called, - &sync_token, viz::RGBA_8888); - - if (i == kShutdownAfterExport || i == kShutdownAfterExportAndReturn || - i == kShutdownAfterExportAndReturnWithLostResource || - i == kShutdownAfterContextLossAfterExportAndReturn) { - std::vector<viz::TransferableResource> send_list; - child_resource_provider_->PrepareSendToParent({id}, &send_list); - } - - if (i == kShutdownAfterExportAndReturn || - i == kShutdownAfterExportAndReturnWithLostResource || - i == kShutdownAfterContextLossAfterExportAndReturn) { - viz::ReturnedResource r; - r.id = id; - r.sync_token = sync_token; - r.count = 1; - r.lost = (i == kShutdownAfterExportAndReturnWithLostResource); - child_resource_provider_->ReceiveReturnsFromParent({r}); - } - - EXPECT_FALSE(release_sync_token.HasData()); - EXPECT_FALSE(lost_resource); - - // Shutdown! - child_resource_provider_ = nullptr; - - // If the resource was exported and returned, then it should come with a - // sync token. - if (use_gpu()) { - if (i == kShutdownAfterExportAndReturn || - i == kShutdownAfterExportAndReturnWithLostResource || - i == kShutdownAfterContextLossAfterExportAndReturn) { - EXPECT_LE(sync_token.release_count(), - release_sync_token.release_count()); - } - } - - // We always get the ReleaseCallback called. - EXPECT_TRUE(release_called); - bool expect_lost = i == kShutdownAfterExport || - i == kShutdownAfterExportAndReturnWithLostResource; - EXPECT_EQ(expect_lost, lost_resource); - - // Recreate it for the next case. - MakeChildResourceProvider(); - } -} - -TEST_P(ResourceProviderTest, ScopedSampler) { - // Sampling is only supported for GL textures. - if (!use_gpu()) - return; - - auto context_owned = std::make_unique<TextureStateTrackingContext>(); - TextureStateTrackingContext* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - viz::ResourceSettings resource_settings = CreateResourceSettings(); - auto resource_provider(std::make_unique<DisplayResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get())); - - auto child_context_owned = std::make_unique<TextureStateTrackingContext>(); - TextureStateTrackingContext* child_context = child_context_owned.get(); - - auto child_context_provider = - viz::TestContextProvider::Create(std::move(child_context_owned)); - child_context_provider->BindToCurrentThread(); - - auto child_resource_provider(std::make_unique<LayerTreeResourceProvider>( - child_context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - resource_settings)); - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - int texture_id = 1; - - viz::ResourceId id = child_resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - - // Check that the texture gets created with the right sampler settings. - EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, texture_id)) - .Times(2); // Once to create and once to allocate. - EXPECT_CALL(*child_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - EXPECT_CALL(*child_context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - EXPECT_CALL(*child_context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE)); - EXPECT_CALL(*child_context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE)); - - child_resource_provider->AllocateForTesting(id); - Mock::VerifyAndClearExpectations(child_context); - - // Return the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - SendResourceAndGetChildToParentMap({id}, resource_provider.get(), - child_resource_provider.get()); - viz::ResourceId mapped_id = resource_map[id]; - resource_provider->WaitSyncToken(mapped_id); - int parent_texture_id = 3; - // Creating a sampler with the default filter should not change any texture - // parameters. - { - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)) - .WillOnce(Return(parent_texture_id)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, parent_texture_id)); - DisplayResourceProvider::ScopedSamplerGL sampler( - resource_provider.get(), mapped_id, GL_TEXTURE_2D, GL_LINEAR); - Mock::VerifyAndClearExpectations(context); - } - - // Using a different filter should be reflected in the texture parameters. - { - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, parent_texture_id)); - EXPECT_CALL( - *context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - EXPECT_CALL( - *context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - DisplayResourceProvider::ScopedSamplerGL sampler( - resource_provider.get(), mapped_id, GL_TEXTURE_2D, GL_NEAREST); - Mock::VerifyAndClearExpectations(context); - } - - // Test resetting to the default filter. - { - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, parent_texture_id)); - EXPECT_CALL(*context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - EXPECT_CALL(*context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - DisplayResourceProvider::ScopedSamplerGL sampler( - resource_provider.get(), mapped_id, GL_TEXTURE_2D, GL_LINEAR); - Mock::VerifyAndClearExpectations(context); - } -} - -TEST_P(ResourceProviderTest, ManagedResource) { - // Sampling is only supported for GL textures. - if (!use_gpu()) - return; - - auto context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - int texture_id = 1; - - // Check that the texture gets created with the right sampler settings. - viz::ResourceId id = resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); - EXPECT_CALL(*context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - EXPECT_CALL(*context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - EXPECT_CALL( - *context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - EXPECT_CALL( - *context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - resource_provider->CreateForTesting(id); - EXPECT_NE(0u, id); - - Mock::VerifyAndClearExpectations(context); -} - -TEST_P(ResourceProviderTest, TextureWrapMode) { - // Sampling is only supported for GL textures. - if (!use_gpu()) - return; - - auto context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - for (int texture_id = 1; texture_id <= 2; ++texture_id) { - // Check that the texture gets created with the right sampler settings. - viz::ResourceId id = resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); - EXPECT_CALL(*context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - EXPECT_CALL(*context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE)); - EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE)); - resource_provider->CreateForTesting(id); - EXPECT_NE(0u, id); - - Mock::VerifyAndClearExpectations(context); - } -} - -TEST_P(ResourceProviderTest, TextureHint) { - // Sampling is only supported for GL textures. - if (!use_gpu()) - return; - - auto context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* context = context_owned.get(); - context->set_support_texture_storage(true); - context->set_support_texture_usage(true); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - const viz::ResourceTextureHint hints[] = { - viz::ResourceTextureHint::kDefault, - viz::ResourceTextureHint::kFramebuffer, - }; - for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) { - // Check that the texture gets created with the right sampler settings. - viz::ResourceId id = resource_provider->CreateGpuTextureResource( - size, hints[texture_id - 1], format, gfx::ColorSpace()); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); - EXPECT_CALL(*context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - EXPECT_CALL(*context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - EXPECT_CALL( - *context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - EXPECT_CALL( - *context, - texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - // Check that GL_TEXTURE_USAGE_ANGLE is set iff the kFramebuffer hint is - // used. - bool is_framebuffer_hint = - hints[texture_id - 1] & viz::ResourceTextureHint::kFramebuffer; - EXPECT_CALL(*context, - texParameteri(GL_TEXTURE_2D, - GL_TEXTURE_USAGE_ANGLE, - GL_FRAMEBUFFER_ATTACHMENT_ANGLE)) - .Times(is_framebuffer_hint ? 1 : 0); - resource_provider->CreateForTesting(id); - EXPECT_NE(0u, id); - - Mock::VerifyAndClearExpectations(context); - } -} - -TEST_P(ResourceProviderTest, ImportedResource_SharedMemory) { - if (use_gpu()) - return; - - gfx::Size size(64, 64); - viz::ResourceFormat format = viz::RGBA_8888; - const uint32_t kBadBeef = 0xbadbeef; - std::unique_ptr<viz::SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap( - shared_bitmap_manager_.get(), size, format, kBadBeef)); - - auto resource_provider(std::make_unique<DisplayResourceProvider>( - nullptr, shared_bitmap_manager_.get())); - - auto child_resource_provider(std::make_unique<LayerTreeResourceProvider>( - nullptr, shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), - kDelegatedSyncPointsRequired, CreateResourceSettings())); - - gpu::SyncToken release_sync_token; - bool lost_resource = false; - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create( - base::Bind(&ReleaseCallback, &release_sync_token, &lost_resource)); - auto resource = viz::TransferableResource::MakeSoftware( - shared_bitmap->id(), shared_bitmap->sequence_number(), size, format); - - viz::ResourceId resource_id = - child_resource_provider->ImportResource(resource, std::move(callback)); - EXPECT_NE(0u, resource_id); - - // Transfer resources to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(resource_id); - - std::vector<viz::TransferableResource> send_to_parent; - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = resource_provider->CreateChild( - base::Bind(&CollectResources, &returned_to_child)); - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &send_to_parent); - resource_provider->ReceiveFromChild(child_id, send_to_parent); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - resource_provider->GetChildToParentMap(child_id); - viz::ResourceId mapped_resource_id = resource_map[resource_id]; - - { - DisplayResourceProvider::ScopedReadLockSoftware lock( - resource_provider.get(), mapped_resource_id); - const SkBitmap* sk_bitmap = lock.sk_bitmap(); - EXPECT_EQ(sk_bitmap->width(), size.width()); - EXPECT_EQ(sk_bitmap->height(), size.height()); - EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef); - } - - EXPECT_EQ(0u, returned_to_child.size()); - // Transfer resources back from the parent to the child. Set no resources as - // being in use. - resource_provider->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - EXPECT_EQ(1u, returned_to_child.size()); - child_resource_provider->ReceiveReturnsFromParent(returned_to_child); - - child_resource_provider->RemoveImportedResource(resource_id); - EXPECT_FALSE(release_sync_token.HasData()); - EXPECT_FALSE(lost_resource); -} - -class ResourceProviderTestImportedResourceGLFilters - : public ResourceProviderTest { - public: - static void RunTest( - viz::TestSharedBitmapManager* shared_bitmap_manager, - viz::TestGpuMemoryBufferManager* gpu_memory_buffer_manager, - bool mailbox_nearest_neighbor, - GLenum sampler_filter) { - auto context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider(std::make_unique<DisplayResourceProvider>( - context_provider.get(), shared_bitmap_manager)); - - auto child_context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* child_context = child_context_owned.get(); - auto child_context_provider = - viz::TestContextProvider::Create(std::move(child_context_owned)); - child_context_provider->BindToCurrentThread(); - - auto child_resource_provider(std::make_unique<LayerTreeResourceProvider>( - child_context_provider.get(), shared_bitmap_manager, - gpu_memory_buffer_manager, kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - unsigned texture_id = 1; - gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x12), - 0x34); - const GLuint64 current_fence_sync = child_context->GetNextFenceSync(); - - EXPECT_CALL(*child_context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*child_context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*child_context, produceTextureDirectCHROMIUM(_, _)).Times(0); - EXPECT_CALL(*child_context, createAndConsumeTextureCHROMIUM(_)).Times(0); - - gpu::Mailbox gpu_mailbox; - memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); - gpu::SyncToken release_sync_token; - bool lost_resource = false; - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create( - base::Bind(&ReleaseCallback, &release_sync_token, &lost_resource)); - - GLuint filter = mailbox_nearest_neighbor ? GL_NEAREST : GL_LINEAR; - auto resource = viz::TransferableResource::MakeGL( - gpu_mailbox, filter, GL_TEXTURE_2D, sync_token); - - viz::ResourceId resource_id = - child_resource_provider->ImportResource(resource, std::move(callback)); - EXPECT_NE(0u, resource_id); - EXPECT_EQ(current_fence_sync, child_context->GetNextFenceSync()); - - Mock::VerifyAndClearExpectations(child_context); - - // Transfer resources to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(resource_id); - - std::vector<viz::TransferableResource> send_to_parent; - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = resource_provider->CreateChild( - base::Bind(&CollectResources, &returned_to_child)); - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &send_to_parent); - resource_provider->ReceiveFromChild(child_id, send_to_parent); - - // In DisplayResourceProvider's namespace, use the mapped resource id. - ResourceProvider::ResourceIdMap resource_map = - resource_provider->GetChildToParentMap(child_id); - viz::ResourceId mapped_resource_id = resource_map[resource_id]; - { - // The verified flush flag will be set by - // LayerTreeResourceProvider::PrepareSendToParent. Before checking if - // the gpu::SyncToken matches, set this flag first. - sync_token.SetVerifyFlush(); - - // Mailbox sync point WaitSyncToken before using the texture. - EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); - resource_provider->WaitSyncToken(mapped_resource_id); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)) - .WillOnce(Return(texture_id)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); - - EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0); - - // The sampler will reset these if |mailbox_nearest_neighbor| does not - // match |sampler_filter|. - if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) { - EXPECT_CALL(*context, texParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter)); - EXPECT_CALL(*context, texParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter)); - } - - DisplayResourceProvider::ScopedSamplerGL lock( - resource_provider.get(), mapped_resource_id, sampler_filter); - Mock::VerifyAndClearExpectations(context); - EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); - - // When done with it, a sync point should be inserted, but no produce is - // necessary. - EXPECT_CALL(*child_context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*child_context, produceTextureDirectCHROMIUM(_, _)).Times(0); - - EXPECT_CALL(*child_context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*child_context, createAndConsumeTextureCHROMIUM(_)).Times(0); - } - - EXPECT_EQ(0u, returned_to_child.size()); - // Transfer resources back from the parent to the child. Set no resources as - // being in use. - resource_provider->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - EXPECT_EQ(1u, returned_to_child.size()); - child_resource_provider->ReceiveReturnsFromParent(returned_to_child); - - child_resource_provider->RemoveImportedResource(resource_id); - EXPECT_TRUE(release_sync_token.HasData()); - EXPECT_FALSE(lost_resource); - } -}; - -TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_LinearToLinear) { - // Mailboxing is only supported for GL textures. - if (!use_gpu()) - return; - - ResourceProviderTestImportedResourceGLFilters::RunTest( - shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), false, - GL_LINEAR); -} - -TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_NearestToNearest) { - // Mailboxing is only supported for GL textures. - if (!use_gpu()) - return; - - ResourceProviderTestImportedResourceGLFilters::RunTest( - shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), true, - GL_NEAREST); -} - -TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_NearestToLinear) { - // Mailboxing is only supported for GL textures. - if (!use_gpu()) - return; - - ResourceProviderTestImportedResourceGLFilters::RunTest( - shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), true, - GL_LINEAR); -} - -TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_LinearToNearest) { - // Mailboxing is only supported for GL textures. - if (!use_gpu()) - return; - - ResourceProviderTestImportedResourceGLFilters::RunTest( - shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), false, - GL_NEAREST); -} - -TEST_P(ResourceProviderTest, ImportedResource_GLTextureExternalOES) { - // Mailboxing is only supported for GL textures. - if (!use_gpu()) - return; - - auto context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider(std::make_unique<DisplayResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get())); - - auto child_context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* child_context = child_context_owned.get(); - auto child_context_provider = - viz::TestContextProvider::Create(std::move(child_context_owned)); - child_context_provider->BindToCurrentThread(); - - auto child_resource_provider(std::make_unique<LayerTreeResourceProvider>( - child_context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x12), 0x34); - const GLuint64 current_fence_sync = child_context->GetNextFenceSync(); - - EXPECT_CALL(*child_context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*child_context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*child_context, produceTextureDirectCHROMIUM(_, _)).Times(0); - EXPECT_CALL(*child_context, createAndConsumeTextureCHROMIUM(_)).Times(0); - - gpu::Mailbox gpu_mailbox; - memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::DoNothing()); - - auto resource = viz::TransferableResource::MakeGL( - gpu_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, sync_token); - - viz::ResourceId resource_id = - child_resource_provider->ImportResource(resource, std::move(callback)); - EXPECT_NE(0u, resource_id); - EXPECT_EQ(current_fence_sync, child_context->GetNextFenceSync()); - - Mock::VerifyAndClearExpectations(child_context); - - // Transfer resources to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(resource_id); - - std::vector<viz::TransferableResource> send_to_parent; - std::vector<viz::ReturnedResource> returned_to_child; - int child_id = resource_provider->CreateChild( - base::Bind(&CollectResources, &returned_to_child)); - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &send_to_parent); - resource_provider->ReceiveFromChild(child_id, send_to_parent); - - // Before create DrawQuad in DisplayResourceProvider's namespace, get the - // mapped resource id first. - ResourceProvider::ResourceIdMap resource_map = - resource_provider->GetChildToParentMap(child_id); - viz::ResourceId mapped_resource_id = resource_map[resource_id]; - { - // The verified flush flag will be set by - // LayerTreeResourceProvider::PrepareSendToParent. Before checking if - // the gpu::SyncToken matches, set this flag first. - sync_token.SetVerifyFlush(); - - // Mailbox sync point WaitSyncToken before using the texture. - EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); - resource_provider->WaitSyncToken(mapped_resource_id); - Mock::VerifyAndClearExpectations(context); - - unsigned texture_id = 1; - - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)) - .WillOnce(Return(texture_id)); - - EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0); - - DisplayResourceProvider::ScopedReadLockGL lock(resource_provider.get(), - mapped_resource_id); - Mock::VerifyAndClearExpectations(context); - - // When done with it, a sync point should be inserted, but no produce is - // necessary. - EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0); - - EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)).Times(0); - Mock::VerifyAndClearExpectations(context); - } - EXPECT_EQ(0u, returned_to_child.size()); - // Transfer resources back from the parent to the child. Set no resources as - // being in use. - resource_provider->DeclareUsedResourcesFromChild(child_id, - viz::ResourceIdSet()); - EXPECT_EQ(1u, returned_to_child.size()); - child_resource_provider->ReceiveReturnsFromParent(returned_to_child); - - child_resource_provider->RemoveImportedResource(resource_id); -} - -TEST_P(ResourceProviderTest, WaitSyncTokenIfNeeded_ResourceFromChild) { - // Mailboxing is only supported for GL textures. - if (!use_gpu()) - return; - - auto context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider = std::make_unique<DisplayResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get()); - - gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x12), 0x34); - const GLuint64 current_fence_sync = context->GetNextFenceSync(); - - EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0); - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)).Times(0); - - // Receive a resource from the child. - std::vector<viz::ReturnedResource> returned; - ReturnCallback return_callback = base::Bind( - [](std::vector<viz::ReturnedResource>* out, - const std::vector<viz::ReturnedResource>& in) { - *out = std::move(in); - }, - &returned); - int child = resource_provider->CreateChild(return_callback); - - // Send a bunch of resources, to make sure things work when there's more than - // one resource, and to make vectors reallocate and such. - for (int i = 0; i < 100; ++i) { - gpu::Mailbox gpu_mailbox; - memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); - auto resource = viz::TransferableResource::MakeGL( - gpu_mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token); - resource.id = i; - resource_provider->ReceiveFromChild(child, {resource}); - auto& map = resource_provider->GetChildToParentMap(child); - EXPECT_EQ(i + 1u, map.size()); - } - - EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); - resource_provider.reset(); - // Returned resources don't have InsertFenceSyncCHROMIUM() called. - EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); - - // The returned resource has a verified sync token. - ASSERT_EQ(returned.size(), 100u); - for (viz::ReturnedResource& r : returned) - EXPECT_TRUE(r.sync_token.verified_flush()); -} - -TEST_P(ResourceProviderTest, WaitSyncTokenIfNeeded_WithSyncToken) { - // Mailboxing is only supported for GL textures. - if (!use_gpu()) - return; - - auto context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider = std::make_unique<DisplayResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get()); - - gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, - gpu::CommandBufferId::FromUnsafeValue(0x12), 0x34); - const GLuint64 current_fence_sync = context->GetNextFenceSync(); - - EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0); - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)).Times(0); - - viz::ResourceId id = MakeGpuResourceAndSendToDisplay( - 'a', GL_LINEAR, GL_TEXTURE_2D, sync_token, resource_provider.get()); - EXPECT_NE(0u, id); - EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); - - Mock::VerifyAndClearExpectations(context); - - { - // First call to WaitSyncToken should call waitSyncToken. - EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); - resource_provider->WaitSyncToken(id); - Mock::VerifyAndClearExpectations(context); - - // Subsequent calls to WaitSyncToken shouldn't call waitSyncToken. - EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - resource_provider->WaitSyncToken(id); - Mock::VerifyAndClearExpectations(context); - } -} - -TEST_P(ResourceProviderTest, - ImportedResource_WaitSyncTokenIfNeeded_NoSyncToken) { - // Mailboxing is only supported for GL textures. - if (!use_gpu()) - return; - - auto context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider = std::make_unique<DisplayResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get()); - - gpu::SyncToken sync_token; - const GLuint64 current_fence_sync = context->GetNextFenceSync(); - - EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0); - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)).Times(0); - - viz::ResourceId id = MakeGpuResourceAndSendToDisplay( - 'h', GL_LINEAR, GL_TEXTURE_2D, sync_token, resource_provider.get()); - - EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); - EXPECT_NE(0u, id); - - Mock::VerifyAndClearExpectations(context); - - { - // WaitSyncToken with empty sync_token shouldn't call waitSyncToken. - EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - resource_provider->WaitSyncToken(id); - Mock::VerifyAndClearExpectations(context); - } -} - -TEST_P(ResourceProviderTest, ImportedResource_PrepareSendToParent_NoSyncToken) { - // Mailboxing is only supported for GL textures. - if (!use_gpu()) - return; - - auto context_owned(std::make_unique<TextureStateTrackingContext>()); - TextureStateTrackingContext* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - EXPECT_CALL(*context, bindTexture(_, _)).Times(0); - EXPECT_CALL(*context, waitSyncToken(_)).Times(0); - EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0); - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)).Times(0); - - auto resource = viz::TransferableResource::MakeGL( - gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken()); - - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::DoNothing()); - - viz::ResourceId id = - resource_provider->ImportResource(resource, std::move(callback)); - EXPECT_NE(0u, id); - Mock::VerifyAndClearExpectations(context); - - ResourceProvider::ResourceIdArray resource_ids_to_transfer{id}; - std::vector<viz::TransferableResource> list; - resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list); - ASSERT_EQ(1u, list.size()); - EXPECT_FALSE(list[0].mailbox_holder.sync_token.HasData()); - EXPECT_TRUE(list[0].mailbox_holder.sync_token.verified_flush()); - Mock::VerifyAndClearExpectations(context); -} - -class AllocationTrackingContext3D : public TextureStateTrackingContext { - public: - MOCK_METHOD0(NextTextureId, GLuint()); - MOCK_METHOD1(RetireTextureId, void(GLuint id)); - MOCK_METHOD5(texStorage2DImageCHROMIUM, - void(GLenum target, - GLenum internalformat, - GLenum bufferusage, - GLsizei width, - GLsizei height)); - MOCK_METHOD5(texStorage2DEXT, - void(GLenum target, - GLsizei levels, - GLenum internalformat, - GLsizei width, - GLsizei height)); - MOCK_METHOD9(texImage2D, - void(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void* pixels)); - MOCK_METHOD9(texSubImage2D, - void(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void* pixels)); - MOCK_METHOD9(asyncTexImage2DCHROMIUM, - void(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const void* pixels)); - MOCK_METHOD9(asyncTexSubImage2DCHROMIUM, - void(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const void* pixels)); - MOCK_METHOD8(compressedTexImage2D, - void(GLenum target, - GLint level, - GLenum internalformat, - GLsizei width, - GLsizei height, - GLint border, - GLsizei image_size, - const void* data)); - MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum)); - MOCK_METHOD4(createImageCHROMIUM, - GLuint(ClientBuffer, GLsizei, GLsizei, GLenum)); - MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint)); - MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint)); - MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint)); - MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param)); -}; - -TEST_P(ResourceProviderTest, TextureAllocation) { - if (!use_gpu()) - return; - - std::unique_ptr<AllocationTrackingContext3D> context_owned( - new StrictMock<AllocationTrackingContext3D>); - AllocationTrackingContext3D* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - gfx::Size size(2, 2); - viz::ResourceFormat format = viz::RGBA_8888; - viz::ResourceId id = 0; - uint8_t pixels[16] = { 0 }; - int texture_id = 123; - - EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber()); - // Lazy allocation. Don't allocate when creating the resource. - id = resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1); - resource_provider->CreateForTesting(id); - - EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); - resource_provider->DeleteResource(id); - - Mock::VerifyAndClearExpectations(context); - EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber()); - - // Do allocate when we set the pixels. - id = resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3); - EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, _, _, 2, 2, _, _, _, _)) - .Times(1); - EXPECT_CALL(*context, texSubImage2D(GL_TEXTURE_2D, _, _, _, 2, 2, _, _, _)) - .Times(1); - resource_provider->CopyToResource(id, pixels, size); - - EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); - resource_provider->DeleteResource(id); - - Mock::VerifyAndClearExpectations(context); -} - -TEST_P(ResourceProviderTest, TextureStorageAllocation) { - if (!use_gpu()) - return; - - auto context_owned = - std::make_unique<StrictMock<AllocationTrackingContext3D>>(); - auto* context = context_owned.get(); - context->set_support_texture_storage(true); - context->set_support_texture_usage(true); - - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - auto child_resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - viz::ResourceId id = child_resource_provider->CreateGpuTextureResource( - gfx::Size(2, 2), viz::ResourceTextureHint::kDefault, viz::RGBA_8888, - gfx::ColorSpace()); - - const GLuint kTextureId = 123u; - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2); - EXPECT_CALL(*context, texStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 2, 2)) - .Times(1); - EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, _, _)).Times(AnyNumber()); - child_resource_provider->AllocateForTesting(id); - - EXPECT_CALL(*context, RetireTextureId(kTextureId)); - child_resource_provider->DeleteResource(id); -} - -TEST_P(ResourceProviderTest, ScopedWriteLockGpuMemoryBuffer) { - if (!use_gpu()) - return; - - std::unique_ptr<AllocationTrackingContext3D> context_owned( - new StrictMock<AllocationTrackingContext3D>); - AllocationTrackingContext3D* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - const int kWidth = 2; - const int kHeight = 2; - viz::ResourceFormat format = viz::RGBA_8888; - const unsigned kTextureId = 123u; - const unsigned kImageId = 234u; - - auto resource_provider = std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings()); - - viz::ResourceId id = resource_provider->CreateGpuMemoryBufferResource( - gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kDefault, format, - gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace()); - - InSequence sequence; - - // Create texture and image upon releasing the lock. - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); - EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber()); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); - EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA)) - .WillOnce(Return(kImageId)); - EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)); - - { - LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( - resource_provider.get(), id); - EXPECT_TRUE(lock.GetGpuMemoryBuffer()); - } - Mock::VerifyAndClearExpectations(context); - - // Upload to GPU again since image is dirty after the write lock. - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); - EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)); - EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)); - - { - LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( - resource_provider.get(), id); - EXPECT_TRUE(lock.GetGpuMemoryBuffer()); - } - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)); - EXPECT_CALL(*context, RetireTextureId(kTextureId)); -} - -TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { - if (!use_gpu()) - return; - - std::unique_ptr<AllocationTrackingContext3D> context_owned( - new AllocationTrackingContext3D); - AllocationTrackingContext3D* context = context_owned.get(); - context_owned->set_support_compressed_texture_etc1(true); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - gfx::Size size(4, 4); - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - int texture_id = 123; - - viz::ResourceId id = resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, viz::ETC1, gfx::ColorSpace()); - EXPECT_NE(0u, id); - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1); - resource_provider->AllocateForTesting(id); - - EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); - resource_provider->DeleteResource(id); -} - -TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) { - if (!use_gpu()) - return; - - std::unique_ptr<AllocationTrackingContext3D> context_owned( - new AllocationTrackingContext3D); - AllocationTrackingContext3D* context = context_owned.get(); - context_owned->set_support_compressed_texture_etc1(true); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - gfx::Size size(4, 4); - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - int texture_id = 123; - uint8_t pixels[8]; - - viz::ResourceId id = resource_provider->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, viz::ETC1, gfx::ColorSpace()); - EXPECT_NE(0u, id); - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); - EXPECT_CALL(*context, - compressedTexImage2D( - _, 0, _, size.width(), size.height(), _, _, _)).Times(1); - resource_provider->CopyToResource(id, pixels, size); - - EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); - resource_provider->DeleteResource(id); -} - -INSTANTIATE_TEST_CASE_P(ResourceProviderTests, - ResourceProviderTest, - ::testing::Values(true, false)); - -class TextureIdAllocationTrackingContext - : public viz::TestWebGraphicsContext3D { - public: - GLuint NextTextureId() override { - base::AutoLock lock(namespace_->lock); - return namespace_->next_texture_id++; - } - void RetireTextureId(GLuint) override {} - GLuint PeekTextureId() { - base::AutoLock lock(namespace_->lock); - return namespace_->next_texture_id; - } -}; - -TEST_P(ResourceProviderTest, GetSyncTokenForResources) { - if (!use_gpu()) - return; - - gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; - - // ~Random set of |release_count|s to set on sync tokens. - uint64_t release_counts[5] = {7, 3, 10, 2, 5}; - - ResourceProvider::ResourceIdArray array; - for (uint32_t i = 0; i < arraysize(release_counts); ++i) { - viz::ResourceId id = child_resource_provider_->CreateGpuTextureResource( - size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace()); - array.push_back(id); - - LayerTreeResourceProvider::ScopedWriteLockGL lock( - child_resource_provider_.get(), id); - gpu::SyncToken token; - token.Set(gpu::CommandBufferNamespace::INVALID, gpu::CommandBufferId(), - release_counts[i]); - lock.set_sync_token(token); - } - - gpu::SyncToken last_token = - child_resource_provider_->GetSyncTokenForResources(array); - EXPECT_EQ(last_token.release_count(), 10u); -} - -TEST_P(ResourceProviderTest, ScopedWriteLockGL) { - if (!use_gpu()) - return; - std::unique_ptr<AllocationTrackingContext3D> context_owned( - new StrictMock<AllocationTrackingContext3D>); - AllocationTrackingContext3D* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - const int kWidth = 2; - const int kHeight = 2; - const viz::ResourceFormat format = viz::RGBA_8888; - const unsigned kTextureId = 123u; - - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - viz::ResourceId id = resource_provider->CreateGpuTextureResource( - gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kDefault, format, - gfx::ColorSpace()); - - InSequence sequence; - - // First use will allocate lazily when accessing the texture. - { - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); - EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber()); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); - EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), - kWidth, kHeight, 0, GLDataFormat(format), - GLDataType(format), nullptr)); - LayerTreeResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), - id); - EXPECT_EQ(lock.GetTexture(), kTextureId); - Mock::VerifyAndClearExpectations(context); - } - - // Subsequent uses will not allocate. - { - LayerTreeResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), - id); - EXPECT_EQ(lock.GetTexture(), kTextureId); - } - - EXPECT_CALL(*context, RetireTextureId(kTextureId)); - resource_provider->DeleteResource(id); -} - -TEST_P(ResourceProviderTest, ScopedWriteLockGL_Overlay) { - if (!use_gpu()) - return; - std::unique_ptr<AllocationTrackingContext3D> context_owned( - new StrictMock<AllocationTrackingContext3D>); - AllocationTrackingContext3D* context = context_owned.get(); - context->set_support_texture_storage_image(true); - - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - const int kWidth = 2; - const int kHeight = 2; - const viz::ResourceFormat format = viz::RGBA_8888; - const unsigned kTextureId = 123u; - - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - viz::ResourceId id = resource_provider->CreateGpuTextureResource( - gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kOverlay, format, - gfx::ColorSpace()); - - InSequence sequence; - - // First use will allocate lazily on accessing the texture. - { - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); - EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber()); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); - EXPECT_CALL(*context, texStorage2DImageCHROMIUM(GL_TEXTURE_2D, GL_RGBA8_OES, - GL_SCANOUT_CHROMIUM, kWidth, - kHeight)); - LayerTreeResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), - id); - EXPECT_EQ(lock.GetTexture(), kTextureId); - Mock::VerifyAndClearExpectations(context); - } - - // Subsequent uses will not allocate. - { - LayerTreeResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), - id); - EXPECT_EQ(lock.GetTexture(), kTextureId); - } - - EXPECT_CALL(*context, RetireTextureId(kTextureId)); - resource_provider->DeleteResource(id); -} - -TEST_P(ResourceProviderTest, ScopedWriteLockRaster_Mailbox) { - if (!use_gpu()) - return; - std::unique_ptr<AllocationTrackingContext3D> context_owned( - new StrictMock<AllocationTrackingContext3D>); - AllocationTrackingContext3D* context = context_owned.get(); - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - const int kWidth = 2; - const int kHeight = 2; - const viz::ResourceFormat format = viz::RGBA_8888; - const unsigned kTextureId = 123u; - const unsigned kWorkerTextureId = 234u; - - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - viz::ResourceId id = resource_provider->CreateGpuTextureResource( - gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kDefault, format, - gfx::ColorSpace()); - - InSequence sequence; - gpu::SyncToken sync_token; - - // First use will create mailbox when lock is created and allocate lazily in - // ConsumeTexture. - { - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); - EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber()); - LayerTreeResourceProvider::ScopedWriteLockRaster lock( - resource_provider.get(), id); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, produceTextureDirectCHROMIUM(kTextureId, _)); - lock.CreateMailbox(); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)) - .WillOnce(Return(kWorkerTextureId)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kWorkerTextureId)); - EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), - kWidth, kHeight, 0, GLDataFormat(format), - GLDataType(format), nullptr)); - EXPECT_EQ(kWorkerTextureId, - lock.ConsumeTexture(context_provider->RasterInterface())); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId)); - context_provider->ContextGL()->DeleteTextures(1, &kWorkerTextureId); - Mock::VerifyAndClearExpectations(context); - } - - // Subsequent uses will not create mailbox or allocate. - { - LayerTreeResourceProvider::ScopedWriteLockRaster lock( - resource_provider.get(), id); - lock.CreateMailbox(); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)) - .WillOnce(Return(kWorkerTextureId)); - EXPECT_EQ(kWorkerTextureId, - lock.ConsumeTexture(context_provider->RasterInterface())); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId)); - context_provider->ContextGL()->DeleteTextures(1, &kWorkerTextureId); - - sync_token = LayerTreeResourceProvider::GenerateSyncTokenHelper( - context_provider->RasterInterface()); - lock.set_sync_token(sync_token); - Mock::VerifyAndClearExpectations(context); - } - - // Wait for worker context sync token before deleting texture. - EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); - EXPECT_CALL(*context, RetireTextureId(kTextureId)); - resource_provider->DeleteResource(id); -} - -TEST_P(ResourceProviderTest, ScopedWriteLockRaster_Mailbox_Overlay) { - if (!use_gpu()) - return; - - std::unique_ptr<AllocationTrackingContext3D> context_owned( - new StrictMock<AllocationTrackingContext3D>); - AllocationTrackingContext3D* context = context_owned.get(); - context->set_support_texture_storage_image(true); - - auto context_provider = - viz::TestContextProvider::Create(std::move(context_owned)); - context_provider->BindToCurrentThread(); - - const int kWidth = 2; - const int kHeight = 2; - const viz::ResourceFormat format = viz::RGBA_8888; - const unsigned kTextureId = 123u; - const unsigned kWorkerTextureId = 234u; - - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( - context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); - - viz::ResourceId id = resource_provider->CreateGpuTextureResource( - gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kOverlay, format, - gfx::ColorSpace()); - - InSequence sequence; - gpu::SyncToken sync_token; - - // First use will create mailbox when lock is created and allocate lazily in - // ConsumeTexture. - { - EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); - EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber()); - LayerTreeResourceProvider::ScopedWriteLockRaster lock( - resource_provider.get(), id); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, produceTextureDirectCHROMIUM(kTextureId, _)); - lock.CreateMailbox(); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)) - .WillOnce(Return(kWorkerTextureId)); - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kWorkerTextureId)); - EXPECT_CALL(*context, texStorage2DImageCHROMIUM(GL_TEXTURE_2D, GL_RGBA8_OES, - GL_SCANOUT_CHROMIUM, kWidth, - kHeight)); - EXPECT_EQ(kWorkerTextureId, - lock.ConsumeTexture(context_provider->RasterInterface())); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId)); - context_provider->ContextGL()->DeleteTextures(1, &kWorkerTextureId); - Mock::VerifyAndClearExpectations(context); - } - - // Subsequent uses will not create mailbox or allocate. - { - LayerTreeResourceProvider::ScopedWriteLockRaster lock( - resource_provider.get(), id); - lock.CreateMailbox(); - Mock::VerifyAndClearExpectations(context); - - EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)) - .WillOnce(Return(kWorkerTextureId)); - EXPECT_EQ(kWorkerTextureId, - lock.ConsumeTexture(context_provider->RasterInterface())); - Mock::VerifyAndClearExpectations(context); - - sync_token = LayerTreeResourceProvider::GenerateSyncTokenHelper( - context_provider->RasterInterface()); - lock.set_sync_token(sync_token); - - EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId)); - context_provider->ContextGL()->DeleteTextures(1, &kWorkerTextureId); - Mock::VerifyAndClearExpectations(context); - } - - // Wait for worker context sync token before deleting texture. - EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); - EXPECT_CALL(*context, RetireTextureId(kTextureId)); - resource_provider->DeleteResource(id); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/resources/resource_util_unittest.cc b/chromium/cc/resources/resource_util_unittest.cc deleted file mode 100644 index 4680c0ca312..00000000000 --- a/chromium/cc/resources/resource_util_unittest.cc +++ /dev/null @@ -1,171 +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 <stddef.h> - -#include "base/logging.h" -#include "components/viz/common/resources/resource_sizes.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace cc { -namespace { - -struct TestFormat { - viz::ResourceFormat format; - size_t expected_bytes; - size_t expected_bytes_aligned; -}; - -// Modify this constant as per TestFormat variables defined in following tests. -const int kTestFormats = 4; - -class ResourceUtilTest : public testing::Test { - public: - void TestVerifyWidthInBytes(int width, const TestFormat* test_formats) { - for (int i = 0; i < kTestFormats; ++i) { - EXPECT_TRUE(viz::ResourceSizes::VerifyWidthInBytes<size_t>( - width, test_formats[i].format)); - } - } - - void TestCheckedWidthInBytes(int width, const TestFormat* test_formats) { - for (int i = 0; i < kTestFormats; ++i) { - size_t bytes = viz::ResourceSizes::CheckedWidthInBytes<size_t>( - width, test_formats[i].format); - EXPECT_EQ(bytes, test_formats[i].expected_bytes); - } - } - - void TestUncheckedWidthInBytes(int width, const TestFormat* test_formats) { - for (int i = 0; i < kTestFormats; ++i) { - size_t bytes = viz::ResourceSizes::UncheckedWidthInBytes<size_t>( - width, test_formats[i].format); - EXPECT_EQ(bytes, test_formats[i].expected_bytes); - } - } - - void TestUncheckedWidthInBytesAligned(int width, - const TestFormat* test_formats) { - for (int i = 0; i < kTestFormats; ++i) { - size_t bytes = viz::ResourceSizes::UncheckedWidthInBytesAligned<size_t>( - width, test_formats[i].format); - EXPECT_EQ(bytes, test_formats[i].expected_bytes_aligned); - } - } - - void TestVerifySizeInBytes(const gfx::Size& size, - const TestFormat* test_formats) { - for (int i = 0; i < kTestFormats; ++i) { - EXPECT_TRUE(viz::ResourceSizes::VerifySizeInBytes<size_t>( - size, test_formats[i].format)); - } - } - - void TestCheckedSizeInBytes(const gfx::Size& size, - const TestFormat* test_formats) { - for (int i = 0; i < kTestFormats; ++i) { - size_t bytes = viz::ResourceSizes::CheckedSizeInBytes<size_t>( - size, test_formats[i].format); - EXPECT_EQ(bytes, test_formats[i].expected_bytes); - } - } - - void TestUncheckedSizeInBytes(const gfx::Size& size, - const TestFormat* test_formats) { - for (int i = 0; i < kTestFormats; ++i) { - size_t bytes = viz::ResourceSizes::UncheckedSizeInBytes<size_t>( - size, test_formats[i].format); - EXPECT_EQ(bytes, test_formats[i].expected_bytes); - } - } - - void TestUncheckedSizeInBytesAligned(const gfx::Size& size, - const TestFormat* test_formats) { - for (int i = 0; i < kTestFormats; ++i) { - size_t bytes = viz::ResourceSizes::UncheckedSizeInBytesAligned<size_t>( - size, test_formats[i].format); - EXPECT_EQ(bytes, test_formats[i].expected_bytes_aligned); - } - } -}; - -TEST_F(ResourceUtilTest, WidthInBytes) { - // Check bytes for even width. - int width = 10; - TestFormat test_formats[] = { - {viz::RGBA_8888, 40, 40}, // for 32 bits - {viz::RGBA_4444, 20, 20}, // for 16 bits - {viz::ALPHA_8, 10, 12}, // for 8 bits - {viz::ETC1, 5, 8} // for 4 bits - }; - - TestVerifyWidthInBytes(width, test_formats); - TestCheckedWidthInBytes(width, test_formats); - TestUncheckedWidthInBytes(width, test_formats); - TestUncheckedWidthInBytesAligned(width, test_formats); - - // Check bytes for odd width. - int width_odd = 11; - TestFormat test_formats_odd[] = { - {viz::RGBA_8888, 44, 44}, // for 32 bits - {viz::RGBA_4444, 22, 24}, // for 16 bits - {viz::ALPHA_8, 11, 12}, // for 8 bits - {viz::ETC1, 6, 8} // for 4 bits - }; - - TestVerifyWidthInBytes(width_odd, test_formats_odd); - TestCheckedWidthInBytes(width_odd, test_formats_odd); - TestUncheckedWidthInBytes(width_odd, test_formats_odd); - TestUncheckedWidthInBytesAligned(width_odd, test_formats_odd); -} - -TEST_F(ResourceUtilTest, SizeInBytes) { - // Check bytes for even size. - gfx::Size size(10, 10); - TestFormat test_formats[] = { - {viz::RGBA_8888, 400, 400}, // for 32 bits - {viz::RGBA_4444, 200, 200}, // for 16 bits - {viz::ALPHA_8, 100, 120}, // for 8 bits - {viz::ETC1, 50, 80} // for 4 bits - }; - - TestVerifySizeInBytes(size, test_formats); - TestCheckedSizeInBytes(size, test_formats); - TestUncheckedSizeInBytes(size, test_formats); - TestUncheckedSizeInBytesAligned(size, test_formats); - - // Check bytes for odd size. - gfx::Size size_odd(11, 11); - TestFormat test_formats_odd[] = { - {viz::RGBA_8888, 484, 484}, // for 32 bits - {viz::RGBA_4444, 242, 264}, // for 16 bits - {viz::ALPHA_8, 121, 132}, // for 8 bits - {viz::ETC1, 66, 88} // for 4 bits - }; - - TestVerifySizeInBytes(size_odd, test_formats_odd); - TestCheckedSizeInBytes(size_odd, test_formats_odd); - TestUncheckedSizeInBytes(size_odd, test_formats_odd); - TestUncheckedSizeInBytesAligned(size_odd, test_formats_odd); -} - -TEST_F(ResourceUtilTest, WidthInBytesOverflow) { - int width = 10; - // 10 * 16 = 160 bits, overflows in char, but fits in unsigned char. - EXPECT_FALSE(viz::ResourceSizes::VerifyWidthInBytes<signed char>( - width, viz::RGBA_4444)); - EXPECT_TRUE(viz::ResourceSizes::VerifyWidthInBytes<unsigned char>( - width, viz::RGBA_4444)); -} - -TEST_F(ResourceUtilTest, SizeInBytesOverflow) { - gfx::Size size(10, 10); - // 10 * 16 * 10 = 1600 bits, overflows in char, but fits in int. - EXPECT_FALSE( - viz::ResourceSizes::VerifySizeInBytes<signed char>(size, viz::RGBA_4444)); - EXPECT_TRUE(viz::ResourceSizes::VerifySizeInBytes<int>(size, viz::RGBA_4444)); -} - -} // namespace -} // namespace cc diff --git a/chromium/cc/resources/return_callback.h b/chromium/cc/resources/return_callback.h deleted file mode 100644 index a8d5c3a1819..00000000000 --- a/chromium/cc/resources/return_callback.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_RESOURCES_RETURN_CALLBACK_H_ -#define CC_RESOURCES_RETURN_CALLBACK_H_ - -#include "base/callback.h" -#include "components/viz/common/resources/returned_resource.h" - -namespace cc { - -using ReturnCallback = - base::Callback<void(const std::vector<viz::ReturnedResource>&)>; - -} // namespace cc - -#endif // CC_RESOURCES_RETURN_CALLBACK_H_ diff --git a/chromium/cc/resources/video_resource_updater.cc b/chromium/cc/resources/video_resource_updater.cc index 6b3b19215d7..5004919630a 100644 --- a/chromium/cc/resources/video_resource_updater.cc +++ b/chromium/cc/resources/video_resource_updater.cc @@ -22,7 +22,6 @@ #include "cc/base/math_util.h" #include "cc/paint/skia_paint_canvas.h" #include "cc/resources/layer_tree_resource_provider.h" -#include "cc/trees/layer_tree_frame_sink.h" #include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/gpu/texture_allocation.h" #include "components/viz/common/quads/render_pass.h" @@ -31,6 +30,7 @@ #include "components/viz/common/quads/yuv_video_draw_quad.h" #include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/resources/resource_sizes.h" +#include "components/viz/common/resources/shared_bitmap_reporter.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -43,6 +43,7 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/skia_util.h" +#include "ui/gl/gl_enums.h" #include "ui/gl/trace_util.h" namespace cc { @@ -84,8 +85,7 @@ VideoFrameResourceType ExternalResourceTypeForHardwarePlanes( case media::PIXEL_FORMAT_NV12: DCHECK(target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB) - << "Unsupported texture target " << std::hex << std::showbase - << target; + << "Unsupported target " << gl::GLEnums::GetStringEnum(target); // Single plane textures can be sampled as RGB. if (num_textures > 1) return VideoFrameResourceType::YUV; @@ -252,14 +252,14 @@ class VideoResourceUpdater::SoftwarePlaneResource public: SoftwarePlaneResource(uint32_t plane_resource_id, const gfx::Size& size, - LayerTreeFrameSink* layer_tree_frame_sink) + viz::SharedBitmapReporter* shared_bitmap_reporter) : PlaneResource(plane_resource_id, size, viz::ResourceFormat::RGBA_8888, /*is_software=*/true), - layer_tree_frame_sink_(layer_tree_frame_sink), + shared_bitmap_reporter_(shared_bitmap_reporter), shared_bitmap_id_(viz::SharedBitmap::GenerateId()) { - DCHECK(layer_tree_frame_sink_); + DCHECK(shared_bitmap_reporter_); // Allocate SharedMemory and notify display compositor of the allocation. shared_memory_ = viz::bitmap_allocation::AllocateMappedBitmap( @@ -268,11 +268,11 @@ class VideoResourceUpdater::SoftwarePlaneResource viz::bitmap_allocation::DuplicateAndCloseMappedBitmap( shared_memory_.get(), resource_size(), viz::ResourceFormat::RGBA_8888); - layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(handle), - shared_bitmap_id_); + shared_bitmap_reporter_->DidAllocateSharedBitmap(std::move(handle), + shared_bitmap_id_); } ~SoftwarePlaneResource() override { - layer_tree_frame_sink_->DidDeleteSharedBitmap(shared_bitmap_id_); + shared_bitmap_reporter_->DidDeleteSharedBitmap(shared_bitmap_id_); } const viz::SharedBitmapId& shared_bitmap_id() const { @@ -286,7 +286,7 @@ class VideoResourceUpdater::SoftwarePlaneResource } private: - LayerTreeFrameSink* const layer_tree_frame_sink_; + viz::SharedBitmapReporter* const shared_bitmap_reporter_; const viz::SharedBitmapId shared_bitmap_id_; std::unique_ptr<base::SharedMemory> shared_memory_; @@ -340,18 +340,22 @@ VideoResourceUpdater::PlaneResource::AsHardware() { VideoResourceUpdater::VideoResourceUpdater( viz::ContextProvider* context_provider, - LayerTreeFrameSink* layer_tree_frame_sink, + viz::SharedBitmapReporter* shared_bitmap_reporter, LayerTreeResourceProvider* resource_provider, bool use_stream_video_draw_quad, - bool use_gpu_memory_buffer_resources) + bool use_gpu_memory_buffer_resources, + bool use_r16_texture, + int max_resource_size) : context_provider_(context_provider), - layer_tree_frame_sink_(layer_tree_frame_sink), + shared_bitmap_reporter_(shared_bitmap_reporter), resource_provider_(resource_provider), use_stream_video_draw_quad_(use_stream_video_draw_quad), use_gpu_memory_buffer_resources_(use_gpu_memory_buffer_resources), + use_r16_texture_(use_r16_texture), + max_resource_size_(max_resource_size), tracing_id_(g_next_video_resource_updater_id.GetNext()), weak_ptr_factory_(this) { - DCHECK(context_provider_ || layer_tree_frame_sink_); + DCHECK(context_provider_ || shared_bitmap_reporter_); base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( this, "cc::VideoResourceUpdater", base::ThreadTaskRunnerHandle::Get()); @@ -477,6 +481,8 @@ void VideoResourceUpdater::AppendQuads(viz::RenderPass* render_pass, frame_resource_multiplier_, frame_bits_per_channel_); yuv_video_quad->require_overlay = frame->metadata()->IsTrue(media::VideoFrameMetadata::REQUIRE_OVERLAY); + yuv_video_quad->is_protected_video = + frame->metadata()->IsTrue(media::VideoFrameMetadata::PROTECTED_VIDEO); for (viz::ResourceId resource_id : yuv_video_quad->resources) { resource_provider_->ValidateResource(resource_id); @@ -543,6 +549,21 @@ VideoResourceUpdater::CreateExternalResourcesFromVideoFrame( return CreateForSoftwarePlanes(std::move(video_frame)); } +viz::ResourceFormat VideoResourceUpdater::YuvResourceFormat( + int bits_per_channel) { + DCHECK(context_provider_); + const auto& caps = context_provider_->ContextCapabilities(); + if (caps.disable_one_component_textures) + return viz::RGBA_8888; + if (bits_per_channel <= 8) + return caps.texture_rg ? viz::RED_8 : viz::LUMINANCE_8; + if (use_r16_texture_ && caps.texture_norm16) + return viz::R16_EXT; + if (caps.texture_half_float_linear) + return viz::LUMINANCE_F16; + return viz::LUMINANCE_8; +} + VideoResourceUpdater::PlaneResource* VideoResourceUpdater::RecycleOrAllocateResource( const gfx::Size& resource_size, @@ -591,7 +612,7 @@ VideoResourceUpdater::PlaneResource* VideoResourceUpdater::AllocateResource( DCHECK_EQ(format, viz::ResourceFormat::RGBA_8888); all_resources_.push_back(std::make_unique<SoftwarePlaneResource>( - plane_resource_id, plane_size, layer_tree_frame_sink_)); + plane_resource_id, plane_size, shared_bitmap_reporter_)); } else { // Video textures get composited into the display frame, the GPU doesn't // draw to them directly. @@ -718,7 +739,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( #if defined(OS_ANDROID) transfer_resource.is_backed_by_surface_texture = video_frame->metadata()->IsTrue( - media::VideoFrameMetadata::SURFACE_TEXTURE); + media::VideoFrameMetadata::TEXTURE_OWNER); transfer_resource.wants_promotion_hint = video_frame->metadata()->IsTrue( media::VideoFrameMetadata::WANTS_PROMOTION_HINT); #endif @@ -749,10 +770,9 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( // compositing. output_resource_format = viz::RGBA_8888; output_color_space = output_color_space.GetAsFullRangeRGB(); - } else { + } else if (!software_compositor()) { // Can be composited directly from yuv planes. - output_resource_format = - resource_provider_->YuvResourceFormat(bits_per_channel); + output_resource_format = YuvResourceFormat(bits_per_channel); } // If GPU compositing is enabled, but the output resource format @@ -780,37 +800,43 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( output_color_space = output_color_space.GetAsFullRangeRGB(); } - // Drop recycled resources that are the wrong format. - auto can_delete_resource_fn = - [output_resource_format](const std::unique_ptr<PlaneResource>& resource) { - return !resource->has_refs() && - resource->resource_format() != output_resource_format; - }; - base::EraseIf(all_resources_, can_delete_resource_fn); - // TODO(kylechar): Delete resources that are the wrong size for all output - // planes. - - const int max_resource_size = resource_provider_->max_texture_size(); - std::vector<PlaneResource*> plane_resources; + std::vector<gfx::Size> outplane_plane_sizes; + outplane_plane_sizes.reserve(output_plane_count); for (size_t i = 0; i < output_plane_count; ++i) { - gfx::Size output_plane_resource_size = - SoftwarePlaneDimension(video_frame.get(), software_compositor(), i); + outplane_plane_sizes.push_back( + SoftwarePlaneDimension(video_frame.get(), software_compositor(), i)); + const gfx::Size& output_plane_resource_size = outplane_plane_sizes.back(); if (output_plane_resource_size.IsEmpty() || - output_plane_resource_size.width() > max_resource_size || - output_plane_resource_size.height() > max_resource_size) { - // This output plane has invalid geometry. Clean up and return an empty - // external resources. - for (auto* plane_resource : plane_resources) - plane_resource->remove_ref(); + output_plane_resource_size.width() > max_resource_size_ || + output_plane_resource_size.height() > max_resource_size_) { + // This output plane has invalid geometry so return an empty external + // resources. return VideoFrameExternalResources(); } + } - PlaneResource* plane_resource = RecycleOrAllocateResource( - output_plane_resource_size, output_resource_format, output_color_space, - video_frame->unique_id(), i); + // Delete recycled resources that are the wrong format or wrong size. + auto can_delete_resource_fn = + [output_resource_format, + &outplane_plane_sizes](const std::unique_ptr<PlaneResource>& resource) { + // Resources that are still being used can't be deleted. + if (resource->has_refs()) + return false; + + return resource->resource_format() != output_resource_format || + !base::ContainsValue(outplane_plane_sizes, + resource->resource_size()); + }; + base::EraseIf(all_resources_, can_delete_resource_fn); - plane_resource->add_ref(); - plane_resources.push_back(plane_resource); + // Recycle or allocate resources for each video plane. + std::vector<PlaneResource*> plane_resources; + plane_resources.reserve(output_plane_count); + for (size_t i = 0; i < output_plane_count; ++i) { + plane_resources.push_back(RecycleOrAllocateResource( + outplane_plane_sizes[i], output_resource_format, output_color_space, + video_frame->unique_id(), i)); + plane_resources.back()->add_ref(); } VideoFrameExternalResources external_resources; @@ -874,7 +900,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( SoftwarePlaneResource* software_resource = plane_resource->AsSoftware(); external_resources.type = VideoFrameResourceType::RGBA_PREMULTIPLIED; transferable_resource = viz::TransferableResource::MakeSoftware( - software_resource->shared_bitmap_id(), 0 /* sequence_number */, + software_resource->shared_bitmap_id(), software_resource->resource_size(), plane_resource->resource_format()); } else { @@ -902,7 +928,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( } const viz::ResourceFormat yuv_resource_format = - resource_provider_->YuvResourceFormat(bits_per_channel); + YuvResourceFormat(bits_per_channel); DCHECK(yuv_resource_format == viz::LUMINANCE_F16 || yuv_resource_format == viz::R16_EXT || yuv_resource_format == viz::LUMINANCE_8 || diff --git a/chromium/cc/resources/video_resource_updater.h b/chromium/cc/resources/video_resource_updater.h index 6d152ef2d85..0b3f651bed6 100644 --- a/chromium/cc/resources/video_resource_updater.h +++ b/chromium/cc/resources/video_resource_updater.h @@ -38,10 +38,10 @@ class Transform; namespace viz { class ContextProvider; class RenderPass; +class SharedBitmapReporter; } namespace cc { -class LayerTreeFrameSink; class LayerTreeResourceProvider; // Specifies what type of data is contained in the mailboxes, as well as how @@ -79,22 +79,21 @@ class CC_EXPORT VideoResourceUpdater : public base::trace_event::MemoryDumpProvider { public: // For GPU compositing |context_provider| should be provided and for software - // compositing |layer_tree_frame_sink| should be provided. If there is a + // compositing |shared_bitmap_reporter| should be provided. If there is a // non-null |context_provider| we assume GPU compositing. - // TODO(kylechar): Don't use LayerTreeFrameSink for the software compositing - // path. The UseSurfaceLayerForVideo path isn't compatible with this. We can - // maybe use mojom::CompositorFrameSink instead. VideoResourceUpdater(viz::ContextProvider* context_provider, - LayerTreeFrameSink* layer_tree_frame_sink, + viz::SharedBitmapReporter* shared_bitmap_reporter, LayerTreeResourceProvider* resource_provider, bool use_stream_video_draw_quad, - bool use_gpu_memory_buffer_resources); + bool use_gpu_memory_buffer_resources, + bool use_r16_texture, + int max_resource_size); ~VideoResourceUpdater() override; // For each CompositorFrame the following sequence is expected: // 1. ObtainFrameResources(): Import resources for the next video frame with - // LayerTreeResourceProvider. This will reuse existing GPU or SharedBitmap + // LayerTreeResourceProvider. This will reuse existing GPU or SharedMemory // buffers if possible, otherwise it will allocate new ones. // 2. AppendQuads(): Add DrawQuads to CompositorFrame for video. // 3. ReleaseFrameResources(): After the CompositorFrame has been submitted, @@ -117,6 +116,8 @@ class CC_EXPORT VideoResourceUpdater VideoFrameExternalResources CreateExternalResourcesFromVideoFrame( scoped_refptr<media::VideoFrame> video_frame); + viz::ResourceFormat YuvResourceFormat(int bits_per_channel); + private: class PlaneResource; class HardwarePlaneResource; @@ -181,10 +182,13 @@ class CC_EXPORT VideoResourceUpdater base::trace_event::ProcessMemoryDump* pmd) override; viz::ContextProvider* const context_provider_; - LayerTreeFrameSink* const layer_tree_frame_sink_; + viz::SharedBitmapReporter* const shared_bitmap_reporter_; LayerTreeResourceProvider* const resource_provider_; const bool use_stream_video_draw_quad_; const bool use_gpu_memory_buffer_resources_; + // TODO(crbug.com/759456): Remove after r16 is used without the flag. + const bool use_r16_texture_; + const int max_resource_size_; const int tracing_id_; std::unique_ptr<media::PaintCanvasVideoRenderer> video_renderer_; uint32_t next_plane_resource_id_ = 1; diff --git a/chromium/cc/resources/video_resource_updater_unittest.cc b/chromium/cc/resources/video_resource_updater_unittest.cc index 17b44064587..a26069cdd48 100644 --- a/chromium/cc/resources/video_resource_updater_unittest.cc +++ b/chromium/cc/resources/video_resource_updater_unittest.cc @@ -8,11 +8,12 @@ #include <stdint.h> #include "base/bind.h" -#include "cc/resources/resource_provider.h" +#include "cc/resources/layer_tree_resource_provider.h" #include "cc/test/fake_layer_tree_frame_sink.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_resource_provider.h" #include "components/viz/test/fake_output_surface.h" +#include "components/viz/test/test_gles2_interface.h" #include "components/viz/test/test_web_graphics_context_3d.h" #include "gpu/GLES2/gl2extchromium.h" #include "media/base/video_frame.h" @@ -21,9 +22,9 @@ namespace cc { namespace { -class WebGraphicsContext3DUploadCounter : public viz::TestWebGraphicsContext3D { +class UploadCounterGLES2Interface : public viz::TestGLES2Interface { public: - void texSubImage2D(GLenum target, + void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, @@ -35,26 +36,20 @@ class WebGraphicsContext3DUploadCounter : public viz::TestWebGraphicsContext3D { ++upload_count_; } - void texStorage2DEXT(GLenum target, + void TexStorage2DEXT(GLenum target, GLint levels, GLuint internalformat, GLint width, - GLint height) override { - } - - GLuint createTexture() override { - ++created_texture_count_; - return TestWebGraphicsContext3D::createTexture(); - } + GLint height) override {} - void deleteTexture(GLuint texture) override { - --created_texture_count_; - TestWebGraphicsContext3D::deleteTexture(texture); + void GenTextures(GLsizei n, GLuint* textures) override { + created_texture_count_ += n; + viz::TestGLES2Interface::GenTextures(n, textures); } - void deleteTextures(GLsizei count, const GLuint* ids) override { - created_texture_count_ -= count; - TestWebGraphicsContext3D::deleteTextures(count, ids); + void DeleteTextures(GLsizei n, const GLuint* textures) override { + created_texture_count_ -= n; + viz::TestGLES2Interface::DeleteTextures(n, textures); } int UploadCount() { return upload_count_; } @@ -71,13 +66,13 @@ class WebGraphicsContext3DUploadCounter : public viz::TestWebGraphicsContext3D { class VideoResourceUpdaterTest : public testing::Test { protected: VideoResourceUpdaterTest() { - std::unique_ptr<WebGraphicsContext3DUploadCounter> context3d( - new WebGraphicsContext3DUploadCounter()); + std::unique_ptr<UploadCounterGLES2Interface> gl( + new UploadCounterGLES2Interface()); - context3d_ = context3d.get(); - context3d_->set_support_texture_storage(true); + gl_ = gl.get(); + gl_->set_support_texture_storage(true); - context_provider_ = viz::TestContextProvider::Create(std::move(context3d)); + context_provider_ = viz::TestContextProvider::Create(std::move(gl)); context_provider_->BindToCurrentThread(); } @@ -87,17 +82,17 @@ class VideoResourceUpdaterTest : public testing::Test { layer_tree_frame_sink_software_ = FakeLayerTreeFrameSink::CreateSoftware(); resource_provider3d_ = FakeResourceProvider::CreateLayerTreeResourceProvider( - context_provider_.get(), nullptr, nullptr, high_bit_for_testing_); + context_provider_.get()); resource_provider_software_ = - FakeResourceProvider::CreateLayerTreeResourceProvider( - nullptr, nullptr, nullptr, high_bit_for_testing_); + FakeResourceProvider::CreateLayerTreeResourceProvider(nullptr); } std::unique_ptr<VideoResourceUpdater> CreateUpdaterForHardware( bool use_stream_video_draw_quad = false) { return std::make_unique<VideoResourceUpdater>( context_provider_.get(), nullptr, resource_provider3d_.get(), - use_stream_video_draw_quad, /*use_gpu_memory_buffer_resources=*/false); + use_stream_video_draw_quad, /*use_gpu_memory_buffer_resources=*/false, + /*use_r16_texture=*/use_r16_texture_, /*max_resource_size=*/10000); } std::unique_ptr<VideoResourceUpdater> CreateUpdaterForSoftware() { @@ -105,15 +100,21 @@ class VideoResourceUpdaterTest : public testing::Test { nullptr, layer_tree_frame_sink_software_.get(), resource_provider_software_.get(), /*use_stream_video_draw_quad=*/false, - /*use_gpu_memory_buffer_resources=*/false); + /*use_gpu_memory_buffer_resources=*/false, + /*use_r16_texture=*/false, + /*max_resource_size=*/10000); } - scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() { - const int kDimension = 10; - gfx::Size size(kDimension, kDimension); - static uint8_t y_data[kDimension * kDimension] = {0}; - static uint8_t u_data[kDimension * kDimension / 2] = {0}; - static uint8_t v_data[kDimension * kDimension / 2] = {0}; + // Note that the number of pixels needed for |size| must be less than or equal + // to the number of pixels needed for size of 100x100. + scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame( + const gfx::Size& size = gfx::Size(10, 10)) { + constexpr int kMaxDimension = 100; + static uint8_t y_data[kMaxDimension * kMaxDimension] = {0}; + static uint8_t u_data[kMaxDimension * kMaxDimension / 2] = {0}; + static uint8_t v_data[kMaxDimension * kMaxDimension / 2] = {0}; + + CHECK_LE(size.width() * size.height(), kMaxDimension * kMaxDimension); scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::WrapExternalYuvData( @@ -240,13 +241,13 @@ class VideoResourceUpdaterTest : public testing::Test { static const gpu::SyncToken kMailboxSyncToken; - WebGraphicsContext3DUploadCounter* context3d_; + UploadCounterGLES2Interface* gl_; scoped_refptr<viz::TestContextProvider> context_provider_; std::unique_ptr<FakeLayerTreeFrameSink> layer_tree_frame_sink_software_; std::unique_ptr<LayerTreeResourceProvider> resource_provider3d_; std::unique_ptr<LayerTreeResourceProvider> resource_provider_software_; gpu::SyncToken release_sync_token_; - bool high_bit_for_testing_ = false; + bool use_r16_texture_ = false; }; const gpu::SyncToken VideoResourceUpdaterTest::kMailboxSyncToken = @@ -275,7 +276,7 @@ TEST_F(VideoResourceUpdaterTest, HighBitFrameNoF16) { class VideoResourceUpdaterTestWithF16 : public VideoResourceUpdaterTest { public: VideoResourceUpdaterTestWithF16() : VideoResourceUpdaterTest() { - context3d_->set_support_texture_half_float_linear(true); + gl_->set_support_texture_half_float_linear(true); } }; @@ -301,8 +302,8 @@ TEST_F(VideoResourceUpdaterTestWithF16, HighBitFrame) { class VideoResourceUpdaterTestWithR16 : public VideoResourceUpdaterTest { public: VideoResourceUpdaterTestWithR16() : VideoResourceUpdaterTest() { - high_bit_for_testing_ = true; - context3d_->set_support_texture_norm16(true); + use_r16_texture_ = true; + gl_->set_support_texture_norm16(true); } }; @@ -361,14 +362,14 @@ TEST_F(VideoResourceUpdaterTest, ReuseResource) { video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234)); // Allocate the resources for a YUV video frame. - context3d_->ResetUploadCount(); + gl_->ResetUploadCount(); VideoFrameExternalResources resources = updater->CreateExternalResourcesFromVideoFrame(video_frame); EXPECT_EQ(VideoFrameResourceType::YUV, resources.type); EXPECT_EQ(3u, resources.resources.size()); EXPECT_EQ(3u, resources.release_callbacks.size()); // Expect exactly three texture uploads, one for each plane. - EXPECT_EQ(3, context3d_->UploadCount()); + EXPECT_EQ(3, gl_->UploadCount()); // Simulate the ResourceProvider releasing the resources back to the video // updater. @@ -376,13 +377,13 @@ TEST_F(VideoResourceUpdaterTest, ReuseResource) { std::move(release_callback).Run(gpu::SyncToken(), false); // Allocate resources for the same frame. - context3d_->ResetUploadCount(); + gl_->ResetUploadCount(); resources = updater->CreateExternalResourcesFromVideoFrame(video_frame); EXPECT_EQ(VideoFrameResourceType::YUV, resources.type); EXPECT_EQ(3u, resources.resources.size()); EXPECT_EQ(3u, resources.release_callbacks.size()); // The data should be reused so expect no texture uploads. - EXPECT_EQ(0, context3d_->UploadCount()); + EXPECT_EQ(0, gl_->UploadCount()); } TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDelete) { @@ -391,23 +392,23 @@ TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDelete) { video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234)); // Allocate the resources for a YUV video frame. - context3d_->ResetUploadCount(); + gl_->ResetUploadCount(); VideoFrameExternalResources resources = updater->CreateExternalResourcesFromVideoFrame(video_frame); EXPECT_EQ(VideoFrameResourceType::YUV, resources.type); EXPECT_EQ(3u, resources.resources.size()); EXPECT_EQ(3u, resources.release_callbacks.size()); // Expect exactly three texture uploads, one for each plane. - EXPECT_EQ(3, context3d_->UploadCount()); + EXPECT_EQ(3, gl_->UploadCount()); // Allocate resources for the same frame. - context3d_->ResetUploadCount(); + gl_->ResetUploadCount(); resources = updater->CreateExternalResourcesFromVideoFrame(video_frame); EXPECT_EQ(VideoFrameResourceType::YUV, resources.type); EXPECT_EQ(3u, resources.resources.size()); EXPECT_EQ(3u, resources.release_callbacks.size()); // The data should be reused so expect no texture uploads. - EXPECT_EQ(0, context3d_->UploadCount()); + EXPECT_EQ(0, gl_->UploadCount()); } TEST_F(VideoResourceUpdaterTest, SoftwareFrameSoftwareCompositor) { @@ -473,6 +474,35 @@ TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDeleteSoftwareCompositor) { EXPECT_EQ(layer_tree_frame_sink_software_->shared_bitmaps(), shared_bitmaps); } +TEST_F(VideoResourceUpdaterTest, ChangeResourceSizeSoftwareCompositor) { + constexpr gfx::Size kSize1(10, 10); + constexpr gfx::Size kSize2(20, 20); + + std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware(); + + // Allocate the resources for a software video frame. + VideoFrameExternalResources resources = + updater->CreateExternalResourcesFromVideoFrame( + CreateTestYUVVideoFrame(kSize1)); + // Expect exactly one allocated shared bitmap. + EXPECT_EQ(1u, layer_tree_frame_sink_software_->shared_bitmaps().size()); + auto shared_bitmaps = layer_tree_frame_sink_software_->shared_bitmaps(); + + // Simulate the ResourceProvider releasing the resource back to the video + // updater. + std::move(resources.release_callbacks[0]).Run(gpu::SyncToken(), false); + + // Allocate resources for the next frame with a different size. + resources = updater->CreateExternalResourcesFromVideoFrame( + CreateTestYUVVideoFrame(kSize2)); + + // The first resource was released, so it can be reused but it's the wrong + // size. We should expect the first shared bitmap to be deleted and a new + // shared bitmap to be allocated. + EXPECT_EQ(1u, layer_tree_frame_sink_software_->shared_bitmaps().size()); + EXPECT_NE(layer_tree_frame_sink_software_->shared_bitmaps(), shared_bitmaps); +} + TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes) { std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware(); @@ -511,7 +541,7 @@ TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_StreamTexture) { // Note that |use_stream_video_draw_quad| is true for this test. std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware(true); - context3d_->ResetTextureCreationCount(); + gl_->ResetTextureCreationCount(); scoped_refptr<media::VideoFrame> video_frame = CreateTestStreamTextureHardwareVideoFrame(false); @@ -522,11 +552,11 @@ TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_StreamTexture) { EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES, resources.resources[0].mailbox_holder.texture_target); EXPECT_EQ(1u, resources.release_callbacks.size()); - EXPECT_EQ(0, context3d_->TextureCreationCount()); + EXPECT_EQ(0, gl_->TextureCreationCount()); // A copied stream texture should return an RGBA resource in a new // GL_TEXTURE_2D texture. - context3d_->ResetTextureCreationCount(); + gl_->ResetTextureCreationCount(); video_frame = CreateTestStreamTextureHardwareVideoFrame(true); resources = updater->CreateExternalResourcesFromVideoFrame(video_frame); EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type); @@ -534,12 +564,12 @@ TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_StreamTexture) { EXPECT_EQ((GLenum)GL_TEXTURE_2D, resources.resources[0].mailbox_holder.texture_target); EXPECT_EQ(1u, resources.release_callbacks.size()); - EXPECT_EQ(1, context3d_->TextureCreationCount()); + EXPECT_EQ(0, gl_->TextureCreationCount()); } TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_TextureQuad) { std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware(); - context3d_->ResetTextureCreationCount(); + gl_->ResetTextureCreationCount(); scoped_refptr<media::VideoFrame> video_frame = CreateTestStreamTextureHardwareVideoFrame(false); @@ -550,7 +580,7 @@ TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_TextureQuad) { EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES, resources.resources[0].mailbox_holder.texture_target); EXPECT_EQ(1u, resources.release_callbacks.size()); - EXPECT_EQ(0, context3d_->TextureCreationCount()); + EXPECT_EQ(0, gl_->TextureCreationCount()); } // Passthrough the sync token returned by the compositor if we don't have an @@ -646,7 +676,7 @@ TEST_F(VideoResourceUpdaterTest, GenerateSyncTokenOnTextureCopy) { // of the underlying buffer, that is YUV_420_BIPLANAR. TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_SingleNV12) { std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware(); - context3d_->ResetTextureCreationCount(); + gl_->ResetTextureCreationCount(); scoped_refptr<media::VideoFrame> video_frame = CreateTestHardwareVideoFrame( media::PIXEL_FORMAT_NV12, GL_TEXTURE_EXTERNAL_OES); @@ -669,12 +699,12 @@ TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_SingleNV12) { EXPECT_EQ(gfx::BufferFormat::YUV_420_BIPLANAR, resources.resources[0].buffer_format); - EXPECT_EQ(0, context3d_->TextureCreationCount()); + EXPECT_EQ(0, gl_->TextureCreationCount()); } TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_DualNV12) { std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware(); - context3d_->ResetTextureCreationCount(); + gl_->ResetTextureCreationCount(); scoped_refptr<media::VideoFrame> video_frame = CreateTestYuvHardwareVideoFrame(media::PIXEL_FORMAT_NV12, 2, GL_TEXTURE_EXTERNAL_OES); @@ -697,8 +727,10 @@ TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_DualNV12) { EXPECT_EQ((GLenum)GL_TEXTURE_RECTANGLE_ARB, resources.resources[0].mailbox_holder.texture_target); EXPECT_EQ(gfx::BufferFormat::RGBA_8888, resources.resources[0].buffer_format); - - EXPECT_EQ(0, context3d_->TextureCreationCount()); + // When TestWebGraphicsContext3D is used, createAndConsumeTextureCHROMIUM will + // call createTexture. But this is incorrect, so when this is converted to + // TestGLES2Interface, GenTextures will not being called. + EXPECT_EQ(0, gl_->TextureCreationCount()); } } // namespace diff --git a/chromium/cc/scheduler/compositor_timing_history.cc b/chromium/cc/scheduler/compositor_timing_history.cc index 20ec6a038fa..dd4d8f8a958 100644 --- a/chromium/cc/scheduler/compositor_timing_history.cc +++ b/chromium/cc/scheduler/compositor_timing_history.cc @@ -54,8 +54,6 @@ class CompositorTimingHistory::UMAReporter { base::TimeDelta duration) = 0; virtual void AddDrawIntervalWithMainThreadAnimations( base::TimeDelta duration) = 0; - virtual void AddDrawIntervalWithMainThreadCompositableAnimations( - base::TimeDelta duration) = 0; // Synchronization measurements virtual void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) = 0; @@ -198,13 +196,6 @@ class RendererUMAReporter : public CompositorTimingHistory::UMAReporter { "Scheduling.Renderer.DrawIntervalWithMainThreadAnimations", interval); } - void AddDrawIntervalWithMainThreadCompositableAnimations( - base::TimeDelta interval) override { - UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED( - "Scheduling.Renderer.DrawIntervalWithMainThreadCompositableAnimations", - interval); - } - void AddBeginImplFrameLatency(base::TimeDelta delta) override { UMA_HISTOGRAM_CUSTOM_TIMES_DURATION( "Scheduling.Renderer.BeginImplFrameLatency", delta); @@ -325,15 +316,6 @@ class BrowserUMAReporter : public CompositorTimingHistory::UMAReporter { "Scheduling.Browser.DrawIntervalWithMainThreadAnimations", interval); } - void AddDrawIntervalWithMainThreadCompositableAnimations( - base::TimeDelta interval) override { - // Still report, but the data is not meaningful. - UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED( - "Scheduling.Browser." - "DrawIntervalWithMainThreadCompositableAnimations", - interval); - } - void AddBeginImplFrameLatency(base::TimeDelta delta) override { UMA_HISTOGRAM_CUSTOM_TIMES_DURATION( "Scheduling.Browser.BeginImplFrameLatency", delta); @@ -428,8 +410,6 @@ class NullUMAReporter : public CompositorTimingHistory::UMAReporter { base::TimeDelta inverval) override {} void AddDrawIntervalWithMainThreadAnimations( base::TimeDelta inverval) override {} - void AddDrawIntervalWithMainThreadCompositableAnimations( - base::TimeDelta interval) override {} void AddBeginImplFrameLatency(base::TimeDelta delta) override {} void AddBeginMainFrameQueueDurationCriticalDuration( base::TimeDelta duration) override {} @@ -883,7 +863,6 @@ void CompositorTimingHistory::DidDraw( base::TimeTicks impl_frame_time, size_t composited_animations_count, size_t main_thread_animations_count, - size_t main_thread_compositable_animations_count, bool current_frame_had_raf, bool next_frame_has_pending_raf) { DCHECK_NE(base::TimeTicks(), draw_start_time_); @@ -936,17 +915,8 @@ void CompositorTimingHistory::DidDraw( draw_end_time - new_active_tree_draw_end_time_prev_; uma_reporter_->AddDrawIntervalWithMainThreadAnimations(draw_interval); } - if (main_thread_compositable_animations_count > 0 && - previous_frame_had_main_thread_compositable_animations_) { - base::TimeDelta draw_interval = - draw_end_time - new_active_tree_draw_end_time_prev_; - uma_reporter_->AddDrawIntervalWithMainThreadCompositableAnimations( - draw_interval); - } previous_frame_had_main_thread_animations_ = main_thread_animations_count > 0; - previous_frame_had_main_thread_compositable_animations_ = - main_thread_compositable_animations_count > 0; // It's possible that two consecutive main frames both run a rAF but are // separated by idle time (for example: calling requestAnimationFrame from a // setInterval function, with nothing else producing a main frame diff --git a/chromium/cc/scheduler/compositor_timing_history.h b/chromium/cc/scheduler/compositor_timing_history.h index 16b03390299..84aa1545eba 100644 --- a/chromium/cc/scheduler/compositor_timing_history.h +++ b/chromium/cc/scheduler/compositor_timing_history.h @@ -82,7 +82,6 @@ class CC_EXPORT CompositorTimingHistory { base::TimeTicks impl_frame_time, size_t composited_animations_count, size_t main_thread_animations_count, - size_t main_thread_compositable_animations_count, bool current_frame_had_raf, bool next_frame_has_pending_raf); void DidSubmitCompositorFrame(); @@ -164,7 +163,6 @@ class CC_EXPORT CompositorTimingHistory { // Used only for reporting animation targeted UMA. bool previous_frame_had_composited_animations_ = false; bool previous_frame_had_main_thread_animations_ = false; - bool previous_frame_had_main_thread_compositable_animations_ = false; bool previous_frame_had_raf_ = false; TreePriority tree_priority_ = SAME_PRIORITY_FOR_BOTH_TREES; diff --git a/chromium/cc/scheduler/compositor_timing_history_unittest.cc b/chromium/cc/scheduler/compositor_timing_history_unittest.cc index a086de7af3c..564bc81c8bd 100644 --- a/chromium/cc/scheduler/compositor_timing_history_unittest.cc +++ b/chromium/cc/scheduler/compositor_timing_history_unittest.cc @@ -46,7 +46,6 @@ class CompositorTimingHistoryTest : public testing::Test { void DrawMainFrame(int advance_ms, int composited_animations_count, int main_thread_animations_count, - int main_thread_compositable_animations_count, bool current_frame_had_raf = false, bool next_frame_has_pending_raf = false) { timing_history_.WillBeginMainFrame(true, Now()); @@ -60,14 +59,12 @@ class CompositorTimingHistoryTest : public testing::Test { AdvanceNowBy(base::TimeDelta::FromMicroseconds(advance_ms)); timing_history_.DidDraw(true, Now(), composited_animations_count, main_thread_animations_count, - main_thread_compositable_animations_count, current_frame_had_raf, next_frame_has_pending_raf); } void DrawImplFrame(int advance_ms, int composited_animations_count, - int main_thread_animations_count, - int main_thread_compositable_animations_count) { + int main_thread_animations_count) { timing_history_.WillBeginMainFrame(true, Now()); timing_history_.BeginMainFrameStarted(Now()); timing_history_.BeginMainFrameAborted(); @@ -75,9 +72,8 @@ class CompositorTimingHistoryTest : public testing::Test { timing_history_.DidActivate(); timing_history_.WillDraw(); AdvanceNowBy(base::TimeDelta::FromMicroseconds(advance_ms)); - timing_history_.DidDraw( - false, Now(), composited_animations_count, main_thread_animations_count, - main_thread_compositable_animations_count, false, false); + timing_history_.DidDraw(false, Now(), composited_animations_count, + main_thread_animations_count, false, false); } protected: @@ -130,7 +126,7 @@ TEST_F(CompositorTimingHistoryTest, AllSequential_Commit) { AdvanceNowBy(one_second); timing_history_.WillDraw(); AdvanceNowBy(draw_duration); - timing_history_.DidDraw(true, Now(), 0, 0, 0, false, false); + timing_history_.DidDraw(true, Now(), 0, 0, false, false); EXPECT_EQ(begin_main_frame_queue_duration, timing_history_.BeginMainFrameQueueDurationCriticalEstimate()); @@ -181,7 +177,7 @@ TEST_F(CompositorTimingHistoryTest, AllSequential_BeginMainFrameAborted) { AdvanceNowBy(one_second); timing_history_.WillDraw(); AdvanceNowBy(draw_duration); - timing_history_.DidDraw(false, Now(), 0, 0, 0, false, false); + timing_history_.DidDraw(false, Now(), 0, 0, false, false); EXPECT_EQ(base::TimeDelta(), timing_history_.BeginMainFrameQueueDurationCriticalEstimate()); @@ -295,150 +291,142 @@ TEST_F(CompositorTimingHistoryTest, BeginMainFrames_NewCriticalSlower) { timing_history_.BeginMainFrameQueueDurationNotCriticalEstimate()); } -void TestAnimationUMA( - const base::HistogramTester& histogram_tester, - base::HistogramBase::Count composited_animation_frames, - base::HistogramBase::Count main_thread_animation_frames, - base::HistogramBase::Count main_thread_compositable_animation_frames) { +void TestAnimationUMA(const base::HistogramTester& histogram_tester, + base::HistogramBase::Count composited_animation_frames, + base::HistogramBase::Count main_thread_animation_frames) { histogram_tester.ExpectTotalCount( "Scheduling.Renderer.DrawIntervalWithCompositedAnimations2", composited_animation_frames); histogram_tester.ExpectTotalCount( "Scheduling.Renderer.DrawIntervalWithMainThreadAnimations2", main_thread_animation_frames); - histogram_tester.ExpectTotalCount( - "Scheduling.Renderer.DrawIntervalWithMainThreadCompositableAnimations2", - main_thread_compositable_animation_frames); } TEST_F(CompositorTimingHistoryTest, AnimationNotReported) { base::HistogramTester histogram_tester; // Initial frame has no main-thread animations or rAF. - DrawMainFrame(123, 0, 0, 0); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(123, 0, 0); + TestAnimationUMA(histogram_tester, 0, 0); // The next frame has one composited and one main thread animation running, // but as the previous frame had no animation we shouldn't report anything. - DrawMainFrame(456, 1, 1, 0); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(456, 1, 1); + TestAnimationUMA(histogram_tester, 0, 0); - DrawMainFrame(123, 0, 0, 0); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(123, 0, 0); + TestAnimationUMA(histogram_tester, 0, 0); // The next frame has just one main thread animation running, but again as the // previous frame had no animation we shouldn't report anything. - DrawMainFrame(456, 0, 1, 1); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(456, 0, 1); + TestAnimationUMA(histogram_tester, 0, 0); - DrawMainFrame(123, 0, 0, 0); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(123, 0, 0); + TestAnimationUMA(histogram_tester, 0, 0); // The next frame has no main thread animations but did have a rAF callback. // Again as the previous frame had no visual change we shouldn't report. - DrawMainFrame(123, 0, 0, 0, true); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(123, 0, 0, true); + TestAnimationUMA(histogram_tester, 0, 0); - DrawMainFrame(123, 0, 0, 0); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(123, 0, 0); + TestAnimationUMA(histogram_tester, 0, 0); // Finally, test the combination of both main thread animations and rAF // callbacks being called. - DrawMainFrame(123, 1, 2, 0, true); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(123, 1, 2, true); + TestAnimationUMA(histogram_tester, 0, 0); } TEST_F(CompositorTimingHistoryTest, ConsecutiveFramesAnimationsReported) { base::HistogramTester histogram_tester; - DrawMainFrame(123, 1, 0, 0); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(123, 1, 0); + TestAnimationUMA(histogram_tester, 0, 0); - DrawMainFrame(456, 1, 0, 0); - TestAnimationUMA(histogram_tester, 1, 0, 0); + DrawMainFrame(456, 1, 0); + TestAnimationUMA(histogram_tester, 1, 0); histogram_tester.ExpectBucketCount( "Scheduling.Renderer.DrawIntervalWithCompositedAnimations2", 456, 1); - DrawMainFrame(321, 0, 1, 0); - TestAnimationUMA(histogram_tester, 1, 0, 0); + DrawMainFrame(321, 0, 1); + TestAnimationUMA(histogram_tester, 1, 0); - DrawMainFrame(654, 0, 1, 0); - TestAnimationUMA(histogram_tester, 1, 1, 0); + DrawMainFrame(654, 0, 1); + TestAnimationUMA(histogram_tester, 1, 1); histogram_tester.ExpectBucketCount( "Scheduling.Renderer.DrawIntervalWithMainThreadAnimations2", 654, 1); - DrawMainFrame(123, 0, 1, 1); - TestAnimationUMA(histogram_tester, 1, 2, 0); + DrawMainFrame(123, 0, 1); + TestAnimationUMA(histogram_tester, 1, 2); - DrawMainFrame(456, 0, 1, 1); - TestAnimationUMA(histogram_tester, 1, 3, 1); - histogram_tester.ExpectBucketCount( - "Scheduling.Renderer.DrawIntervalWithMainThreadCompositableAnimations2", - 456, 1); + DrawMainFrame(456, 0, 1); + TestAnimationUMA(histogram_tester, 1, 3); // Main thread and rAF animations are both considered to be part of the same // animation type. - DrawMainFrame(789, 0, 0, 0, true, true); - TestAnimationUMA(histogram_tester, 1, 4, 1); + DrawMainFrame(789, 0, 0, true, true); + TestAnimationUMA(histogram_tester, 1, 4); - DrawMainFrame(987, 0, 1, 0, false); - TestAnimationUMA(histogram_tester, 1, 5, 1); + DrawMainFrame(987, 0, 1, false); + TestAnimationUMA(histogram_tester, 1, 5); // However if there is no pending rAF for a frame, we don't count the one // after it as being linked. - DrawMainFrame(789, 0, 0, 0, true, false); - TestAnimationUMA(histogram_tester, 1, 6, 1); + DrawMainFrame(789, 0, 0, true, false); + TestAnimationUMA(histogram_tester, 1, 6); - DrawMainFrame(987, 0, 0, 0, true, true); - TestAnimationUMA(histogram_tester, 1, 6, 1); + DrawMainFrame(987, 0, 0, true, true); + TestAnimationUMA(histogram_tester, 1, 6); } TEST_F(CompositorTimingHistoryTest, InterFrameAnimationsNotReported) { base::HistogramTester histogram_tester; - DrawMainFrame(123, 0, 1, 0); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawMainFrame(123, 0, 1); + TestAnimationUMA(histogram_tester, 0, 0); // The previous frame had a main thread animation, where the current one is // main thread compositable animation, we don't measure the timing from a // different animation type. - DrawMainFrame(456, 0, 1, 1); - TestAnimationUMA(histogram_tester, 0, 1, 0); + DrawMainFrame(456, 0, 1); + TestAnimationUMA(histogram_tester, 0, 1); - DrawMainFrame(321, 1, 0, 0); - TestAnimationUMA(histogram_tester, 0, 1, 0); + DrawMainFrame(321, 1, 0); + TestAnimationUMA(histogram_tester, 0, 1); - DrawMainFrame(654, 0, 1, 0); - TestAnimationUMA(histogram_tester, 0, 1, 0); + DrawMainFrame(654, 0, 1); + TestAnimationUMA(histogram_tester, 0, 1); - DrawMainFrame(123, 1, 0, 0); - TestAnimationUMA(histogram_tester, 0, 1, 0); + DrawMainFrame(123, 1, 0); + TestAnimationUMA(histogram_tester, 0, 1); } TEST_F(CompositorTimingHistoryTest, AnimationsWithNewActiveTreeNotUsed) { base::HistogramTester histogram_tester; - DrawImplFrame(123, 1, 1, 0); - TestAnimationUMA(histogram_tester, 0, 0, 0); + DrawImplFrame(123, 1, 1); + TestAnimationUMA(histogram_tester, 0, 0); - DrawImplFrame(456, 1, 0, 0); - TestAnimationUMA(histogram_tester, 1, 0, 0); + DrawImplFrame(456, 1, 0); + TestAnimationUMA(histogram_tester, 1, 0); histogram_tester.ExpectBucketCount( "Scheduling.Renderer.DrawIntervalWithCompositedAnimations2", 456, 1); - DrawMainFrame(321, 0, 1, 0); - TestAnimationUMA(histogram_tester, 1, 0, 0); + DrawMainFrame(321, 0, 1); + TestAnimationUMA(histogram_tester, 1, 0); // This frame verifies that we record that there is a composited animation, // so in the next frame when there is a composited animation, we report it. - DrawImplFrame(234, 1, 1, 0); - TestAnimationUMA(histogram_tester, 1, 0, 0); + DrawImplFrame(234, 1, 1); + TestAnimationUMA(histogram_tester, 1, 0); // Even though the previous frame had no main thread animation, we report it // in this frame because the previous main frame had a main thread animation // with the time between main frame draws. - DrawMainFrame(654, 1, 1, 0); - TestAnimationUMA(histogram_tester, 2, 1, 0); + DrawMainFrame(654, 1, 1); + TestAnimationUMA(histogram_tester, 2, 1); histogram_tester.ExpectBucketCount( "Scheduling.Renderer.DrawIntervalWithCompositedAnimations2", 654, 1); // The recorded time for this main thread animation should be the total time @@ -446,8 +434,8 @@ TEST_F(CompositorTimingHistoryTest, AnimationsWithNewActiveTreeNotUsed) { histogram_tester.ExpectBucketCount( "Scheduling.Renderer.DrawIntervalWithMainThreadAnimations2", 888, 1); - DrawImplFrame(123, 1, 0, 0); - TestAnimationUMA(histogram_tester, 3, 1, 0); + DrawImplFrame(123, 1, 0); + TestAnimationUMA(histogram_tester, 3, 1); histogram_tester.ExpectBucketCount( "Scheduling.Renderer.DrawIntervalWithCompositedAnimations2", 123, 1); } diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc index 352c8649bc6..87db539737f 100644 --- a/chromium/cc/scheduler/scheduler.cc +++ b/chromium/cc/scheduler/scheduler.cc @@ -658,7 +658,6 @@ void Scheduler::DrawIfPossible() { begin_impl_frame_tracker_.DangerousMethodCurrentOrLast().frame_time, client_->CompositedAnimationsCount(), client_->MainThreadAnimationsCount(), - client_->MainThreadCompositableAnimationsCount(), client_->CurrentFrameHadRAF(), client_->NextFrameHasPendingRAF()); } @@ -677,7 +676,6 @@ void Scheduler::DrawForced() { begin_impl_frame_tracker_.DangerousMethodCurrentOrLast().frame_time, client_->CompositedAnimationsCount(), client_->MainThreadAnimationsCount(), - client_->MainThreadCompositableAnimationsCount(), client_->CurrentFrameHadRAF(), client_->NextFrameHasPendingRAF()); } diff --git a/chromium/cc/scheduler/scheduler.h b/chromium/cc/scheduler/scheduler.h index 10cb198610e..79ec95b21d4 100644 --- a/chromium/cc/scheduler/scheduler.h +++ b/chromium/cc/scheduler/scheduler.h @@ -55,7 +55,6 @@ class SchedulerClient { // Functions used for reporting anmation targeting UMA, crbug.com/758439. virtual size_t CompositedAnimationsCount() const = 0; virtual size_t MainThreadAnimationsCount() const = 0; - virtual size_t MainThreadCompositableAnimationsCount() const = 0; virtual bool CurrentFrameHadRAF() const = 0; virtual bool NextFrameHasPendingRAF() const = 0; diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc index a4e1fddba04..d1fcefb1c79 100644 --- a/chromium/cc/scheduler/scheduler_unittest.cc +++ b/chromium/cc/scheduler/scheduler_unittest.cc @@ -12,7 +12,6 @@ #include "base/auto_reset.h" #include "base/logging.h" #include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" #include "base/numerics/safe_conversions.h" #include "base/run_loop.h" #include "base/time/time.h" @@ -245,7 +244,6 @@ class FakeSchedulerClient : public SchedulerClient, size_t CompositedAnimationsCount() const override { return 0; } size_t MainThreadAnimationsCount() const override { return 0; } - size_t MainThreadCompositableAnimationsCount() const override { return 0; } bool CurrentFrameHadRAF() const override { return false; } bool NextFrameHasPendingRAF() const override { return false; } diff --git a/chromium/cc/tiles/checker_image_tracker.cc b/chromium/cc/tiles/checker_image_tracker.cc index 060eb020d1c..33385afc182 100644 --- a/chromium/cc/tiles/checker_image_tracker.cc +++ b/chromium/cc/tiles/checker_image_tracker.cc @@ -209,8 +209,6 @@ void CheckerImageTracker::ClearTracker(bool can_clear_decode_policy_tracking) { // they should be accompanied with an invalidation during paint. image_id_to_decode_.clear(); - decoding_mode_map_.clear(); - if (can_clear_decode_policy_tracking) { image_async_decode_state_.clear(); } else { @@ -273,23 +271,12 @@ bool CheckerImageTracker::ShouldCheckerImage(const DrawImage& draw_image, WhichTree tree) { const PaintImage& image = draw_image.paint_image(); PaintImage::Id image_id = image.stable_id(); - TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", - image_id); - - auto decoding_mode_it = decoding_mode_map_.find(image_id); - PaintImage::DecodingMode decoding_mode_hint = - decoding_mode_it == decoding_mode_map_.end() - ? PaintImage::DecodingMode::kUnspecified - : decoding_mode_it->second; + TRACE_EVENT1("cc.debug", "CheckerImageTracker::ShouldCheckerImage", + "image_id", image_id); - // If we don't have default checker imaging enabled, and the developer did not - // specify "async" then we don't checker the images. To put it different, we - // currently only not respect |enable_checker_imaging_| if the value was - // specified as "async" by the developer. - if (decoding_mode_hint != PaintImage::DecodingMode::kAsync && - !enable_checker_imaging_) { + // Checkering of all images is disabled. + if (!enable_checker_imaging_) return false; - } // If the image was invalidated on the current sync tree and the tile is // for the active tree, continue checkering it on the active tree to ensure @@ -306,6 +293,16 @@ bool CheckerImageTracker::ShouldCheckerImage(const DrawImage& draw_image, return true; } + auto decoding_mode_it = decoding_mode_map_.find(image_id); + PaintImage::DecodingMode decoding_mode_hint = + decoding_mode_it == decoding_mode_map_.end() + ? PaintImage::DecodingMode::kUnspecified + : decoding_mode_it->second; + + // We only checker images if the developer specifies async decoding mode. + if (decoding_mode_hint != PaintImage::DecodingMode::kAsync) + return false; + auto insert_result = image_async_decode_state_.insert( std::pair<PaintImage::Id, DecodeState>(image_id, DecodeState())); auto it = insert_result.first; diff --git a/chromium/cc/tiles/checker_image_tracker_unittest.cc b/chromium/cc/tiles/checker_image_tracker_unittest.cc index 0b4606f1463..88c3f10cdd6 100644 --- a/chromium/cc/tiles/checker_image_tracker_unittest.cc +++ b/chromium/cc/tiles/checker_image_tracker_unittest.cc @@ -112,12 +112,16 @@ class CheckerImageTrackerTest : public testing::Test, } auto generator = CreatePaintImageGenerator(gfx::Size(dimension, dimension)); + auto id = PaintImage::GetNextId(); + checker_image_tracker_->UpdateImageDecodingHints( + {{id, PaintImage::DecodingMode::kAsync}}); return DrawImage(PaintImageBuilder::WithDefault() - .set_id(PaintImage::GetNextId()) + .set_id(id) .set_paint_image_generator(std::move(generator)) .set_animation_type(animation) .set_completion_state(completion) .set_is_multipart(is_multipart) + .set_decoding_mode(PaintImage::DecodingMode::kAsync) .TakePaintImage(), SkIRect::MakeWH(dimension, dimension), kNone_SkFilterQuality, SkMatrix::I(), @@ -379,8 +383,6 @@ TEST_F(CheckerImageTrackerTest, ClearsTracker) { checker_image_tracker_->ClearTracker(can_clear_decode_policy_tracking); image_decode_queue = BuildImageDecodeQueue({checkerable_image}, WhichTree::PENDING_TREE); - image_decode_queue = - BuildImageDecodeQueue({checkerable_image}, WhichTree::PENDING_TREE); EXPECT_EQ(image_decode_queue.size(), 1U); // If an image had been decoded and tracker was cleared after it, we should diff --git a/chromium/cc/tiles/decoded_image_tracker.cc b/chromium/cc/tiles/decoded_image_tracker.cc index 0f8f0dda1f3..cd2d1eeb0b1 100644 --- a/chromium/cc/tiles/decoded_image_tracker.cc +++ b/chromium/cc/tiles/decoded_image_tracker.cc @@ -10,7 +10,11 @@ namespace { const int kNumFramesToLock = 2; } // namespace -DecodedImageTracker::DecodedImageTracker() = default; +DecodedImageTracker::DecodedImageTracker(ImageController* controller) + : image_controller_(controller) { + DCHECK(image_controller_); +} + DecodedImageTracker::~DecodedImageTracker() { for (auto& pair : locked_images_) image_controller_->UnlockImageDecode(pair.first); diff --git a/chromium/cc/tiles/decoded_image_tracker.h b/chromium/cc/tiles/decoded_image_tracker.h index 4b9417ffe88..4321a02d13a 100644 --- a/chromium/cc/tiles/decoded_image_tracker.h +++ b/chromium/cc/tiles/decoded_image_tracker.h @@ -24,7 +24,7 @@ namespace cc { // are silently ignored. class CC_EXPORT DecodedImageTracker { public: - DecodedImageTracker(); + explicit DecodedImageTracker(ImageController* controller); ~DecodedImageTracker(); // Request that the given image be decoded. This issues a callback upon @@ -36,18 +36,13 @@ class CC_EXPORT DecodedImageTracker { void NotifyFrameFinished(); private: - friend class TileManager; friend class DecodedImageTrackerTest; - void set_image_controller(ImageController* controller) { - image_controller_ = controller; - } - void ImageDecodeFinished(const base::Callback<void(bool)>& callback, ImageController::ImageDecodeRequestId id, ImageController::ImageDecodeResult result); - ImageController* image_controller_ = nullptr; + ImageController* image_controller_; std::vector<std::pair<ImageController::ImageDecodeRequestId, int>> locked_images_; diff --git a/chromium/cc/tiles/decoded_image_tracker_unittest.cc b/chromium/cc/tiles/decoded_image_tracker_unittest.cc index f5bb5a37c65..365f93b6348 100644 --- a/chromium/cc/tiles/decoded_image_tracker_unittest.cc +++ b/chromium/cc/tiles/decoded_image_tracker_unittest.cc @@ -63,9 +63,7 @@ class TestImageController : public ImageController { class DecodedImageTrackerTest : public testing::Test { public: - void SetUp() override { - decoded_image_tracker_.set_image_controller(image_controller()); - } + DecodedImageTrackerTest() : decoded_image_tracker_(&image_controller_) {} TestImageController* image_controller() { return &image_controller_; } DecodedImageTracker* decoded_image_tracker() { diff --git a/chromium/cc/tiles/gpu_image_decode_cache.cc b/chromium/cc/tiles/gpu_image_decode_cache.cc index 344515342af..efac77afbf7 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache.cc @@ -25,7 +25,6 @@ #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/raster_interface.h" -#include "skia/ext/texture_handle.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkSurface.h" @@ -189,14 +188,16 @@ bool DrawAndScaleImage(const DrawImage& draw_image, SkPixmap* target_pixmap) { // Returns the GL texture ID backing the given SkImage. GrGLuint GlIdFromSkImage(SkImage* image) { DCHECK(image->isTextureBacked()); - GrBackendObject handle = - image->getTextureHandle(true /* flushPendingGrContextIO */); - if (!handle) + GrBackendTexture backend_texture = + image->getBackendTexture(true /* flushPendingGrContextIO */); + if (!backend_texture.isValid()) return 0; - const GrGLTextureInfo* info = skia::GrBackendObjectToGrGLTextureInfo(handle); - if (!info) + + GrGLTextureInfo info; + if (!backend_texture.getGLTextureInfo(&info)) return 0; - return info->fID; + + return info.fID; } // Takes ownership of the backing texture of an SkImage. This allows us to @@ -209,7 +210,7 @@ sk_sp<SkImage> TakeOwnershipOfSkImageBacking(GrContext* context, } GrSurfaceOrigin origin; - image->getTextureHandle(false /* flushPendingGrContextIO */, &origin); + image->getBackendTexture(false /* flushPendingGrContextIO */, &origin); SkColorType color_type = image->colorType(); if (color_type == kUnknown_SkColorType) { return nullptr; @@ -649,12 +650,6 @@ ImageDecodeCache::TaskResult GpuImageDecodeCache::GetTaskForImageAndRefInternal( if (SkipImage(draw_image)) return TaskResult(false); - // For non-lazy images a decode isn't necessary. - // TODO(khushalsagar): We can still have only the upload task to upload ahead - // of raster. - if (!draw_image.paint_image().IsLazyGenerated()) - return TaskResult(false); - base::AutoLock lock(lock_); const PaintImage::FrameKey frame_key = draw_image.frame_key(); ImageData* image_data = GetImageDataForDrawImage(draw_image); @@ -861,34 +856,38 @@ void GpuImageDecodeCache::SetShouldAggressivelyFreeResources( void GpuImageDecodeCache::ClearCache() { base::AutoLock lock(lock_); - for (auto& entry : persistent_cache_) { - if (entry.second->decode.ref_count != 0 || - entry.second->upload.ref_count != 0) { - // Orphan the entry so it will be deleted once no longer in use. - entry.second->is_orphaned = true; - } else if (entry.second->HasUploadedData()) { - DeleteImage(entry.second.get()); - } - } - persistent_cache_.Clear(); + for (auto it = persistent_cache_.begin(); it != persistent_cache_.end();) + it = RemoveFromPersistentCache(it); + DCHECK(persistent_cache_.empty()); + paint_image_entries_.clear(); } -size_t GpuImageDecodeCache::GetMaximumMemoryLimitBytes() const { - return max_working_set_bytes_; -} +GpuImageDecodeCache::PersistentCache::iterator +GpuImageDecodeCache::RemoveFromPersistentCache(PersistentCache::iterator it) { + lock_.AssertAcquired(); -void GpuImageDecodeCache::NotifyImageUnused( - const PaintImage::FrameKey& frame_key) { - auto it = persistent_cache_.Peek(frame_key); - if (it != persistent_cache_.end()) { - if (it->second->decode.ref_count != 0 || - it->second->upload.ref_count != 0) { - it->second->is_orphaned = true; - } else if (it->second->HasUploadedData()) { + if (it->second->decode.ref_count != 0 || it->second->upload.ref_count != 0) { + // Orphan the image and erase it from the |persisent_cache_|. This ensures + // that the image will be deleted once all refs are removed. + it->second->is_orphaned = true; + } else { + // Current entry has no refs. Ensure it is not locked. + DCHECK(!it->second->decode.is_locked()); + DCHECK(!it->second->upload.is_locked()); + + // Unlocked images must not be budgeted. + DCHECK(!it->second->is_budgeted); + + // Free the uploaded image if it exists. + if (it->second->HasUploadedData()) DeleteImage(it->second.get()); - } - persistent_cache_.Erase(it); } + + return persistent_cache_.Erase(it); +} + +size_t GpuImageDecodeCache::GetMaximumMemoryLimitBytes() const { + return max_working_set_bytes_; } bool GpuImageDecodeCache::OnMemoryDump( @@ -1346,16 +1345,8 @@ void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image, image_info.minRowBytes()); // Set |pixmap| to the desired colorspace to decode into. - if (!SupportsColorSpaceConversion()) { - pixmap.setColorSpace(nullptr); - } else if (image_data->mode == DecodedDataMode::kCpu) { - pixmap.setColorSpace(draw_image.target_color_space().ToSkColorSpace()); - } else { - // For kGpu or kTransferCache images color conversion is handled during - // upload, so keep the original colorspace here. - pixmap.setColorSpace(sk_ref_sp(draw_image.paint_image().color_space())); - } - + pixmap.setColorSpace( + ColorSpaceForImageDecode(draw_image, image_data->mode)); if (!DrawAndScaleImage(draw_image, &pixmap)) { DLOG(ERROR) << "DrawAndScaleImage failed."; backing_memory->Unlock(); @@ -1499,6 +1490,7 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image) { "GpuImageDecodeCache::CreateImageData"); lock_.AssertAcquired(); + WillAddCacheEntry(draw_image); int mip_level = CalculateUploadScaleMipLevel(draw_image); SkImageInfo image_info = CreateImageInfoForDrawImage(draw_image, mip_level); @@ -1514,19 +1506,72 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image) { } size_t data_size = image_info.computeMinByteSize(); + + // We need to cache the result of color conversion on the cpu if the image + // will be color converted during the decode. + auto decode_color_space = ColorSpaceForImageDecode(draw_image, mode); + const bool cache_color_conversion_on_cpu = + decode_color_space && + !SkColorSpace::Equals(decode_color_space.get(), + draw_image.paint_image().color_space()); + // |is_bitmap_backed| specifies whether the image has pixel data which can // directly be used for the upload. This will be the case for non-lazy images // used at the original scale. In these cases, we don't internally cache any // cpu component for the image. - // However, if the image will be scaled, we consider it a lazy image and cache - // the scaled result in discardable memory. - const bool is_bitmap_backed = - !draw_image.paint_image().IsLazyGenerated() && mip_level == 0; + // However, if the image will be scaled or color converts on the cpu, we + // consider it a lazy image and cache the scaled result in discardable memory. + const bool is_bitmap_backed = !draw_image.paint_image().IsLazyGenerated() && + mip_level == 0 && + !cache_color_conversion_on_cpu; return base::WrapRefCounted(new ImageData( mode, data_size, draw_image.target_color_space(), CalculateDesiredFilterQuality(draw_image), mip_level, is_bitmap_backed)); } +void GpuImageDecodeCache::WillAddCacheEntry(const DrawImage& draw_image) { + lock_.AssertAcquired(); + + // Remove any old entries for this image. We keep at-most 2 ContentIds for a + // PaintImage (pending and active tree). + auto& cached_content_ids = + paint_image_entries_[draw_image.paint_image().stable_id()].content_ids; + const PaintImage::ContentId new_content_id = + draw_image.frame_key().content_id(); + + if (cached_content_ids[0] == new_content_id || + cached_content_ids[1] == new_content_id) { + return; + } + + if (cached_content_ids[0] == PaintImage::kInvalidContentId) { + cached_content_ids[0] = new_content_id; + return; + } + + if (cached_content_ids[1] == PaintImage::kInvalidContentId) { + cached_content_ids[1] = new_content_id; + return; + } + + const PaintImage::ContentId content_id_to_remove = + std::min(cached_content_ids[0], cached_content_ids[1]); + const PaintImage::ContentId content_id_to_keep = + std::max(cached_content_ids[0], cached_content_ids[1]); + DCHECK_NE(content_id_to_remove, content_id_to_keep); + + for (auto it = persistent_cache_.begin(); it != persistent_cache_.end();) { + if (it->first.content_id() != content_id_to_remove) { + ++it; + } else { + it = RemoveFromPersistentCache(it); + } + } + + cached_content_ids[0] = content_id_to_keep; + cached_content_ids[1] = new_content_id; +} + void GpuImageDecodeCache::DeleteImage(ImageData* image_data) { if (image_data->HasUploadedData()) { DCHECK(!image_data->upload.is_locked()); @@ -1737,6 +1782,12 @@ bool GpuImageDecodeCache::IsInInUseCacheForTesting( return found != in_use_cache_.end(); } +bool GpuImageDecodeCache::IsInPersistentCacheForTesting( + const DrawImage& image) const { + auto found = persistent_cache_.Peek(image.frame_key()); + return found != persistent_cache_.end(); +} + sk_sp<SkImage> GpuImageDecodeCache::GetSWImageDecodeForTesting( const DrawImage& image) { base::AutoLock lock(lock_); @@ -1769,6 +1820,20 @@ bool GpuImageDecodeCache::SupportsColorSpaceConversion() const { } } +sk_sp<SkColorSpace> GpuImageDecodeCache::ColorSpaceForImageDecode( + const DrawImage& image, + DecodedDataMode mode) const { + if (!SupportsColorSpaceConversion()) + return nullptr; + + if (mode == DecodedDataMode::kCpu) + return image.target_color_space().ToSkColorSpace(); + + // For kGpu or kTransferCache images color conversion is handled during + // upload, so keep the original colorspace here. + return sk_ref_sp(image.paint_image().color_space()); +} + void GpuImageDecodeCache::CheckContextLockAcquiredIfNecessary() { if (!context_->GetLock()) return; diff --git a/chromium/cc/tiles/gpu_image_decode_cache.h b/chromium/cc/tiles/gpu_image_decode_cache.h index ea4fe73dce9..90374d7ab72 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache.h +++ b/chromium/cc/tiles/gpu_image_decode_cache.h @@ -126,7 +126,6 @@ class CC_EXPORT GpuImageDecodeCache bool aggressively_free_resources) override; void ClearCache() override; size_t GetMaximumMemoryLimitBytes() const override; - void NotifyImageUnused(const PaintImage::FrameKey& frame_key) override; // MemoryDumpProvider overrides. bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, @@ -160,6 +159,7 @@ class CC_EXPORT GpuImageDecodeCache void SetImageDecodingFailedForTesting(const DrawImage& image); bool DiscardableIsLockedForTesting(const DrawImage& image); bool IsInInUseCacheForTesting(const DrawImage& image) const; + bool IsInPersistentCacheForTesting(const DrawImage& image) const; sk_sp<SkImage> GetSWImageDecodeForTesting(const DrawImage& image); private: @@ -385,6 +385,7 @@ class CC_EXPORT GpuImageDecodeCache scoped_refptr<GpuImageDecodeCache::ImageData> CreateImageData( const DrawImage& image); + void WillAddCacheEntry(const DrawImage& draw_image); SkImageInfo CreateImageInfoForDrawImage(const DrawImage& draw_image, int upload_scale_mip_level) const; @@ -425,6 +426,17 @@ class CC_EXPORT GpuImageDecodeCache void CheckContextLockAcquiredIfNecessary(); + sk_sp<SkColorSpace> ColorSpaceForImageDecode(const DrawImage& image, + DecodedDataMode mode) const; + + // |persistent_cache_| represents the long-lived cache, keeping a certain + // budget of ImageDatas alive even when their ref count reaches zero. + using PersistentCache = base::HashingMRUCache<PaintImage::FrameKey, + scoped_refptr<ImageData>, + PaintImage::FrameKeyHash>; + PersistentCache::iterator RemoveFromPersistentCache( + PersistentCache::iterator it); + const SkColorType color_type_; const bool use_transfer_cache_ = false; viz::RasterContextProvider* context_; @@ -435,13 +447,16 @@ class CC_EXPORT GpuImageDecodeCache // be accessed without a lock since they are thread safe. base::Lock lock_; - // |persistent_cache_| represents the long-lived cache, keeping a certain - // budget of ImageDatas alive even when their ref count reaches zero. - using PersistentCache = base::HashingMRUCache<PaintImage::FrameKey, - scoped_refptr<ImageData>, - PaintImage::FrameKeyHash>; PersistentCache persistent_cache_; + struct CacheEntries { + PaintImage::ContentId content_ids[2] = {PaintImage::kInvalidContentId, + PaintImage::kInvalidContentId}; + }; + // A map of PaintImage::Id to entries for this image in the + // |persistent_cache_|. + base::flat_map<PaintImage::Id, CacheEntries> paint_image_entries_; + // |in_use_cache_| represents the in-use (short-lived) cache. Entries are // cleaned up as soon as their ref count reaches zero. using InUseCache = diff --git a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc index 2c272ededad..91fc94f17e2 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc @@ -1926,38 +1926,6 @@ TEST_P(GpuImageDecodeCacheTest, GetTaskForLargeImageNonSRGBColorSpace) { cache->UnrefImage(draw_image); } -TEST_P(GpuImageDecodeCacheTest, RemoveUnusedImage) { - auto cache = CreateCache(); - bool is_decomposable = true; - SkFilterQuality quality = kHigh_SkFilterQuality; - std::vector<PaintImage::FrameKey> frame_keys; - - for (int i = 0; i < 10; ++i) { - PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100)); - DrawImage draw_image( - image, SkIRect::MakeWH(image.width(), image.height()), quality, - CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - frame_keys.push_back(draw_image.frame_key()); - ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef( - draw_image, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result.need_unref); - EXPECT_TRUE(result.task); - TestTileTaskRunner::ProcessTask(result.task->dependencies()[0].get()); - TestTileTaskRunner::ProcessTask(result.task.get()); - cache->UnrefImage(draw_image); - } - - // We should now have images in our cache. - EXPECT_EQ(cache->GetNumCacheEntriesForTesting(), 10u); - - // Remove unused ids. - for (uint32_t i = 0; i < 10; ++i) { - cache->NotifyImageUnused(frame_keys[i]); - EXPECT_EQ(cache->GetNumCacheEntriesForTesting(), (10 - i - 1)); - } -} - TEST_P(GpuImageDecodeCacheTest, CacheDecodesExpectedFrames) { auto cache = CreateCache(); @@ -2313,6 +2281,56 @@ TEST_P(GpuImageDecodeCacheTest, NonLazyImageUploadNoScale) { EXPECT_FALSE(cache->GetSWImageDecodeForTesting(draw_image)); } +TEST_P(GpuImageDecodeCacheTest, NonLazyImageUploadNoScaleTask) { + auto cache = CreateCache(); + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + PaintImage image = CreateBitmapImage(gfx::Size(10, 10)); + DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()), + quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + PaintImage::kDefaultFrameIndex, DefaultColorSpace()); + auto result = + cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo()); + EXPECT_TRUE(result.need_unref); + EXPECT_TRUE(result.task); + TestTileTaskRunner::ProcessTask(result.task->dependencies()[0].get()); + TestTileTaskRunner::ProcessTask(result.task.get()); + + cache->UnrefImage(draw_image); +} + +TEST_P(GpuImageDecodeCacheTest, NonLazyImageLargeImageColorConverted) { + auto cache = CreateCache(); + const bool should_cache_sw_image = + cache->SupportsColorSpaceConversion() && !use_transfer_cache_; + + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + PaintImage image = CreateBitmapImage(gfx::Size(10, 24000)); + DrawImage draw_image( + image, SkIRect::MakeWH(image.width(), image.height()), quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + PaintImage::kDefaultFrameIndex, gfx::ColorSpace::CreateDisplayP3D65()); + viz::ContextProvider::ScopedContextLock context_lock(context_provider()); + DecodedDrawImage decoded_draw_image = + EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image)); + EXPECT_TRUE(decoded_draw_image.image()); + EXPECT_TRUE(decoded_draw_image.is_budgeted()); + cache->DrawWithImageFinished(draw_image, decoded_draw_image); + // For non-lazy images color converted during scaling, cpu component should be + // cached. + auto sw_image = cache->GetSWImageDecodeForTesting(draw_image); + ASSERT_EQ(!!sw_image, should_cache_sw_image); + if (should_cache_sw_image) { + EXPECT_TRUE(SkColorSpace::Equals( + sw_image->colorSpace(), + gfx::ColorSpace::CreateDisplayP3D65().ToSkColorSpace().get())); + } +} + TEST_P(GpuImageDecodeCacheTest, NonLazyImageUploadDownscaled) { auto cache = CreateCache(); bool is_decomposable = true; @@ -2337,6 +2355,45 @@ TEST_P(GpuImageDecodeCacheTest, NonLazyImageUploadDownscaled) { EXPECT_EQ(sw_image->height(), 5); } +TEST_P(GpuImageDecodeCacheTest, KeepOnlyLast2ContentIds) { + auto cache = CreateCache(); + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + viz::ContextProvider::ScopedContextLock context_lock(context_provider()); + const PaintImage::Id paint_image_id = PaintImage::GetNextId(); + std::vector<DrawImage> draw_images; + std::vector<DecodedDrawImage> decoded_draw_images; + + for (int i = 0; i < 10; ++i) { + PaintImage image = CreateDiscardablePaintImage( + gfx::Size(10, 10), SkColorSpace::MakeSRGB(), true, paint_image_id); + DrawImage draw_image( + image, SkIRect::MakeWH(image.width(), image.height()), quality, + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + PaintImage::kDefaultFrameIndex, DefaultColorSpace()); + DecodedDrawImage decoded_draw_image = + EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image)); + + draw_images.push_back(draw_image); + decoded_draw_images.push_back(decoded_draw_image); + + if (i == 0) + continue; + + // We should only have the last 2 entries in the persistent cache, even + // though everything is in the in use cache. + EXPECT_EQ(cache->GetNumCacheEntriesForTesting(), 2u); + EXPECT_EQ(cache->GetInUseCacheEntriesForTesting(), i + 1u); + EXPECT_TRUE(cache->IsInPersistentCacheForTesting(draw_images[i])); + EXPECT_TRUE(cache->IsInPersistentCacheForTesting(draw_images[i - 1])); + } + + for (int i = 0; i < 10; ++i) { + cache->DrawWithImageFinished(draw_images[i], decoded_draw_images[i]); + } +} + INSTANTIATE_TEST_CASE_P( GpuImageDecodeCacheTests, GpuImageDecodeCacheTest, diff --git a/chromium/cc/tiles/image_decode_cache.h b/chromium/cc/tiles/image_decode_cache.h index 557059ca463..a1653f4708d 100644 --- a/chromium/cc/tiles/image_decode_cache.h +++ b/chromium/cc/tiles/image_decode_cache.h @@ -138,12 +138,6 @@ class CC_EXPORT ImageDecodeCache { // locked budget before creating a task. virtual size_t GetMaximumMemoryLimitBytes() const = 0; - // Indicate to the cache that the image is no longer going - // to be used. This means it can be deleted altogether. If the - // image is locked, then the cache can do its best to clean it - // up later. - virtual void NotifyImageUnused(const PaintImage::FrameKey& frame_key) = 0; - protected: void RecordImageMipLevelUMA(int mip_level); }; diff --git a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc index 278f97b6f4b..c1f7703c5f3 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc +++ b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc @@ -8,14 +8,12 @@ #include <vector> #include "cc/resources/layer_tree_resource_provider.h" -#include "cc/resources/resource_provider.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_picture_layer_tiling_client.h" #include "cc/test/fake_raster_source.h" #include "cc/test/fake_resource_provider.h" #include "cc/trees/layer_tree_settings.h" #include "components/viz/test/fake_output_surface.h" -#include "components/viz/test/test_shared_bitmap_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/size_conversions.h" @@ -248,13 +246,12 @@ class PictureLayerTilingSetTestWithResources : public testing::Test { viz::TestContextProvider::Create(); ASSERT_EQ(context_provider->BindToCurrentThread(), gpu::ContextResult::kSuccess); - auto shared_bitmap_manager = - std::make_unique<viz::TestSharedBitmapManager>(); std::unique_ptr<LayerTreeResourceProvider> resource_provider = FakeResourceProvider::CreateLayerTreeResourceProvider( - context_provider.get(), shared_bitmap_manager.get()); + context_provider.get()); - FakePictureLayerTilingClient client(resource_provider.get()); + FakePictureLayerTilingClient client(resource_provider.get(), + context_provider.get()); client.SetTileSize(gfx::Size(256, 256)); gfx::Size layer_bounds(1000, 800); std::unique_ptr<TestablePictureLayerTilingSet> set = diff --git a/chromium/cc/tiles/software_image_decode_cache.cc b/chromium/cc/tiles/software_image_decode_cache.cc index e566d3a1e1b..6a52e91c066 100644 --- a/chromium/cc/tiles/software_image_decode_cache.cc +++ b/chromium/cc/tiles/software_image_decode_cache.cc @@ -586,31 +586,6 @@ size_t SoftwareImageDecodeCache::GetMaximumMemoryLimitBytes() const { return locked_images_budget_.total_limit_bytes(); } -void SoftwareImageDecodeCache::NotifyImageUnused( - const PaintImage::FrameKey& frame_key) { - base::AutoLock lock(lock_); - - auto it = frame_key_to_image_keys_.find(frame_key); - if (it == frame_key_to_image_keys_.end()) - return; - - for (auto key_it = it->second.begin(); key_it != it->second.end();) { - // This iterates over the CacheKey vector for the given skimage_id, - // and deletes all entries from decoded_images_ corresponding to the - // skimage_id. - auto image_it = decoded_images_.Peek(*key_it); - // TODO(sohanjg): Find an optimized way to cleanup locked images. - if (image_it != decoded_images_.end() && image_it->second->ref_count == 0) { - decoded_images_.Erase(image_it); - key_it = it->second.erase(key_it); - } else { - ++key_it; - } - } - if (it->second.empty()) - frame_key_to_image_keys_.erase(it); -} - void SoftwareImageDecodeCache::OnImageDecodeTaskCompleted( const CacheKey& key, DecodeTaskType task_type) { diff --git a/chromium/cc/tiles/software_image_decode_cache.h b/chromium/cc/tiles/software_image_decode_cache.h index 47d2287f956..0fa379c2b2f 100644 --- a/chromium/cc/tiles/software_image_decode_cache.h +++ b/chromium/cc/tiles/software_image_decode_cache.h @@ -52,7 +52,6 @@ class CC_EXPORT SoftwareImageDecodeCache bool aggressively_free_resources) override {} void ClearCache() override; size_t GetMaximumMemoryLimitBytes() const override; - void NotifyImageUnused(const PaintImage::FrameKey& frame_key) override; // Decode the given image and store it in the cache. This is only called by an // image decode task from a worker thread. diff --git a/chromium/cc/tiles/software_image_decode_cache_unittest.cc b/chromium/cc/tiles/software_image_decode_cache_unittest.cc index 35ba9ae94c1..c9f8c5a55e0 100644 --- a/chromium/cc/tiles/software_image_decode_cache_unittest.cc +++ b/chromium/cc/tiles/software_image_decode_cache_unittest.cc @@ -1584,39 +1584,6 @@ TEST(SoftwareImageDecodeCacheTest, ClearCache) { EXPECT_EQ(0u, cache.GetNumCacheEntriesForTesting()); } -TEST(SoftwareImageDecodeCacheTest, RemoveUnusedImage) { - TestSoftwareImageDecodeCache cache; - bool is_decomposable = true; - SkFilterQuality quality = kHigh_SkFilterQuality; - - std::vector<PaintImage::FrameKey> frame_keys; - - for (int i = 0; i < 10; ++i) { - SCOPED_TRACE(i); - PaintImage paint_image = CreatePaintImage(100, 100); - DrawImage draw_image( - paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), - quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - frame_keys.push_back(draw_image.frame_key()); - ImageDecodeCache::TaskResult result = cache.GetTaskForImageAndRef( - draw_image, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result.need_unref); - EXPECT_TRUE(result.task); - TestTileTaskRunner::ProcessTask(result.task.get()); - cache.UnrefImage(draw_image); - } - - // We should now have data image in our cache. - EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 10u); - - // Remove unused ids. - for (uint32_t i = 0; i < 10; ++i) { - cache.NotifyImageUnused(frame_keys[i]); - EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), (10 - i - 1)); - } -} - TEST(SoftwareImageDecodeCacheTest, CacheDecodesExpectedFrames) { TestSoftwareImageDecodeCache cache; std::vector<FrameMetadata> frames = { @@ -1731,5 +1698,84 @@ TEST(SoftwareImageDecodeCacheTest, EmptyTargetSizeDecode) { cache.DrawWithImageFinished(empty_draw_image, empty_decoded_draw_image); } +TEST(SoftwareImageDecodeCacheTest, BitmapImageColorConverted) { + TestSoftwareImageDecodeCache cache; + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateDisplayP3D65(); + + PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100)); + DrawImage draw_image( + paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), + quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + PaintImage::kDefaultFrameIndex, target_color_space); + + DecodedDrawImage decoded_draw_image = + cache.GetDecodedImageForDraw(draw_image); + EXPECT_TRUE(decoded_draw_image.image()); + // Expect that we allocated a new image. + EXPECT_NE(decoded_draw_image.image().get(), paint_image.GetSkImage().get()); + // Expect that the image color space match the target color space. + EXPECT_TRUE(decoded_draw_image.image()->colorSpace()); + EXPECT_TRUE(SkColorSpace::Equals(decoded_draw_image.image()->colorSpace(), + target_color_space.ToSkColorSpace().get())); + + cache.DrawWithImageFinished(draw_image, decoded_draw_image); +} + +TEST(SoftwareImageDecodeCacheTest, BitmapImageNotColorConverted) { + TestSoftwareImageDecodeCache cache; + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100)); + DrawImage draw_image( + paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), + quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable), + PaintImage::kDefaultFrameIndex, DefaultColorSpace()); + + DecodedDrawImage decoded_draw_image = + cache.GetDecodedImageForDraw(draw_image); + // Expect that we did not allocate a new image. + EXPECT_EQ(decoded_draw_image.image().get(), paint_image.GetSkImage().get()); + + cache.DrawWithImageFinished(draw_image, decoded_draw_image); +} + +// TODO(ccameron): Re-enable this when the root cause of crashes is discovered. +// https://crbug.com/791828 +TEST(SoftwareImageDecodeCacheTest, DISABLED_ContentIdCaching) { + TestSoftwareImageDecodeCache cache; + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + PaintImage::Id stable_id = 1001; + + for (int i = 0; i < 10; ++i) { + // Create several images with the same stable id, but new content ids. + PaintImage paint_image = CreateDiscardablePaintImage( + gfx::Size(100, 100), nullptr, true, stable_id); + + // Cache two entries of different scales. + for (int j = 0; j < 2; ++j) { + float scale = j == 0 ? 1.f : 0.5f; + DrawImage draw_image( + paint_image, + SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality, + CreateMatrix(SkSize::Make(scale, scale), is_decomposable), + PaintImage::kDefaultFrameIndex, DefaultColorSpace()); + DecodedDrawImage decoded_draw_image = + cache.GetDecodedImageForDraw(draw_image); + EXPECT_TRUE(decoded_draw_image.image()); + cache.DrawWithImageFinished(draw_image, decoded_draw_image); + } + + // After the first two entries come in, we start evicting old content ids. + if (i == 0) + EXPECT_LE(cache.GetNumCacheEntriesForTesting(), 2u); + else + EXPECT_LE(cache.GetNumCacheEntriesForTesting(), 4u); + } +} + } // namespace } // namespace cc diff --git a/chromium/cc/tiles/software_image_decode_cache_utils.cc b/chromium/cc/tiles/software_image_decode_cache_utils.cc index 0a051dbe793..4b6016b4126 100644 --- a/chromium/cc/tiles/software_image_decode_cache_utils.cc +++ b/chromium/cc/tiles/software_image_decode_cache_utils.cc @@ -152,6 +152,7 @@ SoftwareImageDecodeCacheUtils::CacheKey::FromDrawImage(const DrawImage& image, DCHECK(!image.paint_image().GetSkImage()->isTextureBacked()); const PaintImage::FrameKey frame_key = image.frame_key(); + const PaintImage::Id stable_id = image.paint_image().stable_id(); const SkSize& scale = image.scale(); // If the src_rect falls outside of the image, we need to clip it since @@ -170,8 +171,8 @@ SoftwareImageDecodeCacheUtils::CacheKey::FromDrawImage(const DrawImage& image, // If the target size is empty, then we'll be skipping the decode anyway, so // the filter quality doesn't matter. Early out instead. if (target_size.IsEmpty()) { - return CacheKey(frame_key, kSubrectAndScale, false, src_rect, target_size, - image.target_color_space()); + return CacheKey(frame_key, stable_id, kSubrectAndScale, false, src_rect, + target_size, image.target_color_space()); } ProcessingType type = kOriginal; @@ -232,18 +233,20 @@ SoftwareImageDecodeCacheUtils::CacheKey::FromDrawImage(const DrawImage& image, } } - return CacheKey(frame_key, type, is_nearest_neighbor, src_rect, target_size, - image.target_color_space()); + return CacheKey(frame_key, stable_id, type, is_nearest_neighbor, src_rect, + target_size, image.target_color_space()); } SoftwareImageDecodeCacheUtils::CacheKey::CacheKey( PaintImage::FrameKey frame_key, + PaintImage::Id stable_id, ProcessingType type, bool is_nearest_neighbor, const gfx::Rect& src_rect, const gfx::Size& target_size, const gfx::ColorSpace& target_color_space) : frame_key_(frame_key), + stable_id_(stable_id), type_(type), is_nearest_neighbor_(is_nearest_neighbor), src_rect_(src_rect), diff --git a/chromium/cc/tiles/software_image_decode_cache_utils.h b/chromium/cc/tiles/software_image_decode_cache_utils.h index 875a8896f3e..7be7315d02d 100644 --- a/chromium/cc/tiles/software_image_decode_cache_utils.h +++ b/chromium/cc/tiles/software_image_decode_cache_utils.h @@ -64,6 +64,7 @@ class SoftwareImageDecodeCacheUtils { bool operator!=(const CacheKey& other) const { return !(*this == other); } const PaintImage::FrameKey& frame_key() const { return frame_key_; } + PaintImage::Id stable_id() const { return stable_id_; } ProcessingType type() const { return type_; } bool is_nearest_neighbor() const { return is_nearest_neighbor_; } gfx::Rect src_rect() const { return src_rect_; } @@ -88,6 +89,7 @@ class SoftwareImageDecodeCacheUtils { private: CacheKey(PaintImage::FrameKey frame_key, + PaintImage::Id stable_id, ProcessingType type, bool is_nearest_neighbor, const gfx::Rect& src_rect, @@ -95,6 +97,10 @@ class SoftwareImageDecodeCacheUtils { const gfx::ColorSpace& target_color_space); PaintImage::FrameKey frame_key_; + // The stable id is does not factor into the cache key's value for hashing + // and comparison (as it is redundant). It is only used to look up other + // cache entries of the same stable id. + PaintImage::Id stable_id_; ProcessingType type_; bool is_nearest_neighbor_; gfx::Rect src_rect_; diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc index 33324a69a7f..dfebdf4cab6 100644 --- a/chromium/cc/tiles/tile_manager.cc +++ b/chromium/cc/tiles/tile_manager.cc @@ -359,6 +359,7 @@ TileManager::TileManager( did_oom_on_last_assign_(false), image_controller_(origin_task_runner, std::move(image_worker_task_runner)), + decoded_image_tracker_(&image_controller_), checker_image_tracker_(&image_controller_, this, tile_manager_settings_.enable_checker_imaging, @@ -1267,10 +1268,8 @@ void TileManager::OnRasterTaskCompleted( } TileDrawInfo& draw_info = tile->draw_info(); - bool needs_swizzle = - raster_buffer_provider_->IsResourceSwizzleRequired(!tile->is_opaque()); - bool is_premultiplied = - raster_buffer_provider_->IsResourcePremultiplied(!tile->is_opaque()); + bool needs_swizzle = raster_buffer_provider_->IsResourceSwizzleRequired(); + bool is_premultiplied = raster_buffer_provider_->IsResourcePremultiplied(); draw_info.SetResource(std::move(resource), raster_task_was_scheduled_with_checker_images, needs_swizzle, is_premultiplied); @@ -1285,13 +1284,6 @@ void TileManager::OnRasterTaskCompleted( } } -void TileManager::SetDecodedImageTracker( - DecodedImageTracker* decoded_image_tracker) { - // TODO(vmpstr): If the tile manager needs to request out-of-raster decodes, - // it should retain and use |decoded_image_tracker| here. - decoded_image_tracker->set_image_controller(&image_controller_); -} - std::unique_ptr<Tile> TileManager::CreateTile(const Tile::CreateInfo& info, int layer_id, int source_frame_number, @@ -1519,7 +1511,7 @@ void TileManager::NeedsInvalidationForCheckerImagedTiles() { viz::ResourceFormat TileManager::DetermineResourceFormat( const Tile* tile) const { - return raster_buffer_provider_->GetResourceFormat(!tile->is_opaque()); + return raster_buffer_provider_->GetResourceFormat(); } std::unique_ptr<base::trace_event::ConvertableToTraceFormat> @@ -1558,6 +1550,11 @@ void TileManager::CheckPendingGpuWorkAndIssueSignals() { const ResourcePool::InUsePoolResource& resource = tile->draw_info().GetResource(); + // Update requirements first so that if the tile has become required + // it will force a redraw. + if (pending_tile_requirements_dirty_) + tile->tiling()->UpdateRequiredStatesOnTile(tile); + if (global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY || raster_buffer_provider_->IsResourceReadyToDraw(resource)) { tile->draw_info().set_resource_ready_for_draw(); @@ -1569,8 +1566,6 @@ void TileManager::CheckPendingGpuWorkAndIssueSignals() { // TODO(ericrk): If a tile in our list no longer has valid tile priorities, // it may still report that it is required, and unnecessarily delay // activation. crbug.com/687265 - if (pending_tile_requirements_dirty_) - tile->tiling()->UpdateRequiredStatesOnTile(tile); if (tile->required_for_activation()) required_for_activation.push_back(&resource); if (tile->required_for_draw()) diff --git a/chromium/cc/tiles/tile_manager.h b/chromium/cc/tiles/tile_manager.h index 32e9a1ea563..2b79c939ada 100644 --- a/chromium/cc/tiles/tile_manager.h +++ b/chromium/cc/tiles/tile_manager.h @@ -194,7 +194,7 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { ResourcePool::InUsePoolResource resource = resource_pool_->AcquireResource( tiles[i]->desired_texture_size(), - raster_buffer_provider_->GetResourceFormat(false), + raster_buffer_provider_->GetResourceFormat(), client_->GetRasterColorSpace().color_space); raster_buffer_provider_->AcquireBufferForRaster(resource, 0, 0); // The raster here never really happened, cuz tests. So just add an @@ -260,8 +260,6 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { ResourcePool::InUsePoolResource resource, bool was_canceled); - void SetDecodedImageTracker(DecodedImageTracker* decoded_image_tracker); - // CheckerImageTrackerClient implementation. void NeedsInvalidationForCheckerImagedTiles() override; @@ -278,6 +276,9 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { CheckerImageTracker& checker_image_tracker() { return checker_image_tracker_; } + DecodedImageTracker& decoded_image_tracker() { + return decoded_image_tracker_; + } const std::vector<DrawImage>& decode_tasks_for_testing(Tile::Id id) { return scheduled_draw_images_[id]; @@ -414,6 +415,7 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { bool did_oom_on_last_assign_; ImageController image_controller_; + DecodedImageTracker decoded_image_tracker_; CheckerImageTracker checker_image_tracker_; RasterTaskCompletionStats raster_task_completion_stats_; diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc index 8c9a5f4f19a..9c437b15b86 100644 --- a/chromium/cc/tiles/tile_manager_unittest.cc +++ b/chromium/cc/tiles/tile_manager_unittest.cc @@ -1365,8 +1365,6 @@ TEST_F(TileManagerTilePriorityQueueTest, EXPECT_FALSE(queue->IsEmpty()); EXPECT_TRUE(queue->Top().tile()->required_for_draw()); EXPECT_EQ(gfx::Size(256, 256), queue->Top().tile()->desired_texture_size()); - EXPECT_EQ(viz::RGBA_8888, - host_impl()->resource_provider()->best_texture_format()); ManagedMemoryPolicy policy = host_impl()->ActualManagedMemoryPolicy(); policy.bytes_limit_when_visible = @@ -1570,7 +1568,7 @@ class TestSoftwareRasterBufferProvider : public FakeRasterBufferProviderImpl { RasterBufferProvider::PlaybackToMemory( pixels_, viz::RGBA_8888, size_, /*stride=*/0, raster_source, raster_full_rect, /*playback_rect=*/raster_full_rect, transform, - gfx::ColorSpace(), playback_settings); + gfx::ColorSpace(), /*gpu_compositing=*/true, playback_settings); } private: @@ -1723,6 +1721,11 @@ TEST_F(TileManagerTest, ActivateAndDrawWhenOOM) { class PixelInspectTileManagerTest : public TileManagerTest { public: + ~PixelInspectTileManagerTest() override { + // Ensure that the host impl doesn't outlive |raster_buffer_provider_|. + TakeHostImpl(); + } + void SetUp() override { TileManagerTest::SetUp(); // Use a RasterBufferProvider that will let us inspect pixels. @@ -2291,7 +2294,6 @@ TEST_F(TileManagerReadyToDrawTest, SmoothActivationWaitsOnCallback) { run_loop.Quit(); return 1; })); - host_impl()->tile_manager()->DidModifyTilePriorities(); host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); run_loop.Run(); } @@ -2321,7 +2323,6 @@ TEST_F(TileManagerReadyToDrawTest, NonSmoothActivationDoesNotWaitOnCallback) { // will cause a test failure. base::RunLoop run_loop; - host_impl()->tile_manager()->DidModifyTilePriorities(); host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); EXPECT_CALL(MockHostImpl(), NotifyReadyToActivate()) .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); })); @@ -2356,7 +2357,6 @@ TEST_F(TileManagerReadyToDrawTest, SmoothDrawWaitsOnCallback) { run_loop.Quit(); return 1; })); - host_impl()->tile_manager()->DidModifyTilePriorities(); host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); run_loop.Run(); } @@ -2386,7 +2386,6 @@ TEST_F(TileManagerReadyToDrawTest, NonSmoothDrawDoesNotWaitOnCallback) { // will cause a test failure. base::RunLoop run_loop; - host_impl()->tile_manager()->DidModifyTilePriorities(); host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); EXPECT_CALL(MockHostImpl(), NotifyReadyToDraw()) .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); })); @@ -2401,7 +2400,6 @@ TEST_F(TileManagerReadyToDrawTest, NoCallbackWhenAlreadyReadyToDraw) { SetupTreesWithPendingTreeTiles(); base::RunLoop run_loop; - host_impl()->tile_manager()->DidModifyTilePriorities(); host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); EXPECT_CALL(MockHostImpl(), NotifyReadyToActivate()) .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); })); @@ -2413,6 +2411,92 @@ TEST_F(TileManagerReadyToDrawTest, NoCallbackWhenAlreadyReadyToDraw) { EXPECT_TRUE(host_impl()->tile_manager()->IsReadyToActivate()); } +TEST_F(TileManagerReadyToDrawTest, TilePrioritiesUpdated) { + // Use smoothness as that's a mode in which we wait on resources to be + // ready instead of marking them ready immediately. + host_impl()->SetTreePriority(SMOOTHNESS_TAKES_PRIORITY); + gfx::Size very_small(1, 1); + host_impl()->SetViewportSize(very_small); + + gfx::Size layer_bounds(1000, 1000); + SetupDefaultTrees(layer_bounds); + + // Run until all tile tasks are complete, but don't let any draw callbacks + // finish. + { + base::RunLoop run_loop; + EXPECT_CALL(MockHostImpl(), NotifyAllTileTasksCompleted()) + .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); })); + + // Until we activate our ready to draw callback, treat all resources as not + // ready to draw. + EXPECT_CALL(*mock_raster_buffer_provider(), + IsResourceReadyToDraw(testing::_)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*mock_raster_buffer_provider(), SetReadyToDrawCallback(_, _, _)) + .WillRepeatedly(Return(1)); + host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); + run_loop.Run(); + } + + // Inspect the current state of tiles in this world of cpu done but gpu + // not ready yet. + size_t orig_num_required = 0; + size_t orig_num_prepaint = 0; + std::vector<Tile*> prepaint_tiles; + for (auto* tile : host_impl()->tile_manager()->AllTilesForTesting()) { + if (tile->draw_info().has_resource()) { + if (tile->is_prepaint()) { + orig_num_prepaint++; + prepaint_tiles.push_back(tile); + } else { + orig_num_required++; + } + } + } + + // Verify that there exist some prepaint tiles here. + EXPECT_GT(orig_num_prepaint, 0u); + EXPECT_GT(orig_num_required, 0u); + + host_impl()->SetViewportSize(layer_bounds); + host_impl()->active_tree()->UpdateDrawProperties(); + host_impl()->pending_tree()->UpdateDrawProperties(); + + // Rerun prepare tiles. + { + base::RunLoop run_loop; + EXPECT_CALL(MockHostImpl(), NotifyAllTileTasksCompleted()) + .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); })); + host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); + run_loop.Run(); + } + + // Make sure tiles priorities are updated. + size_t final_num_required = 0; + size_t final_num_prepaint = 0; + bool found_one_prepaint_to_required_transition = false; + for (auto* tile : host_impl()->tile_manager()->AllTilesForTesting()) { + if (tile->draw_info().has_resource()) { + if (tile->is_prepaint()) { + final_num_prepaint++; + } else { + final_num_required++; + if (std::find(prepaint_tiles.begin(), prepaint_tiles.end(), tile) != + prepaint_tiles.end()) { + found_one_prepaint_to_required_transition = true; + } + } + } + } + + // Tile priorities should be updated and we should have more required + // and fewer prepaint now that the viewport has changed. + EXPECT_GT(final_num_required, orig_num_required); + EXPECT_LT(final_num_prepaint, orig_num_prepaint); + EXPECT_TRUE(found_one_prepaint_to_required_transition); +} + void UpdateVisibleRect(FakePictureLayerImpl* layer, const gfx::Rect visible_rect) { PictureLayerTilingSet* tiling_set = layer->tilings(); @@ -2495,6 +2579,13 @@ TEST_F(TileManagerReadyToDrawTest, ReadyToDrawRespectsRequirementChange) { EXPECT_TRUE(host_impl()->tile_manager()->IsReadyToActivate()); } +PaintImage MakeCheckerablePaintImage(const gfx::Size& size) { + auto image = CreateDiscardablePaintImage(size); + return PaintImageBuilder::WithCopy(image) + .set_decoding_mode(PaintImage::DecodingMode::kAsync) + .TakePaintImage(); +} + class CheckerImagingTileManagerTest : public TestLayerTreeHostBase { public: class MockImageGenerator : public FakePaintImageGenerator { @@ -2554,7 +2645,6 @@ class CheckerImagingTileManagerTest : public TestLayerTreeHostBase { TEST_F(CheckerImagingTileManagerTest, NoImageDecodeDependencyForCheckeredTiles) { const gfx::Size layer_bounds(512, 512); - SetupDefaultTrees(layer_bounds); std::unique_ptr<FakeRecordingSource> recording_source = FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); @@ -2565,6 +2655,7 @@ TEST_F(CheckerImagingTileManagerTest, PaintImage image = PaintImageBuilder::WithDefault() .set_id(PaintImage::GetNextId()) .set_paint_image_generator(generator) + .set_decoding_mode(PaintImage::DecodingMode::kAsync) .TakePaintImage(); recording_source->add_draw_image(image, gfx::Point(0, 0)); @@ -2572,13 +2663,12 @@ TEST_F(CheckerImagingTileManagerTest, scoped_refptr<RasterSource> raster_source = recording_source->CreateRasterSource(); - std::unique_ptr<PictureLayerImpl> layer_impl = PictureLayerImpl::Create( - host_impl()->pending_tree(), 1, Layer::LayerMaskType::NOT_MASK); - layer_impl->set_contributes_to_drawn_render_surface(true); - PictureLayerTilingSet* tiling_set = layer_impl->picture_layer_tiling_set(); + Region invalidation((gfx::Rect(layer_bounds))); + SetupPendingTree(raster_source, layer_bounds, invalidation); - PictureLayerTiling* tiling = - tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); + PictureLayerTilingSet* tiling_set = + pending_layer()->picture_layer_tiling_set(); + PictureLayerTiling* tiling = tiling_set->tiling_at(0); tiling->set_resolution(HIGH_RESOLUTION); tiling->CreateAllTilesForTesting(); tiling->SetTilePriorityRectsForTesting( @@ -2615,8 +2705,7 @@ TEST_F(EmptyCacheTileManagerTest, AtRasterOnScreenTileRasterTasks) { recording_source->set_fill_with_nonsolid_color(true); int dimension = 500; - PaintImage image = - CreateDiscardablePaintImage(gfx::Size(dimension, dimension)); + PaintImage image = MakeCheckerablePaintImage(gfx::Size(dimension, dimension)); recording_source->add_draw_image(image, gfx::Point(0, 0)); recording_source->Rerecord(); @@ -2652,8 +2741,7 @@ TEST_F(EmptyCacheTileManagerTest, AtRasterPrepaintTileRasterTasksSkipped) { recording_source->set_fill_with_nonsolid_color(true); int dimension = 500; - PaintImage image = - CreateDiscardablePaintImage(gfx::Size(dimension, dimension)); + PaintImage image = MakeCheckerablePaintImage(gfx::Size(dimension, dimension)); recording_source->add_draw_image(image, gfx::Point(0, 0)); recording_source->Rerecord(); @@ -2690,11 +2778,11 @@ TEST_F(CheckerImagingTileManagerTest, BuildsImageDecodeQueueAsExpected) { int dimension = 450; PaintImage image1 = - CreateDiscardablePaintImage(gfx::Size(dimension, dimension)); + MakeCheckerablePaintImage(gfx::Size(dimension, dimension)); PaintImage image2 = - CreateDiscardablePaintImage(gfx::Size(dimension, dimension)); + MakeCheckerablePaintImage(gfx::Size(dimension, dimension)); PaintImage image3 = - CreateDiscardablePaintImage(gfx::Size(dimension, dimension)); + MakeCheckerablePaintImage(gfx::Size(dimension, dimension)); recording_source->add_draw_image(image1, gfx::Point(0, 0)); recording_source->add_draw_image(image2, gfx::Point(600, 0)); recording_source->add_draw_image(image3, gfx::Point(0, 600)); @@ -2851,7 +2939,7 @@ TEST_F(CheckerImagingTileManagerTest, std::unique_ptr<FakeRecordingSource> recording_source = FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); recording_source->set_fill_with_nonsolid_color(true); - PaintImage image = CreateDiscardablePaintImage(gfx::Size(512, 512)); + PaintImage image = MakeCheckerablePaintImage(gfx::Size(512, 512)); recording_source->add_draw_image(image, gfx::Point(0, 0)); recording_source->Rerecord(); scoped_refptr<RasterSource> raster_source = @@ -2890,7 +2978,7 @@ TEST_F(CheckerImagingTileManagerTest, std::unique_ptr<FakeRecordingSource> recording_source = FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); recording_source->set_fill_with_nonsolid_color(true); - PaintImage image = CreateDiscardablePaintImage(gfx::Size(512, 512)); + PaintImage image = MakeCheckerablePaintImage(gfx::Size(512, 512)); recording_source->add_draw_image(image, gfx::Point(0, 0)); recording_source->Rerecord(); scoped_refptr<RasterSource> raster_source = @@ -2975,9 +3063,9 @@ TEST_F(CheckerImagingTileManagerMemoryTest, AddsAllNowTilesToImageDecodeQueue) { int dimension = 450; PaintImage image1 = - CreateDiscardablePaintImage(gfx::Size(dimension, dimension)); + MakeCheckerablePaintImage(gfx::Size(dimension, dimension)); PaintImage image2 = - CreateDiscardablePaintImage(gfx::Size(dimension, dimension)); + MakeCheckerablePaintImage(gfx::Size(dimension, dimension)); recording_source->add_draw_image(image1, gfx::Point(0, 515)); recording_source->add_draw_image(image2, gfx::Point(515, 515)); diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc index d3c1958a13c..b888d085203 100644 --- a/chromium/cc/trees/draw_property_utils.cc +++ b/chromium/cc/trees/draw_property_utils.cc @@ -506,11 +506,12 @@ static void UpdatePageScaleFactorInternal(PropertyTrees* property_trees, float page_scale_factor, float device_scale_factor, gfx::Transform device_transform) { - if (property_trees->transform_tree.page_scale_factor() == page_scale_factor) + if (property_trees->transform_tree.page_scale_factor() == page_scale_factor || + !page_scale_layer) { 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( @@ -648,7 +649,7 @@ static void SetSurfaceDrawTransform(const PropertyTrees* property_trees, 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) { + if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) { render_surface->SetDrawTransform(gfx::Transform()); return; } @@ -1004,7 +1005,7 @@ void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, } void ComputeMaskDrawProperties(LayerImpl* mask_layer, - const PropertyTrees* property_trees) { + 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. @@ -1016,8 +1017,17 @@ void ComputeMaskDrawProperties(LayerImpl* mask_layer, mask_layer->draw_properties().screen_space_transform = ScreenSpaceTransformInternal(mask_layer, property_trees->transform_tree); + + ConditionalClip clip = LayerClipRect(property_trees, mask_layer); + // is_clipped should be set before visible rect computation as it is used + // there. + mask_layer->draw_properties().is_clipped = clip.is_clipped; + mask_layer->draw_properties().clip_rect = + gfx::ToEnclosingRect(clip.clip_rect); + // Calculate actual visible layer rect for mask layers, since we could have + // tiled mask layers and the tile manager would need this info for rastering. mask_layer->draw_properties().visible_layer_rect = - gfx::Rect(mask_layer->bounds()); + LayerVisibleRect(property_trees, mask_layer); mask_layer->draw_properties().opacity = 1; } diff --git a/chromium/cc/trees/draw_property_utils.h b/chromium/cc/trees/draw_property_utils.h index 45ed01f6e88..6c843521df6 100644 --- a/chromium/cc/trees/draw_property_utils.h +++ b/chromium/cc/trees/draw_property_utils.h @@ -59,7 +59,7 @@ ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, PropertyTrees* property_trees); void CC_EXPORT ComputeMaskDrawProperties(LayerImpl* mask_layer, - const PropertyTrees* property_trees); + PropertyTrees* property_trees); void CC_EXPORT ComputeSurfaceDrawProperties(PropertyTrees* property_trees, RenderSurfaceImpl* render_surface); diff --git a/chromium/cc/trees/latency_info_swap_promise.cc b/chromium/cc/trees/latency_info_swap_promise.cc index 6ebf5352014..9b376030ed5 100644 --- a/chromium/cc/trees/latency_info_swap_promise.cc +++ b/chromium/cc/trees/latency_info_swap_promise.cc @@ -44,8 +44,7 @@ void LatencyInfoSwapPromise::DidSwap() {} SwapPromise::DidNotSwapAction LatencyInfoSwapPromise::DidNotSwap( DidNotSwapReason reason) { - latency_.AddLatencyNumber(DidNotSwapReasonToLatencyComponentType(reason), 0, - 0); + latency_.AddLatencyNumber(DidNotSwapReasonToLatencyComponentType(reason), 0); // TODO(miletus): Turn this back on once per-event LatencyInfo tracking // is enabled in GPU side. // DCHECK(latency_.terminated); diff --git a/chromium/cc/trees/latency_info_swap_promise_monitor.cc b/chromium/cc/trees/latency_info_swap_promise_monitor.cc index 7bca0d6ebf0..99ec2c686a4 100644 --- a/chromium/cc/trees/latency_info_swap_promise_monitor.cc +++ b/chromium/cc/trees/latency_info_swap_promise_monitor.cc @@ -21,7 +21,7 @@ bool AddRenderingScheduledComponent(ui::LatencyInfo* latency_info, : ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT; if (latency_info->FindLatency(type, 0, nullptr)) return false; - latency_info->AddLatencyNumber(type, 0, 0); + latency_info->AddLatencyNumber(type, 0); return true; } @@ -31,8 +31,7 @@ bool AddForwardingScrollUpdateToMainComponent(ui::LatencyInfo* latency_info) { nullptr)) return false; latency_info->AddLatencyNumber( - ui::INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT, 0, - latency_info->trace_id()); + ui::INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT, 0); return true; } @@ -70,29 +69,13 @@ void LatencyInfoSwapPromiseMonitor::OnSetNeedsRedrawOnImpl() { void LatencyInfoSwapPromiseMonitor::OnForwardScrollUpdateToMainThreadOnImpl() { if (AddForwardingScrollUpdateToMainComponent(latency_)) { - int64_t new_sequence_number = 0; - for (ui::LatencyInfo::LatencyMap::const_iterator it = - latency_->latency_components().begin(); - it != latency_->latency_components().end(); ++it) { - if (it->first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT) { - new_sequence_number = - ((static_cast<int64_t>(base::PlatformThread::CurrentId()) << 32) ^ - (reinterpret_cast<uint64_t>(this) << 32)) | - (it->second.sequence_number & 0xffffffff); - if (new_sequence_number == it->second.sequence_number) - return; - break; - } - } - if (!new_sequence_number) - return; ui::LatencyInfo new_latency; new_latency.CopyLatencyFrom( *latency_, ui::INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT); new_latency.AddLatencyNumberWithTraceName( ui::LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT, 0, - new_sequence_number, "ScrollUpdate"); + "ScrollUpdate"); std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(new_latency)); host_impl_->QueueSwapPromiseForMainThreadScrollUpdate( diff --git a/chromium/cc/trees/layer_tree_frame_sink.cc b/chromium/cc/trees/layer_tree_frame_sink.cc index 5a1fb748c7b..e1a1b803b72 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.cc +++ b/chromium/cc/trees/layer_tree_frame_sink.cc @@ -43,13 +43,11 @@ LayerTreeFrameSink::LayerTreeFrameSink( scoped_refptr<viz::ContextProvider> context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider, scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - viz::SharedBitmapManager* shared_bitmap_manager) + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) : context_provider_(std::move(context_provider)), worker_context_provider_(std::move(worker_context_provider)), compositor_task_runner_(std::move(compositor_task_runner)), gpu_memory_buffer_manager_(gpu_memory_buffer_manager), - shared_bitmap_manager_(shared_bitmap_manager), weak_ptr_factory_(this) { DETACH_FROM_THREAD(thread_checker_); } diff --git a/chromium/cc/trees/layer_tree_frame_sink.h b/chromium/cc/trees/layer_tree_frame_sink.h index f61c7a6c019..7f550dc9fe8 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.h +++ b/chromium/cc/trees/layer_tree_frame_sink.h @@ -11,15 +11,15 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" #include "cc/cc_export.h" #include "components/viz/common/gpu/context_lost_observer.h" #include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/gpu/raster_context_provider.h" -#include "components/viz/common/quads/shared_bitmap.h" #include "components/viz/common/resources/returned_resource.h" +#include "components/viz/common/resources/shared_bitmap_reporter.h" #include "gpu/command_buffer/common/texture_in_use_response.h" -#include "mojo/public/cpp/system/buffer.h" #include "ui/gfx/color_space.h" namespace gpu { @@ -29,21 +29,20 @@ class GpuMemoryBufferManager; namespace viz { class CompositorFrame; class LocalSurfaceId; -class SharedBitmapManager; struct BeginFrameAck; } // namespace viz namespace cc { class LayerTreeFrameSinkClient; -class LayerTreeHostImpl; // An interface for submitting CompositorFrames to a display compositor // which will compose frames from multiple clients to show on screen to the // user. // If a context_provider() is present, frames should be submitted with // OpenGL resources (created with the context_provider()). If not, then -// SharedBitmap resources should be used. -class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { +// SharedMemory resources should be used. +class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, + public viz::ContextLostObserver { public: struct Capabilities { Capabilities() = default; @@ -74,8 +73,7 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { scoped_refptr<viz::ContextProvider> context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider, scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - viz::SharedBitmapManager* shared_bitmap_manager); + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); ~LayerTreeFrameSink() override; @@ -101,7 +99,7 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { const Capabilities& capabilities() const { return capabilities_; } // The viz::ContextProviders may be null if frames should be submitted with - // software SharedBitmap resources. + // software SharedMemory resources. viz::ContextProvider* context_provider() const { return context_provider_.get(); } @@ -111,13 +109,6 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() const { return gpu_memory_buffer_manager_; } - viz::SharedBitmapManager* shared_bitmap_manager() const { - return shared_bitmap_manager_; - } - - // Generate hit test region list based on LayerTreeHostImpl, the data will be - // submitted with compositor frame. - virtual void UpdateHitTestData(const LayerTreeHostImpl* host_impl) {} // If supported, this sets the viz::LocalSurfaceId the LayerTreeFrameSink will // use to submit a CompositorFrame. @@ -137,13 +128,10 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { // the client did not lead to a CompositorFrame submission. virtual void DidNotProduceFrame(const viz::BeginFrameAck& ack) = 0; - // Associates a SharedBitmapId with a shared buffer handle. - virtual void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, - const viz::SharedBitmapId& id) = 0; - - // Disassociates a SharedBitmapId previously passed to - // DidAllocateSharedBitmap. - virtual void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) = 0; + // viz::SharedBitmapReporter implementation. + void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + const viz::SharedBitmapId& id) override = 0; + void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override = 0; protected: class ContextLostForwarder; @@ -158,7 +146,6 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { scoped_refptr<viz::RasterContextProvider> worker_context_provider_; scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; - viz::SharedBitmapManager* shared_bitmap_manager_; std::unique_ptr<ContextLostForwarder> worker_context_lost_forwarder_; diff --git a/chromium/cc/trees/layer_tree_frame_sink_client.h b/chromium/cc/trees/layer_tree_frame_sink_client.h index a463b770007..d774db56e35 100644 --- a/chromium/cc/trees/layer_tree_frame_sink_client.h +++ b/chromium/cc/trees/layer_tree_frame_sink_client.h @@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "components/viz/common/resources/returned_resource.h" @@ -19,6 +20,7 @@ class Transform; namespace viz { class BeginFrameSource; +struct HitTestRegionList; } namespace cc { @@ -32,6 +34,12 @@ class CC_EXPORT LayerTreeFrameSinkClient { // binding to the client and then call again with a null while detaching. virtual void SetBeginFrameSource(viz::BeginFrameSource* source) = 0; + // Builds and returns a HitTestRegionList from the active LayerTreeImpl. To be + // called during SubmitCompositorFrame(). + // TODO(danakj): Just pass it into SubmitCompositorFrame(), with a + // LayerTreeSetting to enable it or not. + virtual base::Optional<viz::HitTestRegionList> BuildHitTestData() = 0; + // Returns resources sent to SubmitCompositorFrame to be reused or freed. virtual void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) = 0; diff --git a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc index 8ac72b45da5..781effb7740 100644 --- a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc +++ b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc @@ -4,6 +4,7 @@ #include "cc/trees/layer_tree_frame_sink.h" +#include "base/single_thread_task_runner.h" #include "base/test/test_simple_task_runner.h" #include "cc/test/fake_layer_tree_frame_sink_client.h" #include "components/viz/common/quads/compositor_frame.h" @@ -25,7 +26,6 @@ class StubLayerTreeFrameSink : public LayerTreeFrameSink { : LayerTreeFrameSink(std::move(context_provider), std::move(worker_context_provider), std::move(compositor_task_runner), - nullptr, nullptr) {} void SubmitCompositorFrame(viz::CompositorFrame frame) override { diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index d8bf091317a..b47182219c0 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -159,7 +159,7 @@ void LayerTreeHost::SetUIResourceManagerForTesting( } void LayerTreeHost::InitializeProxy(std::unique_ptr<Proxy> proxy) { - TRACE_EVENT0("cc", "LayerTreeHostInProcess::InitializeForReal"); + TRACE_EVENT0("cc", "LayerTreeHost::InitializeForReal"); DCHECK(task_runner_provider_); proxy_ = std::move(proxy); @@ -174,7 +174,7 @@ LayerTreeHost::~LayerTreeHost() { // Track when we're inside a main frame to see if compositor is being // destroyed midway which causes a crash. crbug.com/654672 DCHECK(!inside_main_frame_); - TRACE_EVENT0("cc", "LayerTreeHostInProcess::~LayerTreeHostInProcess"); + TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost"); // Clear any references into the LayerTreeHost. mutator_host_->SetMutatorHostClient(nullptr); @@ -280,25 +280,12 @@ void LayerTreeHost::RequestMainFrameUpdate(VisualStateUpdate requested_update) { // This function commits the LayerTreeHost to an impl tree. When modifying // this function, keep in mind that the function *runs* on the impl thread! Any // code that is logically a main thread operation, e.g. deletion of a Layer, -// should be delayed until the LayerTreeHostInProcess::CommitComplete, which -// will run after the commit, but on the main thread. +// should be delayed until the LayerTreeHost::CommitComplete, which will run +// after the commit, but on the main thread. void LayerTreeHost::FinishCommitOnImplThread( LayerTreeHostImpl* host_impl) { DCHECK(task_runner_provider_->IsImplThread()); - bool is_new_trace; - TRACE_EVENT_IS_NEW_TRACE(&is_new_trace); - if (is_new_trace && - frame_viewer_instrumentation::IsTracingLayerTreeSnapshots() && - root_layer()) { - // We'll be dumping layer trees as part of trace, so make sure - // PushPropertiesTo() propagates layer debug info to the impl side -- - // otherwise this won't happen for the layers that remain unchanged since - // tracing started. - LayerTreeHostCommon::CallFunctionForEveryLayer( - this, [](Layer* layer) { layer->SetNeedsPushProperties(); }); - } - LayerTreeImpl* sync_tree = host_impl->sync_tree(); sync_tree->lifecycle().AdvanceTo(LayerTreeLifecycle::kBeginningSync); @@ -341,7 +328,7 @@ void LayerTreeHost::FinishCommitOnImplThread( } { - TRACE_EVENT0("cc", "LayerTreeHostInProcess::PushProperties"); + TRACE_EVENT0("cc", "LayerTreeHost::PushProperties"); PushPropertyTreesTo(sync_tree); sync_tree->lifecycle().AdvanceTo(LayerTreeLifecycle::kSyncedPropertyTrees); @@ -377,7 +364,7 @@ void LayerTreeHost::FinishCommitOnImplThread( // TODO(pdr): Enforce this comment with DCHECKS and a lifecycle state. sync_tree->UpdatePropertyTreeAnimationFromMainThread(); - TRACE_EVENT0("cc", "LayerTreeHostInProcess::AnimationHost::PushProperties"); + TRACE_EVENT0("cc", "LayerTreeHost::AnimationHost::PushProperties"); DCHECK(host_impl->mutator_host()); mutator_host_->PushPropertiesTo(host_impl->mutator_host()); @@ -427,13 +414,29 @@ void LayerTreeHost::PushPropertyTreesTo(LayerTreeImpl* tree_impl) { void LayerTreeHost::WillCommit() { swap_promise_manager_.WillCommit(); client_->WillCommit(); + + if (frame_viewer_instrumentation::IsTracingLayerTreeSnapshots()) { + bool is_new_trace; + TRACE_EVENT_IS_NEW_TRACE(&is_new_trace); + if (is_new_trace) { + // We'll be dumping layer trees as part of trace, so make sure + // PushPropertiesTo() propagates layer debug info to the impl side -- + // otherwise this won't happen for the layers that remain unchanged since + // tracing started. + LayerTreeHostCommon::CallFunctionForEveryLayer( + this, [](Layer* layer) { layer->SetNeedsPushProperties(); }); + } + + for (Layer* layer : LayersThatShouldPushProperties()) + layer->UpdateDebugInfo(); + } } void LayerTreeHost::UpdateDeferCommitsInternal() { proxy_->SetDeferCommits(defer_commits_ || (settings_.enable_surface_synchronization && - !local_surface_id_.is_valid())); + !local_surface_id_from_parent_.is_valid())); } bool LayerTreeHost::IsUsingLayerLists() const { @@ -451,7 +454,7 @@ void LayerTreeHost::CommitComplete() { void LayerTreeHost::SetLayerTreeFrameSink( std::unique_ptr<LayerTreeFrameSink> surface) { - TRACE_EVENT0("cc", "LayerTreeHostInProcess::SetLayerTreeFrameSink"); + TRACE_EVENT0("cc", "LayerTreeHost::SetLayerTreeFrameSink"); DCHECK(surface); DCHECK(!new_layer_tree_frame_sink_); @@ -514,7 +517,7 @@ LayerTreeHost::CreateLayerTreeHostImpl( } void LayerTreeHost::DidLoseLayerTreeFrameSink() { - TRACE_EVENT0("cc", "LayerTreeHostInProcess::DidLoseLayerTreeFrameSink"); + TRACE_EVENT0("cc", "LayerTreeHost::DidLoseLayerTreeFrameSink"); DCHECK(task_runner_provider_->IsMainThread()); SetNeedsCommit(); } @@ -598,9 +601,9 @@ void LayerTreeHost::SetHasGpuRasterizationTrigger(bool has_trigger) { return; has_gpu_rasterization_trigger_ = has_trigger; - TRACE_EVENT_INSTANT1( - "cc", "LayerTreeHostInProcess::SetHasGpuRasterizationTrigger", - TRACE_EVENT_SCOPE_THREAD, "has_trigger", has_gpu_rasterization_trigger_); + TRACE_EVENT_INSTANT1("cc", "LayerTreeHost::SetHasGpuRasterizationTrigger", + TRACE_EVENT_SCOPE_THREAD, "has_trigger", + has_gpu_rasterization_trigger_); } void LayerTreeHost::ApplyPageScaleDeltaFromImplSide( @@ -745,8 +748,8 @@ void LayerTreeHost::RecordGpuRasterizationHistogram( } bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { - TRACE_EVENT1("cc", "LayerTreeHostInProcess::DoUpdateLayers", - "source_frame_number", SourceFrameNumber()); + TRACE_EVENT1("cc", "LayerTreeHost::DoUpdateLayers", "source_frame_number", + SourceFrameNumber()); UpdateHudLayer(debug_state_.ShowHudInfo()); @@ -777,11 +780,9 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { { base::AutoReset<bool> update_property_trees(&in_update_property_trees_, true); - TRACE_EVENT0("cc", - "LayerTreeHostInProcess::UpdateLayers::BuildPropertyTrees"); - TRACE_EVENT0( - TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), - "LayerTreeHostInProcessCommon::ComputeVisibleRectsWithPropertyTrees"); + TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::BuildPropertyTrees"); + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), + "LayerTreeHostCommon::ComputeVisibleRectsWithPropertyTrees"); PropertyTrees* property_trees = &property_trees_; if (!IsUsingLayerLists()) { // In SPv2 the property trees should have been built by the @@ -791,15 +792,15 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { outer_viewport_scroll_layer(), overscroll_elasticity_layer(), elastic_overscroll_, page_scale_factor_, device_scale_factor_, gfx::Rect(device_viewport_size_), identity_transform, property_trees); - TRACE_EVENT_INSTANT1( - "cc", "LayerTreeHostInProcess::UpdateLayers_BuiltPropertyTrees", - TRACE_EVENT_SCOPE_THREAD, "property_trees", - property_trees->AsTracedValue()); + TRACE_EVENT_INSTANT1("cc", + "LayerTreeHost::UpdateLayers_BuiltPropertyTrees", + TRACE_EVENT_SCOPE_THREAD, "property_trees", + property_trees->AsTracedValue()); } else { - TRACE_EVENT_INSTANT1( - "cc", "LayerTreeHostInProcess::UpdateLayers_ReceivedPropertyTrees", - TRACE_EVENT_SCOPE_THREAD, "property_trees", - property_trees->AsTracedValue()); + TRACE_EVENT_INSTANT1("cc", + "LayerTreeHost::UpdateLayers_ReceivedPropertyTrees", + TRACE_EVENT_SCOPE_THREAD, "property_trees", + property_trees->AsTracedValue()); } draw_property_utils::UpdatePropertyTrees(this, property_trees); @@ -1054,9 +1055,8 @@ void LayerTreeHost::SetEventListenerProperties( void LayerTreeHost::SetViewportSizeAndScale( const gfx::Size& device_viewport_size, float device_scale_factor, - const viz::LocalSurfaceId& local_surface_id) { - if (settings_.enable_surface_synchronization) - SetLocalSurfaceId(local_surface_id); + const viz::LocalSurfaceId& local_surface_id_from_parent) { + SetLocalSurfaceIdFromParent(local_surface_id_from_parent); bool changed = false; if (device_viewport_size_ != device_viewport_size) { @@ -1083,7 +1083,9 @@ void LayerTreeHost::SetViewportSizeAndScale( #if defined(OS_MACOSX) // TODO(ccameron): This check is not valid on Aura or Mus yet, but should // be. - CHECK(!has_pushed_local_surface_id_ || !local_surface_id_.is_valid()); + CHECK(!has_pushed_local_surface_id_from_parent_ || + new_local_surface_id_request_ || + !local_surface_id_from_parent_.is_valid()); #endif } } @@ -1180,16 +1182,34 @@ void LayerTreeHost::SetContentSourceId(uint32_t id) { SetNeedsCommit(); } -void LayerTreeHost::SetLocalSurfaceId( - const viz::LocalSurfaceId& local_surface_id) { - if (local_surface_id_ == local_surface_id) +void LayerTreeHost::SetLocalSurfaceIdFromParent( + const viz::LocalSurfaceId& local_surface_id_from_parent) { + if (local_surface_id_from_parent_ == local_surface_id_from_parent) return; - local_surface_id_ = local_surface_id; - has_pushed_local_surface_id_ = false; + local_surface_id_from_parent_ = local_surface_id_from_parent; + has_pushed_local_surface_id_from_parent_ = false; UpdateDeferCommitsInternal(); SetNeedsCommit(); } +void LayerTreeHost::RequestNewLocalSurfaceId() { + // If surface synchronization is enabled, then we can still request a new + // viz::LocalSurfaceId but that request will be deferred until we have a valid + // viz::LocalSurfaceId from the parent. + DCHECK(settings_.enable_surface_synchronization || + local_surface_id_from_parent_.is_valid()); + if (new_local_surface_id_request_) + return; + new_local_surface_id_request_ = true; + SetNeedsCommit(); +} + +bool LayerTreeHost::TakeNewLocalSurfaceIdRequest() { + bool new_local_surface_id_request = new_local_surface_id_request_; + new_local_surface_id_request_ = false; + return new_local_surface_id_request; +} + void LayerTreeHost::RegisterLayer(Layer* layer) { DCHECK(!LayerById(layer->id())); DCHECK(!in_paint_layer_contents_); @@ -1375,8 +1395,11 @@ void LayerTreeHost::PushLayerTreePropertiesTo(LayerTreeImpl* tree_impl) { tree_impl->set_content_source_id(content_source_id_); - tree_impl->set_local_surface_id(local_surface_id_); - has_pushed_local_surface_id_ = true; + if (TakeNewLocalSurfaceIdRequest()) + tree_impl->RequestNewLocalSurfaceId(); + + tree_impl->SetLocalSurfaceIdFromParent(local_surface_id_from_parent_); + has_pushed_local_surface_id_from_parent_ = true; if (pending_page_scale_animation_) { tree_impl->SetPendingPageScaleAnimation( diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index 9aecadafd1e..2fbf3e6c021 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -292,9 +292,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { return event_listener_properties_[static_cast<size_t>(event_class)]; } - void SetViewportSizeAndScale(const gfx::Size& device_viewport_size, - float device_scale_factor, - const viz::LocalSurfaceId& local_surface_id); + void SetViewportSizeAndScale( + const gfx::Size& device_viewport_size, + float device_scale_factor, + const viz::LocalSurfaceId& local_surface_id_from_parent); void SetViewportVisibleRect(const gfx::Rect& visible_rect); @@ -337,9 +338,20 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // If this LayerTreeHost needs a valid viz::LocalSurfaceId then commits will // be deferred until a valid viz::LocalSurfaceId is provided. - void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id); - const viz::LocalSurfaceId& local_surface_id() const { - return local_surface_id_; + void SetLocalSurfaceIdFromParent( + const viz::LocalSurfaceId& local_surface_id_from_parent); + const viz::LocalSurfaceId& local_surface_id_from_parent() const { + return local_surface_id_from_parent_; + } + + // Requests the allocation of a new LocalSurfaceId on the compositor thread. + void RequestNewLocalSurfaceId(); + + // Returns the current state of the new LocalSurfaceId request and resets + // the state. + bool TakeNewLocalSurfaceIdRequest(); + bool new_local_surface_id_request_for_testing() const { + return new_local_surface_id_request_; } void SetRasterColorSpace(const gfx::ColorSpace& raster_color_space); @@ -418,7 +430,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { LayerListReverseIterator<Layer> rbegin(); LayerListReverseIterator<Layer> rend(); - // LayerTreeHostInProcess interface to Proxy. + // LayerTreeHost interface to Proxy. void WillBeginMainFrame(); void DidBeginMainFrame(); void BeginMainFrame(const viz::BeginFrameArgs& args); @@ -636,9 +648,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; - viz::LocalSurfaceId local_surface_id_; + viz::LocalSurfaceId local_surface_id_from_parent_; // Used to detect surface invariant violations. - bool has_pushed_local_surface_id_ = false; + bool has_pushed_local_surface_id_from_parent_ = false; + bool new_local_surface_id_request_ = false; bool defer_commits_ = false; SkColor background_color_ = SK_ColorWHITE; diff --git a/chromium/cc/trees/layer_tree_host_common_perftest.cc b/chromium/cc/trees/layer_tree_host_common_perftest.cc index f411b4efca1..e599a6b4c1d 100644 --- a/chromium/cc/trees/layer_tree_host_common_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_common_perftest.cc @@ -40,7 +40,8 @@ class LayerTreeHostCommonPerfTest : public LayerTreeTest { void ReadTestFile(const std::string& name) { base::FilePath test_data_dir; - ASSERT_TRUE(PathService::Get(viz::Paths::DIR_TEST_DATA, &test_data_dir)); + ASSERT_TRUE( + base::PathService::Get(viz::Paths::DIR_TEST_DATA, &test_data_dir)); base::FilePath json_file = test_data_dir.AppendASCII(name + ".json"); ASSERT_TRUE(base::ReadFileToString(json_file, &json_)); } diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index 910862ce9a8..df0758ace5d 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -16,6 +16,8 @@ #include "base/auto_reset.h" #include "base/bind.h" +#include "base/compiler_specific.h" +#include "base/containers/adapters.h" #include "base/containers/flat_map.h" #include "base/json/json_writer.h" #include "base/memory/ptr_util.h" @@ -23,6 +25,7 @@ #include "base/numerics/safe_conversions.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" +#include "base/sys_info.h" #include "base/trace_event/trace_event_argument.h" #include "cc/base/devtools_instrumentation.h" #include "cc/base/histograms.h" @@ -82,6 +85,7 @@ #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/delay_based_time_source.h" #include "components/viz/common/gpu/texture_allocation.h" +#include "components/viz/common/hit_test/hit_test_region_list.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/quads/compositor_frame_metadata.h" #include "components/viz/common/quads/frame_deadline.h" @@ -90,6 +94,7 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/resources/bitmap_allocation.h" +#include "components/viz/common/resources/platform_color.h" #include "components/viz/common/traced_value.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" @@ -107,6 +112,53 @@ namespace cc { namespace { +// Used to accommodate finite precision when comparing scaled viewport and +// content widths. While this value may seem large, width=device-width on an N7 +// V1 saw errors of ~0.065 between computed window and content widths. +const float kMobileViewportWidthEpsilon = 0.15f; + +bool HasFixedPageScale(LayerTreeImpl* active_tree) { + return active_tree->min_page_scale_factor() == + active_tree->max_page_scale_factor(); +} + +bool HasMobileViewport(LayerTreeImpl* active_tree) { + float window_width_dip = active_tree->current_page_scale_factor() * + active_tree->ScrollableViewportSize().width(); + float content_width_css = active_tree->ScrollableSize().width(); + return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon; +} + +bool IsMobileOptimized(LayerTreeImpl* active_tree) { + bool has_mobile_viewport = HasMobileViewport(active_tree); + bool has_fixed_page_scale = HasFixedPageScale(active_tree); + return has_fixed_page_scale || has_mobile_viewport; +} + +viz::ResourceFormat TileRasterBufferFormat( + const LayerTreeSettings& settings, + viz::ContextProvider* context_provider, + bool use_gpu_rasterization) { + // Software compositing always uses the native skia RGBA N32 format, but we + // just call it RGBA_8888 everywhere even though it can be BGRA ordering, + // because we don't need to communicate the actual ordering as the code all + // assumes the native skia format. + if (!context_provider) + return viz::RGBA_8888; + + // RGBA4444 overrides the defaults if specified, but only for gpu compositing. + // It is always supported on platforms where it is specified. + if (settings.use_rgba_4444) + return viz::RGBA_4444; + // Otherwise we use BGRA textures if we can but it depends on the context + // capabilities, and we have different preferences when rastering to textures + // vs uploading textures. + const gpu::Capabilities& caps = context_provider->ContextCapabilities(); + if (use_gpu_rasterization) + return viz::PlatformColor::BestSupportedRenderBufferFormat(caps); + return viz::PlatformColor::BestSupportedTextureFormat(caps); +} + // Small helper class that saves the current viewport location as the user sees // it and resets to the same location. class ViewportAnchor { @@ -212,7 +264,6 @@ LayerTreeHostImpl::LayerTreeHostImpl( : client_(client), task_runner_provider_(task_runner_provider), current_begin_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), - layer_tree_frame_sink_(nullptr), need_update_gpu_rasterization_status_(false), content_has_slow_paths_(false), content_has_non_aa_paint_(false), @@ -294,7 +345,9 @@ LayerTreeHostImpl::LayerTreeHostImpl( this, settings.top_controls_show_threshold, settings.top_controls_hide_threshold); - tile_manager_.SetDecodedImageTracker(&decoded_image_tracker_); + memory_pressure_listener_.reset( + new base::MemoryPressureListener(base::BindRepeating( + &LayerTreeHostImpl::OnMemoryPressure, base::Unretained(this)))); } LayerTreeHostImpl::~LayerTreeHostImpl() { @@ -882,8 +935,8 @@ bool LayerTreeHostImpl::HasDamage() const { // If we have a new LocalSurfaceId, we must always submit a CompositorFrame // because the parent is blocking on us. bool local_surface_id_changed = - settings_.enable_surface_synchronization && - (last_draw_local_surface_id_ != active_tree->local_surface_id()); + last_draw_local_surface_id_ != + child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); return root_surface_has_visible_damage || active_tree_->property_trees()->effect_tree.HasCopyRequests() || @@ -1448,6 +1501,7 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy( void LayerTreeHostImpl::DidModifyTilePriorities() { // Mark priorities as dirty and schedule a PrepareTiles(). tile_priorities_dirty_ = true; + tile_manager_.DidModifyTilePriorities(); client_->SetNeedsPrepareTilesOnImplThread(); } @@ -1730,8 +1784,10 @@ void LayerTreeHostImpl::ReclaimResources( // If we're not visible, we likely released resources, so we want to // aggressively flush here to make sure those DeleteTextures make it to the // GPU process to free up the memory. - if (!visible_) - resource_provider_->FlushPendingDeletions(); + if (!visible_ && layer_tree_frame_sink_->context_provider()) { + auto* gl = layer_tree_frame_sink_->context_provider()->ContextGL(); + gl->ShallowFlushCHROMIUM(); + } } void LayerTreeHostImpl::OnDraw(const gfx::Transform& transform, @@ -1844,8 +1900,39 @@ RenderFrameMetadata LayerTreeHostImpl::MakeRenderFrameMetadata() { gfx::ScrollOffsetToVector2dF(active_tree_->TotalScrollOffset()); metadata.root_background_color = active_tree_->background_color(); metadata.is_scroll_offset_at_top = active_tree_->TotalScrollOffset().y() == 0; + metadata.device_scale_factor = active_tree_->painted_device_scale_factor() * + active_tree_->device_scale_factor(); + metadata.viewport_size_in_pixels = device_viewport_size(); + metadata.top_controls_height = + browser_controls_offset_manager_->TopControlsHeight(); + metadata.top_controls_shown_ratio = + browser_controls_offset_manager_->TopControlsShownRatio(); + metadata.bottom_controls_height = + browser_controls_offset_manager_->BottomControlsHeight(); + metadata.bottom_controls_shown_ratio = + browser_controls_offset_manager_->BottomControlsShownRatio(); + + bool allocate_new_local_surface_id = + last_draw_render_frame_metadata_ && + (last_draw_render_frame_metadata_->top_controls_height != + metadata.top_controls_height || + last_draw_render_frame_metadata_->top_controls_shown_ratio != + metadata.top_controls_shown_ratio || + last_draw_render_frame_metadata_->bottom_controls_height != + metadata.bottom_controls_height || + last_draw_render_frame_metadata_->bottom_controls_shown_ratio != + metadata.bottom_controls_shown_ratio); + + viz::LocalSurfaceId local_surface_id = + child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); + if (local_surface_id.is_valid()) { + if (allocate_new_local_surface_id) + local_surface_id = child_local_surface_id_allocator_.GenerateId(); + metadata.local_surface_id = local_surface_id; + } active_tree_->GetViewportSelection(&metadata.selection); + metadata.is_mobile_optimized = IsMobileOptimized(active_tree_.get()); return metadata; } @@ -1923,32 +2010,32 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { active_tree()->FinishSwapPromises(&metadata, &frame_token_allocator_); if (render_frame_metadata_observer_) { - RenderFrameMetadata render_frame_metadata = MakeRenderFrameMetadata(); + last_draw_render_frame_metadata_ = MakeRenderFrameMetadata(); render_frame_metadata_observer_->OnRenderFrameSubmission( - std::move(render_frame_metadata)); + *last_draw_render_frame_metadata_); } metadata.latency_info.emplace_back(ui::SourceEventType::FRAME); ui::LatencyInfo& new_latency_info = metadata.latency_info.back(); if (CommitToActiveTree()) { new_latency_info.AddLatencyNumberWithTimestamp( - ui::LATENCY_BEGIN_FRAME_UI_COMPOSITOR_COMPONENT, 0, 0, frame_time, 1); + ui::LATENCY_BEGIN_FRAME_UI_COMPOSITOR_COMPONENT, 0, frame_time, 1); } else { new_latency_info.AddLatencyNumberWithTimestamp( - ui::LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT, 0, 0, frame_time, + ui::LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT, 0, frame_time, 1); base::TimeTicks draw_time = base::TimeTicks::Now(); for (auto& latency : metadata.latency_info) { latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, 0, draw_time, 1); + ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, draw_time, 1); } } ui::LatencyInfo::TraceIntermediateFlowEvents(metadata.latency_info, "SwapBuffers"); // Collect all resource ids in the render passes into a single array. - ResourceProvider::ResourceIdArray resources; + std::vector<viz::ResourceId> resources; for (const auto& render_pass : frame->render_passes) { for (auto* quad : render_pass->quad_list) { for (viz::ResourceId resource_id : quad->resources) @@ -1962,8 +2049,9 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { viz::CompositorFrame compositor_frame; compositor_frame.metadata = std::move(metadata); - resource_provider_->PrepareSendToParent(resources, - &compositor_frame.resource_list); + resource_provider_->PrepareSendToParent( + resources, &compositor_frame.resource_list, + layer_tree_frame_sink_->context_provider()); compositor_frame.render_pass_list = std::move(frame->render_passes); // TODO(fsamuel): Once all clients get their viz::LocalSurfaceId from their // parent, the viz::LocalSurfaceId should hang off CompositorFrameMetadata. @@ -1974,11 +2062,12 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { // LocalSurfaceId might slip through, but single-thread-without-scheduler // mode is only used in tests so it doesn't matter. CHECK(!settings_.single_thread_proxy_scheduler || - active_tree()->local_surface_id().is_valid()); + active_tree()->local_surface_id_from_parent().is_valid()); layer_tree_frame_sink_->SetLocalSurfaceId( - active_tree()->local_surface_id()); - last_draw_local_surface_id_ = active_tree()->local_surface_id(); + child_local_surface_id_allocator_.GetCurrentLocalSurfaceId()); } + last_draw_local_surface_id_ = + child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); if (const char* client_name = GetClientNameForMetrics()) { size_t total_quad_count = 0; for (const auto& pass : compositor_frame.render_pass_list) @@ -2102,9 +2191,13 @@ void LayerTreeHostImpl::GetGpuRasterizationCapabilities( *supports_disable_msaa = caps.multisample_compatibility; if (!caps.msaa_is_slow && !caps.avoid_stencil_buffers) { // Skia may blacklist MSAA independently of Chrome. Query Skia for its max - // supported sample count. - SkColorType color_type = - ResourceFormatToClosestSkColorType(settings_.preferred_tile_format); + // supported sample count. Assume gpu compositing + gpu raster for this, as + // that is what we are hoping to use. + viz::ResourceFormat tile_format = TileRasterBufferFormat( + settings_, layer_tree_frame_sink_->context_provider(), + /*use_gpu_rasterization=*/true); + SkColorType color_type = ResourceFormatToClosestSkColorType( + /*gpu_compositing=*/true, tile_format); *max_msaa_samples = gr_context->maxSurfaceSampleCountForColorType(color_type); } @@ -2244,7 +2337,7 @@ bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) { void LayerTreeHostImpl::DidFinishImplFrame() { impl_thread_phase_ = ImplThreadPhase::IDLE; current_begin_frame_tracker_.Finish(); - decoded_image_tracker_.NotifyFrameFinished(); + tile_manager_.decoded_image_tracker().NotifyFrameFinished(); } void LayerTreeHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack) { @@ -2302,6 +2395,100 @@ void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() { single_thread_synchronous_task_graph_runner_->RunUntilIdle(); } +static uint32_t GetFlagsForSurfaceLayer(const SurfaceLayerImpl* layer) { + uint32_t flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch; + const auto& surface_id = layer->primary_surface_id(); + if (layer->is_clipped()) { + flags |= viz::HitTestRegionFlags::kHitTestAsk; + } + if (surface_id.local_surface_id().is_valid()) { + flags |= viz::HitTestRegionFlags::kHitTestChildSurface; + } else { + flags |= viz::HitTestRegionFlags::kHitTestMine; + } + return flags; +} + +static void PopulateHitTestRegion(viz::HitTestRegion* hit_test_region, + const LayerImpl* layer, + uint32_t flags, + const gfx::Rect& rect, + const viz::SurfaceId& surface_id, + float device_scale_factor) { + hit_test_region->frame_sink_id = surface_id.frame_sink_id(); + hit_test_region->flags = flags; + + hit_test_region->rect = rect; + // The transform of hit test region maps a point from parent hit test region + // to the local space. This is the inverse of screen space transform. Because + // hit test query wants the point in target to be in Pixel space, we + // counterscale the transform here. Note that the rect is scaled by dsf, so + // the point and the rect are still in the same space. + gfx::Transform surface_to_root_transform = layer->ScreenSpaceTransform(); + surface_to_root_transform.Scale(SK_MScalar1 / device_scale_factor, + SK_MScalar1 / device_scale_factor); + // TODO(sunxd): Avoid losing precision by not using inverse if possible. + bool ok = surface_to_root_transform.GetInverse(&hit_test_region->transform); + // Note: If |ok| is false, the |transform| is set to the identity before + // returning, which is what we want. + ALLOW_UNUSED_LOCAL(ok); +} + +base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { + if (!settings_.build_hit_test_data) + return {}; + + base::Optional<viz::HitTestRegionList> hit_test_region_list(base::in_place); + hit_test_region_list->flags = viz::HitTestRegionFlags::kHitTestMine | + viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch; + hit_test_region_list->bounds = DeviceViewport(); + hit_test_region_list->transform = DrawTransform(); + + float device_scale_factor = active_tree()->device_scale_factor(); + + Region overlapping_region; + for (const auto* layer : base::Reversed(*active_tree())) { + if (!layer->should_hit_test()) + continue; + + if (layer->is_surface_layer()) { + const auto* surface_layer = static_cast<const SurfaceLayerImpl*>(layer); + + if (!surface_layer->surface_hit_testable()) { + overlapping_region.Union(MathUtil::MapEnclosingClippedRect( + layer->ScreenSpaceTransform(), gfx::Rect(surface_layer->bounds()))); + continue; + } + + gfx::Rect content_rect( + gfx::ScaleToEnclosingRect(gfx::Rect(surface_layer->bounds()), + device_scale_factor, device_scale_factor)); + + gfx::Rect layer_screen_space_rect = MathUtil::MapEnclosingClippedRect( + surface_layer->ScreenSpaceTransform(), + gfx::Rect(surface_layer->bounds())); + if (overlapping_region.Contains(layer_screen_space_rect)) + continue; + + auto flag = GetFlagsForSurfaceLayer(surface_layer); + if (overlapping_region.Intersects(layer_screen_space_rect)) + flag |= viz::HitTestRegionFlags::kHitTestAsk; + auto surface_id = surface_layer->primary_surface_id(); + hit_test_region_list->regions.emplace_back(); + PopulateHitTestRegion(&hit_test_region_list->regions.back(), layer, flag, + content_rect, surface_id, device_scale_factor); + continue; + } + // TODO(sunxd): Submit all overlapping layer bounds as hit test regions. + overlapping_region.Union(MathUtil::MapEnclosingClippedRect( + layer->ScreenSpaceTransform(), gfx::Rect(layer->bounds()))); + } + + return hit_test_region_list; +} + void LayerTreeHostImpl::DidLoseLayerTreeFrameSink() { // Check that we haven't already detected context loss because we get it via // two paths: compositor context loss on the compositor thread and worker @@ -2310,8 +2497,6 @@ void LayerTreeHostImpl::DidLoseLayerTreeFrameSink() { if (!has_valid_layer_tree_frame_sink_) return; has_valid_layer_tree_frame_sink_ = false; - if (resource_provider_) - resource_provider_->DidLoseContextProvider(); client_->DidLoseLayerTreeFrameSinkOnImplThread(); } @@ -2502,6 +2687,14 @@ void LayerTreeHostImpl::ActivateSyncTree() { // Activation can change the root scroll offset, so inform the synchronous // input handler. UpdateRootLayerStateForSynchronousInputHandler(); + + // Update the child's LocalSurfaceId. + if (active_tree()->local_surface_id_from_parent().is_valid()) { + child_local_surface_id_allocator_.UpdateFromParent( + active_tree()->local_surface_id_from_parent()); + if (active_tree()->TakeNewLocalSurfaceIdRequest()) + child_local_surface_id_allocator_.GenerateId(); + } } void LayerTreeHostImpl::ActivateStateForImages() { @@ -2509,6 +2702,30 @@ void LayerTreeHostImpl::ActivateStateForImages() { tile_manager_.DidActivateSyncTree(); } +void LayerTreeHostImpl::OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel level) { + // Only work for low-end devices for now. + if (!base::SysInfo::IsLowEndDevice()) + return; + + switch (level) { + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: + break; + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: + ReleaseTileResources(); + ReleaseTreeResources(); + ClearUIResources(); + if (image_decode_cache_) { + image_decode_cache_->SetShouldAggressivelyFreeResources(true); + image_decode_cache_->SetShouldAggressivelyFreeResources(false); + } + if (resource_pool_) + resource_pool_->OnPurgeMemory(); + break; + } +} + void LayerTreeHostImpl::SetVisible(bool visible) { DCHECK(task_runner_provider_->IsImplThread()); @@ -2599,20 +2816,21 @@ void LayerTreeHostImpl::RecreateTileResources() { void LayerTreeHostImpl::CreateTileManagerResources() { raster_buffer_provider_ = CreateRasterBufferProvider(); + viz::ResourceFormat tile_format = TileRasterBufferFormat( + settings_, layer_tree_frame_sink_->context_provider(), + use_gpu_rasterization_); + if (use_gpu_rasterization_) { - int max_texture_size = layer_tree_frame_sink_->context_provider() - ->ContextCapabilities() - .max_texture_size; image_decode_cache_ = std::make_unique<GpuImageDecodeCache>( layer_tree_frame_sink_->worker_context_provider(), use_oop_rasterization_, - viz::ResourceFormatToClosestSkColorType( - settings_.preferred_tile_format), - settings_.decoded_image_working_set_budget_bytes, max_texture_size); + viz::ResourceFormatToClosestSkColorType(/*gpu_compositing=*/true, + tile_format), + settings_.decoded_image_working_set_budget_bytes, max_texture_size_); } else { + bool gpu_compositing = !!layer_tree_frame_sink_->context_provider(); image_decode_cache_ = std::make_unique<SoftwareImageDecodeCache>( - viz::ResourceFormatToClosestSkColorType( - settings_.preferred_tile_format), + viz::ResourceFormatToClosestSkColorType(gpu_compositing, tile_format), settings_.decoded_image_working_set_budget_bytes); } @@ -2643,18 +2861,22 @@ LayerTreeHostImpl::CreateRasterBufferProvider() { if (!compositor_context_provider) return std::make_unique<BitmapRasterBufferProvider>(layer_tree_frame_sink_); + const gpu::Capabilities& caps = + compositor_context_provider->ContextCapabilities(); viz::RasterContextProvider* worker_context_provider = layer_tree_frame_sink_->worker_context_provider(); + + viz::ResourceFormat tile_format = TileRasterBufferFormat( + settings_, compositor_context_provider, use_gpu_rasterization_); + if (use_gpu_rasterization_) { DCHECK(worker_context_provider); int msaa_sample_count = use_msaa_ ? RequestedMSAASampleCount() : 0; return std::make_unique<GpuRasterBufferProvider>( compositor_context_provider, worker_context_provider, - resource_provider_.get(), settings_.resource_settings.use_gpu_memory_buffer_resources, - msaa_sample_count, settings_.preferred_tile_format, - settings_.max_gpu_raster_tile_size, + msaa_sample_count, tile_format, settings_.max_gpu_raster_tile_size, settings_.unpremultiply_and_dither_low_bit_depth_tiles, use_oop_rasterization_); } @@ -2670,21 +2892,18 @@ LayerTreeHostImpl::CreateRasterBufferProvider() { if (use_zero_copy) { return std::make_unique<ZeroCopyRasterBufferProvider>( - resource_provider_.get(), layer_tree_frame_sink_->gpu_memory_buffer_manager(), - compositor_context_provider, settings_.preferred_tile_format); + compositor_context_provider, tile_format); } const int max_copy_texture_chromium_size = - compositor_context_provider->ContextCapabilities() - .max_copy_texture_chromium_size; + caps.max_copy_texture_chromium_size; return std::make_unique<OneCopyRasterBufferProvider>( GetTaskRunner(), compositor_context_provider, worker_context_provider, - resource_provider_.get(), max_copy_texture_chromium_size, - settings_.use_partial_raster, + layer_tree_frame_sink_->gpu_memory_buffer_manager(), + max_copy_texture_chromium_size, settings_.use_partial_raster, settings_.resource_settings.use_gpu_memory_buffer_resources, - settings_.max_staging_buffer_usage_in_bytes, - settings_.preferred_tile_format); + settings_.max_staging_buffer_usage_in_bytes, tile_format); } void LayerTreeHostImpl::SetLayerTreeMutator( @@ -2711,7 +2930,7 @@ void LayerTreeHostImpl::QueueImageDecode(int request_id, image.GetKeyForFrame(image.frame_index()).ToString()); // Optimistically specify the current raster color space, since we assume that // it won't change. - decoded_image_tracker_.QueueImageDecode( + tile_manager_.decoded_image_tracker().QueueImageDecode( image, GetRasterColorSpace().color_space, base::Bind(&LayerTreeHostImpl::ImageDecodeFinished, base::Unretained(this), request_id)); @@ -2795,6 +3014,11 @@ void LayerTreeHostImpl::ReleaseLayerTreeFrameSink() { ClearUIResources(); resource_provider_ = nullptr; + if (layer_tree_frame_sink_->context_provider()) { + auto* gl = layer_tree_frame_sink_->context_provider()->ContextGL(); + gl->Finish(); + } + // Release any context visibility before we destroy the LayerTreeFrameSink. SetContextVisibility(false); @@ -2824,27 +3048,23 @@ bool LayerTreeHostImpl::InitializeRenderer( layer_tree_frame_sink_ = layer_tree_frame_sink; has_valid_layer_tree_frame_sink_ = true; - resource_provider_ = std::make_unique<LayerTreeResourceProvider>( - layer_tree_frame_sink_->context_provider(), - layer_tree_frame_sink_->shared_bitmap_manager(), - layer_tree_frame_sink_->gpu_memory_buffer_manager(), - layer_tree_frame_sink_->capabilities().delegated_sync_points_required, - settings_.resource_settings); - if (!layer_tree_frame_sink_->context_provider()) { - // This ResourcePool will vend software resources. - resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), GetTaskRunner(), - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kSoftware, - settings_.disallow_non_exact_resource_reuse); + + auto* context_provider = layer_tree_frame_sink_->context_provider(); + if (context_provider) { + max_texture_size_ = + context_provider->ContextCapabilities().max_texture_size; } else { - // The ResourcePool will vend gpu resources. - resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), GetTaskRunner(), - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu, - settings_.disallow_non_exact_resource_reuse); + // Pick an arbitrary limit here similar to what hardware might. + max_texture_size_ = 16 * 1024; } - if (features::IsVizHitTestingSurfaceLayerEnabled()) - layer_tree_frame_sink_->UpdateHitTestData(this); + + resource_provider_ = std::make_unique<LayerTreeResourceProvider>( + layer_tree_frame_sink_->context_provider(), + layer_tree_frame_sink_->capabilities().delegated_sync_points_required); + resource_pool_ = std::make_unique<ResourcePool>( + resource_provider_.get(), layer_tree_frame_sink_->context_provider(), + GetTaskRunner(), ResourcePool::kDefaultExpirationDelay, + settings_.disallow_non_exact_resource_reuse); // TODO(piman): Make oop raster always supported: http://crbug.com/786591 use_oop_rasterization_ = settings_.enable_oop_rasterization; @@ -3128,9 +3348,15 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; if (!scrolling_node) { - scroll_status.thread = SCROLL_IGNORED; - if (settings_.is_layer_tree_for_subframe) + if (settings_.is_layer_tree_for_subframe) { + TRACE_EVENT_INSTANT0("cc", "Ignored - No ScrollNode (OOPIF)", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_UNKNOWN; + } else { + TRACE_EVENT_INSTANT0("cc", "Ignroed - No ScrollNode", + TRACE_EVENT_SCOPE_THREAD); + scroll_status.thread = SCROLL_IGNORED; + } scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNoScrollingLayer; return scroll_status; @@ -3140,6 +3366,9 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( browser_controls_offset_manager_->ScrollBegin(); + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode ScrollBeginImpl", + TRACE_EVENT_SCOPE_THREAD, "isNull", + scrolling_node ? false : true); active_tree_->SetCurrentlyScrollingNode(scrolling_node); // TODO(majidvp): get rid of wheel_scrolling_ and set is_direct_manipulation // in input_handler_proxy instead. @@ -3152,6 +3381,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( // If the CurrentlyScrollingNode doesn't exist after distributing scroll // delta, no scroller can scroll in the given delta hint direction(s). if (!active_tree_->CurrentlyScrollingNode()) { + TRACE_EVENT_INSTANT0("cc", "Ignored - Didnt Scroll", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = InputHandler::SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; @@ -3211,6 +3442,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin( if (layer_impl) { if (!IsInitialScrollHitTestReliable(layer_impl, device_viewport_point)) { + TRACE_EVENT_INSTANT0("cc", "Failed Hit Test", TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_UNKNOWN; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kFailedHitTest; @@ -3277,6 +3509,7 @@ bool LayerTreeHostImpl::IsInitialScrollHitTestReliable( InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( ScrollState* scroll_state) { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollAnimatedBegin"); InputHandler::ScrollStatus scroll_status; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; @@ -3288,6 +3521,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( if (ScrollAnimationUpdateTarget(scroll_node, delta, base::TimeDelta())) { scroll_status.thread = SCROLL_ON_IMPL_THREAD; } else { + TRACE_EVENT_INSTANT0("cc", "Failed to create animation", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollable; @@ -3377,6 +3612,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( const gfx::Point& viewport_point, const gfx::Vector2dF& scroll_delta, base::TimeDelta delayed_by) { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollAnimated"); InputHandler::ScrollStatus scroll_status; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; @@ -3403,6 +3639,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( if (ScrollAnimationUpdateTarget(scroll_node, delta, delayed_by)) { scroll_status.thread = SCROLL_ON_IMPL_THREAD; } else { + TRACE_EVENT_INSTANT0("cc", "Failed to update animation", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollable; @@ -3479,10 +3717,13 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( } scroll_state.set_is_ending(true); ScrollEndImpl(&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. + if (scroll_status.thread == SCROLL_ON_IMPL_THREAD) { + // Update scroll_status.thread to SCROLL_IGNORED when there is no ongoing + // scroll animation, we can scroll on impl thread and yet, we couldn't + // create a new scroll animation. This happens when the scroller has hit its + // extent. + TRACE_EVENT_INSTANT0("cc", "Ignored - Scroller at extent", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollable; @@ -3746,8 +3987,13 @@ void LayerTreeHostImpl::DistributeScrollDelta(ScrollState* scroll_state) { } } } - active_tree_->SetCurrentlyScrollingNode( - current_scroll_chain.empty() ? nullptr : current_scroll_chain.back()); + + scroll_node = + current_scroll_chain.empty() ? nullptr : current_scroll_chain.back(); + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode DistributeScrollDelta", + TRACE_EVENT_SCOPE_THREAD, "isNull", + scroll_node ? false : true); + active_tree_->SetCurrentlyScrollingNode(scroll_node); scroll_state->set_scroll_chain_and_layer_tree(current_scroll_chain, active_tree()); scroll_state->DistributeToScrollChainDescendant(); @@ -3803,8 +4049,27 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( DCHECK(scroll_state); TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); - ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; + auto& scroll_tree = active_tree_->property_trees()->scroll_tree; + + ElementId provided_element = + scroll_state->data()->current_native_scrolling_element(); + const auto* provided_scroll_node = + scroll_tree.FindNodeFromElementId(provided_element); + + // If the currently scrolling node is not set, set it with + // |provided_scroll_node|. ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + if (scroll_node) { + // If |provided_scroll_node| is not null, make sure it matches + // |scroll_node|. + DCHECK(!provided_scroll_node || scroll_node == provided_scroll_node); + } else { + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode ScrollBy", + TRACE_EVENT_SCOPE_THREAD, "isNull", + provided_scroll_node ? false : true); + active_tree_->SetCurrentlyScrollingNode(provided_scroll_node); + scroll_node = scroll_tree.CurrentlyScrollingNode(); + } if (!scroll_node) return InputHandlerScrollResult(); @@ -3825,13 +4090,15 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( scroll_state->set_delta_consumed_for_scroll_sequence( did_lock_scrolling_layer_); scroll_state->set_is_direct_manipulation(!wheel_scrolling_); - scroll_state->set_current_native_scrolling_node( - active_tree()->property_trees()->scroll_tree.CurrentlyScrollingNode()); + scroll_state->set_current_native_scrolling_node(scroll_node); DistributeScrollDelta(scroll_state); ScrollNode* current_scrolling_node = scroll_state->current_native_scrolling_node(); + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode ApplyDelta", + TRACE_EVENT_SCOPE_THREAD, "isNull", + current_scrolling_node ? false : true); active_tree_->SetCurrentlyScrollingNode(current_scrolling_node); did_lock_scrolling_layer_ = scroll_state->delta_consumed_for_scroll_sequence(); @@ -3898,10 +4165,10 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( UpdateRootLayerStateForSynchronousInputHandler(); } - scroll_result.current_offset = ScrollOffsetToVector2dF( - scroll_tree.current_scroll_offset(scroll_node->element_id)); + scroll_result.current_visual_offset = + ScrollOffsetToVector2dF(GetVisualScrollOffset(*scroll_node)); float scale_factor = active_tree()->current_page_scale_factor(); - scroll_result.current_offset.Scale(scale_factor); + scroll_result.current_visual_offset.Scale(scale_factor); // Run animations which need to respond to updated scroll offset. mutator_host_->TickScrollAnimations( @@ -3917,6 +4184,9 @@ void LayerTreeHostImpl::RequestUpdateForSynchronousInputHandler() { void LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset( const gfx::ScrollOffset& root_offset) { + TRACE_EVENT2("cc", + "LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset", + "offset_x", root_offset.x(), "offset_y", root_offset.y()); bool changed = active_tree_->DistributeRootScrollOffset(root_offset); if (!changed) return; @@ -3936,9 +4206,7 @@ bool LayerTreeHostImpl::SnapAtScrollEnd() { return false; const SnapContainerData& data = scroll_node->snap_container_data.value(); - ScrollTree& scroll_tree = active_tree()->property_trees()->scroll_tree; - gfx::ScrollOffset current_position = - scroll_tree.current_scroll_offset(scroll_node->element_id); + gfx::ScrollOffset current_position = GetVisualScrollOffset(*scroll_node); gfx::ScrollOffset snap_position; if (!data.FindSnapPosition(current_position, did_scroll_x_for_scroll_gesture_, @@ -3947,12 +4215,43 @@ bool LayerTreeHostImpl::SnapAtScrollEnd() { return false; } - ScrollAnimationCreate( - scroll_node, ScrollOffsetToVector2dF(snap_position - current_position), - base::TimeDelta()); + gfx::Vector2dF delta = + ScrollOffsetToVector2dF(snap_position - current_position); + bool scrolls_main_viewport_scroll_layer = + scroll_node == ViewportMainScrollNode(); + if (scrolls_main_viewport_scroll_layer) { + // Flash the overlay scrollbar even if the scroll dalta is 0. + if (settings_.scrollbar_flash_after_any_scroll_update) { + FlashAllScrollbars(false); + } else { + ScrollbarAnimationController* animation_controller = + ScrollbarAnimationControllerForElementId(scroll_node->element_id); + if (animation_controller) + animation_controller->WillUpdateScroll(); + } + gfx::Vector2dF scaled_delta(delta); + scaled_delta.Scale(active_tree()->current_page_scale_factor()); + viewport()->ScrollAnimated(scaled_delta, base::TimeDelta()); + } else { + ScrollAnimationCreate(scroll_node, delta, base::TimeDelta()); + } return true; } +gfx::ScrollOffset LayerTreeHostImpl::GetVisualScrollOffset( + const ScrollNode& scroll_node) const { + const ScrollTree& scroll_tree = active_tree()->property_trees()->scroll_tree; + + bool scrolls_main_viewport_scroll_layer = + viewport()->MainScrollLayer() && + viewport()->MainScrollLayer()->scroll_tree_index() == scroll_node.id; + + if (scrolls_main_viewport_scroll_layer) + return viewport()->TotalScrollOffset(); + else + return scroll_tree.current_scroll_offset(scroll_node.element_id); +} + bool LayerTreeHostImpl::GetSnapFlingInfo( const gfx::Vector2dF& natural_displacement_in_viewport, gfx::Vector2dF* initial_offset, @@ -3966,9 +4265,8 @@ bool LayerTreeHostImpl::GetSnapFlingInfo( gfx::Vector2dF natural_displacement_in_content = gfx::ScaleVector2d(natural_displacement_in_viewport, 1.f / scale_factor); - const ScrollTree& scroll_tree = active_tree()->property_trees()->scroll_tree; - *initial_offset = ScrollOffsetToVector2dF( - scroll_tree.current_scroll_offset(scroll_node->element_id)); + *initial_offset = + ScrollOffsetToVector2dF(GetVisualScrollOffset(*scroll_node)); bool did_scroll_x = did_scroll_x_for_scroll_gesture_ || natural_displacement_in_content.x() != 0; @@ -3989,6 +4287,7 @@ bool LayerTreeHostImpl::GetSnapFlingInfo( } void LayerTreeHostImpl::ClearCurrentlyScrollingNode() { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ClearCurrentlyScrollingNode"); active_tree_->ClearCurrentlyScrollingNode(); did_lock_scrolling_layer_ = false; scroll_affects_scroll_handler_ = false; @@ -4118,6 +4417,9 @@ void LayerTreeHostImpl::PinchGestureBegin() { client_->RenewTreePriority(); pinch_gesture_end_should_clear_scrolling_node_ = !CurrentlyScrollingNode(); + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode PinchGestureBegin", + TRACE_EVENT_SCOPE_THREAD, "isNull", + OuterViewportScrollNode() ? false : true); active_tree_->SetCurrentlyScrollingNode(OuterViewportScrollNode()); browser_controls_offset_manager_->PinchBegin(); } @@ -4530,9 +4832,16 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, return; } - viz::ResourceFormat format = resource_provider_->best_texture_format(); + viz::ResourceFormat format; switch (bitmap.GetFormat()) { case UIResourceBitmap::RGBA8: + if (layer_tree_frame_sink_->context_provider()) { + const gpu::Capabilities& caps = + layer_tree_frame_sink_->context_provider()->ContextCapabilities(); + format = viz::PlatformColor::BestSupportedTextureFormat(caps); + } else { + format = viz::RGBA_8888; + } break; case UIResourceBitmap::ALPHA_8: format = viz::ALPHA_8; @@ -4548,13 +4857,12 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, // UIResources are assumed to be rastered in SRGB. const gfx::ColorSpace& color_space = gfx::ColorSpace::CreateSRGB(); - int max_texture_size = resource_provider_->max_texture_size(); - if (source_size.width() > max_texture_size || - source_size.height() > max_texture_size) { + if (source_size.width() > max_texture_size_ || + source_size.height() > max_texture_size_) { // Must resize the bitmap to fit within the max texture size. scaled = true; int edge = std::max(source_size.width(), source_size.height()); - float scale = static_cast<float>(max_texture_size - 1) / edge; + float scale = static_cast<float>(max_texture_size_ - 1) / edge; DCHECK_LT(scale, 1.f); upload_size = gfx::ScaleToCeiledSize(source_size, scale, scale); } @@ -4680,7 +4988,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, shared_memory.get(), upload_size, format); layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(memory_handle), shared_bitmap_id); - transferable = viz::TransferableResource::MakeSoftware(shared_bitmap_id, 0, + transferable = viz::TransferableResource::MakeSoftware(shared_bitmap_id, upload_size, format); } transferable.color_space = color_space; @@ -4976,6 +5284,7 @@ void LayerTreeHostImpl::ElementIsAnimatingChanged( } void LayerTreeHostImpl::ScrollOffsetAnimationFinished() { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollOffsetAnimationFinished"); // TODO(majidvp): We should pass in the original starting scroll position here ScrollStateData scroll_state_data; ScrollState scroll_state(scroll_state_data); diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index 82d50cc888b..3f93eb51e60 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -17,6 +17,7 @@ #include "base/callback.h" #include "base/containers/flat_map.h" #include "base/macros.h" +#include "base/memory/memory_pressure_listener.h" #include "base/sequenced_task_runner.h" #include "base/time/time.h" #include "cc/base/synced_property.h" @@ -41,11 +42,13 @@ #include "cc/trees/layer_tree_settings.h" #include "cc/trees/managed_memory_policy.h" #include "cc/trees/mutator_host_client.h" +#include "cc/trees/render_frame_metadata.h" #include "cc/trees/task_runner_provider.h" #include "cc/trees/ukm_manager.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/gpu/context_cache_controller.h" #include "components/viz/common/quads/render_pass.h" +#include "components/viz/common/surfaces/child_local_surface_id_allocator.h" #include "components/viz/common/surfaces/local_surface_id.h" #include "components/viz/common/surfaces/surface_id.h" #include "ui/gfx/geometry/rect.h" @@ -75,7 +78,6 @@ class PendingTreeDurationHistogramTimer; class PendingTreeRasterDurationHistogramTimer; class RasterTilePriorityQueue; class RasterBufferProvider; -class RenderFrameMetadata; class RenderFrameMetadataObserver; class RenderingStatsInstrumentation; class ResourcePool; @@ -425,6 +427,7 @@ class CC_EXPORT LayerTreeHostImpl void SetExternalTilePriorityConstraints( const gfx::Rect& viewport_rect, const gfx::Transform& transform) override; + base::Optional<viz::HitTestRegionList> BuildHitTestData() override; void DidLoseLayerTreeFrameSink() override; void DidReceiveCompositorFrameAck() override; void DidPresentCompositorFrame(uint32_t presentation_token, @@ -449,6 +452,7 @@ class CC_EXPORT LayerTreeHostImpl LayerTreeFrameSink* layer_tree_frame_sink() const { return layer_tree_frame_sink_; } + int max_texture_size() const { return max_texture_size_; } void ReleaseLayerTreeFrameSink(); std::string LayerListAsJson() const; @@ -531,7 +535,9 @@ class CC_EXPORT LayerTreeHostImpl ManagedMemoryPolicy ActualManagedMemoryPolicy() const; void SetViewportSize(const gfx::Size& device_viewport_size); - gfx::Size device_viewport_size() const { return device_viewport_size_; } + const gfx::Size& device_viewport_size() const { + return device_viewport_size_; + } void SetViewportVisibleRect(const gfx::Rect& visible_rect); gfx::Rect viewport_visible_rect() const { return viewport_visible_rect_; } @@ -596,6 +602,10 @@ class CC_EXPORT LayerTreeHostImpl virtual bool IsUIResourceOpaque(UIResourceId uid) const; + // This method gets the scroll offset for a regular scroller, or the combined + // visual and layout offsets of the viewport. + gfx::ScrollOffset GetVisualScrollOffset(const ScrollNode& scroll_node) const; + bool GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement_in_viewport, gfx::Vector2dF* initial_offset, gfx::Vector2dF* target_offset) const override; @@ -851,6 +861,9 @@ class CC_EXPORT LayerTreeHostImpl // active tree. void ActivateStateForImages(); + void OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel level); + std::unordered_map<UIResourceId, UIResourceData> ui_resource_map_; // UIResources are held here once requested to be deleted until they are // released from the display compositor, then the backing can be deleted. @@ -861,7 +874,14 @@ class CC_EXPORT LayerTreeHostImpl // associated with them anymore, as that is freed at the time of eviction. std::set<UIResourceId> evicted_ui_resources_; - LayerTreeFrameSink* layer_tree_frame_sink_; + // These are valid when has_valid_layer_tree_frame_sink_ is true. + // + // A pointer used for communicating with and submitting output to the display + // compositor. + LayerTreeFrameSink* layer_tree_frame_sink_ = nullptr; + // The maximum size (either width or height) that any texture can be. Also + // holds a reasonable value for software compositing bitmaps. + int max_texture_size_ = 0; // The following scoped variables must not outlive the // |layer_tree_frame_sink_|. @@ -921,7 +941,6 @@ class CC_EXPORT LayerTreeHostImpl const bool is_synchronous_single_threaded_; TileManager tile_manager_; - DecodedImageTracker decoded_image_tracker_; gfx::Vector2dF accumulated_root_overscroll_; @@ -1053,10 +1072,14 @@ class CC_EXPORT LayerTreeHostImpl uint32_t last_presentation_token_ = 0u; viz::LocalSurfaceId last_draw_local_surface_id_; + base::Optional<RenderFrameMetadata> last_draw_render_frame_metadata_; + viz::ChildLocalSurfaceIdAllocator child_local_surface_id_allocator_; const int default_color_space_id_; const gfx::ColorSpace default_color_space_; + std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; + 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 4c4570ee4d7..b7fdefd87dc 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -10,14 +10,17 @@ #include <cmath> #include <utility> +#include "base/base_switches.h" #include "base/bind.h" #include "base/command_line.h" #include "base/location.h" +#include "base/memory/memory_pressure_listener.h" #include "base/memory/ptr_util.h" #include "base/optional.h" #include "base/run_loop.h" #include "base/test/histogram_tester.h" #include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" #include "cc/animation/animation_host.h" #include "cc/animation/animation_id_provider.h" #include "cc/animation/transform_operations.h" @@ -69,11 +72,13 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/quads/tile_draw_quad.h" +#include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/service/display/gl_renderer.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/fake_output_surface.h" #include "components/viz/test/test_layer_tree_frame_sink.h" #include "components/viz/test/test_web_graphics_context_3d.h" +#include "gpu/GLES2/gl2extchromium.h" #include "media/base/media.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -180,7 +185,7 @@ class LayerTreeHostImplTest : public testing::Test, } void DidActivateSyncTree() override { // Make sure the active tree always has a valid LocalSurfaceId. - host_impl_->active_tree()->set_local_surface_id( + host_impl_->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); } void WillPrepareTiles() override {} @@ -242,7 +247,7 @@ class LayerTreeHostImplTest : public testing::Test, bool init = host_impl_->InitializeRenderer(layer_tree_frame_sink_.get()); host_impl_->SetViewportSize(gfx::Size(10, 10)); host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f); - host_impl_->active_tree()->set_local_surface_id( + host_impl_->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); // Set the viz::BeginFrameArgs so that methods which use it are able to. host_impl_->WillBeginImplFrame(viz::CreateBeginFrameArgsForTesting( @@ -1063,15 +1068,23 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) { status.main_thread_scrolling_reasons); } +class LostGLES2Interface : public viz::TestGLES2Interface { + public: + LostGLES2Interface() = default; + + void InitializeTestContext() override { + LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); + } +}; + TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) { - std::unique_ptr<TestWebGraphicsContext3D> context_owned = - TestWebGraphicsContext3D::Create(); - context_owned->set_context_lost(true); + auto gl_owned = std::make_unique<LostGLES2Interface>(); // Initialization will fail. - EXPECT_FALSE(CreateHostImpl( - DefaultSettings(), - FakeLayerTreeFrameSink::Create3d(std::move(context_owned)))); + EXPECT_FALSE( + CreateHostImpl(DefaultSettings(), + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned)))); SetupScrollAndContentsLayers(gfx::Size(100, 100)); @@ -1643,7 +1656,7 @@ TEST_F(LayerTreeHostImplTest, GetSnapFlingInfoWhenZoomed) { InputHandlerScrollResult result = host_impl_->ScrollBy(UpdateState(scroll_position, delta).get()); EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), overflow->CurrentScrollOffset()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_offset); + EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_visual_offset); gfx::Vector2dF initial_offset, target_offset; EXPECT_TRUE(host_impl_->GetSnapFlingInfo(gfx::Vector2dF(10, 10), @@ -2589,8 +2602,7 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) { TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) { ui::LatencyInfo latency_info; latency_info.set_trace_id(5); - latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, - 1234); + latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0); std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(latency_info)); @@ -3532,7 +3544,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->DidBecomeActive(); host_impl_->active_tree()->HandleScrollbarShowRequestsFromMain(); - host_impl_->active_tree()->set_local_surface_id( + host_impl_->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); DrawFrame(); @@ -4884,11 +4896,9 @@ class MissingTextureAnimatingLayer : public DidDrawCheckLayer { bool tile_missing, bool had_incomplete_tile, bool animating, - ResourceProvider* resource_provider, scoped_refptr<AnimationTimeline> timeline) { return base::WrapUnique(new MissingTextureAnimatingLayer( - tree_impl, id, tile_missing, had_incomplete_tile, animating, - resource_provider, timeline)); + tree_impl, id, tile_missing, had_incomplete_tile, animating, timeline)); } void AppendQuads(viz::RenderPass* render_pass, @@ -4906,7 +4916,6 @@ class MissingTextureAnimatingLayer : public DidDrawCheckLayer { bool tile_missing, bool had_incomplete_tile, bool animating, - ResourceProvider* resource_provider, scoped_refptr<AnimationTimeline> timeline) : DidDrawCheckLayer(tree_impl, id), tile_missing_(tile_missing), @@ -4946,8 +4955,7 @@ static void CreateLayerFromState( static int layer_id = 2; root->test_properties()->AddChild(MissingTextureAnimatingLayer::Create( root->layer_tree_impl(), layer_id++, state.has_missing_tile, - state.has_incomplete_tile, state.is_animating, - root->layer_tree_impl()->resource_provider(), timeline)); + state.has_incomplete_tile, state.is_animating, timeline)); auto* layer = static_cast<DidDrawCheckLayer*>(root->test_properties()->children.back()); if (state.has_copy_request) @@ -6692,9 +6700,11 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedLatchToChild) { EXPECT_EQ(gfx::ScrollOffset(0, 50), child_layer->CurrentScrollOffset()); host_impl_->DidFinishImplFrame(); - // Second ScrollAnimated should still latch to the grand_child_layer. + // Second ScrollAnimated should still latch to the grand_child_layer. Since it + // is already at its extent and no scrolling happens, the scroll result must + // be ignored. EXPECT_EQ( - InputHandler::SCROLL_ON_IMPL_THREAD, + InputHandler::SCROLL_IGNORED, host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, -100)).thread); begin_frame_args.frame_time = @@ -8364,15 +8374,10 @@ class BlendStateCheckLayer : public LayerImpl { quads_appended_(false), quad_rect_(5, 5, 5, 5), quad_visible_rect_(5, 5, 5, 5) { - if (tree_impl->context_provider()) { - resource_id_ = resource_provider->CreateGpuTextureResource( - gfx::Size(1, 1), viz::ResourceTextureHint::kDefault, viz::RGBA_8888, - gfx::ColorSpace()); - } else { - resource_id_ = resource_provider->CreateBitmapResource( - gfx::Size(1, 1), gfx::ColorSpace(), viz::RGBA_8888); - } - resource_provider->AllocateForTesting(resource_id_); + resource_id_ = resource_provider->ImportResource( + viz::TransferableResource::MakeSoftware( + viz::SharedBitmap::GenerateId(), gfx::Size(1, 1), viz::RGBA_8888), + viz::SingleReleaseCallback::Create(base::DoNothing())); SetBounds(gfx::Size(10, 10)); SetDrawsContent(true); } @@ -9053,10 +9058,11 @@ class FakeDrawableLayerImpl : public LayerImpl { // submitted to the LayerTreeFrameSink, where it should request to swap only // the sub-buffer that is damaged. TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + gl_owned->set_have_post_sub_buffer(true); scoped_refptr<viz::TestContextProvider> context_provider( - viz::TestContextProvider::Create()); + viz::TestContextProvider::Create(std::move(gl_owned))); context_provider->BindToCurrentThread(); - context_provider->TestContext3d()->set_have_post_sub_buffer(true); std::unique_ptr<FakeLayerTreeFrameSink> layer_tree_frame_sink( FakeLayerTreeFrameSink::Create3d(context_provider)); @@ -9090,7 +9096,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { root->test_properties()->AddChild(std::move(child)); layer_tree_host_impl->active_tree()->SetRootLayerForTesting(std::move(root)); layer_tree_host_impl->active_tree()->BuildPropertyTreesForTesting(); - layer_tree_host_impl->active_tree()->set_local_surface_id( + layer_tree_host_impl->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); TestFrameData frame; @@ -9190,11 +9196,10 @@ class FakeLayerWithQuads : public LayerImpl { }; TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { - std::unique_ptr<TestWebGraphicsContext3D> context = - TestWebGraphicsContext3D::Create(); - TestWebGraphicsContext3D* context3d = context.get(); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + viz::TestGLES2Interface* gl = gl_owned.get(); std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink( - FakeLayerTreeFrameSink::Create3d(std::move(context))); + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned))); CreateHostImpl(DefaultSettings(), std::move(layer_tree_frame_sink)); std::unique_ptr<LayerImpl> root_layer = @@ -9215,27 +9220,21 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { host_impl_->active_tree()->SetRootLayerForTesting(std::move(root_layer)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); - EXPECT_GT(context3d->NumTextures(), 0u); + EXPECT_GT(gl->NumTextures(), 0u); // Kill the layer tree. host_impl_->active_tree()->DetachLayers(); // There should be no textures left in use after. - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); } -class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D { - public: - MOCK_METHOD1(useProgram, void(GLuint program)); - MOCK_METHOD4(drawElements, - void(GLenum mode, GLsizei count, GLenum type, GLintptr offset)); -}; TEST_F(LayerTreeHostImplTest, HasTransparentBackground) { SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1)); @@ -9548,8 +9547,7 @@ TEST_F(LayerTreeHostImplTest, MemoryLimits) { AnimationHost::CreateForTesting(ThreadInstance::IMPL), 0, nullptr); // Gpu compositing. - layer_tree_frame_sink_ = - FakeLayerTreeFrameSink::Create3d(TestWebGraphicsContext3D::Create()); + layer_tree_frame_sink_ = FakeLayerTreeFrameSink::Create3d(); host_impl_->SetVisible(true); host_impl_->InitializeRenderer(layer_tree_frame_sink_.get()); { @@ -9712,58 +9710,58 @@ TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) { } TEST_F(LayerTreeHostImplTest, UIResourceManagement) { - std::unique_ptr<TestWebGraphicsContext3D> context = - TestWebGraphicsContext3D::Create(); - TestWebGraphicsContext3D* context3d = context.get(); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + viz::TestGLES2Interface* gl = gl_owned.get(); + std::unique_ptr<FakeLayerTreeFrameSink> layer_tree_frame_sink = - FakeLayerTreeFrameSink::Create3d(); + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned)); CreateHostImpl(DefaultSettings(), std::move(layer_tree_frame_sink)); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); UIResourceId ui_resource_id = 1; bool is_opaque = false; UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque); host_impl_->CreateUIResource(ui_resource_id, bitmap); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); viz::ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id1); // Multiple requests with the same id is allowed. The previous texture is // deleted. host_impl_->CreateUIResource(ui_resource_id, bitmap); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); viz::ResourceId id2 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id2); EXPECT_NE(id1, id2); // Deleting invalid UIResourceId is allowed and does not change state. host_impl_->DeleteUIResource(-1); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); // Should return zero for invalid UIResourceId. Number of textures should // not change. EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1)); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); host_impl_->DeleteUIResource(ui_resource_id); EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id)); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); // Should not change state for multiple deletion on one UIResourceId host_impl_->DeleteUIResource(ui_resource_id); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); } TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { - std::unique_ptr<TestWebGraphicsContext3D> context = - TestWebGraphicsContext3D::Create(); - TestWebGraphicsContext3D* context3d = context.get(); - context3d->set_support_compressed_texture_etc1(true); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + gl_owned->set_support_compressed_texture_etc1(true); + viz::TestGLES2Interface* gl = gl_owned.get(); + CreateHostImpl(DefaultSettings(), - FakeLayerTreeFrameSink::Create3d(std::move(context))); + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned))); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); gfx::Size size(4, 4); // SkImageInfo has no support for ETC1. The |info| below contains the right @@ -9776,7 +9774,7 @@ TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { UIResourceBitmap bitmap(std::move(pixel_ref), size); UIResourceId ui_resource_id = 1; host_impl_->CreateUIResource(ui_resource_id, bitmap); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); viz::ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id1); } @@ -9854,9 +9852,8 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) { constexpr double refresh_rate = 60.0; auto layer_tree_frame_sink = std::make_unique<viz::TestLayerTreeFrameSink>( context_provider, viz::TestContextProvider::CreateWorker(), nullptr, - nullptr, viz::RendererSettings(), - base::ThreadTaskRunnerHandle::Get().get(), synchronous_composite, - disable_display_vsync, refresh_rate); + viz::RendererSettings(), base::ThreadTaskRunnerHandle::Get().get(), + synchronous_composite, disable_display_vsync, refresh_rate); layer_tree_frame_sink->SetClient(&test_client); CreateHostImpl(DefaultSettings(), std::move(layer_tree_frame_sink)); @@ -10257,8 +10254,7 @@ TEST_F(LayerTreeHostImplLatencyInfoRendererTest, // component attached via LatencyInfoSwapPromise. ui::LatencyInfo latency_info; latency_info.set_trace_id(5); - latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, - 0); + latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0); std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(latency_info)); host_impl_->active_tree()->QueuePinnedSwapPromise(std::move(swap_promise)); @@ -10313,8 +10309,7 @@ TEST_F(LayerTreeHostImplLatencyInfoUITest, // component attached via LatencyInfoSwapPromise. ui::LatencyInfo latency_info; latency_info.set_trace_id(5); - latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, - 0); + latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0); std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(latency_info)); host_impl_->active_tree()->QueuePinnedSwapPromise(std::move(swap_promise)); @@ -11626,6 +11621,52 @@ TEST_F(LayerTreeHostImplTest, OnDrawConstraintSetNeedsRedraw) { EXPECT_FALSE(last_on_draw_frame_->has_no_damage); } +// TODO(gyuyoung): OnMemoryPressure disabled on ASAN, TSAN, Android, windows +// due to the test failure. Will be handled on +// http://crbug.com/839687. +#if defined(OS_WIN) || defined(OS_ANDROID) || defined(ADDRESS_SANITIZER) || \ + defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) || \ + defined(LEAK_SANITIZER) +#define MAYBE_OnMemoryPressure DISABLED_OnMemoryPressure +#else +#define MAYBE_OnMemoryPressure OnMemoryPressure +#endif + +TEST_F(LayerTreeHostImplTest, MAYBE_OnMemoryPressure) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableLowEndDeviceMode); + + const gfx::Size viewport_size(100, 100); + host_impl_->SetViewportSize(viewport_size); + host_impl_->CreatePendingTree(); + scoped_refptr<FakeRasterSource> raster_source( + FakeRasterSource::CreateFilled(viewport_size)); + std::unique_ptr<FakePictureLayerImpl> layer( + FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(), + 11, raster_source)); + layer->SetBounds(viewport_size); + layer->SetDrawsContent(true); + host_impl_->pending_tree()->SetRootLayerForTesting(std::move(layer)); + host_impl_->pending_tree()->BuildPropertyTreesForTesting(); + host_impl_->ActivateSyncTree(); + const gfx::Transform draw_transform; + host_impl_->OnDraw(draw_transform, gfx::Rect(viewport_size), false); + + std::unique_ptr<base::ProcessMetrics> metric( + base::ProcessMetrics::CreateCurrentProcessMetrics()); + size_t current_memory_usage = metric->GetMallocUsage(); + + base::MemoryPressureListener::SimulatePressureNotification( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); + base::RunLoop().RunUntilIdle(); + + size_t memory_usage_after_memory_pressure = metric->GetMallocUsage(); + + // Memory usage after the memory pressure should be less than previous one. + EXPECT_LT(memory_usage_after_memory_pressure, current_memory_usage); + EXPECT_FALSE(host_impl_->use_gpu_rasterization()); +} + // 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) { @@ -13464,8 +13505,7 @@ TEST_F(LayerTreeHostImplTest, RecomputeGpuRasterOnLayerTreeFrameSinkChange) { host_impl_->SetVisible(true); // InitializeRenderer with a gpu-raster enabled output surface. - auto gpu_raster_layer_tree_frame_sink = - FakeLayerTreeFrameSink::Create3d(TestWebGraphicsContext3D::Create()); + auto gpu_raster_layer_tree_frame_sink = FakeLayerTreeFrameSink::Create3d(); host_impl_->InitializeRenderer(gpu_raster_layer_tree_frame_sink.get()); EXPECT_TRUE(host_impl_->use_gpu_rasterization()); @@ -13743,7 +13783,10 @@ TEST_F(LayerTreeHostImplTest, CheckerImagingTileInvalidation) { std::unique_ptr<FakeRecordingSource> recording_source = FakeRecordingSource::CreateFilledRecordingSource(layer_size); PaintImage checkerable_image = - CreateDiscardablePaintImage(gfx::Size(500, 500)); + PaintImageBuilder::WithCopy( + CreateDiscardablePaintImage(gfx::Size(500, 500))) + .set_decoding_mode(PaintImage::DecodingMode::kAsync) + .TakePaintImage(); recording_source->add_draw_image(checkerable_image, gfx::Point(0, 0)); SkColor non_solid_color = SkColorSetARGB(128, 45, 56, 67); @@ -13773,6 +13816,11 @@ TEST_F(LayerTreeHostImplTest, CheckerImagingTileInvalidation) { root->SetDrawsContent(true); pending_tree->BuildPropertyTreesForTesting(); + // Update the decoding state map for the tracker so it knows the correct + // decoding preferences for the image. + host_impl_->tile_manager()->checker_image_tracker().UpdateImageDecodingHints( + raster_source->TakeDecodingModeMap()); + // CompleteCommit which should perform a PrepareTiles, adding tilings for the // root layer, each one having a raster task. host_impl_->CommitComplete(); @@ -14251,5 +14299,211 @@ TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToRenderFrameMetadata) { EXPECT_TRUE(selection_2.end.visible()); } +// Tests ScrollBy() to see if the method sets the scroll tree's currently +// scrolling node and the ScrollState properly. +TEST_F(LayerTreeHostImplTest, ScrollByScrollingNode) { + SetupScrollAndContentsLayers(gfx::Size(100, 100)); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + // Create a ScrollState object with no scrolling element. + ScrollStateData scroll_state_data; + scroll_state_data.set_current_native_scrolling_element(ElementId()); + std::unique_ptr<ScrollState> scroll_state(new ScrollState(scroll_state_data)); + + ScrollTree& scroll_tree = + host_impl_->active_tree()->property_trees()->scroll_tree; + + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_ + ->ScrollBegin(BeginState(gfx::Point()).get(), + InputHandler::TOUCHSCREEN) + .thread); + + ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + EXPECT_TRUE(scroll_node); + + host_impl_->ScrollBy(scroll_state.get()); + + // Check to see the scroll tree's currently scrolling node is + // still the same. |scroll_state|'s scrolling node should match + // it. + EXPECT_EQ(scroll_node, scroll_tree.CurrentlyScrollingNode()); + EXPECT_EQ(scroll_state->data()->current_native_scrolling_node(), + scroll_tree.CurrentlyScrollingNode()); + EXPECT_EQ(scroll_state->data()->current_native_scrolling_element(), + scroll_tree.CurrentlyScrollingNode()->element_id); + + // Set the scroll tree's currently scrolling node to null. Calling + // ScrollBy() should set the node to the one inside |scroll_state|. + host_impl_->active_tree()->SetCurrentlyScrollingNode(nullptr); + EXPECT_FALSE(scroll_tree.CurrentlyScrollingNode()); + + host_impl_->ScrollBy(scroll_state.get()); + + EXPECT_EQ(scroll_node, scroll_tree.CurrentlyScrollingNode()); + EXPECT_EQ(scroll_state->data()->current_native_scrolling_node(), + scroll_tree.CurrentlyScrollingNode()); + EXPECT_EQ(scroll_state->data()->current_native_scrolling_element(), + scroll_tree.CurrentlyScrollingNode()->element_id); +} + +class HitTestRegionListGeneratingLayerTreeHostImplTest + : public LayerTreeHostImplTest { + public: + bool CreateHostImpl( + const LayerTreeSettings& settings, + std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink) override { + // Enable hit test data generation with the CompositorFrame. + LayerTreeSettings new_settings = settings; + new_settings.build_hit_test_data = true; + return CreateHostImplWithTaskRunnerProvider( + new_settings, std::move(layer_tree_frame_sink), &task_runner_provider_); + } +}; + +// When disabled, no HitTestRegionList should be generated. +// Test to ensure that hit test data is created correctly from the active layer +// tree. +TEST_F(LayerTreeHostImplTest, DisabledBuildHitTestData) { + // Setup surface layers in LayerTreeHostImpl. + host_impl_->CreatePendingTree(); + host_impl_->ActivateSyncTree(); + host_impl_->SetViewportSize(gfx::Size(1024, 768)); + + std::unique_ptr<LayerImpl> root = + LayerImpl::Create(host_impl_->active_tree(), 1); + std::unique_ptr<SurfaceLayerImpl> surface_child = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 3); + + surface_child->SetPosition(gfx::PointF(50, 50)); + surface_child->SetBounds(gfx::Size(100, 100)); + surface_child->SetDrawsContent(true); + surface_child->SetSurfaceHitTestable(true); + + root->test_properties()->AddChild(std::move(surface_child)); + host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + base::Optional<viz::HitTestRegionList> hit_test_region_list = + host_impl_->BuildHitTestData(); + EXPECT_FALSE(hit_test_region_list); +} + +// Test to ensure that hit test data is created correctly from the active layer +// tree. +TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, BuildHitTestData) { + // Setup surface layers in LayerTreeHostImpl. + host_impl_->CreatePendingTree(); + host_impl_->ActivateSyncTree(); + + // The structure of the layer tree: + // +-Root (1024x768) + // +---intermediate_layer (200, 300), 200x200 + // +-----surface_child1 (50, 50), 100x100, Rotate(45) + // +---surface_child2 (450, 300), 100x100 + // +---overlapping_layer (500, 350), 200x200 + std::unique_ptr<LayerImpl> intermediate_layer = + LayerImpl::Create(host_impl_->active_tree(), 2); + std::unique_ptr<SurfaceLayerImpl> surface_child1 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 3); + std::unique_ptr<SurfaceLayerImpl> surface_child2 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 4); + std::unique_ptr<LayerImpl> overlapping_layer = + LayerImpl::Create(host_impl_->active_tree(), 5); + + host_impl_->SetViewportSize(gfx::Size(1024, 768)); + + intermediate_layer->SetPosition(gfx::PointF(200, 300)); + intermediate_layer->SetBounds(gfx::Size(200, 200)); + + surface_child1->SetPosition(gfx::PointF(50, 50)); + surface_child1->SetBounds(gfx::Size(100, 100)); + gfx::Transform rotate; + rotate.Rotate(45); + surface_child1->test_properties()->transform = rotate; + surface_child1->SetDrawsContent(true); + surface_child1->SetSurfaceHitTestable(true); + + surface_child2->SetPosition(gfx::PointF(450, 300)); + surface_child2->SetBounds(gfx::Size(100, 100)); + surface_child2->SetDrawsContent(true); + surface_child2->SetSurfaceHitTestable(true); + + overlapping_layer->SetPosition(gfx::PointF(500, 350)); + overlapping_layer->SetBounds(gfx::Size(200, 200)); + overlapping_layer->SetDrawsContent(true); + + viz::LocalSurfaceId child_local_surface_id(2, + base::UnguessableToken::Create()); + viz::FrameSinkId frame_sink_id(2, 0); + viz::SurfaceId child_surface_id(frame_sink_id, child_local_surface_id); + surface_child1->SetPrimarySurfaceId(child_surface_id, base::nullopt); + surface_child2->SetPrimarySurfaceId(child_surface_id, base::nullopt); + + std::unique_ptr<LayerImpl> root = + LayerImpl::Create(host_impl_->active_tree(), 1); + host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); + intermediate_layer->test_properties()->AddChild(std::move(surface_child1)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(intermediate_layer)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(surface_child2)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(overlapping_layer)); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + constexpr gfx::Rect kFrameRect(0, 0, 1024, 768); + + base::Optional<viz::HitTestRegionList> hit_test_region_list = + host_impl_->BuildHitTestData(); + // Generating HitTestRegionList should have been enabled for this test. + ASSERT_TRUE(hit_test_region_list); + + // Since surface_child2 draws in front of surface_child1, it should also be in + // the front of the hit test region list. + uint32_t expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestMine; + EXPECT_EQ(expected_flags, hit_test_region_list->flags); + EXPECT_EQ(kFrameRect, hit_test_region_list->bounds); + EXPECT_EQ(2u, hit_test_region_list->regions.size()); + + EXPECT_EQ(child_surface_id.frame_sink_id(), + hit_test_region_list->regions[1].frame_sink_id); + expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestChildSurface; + EXPECT_EQ(expected_flags, hit_test_region_list->regions[1].flags); + gfx::Transform child1_transform; + child1_transform.Rotate(-45); + child1_transform.Translate(-250, -350); + EXPECT_TRUE(child1_transform.ApproximatelyEqual( + hit_test_region_list->regions[1].transform)); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), + hit_test_region_list->regions[1].rect.ToString()); + + EXPECT_EQ(child_surface_id.frame_sink_id(), + hit_test_region_list->regions[0].frame_sink_id); + expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestChildSurface | + viz::HitTestRegionFlags::kHitTestAsk; + EXPECT_EQ(expected_flags, hit_test_region_list->regions[0].flags); + gfx::Transform child2_transform; + child2_transform.Translate(-450, -300); + EXPECT_TRUE(child2_transform.ApproximatelyEqual( + hit_test_region_list->regions[0].transform)); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), + hit_test_region_list->regions[0].rect.ToString()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc index 92765547065..871e1a10a17 100644 --- a/chromium/cc/trees/layer_tree_host_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_perftest.cc @@ -59,9 +59,8 @@ class LayerTreeHostPerfTest : public LayerTreeTest { !layer_tree_host()->GetSettings().single_thread_proxy_scheduler; return std::make_unique<viz::TestLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), - shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings, - ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync, - refresh_rate); + gpu_memory_buffer_manager(), renderer_settings, ImplThreadTaskRunner(), + synchronous_composite, disable_display_vsync, refresh_rate); } void BeginTest() override { @@ -140,7 +139,8 @@ class LayerTreeHostPerfTestJsonReader : public LayerTreeHostPerfTest { void ReadTestFile(const std::string& name) { base::FilePath test_data_dir; - ASSERT_TRUE(PathService::Get(viz::Paths::DIR_TEST_DATA, &test_data_dir)); + ASSERT_TRUE( + base::PathService::Get(viz::Paths::DIR_TEST_DATA, &test_data_dir)); base::FilePath json_file = test_data_dir.AppendASCII(name + ".json"); ASSERT_TRUE(base::ReadFileToString(json_file, &json_)); } diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc index c0706014c1a..378d4338879 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc @@ -37,8 +37,8 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlur) { 2.f, SkBlurImageFilter::kClamp_TileMode)); blur->SetBackgroundFilters(filters); -#if defined(OS_WIN) - // Windows has 436 pixels off by 1: crbug.com/259915 +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) + // Windows and ARM64 have 436 pixels off by 1: crbug.com/259915 float percentage_pixels_large_error = 1.09f; // 436px / (200*200) float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; @@ -79,9 +79,14 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOutsets) { 5.f, SkBlurImageFilter::kClamp_TileMode)); blur->SetBackgroundFilters(filters); -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(_MIPS_ARCH_LOONGSON) || defined(ARCH_CPU_ARM64) +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) // Windows has 5.9325% pixels by at most 2: crbug.com/259922 float percentage_pixels_large_error = 6.0f; +#else + // Loongson has 8.685% pixels by at most 2: crbug.com/819110 + float percentage_pixels_large_error = 8.7f; +#endif float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 2.f; int large_error_allowed = 2; @@ -141,12 +146,17 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) { 2.f, SkBlurImageFilter::kClamp_TileMode)); blur->SetBackgroundFilters(filters); +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) // Windows has 116 pixels off by at most 2: crbug.com/225027 float percentage_pixels_large_error = 0.3f; // 116px / (200*200), rounded up + int large_error_allowed = 2; +#else + float percentage_pixels_large_error = 0.25f; // 96px / (200*200), rounded up + int large_error_allowed = 1; +#endif float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; - int large_error_allowed = 2; int small_error_allowed = 0; pixel_comparator_.reset(new FuzzyPixelComparator( true, // discard_alpha @@ -414,12 +424,21 @@ class ImageScaledBackgroundFilter : public LayerTreeHostFiltersPixelTest { filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f)); filter->SetBackgroundFilters(filters); +#if defined(OS_WIN) || defined(_MIPS_ARCH_LOONGSON) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) // Windows has 153 pixels off by at most 2: crbug.com/225027 float percentage_pixels_large_error = 0.3825f; // 153px / (200*200) + int large_error_allowed = 2; +#elif defined(_MIPS_ARCH_LOONGSON) + // Loongson has 2 pixels off by at most 2: crbug.com/819075 + float percentage_pixels_large_error = 0.005f; // 2px / (200*200) + int large_error_allowed = 2; +#else + float percentage_pixels_large_error = 0.0325f; // 13px / (200*200) + int large_error_allowed = 1; +#endif float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; - int large_error_allowed = 2; int small_error_allowed = 0; pixel_comparator_.reset(new FuzzyPixelComparator( true, // discard_alpha @@ -726,8 +745,8 @@ class RotatedDropShadowFilterTest : public LayerTreeHostFiltersPixelTest { background->AddChild(child); -#if defined(OS_WIN) - // Windows has 3 pixels off by 1: crbug.com/259915 +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) + // Windows and ARM64 have 3 pixels off by 1: crbug.com/259915 float percentage_pixels_large_error = 0.00333334f; // 3px / (300*300) float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; @@ -941,9 +960,15 @@ class BlurFilterWithClip : public LayerTreeHostFiltersPixelTest { // Force the allocation a larger textures. set_enlarge_texture_amount(gfx::Size(50, 50)); +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) // Windows has 1880 pixels off by 1: crbug.com/259915 float percentage_pixels_large_error = 4.7f; // 1880px / (200*200) +#else + // Differences in floating point calculation on ARM means a small percentage + // of pixels will have small differences. + float percentage_pixels_large_error = 2.76f; // 1104px / (200*200) +#endif float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; int large_error_allowed = 2; diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc index 02e0e7bf246..6a6cfa4d11e 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -312,13 +312,13 @@ TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, float average_error_allowed_in_bad_pixels = 100.0f; int large_error_allowed = 256; int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( true, // discard_alpha percentage_pixels_large_error, percentage_pixels_small_error, average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + small_error_allowed); RunPixelResourceTest(background, base::FilePath( @@ -363,13 +363,13 @@ TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, float average_error_allowed_in_bad_pixels = 256.0f; int large_error_allowed = 256; int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( true, // discard_alpha percentage_pixels_large_error, percentage_pixels_small_error, average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + small_error_allowed); RunPixelResourceTest(background, base::FilePath( @@ -428,13 +428,21 @@ class LayerTreeHostMaskAsBlendingPixelTest average_error_allowed_in_bad_pixels = 3.5f; large_error_allowed = 15; small_error_allowed = 1; + } else { +#if defined(ARCH_CPU_ARM64) + // Differences in floating point calculation on ARM means a small + // percentage of pixels will be off by 1. + percentage_pixels_error = 0.112f; + average_error_allowed_in_bad_pixels = 1.f; + large_error_allowed = 1; +#endif } - pixel_comparator_.reset(new FuzzyPixelComparator( + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( false, // discard_alpha percentage_pixels_error, percentage_pixels_small_error, average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + small_error_allowed); } static scoped_refptr<Layer> CreateCheckerboardLayer(const gfx::Size& bounds) { @@ -714,6 +722,59 @@ TEST_P(LayerTreeHostMaskAsBlendingPixelTest, RotatedClippedCircleUnderflow) { "mask_as_blending_rotated_circle_underflow.png"))); } +TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, + MaskOfLayerWithBackgroundFilterAndBlend) { + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(128, 128), SK_ColorWHITE); + + gfx::Size picture_bounds(128, 128); + CheckerContentLayerClient picture_client_vertical(picture_bounds, + SK_ColorGREEN, true); + scoped_refptr<PictureLayer> picture_vertical = + PictureLayer::Create(&picture_client_vertical); + picture_vertical->SetBounds(picture_bounds); + picture_vertical->SetIsDrawable(true); + + CheckerContentLayerClient picture_client_horizontal(picture_bounds, + SK_ColorMAGENTA, false); + scoped_refptr<PictureLayer> picture_horizontal = + PictureLayer::Create(&picture_client_horizontal); + picture_horizontal->SetBounds(picture_bounds); + picture_horizontal->SetIsDrawable(true); + picture_horizontal->SetContentsOpaque(false); + picture_horizontal->SetBlendMode(SkBlendMode::kMultiply); + + FilterOperations filters; + filters.Append(FilterOperation::CreateGrayscaleFilter(1.0)); + picture_horizontal->SetBackgroundFilters(filters); + + background->AddChild(picture_vertical); + background->AddChild(picture_horizontal); + + gfx::Size mask_bounds(128, 128); + CircleContentLayerClient mask_client(mask_bounds); + scoped_refptr<PictureLayer> mask = PictureLayer::Create(&mask_client); + mask->SetBounds(mask_bounds); + mask->SetIsDrawable(true); + mask->SetLayerMaskType(mask_type_); + picture_horizontal->SetMaskLayer(mask.get()); + + float percentage_pixels_large_error = 0.062f; // 0.062%, ~10px / (128*128) + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 200.0f; + int large_error_allowed = 256; + int small_error_allowed = 0; + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed); + + RunPixelResourceTest(background, + base::FilePath(FILE_PATH_LITERAL( + "mask_of_background_filter_and_blend.png"))); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc index a4f98ae353a..b251df562ab 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc @@ -150,7 +150,7 @@ TEST_F(LayerTreeHostScrollbarsPixelTest, HugeTransformScale) { background->AddChild(layer); scoped_refptr<TestInProcessContextProvider> context( - new TestInProcessContextProvider(nullptr, false)); + new TestInProcessContextProvider(/*enable_oop_rasterization=*/false)); context->BindToCurrentThread(); int max_texture_size = 0; context->ContextGL()->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc index bf42914b95d..eabe1909a4f 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc @@ -60,13 +60,13 @@ class LayerTreeHostTilesPixelTest : public LayerTreePixelTest { case PARTIAL_GPU_LOW_BIT_DEPTH: settings->gpu_rasterization_forced = true; settings->use_partial_raster = true; - settings->preferred_tile_format = viz::RGBA_4444; + settings->use_rgba_4444 = true; settings->unpremultiply_and_dither_low_bit_depth_tiles = true; break; case FULL_GPU_LOW_BIT_DEPTH: settings->gpu_rasterization_forced = true; settings->use_partial_raster = false; - settings->preferred_tile_format = viz::RGBA_4444; + settings->use_rgba_4444 = true; settings->unpremultiply_and_dither_low_bit_depth_tiles = true; break; } diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index acbd577abcd..e66bf23fa85 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -65,6 +65,7 @@ #include "components/viz/service/display/output_surface.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/fake_output_surface.h" +#include "components/viz/test/test_gles2_interface.h" #include "components/viz/test/test_layer_tree_frame_sink.h" #include "components/viz/test/test_web_graphics_context_3d.h" #include "gpu/GLES2/gl2extchromium.h" @@ -460,14 +461,14 @@ class LayerTreeHostContextCacheTest : public LayerTreeHostTest { // Create the main viz::ContextProvider with a MockContextSupport. auto main_support = std::make_unique<MockContextSupport>(); mock_main_context_support_ = main_support.get(); - auto test_main_context_provider = viz::TestContextProvider::Create( - viz::TestWebGraphicsContext3D::Create(), std::move(main_support)); + auto test_main_context_provider = + viz::TestContextProvider::Create(std::move(main_support)); // Create the main viz::ContextProvider with a MockContextSupport. auto worker_support = std::make_unique<MockContextSupport>(); mock_worker_context_support_ = worker_support.get(); - auto test_worker_context_provider = viz::TestContextProvider::CreateWorker( - viz::TestWebGraphicsContext3D::Create(), std::move(worker_support)); + auto test_worker_context_provider = + viz::TestContextProvider::CreateWorker(std::move(worker_support)); // At init, visibility is set to true, so SetAggressivelyFreeResources will // be disabled. @@ -563,7 +564,8 @@ class LayerTreeHostFreesWorkerContextResourcesOnZeroMemoryLimitSynchronous } }; -SINGLE_AND_MULTI_THREAD_TEST_F( +// Android Webview only runs in multi-threaded compositing mode. +MULTI_THREAD_TEST_F( LayerTreeHostFreesWorkerContextResourcesOnZeroMemoryLimitSynchronous); // Test if the LTH successfully frees main and worker resources when the @@ -1231,9 +1233,12 @@ class LayerTreeHostTestEarlyDamageCheckStops : public LayerTreeHostTest { } } + void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { + PostSetNeedsCommitToMainThread(); + } + void DidInvalidateLayerTreeFrameSink(LayerTreeHostImpl* impl) override { int frame_number = impl->active_tree()->source_frame_number(); - // Frames 0 and 1 invalidate because the early damage check is not enabled // during this setup. But frames 1 and 2 are not damaged, so the early // check should prevent frame 2 from invalidating. @@ -1250,8 +1255,6 @@ class LayerTreeHostTestEarlyDamageCheckStops : public LayerTreeHostTest { EndTest(); return; } - - PostSetNeedsCommitToMainThread(); } void AfterTest() override { @@ -1269,9 +1272,7 @@ class LayerTreeHostTestEarlyDamageCheckStops : public LayerTreeHostTest { // This behavior is specific to Android WebView, which only uses // multi-threaded compositor. -// Flaky on Win7 Tests (dbg)(1). https://crbug.com/813578 -// Flaky on linux_chromium_tsan_rel_ng. https://crbug.com/822473 -// MULTI_THREAD_TEST_F(LayerTreeHostTestEarlyDamageCheckStops); +MULTI_THREAD_TEST_F(LayerTreeHostTestEarlyDamageCheckStops); // Verify CanDraw() is false until first commit. class LayerTreeHostTestCantDrawBeforeCommit : public LayerTreeHostTest { @@ -2241,7 +2242,7 @@ class LayerTreeHostTestNoExtraCommitFromScrollbarInvalidate // a second commit as a result. layer_tree_host()->SetViewportSizeAndScale( layer_tree_host()->device_viewport_size(), 4.f, - layer_tree_host()->local_surface_id()); + layer_tree_host()->local_surface_id_from_parent()); break; default: // No extra commits. @@ -2286,7 +2287,7 @@ class LayerTreeHostTestDeviceScaleFactorChange : public LayerTreeHostTest { if (layer_tree_host()->SourceFrameNumber() == 1) { layer_tree_host()->SetViewportSizeAndScale( layer_tree_host()->device_viewport_size(), 4.f, - layer_tree_host()->local_surface_id()); + layer_tree_host()->local_surface_id_from_parent()); } } @@ -3811,7 +3812,6 @@ class OnDrawLayerTreeFrameSink : public viz::TestLayerTreeFrameSink { OnDrawLayerTreeFrameSink( scoped_refptr<viz::ContextProvider> compositor_context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider, - viz::SharedBitmapManager* shared_bitmap_manager, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, const viz::RendererSettings& renderer_settings, base::SingleThreadTaskRunner* task_runner, @@ -3820,7 +3820,6 @@ class OnDrawLayerTreeFrameSink : public viz::TestLayerTreeFrameSink { base::Closure invalidate_callback) : TestLayerTreeFrameSink(std::move(compositor_context_provider), std::move(worker_context_provider), - shared_bitmap_manager, gpu_memory_buffer_manager, renderer_settings, task_runner, @@ -3862,8 +3861,8 @@ class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor base::Unretained(this)); auto frame_sink = std::make_unique<OnDrawLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), - shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings, - ImplThreadTaskRunner(), false /* synchronous_composite */, refresh_rate, + gpu_memory_buffer_manager(), renderer_settings, ImplThreadTaskRunner(), + false /* synchronous_composite */, refresh_rate, std::move(on_draw_callback)); layer_tree_frame_sink_ = frame_sink.get(); return std::move(frame_sink); @@ -5710,19 +5709,22 @@ class LayerTreeHostTestBreakSwapPromiseForVisibility void SetVisibleFalseAndQueueSwapPromise() { layer_tree_host()->SetVisible(false); - std::unique_ptr<SwapPromise> swap_promise( - new TestSwapPromise(&swap_promise_result_)); + auto swap_promise = + std::make_unique<TestSwapPromise>(&swap_promise_result_); layer_tree_host()->GetSwapPromiseManager()->QueueSwapPromise( std::move(swap_promise)); } void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl, const viz::BeginFrameArgs& args) override { - MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&LayerTreeHostTestBreakSwapPromiseForVisibility:: - SetVisibleFalseAndQueueSwapPromise, - base::Unretained(this))); + if (!sent_queue_request_) { + sent_queue_request_ = true; + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&LayerTreeHostTestBreakSwapPromiseForVisibility:: + SetVisibleFalseAndQueueSwapPromise, + base::Unretained(this))); + } } void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, @@ -5742,11 +5744,10 @@ class LayerTreeHostTestBreakSwapPromiseForVisibility } TestSwapPromiseResult swap_promise_result_; + bool sent_queue_request_ = false; }; -// Flaky: https://crbug.com/657910 -// SINGLE_AND_MULTI_THREAD_TEST_F( -// LayerTreeHostTestBreakSwapPromiseForVisibility); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestBreakSwapPromiseForVisibility); class SimpleSwapPromiseMonitor : public SwapPromiseMonitor { public: @@ -5895,41 +5896,43 @@ class LayerTreeHostTestHighResRequiredAfterEvictingUIResources LayerTreeHostTest::SetupTree(); ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()->GetUIResourceManager()); - client_.set_bounds(layer_tree_host()->root_layer()->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { + if (TestEnded()) + return; + host_impl->EvictAllUIResources(); // Existence of evicted UI resources will trigger NEW_CONTENT_TAKES_PRIORITY // mode. Active tree should require high-res to draw after entering this // mode to ensure that high-res tiles are also required for a pending tree // to be activated. EXPECT_TRUE(host_impl->RequiresHighResToDraw()); + + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce( + &LayerTreeHostTestHighResRequiredAfterEvictingUIResources:: + DeleteResourceAndEndTest, + base::Unretained(this))); } - void DidCommit() override { - int frame = layer_tree_host()->SourceFrameNumber(); - switch (frame) { - case 1: - PostSetNeedsCommitToMainThread(); - break; - case 2: - ui_resource_ = nullptr; - EndTest(); - break; - } + void DeleteResourceAndEndTest() { + // This must be destroyed before the test ends and tears down the + // LayerTreeHost. It causes another commit+activation though, which + // may run before the test exits. + ui_resource_ = nullptr; + EndTest(); } void AfterTest() override {} - FakeContentLayerClient client_; std::unique_ptr<FakeScopedUIResource> ui_resource_; }; -// This test is flaky, see http://crbug.com/386199 -// MULTI_THREAD_TEST_F(LayerTreeHostTestHighResRequiredAfterEvictingUIResources) +MULTI_THREAD_TEST_F(LayerTreeHostTestHighResRequiredAfterEvictingUIResources); class LayerTreeHostTestGpuRasterizationDefault : public LayerTreeHostTest { protected: @@ -6323,10 +6326,6 @@ class LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame : will_begin_impl_frame_count_(0), did_finish_impl_frame_count_(0) {} void BeginTest() override { - // Test terminates when a main frame is no longer expected so request that - // this message is actually sent. - layer_tree_host()->RequestBeginMainFrameNotExpected(true); - PostSetNeedsCommitToMainThread(); } @@ -6341,27 +6340,20 @@ class LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame did_finish_impl_frame_count_++; EXPECT_EQ(will_begin_impl_frame_count_, did_finish_impl_frame_count_); - // Request a number of commits to cause multiple impl frames. We expect to - // get one more impl frames than the number of commits requested because - // after a commit it takes one frame to become idle. - if (did_finish_impl_frame_count_ < kExpectedNumImplFrames - 1) - PostSetNeedsCommitToMainThread(); + // Trigger a new impl frame until we are done testing. + if (did_finish_impl_frame_count_ < kExpectedNumImplFrames) + PostSetNeedsRedrawToMainThread(); + else + EndTest(); } - void BeginMainFrameNotExpectedSoon() override { EndTest(); } - void AfterTest() override { EXPECT_GT(will_begin_impl_frame_count_, 0); EXPECT_GT(did_finish_impl_frame_count_, 0); EXPECT_EQ(will_begin_impl_frame_count_, did_finish_impl_frame_count_); - // TODO(mithro): Figure out why the multithread version of this test - // sometimes has one more frame then expected. Possibly related to - // http://crbug.com/443185 - if (!HasImplThread()) { - EXPECT_EQ(will_begin_impl_frame_count_, kExpectedNumImplFrames); - EXPECT_EQ(did_finish_impl_frame_count_, kExpectedNumImplFrames); - } + EXPECT_EQ(will_begin_impl_frame_count_, kExpectedNumImplFrames); + EXPECT_EQ(did_finish_impl_frame_count_, kExpectedNumImplFrames); } private: @@ -6593,9 +6585,8 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise !layer_tree_host()->GetSettings().single_thread_proxy_scheduler; return std::make_unique<viz::TestLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), - shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings, - ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync, - refresh_rate); + gpu_memory_buffer_manager(), renderer_settings, ImplThreadTaskRunner(), + synchronous_composite, disable_display_vsync, refresh_rate); } void BeginTest() override { @@ -7400,478 +7391,6 @@ 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()); - layer_tree_host()->outer_viewport_container_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()); - viz::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(viz::DrawQuad::SOLID_COLOR, - root_pass->quad_list.back()->material); - - EXPECT_EQ(viz::DrawQuad::RENDER_PASS, - root_pass->quad_list.front()->material); - const viz::RenderPassDrawQuad* render_pass_quad = - viz::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_; -}; - -class LayerTreeTestSingleTextureMaskLayerForSurfaceWithContentRectNotAtOrigin - : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestSingleTextureMaskLayerForSurfaceWithContentRectNotAtOrigin); - -class LayerTreeTestMultiTextureMaskLayerForSurfaceWithContentRectNotAtOrigin - : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMultiTextureMaskLayerForSurfaceWithContentRectNotAtOrigin); - -class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : 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<Layer> clipping_layer = Layer::Create(); - root->AddChild(clipping_layer); - - scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); - clipping_layer->AddChild(content_layer); - - scoped_refptr<FakePictureLayer> content_child_layer = - FakePictureLayer::Create(&client_); - content_layer->AddChild(content_child_layer); - - std::unique_ptr<RecordingSource> recording_source = - FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(50, 50)); - PaintFlags paint1, paint2; - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 0, 50, 40), paint1); - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 40, 50, 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::PointF clipping_origin(20.f, 10.f); - gfx::Size clipping_size(10, 20); - clipping_layer->SetBounds(clipping_size); - clipping_layer->SetPosition(clipping_origin); - clipping_layer->SetMasksToBounds(true); - - gfx::Size layer_size(50, 50); - content_layer->SetBounds(layer_size); - content_layer->SetPosition(gfx::PointF() - - clipping_origin.OffsetFromOrigin()); - - gfx::Size child_size(50, 50); - content_child_layer->SetBounds(child_size); - content_child_layer->SetPosition(gfx::PointF(20.f, 0.f)); - - gfx::Size mask_size(50, 50); - 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(); - client_.set_bounds(root->bounds()); - } - - 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()); - viz::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(viz::DrawQuad::SOLID_COLOR, - root_pass->quad_list.back()->material); - - // The surface is clipped to 10x20. - EXPECT_EQ(viz::DrawQuad::RENDER_PASS, - root_pass->quad_list.front()->material); - const viz::RenderPassDrawQuad* render_pass_quad = - viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); - EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(), - render_pass_quad->rect.ToString()); - // The masked layer is 50x50, but the surface size is 10x20. So the texture - // coords in the mask are scaled by 10/50 and 20/50. - // The surface is clipped to (20,10) so the mask texture coords are offset - // by 20/50 and 10/50 - 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_; -}; - -class LayerTreeTestSingleTextureMaskLayerForSurfaceWithClippedLayer - : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestSingleTextureMaskLayerForSurfaceWithClippedLayer); - -class LayerTreeTestMultiTextureMaskLayerForSurfaceWithClippedLayer - : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMultiTextureMaskLayerForSurfaceWithClippedLayer); - -class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { - protected: - void SetupTree() override { - // Root - // | - // +-- Scaling Layer (adds a 2x scale) - // | - // +-- Content Layer - // +--Mask - - scoped_refptr<Layer> root = Layer::Create(); - - scoped_refptr<Layer> scaling_layer = Layer::Create(); - root->AddChild(scaling_layer); - - scoped_refptr<FakePictureLayer> content_layer = - 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::CreateWithRecordingSource( - &client_, std::move(recording_source)); - content_layer->SetMaskLayer(mask_layer.get()); - - gfx::Size root_size(100, 100); - root->SetBounds(root_size); - - gfx::Size scaling_layer_size(50, 50); - scaling_layer->SetBounds(scaling_layer_size); - gfx::Transform scale; - scale.Scale(2.f, 2.f); - scaling_layer->SetTransform(scale); - - content_layer->SetBounds(scaling_layer_size); - - mask_layer->SetBounds(scaling_layer_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); - - layer_tree_host()->SetRootLayer(root); - LayerTreeTest::SetupTree(); - client_.set_bounds(root->bounds()); - } - - 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()); - viz::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(viz::DrawQuad::SOLID_COLOR, - root_pass->quad_list.back()->material); - - EXPECT_EQ(viz::DrawQuad::RENDER_PASS, - root_pass->quad_list.front()->material); - const viz::RenderPassDrawQuad* render_pass_quad = - viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); - switch (host_impl->active_tree()->source_frame_number()) { - case 0: - // Check that the tree scaling is correctly taken into account for the - // mask, that should fully map onto the quad. - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - render_pass_quad->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()); - 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; - } - return draw_result; - } - - void DidCommit() override { - switch (layer_tree_host()->SourceFrameNumber()) { - case 1: - gfx::Size double_root_size(200, 200); - layer_tree_host()->SetViewportSizeAndScale(double_root_size, 2.f, - viz::LocalSurfaceId()); - break; - } - } - - void AfterTest() override {} - - FakeContentLayerClient client_; -}; - -class LayerTreeTestSingleTextureMaskLayerWithScaling - : public LayerTreeTestMaskLayerWithScaling { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - settings->layer_transforms_should_scale_layer_contents = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestSingleTextureMaskLayerWithScaling); - -class LayerTreeTestMultiTextureMaskLayerWithScaling - : public LayerTreeTestMaskLayerWithScaling { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - settings->layer_transforms_should_scale_layer_contents = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMultiTextureMaskLayerWithScaling); - -class LayerTreeTestMaskWithNonExactTextureSize : public LayerTreeTest { - protected: - void SetupTree() override { - // The masked layer has bounds 100x100, but is allocated a 120x150 texture. - - scoped_refptr<Layer> root = Layer::Create(); - - scoped_refptr<FakePictureLayer> content_layer = - 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::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); - gfx::Size mask_texture_size(120, 150); - mask_layer->SetBounds(mask_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::SINGLE_TEXTURE_MASK); - mask_layer->set_fixed_tile_size(mask_texture_size); - - layer_tree_host()->SetRootLayer(root); - LayerTreeTest::SetupTree(); - client_.set_bounds(root->bounds()); - } - - 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()); - viz::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(viz::DrawQuad::SOLID_COLOR, - root_pass->quad_list.back()->material); - - // The surface is 100x100 - EXPECT_EQ(viz::DrawQuad::RENDER_PASS, - root_pass->quad_list.front()->material); - const viz::RenderPassDrawQuad* render_pass_quad = - viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - render_pass_quad->rect.ToString()); - // The mask layer is 100x100, but is backed by a 120x150 image. - EXPECT_EQ(gfx::RectF(0.0f, 0.0f, 100.f / 120.0f, 100.f / 150.0f).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(LayerTreeTestMaskWithNonExactTextureSize); - class LayerTreeTestPageScaleFlags : public LayerTreeTest { protected: void SetupTree() override { @@ -7993,6 +7512,25 @@ class LayerTreeHostTestPaintedDeviceScaleFactor : public LayerTreeHostTest { }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPaintedDeviceScaleFactor); +// Makes sure that presentation-time requests are correctly propagated to the +// frame's metadata. +class LayerTreeHostTestPresentationTimeRequest : public LayerTreeHostTest { + protected: + void BeginTest() override { + layer_tree_host()->RequestPresentationTimeForNextFrame(base::DoNothing()); + PostSetNeedsCommitToMainThread(); + } + + void DisplayReceivedCompositorFrameOnThread( + const viz::CompositorFrame& frame) override { + EXPECT_NE(0u, frame.metadata.presentation_token); + EndTest(); + } + + void AfterTest() override {} +}; +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPresentationTimeRequest); + // Makes sure that viz::LocalSurfaceId is propagated to the LayerTreeFrameSink. class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { protected: @@ -8001,7 +7539,7 @@ class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { } void BeginTest() override { - expected_local_surface_id_ = allocator_.GenerateId(); + expected_local_surface_id_ = allocator_.GetCurrentLocalSurfaceId(); PostSetLocalSurfaceIdToMainThread(expected_local_surface_id_); } @@ -8010,7 +7548,7 @@ class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { DrawResult draw_result) override { EXPECT_EQ(DRAW_SUCCESS, draw_result); EXPECT_EQ(expected_local_surface_id_, - host_impl->active_tree()->local_surface_id()); + host_impl->active_tree()->local_surface_id_from_parent()); return draw_result; } @@ -8025,9 +7563,56 @@ class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { viz::LocalSurfaceId expected_local_surface_id_; viz::ParentLocalSurfaceIdAllocator allocator_; }; - SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestLocalSurfaceId); +// Makes sure that viz::LocalSurfaceId allocation requests propagate all the way +// to LayerTreeFrameSink. +class LayerTreeHostTestRequestNewLocalSurfaceId : public LayerTreeHostTest { + protected: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_surface_synchronization = true; + } + + void BeginTest() override { + expected_parent_local_surface_id_ = allocator_.GetCurrentLocalSurfaceId(); + PostSetLocalSurfaceIdToMainThread(expected_parent_local_surface_id_); + PostRequestNewLocalSurfaceIdToMainThread(); + } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(DRAW_SUCCESS, draw_result); + EXPECT_EQ(expected_parent_local_surface_id_, + host_impl->active_tree()->local_surface_id_from_parent()); + return draw_result; + } + + void DisplayReceivedLocalSurfaceIdOnThread( + const viz::LocalSurfaceId& local_surface_id) override { + viz::LocalSurfaceId child_local_surface_id( + expected_parent_local_surface_id_.parent_sequence_number(), + expected_parent_local_surface_id_.child_sequence_number() + 1, + expected_parent_local_surface_id_.embed_token()); + EXPECT_NE(expected_parent_local_surface_id_, local_surface_id); + EXPECT_EQ(child_local_surface_id, local_surface_id); + } + + // This gets called after DispllayReceivedLocalSurfaceIdOnThread. + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { + // Verify that the request bit doesn't stick after we submit a frame. + EXPECT_FALSE( + host_impl->active_tree()->new_local_surface_id_request_for_testing()); + EndTest(); + } + + void AfterTest() override {} + + viz::LocalSurfaceId expected_parent_local_surface_id_; + viz::ParentLocalSurfaceIdAllocator allocator_; +}; +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestRequestNewLocalSurfaceId); + // 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 @@ -8144,6 +7729,20 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSubmitFrameMetadata); class LayerTreeHostTestSubmitFrameResources : public LayerTreeHostTest { protected: + std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + const viz::RendererSettings& renderer_settings, + double refresh_rate, + scoped_refptr<viz::ContextProvider> compositor_context_provider, + scoped_refptr<viz::RasterContextProvider> worker_context_provider) + override { + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + gl_owned->set_have_extension_egl_image(true); + auto provider = viz::TestContextProvider::Create(std::move(gl_owned)); + return LayerTreeTest::CreateLayerTreeFrameSink( + renderer_settings, refresh_rate, std::move(provider), + std::move(worker_context_provider)); + } + void BeginTest() override { PostSetNeedsCommitToMainThread(); } DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, @@ -8154,15 +7753,12 @@ class LayerTreeHostTestSubmitFrameResources : public LayerTreeHostTest { viz::RenderPass* child_pass = AddRenderPass(&frame->render_passes, 2, gfx::Rect(3, 3, 10, 10), gfx::Transform(), FilterOperations()); - gpu::SyncToken mailbox_sync_token; - AddOneOfEveryQuadType(child_pass, host_impl->resource_provider(), 0, - &mailbox_sync_token); + AddOneOfEveryQuadType(child_pass, host_impl->resource_provider(), 0); viz::RenderPass* pass = AddRenderPass(&frame->render_passes, 1, gfx::Rect(3, 3, 10, 10), gfx::Transform(), FilterOperations()); - AddOneOfEveryQuadType(pass, host_impl->resource_provider(), child_pass->id, - &mailbox_sync_token); + AddOneOfEveryQuadType(pass, host_impl->resource_provider(), child_pass->id); return draw_result; } @@ -8293,11 +7889,9 @@ class LayerTreeHostTestQueueImageDecode : public LayerTreeHostTest { void ReadyToCommitOnThread(LayerTreeHostImpl* impl) override { if (one_commit_done_) return; - EXPECT_TRUE( + EXPECT_FALSE( impl->tile_manager()->checker_image_tracker().ShouldCheckerImage( image_, WhichTree::PENDING_TREE)); - // Reset the tracker as if it has never seen this image. - impl->tile_manager()->checker_image_tracker().ClearTracker(true); } void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { diff --git a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc index f71c658c3fa..929c6658fe8 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc @@ -60,6 +60,9 @@ class LayerTreeHostCheckerImagingTest : public LayerTreeTest { content_layer_client_.set_fill_with_nonsolid_color(true); PaintImage checkerable_image = CreateDiscardablePaintImage(gfx::Size(450, 450)); + checkerable_image = PaintImageBuilder::WithCopy(checkerable_image) + .set_decoding_mode(PaintImage::DecodingMode::kAsync) + .TakePaintImage(); content_layer_client_.add_draw_image(checkerable_image, gfx::Point(0, 0), PaintFlags()); diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc index 024ca0204ab..f3ec645e85a 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_context.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc @@ -34,6 +34,7 @@ #include "cc/trees/single_thread_proxy.h" #include "components/viz/common/resources/single_release_callback.h" #include "components/viz/test/test_context_provider.h" +#include "components/viz/test/test_gles2_interface.h" #include "components/viz/test/test_layer_tree_frame_sink.h" #include "components/viz/test/test_shared_bitmap_manager.h" #include "components/viz/test/test_web_graphics_context_3d.h" @@ -56,7 +57,6 @@ class LayerTreeHostContextTest : public LayerTreeTest { public: LayerTreeHostContextTest() : LayerTreeTest(), - context3d_(nullptr), times_to_fail_create_(0), times_to_lose_during_commit_(0), times_to_lose_during_draw_(0), @@ -72,15 +72,15 @@ class LayerTreeHostContextTest : public LayerTreeTest { void LoseContext() { // CreateDisplayLayerTreeFrameSink happens on a different thread, so lock - // context3d_ to make sure we don't set it to null after recreating it + // gl_ to make sure we don't set it to null after recreating it // there. - base::AutoLock lock(context3d_lock_); + base::AutoLock lock(gl_lock_); // For sanity-checking tests, they should only call this when the // context is not lost. - CHECK(context3d_); - context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, - GL_INNOCENT_CONTEXT_RESET_ARB); - context3d_ = nullptr; + CHECK(gl_); + gl_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); + gl_ = nullptr; } std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( @@ -89,26 +89,26 @@ class LayerTreeHostContextTest : public LayerTreeTest { scoped_refptr<viz::ContextProvider> compositor_context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider) override { - base::AutoLock lock(context3d_lock_); + base::AutoLock lock(gl_lock_); - std::unique_ptr<viz::TestWebGraphicsContext3D> compositor_context3d = - viz::TestWebGraphicsContext3D::Create(); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); if (context_should_support_io_surface_) { - compositor_context3d->set_have_extension_io_surface(true); - compositor_context3d->set_have_extension_egl_image(true); + gl_owned->set_have_extension_io_surface(true); + gl_owned->set_have_extension_egl_image(true); } - context3d_ = compositor_context3d.get(); + gl_ = gl_owned.get(); + + auto provider = viz::TestContextProvider::Create(std::move(gl_owned)); if (times_to_fail_create_) { --times_to_fail_create_; ExpectCreateToFail(); - context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, - GL_INNOCENT_CONTEXT_RESET_ARB); + gl_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); } return LayerTreeTest::CreateLayerTreeFrameSink( - renderer_settings, refresh_rate, - viz::TestContextProvider::Create(std::move(compositor_context3d)), + renderer_settings, refresh_rate, std::move(provider), std::move(worker_context_provider)); } @@ -158,10 +158,10 @@ class LayerTreeHostContextTest : public LayerTreeTest { void ExpectCreateToFail() { ++times_to_expect_create_failed_; } protected: - // Protects use of context3d_ so LoseContext and + // Protects use of gl_ so LoseContext and // CreateDisplayLayerTreeFrameSink can both use it on different threads. - base::Lock context3d_lock_; - viz::TestWebGraphicsContext3D* context3d_; + base::Lock gl_lock_; + viz::TestGLES2Interface* gl_ = nullptr; int times_to_fail_create_; int times_to_lose_during_commit_; @@ -887,7 +887,7 @@ class LayerTreeHostContextTestDontUseLostResources shared_bitmap_manager_ = std::make_unique<viz::TestSharedBitmapManager>(); child_resource_provider_ = FakeResourceProvider::CreateLayerTreeResourceProvider( - child_context_provider_.get(), shared_bitmap_manager_.get()); + child_context_provider_.get()); } static void EmptyReleaseCallback(const gpu::SyncToken& sync_token, @@ -1008,7 +1008,7 @@ class LayerTreeHostContextTestDontUseLostResources if (host_impl->active_tree()->source_frame_number() == 2) { // Lose the context after draw on the second commit. This will cause // a third commit to recover. - context3d_->set_times_bind_texture_succeeds(0); + gl_->set_times_bind_texture_succeeds(0); } return draw_result; } @@ -1042,7 +1042,7 @@ class LayerTreeHostContextTestDontUseLostResources scoped_refptr<viz::TestContextProvider> child_context_provider_; std::unique_ptr<viz::SharedBitmapManager> shared_bitmap_manager_; - std::unique_ptr<ResourceProvider> child_resource_provider_; + std::unique_ptr<LayerTreeResourceProvider> child_resource_provider_; scoped_refptr<VideoFrame> color_video_frame_; scoped_refptr<VideoFrame> hw_video_frame_; @@ -1345,8 +1345,9 @@ class UIResourceLostBeforeCommit : public UIResourceLostTestSimple { UIResourceId test_id1_; }; -// http://crbug.com/803532 : Flaky on Win 7 (dbg). -#if defined(NDEBUG) || !defined(OS_WIN) +// http://crbug.com/803532 : Flaky on Win 7 (dbg) and linux tsan +#if (defined(NDEBUG) || !defined(OS_WIN)) && \ + (!defined(THREAD_SANITIZER) || !defined(OS_LINUX)) SINGLE_THREAD_TEST_F(UIResourceLostBeforeCommit); #endif MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit); @@ -1479,7 +1480,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl, bool visible) override { if (!visible) { // All resources should have been evicted. - ASSERT_EQ(0u, context3d_->NumTextures()); + ASSERT_EQ(0u, gl_->NumTextures()); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource3_->id())); @@ -1499,7 +1500,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { case 1: // The first two resources should have been created on LTHI after the // commit. - ASSERT_EQ(2u, context3d_->NumTextures()); + ASSERT_EQ(2u, gl_->NumTextures()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(1, ui_resource_->resource_create_count); @@ -1507,7 +1508,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { EXPECT_TRUE(impl->CanDraw()); // Evict all UI resources. This will trigger a commit. impl->EvictAllUIResources(); - ASSERT_EQ(0u, context3d_->NumTextures()); + ASSERT_EQ(0u, gl_->NumTextures()); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(1, ui_resource_->resource_create_count); @@ -1516,7 +1517,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { break; case 2: // The first two resources should have been recreated. - ASSERT_EQ(2u, context3d_->NumTextures()); + ASSERT_EQ(2u, gl_->NumTextures()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(2, ui_resource_->resource_create_count); EXPECT_EQ(1, ui_resource_->lost_resource_count); @@ -1528,7 +1529,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { case 3: // The first resource should have been recreated after visibility was // restored. - ASSERT_EQ(2u, context3d_->NumTextures()); + ASSERT_EQ(2u, gl_->NumTextures()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(3, ui_resource_->resource_create_count); EXPECT_EQ(2, ui_resource_->lost_resource_count); diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc index edc62a8e36a..fcc95241448 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc @@ -1049,63 +1049,6 @@ class LayerTreeHostCopyRequestTestCreatesTexture SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestCreatesTexture); -class LayerTreeHostCopyRequestTestProvideTexture - : public LayerTreeHostCopyRequestTestCountTextures { - protected: - void BeginTest() override { - external_context_provider_ = viz::TestContextProvider::Create(); - EXPECT_EQ(external_context_provider_->BindToCurrentThread(), - gpu::ContextResult::kSuccess); - LayerTreeHostCopyRequestTestCountTextures::BeginTest(); - } - - void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) { - EXPECT_FALSE(result->IsEmpty()); - EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE); - ASSERT_NE(nullptr, result->GetTextureResult()); - - std::unique_ptr<viz::SingleReleaseCallback> release_callback = - result->TakeTextureOwnership(); - ASSERT_TRUE(release_callback); - release_callback->Run(gpu::SyncToken(), false); - } - - void RequestCopy(Layer* layer) override { - // Request a copy to a provided texture. This should not create a new - // texture. - std::unique_ptr<viz::CopyOutputRequest> request = - std::make_unique<viz::CopyOutputRequest>( - viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE, - base::BindOnce( - &LayerTreeHostCopyRequestTestProvideTexture::CopyOutputCallback, - base::Unretained(this))); - - gpu::gles2::GLES2Interface* gl = external_context_provider_->ContextGL(); - gpu::Mailbox mailbox; - gl->GenMailboxCHROMIUM(mailbox.name); - - gl->GenSyncTokenCHROMIUM(sync_token_.GetData()); - - request->SetMailbox(mailbox, sync_token_); - EXPECT_TRUE(request->has_mailbox()); - - copy_layer_->RequestCopyOfOutput(std::move(request)); - } - - void AfterTest() override { - // Expect the compositor to have waited for the sync point provided with the - // mailbox. - EXPECT_EQ(sync_token_, waited_sync_token_after_readback_); - // Except the copy to have *not* made another texture. - EXPECT_EQ(num_textures_without_readback_, num_textures_with_readback_); - } - - scoped_refptr<viz::TestContextProvider> external_context_provider_; - gpu::SyncToken sync_token_; -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestProvideTexture); - class LayerTreeHostCopyRequestTestDestroyBeforeCopy : public LayerTreeHostCopyRequestTest { protected: diff --git a/chromium/cc/trees/layer_tree_host_unittest_masks.cc b/chromium/cc/trees/layer_tree_host_unittest_masks.cc new file mode 100644 index 00000000000..b1615f0eb7e --- /dev/null +++ b/chromium/cc/trees/layer_tree_host_unittest_masks.cc @@ -0,0 +1,666 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/trees/layer_tree_host.h" + +#include "cc/test/fake_picture_layer.h" +#include "cc/test/fake_recording_source.h" +#include "cc/test/layer_tree_test.h" +#include "cc/trees/layer_tree_impl.h" +#include "components/viz/common/quads/render_pass_draw_quad.h" + +namespace cc { +namespace { + +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()); + layer_tree_host()->outer_viewport_container_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()); + viz::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(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + gfx::Rect rect_in_target_space = MathUtil::MapEnclosingClippedRect( + render_pass_quad->shared_quad_state->quad_to_target_transform, + render_pass_quad->rect); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), + rect_in_target_space.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_; +}; + +class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Untiled + : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Untiled); + +class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Tiled + : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Tiled); + +class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : 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<Layer> clipping_layer = Layer::Create(); + root->AddChild(clipping_layer); + + scoped_refptr<FakePictureLayer> content_layer = + FakePictureLayer::Create(&client_); + clipping_layer->AddChild(content_layer); + + scoped_refptr<FakePictureLayer> content_child_layer = + FakePictureLayer::Create(&client_); + content_layer->AddChild(content_child_layer); + + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(50, 50)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 50, 40), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 40, 50, 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::PointF clipping_origin(20.f, 10.f); + gfx::Size clipping_size(10, 20); + clipping_layer->SetBounds(clipping_size); + clipping_layer->SetPosition(clipping_origin); + clipping_layer->SetMasksToBounds(true); + + gfx::Size layer_size(50, 50); + content_layer->SetBounds(layer_size); + content_layer->SetPosition(gfx::PointF() - + clipping_origin.OffsetFromOrigin()); + + gfx::Size child_size(50, 50); + content_child_layer->SetBounds(child_size); + content_child_layer->SetPosition(gfx::PointF(20.f, 0.f)); + + gfx::Size mask_size(50, 50); + 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(); + client_.set_bounds(root->bounds()); + } + + 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()); + viz::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(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + // The surface is clipped to 10x20. + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + gfx::Rect rect_in_target_space = MathUtil::MapEnclosingClippedRect( + render_pass_quad->shared_quad_state->quad_to_target_transform, + render_pass_quad->rect); + EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(), + rect_in_target_space.ToString()); + // The masked layer is 50x50, but the surface size is 10x20. So the texture + // coords in the mask are scaled by 10/50 and 20/50. + // The surface is clipped to (20,10) so the mask texture coords are offset + // by 20/50 and 10/50 + 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_; +}; + +class LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Untiled + : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Untiled); + +class LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Tiled + : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Tiled); + +class LayerTreeTestMaskLayerForSurfaceWithDifferentScale + : 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<Layer> clipping_scaling_layer = Layer::Create(); + root->AddChild(clipping_scaling_layer); + + scoped_refptr<FakePictureLayer> content_layer = + FakePictureLayer::Create(&client_); + clipping_scaling_layer->AddChild(content_layer); + + scoped_refptr<FakePictureLayer> content_child_layer = + FakePictureLayer::Create(&client_); + content_layer->AddChild(content_child_layer); + + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(50, 50)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 50, 40), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 40, 50, 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::Transform scale; + scale.Scale(2, 2); + gfx::PointF clipping_origin(20.f, 10.f); + gfx::Size clipping_size(10, 20); + clipping_scaling_layer->SetBounds(clipping_size); + clipping_scaling_layer->SetPosition(clipping_origin); + // This changes scale between contributing layer and render surface to 2. + clipping_scaling_layer->SetTransform(scale); + clipping_scaling_layer->SetMasksToBounds(true); + + gfx::Size layer_size(50, 50); + content_layer->SetBounds(layer_size); + content_layer->SetPosition(gfx::PointF() - + clipping_origin.OffsetFromOrigin()); + + gfx::Size child_size(50, 50); + content_child_layer->SetBounds(child_size); + content_child_layer->SetPosition(gfx::PointF(20.f, 0.f)); + + gfx::Size mask_size(50, 50); + mask_layer->SetBounds(mask_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + // Setting will change transform on mask layer will make it not adjust + // raster scale, which will remain 1. This means the mask_layer and render + // surface will have a scale of 2 during draw time. + mask_layer->SetHasWillChangeTransformHint(true); + mask_layer_id_ = mask_layer->id(); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); + } + + 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()); + viz::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(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + // The surface is clipped to 10x20, and then scaled by 2, which ends up + // being 20x40. + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + gfx::Rect rect_in_target_space = MathUtil::MapEnclosingClippedRect( + render_pass_quad->shared_quad_state->quad_to_target_transform, + render_pass_quad->rect); + EXPECT_EQ(gfx::Rect(20, 10, 20, 40).ToString(), + rect_in_target_space.ToString()); + gfx::Rect visible_rect_in_target_space = MathUtil::MapEnclosingClippedRect( + render_pass_quad->shared_quad_state->quad_to_target_transform, + render_pass_quad->visible_rect); + EXPECT_EQ(gfx::Rect(20, 10, 20, 40).ToString(), + visible_rect_in_target_space.ToString()); + // The masked layer is 50x50, but the surface size is 10x20. So the texture + // coords in the mask are scaled by 10/50 and 20/50. + // The surface is clipped to (20,10) so the mask texture coords are offset + // by 20/50 and 10/50 + 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_; +}; + +class LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Untiled + : public LayerTreeTestMaskLayerForSurfaceWithDifferentScale { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Untiled); + +class LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Tiled + : public LayerTreeTestMaskLayerForSurfaceWithDifferentScale { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Tiled); + +class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { + protected: + void SetupTree() override { + // Root + // | + // +-- Scaling Layer (adds a 2x scale) + // | + // +-- Content Layer + // +--Mask + + scoped_refptr<Layer> root = Layer::Create(); + + scoped_refptr<Layer> scaling_layer = Layer::Create(); + root->AddChild(scaling_layer); + + scoped_refptr<FakePictureLayer> content_layer = + 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::CreateWithRecordingSource( + &client_, std::move(recording_source)); + content_layer->SetMaskLayer(mask_layer.get()); + + gfx::Size root_size(100, 100); + root->SetBounds(root_size); + + gfx::Size scaling_layer_size(50, 50); + scaling_layer->SetBounds(scaling_layer_size); + gfx::Transform scale; + scale.Scale(2.f, 2.f); + scaling_layer->SetTransform(scale); + + content_layer->SetBounds(scaling_layer_size); + + mask_layer->SetBounds(scaling_layer_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); + } + + 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()); + viz::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(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + switch (host_impl->active_tree()->source_frame_number()) { + case 0: + // Check that the tree scaling is correctly taken into account for the + // mask, that should fully map onto the quad. + EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), + render_pass_quad->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()); + 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; + } + return draw_result; + } + + void DidCommit() override { + switch (layer_tree_host()->SourceFrameNumber()) { + case 1: + gfx::Size double_root_size(200, 200); + layer_tree_host()->SetViewportSizeAndScale(double_root_size, 2.f, + viz::LocalSurfaceId()); + break; + } + } + + void AfterTest() override {} + + FakeContentLayerClient client_; +}; + +class LayerTreeTestMaskLayerWithScaling_Untiled + : public LayerTreeTestMaskLayerWithScaling { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + settings->layer_transforms_should_scale_layer_contents = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskLayerWithScaling_Untiled); + +class LayerTreeTestMaskLayerWithScaling_Tiled + : public LayerTreeTestMaskLayerWithScaling { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + settings->layer_transforms_should_scale_layer_contents = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskLayerWithScaling_Tiled); + +class LayerTreeTestMaskWithNonExactTextureSize : public LayerTreeTest { + protected: + void SetupTree() override { + // The masked layer has bounds 100x100, but is allocated a 120x150 texture. + + scoped_refptr<Layer> root = Layer::Create(); + + scoped_refptr<FakePictureLayer> content_layer = + 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::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); + gfx::Size mask_texture_size(120, 150); + mask_layer->SetBounds(mask_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::SINGLE_TEXTURE_MASK); + mask_layer->set_fixed_tile_size(mask_texture_size); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); + } + + 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()); + viz::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(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + // The surface is 100x100 + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), + render_pass_quad->rect.ToString()); + // The mask layer is 100x100, but is backed by a 120x150 image. + EXPECT_EQ(gfx::RectF(0.0f, 0.0f, 100.f / 120.0f, 100.f / 150.0f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + EndTest(); + return draw_result; + } + + void AfterTest() override {} + + int mask_layer_id_; + FakeContentLayerClient client_; +}; + +class LayerTreeTestMaskWithNonExactTextureSize_Untiled + : public LayerTreeTestMaskWithNonExactTextureSize { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskWithNonExactTextureSize_Untiled); + +class LayerTreeTestMaskWithNonExactTextureSize_Tiled + : public LayerTreeTestMaskWithNonExactTextureSize { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskWithNonExactTextureSize_Tiled); + +} // namespace +} // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_picture.cc b/chromium/cc/trees/layer_tree_host_unittest_picture.cc index 40aeeb1acb3..205d1f2c648 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_picture.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_picture.cc @@ -41,14 +41,16 @@ class LayerTreeHostPictureTestTwinLayer } void BeginTest() override { - activates_ = 0; + // Commit and activate to produce a pending (recycled) layer and an active + // layer. PostSetNeedsCommitToMainThread(); } void DidCommit() override { switch (layer_tree_host()->SourceFrameNumber()) { case 1: - // Activate while there are pending and active twins in place. + // Activate reusing an existing recycled pending layer, to an already + // existing active layer. layer_tree_host()->SetNeedsCommit(); break; case 2: @@ -66,12 +68,9 @@ class LayerTreeHostPictureTestTwinLayer break; } case 4: - // Active while there are pending and active twins again. + // Activate while there are pending and active twins again. layer_tree_host()->SetNeedsCommit(); break; - case 5: - EndTest(); - break; } } @@ -131,11 +130,14 @@ class LayerTreeHostPictureTestTwinLayer } ++activates_; + if (activates_ == 5) + EndTest(); } - void AfterTest() override { EXPECT_EQ(5, activates_); } + void AfterTest() override {} + + int activates_ = 0; - int activates_; int picture_id1_; int picture_id2_; }; diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc index 68982f6f0cf..dc45563a2c7 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc @@ -1250,7 +1250,7 @@ class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent layer_tree_host() ->inner_viewport_scroll_layer() ->AddMainThreadScrollingReasons( - MainThreadScrollingReason::kNonFastScrollableRegion); + MainThreadScrollingReason::kScrollbarScrolling); } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { @@ -1268,7 +1268,7 @@ class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent impl->TryScroll(gfx::PointF(1.f, 1.f), InputHandler::TOUCHSCREEN, scroll_tree, inner_scroll_node); EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, + EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling, status.main_thread_scrolling_reasons); status = impl->TryScroll(gfx::PointF(1.f, 1.f), InputHandler::TOUCHSCREEN, diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index fa670feff83..a6b06c59e26 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -468,8 +468,11 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { target_tree->elastic_overscroll()->PushPendingToActive(); target_tree->set_content_source_id(content_source_id()); + target_tree->set_request_presentation_time(request_presentation_time()); - target_tree->set_local_surface_id(local_surface_id()); + if (TakeNewLocalSurfaceIdRequest()) + target_tree->RequestNewLocalSurfaceId(); + target_tree->SetLocalSurfaceIdFromParent(local_surface_id_from_parent()); target_tree->pending_page_scale_animation_ = std::move(pending_page_scale_animation_); @@ -963,6 +966,21 @@ void LayerTreeImpl::SetDeviceScaleFactor(float device_scale_factor) { host_impl_->SetNeedUpdateGpuRasterizationStatus(); } +void LayerTreeImpl::SetLocalSurfaceIdFromParent( + const viz::LocalSurfaceId& local_surface_id_from_parent) { + local_surface_id_from_parent_ = local_surface_id_from_parent; +} + +void LayerTreeImpl::RequestNewLocalSurfaceId() { + new_local_surface_id_request_ = true; +} + +bool LayerTreeImpl::TakeNewLocalSurfaceIdRequest() { + bool new_local_surface_id_request = new_local_surface_id_request_; + new_local_surface_id_request_ = false; + return new_local_surface_id_request; +} + void LayerTreeImpl::SetRasterColorSpace( int raster_color_space_id, const gfx::ColorSpace& raster_color_space) { @@ -1085,7 +1103,7 @@ bool LayerTreeImpl::UpdateDrawProperties( device_scale_factor(), current_page_scale_factor(), PageScaleLayer(), InnerViewportScrollLayer(), OuterViewportScrollLayer(), elastic_overscroll()->Current(IsActiveTree()), - OverscrollElasticityLayer(), resource_provider()->max_texture_size(), + OverscrollElasticityLayer(), max_texture_size(), settings().layer_transforms_should_scale_layer_contents, &render_surface_list_, &property_trees_); LayerTreeHostCommon::CalculateDrawProperties(&inputs); @@ -1376,6 +1394,10 @@ LayerTreeFrameSink* LayerTreeImpl::layer_tree_frame_sink() { return host_impl_->layer_tree_frame_sink(); } +int LayerTreeImpl::max_texture_size() const { + return host_impl_->max_texture_size(); +} + const LayerTreeSettings& LayerTreeImpl::settings() const { return host_impl_->settings(); } @@ -1388,10 +1410,6 @@ viz::ContextProvider* LayerTreeImpl::context_provider() const { return host_impl_->layer_tree_frame_sink()->context_provider(); } -viz::SharedBitmapManager* LayerTreeImpl::shared_bitmap_manager() const { - return host_impl_->layer_tree_frame_sink()->shared_bitmap_manager(); -} - LayerTreeResourceProvider* LayerTreeImpl::resource_provider() const { return host_impl_->resource_provider(); } diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index 62c31dbd0a1..11e406e78d4 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -106,10 +106,10 @@ class CC_EXPORT LayerTreeImpl { // Methods called by the layer tree that pass-through or access LTHI. // --------------------------------------------------------------------------- LayerTreeFrameSink* layer_tree_frame_sink(); + int max_texture_size() const; const LayerTreeSettings& settings() const; const LayerTreeDebugState& debug_state() const; viz::ContextProvider* context_provider() const; - viz::SharedBitmapManager* shared_bitmap_manager() const; LayerTreeResourceProvider* resource_provider() const; TileManager* tile_manager() const; ImageDecodeCache* image_decode_cache() const; @@ -299,11 +299,15 @@ 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 set_local_surface_id(const viz::LocalSurfaceId& id) { - local_surface_id_ = id; + void SetLocalSurfaceIdFromParent(const viz::LocalSurfaceId& id); + const viz::LocalSurfaceId& local_surface_id_from_parent() const { + return local_surface_id_from_parent_; } - const viz::LocalSurfaceId& local_surface_id() const { - return local_surface_id_; + + void RequestNewLocalSurfaceId(); + bool TakeNewLocalSurfaceIdRequest(); + bool new_local_surface_id_request_for_testing() const { + return new_local_surface_id_request_; } void SetRasterColorSpace(int raster_color_space_id, @@ -608,7 +612,8 @@ class CC_EXPORT LayerTreeImpl { gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; - viz::LocalSurfaceId local_surface_id_; + viz::LocalSurfaceId local_surface_id_from_parent_; + bool new_local_surface_id_request_ = false; scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_; diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc index 08137e0e846..3f3000b41bf 100644 --- a/chromium/cc/trees/layer_tree_settings.cc +++ b/chromium/cc/trees/layer_tree_settings.cc @@ -15,8 +15,7 @@ LayerTreeSettings::LayerTreeSettings() minimum_occlusion_tracking_size(gfx::Size(160, 160)), memory_policy(64 * 1024 * 1024, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, - ManagedMemoryPolicy::kDefaultNumResourcesLimit), - preferred_tile_format(viz::PlatformColor::BestTextureFormat()) {} + ManagedMemoryPolicy::kDefaultNumResourcesLimit) {} LayerTreeSettings::LayerTreeSettings(const LayerTreeSettings& other) = default; LayerTreeSettings::~LayerTreeSettings() = default; diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h index 2584543f863..50b8805bc7a 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -93,7 +93,7 @@ class CC_EXPORT LayerTreeSettings { ManagedMemoryPolicy memory_policy; size_t decoded_image_working_set_budget_bytes = 128 * 1024 * 1024; int max_preraster_distance_in_screen_pixels = 1000; - viz::ResourceFormat preferred_tile_format; + bool use_rgba_4444 = false; bool unpremultiply_and_dither_low_bit_depth_tiles = false; bool enable_mask_tiling = true; @@ -156,6 +156,10 @@ class CC_EXPORT LayerTreeSettings { // Whether SetViewportSizeAndScale should update the painted scale factor or // the device scale factor. bool use_painted_device_scale_factor = false; + + // Whether a HitTestRegionList should be built from the active layer tree when + // submitting a CompositorFrame. + bool build_hit_test_data = false; }; } // namespace cc diff --git a/chromium/cc/trees/mutator_host.h b/chromium/cc/trees/mutator_host.h index e4aae914bae..18b7fe5118c 100644 --- a/chromium/cc/trees/mutator_host.h +++ b/chromium/cc/trees/mutator_host.h @@ -129,7 +129,6 @@ class MutatorHost { virtual size_t CompositedAnimationsCount() const = 0; virtual size_t MainThreadAnimationsCount() const = 0; - virtual size_t MainThreadCompositableAnimationsCount() const = 0; virtual bool CurrentFrameHadRAF() const = 0; virtual bool NextFrameHasPendingRAF() const = 0; }; diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc index 4c4cdd4c632..06b051455ed 100644 --- a/chromium/cc/trees/proxy_impl.cc +++ b/chromium/cc/trees/proxy_impl.cc @@ -367,10 +367,6 @@ size_t ProxyImpl::MainThreadAnimationsCount() const { return host_impl_->mutator_host()->MainThreadAnimationsCount(); } -size_t ProxyImpl::MainThreadCompositableAnimationsCount() const { - return host_impl_->mutator_host()->MainThreadCompositableAnimationsCount(); -} - bool ProxyImpl::CurrentFrameHadRAF() const { return host_impl_->mutator_host()->CurrentFrameHadRAF(); } diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h index 0e3347383df..467f0e616d8 100644 --- a/chromium/cc/trees/proxy_impl.h +++ b/chromium/cc/trees/proxy_impl.h @@ -125,7 +125,6 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, base::TimeTicks time) override; size_t CompositedAnimationsCount() const override; size_t MainThreadAnimationsCount() const override; - size_t MainThreadCompositableAnimationsCount() const override; bool CurrentFrameHadRAF() const override; bool NextFrameHasPendingRAF() const override; diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc index 7b7589167bb..668e674e30d 100644 --- a/chromium/cc/trees/proxy_main.cc +++ b/chromium/cc/trees/proxy_main.cc @@ -300,7 +300,7 @@ void ProxyMain::BeginMainFrame( // commit. ui::LatencyInfo new_latency_info(ui::SourceEventType::FRAME); new_latency_info.AddLatencyNumberWithTimestamp( - ui::LATENCY_BEGIN_FRAME_RENDERER_MAIN_COMPONENT, 0, 0, + ui::LATENCY_BEGIN_FRAME_RENDERER_MAIN_COMPONENT, 0, begin_main_frame_state->begin_frame_args.frame_time, 1); layer_tree_host_->QueueSwapPromise( std::make_unique<LatencyInfoSwapPromise>(new_latency_info)); diff --git a/chromium/cc/trees/render_frame_metadata.cc b/chromium/cc/trees/render_frame_metadata.cc index 4466cb928c1..5678f5c8987 100644 --- a/chromium/cc/trees/render_frame_metadata.cc +++ b/chromium/cc/trees/render_frame_metadata.cc @@ -21,7 +21,15 @@ bool RenderFrameMetadata::HasAlwaysUpdateMetadataChanged( const RenderFrameMetadata& rfm2) { return rfm1.root_background_color != rfm2.root_background_color || rfm1.is_scroll_offset_at_top != rfm2.is_scroll_offset_at_top || - rfm1.selection != rfm2.selection; + rfm1.selection != rfm2.selection || + rfm1.is_mobile_optimized != rfm2.is_mobile_optimized || + rfm1.device_scale_factor != rfm2.device_scale_factor || + rfm1.viewport_size_in_pixels != rfm2.viewport_size_in_pixels || + rfm1.local_surface_id != rfm2.local_surface_id || + rfm1.top_controls_height != rfm2.top_controls_height || + rfm1.top_controls_shown_ratio != rfm2.top_controls_shown_ratio || + rfm1.bottom_controls_height != rfm2.bottom_controls_height || + rfm1.bottom_controls_shown_ratio != rfm2.bottom_controls_shown_ratio; } RenderFrameMetadata& RenderFrameMetadata::operator=( @@ -30,14 +38,22 @@ RenderFrameMetadata& RenderFrameMetadata::operator=( RenderFrameMetadata& RenderFrameMetadata::operator=( RenderFrameMetadata&& other) = default; -bool RenderFrameMetadata::operator==(const RenderFrameMetadata& other) { +bool RenderFrameMetadata::operator==(const RenderFrameMetadata& other) const { return root_scroll_offset == other.root_scroll_offset && root_background_color == other.root_background_color && is_scroll_offset_at_top == other.is_scroll_offset_at_top && - selection == other.selection; + selection == other.selection && + is_mobile_optimized == other.is_mobile_optimized && + device_scale_factor == other.device_scale_factor && + viewport_size_in_pixels == other.viewport_size_in_pixels && + local_surface_id == other.local_surface_id && + top_controls_height == other.top_controls_height && + top_controls_shown_ratio == other.top_controls_shown_ratio && + bottom_controls_height == other.bottom_controls_height && + bottom_controls_shown_ratio == other.bottom_controls_shown_ratio; } -bool RenderFrameMetadata::operator!=(const RenderFrameMetadata& other) { +bool RenderFrameMetadata::operator!=(const RenderFrameMetadata& other) const { return !operator==(other); } diff --git a/chromium/cc/trees/render_frame_metadata.h b/chromium/cc/trees/render_frame_metadata.h index 0a20fa8d73c..d07d7d4bfc6 100644 --- a/chromium/cc/trees/render_frame_metadata.h +++ b/chromium/cc/trees/render_frame_metadata.h @@ -8,7 +8,9 @@ #include "base/optional.h" #include "cc/cc_export.h" #include "components/viz/common/quads/selection.h" +#include "components/viz/common/surfaces/local_surface_id.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/vector2d_f.h" #include "ui/gfx/selection_bound.h" @@ -29,8 +31,8 @@ class CC_EXPORT RenderFrameMetadata { RenderFrameMetadata& operator=(const RenderFrameMetadata&); RenderFrameMetadata& operator=(RenderFrameMetadata&& other); - bool operator==(const RenderFrameMetadata& other); - bool operator!=(const RenderFrameMetadata& other); + bool operator==(const RenderFrameMetadata& other) const; + bool operator!=(const RenderFrameMetadata& other) const; // Indicates whether the scroll offset of the root layer is at top, i.e., // whether scroll_offset.y() == 0. @@ -48,6 +50,32 @@ class CC_EXPORT RenderFrameMetadata { // Selection region relative to the current viewport. If the selection is // empty or otherwise unused, the bound types will indicate such. viz::Selection<gfx::SelectionBound> selection; + + // Determines whether the page is mobile optimized or not, which means at + // least one of the following has to be true: + // - page has a width=device-width or narrower viewport. + // - page prevents zooming in or out (i.e. min and max page scale factors + // are the same). + bool is_mobile_optimized = false; + + // The device scale factor used to generate a CompositorFrame. + float device_scale_factor = 1.f; + + // The size of the viewport used to generate a CompositorFrame. + gfx::Size viewport_size_in_pixels; + + // The last viz::LocalSurfaceId used to submit a CompositorFrame. + base::Optional<viz::LocalSurfaceId> local_surface_id; + + // Used to position the Android location top bar and page content, whose + // precise position is computed by the renderer compositor. + float top_controls_height = 0.f; + float top_controls_shown_ratio = 0.f; + + // Used to position Android bottom bar, whose position is computed by the + // renderer compositor. + float bottom_controls_height = 0.f; + float bottom_controls_shown_ratio = 0.f; }; } // namespace cc diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index 541e264e720..28c45b6196b 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -381,10 +381,6 @@ size_t SingleThreadProxy::MainThreadAnimationsCount() const { return 0; } -size_t SingleThreadProxy::MainThreadCompositableAnimationsCount() const { - return 0; -} - bool SingleThreadProxy::CurrentFrameHadRAF() const { return false; } @@ -748,8 +744,8 @@ void SingleThreadProxy::BeginMainFrame( // know we will commit since QueueSwapPromise itself requests a commit. ui::LatencyInfo new_latency_info(ui::SourceEventType::FRAME); new_latency_info.AddLatencyNumberWithTimestamp( - ui::LATENCY_BEGIN_FRAME_UI_MAIN_COMPONENT, 0, 0, - begin_frame_args.frame_time, 1); + ui::LATENCY_BEGIN_FRAME_UI_MAIN_COMPONENT, 0, begin_frame_args.frame_time, + 1); layer_tree_host_->QueueSwapPromise( std::make_unique<LatencyInfoSwapPromise>(new_latency_info)); @@ -839,7 +835,9 @@ void SingleThreadProxy::ScheduledActionPrepareTiles() { } void SingleThreadProxy::ScheduledActionInvalidateLayerTreeFrameSink() { - NOTREACHED(); + // This is an Android WebView codepath, which only uses multi-thread + // compositor. So this should not occur in single-thread mode. + NOTREACHED() << "Android Webview use-case, so multi-thread only"; } void SingleThreadProxy::ScheduledActionPerformImplSideInvalidation() { diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index 07b8ca1f53c..f505320da40 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -92,7 +92,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, base::TimeTicks time) override; size_t CompositedAnimationsCount() const override; size_t MainThreadAnimationsCount() const override; - size_t MainThreadCompositableAnimationsCount() const override; bool CurrentFrameHadRAF() const override; bool NextFrameHasPendingRAF() const override; |