diff options
author | Torne (Richard Coles) <torne@google.com> | 2013-10-31 11:16:26 +0000 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2013-10-31 11:16:26 +0000 |
commit | 1e9bf3e0803691d0a228da41fc608347b6db4340 (patch) | |
tree | ab2e5565f71b4219b3da406e19f16fe306704ef5 /cc | |
parent | f10b58d5bc6ae3e74076fc4ccca14cbc57ef805c (diff) | |
download | chromium_org-1e9bf3e0803691d0a228da41fc608347b6db4340.tar.gz |
Merge from Chromium at DEPS revision 232015
This commit was generated by merge_to_master.py.
Change-Id: If86767ad396b9e2e1a4c1e9df1427daea29703ef
Diffstat (limited to 'cc')
190 files changed, 5353 insertions, 2128 deletions
@@ -1,6 +1,7 @@ include_rules = [ "+gpu/GLES2", "+gpu/command_buffer/client/context_support.h", + "+gpu/command_buffer/common/gpu_memory_allocation.h", "+gpu/command_buffer/common/mailbox.h", "+media", "+skia/ext", diff --git a/cc/PRESUBMIT.py b/cc/PRESUBMIT.py index 9e84e3f660..76358f39b0 100644 --- a/cc/PRESUBMIT.py +++ b/cc/PRESUBMIT.py @@ -196,4 +196,8 @@ def CheckChangeOnUpload(input_api, output_api): def GetPreferredTrySlaves(project, change): return [ 'linux_layout_rel', + 'win_gpu', + 'linux_gpu', + 'mac_gpu', + 'mac_gpu_retina', ] diff --git a/cc/animation/animation.cc b/cc/animation/animation.cc index 6b4591797e..6b5966be29 100644 --- a/cc/animation/animation.cc +++ b/cc/animation/animation.cc @@ -33,7 +33,8 @@ COMPILE_ASSERT(static_cast<int>(cc::Animation::RunStateEnumSize) == static const char* const s_targetPropertyNames[] = { "Transform", "Opacity", - "Filter" + "Filter", + "BackgroundColor" }; COMPILE_ASSERT(static_cast<int>(cc::Animation::TargetPropertyEnumSize) == diff --git a/cc/animation/animation.h b/cc/animation/animation.h index 9946298a8e..f640318a51 100644 --- a/cc/animation/animation.h +++ b/cc/animation/animation.h @@ -47,6 +47,7 @@ class CC_EXPORT Animation { Transform = 0, Opacity, Filter, + BackgroundColor, // This sentinel must be last. TargetPropertyEnumSize }; diff --git a/cc/animation/animation_curve.cc b/cc/animation/animation_curve.cc index cf04da7f39..65c21db556 100644 --- a/cc/animation/animation_curve.cc +++ b/cc/animation/animation_curve.cc @@ -8,6 +8,13 @@ namespace cc { +const ColorAnimationCurve* AnimationCurve::ToColorAnimationCurve() const { + DCHECK(Type() == AnimationCurve::Color); + return static_cast<const ColorAnimationCurve*>(this); +} + +AnimationCurve::CurveType ColorAnimationCurve::Type() const { return Color; } + const FloatAnimationCurve* AnimationCurve::ToFloatAnimationCurve() const { DCHECK(Type() == AnimationCurve::Float); return static_cast<const FloatAnimationCurve*>(this); diff --git a/cc/animation/animation_curve.h b/cc/animation/animation_curve.h index f4cdb10560..f84bb1ab4f 100644 --- a/cc/animation/animation_curve.h +++ b/cc/animation/animation_curve.h @@ -16,6 +16,7 @@ class BoxF; namespace cc { +class ColorAnimationCurve; class FilterAnimationCurve; class FloatAnimationCurve; class TransformAnimationCurve; @@ -24,7 +25,7 @@ class TransformOperations; // An animation curve is a function that returns a value given a time. class CC_EXPORT AnimationCurve { public: - enum CurveType { Float, Transform, Filter }; + enum CurveType { Color, Float, Transform, Filter }; virtual ~AnimationCurve() {} @@ -32,11 +33,22 @@ class CC_EXPORT AnimationCurve { virtual CurveType Type() const = 0; virtual scoped_ptr<AnimationCurve> Clone() const = 0; + const ColorAnimationCurve* ToColorAnimationCurve() const; const FloatAnimationCurve* ToFloatAnimationCurve() const; const TransformAnimationCurve* ToTransformAnimationCurve() const; const FilterAnimationCurve* ToFilterAnimationCurve() const; }; +class CC_EXPORT ColorAnimationCurve : public AnimationCurve { + public: + virtual ~ColorAnimationCurve() {} + + virtual SkColor GetValue(double t) const = 0; + + // Partial Animation implementation. + virtual CurveType Type() const OVERRIDE; +}; + class CC_EXPORT FloatAnimationCurve : public AnimationCurve { public: virtual ~FloatAnimationCurve() {} diff --git a/cc/animation/keyframed_animation_curve.cc b/cc/animation/keyframed_animation_curve.cc index 14dfd9c844..d855decbaf 100644 --- a/cc/animation/keyframed_animation_curve.cc +++ b/cc/animation/keyframed_animation_curve.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/animation/keyframed_animation_curve.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/box_f.h" namespace cc { @@ -26,6 +27,17 @@ void InsertKeyframe(scoped_ptr<Keyframe> keyframe, keyframes.push_back(keyframe.Pass()); } +template <class Keyframes> +float GetProgress(double t, size_t i, const Keyframes& keyframes) { + float progress = + static_cast<float>((t - keyframes[i]->Time()) / + (keyframes[i + 1]->Time() - keyframes[i]->Time())); + + if (keyframes[i]->timing_function()) + progress = keyframes[i]->timing_function()->GetValue(progress); + return progress; +} + scoped_ptr<TimingFunction> CloneTimingFunction( const TimingFunction* timing_function) { DCHECK(timing_function); @@ -46,6 +58,31 @@ double Keyframe::Time() const { return time_; } +scoped_ptr<ColorKeyframe> ColorKeyframe::Create( + double time, + SkColor value, + scoped_ptr<TimingFunction> timing_function) { + return make_scoped_ptr( + new ColorKeyframe(time, value, timing_function.Pass())); +} + +ColorKeyframe::ColorKeyframe(double time, + SkColor value, + scoped_ptr<TimingFunction> timing_function) + : Keyframe(time, timing_function.Pass()), + value_(value) {} + +ColorKeyframe::~ColorKeyframe() {} + +SkColor ColorKeyframe::Value() const { return value_; } + +scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const { + scoped_ptr<TimingFunction> func; + if (timing_function()) + func = CloneTimingFunction(timing_function()); + return ColorKeyframe::Create(Time(), Value(), func.Pass()); +} + scoped_ptr<FloatKeyframe> FloatKeyframe::Create( double time, float value, @@ -127,6 +164,53 @@ scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const { return FilterKeyframe::Create(Time(), Value(), func.Pass()); } +scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve:: + Create() { + return make_scoped_ptr(new KeyframedColorAnimationCurve); +} + +KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {} + +KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {} + +void KeyframedColorAnimationCurve::AddKeyframe( + scoped_ptr<ColorKeyframe> keyframe) { + InsertKeyframe(keyframe.Pass(), keyframes_); +} + +double KeyframedColorAnimationCurve::Duration() const { + return keyframes_.back()->Time() - keyframes_.front()->Time(); +} + +scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const { + scoped_ptr<KeyframedColorAnimationCurve> to_return( + KeyframedColorAnimationCurve::Create()); + for (size_t i = 0; i < keyframes_.size(); ++i) + to_return->AddKeyframe(keyframes_[i]->Clone()); + return to_return.PassAs<AnimationCurve>(); +} + +SkColor KeyframedColorAnimationCurve::GetValue(double t) const { + if (t <= keyframes_.front()->Time()) + return keyframes_.front()->Value(); + + if (t >= keyframes_.back()->Time()) + return keyframes_.back()->Value(); + + size_t i = 0; + for (; i < keyframes_.size() - 1; ++i) { + if (t < keyframes_[i + 1]->Time()) + break; + } + + float progress = GetProgress(t, i, keyframes_); + + return gfx::Tween::ColorValueBetween( + progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value()); +} + +// KeyframedFloatAnimationCurve + scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve:: Create() { return make_scoped_ptr(new KeyframedFloatAnimationCurve); @@ -166,12 +250,7 @@ float KeyframedFloatAnimationCurve::GetValue(double t) const { break; } - float progress = - static_cast<float>((t - keyframes_[i]->Time()) / - (keyframes_[i+1]->Time() - keyframes_[i]->Time())); - - if (keyframes_[i]->timing_function()) - progress = keyframes_[i]->timing_function()->GetValue(progress); + float progress = GetProgress(t, i, keyframes_); return keyframes_[i]->Value() + (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress; diff --git a/cc/animation/keyframed_animation_curve.h b/cc/animation/keyframed_animation_curve.h index 5892dc70e5..4b5ac3bf30 100644 --- a/cc/animation/keyframed_animation_curve.h +++ b/cc/animation/keyframed_animation_curve.h @@ -31,6 +31,26 @@ class CC_EXPORT Keyframe { DISALLOW_COPY_AND_ASSIGN(Keyframe); }; +class CC_EXPORT ColorKeyframe : public Keyframe { + public: + static scoped_ptr<ColorKeyframe> Create( + double time, + SkColor value, + scoped_ptr<TimingFunction> timing_function); + virtual ~ColorKeyframe(); + + SkColor Value() const; + + scoped_ptr<ColorKeyframe> Clone() const; + + private: + ColorKeyframe(double time, + SkColor value, + scoped_ptr<TimingFunction> timing_function); + + SkColor value_; +}; + class CC_EXPORT FloatKeyframe : public Keyframe { public: static scoped_ptr<FloatKeyframe> Create( @@ -93,6 +113,32 @@ class CC_EXPORT FilterKeyframe : public Keyframe { FilterOperations value_; }; +class CC_EXPORT KeyframedColorAnimationCurve : public ColorAnimationCurve { + public: + // It is required that the keyframes be sorted by time. + static scoped_ptr<KeyframedColorAnimationCurve> Create(); + + virtual ~KeyframedColorAnimationCurve(); + + void AddKeyframe(scoped_ptr<ColorKeyframe> keyframe); + + // AnimationCurve implementation + virtual double Duration() const OVERRIDE; + virtual scoped_ptr<AnimationCurve> Clone() const OVERRIDE; + + // BackgrounColorAnimationCurve implementation + virtual SkColor GetValue(double t) const OVERRIDE; + + private: + KeyframedColorAnimationCurve(); + + // Always sorted in order of increasing time. No two keyframes have the + // same time. + ScopedPtrVector<ColorKeyframe> keyframes_; + + DISALLOW_COPY_AND_ASSIGN(KeyframedColorAnimationCurve); +}; + class CC_EXPORT KeyframedFloatAnimationCurve : public FloatAnimationCurve { public: // It is required that the keyframes be sorted by time. diff --git a/cc/animation/keyframed_animation_curve_unittest.cc b/cc/animation/keyframed_animation_curve_unittest.cc index 7eb3b1c5b5..63e9866802 100644 --- a/cc/animation/keyframed_animation_curve_unittest.cc +++ b/cc/animation/keyframed_animation_curve_unittest.cc @@ -7,7 +7,9 @@ #include "cc/animation/transform_operations.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/box_f.h" +#include "ui/gfx/test/color_util.h" namespace cc { namespace { @@ -22,6 +24,98 @@ void ExpectBrightness(double brightness, const FilterOperations& filter) { EXPECT_FLOAT_EQ(brightness, filter.at(0).amount()); } +// Tests that a color animation with one keyframe works as expected. +TEST(KeyframedAnimationCurveTest, OneColorKeyFrame) { + SkColor color = SkColorSetARGB(255, 255, 255, 255); + scoped_ptr<KeyframedColorAnimationCurve> curve( + KeyframedColorAnimationCurve::Create()); + curve->AddKeyframe( + ColorKeyframe::Create(0.0, color, scoped_ptr<TimingFunction>())); + + EXPECT_SKCOLOR_EQ(color, curve->GetValue(-1.f)); + EXPECT_SKCOLOR_EQ(color, curve->GetValue(0.f)); + EXPECT_SKCOLOR_EQ(color, curve->GetValue(0.5f)); + EXPECT_SKCOLOR_EQ(color, curve->GetValue(1.f)); + EXPECT_SKCOLOR_EQ(color, curve->GetValue(2.f)); +} + +// Tests that a color animation with two keyframes works as expected. +TEST(KeyframedAnimationCurveTest, TwoColorKeyFrame) { + SkColor color_a = SkColorSetARGB(255, 255, 0, 0); + SkColor color_b = SkColorSetARGB(255, 0, 255, 0); + SkColor color_midpoint = gfx::Tween::ColorValueBetween(0.5, color_a, color_b); + scoped_ptr<KeyframedColorAnimationCurve> curve( + KeyframedColorAnimationCurve::Create()); + curve->AddKeyframe( + ColorKeyframe::Create(0.0, color_a, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(1.0, color_b, scoped_ptr<TimingFunction>())); + + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(-1.f)); + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.f)); + EXPECT_SKCOLOR_EQ(color_midpoint, curve->GetValue(0.5f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(1.f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(2.f)); +} + +// Tests that a color animation with three keyframes works as expected. +TEST(KeyframedAnimationCurveTest, ThreeColorKeyFrame) { + SkColor color_a = SkColorSetARGB(255, 255, 0, 0); + SkColor color_b = SkColorSetARGB(255, 0, 255, 0); + SkColor color_c = SkColorSetARGB(255, 0, 0, 255); + SkColor color_midpoint1 = + gfx::Tween::ColorValueBetween(0.5, color_a, color_b); + SkColor color_midpoint2 = + gfx::Tween::ColorValueBetween(0.5, color_b, color_c); + scoped_ptr<KeyframedColorAnimationCurve> curve( + KeyframedColorAnimationCurve::Create()); + curve->AddKeyframe( + ColorKeyframe::Create(0.0, color_a, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(1.0, color_b, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(2.0, color_c, scoped_ptr<TimingFunction>())); + + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(-1.f)); + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.f)); + EXPECT_SKCOLOR_EQ(color_midpoint1, curve->GetValue(0.5f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(1.f)); + EXPECT_SKCOLOR_EQ(color_midpoint2, curve->GetValue(1.5f)); + EXPECT_SKCOLOR_EQ(color_c, curve->GetValue(2.f)); + EXPECT_SKCOLOR_EQ(color_c, curve->GetValue(3.f)); +} + +// Tests that a colro animation with multiple keys at a given time works sanely. +TEST(KeyframedAnimationCurveTest, RepeatedColorKeyFrame) { + SkColor color_a = SkColorSetARGB(255, 64, 0, 0); + SkColor color_b = SkColorSetARGB(255, 192, 0, 0); + + scoped_ptr<KeyframedColorAnimationCurve> curve( + KeyframedColorAnimationCurve::Create()); + curve->AddKeyframe( + ColorKeyframe::Create(0.0, color_a, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(1.0, color_a, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(1.0, color_b, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(2.0, color_b, scoped_ptr<TimingFunction>())); + + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(-1.f)); + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.f)); + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.5f)); + + SkColor value = curve->GetValue(1.0f); + EXPECT_EQ(255u, SkColorGetA(value)); + int red_value = SkColorGetR(value); + EXPECT_LE(64, red_value); + EXPECT_GE(192, red_value); + + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(1.5f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(2.f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(3.f)); +} + // Tests that a float animation with one keyframe works as expected. TEST(KeyframedAnimationCurveTest, OneFloatKeyframe) { scoped_ptr<KeyframedFloatAnimationCurve> curve( diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc index 995a393109..f720229152 100644 --- a/cc/animation/layer_animation_controller.cc +++ b/cc/animation/layer_animation_controller.cc @@ -92,7 +92,7 @@ void LayerAnimationController::RemoveAnimation( UpdateActivation(NormalActivation); } -// According to render layer backing, these are for testing only. +// For testing only. void LayerAnimationController::SuspendAnimations(double monotonic_time) { for (size_t i = 0; i < active_animations_.size(); ++i) { if (!active_animations_[i]->is_finished()) @@ -100,15 +100,6 @@ void LayerAnimationController::SuspendAnimations(double monotonic_time) { } } -// Looking at GraphicsLayerCA, this appears to be the analog to -// SuspendAnimations, which is for testing. -void LayerAnimationController::ResumeAnimations(double monotonic_time) { - for (size_t i = 0; i < active_animations_.size(); ++i) { - if (active_animations_[i]->run_state() == Animation::Paused) - active_animations_[i]->SetRunState(Animation::Running, monotonic_time); - } -} - // Ensures that the list of active animations on the main thread and the impl // thread are kept in sync. void LayerAnimationController::PushAnimationUpdatesTo( @@ -196,6 +187,8 @@ void LayerAnimationController::AccumulatePropertyUpdates( break; } + case Animation::BackgroundColor: { break; } + case Animation::TargetPropertyEnumSize: NOTREACHED(); } @@ -719,6 +712,11 @@ void LayerAnimationController::TickAnimations(double monotonic_time) { break; } + case Animation::BackgroundColor: { + // Not yet implemented. + break; + } + // Do nothing for sentinel value. case Animation::TargetPropertyEnumSize: NOTREACHED(); diff --git a/cc/animation/layer_animation_controller.h b/cc/animation/layer_animation_controller.h index e397794016..4861e2515b 100644 --- a/cc/animation/layer_animation_controller.h +++ b/cc/animation/layer_animation_controller.h @@ -45,7 +45,6 @@ class CC_EXPORT LayerAnimationController virtual void RemoveAnimation(int animation_id, Animation::TargetProperty target_property); virtual void SuspendAnimations(double monotonic_time); - virtual void ResumeAnimations(double monotonic_time); // Ensures that the list of active animations on the main thread and the impl // thread are kept in sync. This function does not take ownership of the impl diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc index 0a88bfd3a5..32252f1da7 100644 --- a/cc/animation/layer_animation_controller_unittest.cc +++ b/cc/animation/layer_animation_controller_unittest.cc @@ -138,18 +138,6 @@ TEST(LayerAnimationControllerTest, SyncPauseAndResume) { EXPECT_EQ(Animation::Paused, controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state()); - - // Resume the main-thread animation. - controller->ResumeAnimations(2.0); - EXPECT_EQ(Animation::Running, - controller->GetAnimation(group_id, - Animation::Opacity)->run_state()); - - // The pause run state change should make it to the impl thread controller. - controller->PushAnimationUpdatesTo(controller_impl.get()); - EXPECT_EQ(Animation::Running, - controller_impl->GetAnimation(group_id, - Animation::Opacity)->run_state()); } TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) { diff --git a/cc/animation/scrollbar_animation_controller_thinning.cc b/cc/animation/scrollbar_animation_controller_thinning.cc index ce196fbf95..3de75989d0 100644 --- a/cc/animation/scrollbar_animation_controller_thinning.cc +++ b/cc/animation/scrollbar_animation_controller_thinning.cc @@ -10,14 +10,22 @@ #include "cc/layers/layer_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" +namespace { +const float kIdleThicknessScale = 0.4f; +const float kIdleOpacity = 0.7f; +const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f; +const int kDefaultAnimationDelay = 500; +const int kDefaultAnimationDuration = 300; +} + namespace cc { scoped_ptr<ScrollbarAnimationControllerThinning> ScrollbarAnimationControllerThinning::Create(LayerImpl* scroll_layer) { return make_scoped_ptr(new ScrollbarAnimationControllerThinning( scroll_layer, - base::TimeDelta::FromMilliseconds(500), - base::TimeDelta::FromMilliseconds(300))); + base::TimeDelta::FromMilliseconds(kDefaultAnimationDelay), + base::TimeDelta::FromMilliseconds(kDefaultAnimationDuration))); } scoped_ptr<ScrollbarAnimationControllerThinning> @@ -33,11 +41,17 @@ ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning( base::TimeDelta animation_duration) : ScrollbarAnimationController(), scroll_layer_(scroll_layer), - scroll_gesture_in_progress_(false), mouse_is_over_scrollbar_(false), + mouse_is_near_scrollbar_(false), + thickness_change_(NONE), + opacity_change_(NONE), + should_delay_animation_(false), animation_delay_(animation_delay), animation_duration_(animation_duration), - mouse_move_distance_to_trigger_animation_(100.f) {} + mouse_move_distance_to_trigger_animation_( + kDefaultMouseMoveDistanceToTriggerAnimation) { + ApplyOpacityAndThumbThicknessScale(kIdleOpacity, kIdleThicknessScale); +} ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() { } @@ -48,92 +62,120 @@ bool ScrollbarAnimationControllerThinning::IsAnimating() const { base::TimeDelta ScrollbarAnimationControllerThinning::DelayBeforeStart( base::TimeTicks now) const { + if (!should_delay_animation_) + return base::TimeDelta(); if (now > last_awaken_time_ + animation_delay_) return base::TimeDelta(); return animation_delay_ - (now - last_awaken_time_); } bool ScrollbarAnimationControllerThinning::Animate(base::TimeTicks now) { - if (mouse_is_over_scrollbar_) { - ApplyOpacityAndThumbThicknessScale(1, 1); - return false; - } float progress = AnimationProgressAtTime(now); float opacity = OpacityAtAnimationProgress(progress); float thumb_thickness_scale = ThumbThicknessScaleAtAnimationProgress( progress); ApplyOpacityAndThumbThicknessScale(opacity, thumb_thickness_scale); - if (progress == 1.f) + if (progress == 1.f) { + opacity_change_ = NONE; + thickness_change_ = NONE; last_awaken_time_ = base::TimeTicks(); + } return IsAnimating() && DelayBeforeStart(now) == base::TimeDelta(); } void ScrollbarAnimationControllerThinning::DidScrollGestureBegin() { - ApplyOpacityAndThumbThicknessScale(1, 1); - last_awaken_time_ = base::TimeTicks(); - scroll_gesture_in_progress_ = true; } void ScrollbarAnimationControllerThinning::DidScrollGestureEnd( base::TimeTicks now) { - last_awaken_time_ = now; - scroll_gesture_in_progress_ = false; } void ScrollbarAnimationControllerThinning::DidMouseMoveOffScrollbar( base::TimeTicks now) { mouse_is_over_scrollbar_ = false; - DidScrollUpdate(now); + mouse_is_near_scrollbar_ = false; + last_awaken_time_ = now; + should_delay_animation_ = false; + opacity_change_ = DECREASE; + thickness_change_ = DECREASE; } bool ScrollbarAnimationControllerThinning::DidScrollUpdate( base::TimeTicks now) { - ApplyOpacityAndThumbThicknessScale(1, 1); + ApplyOpacityAndThumbThicknessScale( + 1, mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale); last_awaken_time_ = now; + should_delay_animation_ = true; + if (!mouse_is_over_scrollbar_) + opacity_change_ = DECREASE; return true; } bool ScrollbarAnimationControllerThinning::DidMouseMoveNear( base::TimeTicks now, float distance) { - if (distance == 0.0) { - mouse_is_over_scrollbar_ = true; + bool mouse_is_over_scrollbar = distance == 0.0; + bool mouse_is_near_scrollbar = + distance < mouse_move_distance_to_trigger_animation_; + + if (mouse_is_over_scrollbar == mouse_is_over_scrollbar_ && + mouse_is_near_scrollbar == mouse_is_near_scrollbar_) return false; + + if (mouse_is_over_scrollbar_ != mouse_is_over_scrollbar) { + mouse_is_over_scrollbar_ = mouse_is_over_scrollbar; + opacity_change_ = mouse_is_over_scrollbar_ ? INCREASE : DECREASE; } - if (distance < mouse_move_distance_to_trigger_animation_) - return DidScrollUpdate(now); + if (mouse_is_near_scrollbar_ != mouse_is_near_scrollbar) { + mouse_is_near_scrollbar_ = mouse_is_near_scrollbar; + thickness_change_ = mouse_is_near_scrollbar_ ? INCREASE : DECREASE; + } - return false; + last_awaken_time_ = now; + should_delay_animation_ = false; + return true; } float ScrollbarAnimationControllerThinning::AnimationProgressAtTime( base::TimeTicks now) { - if (scroll_gesture_in_progress_) - return 0; - if (last_awaken_time_.is_null()) return 1; base::TimeDelta delta = now - last_awaken_time_; - float progress = (delta - animation_delay_).InSecondsF() / - animation_duration_.InSecondsF(); + if (should_delay_animation_) + delta -= animation_delay_; + float progress = delta.InSecondsF() / animation_duration_.InSecondsF(); return std::max(std::min(progress, 1.f), 0.f); } float ScrollbarAnimationControllerThinning::OpacityAtAnimationProgress( float progress) { - const float kIdleOpacity = 0.7f; - - return ((1.f - kIdleOpacity) * (1.f - progress)) + kIdleOpacity; + if (opacity_change_ == NONE) + return mouse_is_over_scrollbar_ ? 1.f : kIdleOpacity; + float factor = opacity_change_ == INCREASE ? progress : (1.f - progress); + float ret = ((1.f - kIdleOpacity) * factor) + kIdleOpacity; + return ret; } float ScrollbarAnimationControllerThinning::ThumbThicknessScaleAtAnimationProgress( float progress) { - const float kIdleThicknessScale = 0.4f; + if (thickness_change_ == NONE) + return mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale; + float factor = thickness_change_ == INCREASE ? progress : (1.f - progress); + return ((1.f - kIdleThicknessScale) * factor) + kIdleThicknessScale; +} - return ((1.f - kIdleThicknessScale) * (1.f - progress)) + kIdleThicknessScale; +float ScrollbarAnimationControllerThinning::AdjustScale( + float new_value, + float current_value, + AnimationChange animation_change) { + if (animation_change == INCREASE && current_value > new_value) + return current_value; + if (animation_change == DECREASE && current_value < new_value) + return current_value; + return new_value; } void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale( @@ -141,16 +183,25 @@ void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale( ScrollbarLayerImplBase* horizontal_scrollbar = scroll_layer_->horizontal_scrollbar_layer(); if (horizontal_scrollbar) { - horizontal_scrollbar->SetOpacity(opacity); - horizontal_scrollbar->set_thumb_thickness_scale_factor( - thumb_thickness_scale); + horizontal_scrollbar->SetOpacity( + AdjustScale(opacity, horizontal_scrollbar->opacity(), opacity_change_)); + horizontal_scrollbar->SetThumbThicknessScaleFactor( + AdjustScale( + thumb_thickness_scale, + horizontal_scrollbar->thumb_thickness_scale_factor(), + thickness_change_)); } ScrollbarLayerImplBase* vertical_scrollbar = scroll_layer_->vertical_scrollbar_layer(); if (vertical_scrollbar) { - vertical_scrollbar->SetOpacity(opacity); - vertical_scrollbar->set_thumb_thickness_scale_factor(thumb_thickness_scale); + vertical_scrollbar->SetOpacity( + AdjustScale(opacity, vertical_scrollbar->opacity(), opacity_change_)); + vertical_scrollbar->SetThumbThicknessScaleFactor( + AdjustScale( + thumb_thickness_scale, + vertical_scrollbar->thumb_thickness_scale_factor(), + thickness_change_)); } } diff --git a/cc/animation/scrollbar_animation_controller_thinning.h b/cc/animation/scrollbar_animation_controller_thinning.h index 8038745369..07b4515ec3 100644 --- a/cc/animation/scrollbar_animation_controller_thinning.h +++ b/cc/animation/scrollbar_animation_controller_thinning.h @@ -29,6 +29,8 @@ class CC_EXPORT ScrollbarAnimationControllerThinning void set_mouse_move_distance_for_test(float distance) { mouse_move_distance_to_trigger_animation_ = distance; } + bool mouse_is_over_scrollbar() const { return mouse_is_over_scrollbar_; } + bool mouse_is_near_scrollbar() const { return mouse_is_near_scrollbar_; } // ScrollbarAnimationController overrides. virtual bool IsAnimating() const OVERRIDE; @@ -47,22 +49,40 @@ class CC_EXPORT ScrollbarAnimationControllerThinning base::TimeDelta animation_duration); private: + // Describes whether the current animation should INCREASE (darken / thicken) + // a bar or DECREASE it (lighten / thin). + enum AnimationChange { + NONE, + INCREASE, + DECREASE + }; // Returns how far through the animation we are as a progress value from // 0 to 1. float AnimationProgressAtTime(base::TimeTicks now); float OpacityAtAnimationProgress(float progress); float ThumbThicknessScaleAtAnimationProgress(float progress); + float AdjustScale(float new_value, + float current_value, + AnimationChange animation_change); void ApplyOpacityAndThumbThicknessScale(float opacity, float thumb_thickness_scale); LayerImpl* scroll_layer_; base::TimeTicks last_awaken_time_; - bool scroll_gesture_in_progress_; bool mouse_is_over_scrollbar_; - + bool mouse_is_near_scrollbar_; + // Are we narrowing or thickening the bars. + AnimationChange thickness_change_; + // Are we darkening or lightening the bars. + AnimationChange opacity_change_; + // Should the animation be delayed or start immediately. + bool should_delay_animation_; + // If |should_delay_animation_| is true, delay the animation by this amount. base::TimeDelta animation_delay_; + // The time for the animation to run. base::TimeDelta animation_duration_; + // How close should the mouse be to the scrollbar before we thicken it. float mouse_move_distance_to_trigger_animation_; DISALLOW_COPY_AND_ASSIGN(ScrollbarAnimationControllerThinning); diff --git a/cc/animation/scrollbar_animation_controller_thinning_unittest.cc b/cc/animation/scrollbar_animation_controller_thinning_unittest.cc index 7bb507614e..c915632f2f 100644 --- a/cc/animation/scrollbar_animation_controller_thinning_unittest.cc +++ b/cc/animation/scrollbar_animation_controller_thinning_unittest.cc @@ -43,128 +43,194 @@ class ScrollbarAnimationControllerThinningTest : public testing::Test { scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar_layer_; }; +// Check initialization of scrollbar. TEST_F(ScrollbarAnimationControllerThinningTest, Idle) { scrollbar_controller_->Animate(base::TimeTicks()); EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); } -TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByScrollGesture) { +// Scroll content. Confirm the scrollbar gets dark and then becomes light +// after stopping. +TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByProgrammaticScroll) { base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->DidScrollGestureBegin(); - EXPECT_FALSE(scrollbar_controller_->IsAnimating()); + EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time)); + EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + // Scrollbar doesn't change size if triggered by scroll. + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); - time += base::TimeDelta::FromSeconds(100); + time += base::TimeDelta::FromSeconds(1); + EXPECT_EQ(1, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - scrollbar_controller_->DidScrollGestureEnd(time); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); - EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + // Subsequent scroll restarts animation. + EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time)); EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); time += base::TimeDelta::FromSeconds(1); + EXPECT_EQ(1, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); time += base::TimeDelta::FromSeconds(1); + EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); - scrollbar_controller_->DidScrollGestureBegin(); - scrollbar_controller_->DidScrollGestureEnd(time); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); +} +// Initiate a scroll when the pointer is already near the scrollbar. It should +// remain thick. +TEST_F(ScrollbarAnimationControllerThinningTest, ScrollWithMouseNear) { + base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); + + scrollbar_controller_->DidMouseMoveNear(time, 1); + time += base::TimeDelta::FromSeconds(3); scrollbar_controller_->Animate(time); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time)); + EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); + // Scrollbar should still be thick. EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - time += base::TimeDelta::FromSeconds(1); + time += base::TimeDelta::FromSeconds(5); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); +} +// Move the pointer near the scrollbar. Confirm it gets thick and narrow when +// moved away. +TEST_F(ScrollbarAnimationControllerThinningTest, MouseNear) { + base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor()); + scrollbar_controller_->DidMouseMoveNear(time, 1); + EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); + // Should animate to thickened but not darken. time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor()); time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); -} + EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor()); -TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByProgrammaticScroll) { - base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time)); - EXPECT_TRUE(scrollbar_controller_->IsAnimating()); - EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); + // Subsequent moves should not change anything. + scrollbar_controller_->DidMouseMoveNear(time, 1); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); + + // Now move away from bar. time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); + scrollbar_controller_->DidMouseMoveNear(time, 26); + EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time)); + // Animate to narrow. time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor()); time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor()); time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); +} +// Move the pointer over the scrollbar. Make sure it gets thick and dark +// and that it gets thin and light when moved away. +TEST_F(ScrollbarAnimationControllerThinningTest, MouseOver) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->DidMouseMoveNear(time, 0); + EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Should animate to thickened and darkened. time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor()); time += base::TimeDelta::FromSeconds(1); - EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time)); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor()); + time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); + + // Subsequent moves should not change anything. + scrollbar_controller_->DidMouseMoveNear(time, 0); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); + // Now move away from bar. time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->Animate(time); + scrollbar_controller_->DidMouseMoveNear(time, 26); + EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + // Animate to narrow. time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity()); @@ -179,47 +245,87 @@ TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByProgrammaticScroll) { scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); } -TEST_F(ScrollbarAnimationControllerThinningTest, MouseOverAndOut) { +// First move the pointer near the scrollbar, then over it, then back near +// then far away. Confirm that first the bar gets thick, then dark, then light, +// then narrow. +TEST_F(ScrollbarAnimationControllerThinningTest, MouseNearThenOver) { base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time)); + scrollbar_controller_->DidMouseMoveNear(time, 1); EXPECT_TRUE(scrollbar_controller_->IsAnimating()); - EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); + EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Should animate to thickened but not darken. + time += base::TimeDelta::FromSeconds(3); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); - time += base::TimeDelta::FromSeconds(4); + // Now move over. + scrollbar_controller_->DidMouseMoveNear(time, 0); + EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds()); + + // Should animate to darkened. + time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - scrollbar_controller_->DidMouseMoveNear(time, 0); + time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - time += base::TimeDelta::FromSeconds(4); + time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FALSE(scrollbar_controller_->IsAnimating()); + // This is tricky. The DidMouseMoveOffScrollbar() is sent before the + // subsequent DidMouseMoveNear(), if the mouse moves in that direction. + // This results in the thumb thinning. We want to make sure that when the + // thumb starts expanding it doesn't first narrow to the idle thinness. + time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidMouseMoveOffScrollbar(time); + EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + + time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity()); + EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor()); - time += base::TimeDelta::FromSeconds(4); + scrollbar_controller_->DidMouseMoveNear(time, 1); + // A new animation is kicked off. + EXPECT_TRUE(scrollbar_controller_->IsAnimating()); + + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->Animate(time); + // We will initiate the narrowing again, but it won't get decremented until + // the new animation catches up to it. + EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity()); + // Now the thickness should be increasing, but it shouldn't happen until the + // animation catches up. + EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor()); + + time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor()); + // The thickness now gets big again. + EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor()); time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity()); - EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); + // The thickness now gets big again. + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); } } // namespace diff --git a/cc/animation/transform_operation.cc b/cc/animation/transform_operation.cc index 5ede71b6e6..889f7bd410 100644 --- a/cc/animation/transform_operation.cc +++ b/cc/animation/transform_operation.cc @@ -163,11 +163,19 @@ bool TransformOperation::BlendTransformOperations( SkMScalar from_perspective_depth = IsOperationIdentity(from) ? std::numeric_limits<SkMScalar>::max() : from->perspective_depth; - SkMScalar to_perspective_depth = IsOperationIdentity(to) - ? std::numeric_limits<SkMScalar>::max() - : to->perspective_depth; - result->ApplyPerspectiveDepth(BlendSkMScalars( - from_perspective_depth, to_perspective_depth, progress)); + SkMScalar to_perspective_depth = + IsOperationIdentity(to) ? std::numeric_limits<SkMScalar>::max() + : to->perspective_depth; + if (from_perspective_depth == 0.f || to_perspective_depth == 0.f) + return false; + + SkMScalar blended_perspective_depth = BlendSkMScalars( + 1.f / from_perspective_depth, 1.f / to_perspective_depth, progress); + + if (blended_perspective_depth == 0.f) + return false; + + result->ApplyPerspectiveDepth(1.f / blended_perspective_depth); break; } case TransformOperation::TransformOperationMatrix: { diff --git a/cc/animation/transform_operations_unittest.cc b/cc/animation/transform_operations_unittest.cc index 6bc9e03976..49b208e128 100644 --- a/cc/animation/transform_operations_unittest.cc +++ b/cc/animation/transform_operations_unittest.cc @@ -570,8 +570,7 @@ TEST(TransformOperationTest, BlendPerspectiveFromIdentity) { SkMScalar progress = 0.5f; gfx::Transform expected; - expected.ApplyPerspectiveDepth(500 + - 0.5 * std::numeric_limits<SkMScalar>::max()); + expected.ApplyPerspectiveDepth(2000); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, operations.Blend(*identity_operations[i], progress)); @@ -662,8 +661,7 @@ TEST(TransformOperationTest, BlendPerspectiveToIdentity) { SkMScalar progress = 0.5f; gfx::Transform expected; - expected.ApplyPerspectiveDepth(500 + - 0.5 * std::numeric_limits<SkMScalar>::max()); + expected.ApplyPerspectiveDepth(2000); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, identity_operations[i]->Blend(operations, progress)); @@ -678,13 +676,13 @@ TEST(TransformOperationTest, ExtrapolatePerspectiveBlending) { operations2.AppendPerspective(500); gfx::Transform expected; - expected.ApplyPerspectiveDepth(250); + expected.ApplyPerspectiveDepth(400); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, operations1.Blend(operations2, -0.5)); expected.MakeIdentity(); - expected.ApplyPerspectiveDepth(1250); + expected.ApplyPerspectiveDepth(2000); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, operations1.Blend(operations2, 1.5)); @@ -1072,6 +1070,33 @@ TEST(TransformOperationsTest, BlendedBoundsForRotationEmpiricalTests) { } } +TEST(TransformOperationTest, PerspectiveMatrixAndTransformBlendingEquivalency) { + TransformOperations from_operations; + from_operations.AppendPerspective(200); + + TransformOperations to_operations; + to_operations.AppendPerspective(1000); + + gfx::Transform from_transform; + from_transform.ApplyPerspectiveDepth(200); + + gfx::Transform to_transform; + to_transform.ApplyPerspectiveDepth(1000); + + static const int steps = 20; + for (int i = 0; i < steps; ++i) { + double progress = static_cast<double>(i) / (steps - 1); + + gfx::Transform blended_matrix = to_transform; + EXPECT_TRUE(blended_matrix.Blend(from_transform, progress)); + + gfx::Transform blended_transform = + to_operations.Blend(from_operations, progress); + + EXPECT_TRANSFORMATION_MATRIX_EQ(blended_matrix, blended_transform); + } +} + TEST(TransformOperationTest, BlendedBoundsForSequence) { TransformOperations operations_from; operations_from.AppendTranslate(2.0, 4.0, -1.0); diff --git a/cc/base/math_util.cc b/cc/base/math_util.cc index eeb1523db4..76b2bb93cc 100644 --- a/cc/base/math_util.cc +++ b/cc/base/math_util.cc @@ -466,6 +466,13 @@ gfx::RectF MathUtil::ScaleRectProportional(const gfx::RectF& input_outer_rect, } static inline float ScaleOnAxis(double a, double b, double c) { + if (!b && !c) + return a; + if (!a && !c) + return b; + if (!a && !b) + return c; + // Do the sqrt as a double to not lose precision. return static_cast<float>(std::sqrt(a * a + b * b + c * c)); } diff --git a/cc/base/switches.cc b/cc/base/switches.cc index 5dbb2960a2..be4a2c55ad 100644 --- a/cc/base/switches.cc +++ b/cc/base/switches.cc @@ -141,6 +141,9 @@ const char kDisableMapImage[] = "disable-map-image"; // Prevents the layer tree unit tests from timing out. const char kCCLayerTreeTestNoTimeout[] = "cc-layer-tree-test-no-timeout"; +// Makes pixel tests write their output instead of read it. +const char kCCRebaselinePixeltests[] = "cc-rebaseline-pixeltests"; + // Disable textures using RGBA_4444 layout. const char kDisable4444Textures[] = "disable-4444-textures"; @@ -162,7 +165,8 @@ bool IsLCDTextEnabled() { #endif } -bool IsImplSidePaintingEnabled() { +namespace { +bool CheckImplSidePaintingStatus() { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); if (command_line.HasSwitch(cc::switches::kDisableImplSidePainting)) @@ -176,6 +180,12 @@ bool IsImplSidePaintingEnabled() { return false; #endif } +} // namespace + +bool IsImplSidePaintingEnabled() { + static bool enabled = CheckImplSidePaintingStatus(); + return enabled; +} bool IsMapImageEnabled() { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); diff --git a/cc/base/switches.h b/cc/base/switches.h index ed6555a6e6..e92eb2e31c 100644 --- a/cc/base/switches.h +++ b/cc/base/switches.h @@ -69,6 +69,7 @@ CC_EXPORT extern const char kUIShowNonOccludingRects[]; // Unit test related. CC_EXPORT extern const char kCCLayerTreeTestNoTimeout[]; +CC_EXPORT extern const char kCCRebaselinePixeltests[]; CC_EXPORT bool IsLCDTextEnabled(); CC_EXPORT bool IsImplSidePaintingEnabled(); @@ -360,6 +360,9 @@ 'resources/scoped_resource.h', 'resources/scoped_ui_resource.cc', 'resources/scoped_ui_resource.h', + 'resources/shared_bitmap.cc', + 'resources/shared_bitmap.h', + 'resources/shared_bitmap_manager.h', 'resources/single_release_callback.cc', 'resources/single_release_callback.h', 'resources/skpicture_content_layer_updater.cc', diff --git a/cc/cc.target.darwin-arm.mk b/cc/cc.target.darwin-arm.mk index 9c23ae0168..570ebfd0d5 100644 --- a/cc/cc.target.darwin-arm.mk +++ b/cc/cc.target.darwin-arm.mk @@ -180,6 +180,7 @@ LOCAL_SRC_FILES := \ cc/resources/resource_update_queue.cc \ cc/resources/scoped_resource.cc \ cc/resources/scoped_ui_resource.cc \ + cc/resources/shared_bitmap.cc \ cc/resources/single_release_callback.cc \ cc/resources/skpicture_content_layer_updater.cc \ cc/resources/texture_mailbox.cc \ @@ -253,13 +254,13 @@ MY_DEFS_Debug := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ @@ -363,13 +364,13 @@ MY_DEFS_Release := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ diff --git a/cc/cc.target.darwin-mips.mk b/cc/cc.target.darwin-mips.mk index 20fcbe3e92..c0d84f746f 100644 --- a/cc/cc.target.darwin-mips.mk +++ b/cc/cc.target.darwin-mips.mk @@ -180,6 +180,7 @@ LOCAL_SRC_FILES := \ cc/resources/resource_update_queue.cc \ cc/resources/scoped_resource.cc \ cc/resources/scoped_ui_resource.cc \ + cc/resources/shared_bitmap.cc \ cc/resources/single_release_callback.cc \ cc/resources/skpicture_content_layer_updater.cc \ cc/resources/texture_mailbox.cc \ @@ -252,13 +253,13 @@ MY_DEFS_Debug := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ @@ -361,13 +362,13 @@ MY_DEFS_Release := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ diff --git a/cc/cc.target.darwin-x86.mk b/cc/cc.target.darwin-x86.mk index d358842a7d..585967d466 100644 --- a/cc/cc.target.darwin-x86.mk +++ b/cc/cc.target.darwin-x86.mk @@ -180,6 +180,7 @@ LOCAL_SRC_FILES := \ cc/resources/resource_update_queue.cc \ cc/resources/scoped_resource.cc \ cc/resources/scoped_ui_resource.cc \ + cc/resources/shared_bitmap.cc \ cc/resources/single_release_callback.cc \ cc/resources/skpicture_content_layer_updater.cc \ cc/resources/texture_mailbox.cc \ @@ -255,13 +256,13 @@ MY_DEFS_Debug := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ @@ -368,13 +369,13 @@ MY_DEFS_Release := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ diff --git a/cc/cc.target.linux-arm.mk b/cc/cc.target.linux-arm.mk index 9c23ae0168..570ebfd0d5 100644 --- a/cc/cc.target.linux-arm.mk +++ b/cc/cc.target.linux-arm.mk @@ -180,6 +180,7 @@ LOCAL_SRC_FILES := \ cc/resources/resource_update_queue.cc \ cc/resources/scoped_resource.cc \ cc/resources/scoped_ui_resource.cc \ + cc/resources/shared_bitmap.cc \ cc/resources/single_release_callback.cc \ cc/resources/skpicture_content_layer_updater.cc \ cc/resources/texture_mailbox.cc \ @@ -253,13 +254,13 @@ MY_DEFS_Debug := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ @@ -363,13 +364,13 @@ MY_DEFS_Release := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ diff --git a/cc/cc.target.linux-mips.mk b/cc/cc.target.linux-mips.mk index 20fcbe3e92..c0d84f746f 100644 --- a/cc/cc.target.linux-mips.mk +++ b/cc/cc.target.linux-mips.mk @@ -180,6 +180,7 @@ LOCAL_SRC_FILES := \ cc/resources/resource_update_queue.cc \ cc/resources/scoped_resource.cc \ cc/resources/scoped_ui_resource.cc \ + cc/resources/shared_bitmap.cc \ cc/resources/single_release_callback.cc \ cc/resources/skpicture_content_layer_updater.cc \ cc/resources/texture_mailbox.cc \ @@ -252,13 +253,13 @@ MY_DEFS_Debug := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ @@ -361,13 +362,13 @@ MY_DEFS_Release := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ diff --git a/cc/cc.target.linux-x86.mk b/cc/cc.target.linux-x86.mk index d358842a7d..585967d466 100644 --- a/cc/cc.target.linux-x86.mk +++ b/cc/cc.target.linux-x86.mk @@ -180,6 +180,7 @@ LOCAL_SRC_FILES := \ cc/resources/resource_update_queue.cc \ cc/resources/scoped_resource.cc \ cc/resources/scoped_ui_resource.cc \ + cc/resources/shared_bitmap.cc \ cc/resources/single_release_callback.cc \ cc/resources/skpicture_content_layer_updater.cc \ cc/resources/texture_mailbox.cc \ @@ -255,13 +256,13 @@ MY_DEFS_Debug := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ @@ -368,13 +369,13 @@ MY_DEFS_Release := \ '-DANGLE_DX11' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ - '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ - '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DDISABLE_NACL' \ '-DCHROMIUM_BUILD' \ '-DUSE_LIBJPEG_TURBO=1' \ '-DUSE_PROPRIETARY_CODECS' \ '-DENABLE_CONFIGURATION_POLICY' \ + '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ + '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index d48a4aefd8..49e82fcbae 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -24,6 +24,7 @@ 'layers/content_layer_unittest.cc', 'layers/contents_scaling_layer_unittest.cc', 'layers/delegated_frame_provider_unittest.cc', + 'layers/delegated_frame_resource_collection_unittest.cc', 'layers/delegated_renderer_layer_impl_unittest.cc', 'layers/heads_up_display_unittest.cc', 'layers/heads_up_display_layer_impl_unittest.cc', @@ -35,6 +36,7 @@ 'layers/nine_patch_layer_unittest.cc', 'layers/picture_image_layer_impl_unittest.cc', 'layers/picture_layer_impl_unittest.cc', + 'layers/picture_layer_unittest.cc', 'layers/render_surface_unittest.cc', 'layers/scrollbar_layer_unittest.cc', 'layers/solid_color_layer_impl_unittest.cc', @@ -76,6 +78,7 @@ 'scheduler/scheduler_unittest.cc', 'scheduler/texture_uploader_unittest.cc', 'test/fake_web_graphics_context_3d_unittest.cc', + 'test/layer_tree_json_parser_unittest.cc', 'trees/damage_tracker_unittest.cc', 'trees/layer_sorter_unittest.cc', 'trees/layer_tree_host_common_unittest.cc', @@ -259,7 +262,8 @@ 'resources/worker_pool_perftest.cc', 'test/cc_test_suite.cc', 'test/lap_timer.cc', - 'test/run_all_unittests.cc', + 'test/run_all_perftests.cc', + 'trees/layer_tree_host_common_perftest.cc', 'trees/layer_tree_host_perftest.cc', ], 'include_dirs': [ @@ -324,6 +328,7 @@ 'dependencies': [ '../skia/skia.gyp:skia', '../ui/gfx/gfx.gyp:gfx', + '../ui/ui_unittests.gyp:ui_test_support', ], }, ], diff --git a/cc/debug/fake_web_graphics_context_3d.cc b/cc/debug/fake_web_graphics_context_3d.cc index 25157bfe49..eab653b360 100644 --- a/cc/debug/fake_web_graphics_context_3d.cc +++ b/cc/debug/fake_web_graphics_context_3d.cc @@ -9,6 +9,7 @@ using WebKit::WGC3Dboolean; using WebKit::WGC3Denum; +using WebKit::WGC3Dsizei; using WebKit::WebGLId; using WebKit::WebGraphicsContext3D; @@ -234,46 +235,82 @@ WGC3Dboolean FakeWebGraphicsContext3D::isTexture( return false; } -WebGLId FakeWebGraphicsContext3D::createBuffer() { - return 1; +void FakeWebGraphicsContext3D::genBuffers(WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) + ids[i] = 1; } -void FakeWebGraphicsContext3D::deleteBuffer(WebKit::WebGLId id) { +void FakeWebGraphicsContext3D::genFramebuffers( + WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) + ids[i] = 1; } -WebGLId FakeWebGraphicsContext3D::createFramebuffer() { - return 1; +void FakeWebGraphicsContext3D::genRenderbuffers( + WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) + ids[i] = 1; } -void FakeWebGraphicsContext3D::deleteFramebuffer(WebKit::WebGLId id) { +void FakeWebGraphicsContext3D::genTextures(WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) + ids[i] = 1; } -WebGLId FakeWebGraphicsContext3D::createProgram() { +void FakeWebGraphicsContext3D::deleteBuffers(WGC3Dsizei count, WebGLId* ids) { +} + +void FakeWebGraphicsContext3D::deleteFramebuffers( + WGC3Dsizei count, WebGLId* ids) { +} + +void FakeWebGraphicsContext3D::deleteRenderbuffers( + WGC3Dsizei count, WebGLId* ids) { +} + +void FakeWebGraphicsContext3D::deleteTextures(WGC3Dsizei count, WebGLId* ids) { +} + +WebGLId FakeWebGraphicsContext3D::createBuffer() { return 1; } -void FakeWebGraphicsContext3D::deleteProgram(WebKit::WebGLId id) { +WebGLId FakeWebGraphicsContext3D::createFramebuffer() { + return 1; } WebGLId FakeWebGraphicsContext3D::createRenderbuffer() { return 1; } +WebGLId FakeWebGraphicsContext3D::createTexture() { + return 1; +} + +void FakeWebGraphicsContext3D::deleteBuffer(WebKit::WebGLId id) { +} + +void FakeWebGraphicsContext3D::deleteFramebuffer(WebKit::WebGLId id) { +} + void FakeWebGraphicsContext3D::deleteRenderbuffer(WebKit::WebGLId id) { } -WebGLId FakeWebGraphicsContext3D::createShader(WGC3Denum) { - return 1; +void FakeWebGraphicsContext3D::deleteTexture(WebGLId texture_id) { } -void FakeWebGraphicsContext3D::deleteShader(WebKit::WebGLId id) { +WebGLId FakeWebGraphicsContext3D::createProgram() { + return 1; } -WebGLId FakeWebGraphicsContext3D::createTexture() { +WebGLId FakeWebGraphicsContext3D::createShader(WGC3Denum) { return 1; } -void FakeWebGraphicsContext3D::deleteTexture(WebGLId texture_id) { +void FakeWebGraphicsContext3D::deleteProgram(WebKit::WebGLId id) { +} + +void FakeWebGraphicsContext3D::deleteShader(WebKit::WebGLId id) { } void FakeWebGraphicsContext3D::attachShader(WebGLId program, WebGLId shader) { diff --git a/cc/debug/fake_web_graphics_context_3d.h b/cc/debug/fake_web_graphics_context_3d.h index 1bd3647276..f923f71409 100644 --- a/cc/debug/fake_web_graphics_context_3d.h +++ b/cc/debug/fake_web_graphics_context_3d.h @@ -530,19 +530,33 @@ class CC_EXPORT FakeWebGraphicsContext3D WebKit::WGC3Dsizei width, WebKit::WGC3Dsizei height) {} + virtual void genBuffers(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void genFramebuffers(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void genRenderbuffers(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void genTextures(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + + virtual void deleteBuffers(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void deleteFramebuffers( + WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void deleteRenderbuffers( + WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void deleteTextures(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual WebKit::WebGLId createBuffer(); virtual WebKit::WebGLId createFramebuffer(); - virtual WebKit::WebGLId createProgram(); virtual WebKit::WebGLId createRenderbuffer(); - virtual WebKit::WebGLId createShader(WebKit::WGC3Denum); virtual WebKit::WebGLId createTexture(); virtual void deleteBuffer(WebKit::WebGLId id); virtual void deleteFramebuffer(WebKit::WebGLId id); - virtual void deleteProgram(WebKit::WebGLId id); virtual void deleteRenderbuffer(WebKit::WebGLId id); + virtual void deleteTexture(WebKit::WebGLId id); + + virtual WebKit::WebGLId createProgram(); + virtual WebKit::WebGLId createShader(WebKit::WGC3Denum); + + virtual void deleteProgram(WebKit::WebGLId id); virtual void deleteShader(WebKit::WebGLId id); - virtual void deleteTexture(WebKit::WebGLId texture_id); virtual void texStorage2DEXT( WebKit::WGC3Denum target, diff --git a/cc/debug/test_context_support.cc b/cc/debug/test_context_support.cc index edbbd72977..e5a0b93cef 100644 --- a/cc/debug/test_context_support.cc +++ b/cc/debug/test_context_support.cc @@ -21,6 +21,10 @@ void TestContextSupport::SignalQuery(uint32 query, sync_point_callbacks_.push_back(callback); } +void TestContextSupport::SendManagedMemoryStats( + const gpu::ManagedMemoryStats& stats) { +} + void TestContextSupport::CallAllSyncPointCallbacks() { for (size_t i = 0; i < sync_point_callbacks_.size(); ++i) { base::MessageLoop::current()->PostTask( diff --git a/cc/debug/test_context_support.h b/cc/debug/test_context_support.h index 4c092e902b..067bcaf4f5 100644 --- a/cc/debug/test_context_support.h +++ b/cc/debug/test_context_support.h @@ -21,6 +21,8 @@ class TestContextSupport : public gpu::ContextSupport { const base::Closure& callback) OVERRIDE; virtual void SignalQuery(uint32 query, const base::Closure& callback) OVERRIDE; + virtual void SendManagedMemoryStats(const gpu::ManagedMemoryStats& stats) + OVERRIDE; void CallAllSyncPointCallbacks(); diff --git a/cc/debug/test_web_graphics_context_3d.cc b/cc/debug/test_web_graphics_context_3d.cc index 22f7602a3c..4135ba0217 100644 --- a/cc/debug/test_web_graphics_context_3d.cc +++ b/cc/debug/test_web_graphics_context_3d.cc @@ -188,56 +188,109 @@ WGC3Dboolean TestWebGraphicsContext3D::isTexture( return false; } -WebGLId TestWebGraphicsContext3D::createBuffer() { - return NextBufferId(); +void TestWebGraphicsContext3D::genBuffers(WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) + ids[i] = NextBufferId(); } -void TestWebGraphicsContext3D::deleteBuffer(WebGLId id) { +void TestWebGraphicsContext3D::genFramebuffers( + WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) + ids[i] = kFramebufferId | context_id_ << 16; +} + +void TestWebGraphicsContext3D::genRenderbuffers( + WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) + ids[i] = kRenderbufferId | context_id_ << 16; +} + +void TestWebGraphicsContext3D::genTextures(WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) { + ids[i] = NextTextureId(); + DCHECK_NE(ids[i], kExternalTextureId); + } base::AutoLock lock(namespace_->lock); - unsigned context_id = id >> 17; - unsigned buffer_id = id & 0x1ffff; - DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id); - DCHECK_EQ(context_id, context_id_); + for (int i = 0; i < count; ++i) + namespace_->textures.Append(ids[i], new TestTexture()); } -WebGLId TestWebGraphicsContext3D::createFramebuffer() { - return kFramebufferId | context_id_ << 16; +void TestWebGraphicsContext3D::deleteBuffers(WGC3Dsizei count, WebGLId* ids) { + base::AutoLock lock(namespace_->lock); + for (int i = 0; i < count; ++i) { + unsigned context_id = ids[i] >> 17; + unsigned buffer_id = ids[i] & 0x1ffff; + DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id); + DCHECK_EQ(context_id, context_id_); + } } -void TestWebGraphicsContext3D::deleteFramebuffer(WebGLId id) { - DCHECK_EQ(kFramebufferId | context_id_ << 16, id); +void TestWebGraphicsContext3D::deleteFramebuffers( + WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) + DCHECK_EQ(kFramebufferId | context_id_ << 16, ids[i]); } -WebGLId TestWebGraphicsContext3D::createProgram() { - return kProgramId | context_id_ << 16; +void TestWebGraphicsContext3D::deleteRenderbuffers( + WGC3Dsizei count, WebGLId* ids) { + for (int i = 0; i < count; ++i) + DCHECK_EQ(kRenderbufferId | context_id_ << 16, ids[i]); } -void TestWebGraphicsContext3D::deleteProgram(WebGLId id) { - DCHECK_EQ(kProgramId | context_id_ << 16, id); +void TestWebGraphicsContext3D::deleteTextures(WGC3Dsizei count, WebGLId* ids) { + base::AutoLock lock(namespace_->lock); + for (int i = 0; i < count; ++i) { + namespace_->textures.Remove(ids[i]); + texture_targets_.UnbindTexture(ids[i]); + } +} + +WebGLId TestWebGraphicsContext3D::createBuffer() { + WebGLId id; + genBuffers(1, &id); + return id; +} + +WebGLId TestWebGraphicsContext3D::createFramebuffer() { + WebGLId id; + genFramebuffers(1, &id); + return id; } WebGLId TestWebGraphicsContext3D::createRenderbuffer() { - return kRenderbufferId | context_id_ << 16; + WebGLId id; + genRenderbuffers(1, &id); + return id; +} + +WebGLId TestWebGraphicsContext3D::createTexture() { + WebGLId id; + genTextures(1, &id); + return id; +} + +void TestWebGraphicsContext3D::deleteBuffer(WebGLId id) { + deleteBuffers(1, &id); +} + +void TestWebGraphicsContext3D::deleteFramebuffer(WebGLId id) { + deleteFramebuffers(1, &id); } void TestWebGraphicsContext3D::deleteRenderbuffer(WebGLId id) { - DCHECK_EQ(kRenderbufferId | context_id_ << 16, id); + deleteRenderbuffers(1, &id); } -WebGLId TestWebGraphicsContext3D::createShader(WGC3Denum) { - return kShaderId | context_id_ << 16; +void TestWebGraphicsContext3D::deleteTexture(WebGLId id) { + deleteTextures(1, &id); } -void TestWebGraphicsContext3D::deleteShader(WebGLId id) { - DCHECK_EQ(kShaderId | context_id_ << 16, id); +WebGLId TestWebGraphicsContext3D::createProgram() { + return kProgramId | context_id_ << 16; } -WebGLId TestWebGraphicsContext3D::createTexture() { - WebGLId texture_id = NextTextureId(); - DCHECK_NE(texture_id, kExternalTextureId); - base::AutoLock lock(namespace_->lock); - namespace_->textures.Append(texture_id, new TestTexture()); - return texture_id; +WebGLId TestWebGraphicsContext3D::createShader(WGC3Denum) { + return kShaderId | context_id_ << 16; } WebGLId TestWebGraphicsContext3D::createExternalTexture() { @@ -246,10 +299,12 @@ WebGLId TestWebGraphicsContext3D::createExternalTexture() { return kExternalTextureId; } -void TestWebGraphicsContext3D::deleteTexture(WebGLId texture_id) { - base::AutoLock lock(namespace_->lock); - namespace_->textures.Remove(texture_id); - texture_targets_.UnbindTexture(texture_id); +void TestWebGraphicsContext3D::deleteProgram(WebGLId id) { + DCHECK_EQ(kProgramId | context_id_ << 16, id); +} + +void TestWebGraphicsContext3D::deleteShader(WebGLId id) { + DCHECK_EQ(kShaderId | context_id_ << 16, id); } void TestWebGraphicsContext3D::attachShader(WebGLId program, WebGLId shader) { @@ -370,18 +425,6 @@ void TestWebGraphicsContext3D::loseContextCHROMIUM(WGC3Denum current, shared_contexts_.clear(); } -void TestWebGraphicsContext3D::signalSyncPoint( - unsigned sync_point, - WebGraphicsSyncPointCallback* callback) { - NOTREACHED(); -} - -void TestWebGraphicsContext3D::signalQuery( - WebKit::WebGLId query, - WebGraphicsSyncPointCallback* callback) { - NOTREACHED(); -} - void TestWebGraphicsContext3D::setSwapBuffersCompleteCallbackCHROMIUM( WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* callback) { if (test_capabilities_.swapbuffers_complete_callback) diff --git a/cc/debug/test_web_graphics_context_3d.h b/cc/debug/test_web_graphics_context_3d.h index 574a6bd3c2..48ee70fac1 100644 --- a/cc/debug/test_web_graphics_context_3d.h +++ b/cc/debug/test_web_graphics_context_3d.h @@ -70,20 +70,34 @@ class CC_EXPORT TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { virtual void useProgram(WebKit::WebGLId program); + virtual void genBuffers(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void genFramebuffers(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void genRenderbuffers(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void genTextures(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + + virtual void deleteBuffers(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void deleteFramebuffers( + WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void deleteRenderbuffers( + WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual void deleteTextures(WebKit::WGC3Dsizei count, WebKit::WebGLId* ids); + virtual WebKit::WebGLId createBuffer(); virtual WebKit::WebGLId createFramebuffer(); - virtual WebKit::WebGLId createProgram(); virtual WebKit::WebGLId createRenderbuffer(); - virtual WebKit::WebGLId createShader(WebKit::WGC3Denum); virtual WebKit::WebGLId createTexture(); - virtual WebKit::WebGLId createExternalTexture(); virtual void deleteBuffer(WebKit::WebGLId id); virtual void deleteFramebuffer(WebKit::WebGLId id); - virtual void deleteProgram(WebKit::WebGLId id); virtual void deleteRenderbuffer(WebKit::WebGLId id); + virtual void deleteTexture(WebKit::WebGLId id); + + virtual WebKit::WebGLId createProgram(); + virtual WebKit::WebGLId createShader(WebKit::WGC3Denum); + virtual WebKit::WebGLId createExternalTexture(); + + virtual void deleteProgram(WebKit::WebGLId id); virtual void deleteShader(WebKit::WebGLId id); - virtual void deleteTexture(WebKit::WebGLId texture_id); virtual void endQueryEXT(WebKit::WGC3Denum target); virtual void getQueryObjectuivEXT( @@ -107,11 +121,6 @@ class CC_EXPORT TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { virtual void loseContextCHROMIUM(WebKit::WGC3Denum current, WebKit::WGC3Denum other); - virtual void signalSyncPoint(unsigned sync_point, - WebGraphicsSyncPointCallback* callback); - virtual void signalQuery(WebKit::WebGLId query, - WebGraphicsSyncPointCallback* callback); - virtual void setSwapBuffersCompleteCallbackCHROMIUM( WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* callback); @@ -194,6 +203,9 @@ class CC_EXPORT TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { void set_have_discard_framebuffer(bool have) { test_capabilities_.discard_framebuffer = have; } + void set_support_compressed_texture_etc1(bool support) { + test_capabilities_.texture_format_etc1 = support; + } // When this context is lost, all contexts in its share group are also lost. void add_share_group_context(WebKit::WebGraphicsContext3D* context3d) { @@ -290,7 +302,6 @@ class CC_EXPORT TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { int times_map_buffer_chromium_succeeds_; WebGraphicsContextLostCallback* context_lost_callback_; WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* swap_buffers_callback_; - std::vector<WebGraphicsSyncPointCallback*> sync_point_callbacks_; base::hash_set<WebKit::WebGLId> used_textures_; std::vector<WebKit::WebGraphicsContext3D*> shared_contexts_; int max_texture_size_; diff --git a/cc/input/top_controls_manager.cc b/cc/input/top_controls_manager.cc index 925830cf40..871d9e6f69 100644 --- a/cc/input/top_controls_manager.cc +++ b/cc/input/top_controls_manager.cc @@ -7,11 +7,12 @@ #include <algorithm> #include "base/logging.h" -#include "base/time/time.h" #include "cc/animation/keyframed_animation_curve.h" #include "cc/animation/timing_function.h" #include "cc/input/top_controls_manager_client.h" +#include "cc/output/begin_frame_args.h" #include "cc/trees/layer_tree_impl.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/transform.h" #include "ui/gfx/vector2d_f.h" @@ -48,7 +49,8 @@ TopControlsManager::TopControlsManager(TopControlsManagerClient* client, top_controls_show_height_( top_controls_height * top_controls_hide_threshold), top_controls_hide_height_( - top_controls_height * (1.f - top_controls_show_threshold)) { + top_controls_height * (1.f - top_controls_show_threshold)), + pinch_gesture_active_(false) { CHECK(client_); } @@ -89,6 +91,7 @@ void TopControlsManager::UpdateTopControlsState(TopControlsState constraints, } void TopControlsManager::ScrollBegin() { + DCHECK(!pinch_gesture_active_); ResetAnimations(); current_scroll_delta_ = 0.f; controls_scroll_begin_offset_ = controls_top_offset_; @@ -96,6 +99,9 @@ void TopControlsManager::ScrollBegin() { gfx::Vector2dF TopControlsManager::ScrollBy( const gfx::Vector2dF pending_delta) { + if (pinch_gesture_active_) + return pending_delta; + if (permitted_state_ == SHOWN && pending_delta.y() > 0) return pending_delta; else if (permitted_state_ == HIDDEN && pending_delta.y() < 0) @@ -120,9 +126,24 @@ gfx::Vector2dF TopControlsManager::ScrollBy( } void TopControlsManager::ScrollEnd() { + DCHECK(!pinch_gesture_active_); StartAnimationIfNecessary(); } +void TopControlsManager::PinchBegin() { + DCHECK(!pinch_gesture_active_); + pinch_gesture_active_ = true; + StartAnimationIfNecessary(); +} + +void TopControlsManager::PinchEnd() { + DCHECK(pinch_gesture_active_); + // Pinch{Begin,End} will always occur within the scope of Scroll{Begin,End}, + // so return to a state expected by the remaining scroll sequence. + pinch_gesture_active_ = false; + ScrollBegin(); +} + void TopControlsManager::SetControlsTopOffset(float controls_top_offset) { controls_top_offset = std::max(controls_top_offset, -top_controls_height_); controls_top_offset = std::min(controls_top_offset, 0.f); @@ -174,7 +195,7 @@ void TopControlsManager::SetupAnimation(AnimationDirection direction) { top_controls_animation_ = KeyframedFloatAnimationCurve::Create(); double start_time = - (base::TimeTicks::Now() - base::TimeTicks()).InMillisecondsF(); + (gfx::FrameTime::Now() - base::TimeTicks()).InMillisecondsF(); top_controls_animation_->AddKeyframe( FloatKeyframe::Create(start_time, controls_top_offset_, scoped_ptr<TimingFunction>())); diff --git a/cc/input/top_controls_manager.h b/cc/input/top_controls_manager.h index 9bc3040d31..246efba5b9 100644 --- a/cc/input/top_controls_manager.h +++ b/cc/input/top_controls_manager.h @@ -56,6 +56,11 @@ class CC_EXPORT TopControlsManager gfx::Vector2dF ScrollBy(const gfx::Vector2dF pending_delta); void ScrollEnd(); + // The caller should ensure that |Pinch{Begin,End}| are called within + // the scope of |Scroll{Begin,End}|. + void PinchBegin(); + void PinchEnd(); + gfx::Vector2dF Animate(base::TimeTicks monotonic_time); protected: @@ -91,6 +96,8 @@ class CC_EXPORT TopControlsManager // the user stops the scroll. float top_controls_hide_height_; + bool pinch_gesture_active_; + DISALLOW_COPY_AND_ASSIGN(TopControlsManager); }; diff --git a/cc/input/top_controls_manager_unittest.cc b/cc/input/top_controls_manager_unittest.cc index da7475f576..74687adfac 100644 --- a/cc/input/top_controls_manager_unittest.cc +++ b/cc/input/top_controls_manager_unittest.cc @@ -12,6 +12,7 @@ #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/vector2d_f.h" namespace cc { @@ -131,7 +132,7 @@ TEST(TopControlsManagerTest, PartialShownHideAnimation) { EXPECT_TRUE(manager->animation()); - base::TimeTicks time = base::TimeTicks::Now(); + base::TimeTicks time = gfx::FrameTime::Now(); float previous_offset = manager->controls_top_offset(); while (manager->animation()) { time = base::TimeDelta::FromMicroseconds(100) + time; @@ -161,7 +162,7 @@ TEST(TopControlsManagerTest, PartialShownShowAnimation) { EXPECT_TRUE(manager->animation()); - base::TimeTicks time = base::TimeTicks::Now(); + base::TimeTicks time = gfx::FrameTime::Now(); float previous_offset = manager->controls_top_offset(); while (manager->animation()) { time = base::TimeDelta::FromMicroseconds(100) + time; @@ -187,7 +188,7 @@ TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdShows) { manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); - base::TimeTicks time = base::TimeTicks::Now(); + base::TimeTicks time = gfx::FrameTime::Now(); float previous_offset = manager->controls_top_offset(); while (manager->animation()) { time = base::TimeDelta::FromMicroseconds(100) + time; @@ -213,7 +214,7 @@ TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdHides) { manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); - base::TimeTicks time = base::TimeTicks::Now(); + base::TimeTicks time = gfx::FrameTime::Now(); float previous_offset = manager->controls_top_offset(); while (manager->animation()) { time = base::TimeDelta::FromMicroseconds(100) + time; @@ -243,7 +244,7 @@ TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdHides) { manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); - base::TimeTicks time = base::TimeTicks::Now(); + base::TimeTicks time = gfx::FrameTime::Now(); float previous_offset = manager->controls_top_offset(); while (manager->animation()) { time = base::TimeDelta::FromMicroseconds(100) + time; @@ -273,7 +274,7 @@ TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdShows) { manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); - base::TimeTicks time = base::TimeTicks::Now(); + base::TimeTicks time = gfx::FrameTime::Now(); float previous_offset = manager->controls_top_offset(); while (manager->animation()) { time = base::TimeDelta::FromMicroseconds(100) + time; @@ -286,5 +287,88 @@ TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdShows) { EXPECT_EQ(100.f, manager->content_top_offset()); } +TEST(TopControlsManagerTest, PinchIgnoresScroll) { + MockTopControlsManagerClient client(0.5f, 0.5f); + TopControlsManager* manager = client.manager(); + + // Hide the controls. + manager->ScrollBegin(); + EXPECT_EQ(0.f, manager->controls_top_offset()); + + manager->ScrollBy(gfx::Vector2dF(0.f, 300.f)); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + + manager->PinchBegin(); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + + // Scrolls are ignored during pinch. + manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + manager->PinchEnd(); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + + // Scrolls should no long be ignored. + manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)); + EXPECT_EQ(-85.f, manager->controls_top_offset()); + EXPECT_EQ(15.f, manager->content_top_offset()); + manager->ScrollEnd(); + + EXPECT_TRUE(manager->animation()); +} + +TEST(TopControlsManagerTest, PinchBeginStartsAnimationIfNecessary) { + MockTopControlsManagerClient client(0.5f, 0.5f); + TopControlsManager* manager = client.manager(); + + manager->ScrollBegin(); + manager->ScrollBy(gfx::Vector2dF(0.f, 300.f)); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + + manager->PinchBegin(); + EXPECT_FALSE(manager->animation()); + + manager->PinchEnd(); + EXPECT_FALSE(manager->animation()); + + manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)); + EXPECT_EQ(-85.f, manager->controls_top_offset()); + EXPECT_EQ(15.f, manager->content_top_offset()); + + manager->PinchBegin(); + EXPECT_TRUE(manager->animation()); + + base::TimeTicks time = base::TimeTicks::Now(); + float previous_offset = manager->controls_top_offset(); + while (manager->animation()) { + time = base::TimeDelta::FromMicroseconds(100) + time; + manager->Animate(time); + EXPECT_LT(manager->controls_top_offset(), previous_offset); + previous_offset = manager->controls_top_offset(); + } + EXPECT_FALSE(manager->animation()); + + manager->PinchEnd(); + EXPECT_FALSE(manager->animation()); + + manager->ScrollBy(gfx::Vector2dF(0.f, -55.f)); + EXPECT_EQ(-45.f, manager->controls_top_offset()); + EXPECT_EQ(55.f, manager->content_top_offset()); + EXPECT_FALSE(manager->animation()); + + manager->ScrollEnd(); + EXPECT_TRUE(manager->animation()); + + time = base::TimeTicks::Now(); + previous_offset = manager->controls_top_offset(); + while (manager->animation()) { + time = base::TimeDelta::FromMicroseconds(100) + time; + manager->Animate(time); + EXPECT_GT(manager->controls_top_offset(), previous_offset); + previous_offset = manager->controls_top_offset(); + } + EXPECT_FALSE(manager->animation()); + EXPECT_EQ(0.f, manager->controls_top_offset()); +} + } // namespace } // namespace cc diff --git a/cc/layers/delegated_frame_resource_collection.cc b/cc/layers/delegated_frame_resource_collection.cc index cd2633dc2a..5ca4eda57d 100644 --- a/cc/layers/delegated_frame_resource_collection.cc +++ b/cc/layers/delegated_frame_resource_collection.cc @@ -12,7 +12,8 @@ namespace cc { DelegatedFrameResourceCollection::DelegatedFrameResourceCollection() : client_(NULL), main_thread_runner_(BlockingTaskRunner::current()), - lost_all_resources_(false) { + lost_all_resources_(false), + weak_ptr_factory_(this) { DCHECK(main_thread_checker_.CalledOnValidThread()); } @@ -112,21 +113,21 @@ void DelegatedFrameResourceCollection::RefResources( resource_id_ref_count_map_[resources[i].id].refs_to_wait_for++; } -ReturnCallback -DelegatedFrameResourceCollection::GetReturnResourcesCallbackForImplThread() { - return base::Bind( - &DelegatedFrameResourceCollection::UnrefResourcesOnImplThread, - this, - main_thread_runner_); -} - -void DelegatedFrameResourceCollection::UnrefResourcesOnImplThread( +static void UnrefResourcesOnImplThread( + base::WeakPtr<DelegatedFrameResourceCollection> self, scoped_refptr<BlockingTaskRunner> main_thread_runner, const ReturnedResourceArray& returned) { main_thread_runner->PostTask( FROM_HERE, base::Bind( - &DelegatedFrameResourceCollection::UnrefResources, this, returned)); + &DelegatedFrameResourceCollection::UnrefResources, self, returned)); +} + +ReturnCallback +DelegatedFrameResourceCollection::GetReturnResourcesCallbackForImplThread() { + return base::Bind(&UnrefResourcesOnImplThread, + weak_ptr_factory_.GetWeakPtr(), + main_thread_runner_); } } // namespace cc diff --git a/cc/layers/delegated_frame_resource_collection.h b/cc/layers/delegated_frame_resource_collection.h index 68ee11a1c1..9a5d336749 100644 --- a/cc/layers/delegated_frame_resource_collection.h +++ b/cc/layers/delegated_frame_resource_collection.h @@ -7,6 +7,7 @@ #include "base/containers/hash_tables.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "cc/base/cc_export.h" #include "cc/resources/return_callback.h" @@ -46,10 +47,6 @@ class CC_EXPORT DelegatedFrameResourceCollection friend class base::RefCounted<DelegatedFrameResourceCollection>; ~DelegatedFrameResourceCollection(); - void UnrefResourcesOnImplThread( - scoped_refptr<BlockingTaskRunner> main_thread_runner, - const ReturnedResourceArray& returned); - DelegatedFrameResourceCollectionClient* client_; scoped_refptr<BlockingTaskRunner> main_thread_runner_; @@ -64,6 +61,7 @@ class CC_EXPORT DelegatedFrameResourceCollection ResourceIdRefCountMap resource_id_ref_count_map_; base::ThreadChecker main_thread_checker_; + base::WeakPtrFactory<DelegatedFrameResourceCollection> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DelegatedFrameResourceCollection); }; diff --git a/cc/layers/delegated_frame_resource_collection_unittest.cc b/cc/layers/delegated_frame_resource_collection_unittest.cc new file mode 100644 index 0000000000..ace3def592 --- /dev/null +++ b/cc/layers/delegated_frame_resource_collection_unittest.cc @@ -0,0 +1,159 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/run_loop.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread.h" +#include "cc/layers/delegated_frame_resource_collection.h" +#include "cc/resources/returned_resource.h" +#include "cc/resources/transferable_resource.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +class DelegatedFrameResourceCollectionTest + : public testing::Test, + public DelegatedFrameResourceCollectionClient { + protected: + DelegatedFrameResourceCollectionTest() : resources_available_(false) {} + + virtual void SetUp() OVERRIDE { CreateResourceCollection(); } + + virtual void TearDown() OVERRIDE { DestroyResourceCollection(); } + + void CreateResourceCollection() { + DCHECK(!resource_collection_); + resource_collection_ = new DelegatedFrameResourceCollection; + resource_collection_->SetClient(this); + } + + void DestroyResourceCollection() { + if (resource_collection_) { + resource_collection_->SetClient(NULL); + resource_collection_ = NULL; + } + } + + TransferableResourceArray CreateResourceArray() { + TransferableResourceArray resources; + TransferableResource resource; + resource.id = 444; + resources.push_back(resource); + return resources; + } + + virtual void UnusedResourcesAreAvailable() OVERRIDE { + resources_available_ = true; + resource_collection_->TakeUnusedResourcesForChildCompositor( + &returned_resources_); + if (!resources_available_closure_.is_null()) + resources_available_closure_.Run(); + } + + bool ReturnAndResetResourcesAvailable() { + bool r = resources_available_; + resources_available_ = false; + return r; + } + + scoped_refptr<DelegatedFrameResourceCollection> resource_collection_; + bool resources_available_; + ReturnedResourceArray returned_resources_; + base::Closure resources_available_closure_; +}; + +// This checks that taking the return callback doesn't take extra refcounts, +// since it's sent to other threads. +TEST_F(DelegatedFrameResourceCollectionTest, NoRef) { + // Start with one ref. + EXPECT_TRUE(resource_collection_->HasOneRef()); + + ReturnCallback return_callback = + resource_collection_->GetReturnResourcesCallbackForImplThread(); + + // Callback shouldn't take a ref since it's sent to other threads. + EXPECT_TRUE(resource_collection_->HasOneRef()); +} + +void ReturnResourcesOnThread(ReturnCallback callback, + const ReturnedResourceArray& resources, + base::WaitableEvent* event) { + callback.Run(resources); + event->Wait(); +} + +// Tests that the ReturnCallback can run safely on threads even after the +// last references to the collection were dropped. +// Flaky: crbug.com/313441 +TEST_F(DelegatedFrameResourceCollectionTest, DISABLED_Thread) { + base::Thread thread("test thread"); + thread.Start(); + + TransferableResourceArray resources = CreateResourceArray(); + resource_collection_->ReceivedResources(resources); + resource_collection_->RefResources(resources); + + ReturnedResourceArray returned_resources; + TransferableResource::ReturnResources(resources, &returned_resources); + + base::WaitableEvent event(false, false); + + { + base::RunLoop run_loop; + resources_available_closure_ = run_loop.QuitClosure(); + + thread.message_loop()->PostTask( + FROM_HERE, + base::Bind( + &ReturnResourcesOnThread, + resource_collection_->GetReturnResourcesCallbackForImplThread(), + returned_resources, + &event)); + + run_loop.Run(); + } + EXPECT_TRUE(ReturnAndResetResourcesAvailable()); + EXPECT_EQ(1u, returned_resources_.size()); + EXPECT_EQ(444u, returned_resources_[0].id); + EXPECT_EQ(1, returned_resources_[0].count); + returned_resources_.clear(); + + // The event prevents the return resources callback from being deleted. + // Destroy the last reference from this thread to the collection before + // signaling the event, to ensure any reference taken by the callback, if any, + // would be the last one. + DestroyResourceCollection(); + event.Signal(); + + CreateResourceCollection(); + resource_collection_->ReceivedResources(resources); + resource_collection_->RefResources(resources); + + // Destroy the collection before we have a chance to run the return callback. + ReturnCallback return_callback = + resource_collection_->GetReturnResourcesCallbackForImplThread(); + resource_collection_->LoseAllResources(); + DestroyResourceCollection(); + + EXPECT_TRUE(ReturnAndResetResourcesAvailable()); + EXPECT_EQ(1u, returned_resources_.size()); + EXPECT_EQ(444u, returned_resources_[0].id); + EXPECT_EQ(1, returned_resources_[0].count); + EXPECT_TRUE(returned_resources_[0].lost); + returned_resources_.clear(); + + thread.message_loop()->PostTask(FROM_HERE, + base::Bind(&ReturnResourcesOnThread, + return_callback, + returned_resources, + &event)); + event.Signal(); + + thread.Stop(); +} + +} // namespace +} // namespace cc diff --git a/cc/layers/delegated_renderer_layer_impl.cc b/cc/layers/delegated_renderer_layer_impl.cc index 35bd0b7f1b..25a27afeb4 100644 --- a/cc/layers/delegated_renderer_layer_impl.cc +++ b/cc/layers/delegated_renderer_layer_impl.cc @@ -237,6 +237,13 @@ void DelegatedRendererLayerImpl::AppendContributingRenderPasses( RenderPassSink* render_pass_sink) { DCHECK(HasContributingDelegatedRenderPasses()); + const RenderPass* root_delegated_render_pass = + render_passes_in_draw_order_.back(); + gfx::Size frame_size = root_delegated_render_pass->output_rect.size(); + gfx::Transform delegated_frame_to_root_transform = + screen_space_transform() * + DelegatedFrameToLayerSpaceTransform(frame_size); + for (size_t i = 0; i < render_passes_in_draw_order_.size() - 1; ++i) { RenderPass::Id output_render_pass_id(-1, -1); bool present = @@ -248,8 +255,11 @@ void DelegatedRendererLayerImpl::AppendContributingRenderPasses( << render_passes_in_draw_order_[i]->id.index; DCHECK_GT(output_render_pass_id.index, 0); - render_pass_sink->AppendRenderPass( - render_passes_in_draw_order_[i]->Copy(output_render_pass_id)); + scoped_ptr<RenderPass> copy_pass = + render_passes_in_draw_order_[i]->Copy(output_render_pass_id); + copy_pass->transform_to_root_target.ConcatTransform( + delegated_frame_to_root_transform); + render_pass_sink->AppendRenderPass(copy_pass.Pass()); } } diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc index 58fa36692e..05e8513d29 100644 --- a/cc/layers/delegated_renderer_layer_impl_unittest.cc +++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc @@ -25,6 +25,7 @@ #include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/transform.h" namespace cc { @@ -88,24 +89,21 @@ class DelegatedRendererLayerImplTestSimple delegated_renderer_layer->SetTransform(transform); ScopedPtrVector<RenderPass> delegated_render_passes; - TestRenderPass* pass1 = AddRenderPass( - &delegated_render_passes, - RenderPass::Id(9, 6), - gfx::Rect(6, 6, 6, 6), - gfx::Transform()); + TestRenderPass* pass1 = AddRenderPass(&delegated_render_passes, + RenderPass::Id(9, 6), + gfx::Rect(6, 6, 6, 6), + gfx::Transform(1, 0, 0, 1, 5, 6)); AddQuad(pass1, gfx::Rect(0, 0, 6, 6), 33u); - TestRenderPass* pass2 = AddRenderPass( - &delegated_render_passes, - RenderPass::Id(9, 7), - gfx::Rect(7, 7, 7, 7), - gfx::Transform()); + TestRenderPass* pass2 = AddRenderPass(&delegated_render_passes, + RenderPass::Id(9, 7), + gfx::Rect(7, 7, 7, 7), + gfx::Transform(1, 0, 0, 1, 7, 8)); AddQuad(pass2, gfx::Rect(0, 0, 7, 7), 22u); AddRenderPassQuad(pass2, pass1); - TestRenderPass* pass3 = AddRenderPass( - &delegated_render_passes, - RenderPass::Id(9, 8), - gfx::Rect(0, 0, 8, 8), - gfx::Transform()); + TestRenderPass* pass3 = AddRenderPass(&delegated_render_passes, + RenderPass::Id(9, 8), + gfx::Rect(0, 0, 8, 8), + gfx::Transform(1, 0, 0, 1, 9, 10)); AddRenderPassQuad(pass3, pass2); delegated_renderer_layer->SetFrameDataForRenderPasses( &delegated_render_passes); @@ -165,7 +163,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, AddsContributingRenderPasses) { EXPECT_EQ(gfx::Rect(7, 7, 7, 7).ToString(), frame.render_passes[2]->output_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -201,7 +199,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, EXPECT_EQ(gfx::Rect(0, 0, 6, 6).ToString(), frame.render_passes[1]->quad_list[0]->rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -228,7 +226,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, AddsQuadsToTargetRenderPass) { EXPECT_EQ(gfx::Rect(0, 0, 15, 15).ToString(), frame.render_passes[3]->quad_list[1]->rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -262,6 +260,42 @@ TEST_F(DelegatedRendererLayerImplTestSimple, EXPECT_TRANSFORMATION_MATRIX_EQ( gfx::Transform(), frame.render_passes[1]->quad_list[0]->quadTransform()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); + host_impl_->DidDrawAllLayers(frame); +} + +TEST_F(DelegatedRendererLayerImplTestSimple, RenderPassTransformIsModified) { + LayerTreeHostImpl::FrameData frame; + EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); + + // The delegated layer has a surface between it and the root. + EXPECT_TRUE(delegated_renderer_layer_->render_target()->parent()); + + // Each non-DelegatedRendererLayer added one RenderPass. The + // DelegatedRendererLayer added two contributing passes. + ASSERT_EQ(5u, frame.render_passes.size()); + + // The DelegatedRendererLayer is at position 9,9 compared to the root, so all + // render pass' transforms to the root should be shifted by this amount. + // The DelegatedRendererLayer has a size of 10x10, but the root delegated + // RenderPass has a size of 8x8, so any render passes should be scaled by + // 10/8. + gfx::Transform transform; + transform.Translate(9.0, 9.0); + transform.Scale(10.0 / 8.0, 10.0 / 8.0); + + // The first contributing surface has a translation of 5, 6. + gfx::Transform five_six(1, 0, 0, 1, 5, 6); + + // The second contributing surface has a translation of 7, 8. + gfx::Transform seven_eight(1, 0, 0, 1, 7, 8); + + EXPECT_TRANSFORMATION_MATRIX_EQ( + transform * five_six, frame.render_passes[1]->transform_to_root_target); + EXPECT_TRANSFORMATION_MATRIX_EQ( + transform * seven_eight, + frame.render_passes[2]->transform_to_root_target); + host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -274,7 +308,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, DoesNotOwnARenderSurface) { // has no need to be a RenderSurface for the quads it carries. EXPECT_FALSE(delegated_renderer_layer_->render_surface()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -289,7 +323,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, DoesOwnARenderSurfaceForOpacity) { // render surface. EXPECT_TRUE(delegated_renderer_layer_->render_surface()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -307,7 +341,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, // render surface. EXPECT_TRUE(delegated_renderer_layer_->render_surface()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -354,7 +388,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, AddsRenderPasses) { EXPECT_EQ(gfx::Rect(7, 7, 7, 7).ToString(), frame.render_passes[2]->output_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -391,7 +425,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, EXPECT_EQ(gfx::Rect(0, 0, 6, 6).ToString(), frame.render_passes[1]->quad_list[0]->rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -416,7 +450,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, AddsQuadsToTargetRenderPass) { EXPECT_EQ(gfx::Rect(7, 7, 7, 7).ToString(), frame.render_passes[3]->quad_list[0]->rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -448,7 +482,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, EXPECT_TRANSFORMATION_MATRIX_EQ( gfx::Transform(), frame.render_passes[1]->quad_list[0]->quadTransform()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -682,7 +716,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_NoSurface) { expected, contrib_delegated_shared_quad_state->content_to_target_transform); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -745,7 +779,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_NoSurface) { expected, contrib_delegated_shared_quad_state->content_to_target_transform); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -801,7 +835,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_Surface) { expected, contrib_delegated_shared_quad_state->content_to_target_transform); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -856,7 +890,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_Surface) { expected, contrib_delegated_shared_quad_state->content_to_target_transform); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1032,7 +1066,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, // Quads are clipped to the delegated renderer layer. EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1061,7 +1095,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, // Quads came with a clip rect. EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1091,7 +1125,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, // Quads are clipped to the delegated renderer layer. EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1120,7 +1154,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, // Quads came with a clip rect. EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1149,7 +1183,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, // clip rect is ignored, and they are not set as clipped. EXPECT_FALSE(root_delegated_shared_quad_state->is_clipped); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1179,7 +1213,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, // Quads came with a clip rect. EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1208,7 +1242,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, // clip rect is ignored, and they are not set as clipped. EXPECT_FALSE(root_delegated_shared_quad_state->is_clipped); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1239,7 +1273,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, QuadsClipped_LayerClipped_Surface) { // Quads came with a clip rect. EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1292,7 +1326,7 @@ TEST_F(DelegatedRendererLayerImplTest, InvalidRenderPassDrawQuad) { EXPECT_EQ(DrawQuad::SOLID_COLOR, frame.render_passes[0]->quad_list[0]->material); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 80fad6a551..b10112afd1 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc @@ -619,7 +619,7 @@ void Layer::SetScrollOffset(gfx::Vector2d scroll_offset) { void Layer::SetScrollOffsetFromImplSide(gfx::Vector2d scroll_offset) { DCHECK(IsPropertyChangeAllowed()); - // This function only gets called during a begin frame, so there + // This function only gets called during a BeginMainFrame, so there // is no need to call SetNeedsUpdate here. DCHECK(layer_tree_host_ && layer_tree_host_->CommitRequested()); if (scroll_offset_ == scroll_offset) @@ -881,8 +881,8 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { } // Adjust the scroll delta to be just the scrolls that have happened since - // the begin frame was sent. This happens for impl-side painting - // in LayerImpl::ApplyScrollDeltasSinceBeginFrame in a separate tree walk. + // the BeginMainFrame was sent. This happens for impl-side painting + // in LayerImpl::ApplyScrollDeltasSinceBeginMainFrame in a separate tree walk. if (layer->layer_tree_impl()->settings().impl_side_painting) { layer->SetScrollOffset(scroll_offset_); } else { @@ -1028,11 +1028,6 @@ void Layer::SuspendAnimations(double monotonic_time) { SetNeedsCommit(); } -void Layer::ResumeAnimations(double monotonic_time) { - layer_animation_controller_->ResumeAnimations(monotonic_time); - SetNeedsCommit(); -} - void Layer::SetLayerAnimationControllerForTest( scoped_refptr<LayerAnimationController> controller) { layer_animation_controller_->RemoveValueObserver(this); diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 1328b071b9..274e82fc7c 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h @@ -376,7 +376,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, void RemoveAnimation(int animation_id); void SuspendAnimations(double monotonic_time); - void ResumeAnimations(double monotonic_time); bool AnimatedBoundsForBox(const gfx::BoxF& box, gfx::BoxF* bounds) { return layer_animation_controller_->AnimatedBoundsForBox(box, bounds); diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 14f3e2afe1..894daf1a27 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -385,7 +385,7 @@ void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() { sent_scroll_delta_ = gfx::Vector2d(); } -void LayerImpl::ApplyScrollDeltasSinceBeginFrame() { +void LayerImpl::ApplyScrollDeltasSinceBeginMainFrame() { // Only the pending tree can have missing scrolls. DCHECK(layer_tree_impl()->IsPendingTree()); if (!scrollable()) @@ -614,6 +614,13 @@ base::DictionaryValue* LayerImpl::LayerTreeAsJson() const { if (scrollable_) result->SetBoolean("Scrollable", scrollable_); + if (have_wheel_event_handlers_) + result->SetBoolean("WheelHandler", have_wheel_event_handlers_); + if (!touch_event_handler_region_.IsEmpty()) { + scoped_ptr<base::Value> region = touch_event_handler_region_.AsValue(); + result->Set("TouchRegion", region.release()); + } + list = new base::ListValue; for (size_t i = 0; i < children_.size(); ++i) list->Append(children_[i]->LayerTreeAsJson()); diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index 4bd91da0a2..9d3951b78a 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -382,7 +382,7 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver { } void ApplySentScrollDeltasFromAbortedCommit(); - void ApplyScrollDeltasSinceBeginFrame(); + void ApplyScrollDeltasSinceBeginMainFrame(); void SetShouldScrollOnMainThread(bool should_scroll_on_main_thread) { should_scroll_on_main_thread_ = should_scroll_on_main_thread; diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc index 3a7a1c1b2d..c66eb8551e 100644 --- a/cc/layers/layer_unittest.cc +++ b/cc/layers/layer_unittest.cc @@ -39,7 +39,7 @@ namespace { class MockLayerTreeHost : public LayerTreeHost { public: explicit MockLayerTreeHost(LayerTreeHostClient* client) - : LayerTreeHost(client, LayerTreeSettings()) { + : LayerTreeHost(client, NULL, LayerTreeSettings()) { Initialize(NULL); } @@ -803,11 +803,12 @@ class LayerTreeHostFactory { : client_(FakeLayerTreeHostClient::DIRECT_3D) {} scoped_ptr<LayerTreeHost> Create() { - return LayerTreeHost::Create(&client_, LayerTreeSettings(), NULL).Pass(); + return LayerTreeHost::Create(&client_, NULL, LayerTreeSettings(), NULL) + .Pass(); } scoped_ptr<LayerTreeHost> Create(LayerTreeSettings settings) { - return LayerTreeHost::Create(&client_, settings, NULL).Pass(); + return LayerTreeHost::Create(&client_, NULL, settings, NULL).Pass(); } private: diff --git a/cc/layers/nine_patch_layer_unittest.cc b/cc/layers/nine_patch_layer_unittest.cc index f616560c85..7213a51e09 100644 --- a/cc/layers/nine_patch_layer_unittest.cc +++ b/cc/layers/nine_patch_layer_unittest.cc @@ -32,7 +32,7 @@ namespace { class MockLayerTreeHost : public LayerTreeHost { public: explicit MockLayerTreeHost(LayerTreeHostClient* client) - : LayerTreeHost(client, LayerTreeSettings()) { + : LayerTreeHost(client, NULL, LayerTreeSettings()) { Initialize(NULL); } }; diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc index ef17a0924b..bc311a36c0 100644 --- a/cc/layers/picture_layer.cc +++ b/cc/layers/picture_layer.cc @@ -20,7 +20,8 @@ PictureLayer::PictureLayer(ContentLayerClient* client) : client_(client), pile_(make_scoped_refptr(new PicturePile())), instrumentation_object_tracker_(id()), - is_mask_(false) { + is_mask_(false), + update_source_frame_number_(-1) { } PictureLayer::~PictureLayer() { @@ -38,6 +39,18 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { Layer::PushPropertiesTo(base_layer); PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); + if (layer_impl->bounds().IsEmpty()) { + // Update may not get called for an empty layer, so resize here instead. + // Using layer_impl because either bounds() or paint_properties().bounds + // may disagree and either one could have been pushed to layer_impl. + pile_->Resize(gfx::Size()); + pile_->UpdateRecordedRegion(); + } else if (update_source_frame_number_ == + layer_tree_host()->source_frame_number()) { + // If update called, then pile size must match bounds pushed to impl layer. + DCHECK_EQ(layer_impl->bounds().ToString(), pile_->size().ToString()); + } + layer_impl->SetIsMask(is_mask_); // Unlike other properties, invalidation must always be set on layer_impl. // See PictureLayerImpl::PushPropertiesTo for more details. @@ -78,6 +91,7 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue, "source_frame_number", layer_tree_host()->source_frame_number()); + update_source_frame_number_ = layer_tree_host()->source_frame_number(); bool updated = Layer::Update(queue, occlusion); pile_->Resize(paint_properties().bounds); diff --git a/cc/layers/picture_layer.h b/cc/layers/picture_layer.h index f67ca91eb4..e1e4a9cc68 100644 --- a/cc/layers/picture_layer.h +++ b/cc/layers/picture_layer.h @@ -56,6 +56,8 @@ class CC_EXPORT PictureLayer : public Layer { Region pile_invalidation_; bool is_mask_; + int update_source_frame_number_; + DISALLOW_COPY_AND_ASSIGN(PictureLayer); }; diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index 36b2ba9eec..d2ef7d08ae 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc @@ -553,6 +553,7 @@ void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) { if (!DrawsContent()) { ResetRasterScale(); + tilings_->RemoveAllTilings(); return; } @@ -611,7 +612,8 @@ void PictureLayerImpl::SyncTiling( // get updated prior to drawing or activation. If this tree does not // need update draw properties, then its transforms are up to date and // we can create tiles for this tiling immediately. - if (!layer_tree_impl()->needs_update_draw_properties()) + if (!layer_tree_impl()->needs_update_draw_properties() && + should_update_tile_priorities_) UpdateTilePriorities(); } diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index f9dfb9907b..7493e382e3 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc @@ -1106,6 +1106,41 @@ TEST_F(PictureLayerImplTest, ActivateUninitializedLayer) { EXPECT_FALSE(active_layer_->needs_post_commit_initialization()); } +TEST_F(PictureLayerImplTest, SyncTilingAfterReleaseResource) { + SetupDefaultTrees(gfx::Size(10, 10)); + host_impl_.active_tree()->UpdateDrawProperties(); + EXPECT_FALSE(host_impl_.active_tree()->needs_update_draw_properties()); + + // Contrived unit test of a real crash. A layer is transparent during a + // context loss, and later becomes opaque, causing active layer SyncTiling to + // be called. + const float tile_scale = 2.f; + active_layer_->DidLoseOutputSurface(); + EXPECT_FALSE(active_layer_->tilings()->TilingAtScale(tile_scale)); + pending_layer_->AddTiling(2.f); + EXPECT_TRUE(active_layer_->tilings()->TilingAtScale(tile_scale)); +} + +TEST_F(PictureLayerImplTest, NoTilingIfDoesNotDrawContent) { + // Set up layers with tilings. + SetupDefaultTrees(gfx::Size(10, 10)); + SetContentsScaleOnBothLayers(1.f, 1.f, 1.f, false); + pending_layer_->PushPropertiesTo(active_layer_); + EXPECT_TRUE(pending_layer_->DrawsContent()); + EXPECT_TRUE(pending_layer_->CanHaveTilings()); + EXPECT_GE(pending_layer_->num_tilings(), 0u); + EXPECT_GE(active_layer_->num_tilings(), 0u); + + // Set content to false, which should make CanHaveTilings return false. + pending_layer_->SetDrawsContent(false); + EXPECT_FALSE(pending_layer_->DrawsContent()); + EXPECT_FALSE(pending_layer_->CanHaveTilings()); + + // No tilings should be pushed to active layer. + pending_layer_->PushPropertiesTo(active_layer_); + EXPECT_EQ(0u, active_layer_->num_tilings()); +} + class DeferredInitPictureLayerImplTest : public PictureLayerImplTest { public: DeferredInitPictureLayerImplTest() diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc new file mode 100644 index 0000000000..c3dd244c2e --- /dev/null +++ b/cc/layers/picture_layer_unittest.cc @@ -0,0 +1,69 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/layers/picture_layer.h" + +#include "cc/layers/content_layer_client.h" +#include "cc/layers/picture_layer_impl.h" +#include "cc/resources/resource_update_queue.h" +#include "cc/test/fake_layer_tree_host.h" +#include "cc/test/fake_picture_layer_impl.h" +#include "cc/test/fake_proxy.h" +#include "cc/test/impl_side_painting_settings.h" +#include "cc/trees/occlusion_tracker.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +class MockContentLayerClient : public ContentLayerClient { + public: + virtual void PaintContents(SkCanvas* canvas, + gfx::Rect clip, + gfx::RectF* opaque) OVERRIDE {} + virtual void DidChangeLayerCanUseLCDText() OVERRIDE {} +}; + +TEST(PictureLayerTest, NoTilesIfEmptyBounds) { + MockContentLayerClient client; + scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client); + layer->SetBounds(gfx::Size(10, 10)); + + scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(); + host->SetRootLayer(layer); + layer->SetIsDrawable(true); + layer->SavePaintProperties(); + + OcclusionTracker occlusion(gfx::Rect(0, 0, 1000, 1000), false); + scoped_ptr<ResourceUpdateQueue> queue(new ResourceUpdateQueue); + layer->Update(queue.get(), &occlusion); + + layer->SetBounds(gfx::Size(0, 0)); + layer->SavePaintProperties(); + // Intentionally skipping Update since it would normally be skipped on + // a layer with empty bounds. + + FakeProxy proxy; +#ifndef NDEBUG + proxy.SetCurrentThreadIsImplThread(true); +#endif + { + FakeLayerTreeHostImpl host_impl(ImplSidePaintingSettings(), &proxy); + host_impl.CreatePendingTree(); + scoped_ptr<FakePictureLayerImpl> layer_impl = + FakePictureLayerImpl::Create(host_impl.pending_tree(), 1); + + layer->PushPropertiesTo(layer_impl.get()); + EXPECT_FALSE(layer_impl->CanHaveTilings()); + EXPECT_TRUE(layer_impl->bounds() == gfx::Size(0, 0)); + EXPECT_TRUE(layer_impl->pile()->size() == gfx::Size(0, 0)); + EXPECT_TRUE(layer_impl->pile()->recorded_region().IsEmpty()); + } +#ifndef NDEBUG + proxy.SetCurrentThreadIsImplThread(false); +#endif +} + +} // namespace +} // namespace cc diff --git a/cc/layers/scrollbar_layer_impl_base.cc b/cc/layers/scrollbar_layer_impl_base.cc index c1e7126ff5..362465be3b 100644 --- a/cc/layers/scrollbar_layer_impl_base.cc +++ b/cc/layers/scrollbar_layer_impl_base.cc @@ -72,6 +72,13 @@ void ScrollbarLayerImplBase::SetVisibleToTotalLengthRatio(float ratio) { NoteLayerPropertyChanged(); } +void ScrollbarLayerImplBase::SetThumbThicknessScaleFactor(float factor) { + if (thumb_thickness_scale_factor_ == factor) + return; + thumb_thickness_scale_factor_ = factor; + NoteLayerPropertyChanged(); +} + gfx::Rect ScrollbarLayerImplBase::ComputeThumbQuadRect() const { // Thumb extent is the length of the thumb in the scrolling direction, thumb // thickness is in the perpendicular direction. Here's an example of a diff --git a/cc/layers/scrollbar_layer_impl_base.h b/cc/layers/scrollbar_layer_impl_base.h index 55ade6ab04..360ef97089 100644 --- a/cc/layers/scrollbar_layer_impl_base.h +++ b/cc/layers/scrollbar_layer_impl_base.h @@ -44,9 +44,7 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl { float thumb_thickness_scale_factor() { return thumb_thickness_scale_factor_; } - void set_thumb_thickness_scale_factor(float thumb_thickness_scale_factor) { - thumb_thickness_scale_factor_ = thumb_thickness_scale_factor; - } + void SetThumbThicknessScaleFactor(float thumb_thickness_scale_factor); protected: ScrollbarLayerImplBase(LayerTreeImpl* tree_impl, diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index 250d610b0a..0423cdc067 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc @@ -514,7 +514,7 @@ class MockLayerTreeHost : public LayerTreeHost { public: MockLayerTreeHost(LayerTreeHostClient* client, const LayerTreeSettings& settings) - : LayerTreeHost(client, settings), + : LayerTreeHost(client, NULL, settings), next_id_(1), total_ui_resource_created_(0), total_ui_resource_deleted_(0) { diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc index 18410fb5de..45a456e523 100644 --- a/cc/layers/texture_layer.cc +++ b/cc/layers/texture_layer.cc @@ -132,9 +132,10 @@ void TextureLayer::SetTextureId(unsigned id) { SetNextCommitWaitsForActivation(); } -void TextureLayer::SetTextureMailbox( +void TextureLayer::SetTextureMailboxInternal( const TextureMailbox& mailbox, - scoped_ptr<SingleReleaseCallback> release_callback) { + scoped_ptr<SingleReleaseCallback> release_callback, + bool requires_commit) { DCHECK(uses_mailbox_); DCHECK(!mailbox.IsValid() || !holder_ref_ || !mailbox.Equals(holder_ref_->holder()->mailbox())); @@ -146,12 +147,26 @@ void TextureLayer::SetTextureMailbox( else holder_ref_.reset(); needs_set_mailbox_ = true; - SetNeedsCommit(); + // If we are within a commit, no need to do it again immediately after. + if (requires_commit) + SetNeedsCommit(); + else + SetNeedsPushProperties(); + // The active frame needs to be replaced and the mailbox returned before the // commit is called complete. SetNextCommitWaitsForActivation(); } +void TextureLayer::SetTextureMailbox( + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback) { + SetTextureMailboxInternal( + mailbox, + release_callback.Pass(), + true /* requires_commit */); +} + void TextureLayer::WillModifyTexture() { if (layer_tree_host() && (DrawsContent() || content_committed_)) { layer_tree_host()->AcquireLayerTextures(); @@ -209,7 +224,11 @@ bool TextureLayer::Update(ResourceUpdateQueue* queue, &mailbox, &release_callback, layer_tree_host()->UsingSharedMemoryResources())) { - SetTextureMailbox(mailbox, release_callback.Pass()); + // Already within a commit, no need to do another one immediately. + SetTextureMailboxInternal( + mailbox, + release_callback.Pass(), + false /* requires_commit */); updated = true; } } else { diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h index b0edb22ba1..0a7fd4e32e 100644 --- a/cc/layers/texture_layer.h +++ b/cc/layers/texture_layer.h @@ -148,6 +148,11 @@ class CC_EXPORT TextureLayer : public Layer { virtual ~TextureLayer(); private: + void SetTextureMailboxInternal( + const TextureMailbox& mailbox, + scoped_ptr<SingleReleaseCallback> release_callback, + bool requires_commit); + TextureLayerClient* client_; bool uses_mailbox_; diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index bdb1358ae6..63cf132ae8 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc @@ -44,7 +44,7 @@ namespace { class MockLayerTreeHost : public LayerTreeHost { public: explicit MockLayerTreeHost(LayerTreeHostClient* client) - : LayerTreeHost(client, LayerTreeSettings()) { + : LayerTreeHost(client, NULL, LayerTreeSettings()) { Initialize(NULL); } @@ -1695,6 +1695,109 @@ class TextureLayerChangeInvisibleTest // delegating renderer. SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerChangeInvisibleTest); +// Checks that TextureLayer::Update does not cause an extra commit when setting +// the texture mailbox. +class TextureLayerNoExtraCommitForMailboxTest + : public LayerTreeTest, + public TextureLayerClient { + public: + TextureLayerNoExtraCommitForMailboxTest() + : prepare_mailbox_count_(0) {} + + // TextureLayerClient implementation. + virtual unsigned PrepareTexture() OVERRIDE { + NOTREACHED(); + return 0; + } + + // TextureLayerClient implementation. + virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE { + NOTREACHED(); + return NULL; + } + + virtual bool PrepareTextureMailbox( + cc::TextureMailbox* mailbox, + scoped_ptr<SingleReleaseCallback>* release_callback, + bool use_shared_memory) OVERRIDE { + prepare_mailbox_count_++; + // Alternate between two mailboxes to ensure that the TextureLayer updates + // and commits. + if (prepare_mailbox_count_ % 2 == 0) + *mailbox = MakeMailbox('1'); + else + *mailbox = MakeMailbox('2'); + + // Non-zero mailboxes need a callback. + *release_callback = SingleReleaseCallback::Create( + base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased, + base::Unretained(this))); + // If the test fails, this would cause an infinite number of commits. + return true; + } + + TextureMailbox MakeMailbox(char name) { + return TextureMailbox(std::string(64, name)); + } + + void MailboxReleased(unsigned sync_point, bool lost_resource) { + } + + virtual void SetupTree() OVERRIDE { + scoped_refptr<Layer> root = Layer::Create(); + root->SetBounds(gfx::Size(10, 10)); + root->SetAnchorPoint(gfx::PointF()); + root->SetIsDrawable(true); + + solid_layer_ = SolidColorLayer::Create(); + solid_layer_->SetBounds(gfx::Size(10, 10)); + solid_layer_->SetIsDrawable(true); + solid_layer_->SetBackgroundColor(SK_ColorWHITE); + root->AddChild(solid_layer_); + + parent_layer_ = Layer::Create(); + parent_layer_->SetBounds(gfx::Size(10, 10)); + parent_layer_->SetIsDrawable(true); + root->AddChild(parent_layer_); + + texture_layer_ = TextureLayer::CreateForMailbox(this); + texture_layer_->SetBounds(gfx::Size(10, 10)); + texture_layer_->SetAnchorPoint(gfx::PointF()); + texture_layer_->SetIsDrawable(true); + parent_layer_->AddChild(texture_layer_); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + } + + virtual void BeginTest() OVERRIDE { + PostSetNeedsCommitToMainThread(); + } + + + virtual void DidCommit() OVERRIDE { + switch (layer_tree_host()->source_frame_number()) { + case 1: + EndTest(); + break; + default: + NOTREACHED(); + break; + } + } + + virtual void AfterTest() OVERRIDE {} + + private: + scoped_refptr<SolidColorLayer> solid_layer_; + scoped_refptr<Layer> parent_layer_; + scoped_refptr<TextureLayer> texture_layer_; + + int prepare_mailbox_count_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest); + // Checks that changing a mailbox in the client for a TextureLayer that's // invisible correctly works and uses the new mailbox as soon as the layer // becomes visible (and returns the old one). diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc index 47d694b137..9bdb9078c7 100644 --- a/cc/layers/tiled_layer_unittest.cc +++ b/cc/layers/tiled_layer_unittest.cc @@ -60,6 +60,7 @@ class TiledLayerTest : public testing::Test { virtual void SetUp() { impl_thread_.Start(); layer_tree_host_ = LayerTreeHost::Create(&fake_layer_tree_host_client_, + NULL, settings_, impl_thread_.message_loop_proxy()); proxy_ = layer_tree_host_->proxy(); @@ -73,7 +74,7 @@ class TiledLayerTest : public testing::Test { DebugScopedSetImplThreadAndMainThreadBlocked impl_thread_and_main_thread_blocked(proxy_); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false); host_impl_ = make_scoped_ptr(new FakeLayerTreeHostImpl(proxy_)); } diff --git a/cc/layers/ui_resource_layer_impl.cc b/cc/layers/ui_resource_layer_impl.cc index 23e33f9035..2c9a28681c 100644 --- a/cc/layers/ui_resource_layer_impl.cc +++ b/cc/layers/ui_resource_layer_impl.cc @@ -113,8 +113,9 @@ void UIResourceLayerImpl::AppendQuads(QuadSink* quad_sink, gfx::Rect quad_rect(bounds()); - // TODO(clholgat): Properly calculate opacity: crbug.com/300027 - gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect()); + bool opaque = layer_tree_impl()->IsUIResourceOpaque(ui_resource_id_) || + contents_opaque(); + gfx::Rect opaque_rect(opaque ? quad_rect : gfx::Rect()); scoped_ptr<TextureDrawQuad> quad; quad = TextureDrawQuad::Create(); diff --git a/cc/layers/ui_resource_layer_impl_unittest.cc b/cc/layers/ui_resource_layer_impl_unittest.cc index 383b8a3301..35ff05bacf 100644 --- a/cc/layers/ui_resource_layer_impl_unittest.cc +++ b/cc/layers/ui_resource_layer_impl_unittest.cc @@ -23,6 +23,7 @@ scoped_ptr<UIResourceLayerImpl> GenerateUIResourceLayer( FakeUIResourceLayerTreeHostImpl* host_impl, gfx::Size bitmap_size, gfx::Size layer_size, + bool opaque, UIResourceId uid) { gfx::Rect visible_content_rect(layer_size); scoped_ptr<UIResourceLayerImpl> layer = @@ -38,6 +39,7 @@ scoped_ptr<UIResourceLayerImpl> GenerateUIResourceLayer( SkBitmap::kARGB_8888_Config, bitmap_size.width(), bitmap_size.height()); skbitmap.allocPixels(); skbitmap.setImmutable(); + skbitmap.setIsOpaque(opaque); UIResourceBitmap bitmap(skbitmap); host_impl->CreateUIResource(uid, bitmap); @@ -64,10 +66,12 @@ TEST(UIResourceLayerImplTest, VerifyDrawQuads) { gfx::Size bitmap_size(100, 100); gfx::Size layer_size(100, 100);; size_t expected_quad_size = 1; + bool opaque = true; UIResourceId uid = 1; scoped_ptr<UIResourceLayerImpl> layer = GenerateUIResourceLayer(&host_impl, bitmap_size, layer_size, + opaque, uid); QuadSizeTest(layer.Pass(), expected_quad_size); @@ -77,6 +81,7 @@ TEST(UIResourceLayerImplTest, VerifyDrawQuads) { layer = GenerateUIResourceLayer(&host_impl, bitmap_size, layer_size, + opaque, uid); QuadSizeTest(layer.Pass(), expected_quad_size); } @@ -94,26 +99,48 @@ void OpaqueBoundsTest(scoped_ptr<UIResourceLayerImpl> layer, EXPECT_EQ(expected_opaque_bounds, opaque_rect); } -TEST(UIResourceLayerImplTest, VerifyOpaqueBounds) { +TEST(UIResourceLayerImplTest, VerifySetOpaqueOnSkBitmap) { FakeImplProxy proxy; FakeUIResourceLayerTreeHostImpl host_impl(&proxy); gfx::Size bitmap_size(100, 100); gfx::Size layer_size(100, 100);; + bool opaque = false; UIResourceId uid = 1; scoped_ptr<UIResourceLayerImpl> layer = GenerateUIResourceLayer(&host_impl, bitmap_size, layer_size, + opaque, uid); - layer->SetContentsOpaque(false); gfx::Rect expected_opaque_bounds; OpaqueBoundsTest(layer.Pass(), expected_opaque_bounds); + opaque = true; layer = GenerateUIResourceLayer(&host_impl, bitmap_size, layer_size, + opaque, uid); + expected_opaque_bounds = gfx::Rect(layer->bounds()); + OpaqueBoundsTest(layer.Pass(), expected_opaque_bounds); +} + +TEST(UIResourceLayerImplTest, VerifySetOpaqueOnLayer) { + FakeImplProxy proxy; + FakeUIResourceLayerTreeHostImpl host_impl(&proxy); + + gfx::Size bitmap_size(100, 100); + gfx::Size layer_size(100, 100); + bool skbitmap_opaque = false; + UIResourceId uid = 1; + scoped_ptr<UIResourceLayerImpl> layer = GenerateUIResourceLayer( + &host_impl, bitmap_size, layer_size, skbitmap_opaque, uid); + layer->SetContentsOpaque(false); + gfx::Rect expected_opaque_bounds; + OpaqueBoundsTest(layer.Pass(), expected_opaque_bounds); + layer = GenerateUIResourceLayer( + &host_impl, bitmap_size, layer_size, skbitmap_opaque, uid); layer->SetContentsOpaque(true); expected_opaque_bounds = gfx::Rect(layer->bounds()); OpaqueBoundsTest(layer.Pass(), expected_opaque_bounds); diff --git a/cc/layers/ui_resource_layer_unittest.cc b/cc/layers/ui_resource_layer_unittest.cc index 1720b8176a..a2c75c16d0 100644 --- a/cc/layers/ui_resource_layer_unittest.cc +++ b/cc/layers/ui_resource_layer_unittest.cc @@ -32,7 +32,7 @@ namespace { class MockLayerTreeHost : public LayerTreeHost { public: explicit MockLayerTreeHost(LayerTreeHostClient* client) - : LayerTreeHost(client, LayerTreeSettings()) { + : LayerTreeHost(client, NULL, LayerTreeSettings()) { Initialize(NULL); } }; diff --git a/cc/output/begin_frame_args.cc b/cc/output/begin_frame_args.cc index d7da76c3bc..92901afb1f 100644 --- a/cc/output/begin_frame_args.cc +++ b/cc/output/begin_frame_args.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/output/begin_frame_args.h" +#include "ui/gfx/frame_time.h" namespace cc { @@ -29,20 +30,20 @@ BeginFrameArgs BeginFrameArgs::Create(base::TimeTicks frame_time, BeginFrameArgs BeginFrameArgs::CreateForSynchronousCompositor() { // For WebView/SynchronousCompositor, we always want to draw immediately, // so we set the deadline to 0 and guess that the interval is 16 milliseconds. - return BeginFrameArgs(base::TimeTicks::Now(), + return BeginFrameArgs(gfx::FrameTime::Now(), base::TimeTicks(), DefaultInterval()); } BeginFrameArgs BeginFrameArgs::CreateForTesting() { - base::TimeTicks now = base::TimeTicks::Now(); + base::TimeTicks now = gfx::FrameTime::Now(); return BeginFrameArgs(now, now + (DefaultInterval() / 2), DefaultInterval()); } BeginFrameArgs BeginFrameArgs::CreateExpiredForTesting() { - base::TimeTicks now = base::TimeTicks::Now(); + base::TimeTicks now = gfx::FrameTime::Now(); return BeginFrameArgs(now, now - DefaultInterval(), DefaultInterval()); diff --git a/cc/output/context_provider.cc b/cc/output/context_provider.cc index 7f46f7ccc6..a823fa29f3 100644 --- a/cc/output/context_provider.cc +++ b/cc/output/context_provider.cc @@ -21,6 +21,7 @@ ContextProvider::Capabilities::Capabilities() shallow_flush(false), swapbuffers_complete_callback(false), texture_format_bgra8888(false), + texture_format_etc1(false), texture_rectangle(false), texture_storage(false), texture_usage(false), diff --git a/cc/output/context_provider.h b/cc/output/context_provider.h index 01ba0d816e..6db326d7f9 100644 --- a/cc/output/context_provider.h +++ b/cc/output/context_provider.h @@ -41,6 +41,7 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> { bool shallow_flush; bool swapbuffers_complete_callback; bool texture_format_bgra8888; + bool texture_format_etc1; bool texture_rectangle; bool texture_storage; bool texture_usage; diff --git a/cc/output/delegating_renderer.cc b/cc/output/delegating_renderer.cc index 772a16ac65..678d21ab27 100644 --- a/cc/output/delegating_renderer.cc +++ b/cc/output/delegating_renderer.cc @@ -22,6 +22,8 @@ #include "cc/quads/tile_draw_quad.h" #include "cc/quads/yuv_video_draw_quad.h" #include "cc/resources/resource_provider.h" +#include "gpu/command_buffer/client/context_support.h" +#include "gpu/command_buffer/common/gpu_memory_allocation.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" #include "third_party/khronos/GLES2/gl2ext.h" @@ -60,7 +62,8 @@ bool DelegatingRenderer::Initialize() { capabilities_.using_offscreen_context3d = false; if (!output_surface_->context_provider()) { - // TODO(danakj): Make software compositing work. + capabilities_.using_shared_memory_resources = true; + capabilities_.using_map_image = settings_->use_map_image; return true; } @@ -180,12 +183,13 @@ void DelegatingRenderer::SendManagedMemoryStats(size_t bytes_visible, NOTIMPLEMENTED(); return; } - WebKit::WebGraphicsManagedMemoryStats stats; - stats.bytesVisible = bytes_visible; - stats.bytesVisibleAndNearby = bytes_visible_and_nearby; - stats.bytesAllocated = bytes_allocated; - stats.backbufferRequested = false; - context_provider->Context3d()->sendManagedMemoryStatsCHROMIUM(&stats); + gpu::ManagedMemoryStats stats; + stats.bytes_required = bytes_visible; + stats.bytes_nice_to_have = bytes_visible_and_nearby; + stats.bytes_allocated = bytes_allocated; + stats.backbuffer_requested = false; + + context_provider->ContextSupport()->SendManagedMemoryStats(stats); } void DelegatingRenderer::SetDiscardBackBufferWhenNotVisible(bool discard) { diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc index c02200dfd6..24c3fc2795 100644 --- a/cc/output/direct_renderer.cc +++ b/cc/output/direct_renderer.cc @@ -148,10 +148,11 @@ void DirectRenderer::DecideRenderPassAllocationsForFrame( if (!resource_provider_) return; - base::hash_map<RenderPass::Id, const RenderPass*> render_passes_in_frame; + base::hash_map<RenderPass::Id, gfx::Size> render_passes_in_frame; for (size_t i = 0; i < render_passes_in_draw_order.size(); ++i) - render_passes_in_frame.insert(std::pair<RenderPass::Id, const RenderPass*>( - render_passes_in_draw_order[i]->id, render_passes_in_draw_order[i])); + render_passes_in_frame.insert(std::pair<RenderPass::Id, gfx::Size>( + render_passes_in_draw_order[i]->id, + RenderPassTextureSize(render_passes_in_draw_order[i]))); std::vector<RenderPass::Id> passes_to_delete; base::ScopedPtrHashMap<RenderPass::Id, ScopedResource>::const_iterator @@ -159,24 +160,20 @@ void DirectRenderer::DecideRenderPassAllocationsForFrame( for (pass_iter = render_pass_textures_.begin(); pass_iter != render_pass_textures_.end(); ++pass_iter) { - base::hash_map<RenderPass::Id, const RenderPass*>::const_iterator it = + base::hash_map<RenderPass::Id, gfx::Size>::const_iterator it = render_passes_in_frame.find(pass_iter->first); if (it == render_passes_in_frame.end()) { passes_to_delete.push_back(pass_iter->first); continue; } - const RenderPass* render_pass_in_frame = it->second; - gfx::Size required_size = RenderPassTextureSize(render_pass_in_frame); - ResourceFormat required_format = - RenderPassTextureFormat(render_pass_in_frame); + gfx::Size required_size = it->second; ScopedResource* texture = pass_iter->second; DCHECK(texture); bool size_appropriate = texture->size().width() >= required_size.width() && texture->size().height() >= required_size.height(); - if (texture->id() && - (!size_appropriate || texture->format() != required_format)) + if (texture->id() && !size_appropriate) texture->Free(); } @@ -410,9 +407,8 @@ bool DirectRenderer::UseRenderPass(DrawingFrame* frame, size.Enlarge(enlarge_pass_texture_amount_.x(), enlarge_pass_texture_amount_.y()); if (!texture->id() && - !texture->Allocate(size, - ResourceProvider::TextureUsageFramebuffer, - RenderPassTextureFormat(render_pass))) + !texture->Allocate( + size, ResourceProvider::TextureUsageFramebuffer, RGBA_8888)) return false; return BindFramebufferToTexture(frame, texture, render_pass->output_rect); @@ -429,10 +425,4 @@ gfx::Size DirectRenderer::RenderPassTextureSize(const RenderPass* render_pass) { return render_pass->output_rect.size(); } -// static -ResourceFormat DirectRenderer::RenderPassTextureFormat( - const RenderPass* render_pass) { - return RGBA_8888; -} - } // namespace cc diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h index f55cc595be..6be6707a71 100644 --- a/cc/output/direct_renderer.h +++ b/cc/output/direct_renderer.h @@ -86,7 +86,6 @@ class CC_EXPORT DirectRenderer : public Renderer { gfx::RectF draw_space_rect); static gfx::Size RenderPassTextureSize(const RenderPass* render_pass); - static ResourceFormat RenderPassTextureFormat(const RenderPass* render_pass); void DrawRenderPass(DrawingFrame* frame, const RenderPass* render_pass, diff --git a/cc/output/filter_operation.cc b/cc/output/filter_operation.cc index 672dba79d5..50f111fc2d 100644 --- a/cc/output/filter_operation.cc +++ b/cc/output/filter_operation.cc @@ -8,6 +8,7 @@ #include "cc/base/math_util.h" #include "cc/output/filter_operation.h" #include "third_party/skia/include/core/SkMath.h" +#include "ui/gfx/animation/tween.h" namespace cc { @@ -97,52 +98,6 @@ FilterOperation::FilterOperation(const FilterOperation& other) FilterOperation::~FilterOperation() { } -// TODO(ajuma): Define a version of gfx::Tween::ValueBetween for floats, and use -// that instead. -static float BlendFloats(float from, float to, double progress) { - return from * (1.0 - progress) + to * progress; -} - -static int BlendInts(int from, int to, double progress) { - return static_cast<int>( - MathUtil::Round(from * (1.0 - progress) + to * progress)); -} - -static uint8_t BlendColorComponents(uint8_t from, - uint8_t to, - uint8_t from_alpha, - uint8_t to_alpha, - uint8_t blended_alpha, - double progress) { - // Since progress can be outside [0, 1], blending can produce a value outside - // [0, 255]. - int blended_premultiplied = BlendInts(SkMulDiv255Round(from, from_alpha), - SkMulDiv255Round(to, to_alpha), - progress); - int blended = static_cast<int>( - MathUtil::Round(blended_premultiplied * 255.f / blended_alpha)); - return static_cast<uint8_t>(MathUtil::ClampToRange(blended, 0, 255)); -} - -static SkColor BlendSkColors(SkColor from, SkColor to, double progress) { - int from_a = SkColorGetA(from); - int to_a = SkColorGetA(to); - int blended_a = BlendInts(from_a, to_a, progress); - if (blended_a <= 0) - return SkColorSetARGB(0, 0, 0, 0); - blended_a = std::min(blended_a, 255); - - // TODO(ajuma): Use SkFourByteInterp once http://crbug.com/260369 is fixed. - uint8_t blended_r = BlendColorComponents( - SkColorGetR(from), SkColorGetR(to), from_a, to_a, blended_a, progress); - uint8_t blended_g = BlendColorComponents( - SkColorGetG(from), SkColorGetG(to), from_a, to_a, blended_a, progress); - uint8_t blended_b = BlendColorComponents( - SkColorGetB(from), SkColorGetB(to), from_a, to_a, blended_a, progress); - - return SkColorSetARGB(blended_a, blended_r, blended_g, blended_b); -} - static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) { switch (type) { case FilterOperation::GRAYSCALE: @@ -239,21 +194,25 @@ FilterOperation FilterOperation::Blend(const FilterOperation* from, } blended_filter.set_amount(ClampAmountForFilterType( - BlendFloats(from_op.amount(), to_op.amount(), progress), to_op.type())); + gfx::Tween::FloatValueBetween(progress, from_op.amount(), to_op.amount()), + to_op.type())); if (to_op.type() == FilterOperation::DROP_SHADOW) { - gfx::Point blended_offset(BlendInts(from_op.drop_shadow_offset().x(), - to_op.drop_shadow_offset().x(), - progress), - BlendInts(from_op.drop_shadow_offset().y(), - to_op.drop_shadow_offset().y(), - progress)); + gfx::Point blended_offset( + gfx::Tween::LinearIntValueBetween(progress, + from_op.drop_shadow_offset().x(), + to_op.drop_shadow_offset().x()), + gfx::Tween::LinearIntValueBetween(progress, + from_op.drop_shadow_offset().y(), + to_op.drop_shadow_offset().y())); blended_filter.set_drop_shadow_offset(blended_offset); - blended_filter.set_drop_shadow_color(BlendSkColors( - from_op.drop_shadow_color(), to_op.drop_shadow_color(), progress)); + blended_filter.set_drop_shadow_color(gfx::Tween::ColorValueBetween( + progress, from_op.drop_shadow_color(), to_op.drop_shadow_color())); } else if (to_op.type() == FilterOperation::ZOOM) { - blended_filter.set_zoom_inset(std::max( - BlendInts(from_op.zoom_inset(), to_op.zoom_inset(), progress), 0)); + blended_filter.set_zoom_inset( + std::max(gfx::Tween::LinearIntValueBetween( + from_op.zoom_inset(), to_op.zoom_inset(), progress), + 0)); } return blended_filter; diff --git a/cc/output/filter_operations_unittest.cc b/cc/output/filter_operations_unittest.cc index e975ed509f..7f439b9f15 100644 --- a/cc/output/filter_operations_unittest.cc +++ b/cc/output/filter_operations_unittest.cc @@ -412,6 +412,11 @@ TEST(FilterOperationsTest, BlendDropShadowFilters) { gfx::Point(-2, -4), 0.f, SkColorSetARGB(0, 0, 0, 0)); EXPECT_EQ(expected, blended); + blended = FilterOperation::Blend(&from, &to, 0.25); + expected = FilterOperation::CreateDropShadowFilter( + gfx::Point(1, 1), 3.f, SkColorSetARGB(24, 32, 64, 128)); + EXPECT_EQ(expected, blended); + blended = FilterOperation::Blend(&from, &to, 0.75); expected = FilterOperation::CreateDropShadowFilter( gfx::Point(2, 4), 5.f, SkColorSetARGB(42, 30, 61, 121)); diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index 6e8bd752c6..35f8684914 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -38,6 +38,7 @@ #include "cc/trees/single_thread_proxy.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" +#include "gpu/command_buffer/common/gpu_memory_allocation.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" #include "third_party/khronos/GLES2/gl2.h" #include "third_party/khronos/GLES2/gl2ext.h" @@ -278,12 +279,12 @@ void GLRenderer::SetVisible(bool visible) { void GLRenderer::SendManagedMemoryStats(size_t bytes_visible, size_t bytes_visible_and_nearby, size_t bytes_allocated) { - WebKit::WebGraphicsManagedMemoryStats stats; - stats.bytesVisible = bytes_visible; - stats.bytesVisibleAndNearby = bytes_visible_and_nearby; - stats.bytesAllocated = bytes_allocated; - stats.backbufferRequested = !is_backbuffer_discarded_; - context_->sendManagedMemoryStatsCHROMIUM(&stats); + gpu::ManagedMemoryStats stats; + stats.bytes_required = bytes_visible; + stats.bytes_nice_to_have = bytes_visible_and_nearby; + stats.bytes_allocated = bytes_allocated; + stats.backbuffer_requested = !is_backbuffer_discarded_; + context_support_->SendManagedMemoryStats(stats); } void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); } diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index 7f60c2d817..8b71ca403b 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc @@ -221,7 +221,7 @@ class GLRendererTest : public testing::Test { CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false).Pass(); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false).Pass(); renderer_ = make_scoped_ptr(new FakeRendererGL(&renderer_client_, &settings_, output_surface_.get(), @@ -312,8 +312,8 @@ class GLRendererShaderTest : public testing::Test { new ShaderCreatorMockGraphicsContext())).Pass(); CHECK(output_surface_->BindToClient(&output_surface_client_)); - resource_provider_ = ResourceProvider::Create( - output_surface_.get(), 0, false).Pass(); + resource_provider_ = + ResourceProvider::Create(output_surface_.get(), NULL, 0, false).Pass(); renderer_.reset(new FakeRendererGL(&renderer_client_, &settings_, output_surface_.get(), @@ -634,7 +634,7 @@ TEST(GLRendererTest2, InitializationDoesNotMakeSynchronousCalls) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; FakeRendererClient renderer_client; @@ -679,7 +679,7 @@ TEST(GLRendererTest2, InitializationWithQuicklyLostContextDoesNotAssert) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; FakeRendererClient renderer_client; @@ -714,7 +714,7 @@ TEST(GLRendererTest2, OpaqueBackground) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; FakeRendererClient renderer_client; @@ -752,7 +752,7 @@ TEST(GLRendererTest2, TransparentBackground) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; FakeRendererClient renderer_client; @@ -784,7 +784,7 @@ TEST(GLRendererTest2, OffscreenOutputSurface) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; FakeRendererClient renderer_client; @@ -860,7 +860,7 @@ TEST(GLRendererTest2, VisibilityChangeIsLastCall) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; FakeRendererClient renderer_client; @@ -920,7 +920,7 @@ TEST(GLRendererTest2, ActiveTextureState) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; FakeRendererClient renderer_client; @@ -1007,7 +1007,7 @@ TEST(GLRendererTest2, ShouldClearRootRenderPass) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; settings.should_clear_root_render_pass = false; @@ -1095,7 +1095,7 @@ TEST(GLRendererTest2, ScissorTestWhenClearing) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; FakeRendererClient renderer_client; @@ -1181,7 +1181,7 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) { output_surface->set_fixed_size(gfx::Size(100, 100)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; settings.partial_swap_enabled = true; @@ -1360,7 +1360,7 @@ TEST(GLRendererTest2, ScissorAndViewportWithinNonreshapableSurface) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); LayerTreeSettings settings; FakeRendererClient renderer_client; @@ -1714,7 +1714,7 @@ class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient { CHECK(output_surface_.BindToClient(&output_surface_client_)); resource_provider_ = - ResourceProvider::Create(&output_surface_, 0, false).Pass(); + ResourceProvider::Create(&output_surface_, NULL, 0, false).Pass(); renderer_.reset(new FakeRendererGL( this, &settings_, &output_surface_, resource_provider_.get())); diff --git a/cc/output/managed_memory_policy.cc b/cc/output/managed_memory_policy.cc index 7e837662c2..ade2a27f9e 100644 --- a/cc/output/managed_memory_policy.cc +++ b/cc/output/managed_memory_policy.cc @@ -11,18 +11,29 @@ namespace cc { const size_t ManagedMemoryPolicy::kDefaultNumResourcesLimit = 10 * 1000 * 1000; +using gpu::MemoryAllocation; + ManagedMemoryPolicy::ManagedMemoryPolicy(size_t bytes_limit_when_visible) : bytes_limit_when_visible(bytes_limit_when_visible), - priority_cutoff_when_visible(CUTOFF_ALLOW_EVERYTHING), + priority_cutoff_when_visible(MemoryAllocation::CUTOFF_ALLOW_EVERYTHING), bytes_limit_when_not_visible(0), - priority_cutoff_when_not_visible(CUTOFF_ALLOW_NOTHING), + priority_cutoff_when_not_visible(MemoryAllocation::CUTOFF_ALLOW_NOTHING), + num_resources_limit(kDefaultNumResourcesLimit) {} + +ManagedMemoryPolicy::ManagedMemoryPolicy( + const gpu::MemoryAllocation& allocation) + : bytes_limit_when_visible(allocation.bytes_limit_when_visible), + priority_cutoff_when_visible(allocation.priority_cutoff_when_visible), + bytes_limit_when_not_visible(allocation.bytes_limit_when_not_visible), + priority_cutoff_when_not_visible( + allocation.priority_cutoff_when_not_visible), num_resources_limit(kDefaultNumResourcesLimit) {} ManagedMemoryPolicy::ManagedMemoryPolicy( size_t bytes_limit_when_visible, - PriorityCutoff priority_cutoff_when_visible, + MemoryAllocation::PriorityCutoff priority_cutoff_when_visible, size_t bytes_limit_when_not_visible, - PriorityCutoff priority_cutoff_when_not_visible, + MemoryAllocation::PriorityCutoff priority_cutoff_when_not_visible, size_t num_resources_limit) : bytes_limit_when_visible(bytes_limit_when_visible), priority_cutoff_when_visible(priority_cutoff_when_visible), @@ -44,15 +55,16 @@ bool ManagedMemoryPolicy::operator!=(const ManagedMemoryPolicy& other) const { } // static -int ManagedMemoryPolicy::PriorityCutoffToValue(PriorityCutoff priority_cutoff) { +int ManagedMemoryPolicy::PriorityCutoffToValue( + MemoryAllocation::PriorityCutoff priority_cutoff) { switch (priority_cutoff) { - case CUTOFF_ALLOW_NOTHING: + case MemoryAllocation::CUTOFF_ALLOW_NOTHING: return PriorityCalculator::AllowNothingCutoff(); - case CUTOFF_ALLOW_REQUIRED_ONLY: + case MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY: return PriorityCalculator::AllowVisibleOnlyCutoff(); - case CUTOFF_ALLOW_NICE_TO_HAVE: + case MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE: return PriorityCalculator::AllowVisibleAndNearbyCutoff(); - case CUTOFF_ALLOW_EVERYTHING: + case MemoryAllocation::CUTOFF_ALLOW_EVERYTHING: return PriorityCalculator::AllowEverythingCutoff(); } NOTREACHED(); @@ -62,15 +74,15 @@ int ManagedMemoryPolicy::PriorityCutoffToValue(PriorityCutoff priority_cutoff) { // static TileMemoryLimitPolicy ManagedMemoryPolicy::PriorityCutoffToTileMemoryLimitPolicy( - PriorityCutoff priority_cutoff) { + gpu::MemoryAllocation::PriorityCutoff priority_cutoff) { switch (priority_cutoff) { - case CUTOFF_ALLOW_NOTHING: + case MemoryAllocation::CUTOFF_ALLOW_NOTHING: return ALLOW_NOTHING; - case CUTOFF_ALLOW_REQUIRED_ONLY: + case MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY: return ALLOW_ABSOLUTE_MINIMUM; - case CUTOFF_ALLOW_NICE_TO_HAVE: + case MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE: return ALLOW_PREPAINT_ONLY; - case CUTOFF_ALLOW_EVERYTHING: + case MemoryAllocation::CUTOFF_ALLOW_EVERYTHING: return ALLOW_ANYTHING; } NOTREACHED(); diff --git a/cc/output/managed_memory_policy.h b/cc/output/managed_memory_policy.h index 5a607a7a1f..1a234f7da5 100644 --- a/cc/output/managed_memory_policy.h +++ b/cc/output/managed_memory_policy.h @@ -8,36 +8,35 @@ #include "base/basictypes.h" #include "cc/base/cc_export.h" #include "cc/resources/tile_priority.h" +#include "gpu/command_buffer/common/gpu_memory_allocation.h" namespace cc { struct CC_EXPORT ManagedMemoryPolicy { - enum PriorityCutoff { - CUTOFF_ALLOW_NOTHING, - CUTOFF_ALLOW_REQUIRED_ONLY, - CUTOFF_ALLOW_NICE_TO_HAVE, - CUTOFF_ALLOW_EVERYTHING, - }; static const size_t kDefaultNumResourcesLimit; explicit ManagedMemoryPolicy(size_t bytes_limit_when_visible); - ManagedMemoryPolicy(size_t bytes_limit_when_visible, - PriorityCutoff priority_cutoff_when_visible, - size_t bytes_limit_when_not_visible, - PriorityCutoff priority_cutoff_when_not_visible, - size_t num_resources_limit); + explicit ManagedMemoryPolicy( + const gpu::MemoryAllocation& allocation); + ManagedMemoryPolicy( + size_t bytes_limit_when_visible, + gpu::MemoryAllocation::PriorityCutoff priority_cutoff_when_visible, + size_t bytes_limit_when_not_visible, + gpu::MemoryAllocation::PriorityCutoff priority_cutoff_when_not_visible, + size_t num_resources_limit); bool operator==(const ManagedMemoryPolicy&) const; bool operator!=(const ManagedMemoryPolicy&) const; size_t bytes_limit_when_visible; - PriorityCutoff priority_cutoff_when_visible; + gpu::MemoryAllocation::PriorityCutoff priority_cutoff_when_visible; size_t bytes_limit_when_not_visible; - PriorityCutoff priority_cutoff_when_not_visible; + gpu::MemoryAllocation::PriorityCutoff priority_cutoff_when_not_visible; size_t num_resources_limit; - static int PriorityCutoffToValue(PriorityCutoff priority_cutoff); + static int PriorityCutoffToValue( + gpu::MemoryAllocation::PriorityCutoff priority_cutoff); static TileMemoryLimitPolicy PriorityCutoffToTileMemoryLimitPolicy( - PriorityCutoff priority_cutoff); + gpu::MemoryAllocation::PriorityCutoff priority_cutoff); }; } // namespace cc diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc index bcebeab429..002a44a37e 100644 --- a/cc/output/output_surface.cc +++ b/cc/output/output_surface.cc @@ -25,6 +25,7 @@ #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" #include "third_party/khronos/GLES2/gl2.h" #include "third_party/khronos/GLES2/gl2ext.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" @@ -48,10 +49,10 @@ OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider) device_scale_factor_(-1), max_frames_pending_(0), pending_swap_buffers_(0), - needs_begin_frame_(false), - client_ready_for_begin_frame_(true), + needs_begin_impl_frame_(false), + client_ready_for_begin_impl_frame_(true), client_(NULL), - check_for_retroactive_begin_frame_pending_(false), + check_for_retroactive_begin_impl_frame_pending_(false), external_stencil_test_enabled_(false), weak_ptr_factory_(this), gpu_latency_history_(kGpuLatencyHistorySize) {} @@ -64,10 +65,10 @@ OutputSurface::OutputSurface( device_scale_factor_(-1), max_frames_pending_(0), pending_swap_buffers_(0), - needs_begin_frame_(false), - client_ready_for_begin_frame_(true), + needs_begin_impl_frame_(false), + client_ready_for_begin_impl_frame_(true), client_(NULL), - check_for_retroactive_begin_frame_pending_(false), + check_for_retroactive_begin_impl_frame_pending_(false), external_stencil_test_enabled_(false), weak_ptr_factory_(this), gpu_latency_history_(kGpuLatencyHistorySize) {} @@ -82,22 +83,25 @@ OutputSurface::OutputSurface( device_scale_factor_(-1), max_frames_pending_(0), pending_swap_buffers_(0), - needs_begin_frame_(false), - client_ready_for_begin_frame_(true), + needs_begin_impl_frame_(false), + client_ready_for_begin_impl_frame_(true), client_(NULL), - check_for_retroactive_begin_frame_pending_(false), + check_for_retroactive_begin_impl_frame_pending_(false), external_stencil_test_enabled_(false), weak_ptr_factory_(this), gpu_latency_history_(kGpuLatencyHistorySize) {} -void OutputSurface::InitializeBeginFrameEmulation( +void OutputSurface::InitializeBeginImplFrameEmulation( base::SingleThreadTaskRunner* task_runner, bool throttle_frame_production, base::TimeDelta interval) { if (throttle_frame_production) { - frame_rate_controller_.reset( - new FrameRateController( - DelayBasedTimeSource::Create(interval, task_runner))); + scoped_refptr<DelayBasedTimeSource> time_source; + if (gfx::FrameTime::TimestampsAreHighRes()) + time_source = DelayBasedTimeSourceHighRes::Create(interval, task_runner); + else + time_source = DelayBasedTimeSource::Create(interval, task_runner); + frame_rate_controller_.reset(new FrameRateController(time_source)); } else { frame_rate_controller_.reset(new FrameRateController(task_runner)); } @@ -133,9 +137,9 @@ void OutputSurface::FrameRateControllerTick(bool throttled, const BeginFrameArgs& args) { DCHECK(frame_rate_controller_); if (throttled) - skipped_begin_frame_args_ = args; + skipped_begin_impl_frame_args_ = args; else - BeginFrame(args); + BeginImplFrame(args); } // Forwarded to OutputSurfaceClient @@ -144,62 +148,64 @@ void OutputSurface::SetNeedsRedrawRect(gfx::Rect damage_rect) { client_->SetNeedsRedrawRect(damage_rect); } -void OutputSurface::SetNeedsBeginFrame(bool enable) { - TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable); - needs_begin_frame_ = enable; - client_ready_for_begin_frame_ = true; +void OutputSurface::SetNeedsBeginImplFrame(bool enable) { + TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginImplFrame", "enable", enable); + needs_begin_impl_frame_ = enable; + client_ready_for_begin_impl_frame_ = true; if (frame_rate_controller_) { BeginFrameArgs skipped = frame_rate_controller_->SetActive(enable); if (skipped.IsValid()) - skipped_begin_frame_args_ = skipped; + skipped_begin_impl_frame_args_ = skipped; } - if (needs_begin_frame_) - PostCheckForRetroactiveBeginFrame(); + if (needs_begin_impl_frame_) + PostCheckForRetroactiveBeginImplFrame(); } -void OutputSurface::BeginFrame(const BeginFrameArgs& args) { - TRACE_EVENT2("cc", "OutputSurface::BeginFrame", - "client_ready_for_begin_frame_", client_ready_for_begin_frame_, +void OutputSurface::BeginImplFrame(const BeginFrameArgs& args) { + TRACE_EVENT2("cc", "OutputSurface::BeginImplFrame", + "client_ready_for_begin_impl_frame_", + client_ready_for_begin_impl_frame_, "pending_swap_buffers_", pending_swap_buffers_); - if (!needs_begin_frame_ || !client_ready_for_begin_frame_ || + if (!needs_begin_impl_frame_ || !client_ready_for_begin_impl_frame_ || (pending_swap_buffers_ >= max_frames_pending_ && max_frames_pending_ > 0)) { - skipped_begin_frame_args_ = args; + skipped_begin_impl_frame_args_ = args; } else { - client_ready_for_begin_frame_ = false; - client_->BeginFrame(args); - // args might be an alias for skipped_begin_frame_args_. - // Do not reset it before calling BeginFrame! - skipped_begin_frame_args_ = BeginFrameArgs(); + client_ready_for_begin_impl_frame_ = false; + client_->BeginImplFrame(args); + // args might be an alias for skipped_begin_impl_frame_args_. + // Do not reset it before calling BeginImplFrame! + skipped_begin_impl_frame_args_ = BeginFrameArgs(); } } -base::TimeTicks OutputSurface::RetroactiveBeginFrameDeadline() { +base::TimeTicks OutputSurface::RetroactiveBeginImplFrameDeadline() { // TODO(brianderson): Remove the alternative deadline once we have better // deadline estimations. base::TimeTicks alternative_deadline = - skipped_begin_frame_args_.frame_time + + skipped_begin_impl_frame_args_.frame_time + BeginFrameArgs::DefaultRetroactiveBeginFramePeriod(); - return std::max(skipped_begin_frame_args_.deadline, alternative_deadline); + return std::max(skipped_begin_impl_frame_args_.deadline, + alternative_deadline); } -void OutputSurface::PostCheckForRetroactiveBeginFrame() { - if (!skipped_begin_frame_args_.IsValid() || - check_for_retroactive_begin_frame_pending_) +void OutputSurface::PostCheckForRetroactiveBeginImplFrame() { + if (!skipped_begin_impl_frame_args_.IsValid() || + check_for_retroactive_begin_impl_frame_pending_) return; base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&OutputSurface::CheckForRetroactiveBeginFrame, + base::Bind(&OutputSurface::CheckForRetroactiveBeginImplFrame, weak_ptr_factory_.GetWeakPtr())); - check_for_retroactive_begin_frame_pending_ = true; + check_for_retroactive_begin_impl_frame_pending_ = true; } -void OutputSurface::CheckForRetroactiveBeginFrame() { - TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginFrame"); - check_for_retroactive_begin_frame_pending_ = false; - if (base::TimeTicks::Now() < RetroactiveBeginFrameDeadline()) - BeginFrame(skipped_begin_frame_args_); +void OutputSurface::CheckForRetroactiveBeginImplFrame() { + TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginImplFrame"); + check_for_retroactive_begin_impl_frame_pending_ = false; + if (gfx::FrameTime::Now() < RetroactiveBeginImplFrameDeadline()) + BeginImplFrame(skipped_begin_impl_frame_args_); } void OutputSurface::DidSwapBuffers() { @@ -208,7 +214,7 @@ void OutputSurface::DidSwapBuffers() { "pending_swap_buffers_", pending_swap_buffers_); if (frame_rate_controller_) frame_rate_controller_->DidSwapBuffers(); - PostCheckForRetroactiveBeginFrame(); + PostCheckForRetroactiveBeginImplFrame(); } void OutputSurface::OnSwapBuffersComplete() { @@ -218,7 +224,7 @@ void OutputSurface::OnSwapBuffersComplete() { client_->OnSwapBuffersComplete(); if (frame_rate_controller_) frame_rate_controller_->DidSwapBuffersComplete(); - PostCheckForRetroactiveBeginFrame(); + PostCheckForRetroactiveBeginImplFrame(); } void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) { @@ -227,9 +233,9 @@ void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) { void OutputSurface::DidLoseOutputSurface() { TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface"); - client_ready_for_begin_frame_ = true; + client_ready_for_begin_impl_frame_ = true; pending_swap_buffers_ = 0; - skipped_begin_frame_args_ = BeginFrameArgs(); + skipped_begin_impl_frame_args_ = BeginFrameArgs(); if (frame_rate_controller_) frame_rate_controller_->SetActive(false); pending_gpu_latency_query_ids_.clear(); diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h index 97e5744e8d..2887e80eb8 100644 --- a/cc/output/output_surface.h +++ b/cc/output/output_surface.h @@ -68,7 +68,7 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient { int max_frames_pending; bool deferred_gl_initialization; bool draw_and_swap_full_viewport_every_frame; - // This doesn't handle the <webview> case, but once BeginFrame is + // This doesn't handle the <webview> case, but once BeginImplFrame is // supported natively, we shouldn't need adjust_deadline_for_parent. bool adjust_deadline_for_parent; // Whether this output surface renders to the default OpenGL zero @@ -104,7 +104,7 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient { // thread. virtual bool BindToClient(OutputSurfaceClient* client); - void InitializeBeginFrameEmulation( + void InitializeBeginImplFrameEmulation( base::SingleThreadTaskRunner* task_runner, bool throttle_frame_production, base::TimeDelta interval); @@ -128,10 +128,10 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient { // processing should be stopped, or lowered in priority. virtual void UpdateSmoothnessTakesPriority(bool prefer_smoothness) {} - // Requests a BeginFrame notification from the output surface. The + // Requests a BeginImplFrame notification from the output surface. The // notification will be delivered by calling - // OutputSurfaceClient::BeginFrame until the callback is disabled. - virtual void SetNeedsBeginFrame(bool enable); + // OutputSurfaceClient::BeginImplFrame until the callback is disabled. + virtual void SetNeedsBeginImplFrame(bool enable); bool HasClient() { return !!client_; } @@ -160,7 +160,7 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient { float device_scale_factor_; // The FrameRateController is deprecated. - // Platforms should move to native BeginFrames instead. + // Platforms should move to native BeginImplFrames instead. void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval); virtual void FrameRateControllerTick(bool throttled, @@ -168,17 +168,17 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient { scoped_ptr<FrameRateController> frame_rate_controller_; int max_frames_pending_; int pending_swap_buffers_; - bool needs_begin_frame_; - bool client_ready_for_begin_frame_; + bool needs_begin_impl_frame_; + bool client_ready_for_begin_impl_frame_; - // This stores a BeginFrame that we couldn't process immediately, but might - // process retroactively in the near future. - BeginFrameArgs skipped_begin_frame_args_; + // This stores a BeginImplFrame that we couldn't process immediately, + // but might process retroactively in the near future. + BeginFrameArgs skipped_begin_impl_frame_args_; // Forwarded to OutputSurfaceClient but threaded through OutputSurface // first so OutputSurface has a chance to update the FrameRateController void SetNeedsRedrawRect(gfx::Rect damage_rect); - void BeginFrame(const BeginFrameArgs& args); + void BeginImplFrame(const BeginFrameArgs& args); void DidSwapBuffers(); void OnSwapBuffersComplete(); void ReclaimResources(const CompositorFrameAck* ack); @@ -190,13 +190,12 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient { bool valid_for_tile_management); // virtual for testing. - virtual base::TimeTicks RetroactiveBeginFrameDeadline(); - virtual void PostCheckForRetroactiveBeginFrame(); - void CheckForRetroactiveBeginFrame(); + virtual base::TimeTicks RetroactiveBeginImplFrameDeadline(); + virtual void PostCheckForRetroactiveBeginImplFrame(); + void CheckForRetroactiveBeginImplFrame(); private: OutputSurfaceClient* client_; - friend class OutputSurfaceCallbacks; void SetUpContext3d(); void ResetContext3d(); @@ -204,9 +203,9 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient { bool discard_backbuffer_when_not_visible); void UpdateAndMeasureGpuLatency(); - // check_for_retroactive_begin_frame_pending_ is used to avoid posting - // redundant checks for a retroactive BeginFrame. - bool check_for_retroactive_begin_frame_pending_; + // check_for_retroactive_begin_impl_frame_pending_ is used to avoid posting + // redundant checks for a retroactive BeginImplFrame. + bool check_for_retroactive_begin_impl_frame_pending_; bool external_stencil_test_enabled_; diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h index c0e2e4554b..192400c67d 100644 --- a/cc/output/output_surface_client.h +++ b/cc/output/output_surface_client.h @@ -31,7 +31,7 @@ class CC_EXPORT OutputSurfaceClient { scoped_refptr<ContextProvider> offscreen_context_provider) = 0; virtual void ReleaseGL() = 0; virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) = 0; - virtual void BeginFrame(const BeginFrameArgs& args) = 0; + virtual void BeginImplFrame(const BeginFrameArgs& args) = 0; virtual void OnSwapBuffersComplete() = 0; virtual void ReclaimResources(const CompositorFrameAck* ack) = 0; virtual void DidLoseOutputSurface() = 0; diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc index 91e7c39d0b..1a1db29d88 100644 --- a/cc/output/output_surface_unittest.cc +++ b/cc/output/output_surface_unittest.cc @@ -15,6 +15,7 @@ #include "cc/test/scheduler_test_common.h" #include "gpu/GLES2/gl2extchromium.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/frame_time.h" namespace cc { namespace { @@ -23,19 +24,19 @@ class TestOutputSurface : public OutputSurface { public: explicit TestOutputSurface(scoped_refptr<ContextProvider> context_provider) : OutputSurface(context_provider), - retroactive_begin_frame_deadline_enabled_(false), + retroactive_begin_impl_frame_deadline_enabled_(false), override_retroactive_period_(false) {} explicit TestOutputSurface( scoped_ptr<cc::SoftwareOutputDevice> software_device) : OutputSurface(software_device.Pass()), - retroactive_begin_frame_deadline_enabled_(false), + retroactive_begin_impl_frame_deadline_enabled_(false), override_retroactive_period_(false) {} TestOutputSurface(scoped_refptr<ContextProvider> context_provider, scoped_ptr<cc::SoftwareOutputDevice> software_device) : OutputSurface(context_provider, software_device.Pass()), - retroactive_begin_frame_deadline_enabled_(false), + retroactive_begin_impl_frame_deadline_enabled_(false), override_retroactive_period_(false) {} bool InitializeNewContext3d( @@ -51,8 +52,8 @@ class TestOutputSurface : public OutputSurface { OnVSyncParametersChanged(timebase, interval); } - void BeginFrameForTesting() { - OutputSurface::BeginFrame(BeginFrameArgs::CreateExpiredForTesting()); + void BeginImplFrameForTesting() { + OutputSurface::BeginImplFrame(BeginFrameArgs::CreateExpiredForTesting()); } void DidSwapBuffersForTesting() { @@ -67,33 +68,34 @@ class TestOutputSurface : public OutputSurface { OnSwapBuffersComplete(); } - void EnableRetroactiveBeginFrameDeadline(bool enable, - bool override_retroactive_period, - base::TimeDelta period_override) { - retroactive_begin_frame_deadline_enabled_ = enable; + void EnableRetroactiveBeginImplFrameDeadline( + bool enable, + bool override_retroactive_period, + base::TimeDelta period_override) { + retroactive_begin_impl_frame_deadline_enabled_ = enable; override_retroactive_period_ = override_retroactive_period; retroactive_period_override_ = period_override; } protected: - virtual void PostCheckForRetroactiveBeginFrame() OVERRIDE { + virtual void PostCheckForRetroactiveBeginImplFrame() OVERRIDE { // For testing purposes, we check immediately rather than posting a task. - CheckForRetroactiveBeginFrame(); + CheckForRetroactiveBeginImplFrame(); } - virtual base::TimeTicks RetroactiveBeginFrameDeadline() OVERRIDE { - if (retroactive_begin_frame_deadline_enabled_) { + virtual base::TimeTicks RetroactiveBeginImplFrameDeadline() OVERRIDE { + if (retroactive_begin_impl_frame_deadline_enabled_) { if (override_retroactive_period_) { - return skipped_begin_frame_args_.frame_time + + return skipped_begin_impl_frame_args_.frame_time + retroactive_period_override_; } else { - return OutputSurface::RetroactiveBeginFrameDeadline(); + return OutputSurface::RetroactiveBeginImplFrameDeadline(); } } return base::TimeTicks(); } - bool retroactive_begin_frame_deadline_enabled_; + bool retroactive_begin_impl_frame_deadline_enabled_; bool override_retroactive_period_; base::TimeDelta retroactive_period_override_; }; @@ -218,7 +220,7 @@ TEST_F(OutputSurfaceTestInitializeNewContext3d, ClientDeferredInitializeFails) { InitializeNewContextExpectFail(); } -TEST(OutputSurfaceTest, BeginFrameEmulation) { +TEST(OutputSurfaceTest, BeginImplFrameEmulation) { TestOutputSurface output_surface(TestContextProvider::Create()); EXPECT_FALSE(output_surface.HasClient()); @@ -227,84 +229,86 @@ TEST(OutputSurfaceTest, BeginFrameEmulation) { EXPECT_TRUE(output_surface.HasClient()); EXPECT_FALSE(client.deferred_initialize_called()); - // Initialize BeginFrame emulation + // Initialize BeginImplFrame emulation scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; bool throttle_frame_production = true; const base::TimeDelta display_refresh_interval = BeginFrameArgs::DefaultInterval(); - output_surface.InitializeBeginFrameEmulation( + output_surface.InitializeBeginImplFrameEmulation( task_runner.get(), throttle_frame_production, display_refresh_interval); output_surface.SetMaxFramesPending(2); - output_surface.EnableRetroactiveBeginFrameDeadline( + output_surface.EnableRetroactiveBeginImplFrameDeadline( false, false, base::TimeDelta()); - // We should start off with 0 BeginFrames - EXPECT_EQ(client.begin_frame_count(), 0); + // We should start off with 0 BeginImplFrames + EXPECT_EQ(client.begin_impl_frame_count(), 0); EXPECT_EQ(output_surface.pending_swap_buffers(), 0); - // We should not have a pending task until a BeginFrame has been requested. + // We should not have a pending task until a BeginImplFrame has been + // requested. EXPECT_FALSE(task_runner->HasPendingTask()); - output_surface.SetNeedsBeginFrame(true); + output_surface.SetNeedsBeginImplFrame(true); EXPECT_TRUE(task_runner->HasPendingTask()); - // BeginFrame should be called on the first tick. + // BeginImplFrame should be called on the first tick. task_runner->RunPendingTasks(); - EXPECT_EQ(client.begin_frame_count(), 1); + EXPECT_EQ(client.begin_impl_frame_count(), 1); EXPECT_EQ(output_surface.pending_swap_buffers(), 0); - // BeginFrame should not be called when there is a pending BeginFrame. + // BeginImplFrame should not be called when there is a pending BeginImplFrame. task_runner->RunPendingTasks(); - EXPECT_EQ(client.begin_frame_count(), 1); + EXPECT_EQ(client.begin_impl_frame_count(), 1); EXPECT_EQ(output_surface.pending_swap_buffers(), 0); - // SetNeedsBeginFrame should clear the pending BeginFrame after + // SetNeedsBeginImplFrame should clear the pending BeginImplFrame after // a SwapBuffers. output_surface.DidSwapBuffersForTesting(); - output_surface.SetNeedsBeginFrame(true); - EXPECT_EQ(client.begin_frame_count(), 1); + output_surface.SetNeedsBeginImplFrame(true); + EXPECT_EQ(client.begin_impl_frame_count(), 1); EXPECT_EQ(output_surface.pending_swap_buffers(), 1); task_runner->RunPendingTasks(); - EXPECT_EQ(client.begin_frame_count(), 2); + EXPECT_EQ(client.begin_impl_frame_count(), 2); EXPECT_EQ(output_surface.pending_swap_buffers(), 1); - // BeginFrame should be throttled by pending swap buffers. + // BeginImplFrame should be throttled by pending swap buffers. output_surface.DidSwapBuffersForTesting(); - output_surface.SetNeedsBeginFrame(true); - EXPECT_EQ(client.begin_frame_count(), 2); + output_surface.SetNeedsBeginImplFrame(true); + EXPECT_EQ(client.begin_impl_frame_count(), 2); EXPECT_EQ(output_surface.pending_swap_buffers(), 2); task_runner->RunPendingTasks(); - EXPECT_EQ(client.begin_frame_count(), 2); + EXPECT_EQ(client.begin_impl_frame_count(), 2); EXPECT_EQ(output_surface.pending_swap_buffers(), 2); - // SwapAck should decrement pending swap buffers and unblock BeginFrame again. + // SwapAck should decrement pending swap buffers and unblock BeginImplFrame + // again. output_surface.OnSwapBuffersCompleteForTesting(); - EXPECT_EQ(client.begin_frame_count(), 2); + EXPECT_EQ(client.begin_impl_frame_count(), 2); EXPECT_EQ(output_surface.pending_swap_buffers(), 1); task_runner->RunPendingTasks(); - EXPECT_EQ(client.begin_frame_count(), 3); + EXPECT_EQ(client.begin_impl_frame_count(), 3); EXPECT_EQ(output_surface.pending_swap_buffers(), 1); - // Calling SetNeedsBeginFrame again indicates a swap did not occur but - // the client still wants another BeginFrame. - output_surface.SetNeedsBeginFrame(true); + // Calling SetNeedsBeginImplFrame again indicates a swap did not occur but + // the client still wants another BeginImplFrame. + output_surface.SetNeedsBeginImplFrame(true); task_runner->RunPendingTasks(); - EXPECT_EQ(client.begin_frame_count(), 4); + EXPECT_EQ(client.begin_impl_frame_count(), 4); EXPECT_EQ(output_surface.pending_swap_buffers(), 1); - // Disabling SetNeedsBeginFrame should prevent further BeginFrames. - output_surface.SetNeedsBeginFrame(false); + // Disabling SetNeedsBeginImplFrame should prevent further BeginImplFrames. + output_surface.SetNeedsBeginImplFrame(false); task_runner->RunPendingTasks(); EXPECT_FALSE(task_runner->HasPendingTask()); - EXPECT_EQ(client.begin_frame_count(), 4); + EXPECT_EQ(client.begin_impl_frame_count(), 4); EXPECT_EQ(output_surface.pending_swap_buffers(), 1); } -TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginFrames) { +TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginImplFrames) { TestOutputSurface output_surface(TestContextProvider::Create()); EXPECT_FALSE(output_surface.HasClient()); @@ -314,47 +318,48 @@ TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginFrames) { EXPECT_FALSE(client.deferred_initialize_called()); output_surface.SetMaxFramesPending(2); - output_surface.EnableRetroactiveBeginFrameDeadline( + output_surface.EnableRetroactiveBeginImplFrameDeadline( true, false, base::TimeDelta()); - // Optimistically injected BeginFrames should be throttled if - // SetNeedsBeginFrame is false... - output_surface.SetNeedsBeginFrame(false); - output_surface.BeginFrameForTesting(); - EXPECT_EQ(client.begin_frame_count(), 0); - // ...and retroactively triggered by a SetNeedsBeginFrame. - output_surface.SetNeedsBeginFrame(true); - EXPECT_EQ(client.begin_frame_count(), 1); - - // Optimistically injected BeginFrames should be throttled by pending - // BeginFrames... - output_surface.BeginFrameForTesting(); - EXPECT_EQ(client.begin_frame_count(), 1); - // ...and retroactively triggered by a SetNeedsBeginFrame. - output_surface.SetNeedsBeginFrame(true); - EXPECT_EQ(client.begin_frame_count(), 2); + // Optimistically injected BeginImplFrames should be throttled if + // SetNeedsBeginImplFrame is false... + output_surface.SetNeedsBeginImplFrame(false); + output_surface.BeginImplFrameForTesting(); + EXPECT_EQ(client.begin_impl_frame_count(), 0); + // ...and retroactively triggered by a SetNeedsBeginImplFrame. + output_surface.SetNeedsBeginImplFrame(true); + EXPECT_EQ(client.begin_impl_frame_count(), 1); + + // Optimistically injected BeginImplFrames should be throttled by pending + // BeginImplFrames... + output_surface.BeginImplFrameForTesting(); + EXPECT_EQ(client.begin_impl_frame_count(), 1); + // ...and retroactively triggered by a SetNeedsBeginImplFrame. + output_surface.SetNeedsBeginImplFrame(true); + EXPECT_EQ(client.begin_impl_frame_count(), 2); // ...or retroactively triggered by a Swap. - output_surface.BeginFrameForTesting(); - EXPECT_EQ(client.begin_frame_count(), 2); + output_surface.BeginImplFrameForTesting(); + EXPECT_EQ(client.begin_impl_frame_count(), 2); output_surface.DidSwapBuffersForTesting(); - output_surface.SetNeedsBeginFrame(true); - EXPECT_EQ(client.begin_frame_count(), 3); + output_surface.SetNeedsBeginImplFrame(true); + EXPECT_EQ(client.begin_impl_frame_count(), 3); EXPECT_EQ(output_surface.pending_swap_buffers(), 1); - // Optimistically injected BeginFrames should be by throttled by pending + // Optimistically injected BeginImplFrames should be by throttled by pending // swap buffers... output_surface.DidSwapBuffersForTesting(); - output_surface.SetNeedsBeginFrame(true); - EXPECT_EQ(client.begin_frame_count(), 3); + output_surface.SetNeedsBeginImplFrame(true); + EXPECT_EQ(client.begin_impl_frame_count(), 3); EXPECT_EQ(output_surface.pending_swap_buffers(), 2); - output_surface.BeginFrameForTesting(); - EXPECT_EQ(client.begin_frame_count(), 3); + output_surface.BeginImplFrameForTesting(); + EXPECT_EQ(client.begin_impl_frame_count(), 3); // ...and retroactively triggered by OnSwapBuffersComplete output_surface.OnSwapBuffersCompleteForTesting(); - EXPECT_EQ(client.begin_frame_count(), 4); + EXPECT_EQ(client.begin_impl_frame_count(), 4); } -TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) { +TEST(OutputSurfaceTest, + RetroactiveBeginImplFrameDoesNotDoubleTickWhenEmulating) { scoped_refptr<TestContextProvider> context_provider = TestContextProvider::Create(); @@ -368,13 +373,13 @@ TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) { base::TimeDelta big_interval = base::TimeDelta::FromSeconds(10); - // Initialize BeginFrame emulation + // Initialize BeginImplFrame emulation scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; bool throttle_frame_production = true; const base::TimeDelta display_refresh_interval = big_interval; - output_surface.InitializeBeginFrameEmulation( + output_surface.InitializeBeginImplFrameEmulation( task_runner.get(), throttle_frame_production, display_refresh_interval); @@ -382,31 +387,34 @@ TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) { // We need to subtract an epsilon from Now() because some platforms have // a slow clock. output_surface.OnVSyncParametersChangedForTesting( - base::TimeTicks::Now() - base::TimeDelta::FromSeconds(1), big_interval); + gfx::FrameTime::Now() - base::TimeDelta::FromSeconds(1), big_interval); output_surface.SetMaxFramesPending(2); - output_surface.EnableRetroactiveBeginFrameDeadline(true, true, big_interval); + output_surface.EnableRetroactiveBeginImplFrameDeadline( + true, true, big_interval); - // We should start off with 0 BeginFrames - EXPECT_EQ(client.begin_frame_count(), 0); + // We should start off with 0 BeginImplFrames + EXPECT_EQ(client.begin_impl_frame_count(), 0); EXPECT_EQ(output_surface.pending_swap_buffers(), 0); - // The first SetNeedsBeginFrame(true) should start a retroactive BeginFrame. + // The first SetNeedsBeginImplFrame(true) should start a retroactive + // BeginImplFrame. EXPECT_FALSE(task_runner->HasPendingTask()); - output_surface.SetNeedsBeginFrame(true); + output_surface.SetNeedsBeginImplFrame(true); EXPECT_TRUE(task_runner->HasPendingTask()); EXPECT_GT(task_runner->NextPendingTaskDelay(), big_interval / 2); - EXPECT_EQ(client.begin_frame_count(), 1); + EXPECT_EQ(client.begin_impl_frame_count(), 1); - output_surface.SetNeedsBeginFrame(false); + output_surface.SetNeedsBeginImplFrame(false); EXPECT_TRUE(task_runner->HasPendingTask()); - EXPECT_EQ(client.begin_frame_count(), 1); + EXPECT_EQ(client.begin_impl_frame_count(), 1); - // The second SetNeedBeginFrame(true) should not retroactively start a - // BeginFrame if the timestamp would be the same as the previous BeginFrame. - output_surface.SetNeedsBeginFrame(true); + // The second SetNeedBeginImplFrame(true) should not retroactively start a + // BeginImplFrame if the timestamp would be the same as the previous + // BeginImplFrame. + output_surface.SetNeedsBeginImplFrame(true); EXPECT_TRUE(task_runner->HasPendingTask()); - EXPECT_EQ(client.begin_frame_count(), 1); + EXPECT_EQ(client.begin_impl_frame_count(), 1); } TEST(OutputSurfaceTest, MemoryAllocation) { @@ -421,20 +429,20 @@ TEST(OutputSurfaceTest, MemoryAllocation) { ManagedMemoryPolicy policy(0); policy.bytes_limit_when_visible = 1234; policy.priority_cutoff_when_visible = - ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY; + gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY; policy.bytes_limit_when_not_visible = 4567; policy.priority_cutoff_when_not_visible = - ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING; + gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING; bool discard_backbuffer_when_not_visible = false; context_provider->SetMemoryAllocation(policy, discard_backbuffer_when_not_visible); EXPECT_EQ(1234u, client.memory_policy().bytes_limit_when_visible); - EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY, + EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY, client.memory_policy().priority_cutoff_when_visible); EXPECT_EQ(4567u, client.memory_policy().bytes_limit_when_not_visible); - EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING, + EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING, client.memory_policy().priority_cutoff_when_not_visible); EXPECT_FALSE(client.discard_backbuffer_when_not_visible()); @@ -444,14 +452,14 @@ TEST(OutputSurfaceTest, MemoryAllocation) { EXPECT_TRUE(client.discard_backbuffer_when_not_visible()); policy.priority_cutoff_when_visible = - ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING; + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING; policy.priority_cutoff_when_not_visible = - ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE; + gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; context_provider->SetMemoryAllocation(policy, discard_backbuffer_when_not_visible); - EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, + EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, client.memory_policy().priority_cutoff_when_visible); - EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE, + EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, client.memory_policy().priority_cutoff_when_not_visible); // 0 bytes limit should be ignored. diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc index f88a9ee082..450d1fe32f 100644 --- a/cc/output/software_renderer_unittest.cc +++ b/cc/output/software_renderer_unittest.cc @@ -34,7 +34,7 @@ class SoftwareRendererTest : public testing::Test, public RendererClient { CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false); renderer_ = SoftwareRenderer::Create( this, &settings_, output_surface_.get(), resource_provider()); } diff --git a/cc/quads/render_pass.cc b/cc/quads/render_pass.cc index e61a463f33..6d6c430be3 100644 --- a/cc/quads/render_pass.cc +++ b/cc/quads/render_pass.cc @@ -65,10 +65,11 @@ void RenderPass::CopyAll(const ScopedPtrVector<RenderPass>& in, source->shared_quad_state_list[i]->Copy()); } for (size_t i = 0, sqs_i = 0; i < source->quad_list.size(); ++i) { - if (source->quad_list[i]->shared_quad_state != - source->shared_quad_state_list[sqs_i]) + while (source->quad_list[i]->shared_quad_state != + source->shared_quad_state_list[sqs_i]) { ++sqs_i; - DCHECK(sqs_i < source->shared_quad_state_list.size()); + DCHECK_LT(sqs_i, source->shared_quad_state_list.size()); + } DCHECK(source->quad_list[i]->shared_quad_state == source->shared_quad_state_list[sqs_i]); diff --git a/cc/quads/render_pass_unittest.cc b/cc/quads/render_pass_unittest.cc index 259ecad746..394a3ec56a 100644 --- a/cc/quads/render_pass_unittest.cc +++ b/cc/quads/render_pass_unittest.cc @@ -33,6 +33,35 @@ struct RenderPassSize { ScopedPtrVector<CopyOutputRequest> copy_callbacks; }; +static void CompareRenderPassLists(const RenderPassList& expected_list, + const RenderPassList& actual_list) { + EXPECT_EQ(expected_list.size(), actual_list.size()); + for (size_t i = 0; i < actual_list.size(); ++i) { + RenderPass* expected = expected_list[i]; + RenderPass* actual = actual_list[i]; + + EXPECT_EQ(expected->id, actual->id); + EXPECT_RECT_EQ(expected->output_rect, actual->output_rect); + EXPECT_EQ(expected->transform_to_root_target, + actual->transform_to_root_target); + EXPECT_RECT_EQ(expected->damage_rect, actual->damage_rect); + EXPECT_EQ(expected->has_transparent_background, + actual->has_transparent_background); + + EXPECT_EQ(expected->shared_quad_state_list.size(), + actual->shared_quad_state_list.size()); + EXPECT_EQ(expected->quad_list.size(), actual->quad_list.size()); + + for (size_t i = 0; i < expected->quad_list.size(); ++i) { + EXPECT_EQ(expected->quad_list[i]->rect.ToString(), + actual->quad_list[i]->rect.ToString()); + EXPECT_EQ( + expected->quad_list[i]->shared_quad_state->content_bounds.ToString(), + actual->quad_list[i]->shared_quad_state->content_bounds.ToString()); + } + } +} + TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) { RenderPass::Id id(3, 2); gfx::Rect output_rect(45, 22, 120, 13); @@ -177,30 +206,69 @@ TEST(RenderPassTest, CopyAllShouldBeIdentical) { RenderPassList copy_list; RenderPass::CopyAll(pass_list, ©_list); - EXPECT_EQ(pass_list.size(), copy_list.size()); - for (size_t i = 0; i < copy_list.size(); ++i) { - RenderPass* pass = pass_list[i]; - RenderPass* copy = copy_list[i]; - - EXPECT_EQ(pass->id, copy->id); - EXPECT_RECT_EQ(pass->output_rect, copy->output_rect); - EXPECT_EQ(pass->transform_to_root_target, copy->transform_to_root_target); - EXPECT_RECT_EQ(pass->damage_rect, copy->damage_rect); - EXPECT_EQ(pass->has_transparent_background, - copy->has_transparent_background); - - EXPECT_EQ(pass->shared_quad_state_list.size(), - copy->shared_quad_state_list.size()); - EXPECT_EQ(pass->quad_list.size(), copy->quad_list.size()); - - for (size_t i = 0; i < pass->quad_list.size(); ++i) { - EXPECT_EQ(pass->quad_list[i]->rect.ToString(), - copy->quad_list[i]->rect.ToString()); - EXPECT_EQ( - pass->quad_list[i]->shared_quad_state->content_bounds.ToString(), - copy->quad_list[i]->shared_quad_state->content_bounds.ToString()); - } - } + CompareRenderPassLists(pass_list, copy_list); +} + +TEST(RenderPassTest, CopyAllWithCulledQuads) { + RenderPassList pass_list; + + RenderPass::Id id(3, 2); + gfx::Rect output_rect(45, 22, 120, 13); + gfx::Transform transform_to_root = + gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0); + gfx::Rect damage_rect(56, 123, 19, 43); + bool has_transparent_background = true; + + scoped_ptr<TestRenderPass> pass = TestRenderPass::Create(); + pass->SetAll(id, + output_rect, + damage_rect, + transform_to_root, + has_transparent_background); + + // A shared state with a quad. + scoped_ptr<SharedQuadState> shared_state1 = SharedQuadState::Create(); + shared_state1->SetAll( + gfx::Transform(), gfx::Size(1, 1), gfx::Rect(), gfx::Rect(), false, 1); + pass->AppendSharedQuadState(shared_state1.Pass()); + + scoped_ptr<CheckerboardDrawQuad> checkerboard_quad1 = + CheckerboardDrawQuad::Create(); + checkerboard_quad1->SetNew( + pass->shared_quad_state_list.back(), gfx::Rect(1, 1, 1, 1), SkColor()); + pass->quad_list.push_back(checkerboard_quad1.PassAs<DrawQuad>()); + + // A shared state with no quads, they were culled. + scoped_ptr<SharedQuadState> shared_state2 = SharedQuadState::Create(); + shared_state2->SetAll( + gfx::Transform(), gfx::Size(2, 2), gfx::Rect(), gfx::Rect(), false, 1); + pass->AppendSharedQuadState(shared_state2.Pass()); + + // A second shared state with no quads. + scoped_ptr<SharedQuadState> shared_state3 = SharedQuadState::Create(); + shared_state3->SetAll( + gfx::Transform(), gfx::Size(2, 2), gfx::Rect(), gfx::Rect(), false, 1); + pass->AppendSharedQuadState(shared_state3.Pass()); + + // A last shared state with a quad again. + scoped_ptr<SharedQuadState> shared_state4 = SharedQuadState::Create(); + shared_state4->SetAll( + gfx::Transform(), gfx::Size(2, 2), gfx::Rect(), gfx::Rect(), false, 1); + pass->AppendSharedQuadState(shared_state4.Pass()); + + scoped_ptr<CheckerboardDrawQuad> checkerboard_quad2 = + CheckerboardDrawQuad::Create(); + checkerboard_quad2->SetNew( + pass->shared_quad_state_list.back(), gfx::Rect(3, 3, 3, 3), SkColor()); + pass->quad_list.push_back(checkerboard_quad2.PassAs<DrawQuad>()); + + pass_list.push_back(pass.PassAs<RenderPass>()); + + // Make a copy with CopyAll(). + RenderPassList copy_list; + RenderPass::CopyAll(pass_list, ©_list); + + CompareRenderPassLists(pass_list, copy_list); } } // namespace diff --git a/cc/resources/bitmap_skpicture_content_layer_updater.cc b/cc/resources/bitmap_skpicture_content_layer_updater.cc index 6b6cd9f439..cc839a60ee 100644 --- a/cc/resources/bitmap_skpicture_content_layer_updater.cc +++ b/cc/resources/bitmap_skpicture_content_layer_updater.cc @@ -25,9 +25,9 @@ void BitmapSkPictureContentLayerUpdater::Resource::Update( gfx::Vector2d dest_offset, bool partial_update) { bitmap_.setConfig( - SkBitmap::kARGB_8888_Config, source_rect.width(), source_rect.height()); + SkBitmap::kARGB_8888_Config, source_rect.width(), source_rect.height(), 0, + updater_->layer_is_opaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType); bitmap_.allocPixels(); - bitmap_.setIsOpaque(updater_->layer_is_opaque()); SkBitmapDevice device(bitmap_); SkCanvas canvas(&device); updater_->PaintContentsRect(&canvas, source_rect); diff --git a/cc/resources/image_raster_worker_pool.cc b/cc/resources/image_raster_worker_pool.cc index 30add2ad2e..e665837a81 100644 --- a/cc/resources/image_raster_worker_pool.cc +++ b/cc/resources/image_raster_worker_pool.cc @@ -149,7 +149,7 @@ void ImageRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) { set_raster_required_for_activation_finished_task( new_raster_required_for_activation_finished_task); - TRACE_EVENT_ASYNC_STEP1( + TRACE_EVENT_ASYNC_STEP_INTO1( "cc", "ScheduledTasks", this, "rasterizing", "state", TracedValue::FromValue(StateAsValue().release())); } @@ -169,7 +169,7 @@ void ImageRasterWorkerPool::OnRasterTasksFinished() { void ImageRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() { DCHECK(raster_tasks_required_for_activation_pending_); raster_tasks_required_for_activation_pending_ = false; - TRACE_EVENT_ASYNC_STEP1( + TRACE_EVENT_ASYNC_STEP_INTO1( "cc", "ScheduledTasks", this, "rasterizing", "state", TracedValue::FromValue(StateAsValue().release())); client()->DidFinishRunningTasksRequiredForActivation(); diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc index 8083050aca..7e278f8de5 100644 --- a/cc/resources/picture.cc +++ b/cc/resources/picture.cc @@ -86,7 +86,8 @@ scoped_refptr<Picture> Picture::Create(gfx::Rect layer_rect) { } Picture::Picture(gfx::Rect layer_rect) - : layer_rect_(layer_rect) { + : layer_rect_(layer_rect), + cell_size_(layer_rect.size()) { // Instead of recording a trace event for object creation here, we wait for // the picture to be recorded in Picture::Record. } @@ -155,7 +156,8 @@ Picture::Picture(SkPicture* picture, gfx::Rect opaque_rect) : layer_rect_(layer_rect), opaque_rect_(opaque_rect), - picture_(skia::AdoptRef(picture)) { + picture_(skia::AdoptRef(picture)), + cell_size_(layer_rect.size()) { } Picture::Picture(const skia::RefPtr<SkPicture>& picture, @@ -165,7 +167,8 @@ Picture::Picture(const skia::RefPtr<SkPicture>& picture, layer_rect_(layer_rect), opaque_rect_(opaque_rect), picture_(picture), - pixel_refs_(pixel_refs) { + pixel_refs_(pixel_refs), + cell_size_(layer_rect.size()) { } Picture::~Picture() { @@ -294,16 +297,21 @@ void Picture::GatherPixelRefs( int Picture::Raster( SkCanvas* canvas, SkDrawPictureCallback* callback, - gfx::Rect content_rect, + const Region& negated_content_region, float contents_scale) { TRACE_EVENT_BEGIN1( - "cc", "Picture::Raster", - "data", AsTraceableRasterData(content_rect, contents_scale)); + "cc", + "Picture::Raster", + "data", + AsTraceableRasterData(contents_scale)); DCHECK(picture_); canvas->save(); - canvas->clipRect(gfx::RectToSkRect(content_rect)); + + for (Region::Iterator it(negated_content_region); it.has_rect(); it.next()) + canvas->clipRect(gfx::RectToSkRect(it.rect()), SkRegion::kDifference_Op); + canvas->scale(contents_scale, contents_scale); canvas->translate(layer_rect_.x(), layer_rect_.y()); picture_->draw(canvas, callback); @@ -382,8 +390,9 @@ Picture::PixelRefIterator::PixelRefIterator( current_index_(0) { gfx::Rect layer_rect = picture->layer_rect_; gfx::Size cell_size = picture->cell_size_; + DCHECK(!cell_size.IsEmpty()); - // Early out if the query rect doesn't intersect this picture + // Early out if the query rect doesn't intersect this picture. if (!query_rect.Intersects(layer_rect)) { min_point_ = gfx::Point(0, 0); max_point_ = gfx::Point(0, 0); @@ -460,14 +469,10 @@ Picture::PixelRefIterator& Picture::PixelRefIterator::operator++() { } scoped_refptr<base::debug::ConvertableToTraceFormat> - Picture::AsTraceableRasterData(gfx::Rect rect, float scale) const { + Picture::AsTraceableRasterData(float scale) const { scoped_ptr<base::DictionaryValue> raster_data(new base::DictionaryValue()); raster_data->Set("picture_id", TracedValue::CreateIDRef(this).release()); raster_data->SetDouble("scale", scale); - raster_data->SetDouble("rect_x", rect.x()); - raster_data->SetDouble("rect_y", rect.y()); - raster_data->SetDouble("rect_width", rect.width()); - raster_data->SetDouble("rect_height", rect.height()); return TracedValue::FromValue(raster_data.release()); } diff --git a/cc/resources/picture.h b/cc/resources/picture.h index 8210e86318..4eb238ab63 100644 --- a/cc/resources/picture.h +++ b/cc/resources/picture.h @@ -17,6 +17,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" +#include "cc/base/region.h" #include "skia/ext/lazy_pixel_ref.h" #include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkPixelRef.h" @@ -67,10 +68,11 @@ class CC_EXPORT Picture // Has Record() been called yet? bool HasRecording() const { return picture_.get() != NULL; } - // Apply this contents scale and raster the content rect into the canvas. + // Apply this scale and raster the negated region into the canvas. See comment + // in PicturePileImpl::RasterCommon for explanation on negated content region. int Raster(SkCanvas* canvas, SkDrawPictureCallback* callback, - gfx::Rect content_rect, + const Region& negated_content_region, float contents_scale); // Draw the picture directly into the given canvas, without applying any @@ -142,7 +144,7 @@ class CC_EXPORT Picture gfx::Size cell_size_; scoped_refptr<base::debug::ConvertableToTraceFormat> - AsTraceableRasterData(gfx::Rect rect, float scale) const; + AsTraceableRasterData(float scale) const; scoped_refptr<base::debug::ConvertableToTraceFormat> AsTraceableRecordData() const; diff --git a/cc/resources/picture_layer_tiling_perftest.cc b/cc/resources/picture_layer_tiling_perftest.cc index 655603d2e8..7a9b8dff4b 100644 --- a/cc/resources/picture_layer_tiling_perftest.cc +++ b/cc/resources/picture_layer_tiling_perftest.cc @@ -153,7 +153,12 @@ TEST_F(PictureLayerTilingPerfTest, Invalidate) { RunInvalidateTest("50x50", full_region); } +#if defined(OS_ANDROID) +// TODO(vmpstr): Investigate why this is noisy (crbug.com/310220). +TEST_F(PictureLayerTilingPerfTest, DISABLED_UpdateTilePriorities) { +#else TEST_F(PictureLayerTilingPerfTest, UpdateTilePriorities) { +#endif // defined(OS_ANDROID) gfx::Transform transform; RunUpdateTilePrioritiesStationaryTest("no_transform", transform); RunUpdateTilePrioritiesScrollingTest("no_transform", transform); diff --git a/cc/resources/picture_layer_tiling_set_unittest.cc b/cc/resources/picture_layer_tiling_set_unittest.cc index 231e378fbd..c0d6f0d2ef 100644 --- a/cc/resources/picture_layer_tiling_set_unittest.cc +++ b/cc/resources/picture_layer_tiling_set_unittest.cc @@ -66,7 +66,7 @@ class PictureLayerTilingSetTestWithResources : public testing::Test { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider = - ResourceProvider::Create(output_surface.get(), 0, false); + ResourceProvider::Create(output_surface.get(), NULL, 0, false); FakePictureLayerTilingClient client; client.SetTileSize(gfx::Size(256, 256)); diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc index d1cb0e17e4..9f485b8296 100644 --- a/cc/resources/picture_pile.cc +++ b/cc/resources/picture_pile.cc @@ -13,12 +13,6 @@ #include "cc/resources/picture_pile_impl.h" namespace { -// Maximum number of pictures that can overlap before we collapse them into -// a larger one. -const size_t kMaxOverlapping = 2; -// Maximum percentage area of the base picture another picture in the picture -// list can be. If higher, we destroy the list and recreate from scratch. -const float kResetThreshold = 0.7f; // Layout pixel buffer around the visible layer rect to record. Any base // picture that intersects the visible layer rect expanded by this distance // will be recorded. @@ -49,138 +43,74 @@ bool PicturePile::Update( -kPixelDistanceToRecord, -kPixelDistanceToRecord, -kPixelDistanceToRecord); - bool modified_pile = false; + + bool invalidated = false; for (Region::Iterator i(invalidation); i.has_rect(); i.next()) { gfx::Rect invalidation = i.rect(); // Split this inflated invalidation across tile boundaries and apply it // to all tiles that it touches. for (TilingData::Iterator iter(&tiling_, invalidation); iter; ++iter) { - gfx::Rect tile = - tiling_.TileBoundsWithBorder(iter.index_x(), iter.index_y()); - if (!tile.Intersects(interest_rect)) { - // This invalidation touches a tile outside the interest rect, so - // just remove the entire picture list. - picture_list_map_.erase(iter.index()); - modified_pile = true; - continue; - } + const PictureMapKey& key = iter.index(); - gfx::Rect tile_invalidation = gfx::IntersectRects(invalidation, tile); - if (tile_invalidation.IsEmpty()) - continue; - PictureListMap::iterator find = picture_list_map_.find(iter.index()); - if (find == picture_list_map_.end()) + PictureMap::iterator picture_it = picture_map_.find(key); + if (picture_it == picture_map_.end()) continue; - PictureList& pic_list = find->second; - // Leave empty pic_lists empty in case there are multiple invalidations. - if (!pic_list.empty()) { - // Inflate all recordings from invalidations with a margin so that when - // scaled down to at least min_contents_scale, any final pixel touched - // by an invalidation can be fully rasterized by this picture. - tile_invalidation.Inset(-buffer_pixels(), -buffer_pixels()); - - DCHECK_GE(tile_invalidation.width(), buffer_pixels() * 2 + 1); - DCHECK_GE(tile_invalidation.height(), buffer_pixels() * 2 + 1); - - InvalidateRect(pic_list, tile_invalidation); - modified_pile = true; - } - } - } - int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); - - // Walk through all pictures in the rect of interest and record. - for (TilingData::Iterator iter(&tiling_, interest_rect); iter; ++iter) { - // Create a picture in this list if it doesn't exist. - PictureList& pic_list = picture_list_map_[iter.index()]; - if (pic_list.empty()) { - // Inflate the base picture with a margin, similar to invalidations, so - // that when scaled down to at least min_contents_scale, the enclosed - // rect still includes content all the way to the edge of the layer. - gfx::Rect tile = tiling_.TileBounds(iter.index_x(), iter.index_y()); - tile.Inset( - -buffer_pixels(), - -buffer_pixels(), - -buffer_pixels(), - -buffer_pixels()); - scoped_refptr<Picture> base_picture = Picture::Create(tile); - pic_list.push_back(base_picture); + invalidated = picture_it->second.Invalidate() || invalidated; } + } - for (PictureList::iterator pic = pic_list.begin(); - pic != pic_list.end(); ++pic) { - if (!(*pic)->HasRecording()) { - modified_pile = true; - base::TimeDelta best_duration = base::TimeDelta::FromInternalValue( - std::numeric_limits<int64>::max()); - for (int i = 0; i < repeat_count; i++) { - base::TimeTicks start_time = stats_instrumentation->StartRecording(); - (*pic)->Record(painter, tile_grid_info_); - base::TimeDelta duration = - stats_instrumentation->EndRecording(start_time); - best_duration = std::min(duration, best_duration); - } - int recorded_pixel_count = - (*pic)->LayerRect().width() * (*pic)->LayerRect().height(); - stats_instrumentation->AddRecord(best_duration, recorded_pixel_count); - (*pic)->GatherPixelRefs(tile_grid_info_); - (*pic)->CloneForDrawing(num_raster_threads_); - } + gfx::Rect record_rect; + for (TilingData::Iterator it(&tiling_, interest_rect); + it; ++it) { + const PictureMapKey& key = it.index(); + const PictureInfo& info = picture_map_[key]; + if (!info.picture.get()) { + gfx::Rect tile = PaddedRect(key); + record_rect.Union(tile); } } - UpdateRecordedRegion(); - - return modified_pile; -} - -class FullyContainedPredicate { - public: - explicit FullyContainedPredicate(gfx::Rect rect) : layer_rect_(rect) {} - bool operator()(const scoped_refptr<Picture>& picture) { - return picture->LayerRect().IsEmpty() || - layer_rect_.Contains(picture->LayerRect()); - } - gfx::Rect layer_rect_; -}; - -void PicturePile::InvalidateRect( - PictureList& picture_list, - gfx::Rect invalidation) { - DCHECK(!picture_list.empty()); - DCHECK(!invalidation.IsEmpty()); - - std::vector<PictureList::iterator> overlaps; - for (PictureList::iterator i = picture_list.begin(); - i != picture_list.end(); ++i) { - if ((*i)->LayerRect().Contains(invalidation) && !(*i)->HasRecording()) - return; - if ((*i)->LayerRect().Intersects(invalidation) && i != picture_list.begin()) - overlaps.push_back(i); + if (record_rect.IsEmpty()) { + if (invalidated) + UpdateRecordedRegion(); + return invalidated; } - gfx::Rect picture_rect = invalidation; - if (overlaps.size() >= kMaxOverlapping) { - for (size_t j = 0; j < overlaps.size(); j++) - picture_rect.Union((*overlaps[j])->LayerRect()); + int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); + scoped_refptr<Picture> picture = Picture::Create(record_rect); + + { + base::TimeDelta best_duration = base::TimeDelta::FromInternalValue( + std::numeric_limits<int64>::max()); + for (int i = 0; i < repeat_count; i++) { + base::TimeTicks start_time = stats_instrumentation->StartRecording(); + picture->Record(painter, tile_grid_info_); + base::TimeDelta duration = + stats_instrumentation->EndRecording(start_time); + best_duration = std::min(duration, best_duration); + } + int recorded_pixel_count = + picture->LayerRect().width() * picture->LayerRect().height(); + stats_instrumentation->AddRecord(best_duration, recorded_pixel_count); + if (num_raster_threads_ > 1) + picture->GatherPixelRefs(tile_grid_info_); + picture->CloneForDrawing(num_raster_threads_); } - Picture* base_picture = picture_list.front().get(); - int max_pixels = kResetThreshold * base_picture->LayerRect().size().GetArea(); - if (picture_rect.size().GetArea() > max_pixels) { - // This picture list will be entirely recreated, so clear it. - picture_list.clear(); - return; + for (TilingData::Iterator it(&tiling_, record_rect); + it; ++it) { + const PictureMapKey& key = it.index(); + gfx::Rect tile = PaddedRect(key); + if (record_rect.Contains(tile)) { + PictureInfo& info = picture_map_[key]; + info.picture = picture; + } } - FullyContainedPredicate pred(picture_rect); - picture_list.erase(std::remove_if(picture_list.begin(), - picture_list.end(), - pred), - picture_list.end()); - picture_list.push_back(Picture::Create(picture_rect)); + UpdateRecordedRegion(); + return true; } } // namespace cc diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h index 7830a9e62c..90fc015ca9 100644 --- a/cc/resources/picture_pile.h +++ b/cc/resources/picture_pile.h @@ -46,12 +46,6 @@ class CC_EXPORT PicturePile : public PicturePileBase { private: friend class PicturePileImpl; - // Add an invalidation to this picture list. If the list needs to be - // entirely recreated, leave it empty. Do not call this on an empty list. - void InvalidateRect( - PictureList& picture_list, - gfx::Rect invalidation); - DISALLOW_COPY_AND_ASSIGN(PicturePile); }; diff --git a/cc/resources/picture_pile_base.cc b/cc/resources/picture_pile_base.cc index 0352d30816..8633a58165 100644 --- a/cc/resources/picture_pile_base.cc +++ b/cc/resources/picture_pile_base.cc @@ -5,6 +5,7 @@ #include "cc/resources/picture_pile_base.h" #include <algorithm> +#include <set> #include <vector> #include "base/logging.h" @@ -17,7 +18,7 @@ namespace { // Dimensions of the tiles in this picture pile as well as the dimensions of // the base picture in each tile. -const int kBasePictureSize = 3000; +const int kBasePictureSize = 512; const int kTileGridBorderPixels = 1; } @@ -37,7 +38,7 @@ PicturePileBase::PicturePileBase() } PicturePileBase::PicturePileBase(const PicturePileBase* other) - : picture_list_map_(other->picture_list_map_), + : picture_map_(other->picture_map_), tiling_(other->tiling_), recorded_region_(other->recorded_region_), min_contents_scale_(other->min_contents_scale_), @@ -62,16 +63,10 @@ PicturePileBase::PicturePileBase( other->slow_down_raster_scale_factor_for_debug_), show_debug_picture_borders_(other->show_debug_picture_borders_), num_raster_threads_(other->num_raster_threads_) { - const PictureListMap& other_pic_list_map = other->picture_list_map_; - for (PictureListMap::const_iterator map_iter = other_pic_list_map.begin(); - map_iter != other_pic_list_map.end(); ++map_iter) { - PictureList& pic_list = picture_list_map_[map_iter->first]; - const PictureList& other_pic_list = map_iter->second; - for (PictureList::const_iterator pic_iter = other_pic_list.begin(); - pic_iter != other_pic_list.end(); ++pic_iter) { - pic_list.push_back( - (*pic_iter)->GetCloneForDrawingOnThread(thread_index)); - } + for (PictureMap::const_iterator it = other->picture_map_.begin(); + it != other->picture_map_.end(); + ++it) { + picture_map_[it->first] = it->second.CloneForThread(thread_index); } } @@ -86,20 +81,22 @@ void PicturePileBase::Resize(gfx::Size new_size) { tiling_.SetTotalSize(new_size); // Find all tiles that contain any pixels outside the new size. - std::vector<PictureListMapKey> to_erase; + std::vector<PictureMapKey> to_erase; int min_toss_x = tiling_.FirstBorderTileXIndexFromSrcCoord( std::min(old_size.width(), new_size.width())); int min_toss_y = tiling_.FirstBorderTileYIndexFromSrcCoord( std::min(old_size.height(), new_size.height())); - for (PictureListMap::iterator iter = picture_list_map_.begin(); - iter != picture_list_map_.end(); ++iter) { - if (iter->first.first < min_toss_x && iter->first.second < min_toss_y) + for (PictureMap::const_iterator it = picture_map_.begin(); + it != picture_map_.end(); + ++it) { + const PictureMapKey& key = it->first; + if (key.first < min_toss_x && key.second < min_toss_y) continue; - to_erase.push_back(iter->first); + to_erase.push_back(key); } for (size_t i = 0; i < to_erase.size(); ++i) - picture_list_map_.erase(to_erase[i]); + picture_map_.erase(to_erase[i]); } void PicturePileBase::SetMinContentsScale(float min_contents_scale) { @@ -147,25 +144,26 @@ void PicturePileBase::SetBufferPixels(int new_buffer_pixels) { } void PicturePileBase::Clear() { - picture_list_map_.clear(); + picture_map_.clear(); } void PicturePileBase::UpdateRecordedRegion() { recorded_region_.Clear(); - for (PictureListMap::iterator it = picture_list_map_.begin(); - it != picture_list_map_.end(); ++it) { - const PictureListMapKey& key = it->first; - recorded_region_.Union(tile_bounds(key.first, key.second)); + for (PictureMap::const_iterator it = picture_map_.begin(); + it != picture_map_.end(); + ++it) { + if (it->second.picture.get()) { + const PictureMapKey& key = it->first; + recorded_region_.Union(tile_bounds(key.first, key.second)); + } } } bool PicturePileBase::HasRecordingAt(int x, int y) { - PictureListMap::iterator found = - picture_list_map_.find(PictureListMapKey(x, y)); - if (found == picture_list_map_.end()) + PictureMap::const_iterator found = picture_map_.find(PictureMapKey(x, y)); + if (found == picture_map_.end()) return false; - DCHECK(!found->second.empty()); - return true; + return !!found->second.picture.get(); } bool PicturePileBase::CanRaster(float contents_scale, gfx::Rect content_rect) { @@ -177,25 +175,49 @@ bool PicturePileBase::CanRaster(float contents_scale, gfx::Rect content_rect) { return recorded_region_.Contains(layer_rect); } +gfx::Rect PicturePileBase::PaddedRect(const PictureMapKey& key) { + gfx::Rect tile = tiling_.TileBounds(key.first, key.second); + tile.Inset( + -buffer_pixels(), -buffer_pixels(), -buffer_pixels(), -buffer_pixels()); + return tile; +} + scoped_ptr<base::Value> PicturePileBase::AsValue() const { scoped_ptr<base::ListValue> pictures(new base::ListValue()); gfx::Rect layer_rect(tiling_.total_size()); + std::set<void*> appended_pictures; for (TilingData::Iterator tile_iter(&tiling_, layer_rect); tile_iter; ++tile_iter) { - PictureListMap::const_iterator map_iter = - picture_list_map_.find(tile_iter.index()); - if (map_iter == picture_list_map_.end()) - continue; - const PictureList& pic_list= map_iter->second; - if (pic_list.empty()) + PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index()); + if (map_iter == picture_map_.end()) continue; - for (PictureList::const_reverse_iterator i = pic_list.rbegin(); - i != pic_list.rend(); ++i) { - Picture* picture = (*i).get(); + + Picture* picture = map_iter->second.picture.get(); + if (picture && (appended_pictures.count(picture) == 0)) { + appended_pictures.insert(picture); pictures->Append(TracedValue::CreateIDRef(picture).release()); } } return pictures.PassAs<base::Value>(); } +PicturePileBase::PictureInfo::PictureInfo() {} + +PicturePileBase::PictureInfo::~PictureInfo() {} + +bool PicturePileBase::PictureInfo::Invalidate() { + if (!picture.get()) + return false; + picture = NULL; + return true; +} + +PicturePileBase::PictureInfo PicturePileBase::PictureInfo::CloneForThread( + int thread_index) const { + PictureInfo info = *this; + if (picture.get()) + info.picture = picture->GetCloneForDrawingOnThread(thread_index); + return info; +} + } // namespace cc diff --git a/cc/resources/picture_pile_base.h b/cc/resources/picture_pile_base.h index fdb593fa81..0fa63f41f7 100644 --- a/cc/resources/picture_pile_base.h +++ b/cc/resources/picture_pile_base.h @@ -47,19 +47,30 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> { scoped_ptr<base::Value> AsValue() const; protected: + struct CC_EXPORT PictureInfo { + PictureInfo(); + ~PictureInfo(); + + bool Invalidate(); + PictureInfo CloneForThread(int thread_index) const; + + scoped_refptr<Picture> picture; + }; + + typedef std::pair<int, int> PictureMapKey; + typedef base::hash_map<PictureMapKey, PictureInfo> PictureMap; + virtual ~PicturePileBase(); int num_raster_threads() { return num_raster_threads_; } int buffer_pixels() const { return tiling_.border_texels(); } void Clear(); - typedef std::pair<int, int> PictureListMapKey; - typedef std::list<scoped_refptr<Picture> > PictureList; - typedef base::hash_map<PictureListMapKey, PictureList> PictureListMap; + gfx::Rect PaddedRect(const PictureMapKey& key); - // A picture pile is a tiled set of picture lists. The picture list map - // is a map of tile indices to picture lists. - PictureListMap picture_list_map_; + // A picture pile is a tiled set of pictures. The picture map is a map of tile + // indices to picture infos. + PictureMap picture_map_; TilingData tiling_; Region recorded_region_; float min_contents_scale_; diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc index 95b333c3d6..3d0f5ecd77 100644 --- a/cc/resources/picture_pile_impl.cc +++ b/cc/resources/picture_pile_impl.cc @@ -142,6 +142,64 @@ void PicturePileImpl::RasterToBitmap( rendering_stats_instrumentation); } +void PicturePileImpl::CoalesceRasters(gfx::Rect canvas_rect, + gfx::Rect content_rect, + float contents_scale, + PictureRegionMap* results) { + DCHECK(results); + // Rasterize the collection of relevant picture piles. + gfx::Rect layer_rect = gfx::ScaleToEnclosingRect( + content_rect, 1.f / contents_scale); + + // Coalesce rasters of the same picture into different rects: + // - Compute the clip of each of the pile chunks, + // - Subtract it from the canvas rect to get difference region + // - Later, use the difference region to subtract each of the comprising + // rects from the canvas. + // Note that in essence, we're trying to mimic clipRegion with intersect op + // that also respects the current canvas transform and clip. In order to use + // the canvas transform, we must stick to clipRect operations (clipRegion + // ignores the transform). Intersect then can be written as subtracting the + // negation of the region we're trying to intersect. Luckily, we know that all + // of the rects will have to fit into |content_rect|, so we can start with + // that and subtract chunk rects to get the region that we need to subtract + // from the canvas. Then, we can use clipRect with difference op to subtract + // each rect in the region. + for (TilingData::Iterator tile_iter(&tiling_, layer_rect); + tile_iter; ++tile_iter) { + PictureMap::iterator map_iter = picture_map_.find(tile_iter.index()); + if (map_iter == picture_map_.end()) + continue; + PictureInfo& info = map_iter->second; + if (!info.picture.get()) + continue; + + // This is intentionally *enclosed* rect, so that the clip is aligned on + // integral post-scale content pixels and does not extend past the edges + // of the picture chunk's layer rect. The min_contents_scale enforces that + // enough buffer pixels have been added such that the enclosed rect + // encompasses all invalidated pixels at any larger scale level. + gfx::Rect chunk_rect = PaddedRect(tile_iter.index()); + gfx::Rect content_clip = + gfx::ScaleToEnclosedRect(chunk_rect, contents_scale); + DCHECK(!content_clip.IsEmpty()) << "Layer rect: " + << info.picture->LayerRect().ToString() + << "Contents scale: " << contents_scale; + content_clip.Intersect(canvas_rect); + + PictureRegionMap::iterator it = results->find(info.picture.get()); + if (it == results->end()) { + Region& region = (*results)[info.picture.get()]; + region = content_rect; + region.Subtract(content_clip); + continue; + } + + Region& region = it->second; + region.Subtract(content_clip); + } +} + void PicturePileImpl::RasterCommon( SkCanvas* canvas, SkDrawPictureCallback* callback, @@ -151,111 +209,74 @@ void PicturePileImpl::RasterCommon( DCHECK(contents_scale >= min_contents_scale_); canvas->translate(-canvas_rect.x(), -canvas_rect.y()); - gfx::SizeF total_content_size = gfx::ScaleSize(tiling_.total_size(), contents_scale); gfx::Rect total_content_rect(gfx::ToCeiledSize(total_content_size)); gfx::Rect content_rect = total_content_rect; content_rect.Intersect(canvas_rect); - // Rasterize the collection of relevant picture piles. - gfx::Rect layer_rect = gfx::ScaleToEnclosingRect( - content_rect, 1.f / contents_scale); - canvas->clipRect(gfx::RectToSkRect(content_rect), SkRegion::kIntersect_Op); - Region unclipped(content_rect); - for (TilingData::Iterator tile_iter(&tiling_, layer_rect); - tile_iter; ++tile_iter) { - PictureListMap::iterator map_iter = - picture_list_map_.find(tile_iter.index()); - if (map_iter == picture_list_map_.end()) - continue; - PictureList& pic_list= map_iter->second; - if (pic_list.empty()) - continue; + PictureRegionMap picture_region_map; + CoalesceRasters( + canvas_rect, content_rect, contents_scale, &picture_region_map); - // Raster through the picture list top down, using clips to make sure that - // pictures on top are not overdrawn by pictures on the bottom. - for (PictureList::reverse_iterator i = pic_list.rbegin(); - i != pic_list.rend(); ++i) { - // This is intentionally *enclosed* rect, so that the clip is aligned on - // integral post-scale content pixels and does not extend past the edges - // of the picture's layer rect. The min_contents_scale enforces that - // enough buffer pixels have been added such that the enclosed rect - // encompasses all invalidated pixels at any larger scale level. - gfx::Rect content_clip = gfx::ScaleToEnclosedRect( - (*i)->LayerRect(), contents_scale); - - DCHECK(!content_clip.IsEmpty()) << - "Layer rect: " << (*i)->LayerRect().ToString() << - "Contents scale: " << contents_scale; - - content_clip.Intersect(canvas_rect); - - if (!unclipped.Intersects(content_clip)) - continue; - - base::TimeDelta best_duration = - base::TimeDelta::FromInternalValue(std::numeric_limits<int64>::max()); - int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); - int rasterized_pixel_count = 0; - - for (int j = 0; j < repeat_count; ++j) { - base::TimeTicks start_time; - if (rendering_stats_instrumentation) - start_time = rendering_stats_instrumentation->StartRecording(); - rasterized_pixel_count = - (*i)->Raster(canvas, callback, content_clip, contents_scale); - if (rendering_stats_instrumentation) { - base::TimeDelta duration = - rendering_stats_instrumentation->EndRecording(start_time); - best_duration = std::min(best_duration, duration); - } - } - if (rendering_stats_instrumentation) { - rendering_stats_instrumentation->AddRaster(best_duration, - rasterized_pixel_count); - } +#ifndef NDEBUG + Region total_clip; +#endif // NDEBUG + + // Iterate the coalesced map and use each picture's region + // to clip the canvas. + for (PictureRegionMap::iterator it = picture_region_map.begin(); + it != picture_region_map.end(); + ++it) { + Picture* picture = it->first; + Region negated_clip_region = it->second; + +#ifndef NDEBUG + Region positive_clip = content_rect; + positive_clip.Subtract(negated_clip_region); + total_clip.Union(positive_clip); +#endif // NDEBUG + + base::TimeDelta best_duration = + base::TimeDelta::FromInternalValue(std::numeric_limits<int64>::max()); + int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); + int rasterized_pixel_count = 0; + + for (int j = 0; j < repeat_count; ++j) { + base::TimeTicks start_time; + if (rendering_stats_instrumentation) + start_time = rendering_stats_instrumentation->StartRecording(); - if (show_debug_picture_borders_) { - gfx::Rect border = gfx::ScaleToEnclosedRect( - (*i)->LayerRect(), contents_scale); - border.Inset(0, 0, 1, 1); - - SkPaint picture_border_paint; - picture_border_paint.setColor(DebugColors::PictureBorderColor()); - canvas->drawLine(border.x(), border.y(), border.right(), border.y(), - picture_border_paint); - canvas->drawLine(border.right(), border.y(), border.right(), - border.bottom(), picture_border_paint); - canvas->drawLine(border.right(), border.bottom(), border.x(), - border.bottom(), picture_border_paint); - canvas->drawLine(border.x(), border.bottom(), border.x(), border.y(), - picture_border_paint); + rasterized_pixel_count = picture->Raster( + canvas, callback, negated_clip_region, contents_scale); + + if (rendering_stats_instrumentation) { + base::TimeDelta duration = + rendering_stats_instrumentation->EndRecording(start_time); + best_duration = std::min(best_duration, duration); } + } - // Don't allow pictures underneath to draw where this picture did. - canvas->clipRect( - gfx::RectToSkRect(content_clip), - SkRegion::kDifference_Op); - unclipped.Subtract(content_clip); + if (rendering_stats_instrumentation) { + rendering_stats_instrumentation->AddRaster(best_duration, + rasterized_pixel_count); } } #ifndef NDEBUG - // Fill the remaining clip with debug color. This allows us to + // Fill the clip with debug color. This allows us to // distinguish between non painted areas and problems with missing // pictures. SkPaint paint; + for (Region::Iterator it(total_clip); it.has_rect(); it.next()) + canvas->clipRect(gfx::RectToSkRect(it.rect()), SkRegion::kDifference_Op); paint.setColor(DebugColors::MissingPictureFillColor()); paint.setXfermodeMode(SkXfermode::kSrc_Mode); canvas->drawPaint(paint); #endif // NDEBUG - - // We should always paint some part of |content_rect|. - DCHECK(!unclipped.Contains(content_rect)); } skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() { @@ -316,14 +337,12 @@ PicturePileImpl::PixelRefIterator::PixelRefIterator( : picture_pile_(picture_pile), layer_rect_(gfx::ScaleToEnclosingRect( content_rect, 1.f / contents_scale)), - tile_iterator_(&picture_pile_->tiling_, layer_rect_), - picture_list_(NULL) { + tile_iterator_(&picture_pile_->tiling_, layer_rect_) { // Early out if there isn't a single tile. if (!tile_iterator_) return; - if (AdvanceToTileWithPictures()) - AdvanceToPictureWithPixelRefs(); + AdvanceToTilePictureWithPixelRefs(); } PicturePileImpl::PixelRefIterator::~PixelRefIterator() { @@ -335,50 +354,39 @@ PicturePileImpl::PixelRefIterator& if (pixel_ref_iterator_) return *this; - ++picture_list_iterator_; - AdvanceToPictureWithPixelRefs(); + ++tile_iterator_; + AdvanceToTilePictureWithPixelRefs(); return *this; } -bool PicturePileImpl::PixelRefIterator::AdvanceToTileWithPictures() { +void PicturePileImpl::PixelRefIterator::AdvanceToTilePictureWithPixelRefs() { for (; tile_iterator_; ++tile_iterator_) { - PictureListMap::const_iterator map_iterator = - picture_pile_->picture_list_map_.find(tile_iterator_.index()); - if (map_iterator != picture_pile_->picture_list_map_.end()) { - picture_list_ = &map_iterator->second; - picture_list_iterator_ = picture_list_->begin(); - return true; - } - } + PictureMap::const_iterator it = + picture_pile_->picture_map_.find(tile_iterator_.index()); + if (it == picture_pile_->picture_map_.end()) + continue; - return false; -} + const Picture* picture = it->second.picture.get(); + if (!picture || (processed_pictures_.count(picture) != 0)) + continue; -void PicturePileImpl::PixelRefIterator::AdvanceToPictureWithPixelRefs() { - DCHECK(tile_iterator_); - do { - for (; - picture_list_iterator_ != picture_list_->end(); - ++picture_list_iterator_) { - pixel_ref_iterator_ = - Picture::PixelRefIterator(layer_rect_, picture_list_iterator_->get()); - if (pixel_ref_iterator_) - return; - } - ++tile_iterator_; - } while (AdvanceToTileWithPictures()); + processed_pictures_.insert(picture); + pixel_ref_iterator_ = Picture::PixelRefIterator(layer_rect_, picture); + if (pixel_ref_iterator_) + break; + } } void PicturePileImpl::DidBeginTracing() { gfx::Rect layer_rect(tiling_.total_size()); - for (PictureListMap::iterator pli = picture_list_map_.begin(); - pli != picture_list_map_.end(); - pli++) { - PictureList& picture_list = (*pli).second; - for (PictureList::iterator picture = picture_list.begin(); - picture != picture_list.end(); - picture++) { - (*picture)->EmitTraceSnapshot(); + std::set<void*> processed_pictures; + for (PictureMap::iterator it = picture_map_.begin(); + it != picture_map_.end(); + ++it) { + Picture* picture = it->second.picture.get(); + if (picture && (processed_pictures.count(picture) == 0)) { + picture->EmitTraceSnapshot(); + processed_pictures.insert(picture); } } } diff --git a/cc/resources/picture_pile_impl.h b/cc/resources/picture_pile_impl.h index ed50bec8b5..66b5f72fc3 100644 --- a/cc/resources/picture_pile_impl.h +++ b/cc/resources/picture_pile_impl.h @@ -7,6 +7,7 @@ #include <list> #include <map> +#include <set> #include <vector> #include "base/time/time.h" @@ -87,15 +88,13 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase { operator bool() const { return pixel_ref_iterator_; } private: - bool AdvanceToTileWithPictures(); - void AdvanceToPictureWithPixelRefs(); + void AdvanceToTilePictureWithPixelRefs(); const PicturePileImpl* picture_pile_; gfx::Rect layer_rect_; TilingData::Iterator tile_iterator_; Picture::PixelRefIterator pixel_ref_iterator_; - const PictureList* picture_list_; - PictureList::const_iterator picture_list_iterator_; + std::set<const void*> processed_pictures_; }; void DidBeginTracing(); @@ -123,6 +122,13 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase { PicturePileImpl(const PicturePileImpl* other, unsigned thread_index); + private: + typedef std::map<Picture*, Region> PictureRegionMap; + void CoalesceRasters(gfx::Rect canvas_rect, + gfx::Rect content_rect, + float contents_scale, + PictureRegionMap* result); + void RasterCommon( SkCanvas* canvas, SkDrawPictureCallback* callback, diff --git a/cc/resources/picture_pile_impl_unittest.cc b/cc/resources/picture_pile_impl_unittest.cc index a986c8846b..c68b185522 100644 --- a/cc/resources/picture_pile_impl_unittest.cc +++ b/cc/resources/picture_pile_impl_unittest.cc @@ -635,85 +635,6 @@ TEST(PicturePileImplTest, PixelRefIteratorLazyRefsBaseNonLazy) { } } -TEST(PicturePileImplTest, PixelRefIteratorMultiplePictures) { - gfx::Size tile_size(256, 256); - gfx::Size layer_bounds(256, 256); - - SkTileGridPicture::TileGridInfo tile_grid_info; - tile_grid_info.fTileInterval = SkISize::Make(256, 256); - tile_grid_info.fMargin.setEmpty(); - tile_grid_info.fOffset.setZero(); - - scoped_refptr<FakePicturePileImpl> pile = - FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - - SkBitmap lazy_bitmap[2][2]; - CreateBitmap(gfx::Size(32, 32), "lazy", &lazy_bitmap[0][0]); - CreateBitmap(gfx::Size(32, 32), "lazy", &lazy_bitmap[0][1]); - CreateBitmap(gfx::Size(32, 32), "lazy", &lazy_bitmap[1][1]); - SkBitmap non_lazy_bitmap; - CreateBitmap(gfx::Size(256, 256), "notlazy", &non_lazy_bitmap); - - // Each bitmap goes into its own picture, the final layout - // has lazy pixel refs in the following regions: - // ||=======|| - // ||x| |x|| - // ||-- --|| - // || |x|| - // ||=======|| - pile->add_draw_bitmap(non_lazy_bitmap, gfx::Point(0, 0)); - pile->RerecordPile(); - - FakeContentLayerClient content_layer_clients[2][2]; - scoped_refptr<Picture> pictures[2][2]; - for (int y = 0; y < 2; ++y) { - for (int x = 0; x < 2; ++x) { - if (x == 0 && y == 1) - continue; - SkPaint paint; - content_layer_clients[y][x].add_draw_bitmap( - lazy_bitmap[y][x], - gfx::Point(x * 128 + 10, y * 128 + 10), paint); - pictures[y][x] = Picture::Create( - gfx::Rect(x * 128 + 10, y * 128 + 10, 64, 64)); - pictures[y][x]->Record( - &content_layer_clients[y][x], - tile_grid_info); - pictures[y][x]->GatherPixelRefs(tile_grid_info); - pile->AddPictureToRecording(0, 0, pictures[y][x]); - } - } - - // These should find only one pixel ref. - { - PicturePileImpl::PixelRefIterator iterator( - gfx::Rect(0, 0, 128, 128), 1.0, pile.get()); - EXPECT_TRUE(iterator); - EXPECT_TRUE(*iterator == lazy_bitmap[0][0].pixelRef()); - EXPECT_FALSE(++iterator); - } - { - PicturePileImpl::PixelRefIterator iterator( - gfx::Rect(128, 0, 128, 128), 1.0, pile.get()); - EXPECT_TRUE(iterator); - EXPECT_TRUE(*iterator == lazy_bitmap[0][1].pixelRef()); - EXPECT_FALSE(++iterator); - } - { - PicturePileImpl::PixelRefIterator iterator( - gfx::Rect(128, 128, 128, 128), 1.0, pile.get()); - EXPECT_TRUE(iterator); - EXPECT_TRUE(*iterator == lazy_bitmap[1][1].pixelRef()); - EXPECT_FALSE(++iterator); - } - // This one should not find any refs - { - PicturePileImpl::PixelRefIterator iterator( - gfx::Rect(0, 128, 128, 128), 1.0, pile.get()); - EXPECT_FALSE(iterator); - } -} - TEST(PicturePileImpl, RasterContentsOpaque) { gfx::Size tile_size(1000, 1000); gfx::Size layer_bounds(3, 5); diff --git a/cc/resources/picture_pile_unittest.cc b/cc/resources/picture_pile_unittest.cc index 1eeb5ad5fe..0c9b2e1194 100644 --- a/cc/resources/picture_pile_unittest.cc +++ b/cc/resources/picture_pile_unittest.cc @@ -16,11 +16,11 @@ class TestPicturePile : public PicturePile { public: using PicturePile::buffer_pixels; - PictureListMap& picture_list_map() { return picture_list_map_; } + PictureMap& picture_map() { return picture_map_; } - typedef PicturePile::PictureList PictureList; - typedef PicturePile::PictureListMapKey PictureListMapKey; - typedef PicturePile::PictureListMap PictureListMap; + typedef PicturePile::PictureInfo PictureInfo; + typedef PicturePile::PictureMapKey PictureMapKey; + typedef PicturePile::PictureMap PictureMap; protected: virtual ~TestPicturePile() {} @@ -60,22 +60,17 @@ TEST(PicturePileTest, SmallInvalidateInflated) { EXPECT_EQ(1, pile->tiling().num_tiles_x()); EXPECT_EQ(1, pile->tiling().num_tiles_y()); - TestPicturePile::PictureList& picture_list = - pile->picture_list_map().find( - TestPicturePile::PictureListMapKey(0, 0))->second; - EXPECT_EQ(2u, picture_list.size()); - for (TestPicturePile::PictureList::iterator it = picture_list.begin(); - it != picture_list.end(); - ++it) { - scoped_refptr<Picture> picture = *it; - gfx::Rect picture_rect = - gfx::ScaleToEnclosedRect(picture->LayerRect(), min_scale); - - // The invalidation in each tile should have been made large enough - // that scaling it never makes a rect smaller than 1 px wide or tall. - EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect " << - picture_rect.ToString(); - } + TestPicturePile::PictureInfo& picture_info = + pile->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second; + // We should have a picture. + EXPECT_TRUE(!!picture_info.picture.get()); + gfx::Rect picture_rect = + gfx::ScaleToEnclosedRect(picture_info.picture->LayerRect(), min_scale); + + // The the picture should be large enough that scaling it never makes a rect + // smaller than 1 px wide or tall. + EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect " << + picture_rect.ToString(); } TEST(PicturePileTest, LargeInvalidateInflated) { @@ -112,24 +107,17 @@ TEST(PicturePileTest, LargeInvalidateInflated) { EXPECT_EQ(1, pile->tiling().num_tiles_x()); EXPECT_EQ(1, pile->tiling().num_tiles_y()); - TestPicturePile::PictureList& picture_list = - pile->picture_list_map().find( - TestPicturePile::PictureListMapKey(0, 0))->second; - EXPECT_EQ(2u, picture_list.size()); + TestPicturePile::PictureInfo& picture_info = + pile->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second; + EXPECT_TRUE(!!picture_info.picture.get()); int expected_inflation = pile->buffer_pixels(); - scoped_refptr<Picture> base_picture = *picture_list.begin(); + scoped_refptr<Picture> base_picture = picture_info.picture; gfx::Rect base_picture_rect(layer_size); base_picture_rect.Inset(-expected_inflation, -expected_inflation); EXPECT_EQ(base_picture_rect.ToString(), base_picture->LayerRect().ToString()); - - scoped_refptr<Picture> picture = *(++picture_list.begin()); - gfx::Rect picture_rect(invalidate_rect); - picture_rect.Inset(-expected_inflation, -expected_inflation); - EXPECT_EQ(picture_rect.ToString(), - picture->LayerRect().ToString()); } TEST(PicturePileTest, InvalidateOnTileBoundaryInflated) { @@ -179,30 +167,13 @@ TEST(PicturePileTest, InvalidateOnTileBoundaryInflated) { for (int i = 0; i < pile->tiling().num_tiles_x(); ++i) { for (int j = 0; j < pile->tiling().num_tiles_y(); ++j) { - // (1, 0) and (1, 1) should be invalidated partially. - bool expect_invalidated = i == 1 && (j == 0 || j == 1); - - TestPicturePile::PictureList& picture_list = - pile->picture_list_map().find( - TestPicturePile::PictureListMapKey(i, j))->second; - if (!expect_invalidated) { - EXPECT_EQ(1u, picture_list.size()) << "For i,j " << i << "," << j; - continue; - } - - EXPECT_EQ(2u, picture_list.size()) << "For i,j " << i << "," << j; - for (TestPicturePile::PictureList::iterator it = picture_list.begin(); - it != picture_list.end(); - ++it) { - scoped_refptr<Picture> picture = *it; - gfx::Rect picture_rect = - gfx::ScaleToEnclosedRect(picture->LayerRect(), min_scale); - - // The invalidation in each tile should have been made large enough - // that scaling it never makes a rect smaller than 1 px wide or tall. - EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect " << - picture_rect.ToString(); - } + TestPicturePile::PictureInfo& picture_info = + pile->picture_map().find( + TestPicturePile::PictureMapKey(i, j))->second; + + // TODO(vmpstr): Fix this to check invalidation frequency instead + // of the picture, since we always have one picture per tile. + EXPECT_TRUE(!!picture_info.picture.get()); } } } diff --git a/cc/resources/pixel_buffer_raster_worker_pool.cc b/cc/resources/pixel_buffer_raster_worker_pool.cc index a555e58154..edd7d6c99d 100644 --- a/cc/resources/pixel_buffer_raster_worker_pool.cc +++ b/cc/resources/pixel_buffer_raster_worker_pool.cc @@ -212,7 +212,7 @@ void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) { check_for_completed_raster_tasks_pending_ = false; ScheduleCheckForCompletedRasterTasks(); - TRACE_EVENT_ASYNC_STEP1( + TRACE_EVENT_ASYNC_STEP_INTO1( "cc", "ScheduledTasks", this, StateName(), "state", TracedValue::FromValue(StateAsValue().release())); } @@ -397,7 +397,7 @@ void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() { if (PendingRasterTaskCount()) ScheduleMoreTasks(); - TRACE_EVENT_ASYNC_STEP1( + TRACE_EVENT_ASYNC_STEP_INTO1( "cc", "ScheduledTasks", this, StateName(), "state", TracedValue::FromValue(StateAsValue().release())); diff --git a/cc/resources/prioritized_resource.cc b/cc/resources/prioritized_resource.cc index 313b275a3a..8a7874d05b 100644 --- a/cc/resources/prioritized_resource.cc +++ b/cc/resources/prioritized_resource.cc @@ -124,6 +124,7 @@ PrioritizedResource::Backing::Backing(unsigned id, priority_at_last_priority_update_(PriorityCalculator::LowestPriority()), was_above_priority_cutoff_at_last_priority_update_(false), in_drawing_impl_tree_(false), + in_parent_compositor_(false), #ifdef NDEBUG resource_has_been_deleted_(false) {} #else @@ -157,7 +158,7 @@ bool PrioritizedResource::Backing::ResourceHasBeenDeleted() const { bool PrioritizedResource::Backing::CanBeRecycled() const { DCHECK(!proxy() || proxy()->IsImplThread()); return !was_above_priority_cutoff_at_last_priority_update_ && - !in_drawing_impl_tree_; + !in_drawing_impl_tree_ && !in_parent_compositor_; } void PrioritizedResource::Backing::UpdatePriority() { @@ -173,10 +174,12 @@ void PrioritizedResource::Backing::UpdatePriority() { } } -void PrioritizedResource::Backing::UpdateInDrawingImplTree() { +void PrioritizedResource::Backing::UpdateState( + ResourceProvider* resource_provider) { DCHECK(!proxy() || (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked())); in_drawing_impl_tree_ = !!owner(); + in_parent_compositor_ = resource_provider->InUseByConsumer(id()); if (!in_drawing_impl_tree_) { DCHECK_EQ(priority_at_last_priority_update_, PriorityCalculator::LowestPriority()); diff --git a/cc/resources/prioritized_resource.h b/cc/resources/prioritized_resource.h index a3d5d89cf6..bdd906d382 100644 --- a/cc/resources/prioritized_resource.h +++ b/cc/resources/prioritized_resource.h @@ -111,7 +111,7 @@ class CC_EXPORT PrioritizedResource { ResourceFormat format); ~Backing(); void UpdatePriority(); - void UpdateInDrawingImplTree(); + void UpdateState(ResourceProvider* resource_provider); PrioritizedResource* owner() { return owner_; } bool CanBeRecycled() const; @@ -122,6 +122,7 @@ class CC_EXPORT PrioritizedResource { return was_above_priority_cutoff_at_last_priority_update_; } bool in_drawing_impl_tree() const { return in_drawing_impl_tree_; } + bool in_parent_compositor() const { return in_parent_compositor_; } void DeleteResource(ResourceProvider* resource_provider); bool ResourceHasBeenDeleted() const; @@ -137,6 +138,8 @@ class CC_EXPORT PrioritizedResource { // Set if this is currently-drawing impl tree. bool in_drawing_impl_tree_; + // Set if this is in the parent compositor. + bool in_parent_compositor_; bool resource_has_been_deleted_; diff --git a/cc/resources/prioritized_resource_manager.cc b/cc/resources/prioritized_resource_manager.cc index 4743b9aa3d..ece04b1105 100644 --- a/cc/resources/prioritized_resource_manager.cc +++ b/cc/resources/prioritized_resource_manager.cc @@ -160,7 +160,8 @@ void PrioritizedResourceManager::PushTexturePrioritiesToBackings() { memory_visible_and_nearby_bytes_; } -void PrioritizedResourceManager::UpdateBackingsInDrawingImplTree() { +void PrioritizedResourceManager::UpdateBackingsState( + ResourceProvider* resource_provider) { TRACE_EVENT0("cc", "PrioritizedResourceManager::UpdateBackingsInDrawingImplTree"); DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked()); @@ -169,7 +170,7 @@ void PrioritizedResourceManager::UpdateBackingsInDrawingImplTree() { for (BackingList::iterator it = backings_.begin(); it != backings_.end(); ++it) { PrioritizedResource::Backing* backing = (*it); - backing->UpdateInDrawingImplTree(); + backing->UpdateState(resource_provider); } SortBackings(); AssertInvariants(); @@ -320,8 +321,7 @@ void PrioritizedResourceManager::ReduceWastedMemory( ++it) { if ((*it)->owner()) break; - if (resource_provider->InUseByConsumer((*it)->id()) && - !resource_provider->IsLost((*it)->id())) + if ((*it)->in_parent_compositor()) continue; wasted_memory += (*it)->bytes(); } @@ -380,18 +380,6 @@ bool PrioritizedResourceManager::ReduceMemoryOnImplThread( resource_provider); } -void PrioritizedResourceManager::ReduceWastedMemoryOnImplThread( - ResourceProvider* resource_provider) { - DCHECK(proxy_->IsImplThread()); - DCHECK(resource_provider); - // If we are in the process of uploading a new frame then the backings at the - // very end of the list are not sorted by priority. Sort them before doing the - // eviction. - if (backings_tail_not_sorted_) - SortBackings(); - ReduceWastedMemory(resource_provider); -} - void PrioritizedResourceManager::UnlinkAndClearEvictedBackings() { DCHECK(proxy_->IsMainThread()); base::AutoLock scoped_lock(evicted_backings_lock_); diff --git a/cc/resources/prioritized_resource_manager.h b/cc/resources/prioritized_resource_manager.h index 07cc7cf39a..8a7c275ee7 100644 --- a/cc/resources/prioritized_resource_manager.h +++ b/cc/resources/prioritized_resource_manager.h @@ -96,10 +96,6 @@ class CC_EXPORT PrioritizedResourceManager { int priority_cutoff, ResourceProvider* resource_provider); - // Delete contents textures' backing resources that can be recycled. This - // may be called on the impl thread while the main thread is running. - void ReduceWastedMemoryOnImplThread(ResourceProvider* resource_provider); - // Returns true if there exist any textures that are linked to backings that // have had their resources evicted. Only when we commit a tree that has no // textures linked to evicted backings may we allow drawing. After an @@ -129,7 +125,7 @@ class CC_EXPORT PrioritizedResourceManager { void PushTexturePrioritiesToBackings(); // Mark all textures' backings as being in the drawing impl tree. - void UpdateBackingsInDrawingImplTree(); + void UpdateBackingsState(ResourceProvider* resource_provider); const Proxy* ProxyForDebug() const; @@ -159,6 +155,10 @@ class CC_EXPORT PrioritizedResourceManager { // Make textures that can be recycled appear first if (a->CanBeRecycled() != b->CanBeRecycled()) return (a->CanBeRecycled() > b->CanBeRecycled()); + // Put textures in the parent compositor last since they can't be + // freed when they are evicted anyhow. + if (a->in_parent_compositor() != b->in_parent_compositor()) + return (a->in_parent_compositor() < b->in_parent_compositor()); // Then sort by being above or below the priority cutoff. if (a->was_above_priority_cutoff_at_last_priority_update() != b->was_above_priority_cutoff_at_last_priority_update()) diff --git a/cc/resources/prioritized_resource_unittest.cc b/cc/resources/prioritized_resource_unittest.cc index fb71533101..82178c2750 100644 --- a/cc/resources/prioritized_resource_unittest.cc +++ b/cc/resources/prioritized_resource_unittest.cc @@ -4,6 +4,8 @@ #include "cc/resources/prioritized_resource.h" +#include <vector> + #include "cc/resources/prioritized_resource_manager.h" #include "cc/resources/resource.h" #include "cc/test/fake_output_surface.h" @@ -24,7 +26,7 @@ class PrioritizedResourceTest : public testing::Test { DebugScopedSetImplThread impl_thread(&proxy_); CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = - cc::ResourceProvider::Create(output_surface_.get(), 0, false); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false); } virtual ~PrioritizedResourceTest() { @@ -51,7 +53,7 @@ class PrioritizedResourceTest : public testing::Test { texture->RequestLate(); ResourceManagerAssertInvariants(texture->resource_manager()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); bool success = texture->can_acquire_backing_texture(); if (success) texture->AcquireBackingTexture(ResourceProvider()); @@ -67,7 +69,7 @@ class PrioritizedResourceTest : public testing::Test { void ResourceManagerUpdateBackingsPriorities( PrioritizedResourceManager* resource_manager) { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->PushTexturePrioritiesToBackings(); } @@ -77,7 +79,7 @@ class PrioritizedResourceTest : public testing::Test { PrioritizedResourceManager* resource_manager) { #ifndef NDEBUG DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->AssertInvariants(); #endif } @@ -91,12 +93,23 @@ class PrioritizedResourceTest : public testing::Test { return resource_manager->evicted_backings_.size(); } + std::vector<unsigned> BackingResources( + PrioritizedResourceManager* resource_manager) { + std::vector<unsigned> resources; + for (PrioritizedResourceManager::BackingList::iterator it = + resource_manager->backings_.begin(); + it != resource_manager->backings_.end(); + ++it) + resources.push_back((*it)->id()); + return resources; + } + protected: FakeProxy proxy_; const gfx::Size texture_size_; const ResourceFormat texture_format_; FakeOutputSurfaceClient output_surface_client_; - scoped_ptr<OutputSurface> output_surface_; + scoped_ptr<cc::OutputSurface> output_surface_; scoped_ptr<cc::ResourceProvider> resource_provider_; }; @@ -144,7 +157,7 @@ TEST_F(PrioritizedResourceTest, RequestTextureExceedingMaxLimit) { resource_manager->MaxMemoryNeededBytes()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -168,7 +181,7 @@ TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) { ValidateTexture(textures[i].get(), false); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ReduceMemory(ResourceProvider()); } @@ -183,7 +196,7 @@ TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) { EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 5); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ReduceMemory(ResourceProvider()); } @@ -200,7 +213,7 @@ TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) { EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ReduceMemory(ResourceProvider()); } @@ -211,7 +224,7 @@ TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) { resource_manager->MaxMemoryNeededBytes()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -249,7 +262,7 @@ TEST_F(PrioritizedResourceTest, ReduceWastedMemory) { } { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ReduceMemory(ResourceProvider()); } @@ -261,7 +274,8 @@ TEST_F(PrioritizedResourceTest, ReduceWastedMemory) { PrioritizeTexturesAndBackings(resource_manager.get()); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->UpdateBackingsState(ResourceProvider()); resource_manager->ReduceWastedMemory(ResourceProvider()); } EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); @@ -273,13 +287,14 @@ TEST_F(PrioritizedResourceTest, ReduceWastedMemory) { PrioritizeTexturesAndBackings(resource_manager.get()); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->UpdateBackingsState(ResourceProvider()); resource_manager->ReduceWastedMemory(ResourceProvider()); } EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -339,7 +354,8 @@ TEST_F(PrioritizedResourceTest, InUseNotWastedMemory) { PrioritizeTexturesAndBackings(resource_manager.get()); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->UpdateBackingsState(ResourceProvider()); resource_manager->ReduceWastedMemory(ResourceProvider()); } EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); @@ -351,13 +367,14 @@ TEST_F(PrioritizedResourceTest, InUseNotWastedMemory) { resource_provider_->ReceiveReturnsFromParent(returns); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->UpdateBackingsState(ResourceProvider()); resource_manager->ReduceWastedMemory(ResourceProvider()); } EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -384,7 +401,7 @@ TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) { EXPECT_EQ(ValidateTexture(textures[i].get(), true), i < 6); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ReduceMemory(ResourceProvider()); } EXPECT_EQ(TexturesMemorySize(6), resource_manager->MemoryAboveCutoffBytes()); @@ -398,17 +415,16 @@ TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) { EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ReduceMemory(ResourceProvider()); } EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes()); // Do a one-time eviction for one more texture based on priority cutoff - PrioritizedResourceManager::BackingList evicted_backings; resource_manager->UnlinkAndClearEvictedBackings(); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ReduceMemoryOnImplThread( TexturesMemorySize(8), 104, ResourceProvider()); EXPECT_EQ(0u, EvictedBackingCount(resource_manager.get())); @@ -425,13 +441,149 @@ TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) { EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ReduceMemory(ResourceProvider()); } EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->ClearAllMemory(ResourceProvider()); +} + +TEST_F(PrioritizedResourceTest, NotEvictingTexturesInParent) { + const size_t kMaxTextures = 8; + scoped_ptr<PrioritizedResourceManager> resource_manager = + CreateManager(kMaxTextures); + scoped_ptr<PrioritizedResource> textures[kMaxTextures]; + unsigned texture_resource_ids[kMaxTextures]; + + for (size_t i = 0; i < kMaxTextures; ++i) { + textures[i] = + resource_manager->CreateTexture(texture_size_, texture_format_); + textures[i]->set_request_priority(100 + i); + } + + PrioritizeTexturesAndBackings(resource_manager.get()); + for (size_t i = 0; i < kMaxTextures; ++i) { + EXPECT_TRUE(ValidateTexture(textures[i].get(), true)); + + { + DebugScopedSetImplThreadAndMainThreadBlocked + impl_thread_and_main_thread_blocked(&proxy_); + uint8_t image[4] = {0}; + textures[i]->SetPixels(resource_provider_.get(), + image, + gfx::Rect(1, 1), + gfx::Rect(1, 1), + gfx::Vector2d()); + } + } + { + DebugScopedSetImplThreadAndMainThreadBlocked + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->ReduceMemory(ResourceProvider()); + } + EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes()); + + for (size_t i = 0; i < 8; ++i) + texture_resource_ids[i] = textures[i]->resource_id(); + + // Evict four textures. It will be the last four. + { + DebugScopedSetImplThreadAndMainThreadBlocked + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->ReduceMemoryOnImplThread( + TexturesMemorySize(4), 200, ResourceProvider()); + + EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get())); + + // The last four backings are evicted. + std::vector<unsigned> remaining = BackingResources(resource_manager.get()); + EXPECT_TRUE(std::find(remaining.begin(), + remaining.end(), + texture_resource_ids[0]) != remaining.end()); + EXPECT_TRUE(std::find(remaining.begin(), + remaining.end(), + texture_resource_ids[1]) != remaining.end()); + EXPECT_TRUE(std::find(remaining.begin(), + remaining.end(), + texture_resource_ids[2]) != remaining.end()); + EXPECT_TRUE(std::find(remaining.begin(), + remaining.end(), + texture_resource_ids[3]) != remaining.end()); + } + resource_manager->UnlinkAndClearEvictedBackings(); + EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes()); + + // Re-allocate the the texture after the eviction. + PrioritizeTexturesAndBackings(resource_manager.get()); + for (size_t i = 0; i < kMaxTextures; ++i) { + EXPECT_TRUE(ValidateTexture(textures[i].get(), true)); + + { + DebugScopedSetImplThreadAndMainThreadBlocked + impl_thread_and_main_thread_blocked(&proxy_); + uint8_t image[4] = {0}; + textures[i]->SetPixels(resource_provider_.get(), + image, + gfx::Rect(1, 1), + gfx::Rect(1, 1), + gfx::Vector2d()); + } + } + { + DebugScopedSetImplThreadAndMainThreadBlocked + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->ReduceMemory(ResourceProvider()); + } + EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes()); + + // Send the last two of the textures to a parent compositor. + ResourceProvider::ResourceIdArray to_send; + TransferableResourceArray transferable; + for (size_t i = 6; i < 8; ++i) + to_send.push_back(textures[i]->resource_id()); + resource_provider_->PrepareSendToParent(to_send, &transferable); + + for (size_t i = 0; i < 8; ++i) + texture_resource_ids[i] = textures[i]->resource_id(); + + // Drop all the textures. Now we have backings that can be recycled. + for (size_t i = 0; i < 8; ++i) + textures[0].reset(); + PrioritizeTexturesAndBackings(resource_manager.get()); + + // The next commit finishes. + { + DebugScopedSetImplThreadAndMainThreadBlocked + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->UpdateBackingsState(ResourceProvider()); + } + + // Evict four textures. It would be the last four again, except that 2 of them + // are sent to the parent, so they are evicted last. + { + DebugScopedSetImplThreadAndMainThreadBlocked + impl_thread_and_main_thread_blocked(&proxy_); + resource_manager->ReduceMemoryOnImplThread( + TexturesMemorySize(4), 200, ResourceProvider()); + + EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get())); + // The last 2 backings remain this time. + std::vector<unsigned> remaining = BackingResources(resource_manager.get()); + EXPECT_TRUE(std::find(remaining.begin(), + remaining.end(), + texture_resource_ids[6]) != remaining.end()); + EXPECT_TRUE(std::find(remaining.begin(), + remaining.end(), + texture_resource_ids[7]) != remaining.end()); + } + resource_manager->UnlinkAndClearEvictedBackings(); + EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes()); + + DebugScopedSetImplThreadAndMainThreadBlocked + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -494,7 +646,7 @@ TEST_F(PrioritizedResourceTest, ResourceManagerPartialUpdateTextures) { EXPECT_FALSE(textures[3]->have_backing_texture()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -539,7 +691,7 @@ TEST_F(PrioritizedResourceTest, ResourceManagerPrioritiesAreEqual) { resource_manager->MemoryAboveCutoffBytes()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -559,7 +711,7 @@ TEST_F(PrioritizedResourceTest, ResourceManagerDestroyedFirst) { EXPECT_TRUE(texture->have_backing_texture()); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } resource_manager.reset(); @@ -589,7 +741,7 @@ TEST_F(PrioritizedResourceTest, TextureMovedToNewManager) { texture->SetTextureManager(NULL); { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager_one->ClearAllMemory(ResourceProvider()); } resource_manager_one.reset(); @@ -606,7 +758,7 @@ TEST_F(PrioritizedResourceTest, TextureMovedToNewManager) { EXPECT_TRUE(texture->have_backing_texture()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager_two->ClearAllMemory(ResourceProvider()); } @@ -663,7 +815,7 @@ TEST_F(PrioritizedResourceTest, resource_manager->MaxMemoryNeededBytes()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -711,7 +863,7 @@ TEST_F(PrioritizedResourceTest, resource_manager->MaxMemoryNeededBytes()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -763,7 +915,7 @@ TEST_F(PrioritizedResourceTest, resource_manager->MemoryAboveCutoffBytes()); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -815,7 +967,7 @@ TEST_F(PrioritizedResourceTest, RequestLateBackingsSorting) { EXPECT_FALSE(TextureBackingIsAbovePriorityCutoff(textures[i].get())); DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } @@ -841,7 +993,7 @@ TEST_F(PrioritizedResourceTest, ClearUploadsToEvictedResources) { ResourceUpdateQueue queue; DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); for (size_t i = 0; i < kMaxTextures; ++i) { const ResourceUpdate upload = ResourceUpdate::Create( textures[i].get(), NULL, gfx::Rect(), gfx::Rect(), gfx::Vector2d()); @@ -934,7 +1086,7 @@ TEST_F(PrioritizedResourceTest, UsageStatistics) { // Push priorities to backings, and verify we see the new values. { DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->PushTexturePrioritiesToBackings(); EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes()); EXPECT_EQ(TexturesMemorySize(3), resource_manager->MemoryVisibleBytes()); @@ -943,7 +1095,7 @@ TEST_F(PrioritizedResourceTest, UsageStatistics) { } DebugScopedSetImplThreadAndMainThreadBlocked - impl_thread_and_main_thread_blocked(&proxy_); + impl_thread_and_main_thread_blocked(&proxy_); resource_manager->ClearAllMemory(ResourceProvider()); } diff --git a/cc/resources/prioritized_tile_set_unittest.cc b/cc/resources/prioritized_tile_set_unittest.cc index 37c9cc15a0..4bf27fb88c 100644 --- a/cc/resources/prioritized_tile_set_unittest.cc +++ b/cc/resources/prioritized_tile_set_unittest.cc @@ -57,9 +57,9 @@ class PrioritizedTileSetTest : public testing::Test { CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false).Pass(); - tile_manager_.reset(new FakeTileManager(&tile_manager_client_, - resource_provider_.get())); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false).Pass(); + tile_manager_.reset( + new FakeTileManager(&tile_manager_client_, resource_provider_.get())); picture_pile_ = FakePicturePileImpl::CreatePile(); } diff --git a/cc/resources/raster_worker_pool.cc b/cc/resources/raster_worker_pool.cc index 43bc725d1e..67c548f19d 100644 --- a/cc/resources/raster_worker_pool.cc +++ b/cc/resources/raster_worker_pool.cc @@ -140,6 +140,7 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask { break; case LUMINANCE_8: case RGB_565: + case ETC1: NOTREACHED(); break; } diff --git a/cc/resources/raster_worker_pool_unittest.cc b/cc/resources/raster_worker_pool_unittest.cc index 61cb324f77..023be7907a 100644 --- a/cc/resources/raster_worker_pool_unittest.cc +++ b/cc/resources/raster_worker_pool_unittest.cc @@ -68,7 +68,7 @@ class RasterWorkerPoolTest : public testing::Test, CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false).Pass(); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false).Pass(); } virtual ~RasterWorkerPoolTest() { resource_provider_.reset(); diff --git a/cc/resources/resource.h b/cc/resources/resource.h index 2650a0c8b6..e9dd393a6a 100644 --- a/cc/resources/resource.h +++ b/cc/resources/resource.h @@ -26,7 +26,8 @@ class CC_EXPORT Resource { size_t bytes() const; inline static size_t MemorySizeBytes(gfx::Size size, ResourceFormat format) { - return BytesPerPixel(format) * size.width() * size.height(); + DCHECK_EQ(0u, (BitsPerPixel(format) * size.width() * size.height()) % 8); + return (BitsPerPixel(format) * size.width() * size.height()) / 8; } protected: diff --git a/cc/resources/resource_format.cc b/cc/resources/resource_format.cc index edd7b06a32..35617174cb 100644 --- a/cc/resources/resource_format.cc +++ b/cc/resources/resource_format.cc @@ -13,6 +13,7 @@ SkBitmap::Config SkBitmapConfig(ResourceFormat format) { case RGBA_8888: case BGRA_8888: return SkBitmap::kARGB_8888_Config; + case ETC1: case LUMINANCE_8: case RGB_565: NOTREACHED(); diff --git a/cc/resources/resource_format.h b/cc/resources/resource_format.h index 47f9a50571..54061394ff 100644 --- a/cc/resources/resource_format.h +++ b/cc/resources/resource_format.h @@ -17,7 +17,8 @@ enum ResourceFormat { BGRA_8888, LUMINANCE_8, RGB_565, - RESOURCE_FORMAT_MAX = RGB_565, + ETC1, + RESOURCE_FORMAT_MAX = ETC1, }; SkBitmap::Config SkBitmapConfig(ResourceFormat format); diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index d76fc4b45c..874fe3f641 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc @@ -8,6 +8,7 @@ #include <limits> #include "base/containers/hash_tables.h" +#include "base/debug/trace_event.h" #include "base/stl_util.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -15,6 +16,7 @@ #include "cc/output/gl_renderer.h" // For the GLC() macro. #include "cc/resources/platform_color.h" #include "cc/resources/returned_resource.h" +#include "cc/resources/shared_bitmap_manager.h" #include "cc/resources/transferable_resource.h" #include "cc/scheduler/texture_uploader.h" #include "gpu/GLES2/gl2extchromium.h" @@ -45,6 +47,7 @@ GLenum TextureToStorageFormat(ResourceFormat format) { case RGBA_4444: case LUMINANCE_8: case RGB_565: + case ETC1: NOTREACHED(); break; } @@ -60,6 +63,7 @@ bool IsFormatSupportedForStorage(ResourceFormat format) { case RGBA_4444: case LUMINANCE_8: case RGB_565: + case ETC1: return false; } return false; @@ -118,7 +122,8 @@ ResourceProvider::Resource::Resource() lost(false), hint(TextureUsageAny), type(static_cast<ResourceType>(0)), - format(RGBA_8888) {} + format(RGBA_8888), + shared_bitmap(NULL) {} ResourceProvider::Resource::~Resource() {} @@ -159,11 +164,13 @@ ResourceProvider::Resource::Resource(unsigned texture_id, lost(false), hint(hint), type(GLTexture), - format(format) { + format(format), + shared_bitmap(NULL) { DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT); } ResourceProvider::Resource::Resource(uint8_t* pixels, + SharedBitmap* bitmap, gfx::Size size, GLenum filter, GLint wrap_mode) @@ -196,7 +203,8 @@ ResourceProvider::Resource::Resource(uint8_t* pixels, lost(false), hint(TextureUsageAny), type(Bitmap), - format(RGBA_8888) { + format(RGBA_8888), + shared_bitmap(bitmap) { DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT); } @@ -206,10 +214,12 @@ ResourceProvider::Child::~Child() {} scoped_ptr<ResourceProvider> ResourceProvider::Create( OutputSurface* output_surface, + SharedBitmapManager* shared_bitmap_manager, int highp_threshold_min, bool use_rgba_4444_texture_format) { scoped_ptr<ResourceProvider> resource_provider( new ResourceProvider(output_surface, + shared_bitmap_manager, highp_threshold_min, use_rgba_4444_texture_format)); @@ -311,10 +321,19 @@ ResourceProvider::ResourceId ResourceProvider::CreateGLTexture( ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) { DCHECK(thread_checker_.CalledOnValidThread()); - uint8_t* pixels = new uint8_t[4 * size.GetArea()]; + scoped_ptr<SharedBitmap> bitmap; + if (shared_bitmap_manager_) + bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size); + + uint8_t* pixels; + if (bitmap) + pixels = bitmap->pixels(); + else + pixels = new uint8_t[4 * size.GetArea()]; ResourceId id = next_id_++; - Resource resource(pixels, size, GL_LINEAR, GL_CLAMP_TO_EDGE); + Resource resource( + pixels, bitmap.release(), size, GL_LINEAR, GL_CLAMP_TO_EDGE); resource.allocated = true; resources_[id] = resource; return id; @@ -375,8 +394,16 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( base::SharedMemory* shared_memory = mailbox.shared_memory(); DCHECK(shared_memory->memory()); uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory()); - resource = Resource( - pixels, mailbox.shared_memory_size(), GL_LINEAR, GL_CLAMP_TO_EDGE); + scoped_ptr<SharedBitmap> shared_bitmap; + if (shared_bitmap_manager_) { + shared_bitmap = + shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory); + } + resource = Resource(pixels, + shared_bitmap.release(), + mailbox.shared_memory_size(), + GL_LINEAR, + GL_CLAMP_TO_EDGE); } resource.external = true; resource.allocated = true; @@ -407,8 +434,9 @@ void ResourceProvider::DeleteResource(ResourceId id) { void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it, DeleteStyle style) { + TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal"); Resource* resource = &it->second; - bool lost_resource = lost_output_surface_ || resource->lost; + bool lost_resource = resource->lost; DCHECK(resource->exported_count == 0 || style != Normal); if (style == ForShutdown && resource->exported_count > 0) @@ -438,6 +466,7 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it, if (resource->mailbox.IsValid() && resource->external) { unsigned sync_point = resource->mailbox.sync_point(); if (resource->mailbox.IsTexture()) { + lost_resource |= lost_output_surface_; WebGraphicsContext3D* context3d = Context3d(); DCHECK(context3d); if (resource->gl_id) @@ -450,10 +479,16 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it, if (resource->pixels && shared_memory) { DCHECK(shared_memory->memory() == resource->pixels); resource->pixels = NULL; + delete resource->shared_bitmap; + resource->shared_bitmap = NULL; } } resource->release_callback.Run(sync_point, lost_resource); } + if (resource->shared_bitmap) { + delete resource->shared_bitmap; + resource->pixels = NULL; + } if (resource->pixels) delete[] resource->pixels; if (resource->pixel_buffer) @@ -754,9 +789,11 @@ ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { } ResourceProvider::ResourceProvider(OutputSurface* output_surface, + SharedBitmapManager* shared_bitmap_manager, int highp_threshold_min, bool use_rgba_4444_texture_format) : output_surface_(output_surface), + shared_bitmap_manager_(shared_bitmap_manager), lost_output_surface_(false), highp_threshold_min_(highp_threshold_min), next_id_(1), @@ -803,6 +840,7 @@ bool ResourceProvider::InitializeGL() { use_texture_storage_ext_ = caps.texture_storage; use_shallow_flush_ = caps.shallow_flush; use_texture_usage_hint_ = caps.texture_usage; + use_compressed_texture_etc1_ = caps.texture_format_etc1; texture_uploader_ = TextureUploader::Create(context3d, use_map_sub, use_shallow_flush_); @@ -876,17 +914,15 @@ void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources, TransferableResourceArray* list) { DCHECK(thread_checker_.CalledOnValidThread()); WebGraphicsContext3D* context3d = Context3d(); - if (!context3d || !context3d->makeContextCurrent()) { - // TODO(skaslev): Implement this path for software compositing. - return; - } + if (context3d) + context3d->makeContextCurrent(); bool need_sync_point = false; for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { TransferableResource resource; TransferResource(context3d, *it, &resource); - if (!resource.sync_point) + if (!resource.sync_point && !resource.is_software) need_sync_point = true; ++resources_.find(*it)->second.exported_count; list->push_back(resource); @@ -906,10 +942,8 @@ void ResourceProvider::ReceiveFromChild( int child, const TransferableResourceArray& resources) { DCHECK(thread_checker_.CalledOnValidThread()); WebGraphicsContext3D* context3d = Context3d(); - if (!context3d || !context3d->makeContextCurrent()) { - // TODO(skaslev): Implement this path for software compositing. - return; - } + if (context3d) + context3d->makeContextCurrent(); Child& child_info = children_.find(child)->second; for (TransferableResourceArray::const_iterator it = resources.begin(); it != resources.end(); @@ -920,34 +954,58 @@ void ResourceProvider::ReceiveFromChild( resources_[resource_in_map_it->second].imported_count++; continue; } - unsigned texture_id; - // NOTE: If the parent is a browser and the child a renderer, the parent - // is not supposed to have its context wait, because that could induce - // deadlocks and/or security issues. The caller is responsible for - // waiting asynchronously, and resetting sync_point before calling this. - // However if the parent is a renderer (e.g. browser tag), it may be ok - // (and is simpler) to wait. - if (it->sync_point) - GLC(context3d, context3d->waitSyncPoint(it->sync_point)); - GLC(context3d, texture_id = context3d->createTexture()); - GLC(context3d, context3d->bindTexture(it->target, texture_id)); - GLC(context3d, - context3d->consumeTextureCHROMIUM(it->target, it->mailbox.name)); + + scoped_ptr<SharedBitmap> bitmap; + uint8_t* pixels = NULL; + if (it->is_software) { + if (shared_bitmap_manager_) + bitmap = shared_bitmap_manager_->GetSharedBitmapFromId(it->size, + it->mailbox); + if (bitmap) + pixels = bitmap->pixels(); + } + + if ((!it->is_software && !context3d) || (it->is_software && !pixels)) { + TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid"); + ReturnedResourceArray to_return; + to_return.push_back(it->ToReturnedResource()); + child_info.return_callback.Run(to_return); + continue; + } + ResourceId local_id = next_id_++; - Resource resource(texture_id, - it->size, - it->target, - it->filter, - 0, - GL_CLAMP_TO_EDGE, - TextureUsageAny, - it->format); - resource.mailbox.SetName(it->mailbox); + Resource& resource = resources_[local_id]; + if (it->is_software) { + resource = Resource( + pixels, bitmap.release(), it->size, GL_LINEAR, GL_CLAMP_TO_EDGE); + } else { + unsigned texture_id; + // NOTE: If the parent is a browser and the child a renderer, the parent + // is not supposed to have its context wait, because that could induce + // deadlocks and/or security issues. The caller is responsible for + // waiting asynchronously, and resetting sync_point before calling this. + // However if the parent is a renderer (e.g. browser tag), it may be ok + // (and is simpler) to wait. + if (it->sync_point) + GLC(context3d, context3d->waitSyncPoint(it->sync_point)); + GLC(context3d, texture_id = context3d->createTexture()); + GLC(context3d, context3d->bindTexture(it->target, texture_id)); + GLC(context3d, + context3d->consumeTextureCHROMIUM(it->target, it->mailbox.name)); + resource = Resource(texture_id, + it->size, + it->target, + it->filter, + 0, + GL_CLAMP_TO_EDGE, + TextureUsageAny, + it->format); + resource.mailbox.SetName(it->mailbox); + } resource.child_id = child; // Don't allocate a texture for a child. resource.allocated = true; resource.imported_count = 1; - resources_[local_id] = resource; child_info.parent_to_child_map[local_id] = it->id; child_info.child_to_parent_map[it->id] = local_id; } @@ -997,10 +1055,8 @@ void ResourceProvider::ReceiveReturnsFromParent( const ReturnedResourceArray& resources) { DCHECK(thread_checker_.CalledOnValidThread()); WebGraphicsContext3D* context3d = Context3d(); - if (!context3d || !context3d->makeContextCurrent()) { - // TODO(skaslev): Implement this path for software compositing. - return; - } + if (context3d) + context3d->makeContextCurrent(); int child_id = 0; Child* child_info = NULL; @@ -1043,7 +1099,7 @@ void ResourceProvider::ReceiveReturnsFromParent( if (resource->gl_id) { if (returned.sync_point) GLC(context3d, context3d->waitSyncPoint(returned.sync_point)); - } else { + } else if (!resource->shared_bitmap) { resource->mailbox = TextureMailbox(resource->mailbox.name(), returned.sync_point); } @@ -1096,10 +1152,10 @@ void ResourceProvider::TransferResource(WebGraphicsContext3D* context, resource->filter = source->filter; resource->size = source->size; - // TODO(skaslev) Implement this path for shared memory resources. - DCHECK(!source->mailbox.IsSharedMemory()); - - if (!source->mailbox.IsTexture()) { + if (source->shared_bitmap) { + resource->mailbox = source->shared_bitmap->id(); + resource->is_software = true; + } else if (!source->mailbox.IsValid()) { // This is a resource allocated by the compositor, we need to produce it. // Don't set a sync point, the caller will do it. DCHECK(source->gl_id); @@ -1110,6 +1166,7 @@ void ResourceProvider::TransferResource(WebGraphicsContext3D* context, resource->mailbox.name)); source->mailbox.SetName(resource->mailbox); } else { + DCHECK(source->mailbox.IsTexture()); // 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 = source->mailbox.name(); @@ -1129,10 +1186,8 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild( return; WebGraphicsContext3D* context3d = Context3d(); - if (!context3d || !context3d->makeContextCurrent()) { - // TODO(skaslev): Implement this path for software compositing. - return; - } + if (context3d) + context3d->makeContextCurrent(); ReturnedResourceArray to_return; @@ -1152,7 +1207,8 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild( ResourceId child_id = child_info->parent_to_child_map[local_id]; DCHECK(child_info->child_to_parent_map.count(child_id)); - bool is_lost = resource.lost || lost_output_surface_; + bool is_lost = + resource.lost || (!resource.shared_bitmap && lost_output_surface_); if (resource.exported_count > 0) { if (style != ForShutdown) { // Defer this until we receive the resource back from the parent. @@ -1164,7 +1220,7 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild( is_lost = true; } - if (resource.filter != resource.original_filter) { + if (context3d && resource.filter != resource.original_filter) { DCHECK(resource.target); DCHECK(resource.gl_id); @@ -1182,7 +1238,7 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild( ReturnedResource returned; returned.id = child_id; returned.sync_point = resource.mailbox.sync_point(); - if (!returned.sync_point) + if (!returned.sync_point && !resource.shared_bitmap) need_sync_point = true; returned.count = resource.imported_count; returned.lost = is_lost; @@ -1194,6 +1250,7 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild( DeleteResourceInternal(it, style); } if (need_sync_point) { + DCHECK(context3d); unsigned int sync_point = context3d->insertSyncPoint(); for (size_t i = 0; i < to_return.size(); ++i) { if (!to_return[i].sync_point) @@ -1210,6 +1267,7 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) { DCHECK(!resource->external); DCHECK_EQ(resource->exported_count, 0); DCHECK(!resource->image_id); + DCHECK_NE(ETC1, resource->format); if (resource->type == GLTexture) { WebGraphicsContext3D* context3d = Context3d(); @@ -1219,7 +1277,7 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) { context3d->bindBuffer( GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, resource->gl_pixel_buffer_id); - unsigned bytes_per_pixel = BytesPerPixel(resource->format); + unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8; context3d->bufferData( GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, resource->size.height() * RoundUp(bytes_per_pixel @@ -1542,15 +1600,19 @@ void ResourceProvider::LazyAllocate(Resource* resource) { size.width(), size.height())); } else { - GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, - 0, - GLInternalFormat(format), - size.width(), - size.height(), - 0, - GLDataFormat(format), - GLDataType(format), - NULL)); + // ETC1 does not support preallocation. + if (format != ETC1) { + GLC(context3d, + context3d->texImage2D(GL_TEXTURE_2D, + 0, + GLInternalFormat(format), + size.width(), + size.height(), + 0, + GLDataFormat(format), + GLDataType(format), + NULL)); + } } } @@ -1646,6 +1708,16 @@ int ResourceProvider::GetImageStride(ResourceId id) { return stride; } +base::SharedMemory* ResourceProvider::GetSharedMemory(ResourceId id) { + Resource* resource = GetResource(id); + DCHECK(!resource->external); + DCHECK_EQ(resource->exported_count, 0); + + if (!resource->shared_bitmap) + return NULL; + return resource->shared_bitmap->memory(); +} + GLint ResourceProvider::GetActiveTextureUnit(WebGraphicsContext3D* context) { GLint active_unit = 0; context->getIntegerv(GL_ACTIVE_TEXTURE, &active_unit); diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index b8cb399286..23f1414fa0 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h @@ -39,6 +39,8 @@ class Vector2d; } namespace cc { +class SharedBitmap; +class SharedBitmapManager; class TextureUploader; // This class is not thread-safe and can only be called from the thread it was @@ -59,9 +61,11 @@ class CC_EXPORT ResourceProvider { Bitmap, }; - static scoped_ptr<ResourceProvider> Create(OutputSurface* output_surface, - int highp_threshold_min, - bool use_rgba_4444_texture_format); + static scoped_ptr<ResourceProvider> Create( + OutputSurface* output_surface, + SharedBitmapManager* shared_bitmap_manager, + int highp_threshold_min, + bool use_rgba_4444_texture_format); virtual ~ResourceProvider(); void InitializeSoftware(); @@ -320,6 +324,8 @@ class CC_EXPORT ResourceProvider { // Returns the stride for the image. int GetImageStride(ResourceId id); + base::SharedMemory* GetSharedMemory(ResourceId id); + // For tests only! This prevents detecting uninitialized reads. // Use SetPixels or LockForWrite to allocate implicitly. void AllocateForTesting(ResourceId id); @@ -359,6 +365,7 @@ class CC_EXPORT ResourceProvider { TextureUsageHint hint, ResourceFormat format); Resource(uint8_t* pixels, + SharedBitmap* bitmap, gfx::Size size, GLenum filter, GLint wrap_mode); @@ -398,6 +405,7 @@ class CC_EXPORT ResourceProvider { TextureUsageHint hint; ResourceType type; ResourceFormat format; + SharedBitmap* shared_bitmap; }; typedef base::hash_map<ResourceId, Resource> ResourceMap; @@ -422,6 +430,7 @@ class CC_EXPORT ResourceProvider { } ResourceProvider(OutputSurface* output_surface, + SharedBitmapManager* shared_bitmap_manager, int highp_threshold_min, bool use_rgba_4444_texture_format); @@ -461,6 +470,7 @@ class CC_EXPORT ResourceProvider { WebKit::WebGraphicsContext3D* Context3d() const; OutputSurface* output_surface_; + SharedBitmapManager* shared_bitmap_manager_; bool lost_output_surface_; int highp_threshold_min_; ResourceId next_id_; @@ -472,6 +482,7 @@ class CC_EXPORT ResourceProvider { bool use_texture_storage_ext_; bool use_texture_usage_hint_; bool use_shallow_flush_; + bool use_compressed_texture_etc1_; scoped_ptr<TextureUploader> texture_uploader_; int max_texture_size_; ResourceFormat best_texture_format_; @@ -487,16 +498,17 @@ class CC_EXPORT ResourceProvider { // TODO(epenner): Move these format conversions to resource_format.h // once that builds on mac (npapi.h currently #includes OpenGL.h). -inline unsigned BytesPerPixel(ResourceFormat format) { +inline unsigned BitsPerPixel(ResourceFormat format) { DCHECK_LE(format, RESOURCE_FORMAT_MAX); - static const unsigned format_bytes_per_pixel[RESOURCE_FORMAT_MAX + 1] = { - 4, // RGBA_8888 - 2, // RGBA_4444 - 4, // BGRA_8888 - 1, // LUMINANCE_8 - 2 // RGB_565 + static const unsigned format_bits_per_pixel[RESOURCE_FORMAT_MAX + 1] = { + 32, // RGBA_8888 + 16, // RGBA_4444 + 32, // BGRA_8888 + 8, // LUMINANCE_8 + 16, // RGB_565, + 4 // ETC1 }; - return format_bytes_per_pixel[format]; + return format_bits_per_pixel[format]; } inline GLenum GLDataType(ResourceFormat format) { @@ -506,7 +518,8 @@ inline GLenum GLDataType(ResourceFormat format) { GL_UNSIGNED_SHORT_4_4_4_4, // RGBA_4444 GL_UNSIGNED_BYTE, // BGRA_8888 GL_UNSIGNED_BYTE, // LUMINANCE_8 - GL_UNSIGNED_SHORT_5_6_5 // RGB_565 + GL_UNSIGNED_SHORT_5_6_5, // RGB_565, + GL_UNSIGNED_BYTE // ETC1 }; return format_gl_data_type[format]; } @@ -514,11 +527,12 @@ inline GLenum GLDataType(ResourceFormat format) { inline GLenum GLDataFormat(ResourceFormat format) { DCHECK_LE(format, RESOURCE_FORMAT_MAX); static const unsigned format_gl_data_format[RESOURCE_FORMAT_MAX + 1] = { - GL_RGBA, // RGBA_8888 - GL_RGBA, // RGBA_4444 - GL_BGRA_EXT, // BGRA_8888 - GL_LUMINANCE, // LUMINANCE_8 - GL_RGB // RGB_565 + GL_RGBA, // RGBA_8888 + GL_RGBA, // RGBA_4444 + GL_BGRA_EXT, // BGRA_8888 + GL_LUMINANCE, // LUMINANCE_8 + GL_RGB, // RGB_565 + GL_ETC1_RGB8_OES // ETC1 }; return format_gl_data_format[format]; } diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index 1e2318361b..a0b65234e5 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc @@ -15,6 +15,7 @@ #include "cc/debug/test_web_graphics_context_3d.h" #include "cc/output/output_surface.h" #include "cc/resources/returned_resource.h" +#include "cc/resources/shared_bitmap_manager.h" #include "cc/resources/single_release_callback.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" @@ -44,6 +45,41 @@ namespace { static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {} +static void SharedMemoryReleaseCallback(scoped_ptr<base::SharedMemory> memory, + unsigned sync_point, + bool lost_resource) {} + +static void ReleaseTextureMailbox(unsigned* release_sync_point, + bool* release_lost_resource, + unsigned sync_point, + bool lost_resource) { + *release_sync_point = sync_point; + *release_lost_resource = lost_resource; +} + +static void ReleaseSharedMemoryCallback( + scoped_ptr<base::SharedMemory> shared_memory, + bool* release_called, + unsigned* release_sync_point, + bool* lost_resource_result, + unsigned sync_point, + bool lost_resource) { + *release_called = true; + *release_sync_point = sync_point; + *lost_resource_result = lost_resource; +} + +static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory( + gfx::Size size, + uint32_t value) { + scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory); + CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea())); + uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory()); + CHECK(pixels); + std::fill_n(pixels, size.GetArea(), value); + return shared_memory.Pass(); +} + class TextureStateTrackingContext : public TestWebGraphicsContext3D { public: MOCK_METHOD2(bindTexture, void(WGC3Denum target, WebGLId texture)); @@ -196,8 +232,11 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { CheckTextureIsBound(target); ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); ASSERT_FALSE(level); - ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format); 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); } @@ -205,6 +244,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { virtual void texParameteri(WGC3Denum target, WGC3Denum param, WGC3Dint value) OVERRIDE { CheckTextureIsBound(target); + base::AutoLock lock_for_texture_access(namespace_->lock); scoped_refptr<TestTexture> texture = BoundTexture(target); if (param != GL_TEXTURE_MIN_FILTER) return; @@ -224,6 +264,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { // haven't waited on that sync point. scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture); memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox)); + base::AutoLock lock_for_texture_access(namespace_->lock); pending->texture = BoundTexture(target); pending_produce_textures_.push_back(pending.Pass()); } @@ -231,14 +272,15 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { virtual void consumeTextureCHROMIUM(WGC3Denum target, const WGC3Dbyte* mailbox) OVERRIDE { CheckTextureIsBound(target); + base::AutoLock lock_for_texture_access(namespace_->lock); scoped_refptr<TestTexture> texture = shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_); - base::AutoLock lock(namespace_->lock); namespace_->textures.Replace(BoundTextureId(target), texture); } void GetPixels(gfx::Size size, ResourceFormat format, uint8_t* pixels) { CheckTextureIsBound(GL_TEXTURE_2D); + base::AutoLock lock_for_texture_access(namespace_->lock); scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D); ASSERT_EQ(texture->size, size); ASSERT_EQ(texture->format, format); @@ -247,11 +289,13 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { WGC3Denum GetTextureFilter() { CheckTextureIsBound(GL_TEXTURE_2D); + base::AutoLock lock_for_texture_access(namespace_->lock); return BoundTexture(GL_TEXTURE_2D)->filter; } scoped_refptr<TestTexture> BoundTexture(WGC3Denum target) { - base::AutoLock lock(namespace_->lock); + // The caller is expected to lock the namespace for texture access. + namespace_->lock.AssertAcquired(); return namespace_->textures.TextureForId(BoundTextureId(target)); } @@ -276,6 +320,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { texture_format = BGRA_8888; break; } + base::AutoLock lock_for_texture_access(namespace_->lock); BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format); } @@ -285,6 +330,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { int height, const void* pixels) { CheckTextureIsBound(GL_TEXTURE_2D); + base::AutoLock lock_for_texture_access(namespace_->lock); scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D); ASSERT_TRUE(texture->data.get()); ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width()); @@ -313,6 +359,55 @@ class ResourceProviderContext : public TestWebGraphicsContext3D { PendingProduceTextureList pending_produce_textures_; }; +void FreeSharedBitmap(SharedBitmap* shared_bitmap) { + delete shared_bitmap->memory(); +} + +void IgnoreSharedBitmap(SharedBitmap* shared_bitmap) {} + +class TestSharedBitmapManager : public SharedBitmapManager { + public: + TestSharedBitmapManager() : count_(0) {} + virtual ~TestSharedBitmapManager() {} + + virtual scoped_ptr<SharedBitmap> AllocateSharedBitmap(gfx::Size size) + OVERRIDE { + scoped_ptr<base::SharedMemory> memory(new base::SharedMemory); + memory->CreateAndMapAnonymous(size.GetArea() * 4); + int8 name[64] = { 0 }; + name[0] = count_++; + SharedBitmapId id; + id.SetName(name); + bitmap_map_[id] = memory.get(); + return scoped_ptr<SharedBitmap>( + new SharedBitmap(memory.release(), id, base::Bind(&FreeSharedBitmap))); + } + + virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId( + gfx::Size, + const SharedBitmapId& id) OVERRIDE { + if (bitmap_map_.find(id) == bitmap_map_.end()) + return scoped_ptr<SharedBitmap>(); + return scoped_ptr<SharedBitmap>( + new SharedBitmap(bitmap_map_[id], id, base::Bind(&IgnoreSharedBitmap))); + } + + virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory( + base::SharedMemory* memory) OVERRIDE { + int8 name[64] = { 0 }; + name[0] = count_++; + SharedBitmapId id; + id.SetName(name); + bitmap_map_[id] = memory; + return scoped_ptr<SharedBitmap>( + new SharedBitmap(memory, id, base::Bind(&IgnoreSharedBitmap))); + } + + private: + int count_; + std::map<SharedBitmapId, base::SharedMemory*> bitmap_map_; +}; + void GetResourcePixels(ResourceProvider* resource_provider, ResourceProviderContext* context, ResourceProvider::ResourceId id, @@ -346,7 +441,8 @@ class ResourceProviderTest public: ResourceProviderTest() : shared_data_(ContextSharedData::Create()), - context3d_(NULL) { + context3d_(NULL), + child_context_(NULL) { switch (GetParam()) { case ResourceProvider::GLTexture: { scoped_ptr<ResourceProviderContext> context3d( @@ -358,19 +454,33 @@ class ResourceProviderTest context3d.PassAs<TestWebGraphicsContext3D>()); output_surface_ = FakeOutputSurface::Create3d(context_provider); + + scoped_ptr<ResourceProviderContext> child_context_owned = + ResourceProviderContext::Create(shared_data_.get()); + child_context_ = child_context_owned.get(); + child_output_surface_ = FakeOutputSurface::Create3d( + child_context_owned.PassAs<TestWebGraphicsContext3D>()); break; } case ResourceProvider::Bitmap: output_surface_ = FakeOutputSurface::CreateSoftware( make_scoped_ptr(new SoftwareOutputDevice)); + child_output_surface_ = FakeOutputSurface::CreateSoftware( + make_scoped_ptr(new SoftwareOutputDevice)); break; case ResourceProvider::InvalidType: NOTREACHED(); break; } CHECK(output_surface_->BindToClient(&output_surface_client_)); + CHECK(child_output_surface_->BindToClient(&child_output_surface_client_)); + + shared_bitmap_manager_.reset(new TestSharedBitmapManager()); + resource_provider_ = ResourceProvider::Create( - output_surface_.get(), 0, false); + output_surface_.get(), shared_bitmap_manager_.get(), 0, false); + child_resource_provider_ = ResourceProvider::Create( + child_output_surface_.get(), shared_bitmap_manager_.get(), 0, false); } static void CollectResources(ReturnedResourceArray* array, @@ -391,12 +501,56 @@ class ResourceProviderTest ResourceProviderContext* context() { return context3d_; } + ResourceProvider::ResourceId CreateChildMailbox(unsigned* release_sync_point, + bool* lost_resource, + bool* release_called, + unsigned* sync_point) { + if (GetParam() == ResourceProvider::GLTexture) { + unsigned texture = child_context_->createTexture(); + gpu::Mailbox gpu_mailbox; + child_context_->bindTexture(GL_TEXTURE_2D, texture); + child_context_->genMailboxCHROMIUM(gpu_mailbox.name); + child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name); + *sync_point = child_context_->insertSyncPoint(); + EXPECT_LT(0u, *sync_point); + + scoped_ptr<base::SharedMemory> shared_memory; + scoped_ptr<SingleReleaseCallback> callback = + SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback, + base::Passed(&shared_memory), + release_called, + release_sync_point, + lost_resource)); + return child_resource_provider_->CreateResourceFromTextureMailbox( + TextureMailbox(gpu_mailbox, *sync_point), callback.Pass()); + } else { + gfx::Size size(64, 64); + scoped_ptr<base::SharedMemory> shared_memory( + CreateAndFillSharedMemory(size, 0)); + + base::SharedMemory* shared_memory_ptr = shared_memory.get(); + scoped_ptr<SingleReleaseCallback> callback = + SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback, + base::Passed(&shared_memory), + release_called, + release_sync_point, + lost_resource)); + return child_resource_provider_->CreateResourceFromTextureMailbox( + TextureMailbox(shared_memory_ptr, size), callback.Pass()); + } + } + protected: scoped_ptr<ContextSharedData> shared_data_; ResourceProviderContext* context3d_; + ResourceProviderContext* child_context_; FakeOutputSurfaceClient output_surface_client_; + FakeOutputSurfaceClient child_output_surface_client_; scoped_ptr<OutputSurface> output_surface_; + scoped_ptr<OutputSurface> child_output_surface_; scoped_ptr<ResourceProvider> resource_provider_; + scoped_ptr<ResourceProvider> child_resource_provider_; + scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_; }; void CheckCreateResource(ResourceProvider::ResourceType expected_default_type, @@ -502,50 +656,35 @@ TEST_P(ResourceProviderTest, Upload) { resource_provider_->DeleteResource(id); } -TEST_P(ResourceProviderTest, TransferResources) { - // Resource transfer is only supported with GL textures for now. +TEST_P(ResourceProviderTest, TransferGLResources) { if (GetParam() != ResourceProvider::GLTexture) return; - - scoped_ptr<ResourceProviderContext> child_context_owned( - ResourceProviderContext::Create(shared_data_.get())); - ResourceProviderContext* child_context = child_context_owned.get(); - - FakeOutputSurfaceClient child_output_surface_client; - scoped_ptr<OutputSurface> child_output_surface( - FakeOutputSurface::Create3d( - child_context_owned.PassAs<TestWebGraphicsContext3D>())); - CHECK(child_output_surface->BindToClient(&child_output_surface_client)); - - scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), 0, false)); - gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource( + ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); uint8_t data1[4] = { 1, 2, 3, 4 }; gfx::Rect rect(size); - child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); + child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); - ResourceProvider::ResourceId id2 = child_resource_provider->CreateResource( + ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); uint8_t data2[4] = { 5, 5, 5, 5 }; - child_resource_provider->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); + child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); - WebGLId external_texture_id = child_context->createExternalTexture(); - child_context->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id); + WebGLId external_texture_id = child_context_->createExternalTexture(); + child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id); gpu::Mailbox external_mailbox; - child_context->genMailboxCHROMIUM(external_mailbox.name); - child_context->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES, - external_mailbox.name); - const unsigned external_sync_point = child_context->insertSyncPoint(); + child_context_->genMailboxCHROMIUM(external_mailbox.name); + child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES, + external_mailbox.name); + const unsigned external_sync_point = child_context_->insertSyncPoint(); ResourceProvider::ResourceId id3 = - child_resource_provider->CreateResourceFromTextureMailbox( + child_resource_provider_->CreateResourceFromTextureMailbox( TextureMailbox( external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point), SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback))); @@ -560,8 +699,8 @@ TEST_P(ResourceProviderTest, TransferResources) { resource_ids_to_transfer.push_back(id2); resource_ids_to_transfer.push_back(id3); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); ASSERT_EQ(3u, list.size()); EXPECT_NE(0u, list[0].sync_point); EXPECT_NE(0u, list[1].sync_point); @@ -569,9 +708,9 @@ TEST_P(ResourceProviderTest, TransferResources) { EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2)); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id3)); + 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); resource_provider_->DeclareUsedResourcesFromChild(child_id, resource_ids_to_transfer); @@ -605,17 +744,17 @@ TEST_P(ResourceProviderTest, TransferResources) { ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id1); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); EXPECT_EQ(1u, list.size()); EXPECT_EQ(id1, list[0].id); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target); ReturnedResourceArray returned; TransferableResource::ReturnResources(list, &returned); - child_resource_provider->ReceiveReturnsFromParent(returned); + child_resource_provider_->ReceiveReturnsFromParent(returned); // id1 was exported twice, we returned it only once, it should still be // in-use. - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1)); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); } { EXPECT_EQ(0u, returned_to_child.size()); @@ -632,25 +771,27 @@ TEST_P(ResourceProviderTest, TransferResources) { 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); + 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)); + EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1)); + EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2)); + EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3)); { - ResourceProvider::ScopedReadLockGL lock(child_resource_provider.get(), id1); + ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), + id1); ASSERT_NE(0U, lock.texture_id()); - child_context->bindTexture(GL_TEXTURE_2D, lock.texture_id()); - child_context->GetPixels(size, format, result); + child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id()); + child_context_->GetPixels(size, format, result); EXPECT_EQ(0, memcmp(data1, result, pixel_size)); } { - ResourceProvider::ScopedReadLockGL lock(child_resource_provider.get(), id2); + ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), + id2); ASSERT_NE(0U, lock.texture_id()); - child_context->bindTexture(GL_TEXTURE_2D, lock.texture_id()); - child_context->GetPixels(size, format, result); + child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id()); + child_context_->GetPixels(size, format, result); EXPECT_EQ(0, memcmp(data2, result, pixel_size)); } { @@ -660,8 +801,8 @@ TEST_P(ResourceProviderTest, TransferResources) { resource_ids_to_transfer.push_back(id2); resource_ids_to_transfer.push_back(id3); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &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); @@ -672,9 +813,9 @@ TEST_P(ResourceProviderTest, TransferResources) { EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2)); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id3)); + 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); resource_provider_->DeclareUsedResourcesFromChild(child_id, resource_ids_to_transfer); @@ -695,9 +836,234 @@ TEST_P(ResourceProviderTest, TransferResources) { EXPECT_FALSE(returned_to_child[2].lost); } -TEST_P(ResourceProviderTest, DeleteExportedResources) { - // Resource transfer is only supported with GL textures for now. - if (GetParam() != ResourceProvider::GLTexture) +TEST_P(ResourceProviderTest, TransferSoftwareResources) { + if (GetParam() != ResourceProvider::Bitmap) + return; + + gfx::Size size(1, 1); + ResourceFormat format = RGBA_8888; + size_t pixel_size = TextureSizeBytes(size, format); + ASSERT_EQ(4U, pixel_size); + + ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); + uint8_t data1[4] = { 1, 2, 3, 4 }; + gfx::Rect rect(size); + child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); + + ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); + uint8_t data2[4] = { 5, 5, 5, 5 }; + child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); + + scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + shared_memory->CreateAndMapAnonymous(1); + base::SharedMemory* shared_memory_ptr = shared_memory.get(); + ResourceProvider::ResourceId id3 = + child_resource_provider_->CreateResourceFromTextureMailbox( + TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)), + SingleReleaseCallback::Create(base::Bind( + &SharedMemoryReleaseCallback, base::Passed(&shared_memory)))); + + ReturnedResourceArray returned_to_child; + int child_id = + resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); + { + // Transfer some resources to the parent. + ResourceProvider::ResourceIdArray resource_ids_to_transfer; + resource_ids_to_transfer.push_back(id1); + resource_ids_to_transfer.push_back(id2); + resource_ids_to_transfer.push_back(id3); + TransferableResourceArray list; + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); + ASSERT_EQ(3u, list.size()); + EXPECT_EQ(0u, list[0].sync_point); + EXPECT_EQ(0u, list[1].sync_point); + EXPECT_EQ(0u, list[2].sync_point); + 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); + resource_provider_->DeclareUsedResourcesFromChild(child_id, + resource_ids_to_transfer); + } + + EXPECT_EQ(3u, resource_provider_->num_resources()); + ResourceProvider::ResourceIdMap resource_map = + resource_provider_->GetChildToParentMap(child_id); + ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; + ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; + ResourceProvider::ResourceId mapped_id3 = resource_map[id3]; + EXPECT_NE(0u, mapped_id1); + EXPECT_NE(0u, mapped_id2); + EXPECT_NE(0u, mapped_id3); + EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); + EXPECT_FALSE(resource_provider_->InUseByConsumer(id2)); + EXPECT_FALSE(resource_provider_->InUseByConsumer(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)); + + { + // 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); + TransferableResourceArray list; + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); + EXPECT_EQ(1u, list.size()); + EXPECT_EQ(id1, list[0].id); + ReturnedResourceArray returned; + TransferableResource::ReturnResources(list, &returned); + child_resource_provider_->ReceiveReturnsFromParent(returned); + // id1 was exported twice, we returned it only once, it should still be + // in-use. + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); + } + { + EXPECT_EQ(0u, returned_to_child.size()); + + // Transfer resources back from the parent to the child. Set no resources as + // being in use. + ResourceProvider::ResourceIdArray no_resources; + resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); + + ASSERT_EQ(3u, returned_to_child.size()); + EXPECT_EQ(0u, returned_to_child[0].sync_point); + EXPECT_EQ(0u, returned_to_child[1].sync_point); + EXPECT_EQ(0u, returned_to_child[2].sync_point); + EXPECT_EQ(id1, returned_to_child[0].id); + EXPECT_EQ(id2, returned_to_child[1].id); + EXPECT_EQ(id3, returned_to_child[2].id); + 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)); + + { + ResourceProvider::ScopedReadLockSoftware 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)); + } + { + ResourceProvider::ScopedReadLockSoftware 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); + resource_ids_to_transfer.push_back(id3); + TransferableResourceArray 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(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); + resource_provider_->DeclareUsedResourcesFromChild(child_id, + resource_ids_to_transfer); + } + + 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_EQ(0u, returned_to_child[0].sync_point); + EXPECT_EQ(0u, returned_to_child[1].sync_point); + EXPECT_EQ(0u, returned_to_child[2].sync_point); + EXPECT_EQ(id1, returned_to_child[0].id); + EXPECT_EQ(id2, returned_to_child[1].id); + EXPECT_EQ(id3, returned_to_child[2].id); + EXPECT_FALSE(returned_to_child[0].lost); + EXPECT_FALSE(returned_to_child[1].lost); + EXPECT_FALSE(returned_to_child[2].lost); +} + +TEST_P(ResourceProviderTest, TransferSoftwareToNonUber) { + // TODO(jbauman): Remove test when shared bitmap manager available + // everywhere. + if (GetParam() != ResourceProvider::Bitmap) + return; + + scoped_ptr<FakeOutputSurface> parent_output_surface = + FakeOutputSurface::CreateSoftware( + make_scoped_ptr(new SoftwareOutputDevice)); + FakeOutputSurfaceClient parent_output_surface_client; + CHECK(parent_output_surface->BindToClient(&parent_output_surface_client)); + + scoped_ptr<ResourceProvider> parent_resource_provider( + ResourceProvider::Create(parent_output_surface.get(), NULL, 0, false)); + + gfx::Size size(1, 1); + ResourceFormat format = RGBA_8888; + size_t pixel_size = TextureSizeBytes(size, format); + ASSERT_EQ(4U, pixel_size); + + ResourceProvider::ResourceId id1 = resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); + uint8_t data1[4] = { 1, 2, 3, 4 }; + gfx::Rect rect(size); + resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); + + ReturnedResourceArray returned_to_child; + int child_id = parent_resource_provider->CreateChild( + GetReturnCallback(&returned_to_child)); + { + ResourceProvider::ResourceIdArray resource_ids_to_transfer; + resource_ids_to_transfer.push_back(id1); + TransferableResourceArray list; + resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); + ASSERT_EQ(1u, list.size()); + EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); + parent_resource_provider->ReceiveFromChild(child_id, list); + } + + EXPECT_EQ(0u, parent_resource_provider->num_resources()); + ASSERT_EQ(1u, returned_to_child.size()); + EXPECT_EQ(returned_to_child[0].id, id1); + ResourceProvider::ResourceIdMap resource_map = + parent_resource_provider->GetChildToParentMap(child_id); + ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; + EXPECT_EQ(0u, mapped_id1); + + parent_resource_provider->DestroyChild(child_id); + EXPECT_EQ(0u, parent_resource_provider->num_resources()); + + ASSERT_EQ(1u, returned_to_child.size()); + EXPECT_FALSE(returned_to_child[0].lost); +} + +TEST_P(ResourceProviderTest, TransferGLToSoftware) { + if (GetParam() != ResourceProvider::Bitmap) return; scoped_ptr<ResourceProviderContext> child_context_owned( @@ -709,7 +1075,7 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) { CHECK(child_output_surface->BindToClient(&child_output_surface_client)); scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), 0, false)); + ResourceProvider::Create(child_output_surface.get(), NULL, 0, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -718,14 +1084,103 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) { ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); - uint8_t data1[4] = {1, 2, 3, 4}; + uint8_t data1[4] = { 1, 2, 3, 4 }; gfx::Rect rect(size); child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); - ResourceProvider::ResourceId id2 = child_resource_provider->CreateResource( + ReturnedResourceArray 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); + TransferableResourceArray list; + child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, + &list); + ASSERT_EQ(1u, list.size()); + EXPECT_NE(0u, list[0].sync_point); + EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].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); + ResourceProvider::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 (GetParam() != ResourceProvider::Bitmap) + return; + + gfx::Size size(1, 1); + ResourceFormat format = RGBA_8888; + size_t pixel_size = TextureSizeBytes(size, format); + ASSERT_EQ(4U, pixel_size); + + ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); + uint8_t data1[4] = { 1, 2, 3, 4 }; + gfx::Rect rect(size); + child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); + + ReturnedResourceArray 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); + TransferableResourceArray list; + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); + ASSERT_EQ(1u, list.size()); + // Make invalid. + list[0].mailbox.name[1] = 5; + 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); + ResourceProvider::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, DeleteExportedResources) { + gfx::Size size(1, 1); + ResourceFormat format = RGBA_8888; + size_t pixel_size = TextureSizeBytes(size, format); + ASSERT_EQ(4U, pixel_size); + + ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); + uint8_t data1[4] = { 1, 2, 3, 4 }; + gfx::Rect rect(size); + child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); + + ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); uint8_t data2[4] = {5, 5, 5, 5}; - child_resource_provider->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); + child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); ReturnedResourceArray returned_to_child; int child_id = @@ -736,13 +1191,15 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) { resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); ASSERT_EQ(2u, list.size()); - EXPECT_NE(0u, list[0].sync_point); - EXPECT_NE(0u, list[1].sync_point); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2)); + if (GetParam() == ResourceProvider::GLTexture) { + EXPECT_NE(0u, list[0].sync_point); + EXPECT_NE(0u, list[1].sync_point); + } + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); resource_provider_->ReceiveFromChild(child_id, list); resource_provider_->DeclareUsedResourcesFromChild(child_id, resource_ids_to_transfer); @@ -767,8 +1224,10 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) { resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); ASSERT_EQ(2u, list.size()); - EXPECT_NE(0u, list[0].sync_point); - EXPECT_NE(0u, list[1].sync_point); + if (GetParam() == ResourceProvider::GLTexture) { + EXPECT_NE(0u, list[0].sync_point); + EXPECT_NE(0u, list[1].sync_point); + } EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(resource_provider_->InUseByConsumer(id2)); @@ -791,44 +1250,31 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) { EXPECT_EQ(0u, resource_provider_->num_resources()); ASSERT_EQ(2u, returned_to_child.size()); - EXPECT_NE(0u, returned_to_child[0].sync_point); - EXPECT_NE(0u, returned_to_child[1].sync_point); + if (GetParam() == ResourceProvider::GLTexture) { + EXPECT_NE(0u, returned_to_child[0].sync_point); + EXPECT_NE(0u, returned_to_child[1].sync_point); + } EXPECT_FALSE(returned_to_child[0].lost); EXPECT_FALSE(returned_to_child[1].lost); } } TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { - // Resource transfer is only supported with GL textures for now. - if (GetParam() != ResourceProvider::GLTexture) - return; - - scoped_ptr<ResourceProviderContext> child_context_owned( - ResourceProviderContext::Create(shared_data_.get())); - - FakeOutputSurfaceClient child_output_surface_client; - scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d( - child_context_owned.PassAs<TestWebGraphicsContext3D>())); - CHECK(child_output_surface->BindToClient(&child_output_surface_client)); - - scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), 0, false)); - gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource( + ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); uint8_t data1[4] = {1, 2, 3, 4}; gfx::Rect rect(size); - child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); + child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); - ResourceProvider::ResourceId id2 = child_resource_provider->CreateResource( + ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); uint8_t data2[4] = {5, 5, 5, 5}; - child_resource_provider->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); + child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); ReturnedResourceArray returned_to_child; int child_id = @@ -839,13 +1285,15 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); ASSERT_EQ(2u, list.size()); - EXPECT_NE(0u, list[0].sync_point); - EXPECT_NE(0u, list[1].sync_point); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1)); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2)); + if (GetParam() == ResourceProvider::GLTexture) { + EXPECT_NE(0u, list[0].sync_point); + EXPECT_NE(0u, list[1].sync_point); + } + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); resource_provider_->ReceiveFromChild(child_id, list); resource_provider_->DeclareUsedResourcesFromChild(child_id, resource_ids_to_transfer); @@ -870,8 +1318,10 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); ASSERT_EQ(2u, list.size()); - EXPECT_NE(0u, list[0].sync_point); - EXPECT_NE(0u, list[1].sync_point); + if (GetParam() == ResourceProvider::GLTexture) { + EXPECT_NE(0u, list[0].sync_point); + EXPECT_NE(0u, list[1].sync_point); + } EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(resource_provider_->InUseByConsumer(id2)); @@ -889,8 +1339,10 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { EXPECT_EQ(0u, resource_provider_->num_resources()); ASSERT_EQ(2u, returned_to_child.size()); - EXPECT_NE(0u, returned_to_child[0].sync_point); - EXPECT_NE(0u, returned_to_child[1].sync_point); + if (GetParam() == ResourceProvider::GLTexture) { + EXPECT_NE(0u, returned_to_child[0].sync_point); + EXPECT_NE(0u, returned_to_child[1].sync_point); + } EXPECT_TRUE(returned_to_child[0].lost); EXPECT_TRUE(returned_to_child[1].lost); returned_to_child.clear(); @@ -909,32 +1361,16 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { } TEST_P(ResourceProviderTest, DeleteTransferredResources) { - // Resource transfer is only supported with GL textures for now. - if (GetParam() != ResourceProvider::GLTexture) - return; - - scoped_ptr<ResourceProviderContext> child_context_owned( - ResourceProviderContext::Create(shared_data_.get())); - - FakeOutputSurfaceClient child_output_surface_client; - scoped_ptr<OutputSurface> child_output_surface( - FakeOutputSurface::Create3d( - child_context_owned.PassAs<TestWebGraphicsContext3D>())); - CHECK(child_output_surface->BindToClient(&child_output_surface_client)); - - scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), 0, false)); - gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); - ResourceProvider::ResourceId id = child_resource_provider->CreateResource( + ResourceProvider::ResourceId id = child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); uint8_t data[4] = { 1, 2, 3, 4 }; gfx::Rect rect(size); - child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d()); + child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d()); ReturnedResourceArray returned_to_child; int child_id = @@ -944,19 +1380,20 @@ TEST_P(ResourceProviderTest, DeleteTransferredResources) { ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); ASSERT_EQ(1u, list.size()); - EXPECT_NE(0u, list[0].sync_point); - EXPECT_TRUE(child_resource_provider->InUseByConsumer(id)); + if (GetParam() == ResourceProvider::GLTexture) + EXPECT_NE(0u, list[0].sync_point); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id)); resource_provider_->ReceiveFromChild(child_id, list); resource_provider_->DeclareUsedResourcesFromChild(child_id, resource_ids_to_transfer); } // Delete textures in the child, while they are transfered. - child_resource_provider->DeleteResource(id); - EXPECT_EQ(1u, child_resource_provider->num_resources()); + child_resource_provider_->DeleteResource(id); + EXPECT_EQ(1u, child_resource_provider_->num_resources()); { EXPECT_EQ(0u, returned_to_child.size()); @@ -966,10 +1403,11 @@ TEST_P(ResourceProviderTest, DeleteTransferredResources) { resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); ASSERT_EQ(1u, returned_to_child.size()); - EXPECT_NE(0u, returned_to_child[0].sync_point); - child_resource_provider->ReceiveReturnsFromParent(returned_to_child); + if (GetParam() == ResourceProvider::GLTexture) + EXPECT_NE(0u, returned_to_child[0].sync_point); + child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); } - EXPECT_EQ(0u, child_resource_provider->num_resources()); + EXPECT_EQ(0u, child_resource_provider_->num_resources()); } class ResourceProviderTestTextureFilters : public ResourceProviderTest { @@ -985,7 +1423,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { CHECK(child_output_surface->BindToClient(&child_output_surface_client)); scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), 0, false)); + ResourceProvider::Create(child_output_surface.get(), NULL, 0, false)); scoped_ptr<TextureStateTrackingContext> parent_context_owned( new TextureStateTrackingContext); @@ -997,7 +1435,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { CHECK(parent_output_surface->BindToClient(&parent_output_surface_client)); scoped_ptr<ResourceProvider> parent_resource_provider( - ResourceProvider::Create(parent_output_surface.get(), 0, false)); + ResourceProvider::Create(parent_output_surface.get(), NULL, 0, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -1140,16 +1578,8 @@ TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) { ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST); } -void ReleaseTextureMailbox(unsigned* release_sync_point, - bool* release_lost_resource, - unsigned sync_point, - bool lost_resource) { - *release_sync_point = sync_point; - *release_lost_resource = lost_resource; -} - TEST_P(ResourceProviderTest, TransferMailboxResources) { - // Resource transfer is only supported with GL textures for now. + // Other mailbox transfers tested elsewhere. if (GetParam() != ResourceProvider::GLTexture) return; unsigned texture = context()->createTexture(); @@ -1269,27 +1699,14 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) { } TEST_P(ResourceProviderTest, LostResourceInParent) { - // Resource transfer is only supported with GL textures for now. - if (GetParam() != ResourceProvider::GLTexture) - return; - - scoped_ptr<ResourceProviderContext> child_context_owned( - ResourceProviderContext::Create(shared_data_.get())); - - FakeOutputSurfaceClient child_output_surface_client; - scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d( - child_context_owned.PassAs<TestWebGraphicsContext3D>())); - CHECK(child_output_surface->BindToClient(&child_output_surface_client)); - - scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), 0, false)); - gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; ResourceProvider::ResourceId resource = - child_resource_provider->CreateResource( + child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); - child_resource_provider->AllocateForTesting(resource); + child_resource_provider_->AllocateForTesting(resource); + // Expect a GL resource to be lost. + bool should_lose_resource = GetParam() == ResourceProvider::GLTexture; ReturnedResourceArray returned_to_child; int child_id = @@ -1299,8 +1716,8 @@ TEST_P(ResourceProviderTest, LostResourceInParent) { ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(resource); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); EXPECT_EQ(1u, list.size()); resource_provider_->ReceiveFromChild(child_id, list); @@ -1319,42 +1736,28 @@ TEST_P(ResourceProviderTest, LostResourceInParent) { ResourceProvider::ResourceIdArray no_resources; resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - // Expect the resource to be lost. + // Expect a GL resource to be lost. ASSERT_EQ(1u, returned_to_child.size()); - EXPECT_TRUE(returned_to_child[0].lost); - child_resource_provider->ReceiveReturnsFromParent(returned_to_child); + EXPECT_EQ(should_lose_resource, returned_to_child[0].lost); + child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); returned_to_child.clear(); } - // The resource should be lost. - EXPECT_TRUE(child_resource_provider->IsLost(resource)); + // A GL resource should be lost. + EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource)); // Lost resources stay in use in the parent forever. - EXPECT_TRUE(child_resource_provider->InUseByConsumer(resource)); + EXPECT_EQ(should_lose_resource, + child_resource_provider_->InUseByConsumer(resource)); } TEST_P(ResourceProviderTest, LostResourceInGrandParent) { - // Resource transfer is only supported with GL textures for now. - if (GetParam() != ResourceProvider::GLTexture) - return; - - scoped_ptr<ResourceProviderContext> child_context_owned( - ResourceProviderContext::Create(shared_data_.get())); - - FakeOutputSurfaceClient child_output_surface_client; - scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d( - child_context_owned.PassAs<TestWebGraphicsContext3D>())); - CHECK(child_output_surface->BindToClient(&child_output_surface_client)); - - scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), 0, false)); - gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; ResourceProvider::ResourceId resource = - child_resource_provider->CreateResource( + child_resource_provider_->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); - child_resource_provider->AllocateForTesting(resource); + child_resource_provider_->AllocateForTesting(resource); ReturnedResourceArray returned_to_child; int child_id = @@ -1364,8 +1767,8 @@ TEST_P(ResourceProviderTest, LostResourceInGrandParent) { ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(resource); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); EXPECT_EQ(1u, list.size()); resource_provider_->ReceiveFromChild(child_id, list); @@ -1413,47 +1816,24 @@ TEST_P(ResourceProviderTest, LostResourceInGrandParent) { // Expect the resource to be lost. ASSERT_EQ(1u, returned_to_child.size()); EXPECT_TRUE(returned_to_child[0].lost); - child_resource_provider->ReceiveReturnsFromParent(returned_to_child); + child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); returned_to_child.clear(); } // The resource should be lost. - EXPECT_TRUE(child_resource_provider->IsLost(resource)); + EXPECT_TRUE(child_resource_provider_->IsLost(resource)); // Lost resources stay in use in the parent forever. - EXPECT_TRUE(child_resource_provider->InUseByConsumer(resource)); + EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource)); } TEST_P(ResourceProviderTest, LostMailboxInParent) { - // Resource transfer is only supported with GL textures for now. - if (GetParam() != ResourceProvider::GLTexture) - return; - - scoped_ptr<ResourceProviderContext> child_context_owned( - ResourceProviderContext::Create(shared_data_.get())); - ResourceProviderContext* child_context = child_context_owned.get(); - - FakeOutputSurfaceClient child_output_surface_client; - scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d( - child_context_owned.PassAs<TestWebGraphicsContext3D>())); - CHECK(child_output_surface->BindToClient(&child_output_surface_client)); - - scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), 0, false)); - - unsigned texture = child_context->createTexture(); - gpu::Mailbox gpu_mailbox; - child_context->bindTexture(GL_TEXTURE_2D, texture); - child_context->genMailboxCHROMIUM(gpu_mailbox.name); - child_context->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name); - unsigned release_sync_point = 0; bool lost_resource = false; - ReleaseCallback callback = - base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource); - ResourceProvider::ResourceId resource = - child_resource_provider->CreateResourceFromTextureMailbox( - TextureMailbox(gpu_mailbox), SingleReleaseCallback::Create(callback)); + bool release_called = false; + unsigned sync_point = 0; + ResourceProvider::ResourceId resource = CreateChildMailbox( + &release_sync_point, &lost_resource, &release_called, &sync_point); ReturnedResourceArray returned_to_child; int child_id = @@ -1463,8 +1843,8 @@ TEST_P(ResourceProviderTest, LostMailboxInParent) { ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(resource); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); EXPECT_EQ(1u, list.size()); resource_provider_->ReceiveFromChild(child_id, list); @@ -1483,51 +1863,27 @@ TEST_P(ResourceProviderTest, LostMailboxInParent) { ResourceProvider::ResourceIdArray no_resources; resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - // Expect the resource to be lost. ASSERT_EQ(1u, returned_to_child.size()); - EXPECT_TRUE(returned_to_child[0].lost); - child_resource_provider->ReceiveReturnsFromParent(returned_to_child); + // Losing an output surface only loses hardware resources. + EXPECT_EQ(returned_to_child[0].lost, + GetParam() == ResourceProvider::GLTexture); + child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); returned_to_child.clear(); } - // Delete the resource in the child. Expect the resource to be lost. - child_resource_provider->DeleteResource(resource); - EXPECT_TRUE(lost_resource); - - child_context->waitSyncPoint(release_sync_point); - child_context->deleteTexture(texture); + // Delete the resource in the child. Expect the resource to be lost if it's + // a GL texture. + child_resource_provider_->DeleteResource(resource); + EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture); } TEST_P(ResourceProviderTest, LostMailboxInGrandParent) { - // Resource transfer is only supported with GL textures for now. - if (GetParam() != ResourceProvider::GLTexture) - return; - - scoped_ptr<ResourceProviderContext> child_context_owned( - ResourceProviderContext::Create(shared_data_.get())); - ResourceProviderContext* child_context = child_context_owned.get(); - - FakeOutputSurfaceClient child_output_surface_client; - scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d( - child_context_owned.PassAs<TestWebGraphicsContext3D>())); - CHECK(child_output_surface->BindToClient(&child_output_surface_client)); - - scoped_ptr<ResourceProvider> child_resource_provider( - ResourceProvider::Create(child_output_surface.get(), 0, false)); - - unsigned texture = child_context->createTexture(); - gpu::Mailbox gpu_mailbox; - child_context->bindTexture(GL_TEXTURE_2D, texture); - child_context->genMailboxCHROMIUM(gpu_mailbox.name); - child_context->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name); - unsigned release_sync_point = 0; bool lost_resource = false; - ReleaseCallback callback = - base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource); - ResourceProvider::ResourceId resource = - child_resource_provider->CreateResourceFromTextureMailbox( - TextureMailbox(gpu_mailbox), SingleReleaseCallback::Create(callback)); + bool release_called = false; + unsigned sync_point = 0; + ResourceProvider::ResourceId resource = CreateChildMailbox( + &release_sync_point, &lost_resource, &release_called, &sync_point); ReturnedResourceArray returned_to_child; int child_id = @@ -1537,8 +1893,8 @@ TEST_P(ResourceProviderTest, LostMailboxInGrandParent) { ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(resource); TransferableResourceArray list; - child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, - &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); EXPECT_EQ(1u, list.size()); resource_provider_->ReceiveFromChild(child_id, list); @@ -1580,116 +1936,54 @@ TEST_P(ResourceProviderTest, LostMailboxInGrandParent) { // Expect the resource to be lost. ASSERT_EQ(1u, returned_to_child.size()); EXPECT_TRUE(returned_to_child[0].lost); - child_resource_provider->ReceiveReturnsFromParent(returned_to_child); + child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); returned_to_child.clear(); } // Delete the resource in the child. Expect the resource to be lost. - child_resource_provider->DeleteResource(resource); + child_resource_provider_->DeleteResource(resource); EXPECT_TRUE(lost_resource); - - child_context->waitSyncPoint(release_sync_point); - child_context->deleteTexture(texture); } TEST_P(ResourceProviderTest, Shutdown) { - // TextureMailbox callbacks only exist for GL textures for now. - if (GetParam() != ResourceProvider::GLTexture) - return; - unsigned texture = context()->createTexture(); - context()->bindTexture(GL_TEXTURE_2D, texture); - gpu::Mailbox mailbox; - context()->genMailboxCHROMIUM(mailbox.name); - context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); - unsigned sync_point = context()->insertSyncPoint(); - - EXPECT_LT(0u, sync_point); - unsigned release_sync_point = 0; bool lost_resource = false; - scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( - base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource)); - resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, sync_point), - callback.Pass()); + bool release_called = false; + unsigned sync_point = 0; + CreateChildMailbox( + &release_sync_point, &lost_resource, &release_called, &sync_point); EXPECT_EQ(0u, release_sync_point); EXPECT_FALSE(lost_resource); - resource_provider_.reset(); - - EXPECT_LE(sync_point, release_sync_point); - EXPECT_FALSE(lost_resource); -} - -static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory( - gfx::Size size, uint32_t value) { - scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory); - CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea())); - uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory()); - CHECK(pixels); - std::fill_n(pixels, size.GetArea(), value); - return shared_memory.Pass(); -} - -static void ReleaseSharedMemoryCallback( - bool* release_called, - unsigned sync_point, bool lost_resource) { - *release_called = true; -} - -TEST_P(ResourceProviderTest, ShutdownSharedMemory) { - if (GetParam() != ResourceProvider::Bitmap) - return; - - gfx::Size size(64, 64); - scoped_ptr<base::SharedMemory> shared_memory( - CreateAndFillSharedMemory(size, 0)); - - bool release_called = false; - scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( - base::Bind(ReleaseSharedMemoryCallback, &release_called)); - resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(shared_memory.get(), size), - callback.Pass()); - - resource_provider_.reset(); + child_resource_provider_.reset(); + if (GetParam() == ResourceProvider::GLTexture) { + EXPECT_LE(sync_point, release_sync_point); + } EXPECT_TRUE(release_called); + EXPECT_FALSE(lost_resource); } TEST_P(ResourceProviderTest, ShutdownWithExportedResource) { - // TextureMailbox callbacks only exist for GL textures for now. - if (GetParam() != ResourceProvider::GLTexture) - return; - unsigned texture = context()->createTexture(); - context()->bindTexture(GL_TEXTURE_2D, texture); - gpu::Mailbox mailbox; - context()->genMailboxCHROMIUM(mailbox.name); - context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); - unsigned sync_point = context()->insertSyncPoint(); - - EXPECT_LT(0u, sync_point); - unsigned release_sync_point = 0; bool lost_resource = false; - scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( - base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource)); - ResourceProvider::ResourceId resource = - resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(mailbox, sync_point), - callback.Pass()); + bool release_called = false; + unsigned sync_point = 0; + ResourceProvider::ResourceId resource = CreateChildMailbox( + &release_sync_point, &lost_resource, &release_called, &sync_point); // Transfer the resource, so we can't release it properly on shutdown. ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(resource); TransferableResourceArray list; - resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); + child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, + &list); EXPECT_EQ(0u, release_sync_point); EXPECT_FALSE(lost_resource); - resource_provider_.reset(); + child_resource_provider_.reset(); // Since the resource is in the parent, the child considers it lost. EXPECT_EQ(0u, release_sync_point); @@ -1742,7 +2036,7 @@ TEST_P(ResourceProviderTest, ScopedSampler) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -1823,7 +2117,7 @@ TEST_P(ResourceProviderTest, ManagedResource) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -1868,7 +2162,7 @@ TEST_P(ResourceProviderTest, TextureWrapMode) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -1921,7 +2215,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( base::Bind(&EmptyReleaseCallback)); @@ -1956,7 +2250,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); unsigned texture_id = 1; unsigned sync_point = 30; @@ -2020,7 +2314,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); unsigned texture_id = 1; unsigned sync_point = 30; @@ -2114,6 +2408,15 @@ class AllocationTrackingContext3D : public TestWebGraphicsContext3D { WGC3Denum format, WGC3Denum type, const void* pixels)); + MOCK_METHOD8(compressedTexImage2D, + void(WGC3Denum target, + WGC3Dint level, + WGC3Denum internalformat, + WGC3Dsizei width, + WGC3Dsizei height, + WGC3Dint border, + WGC3Dsizei image_size, + const void* data)); MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(WGC3Denum)); MOCK_METHOD3(createImageCHROMIUM, WGC3Duint(WGC3Dsizei, WGC3Dsizei, WGC3Denum)); @@ -2140,7 +2443,7 @@ TEST_P(ResourceProviderTest, TextureAllocation) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); gfx::Size size(2, 2); gfx::Vector2d offset(0, 0); @@ -2216,7 +2519,7 @@ TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) { int texture_id = 123; scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); @@ -2253,7 +2556,7 @@ TEST_P(ResourceProviderTest, PixelBuffer_Bitmap) { const uint32_t kBadBeef = 0xbadbeef; scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); @@ -2299,7 +2602,7 @@ TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) { int texture_id = 123; scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); @@ -2340,7 +2643,7 @@ TEST_P(ResourceProviderTest, PixelBufferLostContext) { int texture_id = 123; scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); EXPECT_CALL(*context, createTexture()).WillRepeatedly(Return(texture_id)); @@ -2378,7 +2681,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { const unsigned kImageId = 234u; scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); @@ -2470,7 +2773,7 @@ TEST_P(ResourceProviderTest, Image_Bitmap) { const uint32_t kBadBeef = 0xbadbeef; scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); id = resource_provider->CreateResource( size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); @@ -2521,7 +2824,7 @@ TEST(ResourceProviderTest, BasicInitializeGLSoftware) { scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice))); EXPECT_TRUE(output_surface->BindToClient(&client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL); @@ -2538,6 +2841,71 @@ TEST(ResourceProviderTest, BasicInitializeGLSoftware) { output_surface.get()); } +TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { + if (GetParam() != ResourceProvider::GLTexture) + return; + + scoped_ptr<AllocationTrackingContext3D> context_owned( + new AllocationTrackingContext3D); + AllocationTrackingContext3D* context = context_owned.get(); + context_owned->set_support_compressed_texture_etc1(true); + + FakeOutputSurfaceClient output_surface_client; + scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( + context_owned.PassAs<TestWebGraphicsContext3D>())); + CHECK(output_surface->BindToClient(&output_surface_client)); + + gfx::Size size(4, 4); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), 0, false)); + int texture_id = 123; + + ResourceProvider::ResourceId id = resource_provider->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1); + EXPECT_NE(0u, id); + EXPECT_CALL(*context, createTexture()).WillOnce(Return(texture_id)); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); + resource_provider->AllocateForTesting(id); + + EXPECT_CALL(*context, deleteTexture(texture_id)).Times(1); + resource_provider->DeleteResource(id); +} + +TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) { + if (GetParam() != ResourceProvider::GLTexture) + return; + + scoped_ptr<AllocationTrackingContext3D> context_owned( + new AllocationTrackingContext3D); + AllocationTrackingContext3D* context = context_owned.get(); + context_owned->set_support_compressed_texture_etc1(true); + + FakeOutputSurfaceClient output_surface_client; + scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( + context_owned.PassAs<TestWebGraphicsContext3D>())); + CHECK(output_surface->BindToClient(&output_surface_client)); + + gfx::Size size(4, 4); + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), 0, false)); + int texture_id = 123; + uint8_t pixels[8]; + + ResourceProvider::ResourceId id = resource_provider->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1); + EXPECT_NE(0u, id); + EXPECT_CALL(*context, createTexture()).WillOnce(Return(texture_id)); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3); + EXPECT_CALL(*context, + compressedTexImage2D( + _, 0, _, size.width(), size.height(), _, _, _)).Times(1); + resource_provider->SetPixels( + id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0)); + + EXPECT_CALL(*context, deleteTexture(texture_id)).Times(1); + resource_provider->DeleteResource(id); +} + INSTANTIATE_TEST_CASE_P( ResourceProviderTests, ResourceProviderTest, diff --git a/cc/resources/resource_update_controller.cc b/cc/resources/resource_update_controller.cc index 3114d1eead..59c536b084 100644 --- a/cc/resources/resource_update_controller.cc +++ b/cc/resources/resource_update_controller.cc @@ -9,6 +9,7 @@ #include "base/single_thread_task_runner.h" #include "cc/resources/prioritized_resource.h" #include "cc/resources/resource_provider.h" +#include "ui/gfx/frame_time.h" namespace { @@ -113,7 +114,7 @@ void ResourceUpdateController::OnTimerFired() { } base::TimeTicks ResourceUpdateController::Now() const { - return base::TimeTicks::Now(); + return gfx::FrameTime::Now(); } base::TimeDelta ResourceUpdateController::UpdateMoreTexturesTime() const { diff --git a/cc/resources/resource_update_controller_unittest.cc b/cc/resources/resource_update_controller_unittest.cc index 498d68202c..9f43f80d7c 100644 --- a/cc/resources/resource_update_controller_unittest.cc +++ b/cc/resources/resource_update_controller_unittest.cc @@ -137,7 +137,7 @@ class ResourceUpdateControllerTest : public Test { CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false); } void AppendFullUploadsOfIndexedTextureToUpdateQueue(int count, diff --git a/cc/resources/scoped_resource_unittest.cc b/cc/resources/scoped_resource_unittest.cc index 8b59995f28..dc0df8bf3b 100644 --- a/cc/resources/scoped_resource_unittest.cc +++ b/cc/resources/scoped_resource_unittest.cc @@ -19,7 +19,7 @@ TEST(ScopedResourceTest, NewScopedResource) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); scoped_ptr<ScopedResource> texture = ScopedResource::create(resource_provider.get()); @@ -37,7 +37,7 @@ TEST(ScopedResourceTest, CreateScopedResource) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); scoped_ptr<ScopedResource> texture = ScopedResource::create(resource_provider.get()); texture->Allocate(gfx::Size(30, 30), @@ -59,7 +59,7 @@ TEST(ScopedResourceTest, ScopedResourceIsDeleted) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); { scoped_ptr<ScopedResource> texture = ScopedResource::create(resource_provider.get()); @@ -93,7 +93,7 @@ TEST(ScopedResourceTest, LeakScopedResource) { CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<ResourceProvider> resource_provider( - ResourceProvider::Create(output_surface.get(), 0, false)); + ResourceProvider::Create(output_surface.get(), NULL, 0, false)); { scoped_ptr<ScopedResource> texture = ScopedResource::create(resource_provider.get()); diff --git a/cc/resources/shared_bitmap.cc b/cc/resources/shared_bitmap.cc new file mode 100644 index 0000000000..3a6fc3589e --- /dev/null +++ b/cc/resources/shared_bitmap.cc @@ -0,0 +1,17 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/shared_bitmap.h" + +namespace cc { + +SharedBitmap::SharedBitmap( + base::SharedMemory* memory, + const SharedBitmapId& id, + const base::Callback<void(SharedBitmap*)>& free_callback) + : memory_(memory), id_(id), free_callback_(free_callback) {} + +SharedBitmap::~SharedBitmap() { free_callback_.Run(this); } + +} // namespace cc diff --git a/cc/resources/shared_bitmap.h b/cc/resources/shared_bitmap.h new file mode 100644 index 0000000000..9575068411 --- /dev/null +++ b/cc/resources/shared_bitmap.h @@ -0,0 +1,51 @@ +// 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_SHARED_BITMAP_H_ +#define CC_RESOURCES_SHARED_BITMAP_H_ + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/shared_memory.h" +#include "cc/base/cc_export.h" +#include "gpu/command_buffer/common/mailbox.h" + +namespace base { class SharedMemory; } + +namespace cc { +typedef gpu::Mailbox SharedBitmapId; + +class CC_EXPORT SharedBitmap { + public: + SharedBitmap(base::SharedMemory* memory, + const SharedBitmapId& id, + const base::Callback<void(SharedBitmap*)>& free_callback); + + ~SharedBitmap(); + + bool operator<(const SharedBitmap& right) const { + if (memory_ < right.memory_) + return true; + if (memory_ > right.memory_) + return false; + return id_ < right.id_; + } + + uint8* pixels() { return static_cast<uint8*>(memory_->memory()); } + + base::SharedMemory* memory() { return memory_; } + + SharedBitmapId id() { return id_; } + + private: + base::SharedMemory* memory_; + SharedBitmapId id_; + base::Callback<void(SharedBitmap*)> free_callback_; + + DISALLOW_COPY_AND_ASSIGN(SharedBitmap); +}; + +} // namespace cc + +#endif // CC_RESOURCES_SHARED_BITMAP_H_ diff --git a/cc/resources/shared_bitmap_manager.h b/cc/resources/shared_bitmap_manager.h new file mode 100644 index 0000000000..53dd156470 --- /dev/null +++ b/cc/resources/shared_bitmap_manager.h @@ -0,0 +1,32 @@ +// 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_SHARED_BITMAP_MANAGER_H_ +#define CC_RESOURCES_SHARED_BITMAP_MANAGER_H_ + +#include "base/basictypes.h" +#include "cc/base/cc_export.h" +#include "cc/resources/shared_bitmap.h" +#include "ui/gfx/size.h" + +namespace cc { + +class CC_EXPORT SharedBitmapManager { + public: + SharedBitmapManager() {} + + virtual scoped_ptr<SharedBitmap> AllocateSharedBitmap(gfx::Size) = 0; + virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId( + gfx::Size, + const SharedBitmapId&) = 0; + virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory( + base::SharedMemory*) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(SharedBitmapManager); +}; + +} // namespace cc + +#endif // CC_RESOURCES_SHARED_BITMAP_MANAGER_H_ diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc index b2e536fa8a..df69f700be 100644 --- a/cc/resources/tile_manager.cc +++ b/cc/resources/tile_manager.cc @@ -471,13 +471,13 @@ void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { // Update internal state. if (state != global_state_) { + global_state_ = state; prioritized_tiles_dirty_ = true; resource_pool_->SetResourceUsageLimits( global_state_.memory_limit_in_bytes, global_state_.unused_memory_limit_in_bytes, global_state_.num_resources_limit); } - global_state_ = state; // We need to call CheckForCompletedTasks() once in-between each call // to ScheduleTasks() to prevent canceled tasks from being scheduled. diff --git a/cc/resources/tile_manager_perftest.cc b/cc/resources/tile_manager_perftest.cc index 7292f1debd..f533e6524b 100644 --- a/cc/resources/tile_manager_perftest.cc +++ b/cc/resources/tile_manager_perftest.cc @@ -40,7 +40,7 @@ class TileManagerPerfTest : public testing::Test { CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false); tile_manager_ = make_scoped_ptr( new FakeTileManager(&tile_manager_client_, resource_provider_.get())); picture_pile_ = FakePicturePileImpl::CreatePile(); diff --git a/cc/resources/tile_manager_unittest.cc b/cc/resources/tile_manager_unittest.cc index 2f9db48d24..c5bc6da4de 100644 --- a/cc/resources/tile_manager_unittest.cc +++ b/cc/resources/tile_manager_unittest.cc @@ -26,7 +26,7 @@ class TileManagerTest : public testing::TestWithParam<bool> { CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false); tile_manager_ = make_scoped_ptr( new FakeTileManager(&tile_manager_client_, resource_provider_.get())); diff --git a/cc/resources/transferable_resource.cc b/cc/resources/transferable_resource.cc index 88ad8fd055..62f1bdb164 100644 --- a/cc/resources/transferable_resource.cc +++ b/cc/resources/transferable_resource.cc @@ -9,7 +9,12 @@ namespace cc { TransferableResource::TransferableResource() - : id(0), sync_point(0), format(RGBA_8888), target(0), filter(0) {} + : id(0), + sync_point(0), + format(RGBA_8888), + target(0), + filter(0), + is_software(false) {} TransferableResource::~TransferableResource() { } diff --git a/cc/resources/transferable_resource.h b/cc/resources/transferable_resource.h index cb650a78ea..5c93d1c042 100644 --- a/cc/resources/transferable_resource.h +++ b/cc/resources/transferable_resource.h @@ -35,6 +35,7 @@ struct CC_EXPORT TransferableResource { uint32 filter; gfx::Size size; gpu::Mailbox mailbox; + bool is_software; }; } // namespace cc diff --git a/cc/resources/ui_resource_bitmap.cc b/cc/resources/ui_resource_bitmap.cc index 86acfa5185..62a85fc8e3 100644 --- a/cc/resources/ui_resource_bitmap.cc +++ b/cc/resources/ui_resource_bitmap.cc @@ -12,20 +12,21 @@ namespace cc { void UIResourceBitmap::Create(const skia::RefPtr<SkPixelRef>& pixel_ref, UIResourceFormat format, - UIResourceWrapMode wrap_mode, gfx::Size size) { DCHECK(size.width()); DCHECK(size.height()); DCHECK(pixel_ref); DCHECK(pixel_ref->isImmutable()); format_ = format; - wrap_mode_ = wrap_mode; size_ = size; pixel_ref_ = pixel_ref; + + // Default values for secondary parameters. + wrap_mode_ = CLAMP_TO_EDGE; + opaque_ = (format == ETC1); } -UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap, - UIResourceWrapMode wrap_mode) { +UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap) { DCHECK_EQ(skbitmap.config(), SkBitmap::kARGB_8888_Config); DCHECK_EQ(skbitmap.width(), skbitmap.rowBytesAsPixels()); DCHECK(skbitmap.isImmutable()); @@ -33,8 +34,15 @@ UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap, skia::RefPtr<SkPixelRef> pixel_ref = skia::SharePtr(skbitmap.pixelRef()); Create(pixel_ref, UIResourceBitmap::RGBA8, - wrap_mode, gfx::Size(skbitmap.width(), skbitmap.height())); + + SetOpaque(skbitmap.isOpaque()); +} + +UIResourceBitmap::UIResourceBitmap(const skia::RefPtr<SkPixelRef>& pixel_ref, + UIResourceFormat format, + gfx::Size size) { + Create(pixel_ref, format, size); } UIResourceBitmap::~UIResourceBitmap() {} diff --git a/cc/resources/ui_resource_bitmap.h b/cc/resources/ui_resource_bitmap.h index 78cb465812..d0f717a7b2 100644 --- a/cc/resources/ui_resource_bitmap.h +++ b/cc/resources/ui_resource_bitmap.h @@ -24,7 +24,8 @@ namespace cc { class CC_EXPORT UIResourceBitmap { public: enum UIResourceFormat { - RGBA8 + RGBA8, + ETC1 }; enum UIResourceWrapMode { CLAMP_TO_EDGE, @@ -34,12 +35,18 @@ class CC_EXPORT UIResourceBitmap { gfx::Size GetSize() const { return size_; } UIResourceFormat GetFormat() const { return format_; } UIResourceWrapMode GetWrapMode() const { return wrap_mode_; } + void SetWrapMode(UIResourceWrapMode wrap_mode) { wrap_mode_ = wrap_mode; } + bool GetOpaque() const { return opaque_; } + void SetOpaque(bool opaque) { opaque_ = opaque; } // The constructor for the UIResourceBitmap. User must ensure that |skbitmap| // is immutable. The SkBitmap format should be in 32-bit RGBA. Wrap mode is // unnecessary for most UI resources and is defaulted to CLAMP_TO_EDGE. - UIResourceBitmap(const SkBitmap& skbitmap, - UIResourceWrapMode wrap_mode = CLAMP_TO_EDGE); + explicit UIResourceBitmap(const SkBitmap& skbitmap); + + UIResourceBitmap(const skia::RefPtr<SkPixelRef>& pixel_ref, + UIResourceFormat format, + gfx::Size size); ~UIResourceBitmap(); @@ -47,13 +54,13 @@ class CC_EXPORT UIResourceBitmap { friend class AutoLockUIResourceBitmap; void Create(const skia::RefPtr<SkPixelRef>& pixel_ref, UIResourceFormat format, - UIResourceWrapMode wrap_mode, gfx::Size size); skia::RefPtr<SkPixelRef> pixel_ref_; UIResourceFormat format_; UIResourceWrapMode wrap_mode_; gfx::Size size_; + bool opaque_; }; class CC_EXPORT AutoLockUIResourceBitmap { diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index 34c7ab65c3..b819b38fbd 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc @@ -261,24 +261,30 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( 0xff); } - // In software mode, the resource provider won't be lost. Soon this callback - // will be called directly from the resource provider, same as 3d - // compositing mode, so this raw unretained resource_provider will always - // be valid when the callback is fired. RecycleResourceData recycle_data = { plane_resources[0].resource_id, plane_resources[0].resource_size, plane_resources[0].resource_format, gpu::Mailbox() }; + base::SharedMemory* shared_memory = + resource_provider_->GetSharedMemory(plane_resources[0].resource_id); + if (shared_memory) { + external_resources.mailboxes.push_back( + TextureMailbox(shared_memory, plane_resources[0].resource_size)); + external_resources.release_callbacks + .push_back(base::Bind(&RecycleResource, AsWeakPtr(), recycle_data)); + external_resources.type = VideoFrameExternalResources::RGB_RESOURCE; + } else { + // TODO(jbauman): Remove this path once shared memory is available + // everywhere. + external_resources.software_resources + .push_back(plane_resources[0].resource_id); + external_resources.software_release_callback = + base::Bind(&RecycleResource, AsWeakPtr(), recycle_data); + external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; + } - external_resources.software_resources.push_back( - plane_resources[0].resource_id); - external_resources.software_release_callback = - base::Bind(&RecycleResource, AsWeakPtr(), recycle_data); - - - external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; return external_resources; } diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc index c36689e16c..028e0a673e 100644 --- a/cc/resources/video_resource_updater_unittest.cc +++ b/cc/resources/video_resource_updater_unittest.cc @@ -26,7 +26,7 @@ class VideoResourceUpdaterTest : public testing::Test { FakeOutputSurface::Create3d(context3d.Pass()); CHECK(output_surface3d_->BindToClient(&client_)); resource_provider3d_ = - ResourceProvider::Create(output_surface3d_.get(), 0, false); + ResourceProvider::Create(output_surface3d_.get(), NULL, 0, false); } scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() { diff --git a/cc/scheduler/delay_based_time_source.cc b/cc/scheduler/delay_based_time_source.cc index d150c717a1..00515b72f7 100644 --- a/cc/scheduler/delay_based_time_source.cc +++ b/cc/scheduler/delay_based_time_source.cc @@ -33,6 +33,27 @@ static const double kPhaseChangeThreshold = 0.25; } // namespace +// The following methods correspond to the DelayBasedTimeSource that uses +// the base::TimeTicks::HighResNow as the timebase. +scoped_refptr<DelayBasedTimeSourceHighRes> DelayBasedTimeSourceHighRes::Create( + base::TimeDelta interval, + base::SingleThreadTaskRunner* task_runner) { + return make_scoped_refptr( + new DelayBasedTimeSourceHighRes(interval, task_runner)); +} + +DelayBasedTimeSourceHighRes::DelayBasedTimeSourceHighRes( + base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner) + : DelayBasedTimeSource(interval, task_runner) {} + +DelayBasedTimeSourceHighRes::~DelayBasedTimeSourceHighRes() {} + +base::TimeTicks DelayBasedTimeSourceHighRes::Now() const { + return base::TimeTicks::HighResNow(); +} + +// The following methods correspond to the DelayBasedTimeSource that uses +// the base::TimeTicks::Now as the timebase. scoped_refptr<DelayBasedTimeSource> DelayBasedTimeSource::Create( base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner) { diff --git a/cc/scheduler/delay_based_time_source.h b/cc/scheduler/delay_based_time_source.h index 55aac5a97f..ddb89da356 100644 --- a/cc/scheduler/delay_based_time_source.h +++ b/cc/scheduler/delay_based_time_source.h @@ -15,7 +15,7 @@ namespace cc { // This timer implements a time source that achieves the specified interval // in face of millisecond-precision delayed callbacks and random queueing -// delays. +// delays. DelayBasedTimeSource uses base::TimeTicks::Now as its timebase. class CC_EXPORT DelayBasedTimeSource : public TimeSource { public: static scoped_refptr<DelayBasedTimeSource> Create( @@ -73,6 +73,23 @@ class CC_EXPORT DelayBasedTimeSource : public TimeSource { DISALLOW_COPY_AND_ASSIGN(DelayBasedTimeSource); }; +// DelayBasedTimeSource uses base::TimeTicks::HighResNow as its timebase. +class DelayBasedTimeSourceHighRes : public DelayBasedTimeSource { + public: + static scoped_refptr<DelayBasedTimeSourceHighRes> Create( + base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner); + + virtual base::TimeTicks Now() const OVERRIDE; + + protected: + DelayBasedTimeSourceHighRes(base::TimeDelta interval, + base::SingleThreadTaskRunner* task_runner); + virtual ~DelayBasedTimeSourceHighRes(); + + private: + DISALLOW_COPY_AND_ASSIGN(DelayBasedTimeSourceHighRes); +}; + } // namespace cc #endif // CC_SCHEDULER_DELAY_BASED_TIME_SOURCE_H_ diff --git a/cc/scheduler/frame_rate_controller.cc b/cc/scheduler/frame_rate_controller.cc index 47c27ed3f8..2729748859 100644 --- a/cc/scheduler/frame_rate_controller.cc +++ b/cc/scheduler/frame_rate_controller.cc @@ -11,6 +11,7 @@ #include "base/single_thread_task_runner.h" #include "cc/scheduler/delay_based_time_source.h" #include "cc/scheduler/time_source.h" +#include "ui/gfx/frame_time.h" namespace cc { @@ -165,7 +166,7 @@ base::TimeTicks FrameRateController::LastTickTime() { if (is_time_source_throttling_) return time_source_->LastTickTime(); - return base::TimeTicks::Now(); + return gfx::FrameTime::Now(); } } // namespace cc diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index 382bd96348..93b91311e6 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc @@ -9,6 +9,7 @@ #include "base/debug/trace_event.h" #include "base/logging.h" #include "cc/debug/traced_value.h" +#include "ui/gfx/frame_time.h" namespace cc { @@ -78,6 +79,11 @@ void Scheduler::SetSwapUsedIncompleteTile(bool used_incomplete_tile) { ProcessScheduledActions(); } +void Scheduler::SetSmoothnessTakesPriority(bool smoothness_takes_priority) { + state_machine_.SetSmoothnessTakesPriority(smoothness_takes_priority); + ProcessScheduledActions(); +} + void Scheduler::SetMainThreadNeedsLayerTextures() { state_machine_.SetMainThreadNeedsLayerTextures(); ProcessScheduledActions(); @@ -118,7 +124,7 @@ base::TimeTicks Scheduler::AnticipatedDrawTime() { last_begin_impl_frame_args_.interval <= base::TimeDelta()) return base::TimeTicks(); - base::TimeTicks now = base::TimeTicks::Now(); + base::TimeTicks now = gfx::FrameTime::Now(); base::TimeTicks timebase = std::max(last_begin_impl_frame_args_.frame_time, last_begin_impl_frame_args_.deadline); int64 intervals = diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index 00b8377e9c..1a284f187d 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h @@ -86,6 +86,8 @@ class CC_EXPORT Scheduler { void SetSwapUsedIncompleteTile(bool used_incomplete_tile); + void SetSmoothnessTakesPriority(bool smoothness_takes_priority); + void FinishCommit(); void BeginMainFrameAborted(bool did_handle); diff --git a/cc/scheduler/scheduler_settings.cc b/cc/scheduler/scheduler_settings.cc index 6c1db6bf10..9b8032c43a 100644 --- a/cc/scheduler/scheduler_settings.cc +++ b/cc/scheduler/scheduler_settings.cc @@ -7,7 +7,7 @@ namespace cc { SchedulerSettings::SchedulerSettings() - : deadline_scheduling_enabled(false), + : deadline_scheduling_enabled(true), impl_side_painting(false), timeout_and_draw_when_animation_checkerboards(true), maximum_number_of_failed_draws_before_draw_is_forced_(3), diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index c14186a74d..0fd0f57b3b 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc @@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/values.h" +#include "ui/gfx/frame_time.h" namespace cc { @@ -39,7 +40,8 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) pending_tree_is_ready_for_activation_(false), active_tree_needs_first_draw_(false), draw_if_possible_failed_(false), - did_create_and_initialize_first_output_surface_(false) {} + did_create_and_initialize_first_output_surface_(false), + smoothness_takes_priority_(false) {} const char* SchedulerStateMachine::OutputSurfaceStateToString( OutputSurfaceState state) { @@ -192,7 +194,7 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { state->Set("major_state", major_state.release()); scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue); - base::TimeTicks now = base::TimeTicks::Now(); + base::TimeTicks now = gfx::FrameTime::Now(); timestamps_state->SetDouble( "0_interval", last_begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L); @@ -255,6 +257,8 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_); minor_state->SetBoolean("did_create_and_initialize_first_output_surface", did_create_and_initialize_first_output_surface_); + minor_state->SetBoolean("smoothness_takes_priority", + smoothness_takes_priority_); state->Set("minor_state", minor_state.release()); return state.PassAs<base::Value>(); @@ -820,7 +824,7 @@ bool SchedulerStateMachine::BeginImplFrameNeededToDraw() const { // These are cases where we are very likely to draw soon, but might not // actually have a new frame to draw when we receive the next BeginImplFrame. // Proactively requesting the BeginImplFrame helps hide the round trip latency -// of the SetNeedsBeginFrame request that has to go to the Browser. +// of the SetNeedsBeginImplFrame request that has to go to the Browser. bool SchedulerStateMachine::ProactiveBeginImplFrameWanted() const { // The output surface is the provider of BeginImplFrames, // so we are not going to get them even if we ask for them. @@ -847,9 +851,10 @@ bool SchedulerStateMachine::ProactiveBeginImplFrameWanted() const { return true; // If we just swapped, it's likely that we are going to produce another - // frame soon. This helps avoid negative glitches in our SetNeedsBeginFrame - // requests, which may propagate to the BeginImplFrame provider and get - // sampled at an inopportune time, delaying the next BeginImplFrame. + // frame soon. This helps avoid negative glitches in our + // SetNeedsBeginImplFrame requests, which may propagate to the BeginImplFrame + // provider and get sampled at an inopportune time, delaying the next + // BeginImplFrame. if (last_frame_number_swap_performed_ == current_frame_number_) return true; @@ -896,12 +901,19 @@ bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const { if (active_tree_needs_first_draw_) return true; + if (!needs_redraw_) + return false; + // This is used to prioritize impl-thread draws when the main thread isn't // producing anything, e.g., after an aborted commit. We also check that we // don't have a pending tree -- otherwise we should give it a chance to // activate. // TODO(skyostil): Revisit this when we have more accurate deadline estimates. - if (commit_state_ == COMMIT_STATE_IDLE && needs_redraw_ && !has_pending_tree_) + if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_) + return true; + + // Prioritize impl-thread draws in smoothness mode. + if (smoothness_takes_priority_) return true; return false; @@ -935,6 +947,11 @@ void SchedulerStateMachine::SetSwapUsedIncompleteTile( swap_used_incomplete_tile_ = used_incomplete_tile; } +void SchedulerStateMachine::SetSmoothnessTakesPriority( + bool smoothness_takes_priority) { + smoothness_takes_priority_ = smoothness_takes_priority; +} + void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) { draw_if_possible_failed_ = !success; if (draw_if_possible_failed_) { diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h index 01eeca60e8..9b6d4fb41e 100644 --- a/cc/scheduler/scheduler_state_machine.h +++ b/cc/scheduler/scheduler_state_machine.h @@ -171,6 +171,10 @@ class CC_EXPORT SchedulerStateMachine { // with a low resolution or checkerboarded tile. void SetSwapUsedIncompleteTile(bool used_incomplete_tile); + // Indicates whether to prioritize animation smoothness over new content + // activation. + void SetSmoothnessTakesPriority(bool smoothness_takes_priority); + // Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen. void DidDrawIfPossibleCompleted(bool success); @@ -283,6 +287,7 @@ class CC_EXPORT SchedulerStateMachine { bool active_tree_needs_first_draw_; bool draw_if_possible_failed_; bool did_create_and_initialize_first_output_surface_; + bool smoothness_takes_priority_; private: DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine); diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc index e58015dd26..67925a059b 100644 --- a/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/cc/scheduler/scheduler_state_machine_unittest.cc @@ -1735,5 +1735,31 @@ TEST(SchedulerStateMachineTest, EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly()); } +TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyForSmoothness) { + SchedulerSettings settings; + settings.deadline_scheduling_enabled = true; + settings.impl_side_painting = true; + StateMachine state(settings); + state.SetCanStart(); + state.UpdateState(state.NextAction()); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); + state.SetVisible(true); + state.SetCanDraw(true); + + // This test ensures that impl-draws are prioritized over main thread updates + // in prefer smoothness mode. + state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + state.SetNeedsRedraw(true); + state.SetNeedsCommit(); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + + // The deadline is not triggered early until we enter prefer smoothness mode. + EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineEarly()); + state.SetSmoothnessTakesPriority(true); + EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly()); +} + } // namespace } // namespace cc diff --git a/cc/scheduler/texture_uploader.cc b/cc/scheduler/texture_uploader.cc index cebc986891..ba4e372175 100644 --- a/cc/scheduler/texture_uploader.cc +++ b/cc/scheduler/texture_uploader.cc @@ -143,6 +143,13 @@ void TextureUploader::Upload(const uint8* image, if (is_full_upload) BeginQuery(); + if (format == ETC1) { + // ETC1 does not support subimage uploads. + DCHECK(is_full_upload); + UploadWithTexImageETC1(image, size); + return; + } + if (use_map_tex_sub_image_) { UploadWithMapTexSubImage( image, image_rect, source_rect, dest_offset, format); @@ -190,7 +197,7 @@ void TextureUploader::UploadWithTexSubImage(const uint8* image, gfx::Vector2d offset(source_rect.origin() - image_rect.origin()); const uint8* pixel_source; - unsigned bytes_per_pixel = BytesPerPixel(format); + unsigned bytes_per_pixel = BitsPerPixel(format) / 8; // Use 4-byte row alignment (OpenGL default) for upload performance. // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. unsigned upload_image_stride = @@ -239,11 +246,13 @@ void TextureUploader::UploadWithMapTexSubImage(const uint8* image, if (source_rect.IsEmpty()) return; DCHECK(image); + // Compressed textures have no implementation of mapTexSubImage. + DCHECK_NE(ETC1, format); // Offset from image-rect to source-rect. gfx::Vector2d offset(source_rect.origin() - image_rect.origin()); - unsigned bytes_per_pixel = BytesPerPixel(format); + unsigned bytes_per_pixel = BitsPerPixel(format) / 8; // Use 4-byte row alignment (OpenGL default) for upload performance. // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. unsigned upload_image_stride = @@ -285,6 +294,22 @@ void TextureUploader::UploadWithMapTexSubImage(const uint8* image, context_->unmapTexSubImage2DCHROMIUM(pixel_dest); } +void TextureUploader::UploadWithTexImageETC1(const uint8* image, + gfx::Size size) { + TRACE_EVENT0("cc", "TextureUploader::UploadWithTexImageETC1"); + DCHECK_EQ(0, size.width() % 4); + DCHECK_EQ(0, size.height() % 4); + + context_->compressedTexImage2D(GL_TEXTURE_2D, + 0, + GLInternalFormat(ETC1), + size.width(), + size.height(), + 0, + Resource::MemorySizeBytes(size, ETC1), + image); +} + void TextureUploader::ProcessQueries() { while (!pending_queries_.empty()) { if (pending_queries_.front()->IsPending()) diff --git a/cc/scheduler/texture_uploader.h b/cc/scheduler/texture_uploader.h index a131ba04f9..5b1b1d8332 100644 --- a/cc/scheduler/texture_uploader.h +++ b/cc/scheduler/texture_uploader.h @@ -103,6 +103,7 @@ class CC_EXPORT TextureUploader { gfx::Rect source_rect, gfx::Vector2d dest_offset, ResourceFormat format); + void UploadWithTexImageETC1(const uint8* image, gfx::Size size); WebKit::WebGraphicsContext3D* context_; ScopedPtrDeque<Query> pending_queries_; diff --git a/cc/test/data/background_filter_blur_off_axis.png b/cc/test/data/background_filter_blur_off_axis.png Binary files differindex 59488a6201..b5777f42e0 100644 --- a/cc/test/data/background_filter_blur_off_axis.png +++ b/cc/test/data/background_filter_blur_off_axis.png diff --git a/cc/test/data/touch_region_heavy.json b/cc/test/data/touch_region_heavy.json new file mode 100644 index 0000000000..26d618e508 --- /dev/null +++ b/cc/test/data/touch_region_heavy.json @@ -0,0 +1,515 @@ +{ + "Bounds": [ 0, 0 ], + "Children": [ { + "Bounds": [ 384, 640 ], + "Children": [ { + "Bounds": [ 384, 1681 ], + "Children": [ { + "Bounds": [ 384, 1681 ], + "Children": [ { + "Bounds": [ 384, 1681 ], + "Children": [ { + "Bounds": [ 298, 114 ], + "Children": [ { + "Bounds": [ 12979, 130 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -10288.0, 118.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ -9999.0, -1.0 ], + "TouchRegion": [ -9999, -1, 11499, 1, -9999, 0, 12979, 126, -9999, 126, 11499, 3 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 11.0, 119.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 11.0, 120.0 ] + }, { + "Bounds": [ 320, 320 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 0.0, + "Position": [ 4.0, 5.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 287.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 288.0 ] + }, { + "Bounds": [ 320, 320 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 0.0, + "Position": [ 4.0, 5.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 287.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 288.0 ] + }, { + "Bounds": [ 320, 320 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 0.0, + "Position": [ 4.0, 5.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 287.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 288.0 ] + }, { + "Bounds": [ 320, 320 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 0.0, + "Position": [ 4.0, 5.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 287.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 288.0 ] + }, { + "Bounds": [ 300, 114 ], + "Children": [ { + "Bounds": [ 300, 114 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 10.0, 119.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ], + "TouchRegion": [ 0, -1, 300, 115, 1, 114, 298, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 10.0, 119.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 10.0, 120.0 ] + }, { + "Bounds": [ 300, 114 ], + "Children": [ { + "Bounds": [ 18, 36 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 10.0, 154.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 35.0 ], + "TouchRegion": [ -9999, -1, 10017, 36 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 10.0, 119.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 10.0, 120.0 ] + }, { + "Bounds": [ 300, 114 ], + "Children": [ { + "Bounds": [ 300, 36 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 10.0, 154.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 35.0 ], + "TouchRegion": [ -9999, -1, 10017, 36 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 10.0, 119.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 10.0, 120.0 ] + }, { + "Bounds": [ 320, 320 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 4.0, 292.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 287.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 288.0 ] + }, { + "Bounds": [ 320, 320 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 164.0, 292.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 287.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 288.0 ] + }, { + "Bounds": [ 320, 320 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 4.0, 452.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 287.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 288.0 ] + }, { + "Bounds": [ 320, 320 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 164.0, 452.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 287.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 288.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 4.0, 658.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 164.0, 658.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 4.0, 818.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 164.0, 818.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 4.0, 978.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 164.0, 978.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 4.0, 1138.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 164.0, 1138.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 4.0, 1298.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 800 ], + "Children": [ { + "Bounds": [ 152, 152 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 164.0, 1298.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 4.0, 5.0 ], + "TouchRegion": [ -1, 0, 152, 117, -9895, 117, 10046, 5, -9994, 122, 10145, 24, -9895, 146, 10046, 1, -1, 147, 152, 5, 5, 152, 140, 1 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 653.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 654.0 ] + }, { + "Bounds": [ 320, 1498 ], + "Children": [ { + "Bounds": [ 104, 37 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 5.0, 256.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 5.0, 147.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 109.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 110.0 ] + }, { + "Bounds": [ 320, 1498 ], + "Children": [ { + "Bounds": [ 1, 13 ], + "Children": [ ], + "ContentsOpaque": true, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 108.0, 266.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 108.0, 157.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 109.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 110.0 ] + } ], + "ContentsOpaque": true, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.0, -1.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ], + "TouchRegion": [ -9993, 0, 326, 50, 0, 0, 320, 50, -9993, 50, 326, 6, -9990, 56, 320, 3, -9990, 59, 320, 1, 8, 59, 44, 1, -9990, 60, 320, 32, 8, 60, 44, 32, 247, 60, 65, 32, -9990, 92, 320, 1, 8, 92, 44, 1, -9990, 93, 320, 27, -9990, 120, 320, 48, 10, 120, 300, 48, -9990, 168, 320, 42, -262, 168, 262, 42, 10, 168, 300, 42, -9990, 210, 320, 2, 10, 210, 300, 2, -9990, 212, 320, 22, -262, 212, 262, 22, 10, 212, 300, 22, -9990, 234, 320, 20, -262, 234, 262, 20, -9990, 254, 320, 2, -9990, 256, 320, 42, -262, 256, 262, 42, -9990, 298, 320, 2, -9990, 300, 320, 42, -262, 300, 262, 42, -9990, 342, 320, 180 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.0, -1.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.0, -1.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ], + "Scrollable": true + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ] + }, { + "Bounds": [ 10, 640 ], + "Children": [ { + "Bounds": [ 10, 640 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 374.0, 0.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::PaintedScrollbarLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 374.0, 0.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 374.0, 0.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ] +} + diff --git a/cc/test/data/touch_region_light.json b/cc/test/data/touch_region_light.json new file mode 100644 index 0000000000..8b737b56e1 --- /dev/null +++ b/cc/test/data/touch_region_light.json @@ -0,0 +1,67 @@ +{ + "Bounds": [ 0, 0 ], + "Children": [ { + "Bounds": [ 384, 640 ], + "Children": [ { + "Bounds": [ 384, 732 ], + "Children": [ { + "Bounds": [ 384, 732 ], + "Children": [ { + "Bounds": [ 384, 732 ], + "Children": [ ], + "ContentsOpaque": true, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.0, -1.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ], + "TouchRegion": [ 0, 0, 384, 732 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.0, -1.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.0, -1.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ], + "Scrollable": true + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ] + }, { + "Bounds": [ 10, 640 ], + "Children": [ { + "Bounds": [ 10, 640 ], + "Children": [ ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 374.0, 0.0, 0.0, 1.0 ], + "DrawsContent": true, + "LayerType": "cc::PaintedScrollbarLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 374.0, 0.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 374.0, 0.0 ] + } ], + "ContentsOpaque": false, + "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], + "DrawsContent": false, + "LayerType": "cc::TiledLayerImpl", + "Opacity": 1.0, + "Position": [ 0.0, 0.0 ] +} + diff --git a/cc/test/fake_layer_tree_host.h b/cc/test/fake_layer_tree_host.h index 074355ddb8..3acfdd291e 100644 --- a/cc/test/fake_layer_tree_host.h +++ b/cc/test/fake_layer_tree_host.h @@ -46,7 +46,7 @@ class FakeLayerTreeHost : protected LayerTreeHost { private: FakeLayerTreeHost(LayerTreeHostClient* client, const LayerTreeSettings& settings) - : LayerTreeHost(client, settings), + : LayerTreeHost(client, NULL, settings), host_impl_(settings, &proxy_), needs_commit_(false) {} diff --git a/cc/test/fake_layer_tree_host_client.h b/cc/test/fake_layer_tree_host_client.h index 0a8470adac..a1e170819a 100644 --- a/cc/test/fake_layer_tree_host_client.h +++ b/cc/test/fake_layer_tree_host_client.h @@ -24,8 +24,8 @@ class FakeLayerTreeHostClient : public LayerTreeHostClient { explicit FakeLayerTreeHostClient(RendererOptions options); virtual ~FakeLayerTreeHostClient(); - virtual void WillBeginFrame() OVERRIDE {} - virtual void DidBeginFrame() OVERRIDE {} + virtual void WillBeginMainFrame() OVERRIDE {} + virtual void DidBeginMainFrame() OVERRIDE {} virtual void Animate(double frame_begin_time) OVERRIDE {} virtual void Layout() OVERRIDE {} virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta, diff --git a/cc/test/fake_layer_tree_host_impl.cc b/cc/test/fake_layer_tree_host_impl.cc index c1a7326f63..258617bc0f 100644 --- a/cc/test/fake_layer_tree_host_impl.cc +++ b/cc/test/fake_layer_tree_host_impl.cc @@ -11,18 +11,19 @@ FakeLayerTreeHostImpl::FakeLayerTreeHostImpl(Proxy* proxy) : LayerTreeHostImpl(LayerTreeSettings(), &client_, proxy, - &stats_instrumentation_) { + &stats_instrumentation_, + NULL) { // Explicitly clear all debug settings. SetDebugState(LayerTreeDebugState()); } -FakeLayerTreeHostImpl::FakeLayerTreeHostImpl( - const LayerTreeSettings& settings, - Proxy* proxy) +FakeLayerTreeHostImpl::FakeLayerTreeHostImpl(const LayerTreeSettings& settings, + Proxy* proxy) : LayerTreeHostImpl(settings, &client_, proxy, - &stats_instrumentation_) { + &stats_instrumentation_, + NULL) { // Explicitly clear all debug settings. SetDebugState(LayerTreeDebugState()); } diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h index b0e3a15807..708bbcf94e 100644 --- a/cc/test/fake_layer_tree_host_impl_client.h +++ b/cc/test/fake_layer_tree_host_impl_client.h @@ -15,7 +15,7 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient { // LayerTreeHostImplClient implementation. virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {} virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {} - virtual void BeginFrameOnImplThread(const BeginFrameArgs& args) + virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {} virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {} virtual void NotifyReadyToActivate() OVERRIDE {} @@ -30,7 +30,6 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient { virtual bool ReduceContentsTextureMemoryOnImplThread( size_t limit_bytes, int priority_cutoff) OVERRIDE; - virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE {} virtual void SendManagedMemoryStats() OVERRIDE {} virtual bool IsInsideDraw() OVERRIDE; virtual void RenewTreePriority() OVERRIDE {} diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc index ae5bd22707..a2d67f7f61 100644 --- a/cc/test/fake_output_surface.cc +++ b/cc/test/fake_output_surface.cc @@ -19,7 +19,7 @@ FakeOutputSurface::FakeOutputSurface( : OutputSurface(context_provider), client_(NULL), num_sent_frames_(0), - needs_begin_frame_(false), + needs_begin_impl_frame_(false), forced_draw_to_software_device_(false), has_external_stencil_test_(false), fake_weak_ptr_factory_(this) { @@ -84,22 +84,22 @@ void FakeOutputSurface::SwapBuffers(CompositorFrame* frame) { } } -void FakeOutputSurface::SetNeedsBeginFrame(bool enable) { - needs_begin_frame_ = enable; - OutputSurface::SetNeedsBeginFrame(enable); +void FakeOutputSurface::SetNeedsBeginImplFrame(bool enable) { + needs_begin_impl_frame_ = enable; + OutputSurface::SetNeedsBeginImplFrame(enable); - // If there is not BeginFrame emulation from the FrameRateController, - // then we just post a BeginFrame to emulate it as part of the test. + // If there is not BeginImplFrame emulation from the FrameRateController, + // then we just post a BeginImplFrame to emulate it as part of the test. if (enable && !frame_rate_controller_) { base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, base::Bind(&FakeOutputSurface::OnBeginFrame, + FROM_HERE, base::Bind(&FakeOutputSurface::OnBeginImplFrame, fake_weak_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(16)); } } -void FakeOutputSurface::OnBeginFrame() { - OutputSurface::BeginFrame(BeginFrameArgs::CreateForTesting()); +void FakeOutputSurface::OnBeginImplFrame() { + OutputSurface::BeginImplFrame(BeginFrameArgs::CreateForTesting()); } diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h index a93b4f3497..0540f13228 100644 --- a/cc/test/fake_output_surface.h +++ b/cc/test/fake_output_surface.h @@ -94,9 +94,9 @@ class FakeOutputSurface : public OutputSurface { virtual void SwapBuffers(CompositorFrame* frame) OVERRIDE; - virtual void SetNeedsBeginFrame(bool enable) OVERRIDE; - bool needs_begin_frame() const { - return needs_begin_frame_; + virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE; + bool needs_begin_impl_frame() const { + return needs_begin_impl_frame_; } void set_forced_draw_to_software_device(bool forced) { @@ -140,12 +140,12 @@ class FakeOutputSurface : public OutputSurface { scoped_ptr<SoftwareOutputDevice> software_device, bool delegated_rendering); - void OnBeginFrame(); + void OnBeginImplFrame(); OutputSurfaceClient* client_; CompositorFrame last_sent_frame_; size_t num_sent_frames_; - bool needs_begin_frame_; + bool needs_begin_impl_frame_; bool forced_draw_to_software_device_; bool has_external_stencil_test_; TransferableResourceArray resources_held_by_parent_; diff --git a/cc/test/fake_output_surface_client.cc b/cc/test/fake_output_surface_client.cc index 2ce6cf077f..841797403c 100644 --- a/cc/test/fake_output_surface_client.cc +++ b/cc/test/fake_output_surface_client.cc @@ -12,8 +12,8 @@ bool FakeOutputSurfaceClient::DeferredInitialize( return deferred_initialize_result_; } -void FakeOutputSurfaceClient::BeginFrame(const BeginFrameArgs& args) { - begin_frame_count_++; +void FakeOutputSurfaceClient::BeginImplFrame(const BeginFrameArgs& args) { + begin_impl_frame_count_++; } void FakeOutputSurfaceClient::DidLoseOutputSurface() { diff --git a/cc/test/fake_output_surface_client.h b/cc/test/fake_output_surface_client.h index 08511ad326..bf127d1d4f 100644 --- a/cc/test/fake_output_surface_client.h +++ b/cc/test/fake_output_surface_client.h @@ -13,7 +13,7 @@ namespace cc { class FakeOutputSurfaceClient : public OutputSurfaceClient { public: FakeOutputSurfaceClient() - : begin_frame_count_(0), + : begin_impl_frame_count_(0), deferred_initialize_result_(true), deferred_initialize_called_(false), did_lose_output_surface_called_(false), @@ -24,7 +24,7 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient { scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE; virtual void ReleaseGL() OVERRIDE {} virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {} - virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE; + virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE; virtual void OnSwapBuffersComplete() OVERRIDE {} virtual void ReclaimResources(const CompositorFrameAck* ack) OVERRIDE {} virtual void DidLoseOutputSurface() OVERRIDE; @@ -37,8 +37,8 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient { virtual void SetDiscardBackBufferWhenNotVisible(bool discard) OVERRIDE; virtual void SetTreeActivationCallback(const base::Closure&) OVERRIDE {} - int begin_frame_count() { - return begin_frame_count_; + int begin_impl_frame_count() { + return begin_impl_frame_count_; } void set_deferred_initialize_result(bool result) { @@ -60,7 +60,7 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient { } private: - int begin_frame_count_; + int begin_impl_frame_count_; bool deferred_initialize_result_; bool deferred_initialize_called_; bool did_lose_output_surface_called_; diff --git a/cc/test/fake_picture_layer_impl.h b/cc/test/fake_picture_layer_impl.h index 2eeaeef959..759ceeb938 100644 --- a/cc/test/fake_picture_layer_impl.h +++ b/cc/test/fake_picture_layer_impl.h @@ -47,6 +47,7 @@ class FakePictureLayerImpl : public PictureLayerImpl { PictureLayerImpl* twin_layer() { return twin_layer_; } PictureLayerTilingSet* tilings() { return tilings_.get(); } + PicturePileImpl* pile() { return pile_.get(); } size_t append_quads_count() { return append_quads_count_; } const Region& invalidation() const { return invalidation_; } diff --git a/cc/test/fake_picture_pile_impl.cc b/cc/test/fake_picture_pile_impl.cc index 03084ed7be..989c4f9f7a 100644 --- a/cc/test/fake_picture_pile_impl.cc +++ b/cc/test/fake_picture_pile_impl.cc @@ -65,19 +65,12 @@ void FakePicturePileImpl::AddRecordingAt(int x, int y) { scoped_refptr<Picture> picture(Picture::Create(bounds)); picture->Record(&client_, tile_grid_info_); picture->GatherPixelRefs(tile_grid_info_); - picture_list_map_[std::pair<int, int>(x, y)].push_back(picture); + picture_map_[std::pair<int, int>(x, y)].picture = picture; EXPECT_TRUE(HasRecordingAt(x, y)); UpdateRecordedRegion(); } -void FakePicturePileImpl::AddPictureToRecording( - int x, - int y, - scoped_refptr<Picture> picture) { - picture_list_map_[std::pair<int, int>(x, y)].push_back(picture); -} - void FakePicturePileImpl::RemoveRecordingAt(int x, int y) { EXPECT_GE(x, 0); EXPECT_GE(y, 0); @@ -86,7 +79,7 @@ void FakePicturePileImpl::RemoveRecordingAt(int x, int y) { if (!HasRecordingAt(x, y)) return; - picture_list_map_.erase(std::pair<int, int>(x, y)); + picture_map_.erase(std::pair<int, int>(x, y)); EXPECT_FALSE(HasRecordingAt(x, y)); UpdateRecordedRegion(); diff --git a/cc/test/fake_picture_pile_impl.h b/cc/test/fake_picture_pile_impl.h index 770dffe4e3..935e4a254e 100644 --- a/cc/test/fake_picture_pile_impl.h +++ b/cc/test/fake_picture_pile_impl.h @@ -29,11 +29,6 @@ class FakePicturePileImpl : public PicturePileImpl { void RemoveRecordingAt(int x, int y); void RerecordPile(); - void AddPictureToRecording( - int x, - int y, - scoped_refptr<Picture> picture); - void add_draw_rect(const gfx::RectF& rect) { client_.add_draw_rect(rect, default_paint_); } diff --git a/cc/test/fake_proxy.cc b/cc/test/fake_proxy.cc index 3fe12c85c9..90c5b1c1cd 100644 --- a/cc/test/fake_proxy.cc +++ b/cc/test/fake_proxy.cc @@ -29,6 +29,8 @@ RendererCapabilities& FakeProxy::GetRendererCapabilities() { return capabilities_; } +bool FakeProxy::BeginMainFrameRequested() const { return false; } + bool FakeProxy::CommitRequested() const { return false; } size_t FakeProxy::MaxPartialTextureUpdates() const { diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h index 3127cb430e..bcde11ecb7 100644 --- a/cc/test/fake_proxy.h +++ b/cc/test/fake_proxy.h @@ -36,6 +36,7 @@ class FakeProxy : public Proxy { virtual void NotifyInputThrottledUntilCommit() OVERRIDE {} virtual void SetDeferCommits(bool defer_commits) OVERRIDE {} virtual void MainThreadHasStoppedFlinging() OVERRIDE {} + virtual bool BeginMainFrameRequested() const OVERRIDE; virtual bool CommitRequested() const OVERRIDE; virtual void Start(scoped_ptr<OutputSurface> first_output_surface) OVERRIDE {} virtual void Stop() OVERRIDE {} diff --git a/cc/test/fake_ui_resource_layer_tree_host_impl.cc b/cc/test/fake_ui_resource_layer_tree_host_impl.cc index ec087f25a8..c1d3e75181 100644 --- a/cc/test/fake_ui_resource_layer_tree_host_impl.cc +++ b/cc/test/fake_ui_resource_layer_tree_host_impl.cc @@ -18,7 +18,12 @@ void FakeUIResourceLayerTreeHostImpl::CreateUIResource( const UIResourceBitmap& bitmap) { if (ResourceIdForUIResource(uid)) DeleteUIResource(uid); - fake_ui_resource_map_[uid] = fake_next_resource_id_; + + UIResourceData data; + data.resource_id = fake_next_resource_id_++; + data.size = bitmap.GetSize(); + data.opaque = bitmap.GetOpaque(); + fake_ui_resource_map_[uid] = data; } void FakeUIResourceLayerTreeHostImpl::DeleteUIResource(UIResourceId uid) { @@ -32,8 +37,15 @@ ResourceProvider::ResourceId UIResourceId uid) const { UIResourceMap::const_iterator iter = fake_ui_resource_map_.find(uid); if (iter != fake_ui_resource_map_.end()) - return iter->second; + return iter->second.resource_id; return 0; } +bool FakeUIResourceLayerTreeHostImpl::IsUIResourceOpaque(UIResourceId uid) + const { + UIResourceMap::const_iterator iter = fake_ui_resource_map_.find(uid); + DCHECK(iter != fake_ui_resource_map_.end()); + return iter->second.opaque; +} + } // namespace cc diff --git a/cc/test/fake_ui_resource_layer_tree_host_impl.h b/cc/test/fake_ui_resource_layer_tree_host_impl.h index eceece96df..7e461dfe28 100644 --- a/cc/test/fake_ui_resource_layer_tree_host_impl.h +++ b/cc/test/fake_ui_resource_layer_tree_host_impl.h @@ -23,9 +23,11 @@ class FakeUIResourceLayerTreeHostImpl : public FakeLayerTreeHostImpl { virtual ResourceProvider::ResourceId ResourceIdForUIResource( UIResourceId uid) const OVERRIDE; + virtual bool IsUIResourceOpaque(UIResourceId uid) const OVERRIDE; + private: ResourceProvider::ResourceId fake_next_resource_id_; - typedef base::hash_map<UIResourceId, ResourceProvider::ResourceId> + typedef base::hash_map<UIResourceId, LayerTreeHostImpl::UIResourceData> UIResourceMap; UIResourceMap fake_ui_resource_map_; }; diff --git a/cc/test/layer_tree_json_parser.cc b/cc/test/layer_tree_json_parser.cc index af24571be9..9a1b198a7b 100644 --- a/cc/test/layer_tree_json_parser.cc +++ b/cc/test/layer_tree_json_parser.cc @@ -53,8 +53,8 @@ scoped_refptr<Layer> ParseTreeFromValue(base::Value* val, ListValue* bounds; success &= dict->GetList("ImageBounds", &bounds); double image_width, image_height; - success &= bounds->GetDouble(0, &image_height); - success &= bounds->GetDouble(1, &image_width); + success &= bounds->GetDouble(0, &image_width); + success &= bounds->GetDouble(1, &image_height); success &= dict->GetList("Border", &list); int border_x, border_y, border_width, border_height; @@ -81,7 +81,7 @@ scoped_refptr<Layer> ParseTreeFromValue(base::Value* val, new_layer = nine_patch_layer; } else if (layer_type == "TextureLayer") { - new_layer = TextureLayer::Create(NULL); + new_layer = TextureLayer::CreateForMailbox(NULL); } else if (layer_type == "PictureLayer") { new_layer = PictureLayer::Create(content_client); } else { // Type "Layer" or "unknown" @@ -104,6 +104,24 @@ scoped_refptr<Layer> ParseTreeFromValue(base::Value* val, if (dict->GetBoolean("Scrollable", &scrollable)) new_layer->SetScrollable(scrollable); + bool wheel_handler; + if (dict->GetBoolean("WheelHandler", &wheel_handler)) + new_layer->SetHaveWheelEventHandlers(wheel_handler); + + if (dict->HasKey("TouchRegion")) { + success &= dict->GetList("TouchRegion", &list); + cc::Region touch_region; + for (size_t i = 0; i < list->GetSize(); ) { + int rect_x, rect_y, rect_width, rect_height; + success &= list->GetInteger(i++, &rect_x); + success &= list->GetInteger(i++, &rect_y); + success &= list->GetInteger(i++, &rect_width); + success &= list->GetInteger(i++, &rect_height); + touch_region.Union(gfx::Rect(rect_x, rect_y, rect_width, rect_height)); + } + new_layer->SetTouchEventHandlerRegion(touch_region); + } + success &= dict->GetList("DrawTransform", &list); double transform[16]; for (int i = 0; i < 16; ++i) diff --git a/cc/test/layer_tree_json_parser_unittest.cc b/cc/test/layer_tree_json_parser_unittest.cc new file mode 100644 index 0000000000..4261a71109 --- /dev/null +++ b/cc/test/layer_tree_json_parser_unittest.cc @@ -0,0 +1,116 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/test/layer_tree_json_parser.h" + +#include "cc/layers/layer.h" +#include "cc/test/fake_impl_proxy.h" +#include "cc/test/fake_layer_tree_host.h" +#include "cc/test/fake_layer_tree_host_impl.h" +#include "cc/test/geometry_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { + +namespace { + +bool LayerTreesMatch(LayerImpl* const layer_impl, + Layer* const layer) { +#define RETURN_IF_EXPECTATION_FAILS(exp) \ + do { \ + exp; \ + if (testing::UnitTest::GetInstance()->current_test_info()-> \ + result()->Failed()) \ + return false; \ + } while (0) + + RETURN_IF_EXPECTATION_FAILS(EXPECT_EQ(layer_impl->children().size(), + layer->children().size())); + RETURN_IF_EXPECTATION_FAILS(EXPECT_SIZE_EQ(layer_impl->bounds(), + layer->bounds())); + RETURN_IF_EXPECTATION_FAILS(EXPECT_POINT_EQ(layer_impl->position(), + layer->position())); + RETURN_IF_EXPECTATION_FAILS( + EXPECT_TRANSFORMATION_MATRIX_EQ(layer_impl->draw_transform(), + layer->draw_transform())); + RETURN_IF_EXPECTATION_FAILS(EXPECT_EQ(layer_impl->contents_opaque(), + layer->contents_opaque())); + RETURN_IF_EXPECTATION_FAILS(EXPECT_EQ(layer_impl->scrollable(), + layer->scrollable())); + RETURN_IF_EXPECTATION_FAILS(EXPECT_FLOAT_EQ(layer_impl->opacity(), + layer->opacity())); + RETURN_IF_EXPECTATION_FAILS(EXPECT_EQ(layer_impl->have_wheel_event_handlers(), + layer->have_wheel_event_handlers())); + RETURN_IF_EXPECTATION_FAILS( + EXPECT_EQ(layer_impl->touch_event_handler_region(), + layer->touch_event_handler_region())); + + for (size_t i = 0; i < layer_impl->children().size(); ++i) { + RETURN_IF_EXPECTATION_FAILS( + EXPECT_TRUE(LayerTreesMatch(layer_impl->children()[i], + layer->children()[i]))); + } + + return true; +#undef RETURN_IF_EXPECTATION_FAILS +} + +} // namespace + +class LayerTreeJsonParserSanityCheck : public testing::Test { +}; + +TEST_F(LayerTreeJsonParserSanityCheck, Basic) { + FakeImplProxy proxy; + FakeLayerTreeHostImpl host_impl(&proxy); + LayerTreeImpl* tree = host_impl.active_tree(); + + scoped_ptr<LayerImpl> root_impl(LayerImpl::Create(tree, 1)); + scoped_ptr<LayerImpl> parent(LayerImpl::Create(tree, 2)); + scoped_ptr<LayerImpl> child(LayerImpl::Create(tree, 3)); + + root_impl->SetBounds(gfx::Size(100, 100)); + parent->SetBounds(gfx::Size(50, 50)); + child->SetBounds(gfx::Size(40, 40)); + + parent->SetPosition(gfx::Point(25, 25)); + + child->SetHaveWheelEventHandlers(true); + + parent->AddChild(child.Pass()); + root_impl->AddChild(parent.Pass()); + tree->SetRootLayer(root_impl.Pass()); + + std::string json = host_impl.LayerTreeAsJson(); + scoped_refptr<Layer> root = ParseTreeFromJson(json, NULL); + ASSERT_TRUE(root); + EXPECT_TRUE(LayerTreesMatch(host_impl.RootLayer(), root.get())); +} + +TEST_F(LayerTreeJsonParserSanityCheck, EventHandlerRegions) { + FakeImplProxy proxy; + FakeLayerTreeHostImpl host_impl(&proxy); + LayerTreeImpl* tree = host_impl.active_tree(); + + scoped_ptr<LayerImpl> root_impl(LayerImpl::Create(tree, 1)); + scoped_ptr<LayerImpl> touch_layer(LayerImpl::Create(tree, 2)); + + root_impl->SetBounds(gfx::Size(100, 100)); + touch_layer->SetBounds(gfx::Size(50, 50)); + + cc::Region touch_region; + touch_region.Union(gfx::Rect(10, 10, 20, 30)); + touch_region.Union(gfx::Rect(40, 10, 20, 20)); + touch_layer->SetTouchEventHandlerRegion(touch_region); + + root_impl->AddChild(touch_layer.Pass()); + tree->SetRootLayer(root_impl.Pass()); + + std::string json = host_impl.LayerTreeAsJson(); + scoped_refptr<Layer> root = ParseTreeFromJson(json, NULL); + ASSERT_TRUE(root); + EXPECT_TRUE(LayerTreesMatch(host_impl.RootLayer(), root.get())); +} + +} // namespace cc diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index 70e6223f30..d0a5c59d4e 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc @@ -4,7 +4,9 @@ #include "cc/test/layer_tree_pixel_test.h" +#include "base/command_line.h" #include "base/path_service.h" +#include "cc/base/switches.h" #include "cc/layers/solid_color_layer.h" #include "cc/layers/texture_layer.h" #include "cc/output/copy_output_request.h" @@ -96,8 +98,9 @@ void LayerTreePixelTest::AfterTest() { EXPECT_TRUE(PathService::Get(cc::DIR_TEST_DATA, &test_data_dir)); base::FilePath ref_file_path = test_data_dir.Append(ref_file_); - // To rebaseline: - // EXPECT_TRUE(WritePNGFile(*result_bitmap_, ref_file_path, true)); + CommandLine* cmd = CommandLine::ForCurrentProcess(); + if (cmd->HasSwitch(switches::kCCRebaselinePixeltests)) + EXPECT_TRUE(WritePNGFile(*result_bitmap_, ref_file_path, true)); EXPECT_TRUE(MatchesPNGFile(*result_bitmap_, ref_file_path, diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index da0ed55872..9ca0bbde14 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc @@ -23,6 +23,7 @@ #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/single_thread_proxy.h" #include "testing/gmock/include/gmock/gmock.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/size_conversions.h" namespace cc { @@ -68,14 +69,15 @@ class LayerTreeHostImplForTesting : public LayerTreeHostImpl { : LayerTreeHostImpl(settings, host_impl_client, proxy, - stats_instrumentation), + stats_instrumentation, + NULL), test_hooks_(test_hooks), block_notify_ready_to_activate_for_testing_(false), notify_ready_to_activate_was_blocked_(false) {} - virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE { + virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE { test_hooks_->WillBeginImplFrameOnThread(this, args); - LayerTreeHostImpl::BeginFrame(args); + LayerTreeHostImpl::BeginImplFrame(args); test_hooks_->DidBeginImplFrameOnThread(this, args); } @@ -233,7 +235,7 @@ class LayerTreeHostForTesting : public LayerTreeHost { LayerTreeHostForTesting(TestHooks* test_hooks, LayerTreeHostClient* client, const LayerTreeSettings& settings) - : LayerTreeHost(client, settings), + : LayerTreeHost(client, NULL, settings), test_hooks_(test_hooks), test_started_(false) {} @@ -250,9 +252,13 @@ class LayerTreeHostClientForTesting : public LayerTreeHostClient { } virtual ~LayerTreeHostClientForTesting() {} - virtual void WillBeginFrame() OVERRIDE { test_hooks_->WillBeginFrame(); } + virtual void WillBeginMainFrame() OVERRIDE { + test_hooks_->WillBeginMainFrame(); + } - virtual void DidBeginFrame() OVERRIDE { test_hooks_->DidBeginFrame(); } + virtual void DidBeginMainFrame() OVERRIDE { + test_hooks_->DidBeginMainFrame(); + } virtual void Animate(double monotonic_time) OVERRIDE { test_hooks_->Animate(base::TimeTicks::FromInternalValue( @@ -586,7 +592,7 @@ void LayerTreeTest::DispatchComposite() { } schedule_when_set_visible_true_ = false; - base::TimeTicks now = base::TimeTicks::Now(); + base::TimeTicks now = gfx::FrameTime::Now(); layer_tree_host_->Composite(now); } @@ -602,7 +608,7 @@ void LayerTreeTest::RunTest(bool threaded, delegating_renderer_ = delegating_renderer; - // Spend less time waiting for BeginFrame because the output is + // Spend less time waiting for BeginImplFrame because the output is // mocked out. settings_.refresh_rate = 200.0; if (impl_side_painting) { diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index 4fb5525e7e..aa5583745e 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h @@ -57,8 +57,8 @@ class TestHooks : public AnimationDelegate { virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta, float scale) {} virtual void Animate(base::TimeTicks monotonic_time) {} - virtual void WillBeginFrame() {} - virtual void DidBeginFrame() {} + virtual void WillBeginMainFrame() {} + virtual void DidBeginMainFrame() {} virtual void Layout() {} virtual void DidInitializeOutputSurface(bool succeeded) {} virtual void DidFailToInitializeOutputSurface() {} diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc index 05688b1de5..12b729b31d 100644 --- a/cc/test/pixel_test.cc +++ b/cc/test/pixel_test.cc @@ -4,8 +4,10 @@ #include "cc/test/pixel_test.h" +#include "base/command_line.h" #include "base/path_service.h" #include "base/run_loop.h" +#include "cc/base/switches.h" #include "cc/output/compositor_frame_metadata.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" @@ -49,7 +51,7 @@ class PixelTest::PixelTestRendererClient } virtual void ReleaseGL() OVERRIDE {} virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {} - virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {} + virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {} virtual void OnSwapBuffersComplete() OVERRIDE {} virtual void ReclaimResources(const CompositorFrameAck* ack) OVERRIDE {} virtual void DidLoseOutputSurface() OVERRIDE {} @@ -147,8 +149,9 @@ bool PixelTest::PixelsMatchReference(const base::FilePath& ref_file, if (!result_bitmap_) return false; - // To rebaseline: - // return WritePNGFile(*result_bitmap_, test_data_dir.Append(ref_file), true); + CommandLine* cmd = CommandLine::ForCurrentProcess(); + if (cmd->HasSwitch(switches::kCCRebaselinePixeltests)) + return WritePNGFile(*result_bitmap_, test_data_dir.Append(ref_file), true); return MatchesPNGFile(*result_bitmap_, test_data_dir.Append(ref_file), @@ -165,7 +168,7 @@ void PixelTest::SetUpGLRenderer(bool use_skia_gpu_backend) { output_surface_->BindToClient(fake_client_.get()); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false); texture_mailbox_deleter_ = make_scoped_ptr(new TextureMailboxDeleter); @@ -208,12 +211,12 @@ void PixelTest::SetUpSoftwareRenderer() { output_surface_.reset(new PixelTestOutputSurface(device.Pass())); output_surface_->BindToClient(fake_client_.get()); resource_provider_ = - ResourceProvider::Create(output_surface_.get(), 0, false); + ResourceProvider::Create(output_surface_.get(), NULL, 0, false); renderer_ = SoftwareRenderer::Create(fake_client_.get(), &settings_, output_surface_.get(), resource_provider_.get()) - .PassAs<DirectRenderer>(); + .PassAs<DirectRenderer>(); } } // namespace cc diff --git a/cc/test/run_all_perftests.cc b/cc/test/run_all_perftests.cc new file mode 100644 index 0000000000..abe854986d --- /dev/null +++ b/cc/test/run_all_perftests.cc @@ -0,0 +1,16 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/test/cc_test_suite.h" +#include "testing/gmock/include/gmock/gmock.h" + +int main(int argc, char** argv) { + ::testing::InitGoogleMock(&argc, argv); + cc::CCTestSuite test_suite(argc, argv); + + // Always run the perf tests serially, to avoid distorting + // perf measurements with randomness resulting from running + // in parallel. + return test_suite.Run(); +} diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 2d3c6083c5..d93e3d5e03 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc @@ -95,10 +95,11 @@ bool LayerTreeHost::AnyLayerTreeHostInstanceExists() { scoped_ptr<LayerTreeHost> LayerTreeHost::Create( LayerTreeHostClient* client, + SharedBitmapManager* manager, const LayerTreeSettings& settings, scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { - scoped_ptr<LayerTreeHost> layer_tree_host(new LayerTreeHost(client, - settings)); + scoped_ptr<LayerTreeHost> layer_tree_host( + new LayerTreeHost(client, manager, settings)); if (!layer_tree_host->Initialize(impl_task_runner)) return scoped_ptr<LayerTreeHost>(); return layer_tree_host.Pass(); @@ -107,6 +108,7 @@ scoped_ptr<LayerTreeHost> LayerTreeHost::Create( static int s_next_tree_id = 1; LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client, + SharedBitmapManager* manager, const LayerTreeSettings& settings) : next_ui_resource_id_(1), animating_(false), @@ -134,7 +136,8 @@ LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client, in_paint_layer_contents_(false), total_frames_used_for_lcd_text_metrics_(0), tree_id_(s_next_tree_id++), - next_commit_forces_redraw_(false) { + next_commit_forces_redraw_(false), + shared_bitmap_manager_(manager) { if (settings_.accelerated_animation_enabled) animation_registrar_ = AnimationRegistrar::Create(); s_num_layer_tree_instances++; @@ -258,8 +261,8 @@ void LayerTreeHost::AcquireLayerTextures() { proxy_->AcquireLayerTextures(); } -void LayerTreeHost::DidBeginFrame() { - client_->DidBeginFrame(); +void LayerTreeHost::DidBeginMainFrame() { + client_->DidBeginMainFrame(); } void LayerTreeHost::UpdateClientAnimations(base::TimeTicks frame_begin_time) { @@ -310,7 +313,8 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) { host_impl->set_max_memory_needed_bytes( contents_texture_manager_->MaxMemoryNeededBytes()); - contents_texture_manager_->UpdateBackingsInDrawingImplTree(); + contents_texture_manager_->UpdateBackingsState( + host_impl->resource_provider()); } // In impl-side painting, synchronize to the pending tree so that it has @@ -469,7 +473,9 @@ scoped_ptr<LayerTreeHostImpl> LayerTreeHost::CreateLayerTreeHostImpl( LayerTreeHostImpl::Create(settings_, client, proxy_.get(), - rendering_stats_instrumentation_.get()); + rendering_stats_instrumentation_.get(), + shared_bitmap_manager_); + shared_bitmap_manager_ = NULL; if (settings_.calculate_top_controls_position && host_impl->top_controls_manager()) { top_controls_manager_weak_ptr_ = @@ -567,6 +573,11 @@ bool LayerTreeHost::CommitRequested() const { return proxy_->CommitRequested(); } +bool LayerTreeHost::BeginMainFrameRequested() const { + return proxy_->BeginMainFrameRequested(); +} + + void LayerTreeHost::SetNextCommitWaitsForActivation() { proxy_->SetNextCommitWaitsForActivation(); } @@ -688,8 +699,9 @@ void LayerTreeHost::SetOverhangBitmap(const SkBitmap& bitmap) { bitmap_copy.setImmutable(); } - overhang_ui_resource_ = ScopedUIResource::Create( - this, UIResourceBitmap(bitmap_copy, UIResourceBitmap::REPEAT)); + UIResourceBitmap overhang_bitmap(bitmap_copy); + overhang_bitmap.SetWrapMode(UIResourceBitmap::REPEAT); + overhang_ui_resource_ = ScopedUIResource::Create(this, overhang_bitmap); } void LayerTreeHost::SetVisible(bool visible) { diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index fa025b67f2..c79f3e515f 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h @@ -67,6 +67,7 @@ class Region; class RenderingStatsInstrumentation; class ResourceProvider; class ResourceUpdateQueue; +class SharedBitmapManager; class TopControlsManager; struct RenderingStats; struct ScrollAndScaleSet; @@ -123,8 +124,10 @@ class CC_EXPORT UIResourceRequest { class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) { public: + // The SharedBitmapManager will be used on the compositor thread. static scoped_ptr<LayerTreeHost> Create( LayerTreeHostClient* client, + SharedBitmapManager* manager, const LayerTreeSettings& settings, scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner); virtual ~LayerTreeHost(); @@ -140,8 +143,8 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) { } // LayerTreeHost interface to Proxy. - void WillBeginFrame() { client_->WillBeginFrame(); } - void DidBeginFrame(); + void WillBeginMainFrame() { client_->WillBeginMainFrame(); } + void DidBeginMainFrame(); void UpdateClientAnimations(base::TimeTicks monotonic_frame_begin_time); void AnimateLayers(base::TimeTicks monotonic_frame_begin_time); void DidStopFlinging(); @@ -212,6 +215,7 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) { void SetNeedsRedraw(); void SetNeedsRedrawRect(gfx::Rect damage_rect); bool CommitRequested() const; + bool BeginMainFrameRequested() const; void SetNextCommitWaitsForActivation(); @@ -223,6 +227,7 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) { void SetRootLayer(scoped_refptr<Layer> root_layer); Layer* root_layer() { return root_layer_.get(); } const Layer* root_layer() const { return root_layer_.get(); } + const Layer* page_scale_layer() const { return page_scale_layer_.get(); } void RegisterViewportLayers( scoped_refptr<Layer> page_scale_layer, scoped_refptr<Layer> inner_viewport_scroll_layer, @@ -324,7 +329,9 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) { const MicroBenchmark::DoneCallback& callback); protected: - LayerTreeHost(LayerTreeHostClient* client, const LayerTreeSettings& settings); + LayerTreeHost(LayerTreeHostClient* client, + SharedBitmapManager* manager, + const LayerTreeSettings& settings); bool Initialize(scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner); bool InitializeForTesting(scoped_ptr<Proxy> proxy_for_testing); void SetOutputSurfaceLostForTesting(bool is_lost) { @@ -465,6 +472,8 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) { scoped_refptr<Layer> inner_viewport_scroll_layer_; scoped_refptr<Layer> outer_viewport_scroll_layer_; + SharedBitmapManager* shared_bitmap_manager_; + DISALLOW_COPY_AND_ASSIGN(LayerTreeHost); }; diff --git a/cc/trees/layer_tree_host_client.h b/cc/trees/layer_tree_host_client.h index 648ee85b4b..bde12dadc7 100644 --- a/cc/trees/layer_tree_host_client.h +++ b/cc/trees/layer_tree_host_client.h @@ -19,10 +19,10 @@ class OutputSurface; class LayerTreeHostClient { public: - virtual void WillBeginFrame() = 0; + virtual void WillBeginMainFrame() = 0; // Marks finishing compositing-related tasks on the main thread. In threaded // mode, this corresponds to DidCommit(). - virtual void DidBeginFrame() = 0; + virtual void DidBeginMainFrame() = 0; virtual void Animate(double frame_begin_time) = 0; virtual void Layout() = 0; virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta, diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 3ccedb14fe..4095900fae 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc @@ -135,8 +135,13 @@ static gfx::Vector2dF ComputeChangeOfBasisTranslation( gfx::Vector2dF translation; for (const LayerType* target = descendant_target; target != ancestor_target; - target = NextTargetSurface(target)) - translation += target->render_surface()->draw_transform().To2dTranslation(); + target = NextTargetSurface(target)) { + const gfx::Transform& trans = target->render_surface()->draw_transform(); + // Ensure that this translation is truly 2d. + DCHECK(trans.IsIdentityOrTranslation()); + DCHECK_EQ(0.f, trans.matrix().get(2, 3)); + translation += trans.To2dTranslation(); + } return translation; } @@ -743,7 +748,8 @@ void ApplyPositionAdjustment( gfx::Transform ComputeScrollCompensationForThisLayer( LayerImpl* scrolling_layer, - const gfx::Transform& parent_matrix) { + const gfx::Transform& parent_matrix, + gfx::Vector2dF scroll_delta) { // For every layer that has non-zero scroll_delta, we have to compute a // transform that can undo the scroll_delta translation. In particular, we // want this matrix to premultiply a fixed-position layer's parent_matrix, so @@ -765,7 +771,6 @@ gfx::Transform ComputeScrollCompensationForThisLayer( // gfx::Transform scroll_compensation_for_this_layer = parent_matrix; // Step 3 - gfx::Vector2dF scroll_delta = GetEffectiveScrollDelta(scrolling_layer); scroll_compensation_for_this_layer.Translate( scroll_delta.x(), scroll_delta.y()); // Step 2 @@ -783,7 +788,8 @@ gfx::Transform ComputeScrollCompensationForThisLayer( gfx::Transform ComputeScrollCompensationMatrixForChildren( Layer* current_layer, const gfx::Transform& current_parent_matrix, - const gfx::Transform& current_scroll_compensation) { + const gfx::Transform& current_scroll_compensation, + gfx::Vector2dF scroll_delta) { // The main thread (i.e. Layer) does not need to worry about scroll // compensation. So we can just return an identity matrix here. return gfx::Transform(); @@ -792,7 +798,8 @@ gfx::Transform ComputeScrollCompensationMatrixForChildren( gfx::Transform ComputeScrollCompensationMatrixForChildren( LayerImpl* layer, const gfx::Transform& parent_matrix, - const gfx::Transform& current_scroll_compensation_matrix) { + const gfx::Transform& current_scroll_compensation_matrix, + gfx::Vector2dF scroll_delta) { // "Total scroll compensation" is the transform needed to cancel out all // scroll_delta translations that occurred since the nearest container layer, // even if there are render_surfaces in-between. @@ -827,7 +834,6 @@ gfx::Transform ComputeScrollCompensationMatrixForChildren( // Avoid the overheads (including stack allocation and matrix // initialization/copy) if we know that the scroll compensation doesn't need // to be reset or adjusted. - gfx::Vector2dF scroll_delta = GetEffectiveScrollDelta(layer); if (!current_layer_resets_scroll_compensation_for_descendants && scroll_delta.IsZero() && !layer->render_surface()) return current_scroll_compensation_matrix; @@ -846,7 +852,7 @@ gfx::Transform ComputeScrollCompensationMatrixForChildren( if (!scroll_delta.IsZero()) { gfx::Transform scroll_compensation_for_this_layer = ComputeScrollCompensationForThisLayer( - layer, parent_matrix); + layer, parent_matrix, scroll_delta); next_scroll_compensation_matrix.PreconcatTransform( scroll_compensation_for_this_layer); } @@ -1093,7 +1099,7 @@ struct SubtreeGlobals { int max_texture_size; float device_scale_factor; float page_scale_factor; - LayerType* page_scale_application_layer; + const LayerType* page_scale_application_layer; bool can_adjust_raster_scales; bool can_render_to_separate_surface; }; @@ -1490,12 +1496,19 @@ static void CalculateDrawPropertiesInternal( combined_transform.Translate(position.x(), position.y()); } + gfx::Vector2dF effective_scroll_delta = GetEffectiveScrollDelta(layer); if (!animating_transform_to_target && layer->scrollable() && combined_transform.IsScaleOrTranslation()) { // Align the scrollable layer's position to screen space pixels to avoid // blurriness. To avoid side-effects, do this only if the transform is // simple. + gfx::Vector2dF previous_translation = combined_transform.To2dTranslation(); RoundTranslationComponents(&combined_transform); + gfx::Vector2dF current_translation = combined_transform.To2dTranslation(); + + // This rounding changes the scroll delta, and so must be included + // in the scroll compensation matrix. + effective_scroll_delta -= current_translation - previous_translation; } // Apply adjustment from position constraints. @@ -1871,7 +1884,8 @@ static void CalculateDrawPropertiesInternal( ComputeScrollCompensationMatrixForChildren( layer, data_from_ancestor.parent_matrix, - data_from_ancestor.scroll_compensation_matrix); + data_from_ancestor.scroll_compensation_matrix, + effective_scroll_delta); data_for_children.fixed_container = layer->IsContainerForFixedPositionLayers() ? layer : data_from_ancestor.fixed_container; @@ -2344,34 +2358,21 @@ LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPoint( LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion( gfx::PointF screen_space_point, const LayerImplList& render_surface_layer_list) { - LayerImpl* found_layer = NULL; - - typedef LayerIterator<LayerImpl, - LayerImplList, - RenderSurfaceImpl, - LayerIteratorActions::FrontToBack> LayerIteratorType; - LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list); - - for (LayerIteratorType - it = LayerIteratorType::Begin(&render_surface_layer_list); - it != end; - ++it) { - // We don't want to consider render_surfaces for hit testing. - if (!it.represents_itself()) - continue; - - LayerImpl* current_layer = (*it); - - if (!LayerHasTouchEventHandlersAt(screen_space_point, current_layer)) - continue; - - found_layer = current_layer; - break; + // First find out which layer was hit from the saved list of visible layers + // in the most recent frame. + LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint( + screen_space_point, + render_surface_layer_list); + + // Walk up the hierarchy and look for a layer with a touch event handler + // region that the given point hits. + // This walk may not be necessary anymore: http://crbug.com/310817 + for (; layer_impl; layer_impl = layer_impl->parent()) { + if (LayerTreeHostCommon::LayerHasTouchEventHandlersAt(screen_space_point, + layer_impl)) + break; } - - // This can potentially return NULL, which means the screen_space_point did - // not successfully hit test any layers, not even the root layer. - return found_layer; + return layer_impl; } bool LayerTreeHostCommon::LayerHasTouchEventHandlersAt( diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h index adabd13516..727244864e 100644 --- a/cc/trees/layer_tree_host_common.h +++ b/cc/trees/layer_tree_host_common.h @@ -36,7 +36,7 @@ class CC_EXPORT LayerTreeHostCommon { const gfx::Transform& device_transform, float device_scale_factor, float page_scale_factor, - LayerType* page_scale_application_layer, + const LayerType* page_scale_application_layer, int max_texture_size, bool can_use_lcd_text, bool can_render_to_separate_surface, @@ -59,7 +59,7 @@ class CC_EXPORT LayerTreeHostCommon { const gfx::Transform& device_transform; float device_scale_factor; float page_scale_factor; - LayerType* page_scale_application_layer; + const LayerType* page_scale_application_layer; int max_texture_size; bool can_use_lcd_text; bool can_render_to_separate_surface; diff --git a/cc/trees/layer_tree_host_common_perftest.cc b/cc/trees/layer_tree_host_common_perftest.cc new file mode 100644 index 0000000000..d9407092ee --- /dev/null +++ b/cc/trees/layer_tree_host_common_perftest.cc @@ -0,0 +1,204 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/trees/layer_tree_host_common.h" + +#include <sstream> + +#include "base/file_util.h" +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/strings/string_piece.h" +#include "base/threading/thread.h" +#include "base/time/time.h" +#include "cc/layers/layer.h" +#include "cc/test/fake_content_layer_client.h" +#include "cc/test/fake_layer_tree_host_client.h" +#include "cc/test/lap_timer.h" +#include "cc/test/layer_tree_json_parser.h" +#include "cc/test/layer_tree_test.h" +#include "cc/test/paths.h" +#include "cc/trees/layer_tree_impl.h" +#include "testing/perf/perf_test.h" + +namespace cc { +namespace { + +static const int kTimeLimitMillis = 2000; +static const int kWarmupRuns = 5; +static const int kTimeCheckInterval = 10; + +class LayerTreeHostCommonPerfTest : public LayerTreeTest { + public: + LayerTreeHostCommonPerfTest() + : timer_(kWarmupRuns, + base::TimeDelta::FromMilliseconds(kTimeLimitMillis), + kTimeCheckInterval) {} + + void ReadTestFile(const std::string& name) { + base::FilePath test_data_dir; + ASSERT_TRUE(PathService::Get(cc::DIR_TEST_DATA, &test_data_dir)); + base::FilePath json_file = test_data_dir.AppendASCII(name + ".json"); + ASSERT_TRUE(base::ReadFileToString(json_file, &json_)); + } + + virtual void SetupTree() OVERRIDE { + gfx::Size viewport = gfx::Size(720, 1038); + layer_tree_host()->SetViewportSize(viewport); + scoped_refptr<Layer> root = + ParseTreeFromJson(json_, &content_layer_client_); + ASSERT_TRUE(root.get()); + layer_tree_host()->SetRootLayer(root); + } + + void SetTestName(const std::string& name) { test_name_ = name; } + + virtual void AfterTest() OVERRIDE { + CHECK(!test_name_.empty()) << "Must SetTestName() before TearDown()."; + perf_test::PrintResult("calc_draw_props_count", + "", + test_name_, + timer_.NumLaps(), + "count", + true); + perf_test::PrintResult("calc_draw_props_time", + "", + test_name_, + 1000 * timer_.MsPerLap(), + "us", + true); + } + + protected: + FakeContentLayerClient content_layer_client_; + LapTimer timer_; + std::string test_name_; + std::string json_; +}; + +class CalcDrawPropsMainTest : public LayerTreeHostCommonPerfTest { + public: + void RunCalcDrawProps() { + RunTest(false, false, false); + } + + virtual void BeginTest() OVERRIDE { + timer_.Reset(); + + do { + bool can_render_to_separate_surface = true; + int max_texture_size = 8096; + RenderSurfaceLayerList update_list; + LayerTreeHostCommon::CalcDrawPropsMainInputs inputs( + layer_tree_host()->root_layer(), + layer_tree_host()->device_viewport_size(), + gfx::Transform(), + layer_tree_host()->device_scale_factor(), + layer_tree_host()->page_scale_factor(), + layer_tree_host()->page_scale_layer(), + max_texture_size, + layer_tree_host()->settings().can_use_lcd_text, + can_render_to_separate_surface, + layer_tree_host() + ->settings() + .layer_transforms_should_scale_layer_contents, + &update_list); + LayerTreeHostCommon::CalculateDrawProperties(&inputs); + + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + + EndTest(); + } +}; + +class CalcDrawPropsImplTest : public LayerTreeHostCommonPerfTest { + public: + void RunCalcDrawProps() { + RunTestWithImplSidePainting(); + } + + virtual void BeginTest() OVERRIDE { + PostSetNeedsCommitToMainThread(); + } + + virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + timer_.Reset(); + LayerTreeImpl* active_tree = host_impl->active_tree(); + + do { + bool can_render_to_separate_surface = true; + int max_texture_size = 8096; + LayerImplList update_list; + LayerTreeHostCommon::CalcDrawPropsImplInputs inputs( + active_tree->root_layer(), + active_tree->DrawViewportSize(), + host_impl->DrawTransform(), + active_tree->device_scale_factor(), + active_tree->total_page_scale_factor(), + active_tree->RootContainerLayer(), + max_texture_size, + host_impl->settings().can_use_lcd_text, + can_render_to_separate_surface, + host_impl->settings().layer_transforms_should_scale_layer_contents, + &update_list); + LayerTreeHostCommon::CalculateDrawProperties(&inputs); + + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + + EndTest(); + } +}; + +TEST_F(CalcDrawPropsMainTest, TenTen) { + SetTestName("10_10"); + ReadTestFile("10_10_layer_tree"); + RunCalcDrawProps(); +} + +TEST_F(CalcDrawPropsMainTest, HeavyPage) { + SetTestName("heavy_page"); + ReadTestFile("heavy_layer_tree"); + RunCalcDrawProps(); +} + +TEST_F(CalcDrawPropsMainTest, TouchRegionLight) { + SetTestName("touch_region_light"); + ReadTestFile("touch_region_light"); + RunCalcDrawProps(); +} + +TEST_F(CalcDrawPropsMainTest, TouchRegionHeavy) { + SetTestName("touch_region_heavy"); + ReadTestFile("touch_region_heavy"); + RunCalcDrawProps(); +} + +TEST_F(CalcDrawPropsImplTest, TenTen) { + SetTestName("10_10"); + ReadTestFile("10_10_layer_tree"); + RunCalcDrawProps(); +} + +TEST_F(CalcDrawPropsImplTest, HeavyPage) { + SetTestName("heavy_page"); + ReadTestFile("heavy_layer_tree"); + RunCalcDrawProps(); +} + +TEST_F(CalcDrawPropsImplTest, TouchRegionLight) { + SetTestName("touch_region_light"); + ReadTestFile("touch_region_light"); + RunCalcDrawProps(); +} + +TEST_F(CalcDrawPropsImplTest, TouchRegionHeavy) { + SetTestName("touch_region_heavy"); + ReadTestFile("touch_region_heavy"); + RunCalcDrawProps(); +} + +} // namespace +} // namespace cc diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 700bca43ea..58d82ceda4 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc @@ -6025,6 +6025,90 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_EQ(456, result_layer->id()); } +TEST_F(LayerTreeHostCommonTest, + HitCheckingTouchHandlerOverlappingRegions) { + gfx::Transform identity_matrix; + gfx::PointF anchor; + + FakeImplProxy proxy; + FakeLayerTreeHostImpl host_impl(&proxy); + scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1); + SetLayerPropertiesForTesting(root.get(), + identity_matrix, + identity_matrix, + anchor, + gfx::PointF(), + gfx::Size(100, 100), + false); + { + scoped_ptr<LayerImpl> touch_layer = + LayerImpl::Create(host_impl.active_tree(), 123); + // this layer is positioned, and hit testing should correctly know where the + // layer is located. + gfx::PointF position; + gfx::Size bounds(50, 50); + SetLayerPropertiesForTesting(touch_layer.get(), + identity_matrix, + identity_matrix, + anchor, + position, + bounds, + false); + touch_layer->SetDrawsContent(true); + touch_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 50, 50)); + root->AddChild(touch_layer.Pass()); + } + + { + scoped_ptr<LayerImpl> notouch_layer = + LayerImpl::Create(host_impl.active_tree(), 1234); + // this layer is positioned, and hit testing should correctly know where the + // layer is located. + gfx::PointF position(0, 25); + gfx::Size bounds(50, 50); + SetLayerPropertiesForTesting(notouch_layer.get(), + identity_matrix, + identity_matrix, + anchor, + position, + bounds, + false); + notouch_layer->SetDrawsContent(true); + root->AddChild(notouch_layer.Pass()); + } + + LayerImplList render_surface_layer_list; + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root.get(), root->bounds(), &render_surface_layer_list); + inputs.can_adjust_raster_scales = true; + LayerTreeHostCommon::CalculateDrawProperties(&inputs); + + // Sanity check the scenario we just created. + ASSERT_EQ(1u, render_surface_layer_list.size()); + ASSERT_EQ(2u, root->render_surface()->layer_list().size()); + ASSERT_EQ(123, root->render_surface()->layer_list().at(0)->id()); + ASSERT_EQ(1234, root->render_surface()->layer_list().at(1)->id()); + + gfx::Point test_point(35, 35); + LayerImpl* result_layer = + LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion( + test_point, render_surface_layer_list); + EXPECT_FALSE(result_layer); + + test_point = gfx::Point(35, 15); + result_layer = + LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion( + test_point, render_surface_layer_list); + ASSERT_TRUE(result_layer); + EXPECT_EQ(123, result_layer->id()); + + test_point = gfx::Point(35, 65); + result_layer = + LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion( + test_point, render_surface_layer_list); + EXPECT_FALSE(result_layer); +} + class NoScaleContentLayer : public ContentLayer { public: static scoped_refptr<NoScaleContentLayer> Create(ContentLayerClient* client) { @@ -9548,5 +9632,118 @@ TEST_F(LayerTreeHostCommonTest, DoNotClobberSorting) { EXPECT_EQ(4, root->render_surface()->layer_list().at(3)->id()); } +TEST_F(LayerTreeHostCommonTest, ScrollCompensationWithRounding) { + // This test verifies that a scrolling layer that gets snapped to + // integer coordinates doesn't move a fixed position child. + // + // + root + // + container + // + scroller + // + fixed + // + FakeImplProxy proxy; + FakeLayerTreeHostImpl host_impl(&proxy); + host_impl.CreatePendingTree(); + scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1); + scoped_ptr<LayerImpl> container = + LayerImpl::Create(host_impl.active_tree(), 2); + LayerImpl* container_layer = container.get(); + scoped_ptr<LayerImpl> scroller = + LayerImpl::Create(host_impl.active_tree(), 3); + LayerImpl* scroll_layer = scroller.get(); + scoped_ptr<LayerImpl> fixed = LayerImpl::Create(host_impl.active_tree(), 4); + LayerImpl* fixed_layer = fixed.get(); + + container->SetIsContainerForFixedPositionLayers(true); + + LayerPositionConstraint constraint; + constraint.set_is_fixed_position(true); + fixed->SetPositionConstraint(constraint); + + scroller->SetScrollable(true); + + gfx::Transform identity_transform; + gfx::Transform container_transform; + container_transform.Translate3d(10.0, 20.0, 0.0); + gfx::Vector2dF container_offset = container_transform.To2dTranslation(); + + SetLayerPropertiesForTesting(root.get(), + identity_transform, + identity_transform, + gfx::PointF(), + gfx::PointF(), + gfx::Size(50, 50), + false); + SetLayerPropertiesForTesting(container.get(), + container_transform, + identity_transform, + gfx::PointF(), + gfx::PointF(), + gfx::Size(40, 40), + false); + SetLayerPropertiesForTesting(scroller.get(), + identity_transform, + identity_transform, + gfx::PointF(), + gfx::PointF(), + gfx::Size(30, 30), + false); + SetLayerPropertiesForTesting(fixed.get(), + identity_transform, + identity_transform, + gfx::PointF(), + gfx::PointF(), + gfx::Size(50, 50), + false); + + scroller->AddChild(fixed.Pass()); + container->AddChild(scroller.Pass()); + root->AddChild(container.Pass()); + + // Rounded to integers already. + { + gfx::Vector2dF scroll_delta(3.0, 5.0); + scroll_layer->SetScrollDelta(scroll_delta); + + LayerImplList render_surface_layer_list; + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root.get(), root->bounds(), &render_surface_layer_list); + LayerTreeHostCommon::CalculateDrawProperties(&inputs); + + EXPECT_TRANSFORMATION_MATRIX_EQ( + container_layer->draw_properties().screen_space_transform, + fixed_layer->draw_properties().screen_space_transform); + EXPECT_VECTOR_EQ( + fixed_layer->draw_properties().screen_space_transform.To2dTranslation(), + container_offset); + EXPECT_VECTOR_EQ(scroll_layer->draw_properties() + .screen_space_transform.To2dTranslation(), + container_offset - scroll_delta); + } + + // Scroll delta requiring rounding. + { + gfx::Vector2dF scroll_delta(4.1f, 8.1f); + scroll_layer->SetScrollDelta(scroll_delta); + + gfx::Vector2dF rounded_scroll_delta(4.f, 8.f); + + LayerImplList render_surface_layer_list; + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root.get(), root->bounds(), &render_surface_layer_list); + LayerTreeHostCommon::CalculateDrawProperties(&inputs); + + EXPECT_TRANSFORMATION_MATRIX_EQ( + container_layer->draw_properties().screen_space_transform, + fixed_layer->draw_properties().screen_space_transform); + EXPECT_VECTOR_EQ( + fixed_layer->draw_properties().screen_space_transform.To2dTranslation(), + container_offset); + EXPECT_VECTOR_EQ(scroll_layer->draw_properties() + .screen_space_transform.To2dTranslation(), + container_offset - rounded_scroll_delta); + } +} + } // namespace } // namespace cc diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index ebc1d83dfc..7171580b86 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -56,6 +56,7 @@ #include "cc/trees/quad_culler.h" #include "cc/trees/single_thread_proxy.h" #include "cc/trees/tree_synchronizer.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/size_conversions.h" #include "ui/gfx/vector2d_conversions.h" @@ -180,19 +181,18 @@ scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create( const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy, - RenderingStatsInstrumentation* rendering_stats_instrumentation) { - return make_scoped_ptr( - new LayerTreeHostImpl(settings, - client, - proxy, - rendering_stats_instrumentation)); + RenderingStatsInstrumentation* rendering_stats_instrumentation, + SharedBitmapManager* manager) { + return make_scoped_ptr(new LayerTreeHostImpl( + settings, client, proxy, rendering_stats_instrumentation, manager)); } LayerTreeHostImpl::LayerTreeHostImpl( const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy, - RenderingStatsInstrumentation* rendering_stats_instrumentation) + RenderingStatsInstrumentation* rendering_stats_instrumentation, + SharedBitmapManager* manager) : client_(client), proxy_(proxy), input_handler_client_(NULL), @@ -207,9 +207,9 @@ LayerTreeHostImpl::LayerTreeHostImpl( visible_(true), cached_managed_memory_policy_( PrioritizedResourceManager::DefaultMemoryAllocationLimit(), - ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 0, - ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING, + gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING, ManagedMemoryPolicy::kDefaultNumResourcesLimit), pinch_gesture_active_(false), pinch_gesture_end_should_clear_scrolling_layer_(false), @@ -230,7 +230,8 @@ LayerTreeHostImpl::LayerTreeHostImpl( external_stencil_test_enabled_(false), animation_registrar_(AnimationRegistrar::Create()), rendering_stats_instrumentation_(rendering_stats_instrumentation), - need_to_update_visible_tiles_before_draw_(false) { + need_to_update_visible_tiles_before_draw_(false), + shared_bitmap_manager_(manager) { DCHECK(proxy_->IsImplThread()); DidVisibilityChange(this, visible_); @@ -280,7 +281,7 @@ void LayerTreeHostImpl::CommitComplete() { // Impl-side painting needs an update immediately post-commit to have the // opportunity to create tilings. Other paths can call UpdateDrawProperties // more lazily when needed prior to drawing. - pending_tree()->ApplyScrollDeltasSinceBeginFrame(); + pending_tree()->ApplyScrollDeltasSinceBeginMainFrame(); pending_tree_->set_needs_update_draw_properties(); pending_tree_->UpdateDrawProperties(); // Start working on newly created tiles immediately if needed. @@ -436,21 +437,11 @@ bool LayerTreeHostImpl::HaveTouchEventHandlersAt(gfx::Point viewport_point) { gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point, device_scale_factor_); - // First find out which layer was hit from the saved list of visible layers - // in the most recent frame. - LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint( - device_viewport_point, - active_tree_->RenderSurfaceLayerList()); - - // Walk up the hierarchy and look for a layer with a touch event handler - // region that the given point hits. - for (; layer_impl; layer_impl = layer_impl->parent()) { - if (LayerTreeHostCommon::LayerHasTouchEventHandlersAt(device_viewport_point, - layer_impl)) - return true; - } - - return false; + LayerImpl* layer_impl = + LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion( + device_viewport_point, + active_tree_->RenderSurfaceLayerList()); + return layer_impl != NULL; } void LayerTreeHostImpl::SetLatencyInfoForInputEvent( @@ -513,7 +504,8 @@ static DrawMode GetDrawMode(OutputSurface* output_surface) { } else if (output_surface->context_provider()) { return DRAW_MODE_HARDWARE; } else { - DCHECK(output_surface->software_device()); + DCHECK_EQ(!output_surface->software_device(), + output_surface->capabilities().delegated_rendering); return DRAW_MODE_SOFTWARE; } } @@ -1207,8 +1199,8 @@ void LayerTreeHostImpl::SetNeedsRedrawRect(gfx::Rect damage_rect) { client_->SetNeedsRedrawRectOnImplThread(damage_rect); } -void LayerTreeHostImpl::BeginFrame(const BeginFrameArgs& args) { - client_->BeginFrameOnImplThread(args); +void LayerTreeHostImpl::BeginImplFrame(const BeginFrameArgs& args) { + client_->BeginImplFrame(args); } void LayerTreeHostImpl::OnSwapBuffersComplete() { @@ -1395,9 +1387,9 @@ bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) { return true; } -void LayerTreeHostImpl::SetNeedsBeginFrame(bool enable) { +void LayerTreeHostImpl::SetNeedsBeginImplFrame(bool enable) { if (output_surface_) - output_surface_->SetNeedsBeginFrame(enable); + output_surface_->SetNeedsBeginImplFrame(enable); } gfx::SizeF LayerTreeHostImpl::UnscaledScrollableViewportSize() const { @@ -1479,9 +1471,7 @@ void LayerTreeHostImpl::CreatePendingTree() { else pending_tree_ = LayerTreeImpl::create(this); client_->OnCanDrawStateChanged(CanDraw()); - TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", pending_tree_.get()); - TRACE_EVENT_ASYNC_STEP0("cc", - "PendingTree", pending_tree_.get(), "waiting"); + TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree:waiting", pending_tree_.get()); } void LayerTreeHostImpl::UpdateVisibleTiles() { @@ -1492,7 +1482,7 @@ void LayerTreeHostImpl::UpdateVisibleTiles() { void LayerTreeHostImpl::ActivatePendingTree() { CHECK(pending_tree_); - TRACE_EVENT_ASYNC_END0("cc", "PendingTree", pending_tree_.get()); + TRACE_EVENT_ASYNC_END0("cc", "PendingTree:waiting", pending_tree_.get()); need_to_update_visible_tiles_before_draw_ = true; @@ -1524,10 +1514,6 @@ void LayerTreeHostImpl::ActivatePendingTree() { active_tree_->SetRootLayerScrollOffsetDelegate( root_layer_scroll_offset_delegate_); - // Reduce wasted memory now that unlinked resources are guaranteed not - // to be used. - client_->ReduceWastedContentsTextureMemoryOnImplThread(); - client_->OnCanDrawStateChanged(CanDraw()); client_->SetNeedsRedrawOnImplThread(); client_->RenewTreePriority(); @@ -1575,9 +1561,9 @@ ManagedMemoryPolicy LayerTreeHostImpl::ActualManagedMemoryPolicy() const { ManagedMemoryPolicy actual = cached_managed_memory_policy_; if (debug_state_.rasterize_only_visible_content) { actual.priority_cutoff_when_not_visible = - ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING; + gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING; actual.priority_cutoff_when_visible = - ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY; + gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY; } if (zero_budget_) { @@ -1682,10 +1668,11 @@ bool LayerTreeHostImpl::InitializeRenderer( if (!output_surface->BindToClient(this)) return false; - scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create( - output_surface.get(), - settings_.highp_threshold_min, - settings_.use_rgba_4444_textures); + scoped_ptr<ResourceProvider> resource_provider = + ResourceProvider::Create(output_surface.get(), + shared_bitmap_manager_, + settings_.highp_threshold_min, + settings_.use_rgba_4444_textures); if (!resource_provider) return false; @@ -1705,14 +1692,14 @@ bool LayerTreeHostImpl::InitializeRenderer( GetRendererCapabilities().using_map_image); } - // Setup BeginFrameEmulation if it's not supported natively - if (!settings_.begin_frame_scheduling_enabled) { + // Setup BeginImplFrameEmulation if it's not supported natively + if (!settings_.begin_impl_frame_scheduling_enabled) { const base::TimeDelta display_refresh_interval = base::TimeDelta::FromMicroseconds( base::Time::kMicrosecondsPerSecond / settings_.refresh_rate); - output_surface->InitializeBeginFrameEmulation( + output_surface->InitializeBeginImplFrameEmulation( proxy_->ImplThreadTaskRunner(), settings_.throttle_frame_production, display_refresh_interval); @@ -2350,10 +2337,8 @@ void LayerTreeHostImpl::MouseMoveAt(gfx::Point viewport_point) { bool should_animate = animation_controller->DidMouseMoveNear( CurrentPhysicalTimeTicks(), distance_to_scrollbar / device_scale_factor_); - if (should_animate) { - client_->SetNeedsRedrawOnImplThread(); + if (should_animate) StartScrollbarAnimation(); - } } bool LayerTreeHostImpl::HandleMouseOverScrollbar(LayerImpl* layer_impl, @@ -2363,8 +2348,11 @@ bool LayerTreeHostImpl::HandleMouseOverScrollbar(LayerImpl* layer_impl, layer_impl = active_tree_->LayerById(scroll_layer_id); if (layer_impl && layer_impl->scrollbar_animation_controller()) { scroll_layer_id_when_mouse_over_scrollbar_ = scroll_layer_id; - layer_impl->scrollbar_animation_controller()->DidMouseMoveNear( - CurrentPhysicalTimeTicks(), 0); + bool should_animate = + layer_impl->scrollbar_animation_controller()->DidMouseMoveNear( + CurrentPhysicalTimeTicks(), 0); + if (should_animate) + StartScrollbarAnimation(); } else { scroll_layer_id_when_mouse_over_scrollbar_ = 0; } @@ -2381,6 +2369,8 @@ void LayerTreeHostImpl::PinchGestureBegin() { client_->RenewTreePriority(); pinch_gesture_end_should_clear_scrolling_layer_ = !CurrentlyScrollingLayer(); active_tree_->SetCurrentlyScrollingLayer(RootScrollLayer()); + if (top_controls_manager_) + top_controls_manager_->PinchBegin(); } void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta, @@ -2418,6 +2408,8 @@ void LayerTreeHostImpl::PinchGestureEnd() { pinch_gesture_end_should_clear_scrolling_layer_ = false; ClearCurrentlyScrollingLayer(); } + if (top_controls_manager_) + top_controls_manager_->PinchEnd(); client_->SetNeedsCommitOnImplThread(); } @@ -2691,7 +2683,7 @@ base::Time LayerTreeHostImpl::CurrentFrameTime() { } base::TimeTicks LayerTreeHostImpl::CurrentPhysicalTimeTicks() const { - return base::TimeTicks::Now(); + return gfx::FrameTime::Now(); } scoped_ptr<base::Value> LayerTreeHostImpl::AsValueWithFrame( @@ -2760,6 +2752,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, UIResourceData data; data.resource_id = id; data.size = bitmap.GetSize(); + data.opaque = bitmap.GetOpaque(); ui_resource_map_[uid] = data; @@ -2806,6 +2799,12 @@ ResourceProvider::ResourceId LayerTreeHostImpl::ResourceIdForUIResource( return 0; } +bool LayerTreeHostImpl::IsUIResourceOpaque(UIResourceId uid) const { + UIResourceMap::const_iterator iter = ui_resource_map_.find(uid); + DCHECK(iter != ui_resource_map_.end()); + return iter->second.opaque; +} + bool LayerTreeHostImpl::EvictedUIResourcesExist() const { return !evicted_ui_resources_.empty(); } diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 555cb24c71..dec0e6c7f7 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -59,7 +59,7 @@ class LayerTreeHostImplClient { public: virtual void DidLoseOutputSurfaceOnImplThread() = 0; virtual void OnSwapBuffersCompleteOnImplThread() = 0; - virtual void BeginFrameOnImplThread(const BeginFrameArgs& args) = 0; + virtual void BeginImplFrame(const BeginFrameArgs& args) = 0; virtual void OnCanDrawStateChanged(bool can_draw) = 0; virtual void NotifyReadyToActivate() = 0; virtual void SetNeedsRedrawOnImplThread() = 0; @@ -74,7 +74,6 @@ class LayerTreeHostImplClient { virtual bool ReduceContentsTextureMemoryOnImplThread( size_t limit_bytes, int priority_cutoff) = 0; - virtual void ReduceWastedContentsTextureMemoryOnImplThread() = 0; virtual void SendManagedMemoryStats() = 0; virtual bool IsInsideDraw() = 0; virtual void RenewTreePriority() = 0; @@ -99,7 +98,8 @@ class CC_EXPORT LayerTreeHostImpl const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy, - RenderingStatsInstrumentation* rendering_stats_instrumentation); + RenderingStatsInstrumentation* rendering_stats_instrumentation, + SharedBitmapManager* manager); virtual ~LayerTreeHostImpl(); // InputHandler implementation @@ -220,7 +220,7 @@ class CC_EXPORT LayerTreeHostImpl scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE; virtual void ReleaseGL() OVERRIDE; virtual void SetNeedsRedrawRect(gfx::Rect rect) OVERRIDE; - virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE; + virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE; virtual void SetExternalDrawConstraints( const gfx::Transform& transform, gfx::Rect viewport, @@ -259,7 +259,7 @@ class CC_EXPORT LayerTreeHostImpl const RendererCapabilities& GetRendererCapabilities() const; virtual bool SwapBuffers(const FrameData& frame); - void SetNeedsBeginFrame(bool enable); + void SetNeedsBeginImplFrame(bool enable); void DidModifyTilePriorities(); void Readback(void* pixels, gfx::Rect rect_in_device_viewport); @@ -401,9 +401,12 @@ class CC_EXPORT LayerTreeHostImpl virtual ResourceProvider::ResourceId ResourceIdForUIResource( UIResourceId uid) const; + virtual bool IsUIResourceOpaque(UIResourceId uid) const; + struct UIResourceData { ResourceProvider::ResourceId resource_id; gfx::Size size; + bool opaque; }; protected: @@ -411,7 +414,8 @@ class CC_EXPORT LayerTreeHostImpl const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy, - RenderingStatsInstrumentation* rendering_stats_instrumentation); + RenderingStatsInstrumentation* rendering_stats_instrumentation, + SharedBitmapManager* manager); // Virtual for testing. virtual void AnimateLayers(base::TimeTicks monotonic_time, @@ -620,6 +624,8 @@ class CC_EXPORT LayerTreeHostImpl // Optional callback to notify of new tree activations. base::Closure tree_activation_callback_; + SharedBitmapManager* shared_bitmap_manager_; + DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl); }; diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index f6350255b1..18b273ef13 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -53,6 +53,7 @@ #include "media/base/media.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/rect_conversions.h" #include "ui/gfx/size_conversions.h" #include "ui/gfx/vector2d_conversions.h" @@ -92,10 +93,8 @@ class LayerTreeHostImplTest : public testing::Test, settings.minimum_occlusion_tracking_size = gfx::Size(); settings.impl_side_painting = true; - host_impl_ = LayerTreeHostImpl::Create(settings, - this, - &proxy_, - &stats_instrumentation_); + host_impl_ = LayerTreeHostImpl::Create( + settings, this, &proxy_, &stats_instrumentation_, NULL); host_impl_->InitializeRenderer(CreateOutputSurface()); host_impl_->SetViewportSize(gfx::Size(10, 10)); } @@ -106,8 +105,7 @@ class LayerTreeHostImplTest : public testing::Test, did_lose_output_surface_ = true; } virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {} - virtual void BeginFrameOnImplThread(const BeginFrameArgs& args) - OVERRIDE {} + virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {} virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE { on_can_draw_state_changed_called_ = true; } @@ -139,7 +137,6 @@ class LayerTreeHostImplTest : public testing::Test, current_priority_cutoff_value_ = priority_cutoff; return reduce_memory_result_; } - virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE {} virtual void SendManagedMemoryStats() OVERRIDE {} virtual bool IsInsideDraw() OVERRIDE { return false; } virtual void RenewTreePriority() OVERRIDE {} @@ -157,10 +154,8 @@ class LayerTreeHostImplTest : public testing::Test, settings.minimum_occlusion_tracking_size = gfx::Size(); settings.partial_swap_enabled = partial_swap; - host_impl_ = LayerTreeHostImpl::Create(settings, - this, - &proxy_, - &stats_instrumentation_); + host_impl_ = LayerTreeHostImpl::Create( + settings, this, &proxy_, &stats_instrumentation_, NULL); host_impl_->InitializeRenderer(output_surface.Pass()); host_impl_->SetViewportSize(gfx::Size(10, 10)); @@ -272,7 +267,7 @@ class LayerTreeHostImplTest : public testing::Test, void DrawFrame() { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -391,7 +386,7 @@ TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) { LayerTreeSettings settings; settings.impl_side_painting = true; host_impl_ = LayerTreeHostImpl::Create( - settings, this, &proxy_, &stats_instrumentation_); + settings, this, &proxy_, &stats_instrumentation_, NULL); scoped_ptr<FakeOutputSurface> output_surface( FakeOutputSurface::CreateAlwaysDrawAndSwap3d()); @@ -494,10 +489,8 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) { TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) { LayerTreeSettings settings; - host_impl_ = LayerTreeHostImpl::Create(settings, - this, - &proxy_, - &stats_instrumentation_); + host_impl_ = LayerTreeHostImpl::Create( + settings, this, &proxy_, &stats_instrumentation_, NULL); scoped_ptr<TestWebGraphicsContext3D> context_owned = TestWebGraphicsContext3D::Create(); context_owned->set_times_make_current_succeeds(0); @@ -1152,8 +1145,8 @@ class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl { : LayerTreeHostImpl(settings, client, proxy, - rendering_stats_instrumentation) {} - + rendering_stats_instrumentation, + NULL) {} virtual base::TimeTicks CurrentPhysicalTimeTicks() const OVERRIDE { return fake_current_physical_time_; @@ -1214,7 +1207,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) { host_impl_->active_tree()->DidBecomeActive(); InitializeRendererAndDrawFrame(); - base::TimeTicks fake_now = base::TimeTicks::Now(); + base::TimeTicks fake_now = gfx::FrameTime::Now(); host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now); // If no scroll happened recently, StartScrollbarAnimation should have no @@ -1286,7 +1279,7 @@ void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( gfx::Size content_size(1000, 1000); host_impl_ = LayerTreeHostImpl::Create( - settings, this, &proxy_, &stats_instrumentation_); + settings, this, &proxy_, &stats_instrumentation_, NULL); host_impl_->InitializeRenderer(CreateOutputSurface()); host_impl_->SetDeviceScaleFactor(device_scale_factor); host_impl_->SetViewportSize(device_viewport_size); @@ -1335,20 +1328,17 @@ void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f); host_impl_->MouseMoveAt(gfx::Point(1, 1)); - EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar()); - did_request_redraw_ = false; host_impl_->MouseMoveAt(gfx::Point(200, 50)); - EXPECT_TRUE(did_request_redraw_); + EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar()); - did_request_redraw_ = false; host_impl_->MouseMoveAt(gfx::Point(184, 100)); - EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar()); scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f); - did_request_redraw_ = false; host_impl_->MouseMoveAt(gfx::Point(184, 100)); - EXPECT_TRUE(did_request_redraw_); + EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar()); did_request_redraw_ = false; EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar()); @@ -1513,7 +1503,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) { { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10))); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); EXPECT_TRUE(layer->will_draw_called()); @@ -1528,7 +1518,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) { layer->ClearDidDrawCheck(); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10))); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); EXPECT_TRUE(layer->will_draw_called()); @@ -1560,7 +1550,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { EXPECT_FALSE(layer->did_draw_called()); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); EXPECT_FALSE(layer->will_draw_called()); @@ -1575,7 +1565,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { EXPECT_FALSE(layer->did_draw_called()); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); EXPECT_TRUE(layer->will_draw_called()); @@ -1614,7 +1604,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) { EXPECT_FALSE(top_layer->did_draw_called()); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); EXPECT_FALSE(occluded_layer->will_draw_called()); @@ -1646,7 +1636,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); EXPECT_TRUE(root->did_draw_called()); @@ -1719,7 +1709,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); // When a texture is missing and we're not animating, we draw as usual with @@ -1737,7 +1727,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) { host_impl_->resource_provider())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); // When a texture is missing and we're animating, we don't want to draw @@ -1755,7 +1745,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) { host_impl_->resource_provider())); EXPECT_FALSE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); // When the layer skips draw and we're animating, we still draw the frame. @@ -1772,7 +1762,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) { host_impl_->resource_provider())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -1794,10 +1784,8 @@ TEST_F(LayerTreeHostImplTest, ScrollNonScrollableRootWithTopControls) { settings.calculate_top_controls_position = true; settings.top_controls_height = 50; - host_impl_ = LayerTreeHostImpl::Create(settings, - this, - &proxy_, - &stats_instrumentation_); + host_impl_ = LayerTreeHostImpl::Create( + settings, this, &proxy_, &stats_instrumentation_, NULL); host_impl_->InitializeRenderer(CreateOutputSurface()); host_impl_->SetViewportSize(gfx::Size(10, 10)); @@ -2068,7 +2056,7 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) { // the page scale delta on the root layer is applied hierarchically. LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0)); @@ -2759,7 +2747,7 @@ TEST_F(LayerTreeHostImplTest, OverscrollAlways) { LayerTreeSettings settings; settings.always_overscroll = true; host_impl_ = LayerTreeHostImpl::Create( - settings, this, &proxy_, &stats_instrumentation_); + settings, this, &proxy_, &stats_instrumentation_, NULL); SetupScrollAndContentsLayers(gfx::Size(50, 50)); host_impl_->SetViewportSize(gfx::Size(50, 50)); @@ -2903,7 +2891,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetExpectation(false, false); layer1->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -2912,7 +2900,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetExpectation(true, false); layer1->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -2922,7 +2910,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetExpectation(true, false); layer1->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -2932,7 +2920,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetExpectation(true, false); layer1->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -2954,7 +2942,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer2->SetExpectation(false, false); layer2->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); EXPECT_TRUE(layer2->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -2967,7 +2955,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer2->SetExpectation(false, false); layer2->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); EXPECT_TRUE(layer2->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -2981,7 +2969,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer2->SetExpectation(false, false); layer2->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); EXPECT_TRUE(layer2->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -2998,7 +2986,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer2->SetExpectation(false, false); layer2->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); EXPECT_TRUE(layer2->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -3014,7 +3002,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer2->SetExpectation(true, false); layer2->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); EXPECT_TRUE(layer2->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -3029,7 +3017,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer2->SetExpectation(true, false); layer2->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); EXPECT_TRUE(layer2->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -3045,7 +3033,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer2->SetExpectation(false, false); layer2->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); EXPECT_TRUE(layer2->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -3058,7 +3046,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetExpectation(true, false); layer1->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -3070,7 +3058,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetExpectation(true, false); layer1->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -3082,7 +3070,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetExpectation(true, false); layer1->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); host_impl_->DidDrawAllLayers(frame); @@ -3095,7 +3083,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetExpectation(false, false); layer1->set_update_rect(gfx::RectF(layer1->content_bounds())); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(layer1->quads_appended()); host_impl_->DidDrawAllLayers(frame); } @@ -3112,7 +3100,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { settings.minimum_occlusion_tracking_size = gfx::Size(); settings.impl_side_painting = true; host_impl_ = LayerTreeHostImpl::Create( - settings, this, &proxy_, &stats_instrumentation_); + settings, this, &proxy_, &stats_instrumentation_, NULL); scoped_ptr<FakeOutputSurface> output_surface; if (always_draw) @@ -3317,7 +3305,8 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) { skbitmap.setImmutable(); // Specify an overhang bitmap to use. - UIResourceBitmap ui_resource_bitmap(skbitmap, UIResourceBitmap::REPEAT); + UIResourceBitmap ui_resource_bitmap(skbitmap); + ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT); UIResourceId ui_resource_id = 12345; host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap); host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32)); @@ -3453,7 +3442,7 @@ TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) { host_impl_->SetViewportSize(gfx::Size(10, 10)); host_impl_->SetDeviceScaleFactor(1.f); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(reshape_tracker->reshape_called()); EXPECT_EQ(reshape_tracker->last_reshape_width(), 10); EXPECT_EQ(reshape_tracker->last_reshape_height(), 10); @@ -3463,7 +3452,7 @@ TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) { host_impl_->SetViewportSize(gfx::Size(20, 30)); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(reshape_tracker->reshape_called()); EXPECT_EQ(reshape_tracker->last_reshape_width(), 20); EXPECT_EQ(reshape_tracker->last_reshape_height(), 30); @@ -3473,7 +3462,7 @@ TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) { host_impl_->SetDeviceScaleFactor(2.f); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); EXPECT_TRUE(reshape_tracker->reshape_called()); EXPECT_EQ(reshape_tracker->last_reshape_width(), 20); EXPECT_EQ(reshape_tracker->last_reshape_height(), 30); @@ -3532,10 +3521,8 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { LayerTreeSettings settings; settings.partial_swap_enabled = true; scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl = - LayerTreeHostImpl::Create(settings, - this, - &proxy_, - &stats_instrumentation_); + LayerTreeHostImpl::Create( + settings, this, &proxy_, &stats_instrumentation_, NULL); layer_tree_host_impl->InitializeRenderer(output_surface.Pass()); layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500)); @@ -3559,7 +3546,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { // First frame, the entire screen should get swapped. EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect())); - layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now()); + layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); layer_tree_host_impl->DidDrawAllLayers(frame); layer_tree_host_impl->SwapBuffers(frame); gfx::Rect actual_swap_rect = swap_tracker->update_rect(); @@ -3577,7 +3564,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition( gfx::PointF()); EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect())); - layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now()); + layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); layer_tree_host_impl->SwapBuffers(frame); actual_swap_rect = swap_tracker->update_rect(); @@ -3597,7 +3584,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor( SK_ColorBLACK); EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect())); - layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now()); + layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); layer_tree_host_impl->SwapBuffers(frame); actual_swap_rect = swap_tracker->update_rect(); @@ -3765,7 +3752,7 @@ TEST_F(LayerTreeHostImplTest, NoPartialSwap) { { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } Mock::VerifyAndClearExpectations(&mock_context); @@ -3778,7 +3765,7 @@ TEST_F(LayerTreeHostImplTest, NoPartialSwap) { { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } Mock::VerifyAndClearExpectations(&mock_context); @@ -3800,7 +3787,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwap) { { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } Mock::VerifyAndClearExpectations(&mock_context); @@ -3815,7 +3802,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwap) { { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } Mock::VerifyAndClearExpectations(&mock_context); @@ -3847,8 +3834,8 @@ static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity( LayerTreeSettings settings; settings.partial_swap_enabled = partial_swap; - scoped_ptr<LayerTreeHostImpl> my_host_impl = - LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation); + scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create( + settings, client, proxy, stats_instrumentation, NULL); my_host_impl->InitializeRenderer(output_surface.Pass()); my_host_impl->SetViewportSize(gfx::Size(100, 100)); @@ -3929,7 +3916,7 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) { EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material); - my_host_impl->DrawLayers(&frame, base::TimeTicks::Now()); + my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); my_host_impl->DidDrawAllLayers(frame); } } @@ -3950,7 +3937,7 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) { EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material); - my_host_impl->DrawLayers(&frame, base::TimeTicks::Now()); + my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); my_host_impl->DidDrawAllLayers(frame); } } @@ -4029,7 +4016,7 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); host_impl_->SwapBuffers(frame); @@ -4072,7 +4059,7 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) { .Times(1); LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); Mock::VerifyAndClearExpectations(&mock_context); @@ -4080,7 +4067,7 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) { host_impl_->active_tree()->set_has_transparent_background(true); host_impl_->SetFullRootLayerDamage(); EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); Mock::VerifyAndClearExpectations(&mock_context); } @@ -4167,7 +4154,7 @@ class LayerTreeHostImplTestWithDelegatingRenderer root_render_pass->quad_list[1]->visible_rect); } - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame)); } @@ -4228,10 +4215,8 @@ class FakeMaskLayerImpl : public LayerImpl { TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) { LayerTreeSettings settings; settings.layer_transforms_should_scale_layer_contents = true; - host_impl_ = LayerTreeHostImpl::Create(settings, - this, - &proxy_, - &stats_instrumentation_); + host_impl_ = LayerTreeHostImpl::Create( + settings, this, &proxy_, &stats_instrumentation_, NULL); host_impl_->InitializeRenderer(CreateOutputSurface()); host_impl_->SetViewportSize(gfx::Size(10, 10)); @@ -4309,7 +4294,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), render_pass_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -4337,7 +4322,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), render_pass_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -4367,7 +4352,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), render_pass_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } } @@ -4430,7 +4415,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), render_pass_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -4457,7 +4442,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), render_pass_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -4487,7 +4472,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), render_pass_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -4512,7 +4497,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), render_pass_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } } @@ -4581,7 +4566,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), replica_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -4609,7 +4594,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), replica_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -4640,7 +4625,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), replica_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -4666,7 +4651,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), replica_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } } @@ -4757,7 +4742,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) { EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(), replica_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -4791,7 +4776,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) { EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(), replica_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } } @@ -4887,7 +4872,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) { 1.f / 50.f).ToString(), render_pass_quad->mask_uv_rect.ToString()); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } } @@ -4960,7 +4945,7 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) { quad->quadTransform(), quad, &device_layer_quad, edge); EXPECT_FALSE(antialiased); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); } @@ -5061,7 +5046,7 @@ TEST_F(LayerTreeHostImplTest, LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); EXPECT_EQ(1u, frame.will_draw_layers.size()); @@ -5219,10 +5204,8 @@ TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OffscreenContext) { // doesn't support memory management extensions. TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) { LayerTreeSettings settings; - host_impl_ = LayerTreeHostImpl::Create(settings, - this, - &proxy_, - &stats_instrumentation_); + host_impl_ = LayerTreeHostImpl::Create( + settings, this, &proxy_, &stats_instrumentation_, NULL); scoped_ptr<OutputSurface> output_surface( FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create())); @@ -5232,8 +5215,8 @@ TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) { TEST_F(LayerTreeHostImplTest, MemoryPolicy) { ManagedMemoryPolicy policy1( - 456, ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, - 123, ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE, 1000); + 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, + 123, gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, 1000); int visible_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue( policy1.priority_cutoff_when_visible); int not_visible_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue( @@ -5331,12 +5314,10 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) { scoped_refptr<TestContextProvider> context_provider = TestContextProvider::Create(); - host_impl_ = LayerTreeHostImpl::Create(LayerTreeSettings(), - this, - &proxy_, - &stats_instrumentation_); - host_impl_->InitializeRenderer( - FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>()); + host_impl_ = LayerTreeHostImpl::Create( + LayerTreeSettings(), this, &proxy_, &stats_instrumentation_, NULL); + host_impl_->InitializeRenderer(FakeOutputSurface::Create3d(context_provider) + .PassAs<OutputSurface>()); host_impl_->SetViewportSize(gfx::Size(10, 10)); SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1)); @@ -5349,7 +5330,7 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) { LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect())); - host_impl_->DrawLayers(&frame, base::TimeTicks::Now()); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); // The CopyOutputResult's callback has a ref on the ContextProvider and a diff --git a/cc/trees/layer_tree_host_perftest.cc b/cc/trees/layer_tree_host_perftest.cc index 1eebe41d9c..79ee46be81 100644 --- a/cc/trees/layer_tree_host_perftest.cc +++ b/cc/trees/layer_tree_host_perftest.cc @@ -44,6 +44,10 @@ class LayerTreeHostPerfTest : public LayerTreeTest { fake_content_layer_client_.set_paint_all_opaque(true); } + virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE { + settings->throttle_frame_production = false; + } + virtual void BeginTest() OVERRIDE { BuildTree(); PostSetNeedsCommitToMainThread(); diff --git a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc index a1990b01d5..c432a5ed0e 100644 --- a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc +++ b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc @@ -29,8 +29,8 @@ class LayerTreeHostOnDemandRasterPixelTest : public LayerTreePixelTest { virtual void BeginCommitOnThread(LayerTreeHostImpl* impl) OVERRIDE { // Not enough memory available. Enforce on-demand rasterization. impl->SetMemoryPolicy( - ManagedMemoryPolicy(1, ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, - 1, ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING, + ManagedMemoryPolicy(1, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, + 1, gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING, 1000)); impl->SetDiscardBackBufferWhenNotVisible(true); } diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index c5127b181b..950fd79466 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -51,6 +51,7 @@ #include "third_party/khronos/GLES2/gl2.h" #include "third_party/khronos/GLES2/gl2ext.h" #include "third_party/skia/include/core/SkPicture.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/point_conversions.h" #include "ui/gfx/size_conversions.h" #include "ui/gfx/vector2d_conversions.h" @@ -730,6 +731,101 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSetNextCommitForcesRedraw); +// Tests that if a layer is not drawn because of some reason in the parent then +// its damage is preserved until the next time it is drawn. +class LayerTreeHostTestUndrawnLayersDamageLater : public LayerTreeHostTest { + public: + LayerTreeHostTestUndrawnLayersDamageLater() + : root_layer_(ContentLayer::Create(&client_)) { + } + + virtual void SetupTree() OVERRIDE { + root_layer_->SetIsDrawable(true); + root_layer_->SetBounds(gfx::Size(50, 50)); + layer_tree_host()->SetRootLayer(root_layer_); + + // The initially transparent layer has a larger child layer, which is + // not initially drawn because of the this (parent) layer. + parent_layer_ = FakeContentLayer::Create(&client_); + parent_layer_->SetBounds(gfx::Size(15, 15)); + parent_layer_->SetOpacity(0.0f); + root_layer_->AddChild(parent_layer_); + + child_layer_ = FakeContentLayer::Create(&client_); + child_layer_->SetBounds(gfx::Size(25, 25)); + parent_layer_->AddChild(child_layer_); + + LayerTreeHostTest::SetupTree(); + } + + virtual void BeginTest() OVERRIDE { + PostSetNeedsCommitToMainThread(); + } + + virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + bool result) OVERRIDE { + EXPECT_TRUE(result); + + gfx::RectF root_damage_rect; + if (!frame_data->render_passes.empty()) + root_damage_rect = frame_data->render_passes.back()->damage_rect; + + // The first time, the whole view needs be drawn. + // Afterwards, just the opacity of surface_layer1 is changed a few times, + // and each damage should be the bounding box of it and its child. If this + // was working improperly, the damage might not include its childs bounding + // box. + switch (layer_tree_host()->source_frame_number()) { + case 1: + EXPECT_RECT_EQ(gfx::Rect(root_layer_->bounds()), root_damage_rect); + break; + case 2: + case 3: + case 4: + EXPECT_RECT_EQ(gfx::Rect(child_layer_->bounds()), root_damage_rect); + break; + default: + NOTREACHED(); + } + + return result; + } + + virtual void DidCommitAndDrawFrame() OVERRIDE { + switch (layer_tree_host()->source_frame_number()) { + case 1: + // Test not owning the surface. + parent_layer_->SetOpacity(1.0f); + break; + case 2: + parent_layer_->SetOpacity(0.0f); + break; + case 3: + // Test owning the surface. + parent_layer_->SetOpacity(0.5f); + parent_layer_->SetForceRenderSurface(true); + break; + case 4: + EndTest(); + break; + default: + NOTREACHED(); + } + } + + + virtual void AfterTest() OVERRIDE {} + + private: + FakeContentLayerClient client_; + scoped_refptr<ContentLayer> root_layer_; + scoped_refptr<FakeContentLayer> parent_layer_; + scoped_refptr<FakeContentLayer> child_layer_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestUndrawnLayersDamageLater); + // If the layerTreeHost says it can't draw, Then we should not try to draw. class LayerTreeHostTestCanDrawBlocksDrawing : public LayerTreeHostTest { public: @@ -1004,10 +1100,9 @@ class LayerTreeHostTestFrameTimeUpdatesAfterDraw : public LayerTreeHostTest { first_frame_time_ = impl->CurrentFrameTimeTicks(); impl->SetNeedsRedraw(); - // Since base::TimeTicks::Now() uses a low-resolution clock on - // Windows, we need to make sure that the clock has incremented past - // first_frame_time_. - while (first_frame_time_ == base::TimeTicks::Now()) {} + // Since we might use a low-resolution clock on Windows, we need to + // make sure that the clock has incremented past first_frame_time_. + while (first_frame_time_ == gfx::FrameTime::Now()) {} return; } @@ -2204,7 +2299,7 @@ class LayerTreeHostWithProxy : public LayerTreeHost { LayerTreeHostWithProxy(FakeLayerTreeHostClient* client, const LayerTreeSettings& settings, scoped_ptr<FakeProxy> proxy) - : LayerTreeHost(client, settings) { + : LayerTreeHost(client, NULL, settings) { proxy->SetLayerTreeHost(this); EXPECT_TRUE(InitializeForTesting(proxy.PassAs<Proxy>())); } @@ -2272,7 +2367,7 @@ TEST(LayerTreeHostTest, PartialUpdatesWithGLRenderer) { settings.max_partial_texture_updates = 4; scoped_ptr<LayerTreeHost> host = - LayerTreeHost::Create(&client, settings, NULL); + LayerTreeHost::Create(&client, NULL, settings, NULL); EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded()); EXPECT_EQ(4u, host->settings().max_partial_texture_updates); } @@ -2284,7 +2379,7 @@ TEST(LayerTreeHostTest, PartialUpdatesWithSoftwareRenderer) { settings.max_partial_texture_updates = 4; scoped_ptr<LayerTreeHost> host = - LayerTreeHost::Create(&client, settings, NULL); + LayerTreeHost::Create(&client, NULL, settings, NULL); EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded()); EXPECT_EQ(4u, host->settings().max_partial_texture_updates); } @@ -2296,7 +2391,7 @@ TEST(LayerTreeHostTest, PartialUpdatesWithDelegatingRendererAndGLContent) { settings.max_partial_texture_updates = 4; scoped_ptr<LayerTreeHost> host = - LayerTreeHost::Create(&client, settings, NULL); + LayerTreeHost::Create(&client, NULL, settings, NULL); EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded()); EXPECT_EQ(0u, host->MaxPartialTextureUpdates()); } @@ -2309,7 +2404,7 @@ TEST(LayerTreeHostTest, settings.max_partial_texture_updates = 4; scoped_ptr<LayerTreeHost> host = - LayerTreeHost::Create(&client, settings, NULL); + LayerTreeHost::Create(&client, NULL, settings, NULL); EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded()); EXPECT_EQ(0u, host->MaxPartialTextureUpdates()); } @@ -2358,9 +2453,9 @@ class LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted // Because a resource was evicted, a commit will be kicked off. host_impl->SetMemoryPolicy( ManagedMemoryPolicy(100 * 100 * 4 * 2, - ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 100 * 100 * 4 * 1, - ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000)); host_impl->SetDiscardBackBufferWhenNotVisible(true); break; @@ -2482,15 +2577,16 @@ class LayerTreeHostTestLCDNotification : public LayerTreeHostTest { SINGLE_THREAD_TEST_F(LayerTreeHostTestLCDNotification); -// Verify that the BeginFrame notification is used to initiate rendering. -class LayerTreeHostTestBeginFrameNotification : public LayerTreeHostTest { +// Verify that the BeginImplFrame notification is used to initiate rendering. +class LayerTreeHostTestBeginImplFrameNotification : public LayerTreeHostTest { public: virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE { - settings->begin_frame_scheduling_enabled = true; + settings->begin_impl_frame_scheduling_enabled = true; } virtual void BeginTest() OVERRIDE { - // This will trigger a SetNeedsBeginFrame which will trigger a BeginFrame. + // This will trigger a SetNeedsBeginImplFrame which will trigger a + // BeginImplFrame. PostSetNeedsCommitToMainThread(); } @@ -2508,24 +2604,24 @@ class LayerTreeHostTestBeginFrameNotification : public LayerTreeHostTest { base::TimeTicks frame_time_; }; -MULTI_THREAD_TEST_F(LayerTreeHostTestBeginFrameNotification); +MULTI_THREAD_TEST_F(LayerTreeHostTestBeginImplFrameNotification); -class LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled +class LayerTreeHostTestBeginImplFrameNotificationShutdownWhileEnabled : public LayerTreeHostTest { public: virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE { - settings->begin_frame_scheduling_enabled = true; + settings->begin_impl_frame_scheduling_enabled = true; settings->using_synchronous_renderer_compositor = true; } virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); } virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { - // The BeginFrame notification is turned off now but will get enabled + // The BeginImplFrame notification is turned off now but will get enabled // once we return. End test while it's enabled. ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostTestBeginFrameNotification::EndTest, + base::Bind(&LayerTreeHostTestBeginImplFrameNotification::EndTest, base::Unretained(this))); } @@ -2533,7 +2629,7 @@ class LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled }; MULTI_THREAD_TEST_F( - LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled); + LayerTreeHostTestBeginImplFrameNotificationShutdownWhileEnabled); class LayerTreeHostTestAbortedCommitDoesntStall : public LayerTreeHostTest { protected: @@ -2541,7 +2637,7 @@ class LayerTreeHostTestAbortedCommitDoesntStall : public LayerTreeHostTest { : commit_count_(0), commit_complete_count_(0) {} virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE { - settings->begin_frame_scheduling_enabled = true; + settings->begin_impl_frame_scheduling_enabled = true; } virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); } @@ -4709,7 +4805,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestUpdateLayerInEmptyViewport); class LayerTreeHostTestAbortEvictedTextures : public LayerTreeHostTest { public: LayerTreeHostTestAbortEvictedTextures() - : num_will_begin_frames_(0), num_impl_commits_(0) {} + : num_will_begin_main_frames_(0), num_impl_commits_(0) {} protected: virtual void SetupTree() OVERRIDE { @@ -4723,9 +4819,9 @@ class LayerTreeHostTestAbortEvictedTextures : public LayerTreeHostTest { virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); } - virtual void WillBeginFrame() OVERRIDE { - num_will_begin_frames_++; - switch (num_will_begin_frames_) { + virtual void WillBeginMainFrame() OVERRIDE { + num_will_begin_main_frames_++; + switch (num_will_begin_main_frames_) { case 2: // Send a redraw to the compositor thread. This will (wrongly) be // ignored unless aborting resets the texture state. @@ -4755,12 +4851,12 @@ class LayerTreeHostTestAbortEvictedTextures : public LayerTreeHostTest { virtual void AfterTest() OVERRIDE { // Ensure that the commit was truly aborted. - EXPECT_EQ(2, num_will_begin_frames_); + EXPECT_EQ(2, num_will_begin_main_frames_); EXPECT_EQ(1, num_impl_commits_); } private: - int num_will_begin_frames_; + int num_will_begin_main_frames_; int num_impl_commits_; }; @@ -4881,9 +4977,9 @@ class LayerTreeHostTestMemoryLimits : public LayerTreeHostTest { // This will trigger a commit because the priority cutoff has changed. impl->SetMemoryPolicy(ManagedMemoryPolicy( 16u*1024u*1024u, - ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE, + gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, 0, - ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING, + gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING, 1000)); break; case 2: @@ -4891,9 +4987,9 @@ class LayerTreeHostTestMemoryLimits : public LayerTreeHostTest { // changed, and there is already enough memory for all allocations. impl->SetMemoryPolicy(ManagedMemoryPolicy( 32u*1024u*1024u, - ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE, + gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, 0, - ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING, + gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING, 1000)); break; case 3: @@ -5041,14 +5137,14 @@ class LayerTreeHostTestSetMemoryPolicyOnLostOutputSurface second_context_provider_ : first_context_provider_)); output_surface->SetMemoryPolicyToSetAtBind(make_scoped_ptr( - new cc::ManagedMemoryPolicy( + new ManagedMemoryPolicy( second_context_provider_ ? second_output_surface_memory_limit_ : first_output_surface_memory_limit_, - cc::ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE, + gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, 0, - cc::ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING, - cc::ManagedMemoryPolicy::kDefaultNumResourcesLimit))); + gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING, + ManagedMemoryPolicy::kDefaultNumResourcesLimit))); return output_surface.PassAs<OutputSurface>(); } diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index 70e2a9ec6d..90fc936519 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc @@ -375,14 +375,17 @@ class LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree // Verify that commits are actually alternating with empty / non-empty // trees. - switch (host_impl->active_tree()->source_frame_number()) { + int frame_number = host_impl->active_tree()->source_frame_number(); + switch (frame_number) { case 0: case 2: - EXPECT_TRUE(host_impl->active_tree()->root_layer()); + EXPECT_TRUE(host_impl->active_tree()->root_layer()) + << "frame: " << frame_number; break; case 1: case 3: - EXPECT_FALSE(host_impl->active_tree()->root_layer()); + EXPECT_FALSE(host_impl->active_tree()->root_layer()) + << "frame: " << frame_number; break; } diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index e4a0ca7ecc..03b8d7f629 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc @@ -894,8 +894,9 @@ TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, RunTest(true, true, false); } +// Flaky on all platforms, http://crbug.com/310979 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, - LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) { + DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) { lose_after_evict_ = true; RunTest(true, true, true); } @@ -1089,7 +1090,7 @@ class LayerTreeHostContextTestDontUseLostResources child_output_surface_ = FakeOutputSurface::Create3d(); child_output_surface_->BindToClient(&output_surface_client_); child_resource_provider_ = - ResourceProvider::Create(child_output_surface_.get(), 0, false); + ResourceProvider::Create(child_output_surface_.get(), NULL, 0, false); } static void EmptyReleaseCallback(unsigned sync_point, bool lost) {} @@ -1402,13 +1403,16 @@ class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit times_output_surface_created_ = 0; + // Post the SetNeedsCommit before the readback to make sure it is run + // on the main thread before the readback's replacement commit when + // we have a threaded compositor. + PostSetNeedsCommitToMainThread(); + char pixels[4]; bool result = layer_tree_host()->CompositeAndReadback( &pixels, gfx::Rect(1, 1)); EXPECT_EQ(!delegating_renderer(), result); EXPECT_EQ(1, times_output_surface_created_); - - PostSetNeedsCommitToMainThread(); } virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE { @@ -1781,6 +1785,7 @@ class LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface settings.impl_side_painting = impl_side_painting; scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::Create( this, + NULL, settings, impl_thread ? impl_thread->message_loop_proxy() : NULL); EXPECT_FALSE(layer_tree_host); diff --git a/cc/trees/layer_tree_host_unittest_damage.cc b/cc/trees/layer_tree_host_unittest_damage.cc index 83831f6349..402a56a898 100644 --- a/cc/trees/layer_tree_host_unittest_damage.cc +++ b/cc/trees/layer_tree_host_unittest_damage.cc @@ -58,9 +58,9 @@ class LayerTreeHostDamageTestSetVisibleDoesNotDraw // No evictions when we become not-visible. impl->SetMemoryPolicy(ManagedMemoryPolicy( 1000 * 1000 * 1000, - ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000 * 1000 * 1000, - ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, ManagedMemoryPolicy::kDefaultNumResourcesLimit)); PostSetVisibleToMainThread(false); diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index ab87be1b5c..1142622529 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc @@ -172,8 +172,8 @@ class LayerTreeHostScrollTestScrollAbortedCommit impl_scroll_(-3, 2), second_main_scroll_(14, -3), impl_scale_(2.f), - num_will_begin_frames_(0), - num_did_begin_frames_(0), + num_will_begin_main_frames_(0), + num_did_begin_main_frames_(0), num_will_commits_(0), num_did_commits_(0), num_impl_commits_(0), @@ -194,10 +194,10 @@ class LayerTreeHostScrollTestScrollAbortedCommit layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f); } - virtual void WillBeginFrame() OVERRIDE { - num_will_begin_frames_++; + virtual void WillBeginMainFrame() OVERRIDE { + num_will_begin_main_frames_++; Layer* root_scroll_layer = layer_tree_host()->root_layer()->children()[0]; - switch (num_will_begin_frames_) { + switch (num_will_begin_main_frames_) { case 1: // This will not be aborted because of the initial prop changes. EXPECT_EQ(0, num_impl_scrolls_); @@ -239,7 +239,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit } } - virtual void DidBeginFrame() OVERRIDE { num_did_begin_frames_++; } + virtual void DidBeginMainFrame() OVERRIDE { num_did_begin_main_frames_++; } virtual void WillCommit() OVERRIDE { num_will_commits_++; } @@ -317,8 +317,8 @@ class LayerTreeHostScrollTestScrollAbortedCommit virtual void AfterTest() OVERRIDE { EXPECT_EQ(3, num_impl_scrolls_); // Verify that the embedder sees aborted commits as real commits. - EXPECT_EQ(4, num_will_begin_frames_); - EXPECT_EQ(4, num_did_begin_frames_); + EXPECT_EQ(4, num_will_begin_main_frames_); + EXPECT_EQ(4, num_did_begin_main_frames_); EXPECT_EQ(4, num_will_commits_); EXPECT_EQ(4, num_did_commits_); // ...but the compositor thread only sees two real ones. @@ -330,8 +330,8 @@ class LayerTreeHostScrollTestScrollAbortedCommit gfx::Vector2d impl_scroll_; gfx::Vector2d second_main_scroll_; float impl_scale_; - int num_will_begin_frames_; - int num_did_begin_frames_; + int num_will_begin_main_frames_; + int num_did_begin_main_frames_; int num_will_commits_; int num_did_commits_; int num_impl_commits_; @@ -1013,7 +1013,7 @@ TEST(LayerTreeHostFlingTest, DidStopFlingingThread) { ASSERT_TRUE(impl_thread.message_loop_proxy().get()); scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::Create( - &client, settings, impl_thread.message_loop_proxy()); + &client, NULL, settings, impl_thread.message_loop_proxy()); impl_thread.message_loop_proxy() ->PostTask(FROM_HERE, diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 3e3d64c6d7..4604043663 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc @@ -271,17 +271,17 @@ void LayerTreeImpl::ApplySentScrollAndScaleDeltasFromAbortedCommit() { root_layer(), base::Bind(&ApplySentScrollDeltasFromAbortedCommitTo)); } -static void ApplyScrollDeltasSinceBeginFrameTo(LayerImpl* layer) { - layer->ApplyScrollDeltasSinceBeginFrame(); +static void ApplyScrollDeltasSinceBeginMainFrameTo(LayerImpl* layer) { + layer->ApplyScrollDeltasSinceBeginMainFrame(); } -void LayerTreeImpl::ApplyScrollDeltasSinceBeginFrame() { +void LayerTreeImpl::ApplyScrollDeltasSinceBeginMainFrame() { DCHECK(IsPendingTree()); if (!root_layer()) return; LayerTreeHostCommon::CallFunctionForSubtree( - root_layer(), base::Bind(&ApplyScrollDeltasSinceBeginFrameTo)); + root_layer(), base::Bind(&ApplyScrollDeltasSinceBeginMainFrameTo)); } void LayerTreeImpl::SetViewportLayersFromIds( @@ -710,6 +710,10 @@ ResourceProvider::ResourceId LayerTreeImpl::ResourceIdForUIResource( return layer_tree_host_impl_->ResourceIdForUIResource(uid); } +bool LayerTreeImpl::IsUIResourceOpaque(UIResourceId uid) const { + return layer_tree_host_impl_->IsUIResourceOpaque(uid); +} + void LayerTreeImpl::ProcessUIResourceRequestQueue() { while (ui_resource_request_queue_.size() > 0) { UIResourceRequest req = ui_resource_request_queue_.front(); diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index faf360f6fc..1b40b926fa 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h @@ -123,7 +123,7 @@ class CC_EXPORT LayerTreeImpl { int outer_viewport_scroll_layer_id); void ClearViewportLayers(); void ApplySentScrollAndScaleDeltasFromAbortedCommit(); - void ApplyScrollDeltasSinceBeginFrame(); + void ApplyScrollDeltasSinceBeginMainFrame(); SkColor background_color() const { return background_color_; } void set_background_color(SkColor color) { background_color_ = color; } @@ -212,6 +212,8 @@ class CC_EXPORT LayerTreeImpl { ResourceProvider::ResourceId ResourceIdForUIResource(UIResourceId uid) const; void ProcessUIResourceRequestQueue(); + bool IsUIResourceOpaque(UIResourceId uid) const; + void AddLayerWithCopyOutputRequest(LayerImpl* layer); void RemoveLayerWithCopyOutputRequest(LayerImpl* layer); const std::vector<LayerImpl*> LayersWithCopyOutputRequest() const; diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc index b7aafbb2d7..eb0f2f3493 100644 --- a/cc/trees/layer_tree_settings.cc +++ b/cc/trees/layer_tree_settings.cc @@ -16,8 +16,8 @@ LayerTreeSettings::LayerTreeSettings() : impl_side_painting(false), allow_antialiasing(true), throttle_frame_production(true), - begin_frame_scheduling_enabled(false), - deadline_scheduling_enabled(false), + begin_impl_frame_scheduling_enabled(false), + deadline_scheduling_enabled(true), using_synchronous_renderer_compositor(false), per_tile_painting_enabled(false), partial_swap_enabled(false), diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h index ca063b82d5..fafeb4db87 100644 --- a/cc/trees/layer_tree_settings.h +++ b/cc/trees/layer_tree_settings.h @@ -21,7 +21,7 @@ class CC_EXPORT LayerTreeSettings { bool impl_side_painting; bool allow_antialiasing; bool throttle_frame_production; - bool begin_frame_scheduling_enabled; + bool begin_impl_frame_scheduling_enabled; bool deadline_scheduling_enabled; bool using_synchronous_renderer_compositor; bool per_tile_painting_enabled; diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc index 2bd9b552e8..8f98c279a4 100644 --- a/cc/trees/occlusion_tracker.cc +++ b/cc/trees/occlusion_tracker.cc @@ -272,12 +272,6 @@ static void ReduceOcclusionBelowSurface(LayerType* contributing_layer, // to expand outside the clip. affected_area_in_target.Inset( -outset_left, -outset_top, -outset_right, -outset_bottom); - - gfx::Rect FilterOutsetsInTarget(-outset_left, - -outset_top, - outset_left + outset_right, - outset_top + outset_bottom); - Region affected_occlusion = IntersectRegions(*occlusion_from_inside_target, affected_area_in_target); Region::Iterator affected_occlusion_rects(affected_occlusion); diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h index 84844c8949..69975a6dd7 100644 --- a/cc/trees/proxy.h +++ b/cc/trees/proxy.h @@ -81,6 +81,7 @@ class CC_EXPORT Proxy { virtual void MainThreadHasStoppedFlinging() = 0; virtual bool CommitRequested() const = 0; + virtual bool BeginMainFrameRequested() const = 0; // Must be called before using the proxy. virtual void Start(scoped_ptr<OutputSurface> first_output_surface) = 0; diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index 634c3bc8b3..9de0fdd8d8 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc @@ -15,6 +15,7 @@ #include "cc/trees/blocking_task_runner.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" +#include "ui/gfx/frame_time.h" namespace cc { @@ -59,7 +60,7 @@ bool SingleThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) { gfx::Rect device_viewport_damage_rect = rect; LayerTreeHostImpl::FrameData frame; - if (!CommitAndComposite(base::TimeTicks::Now(), + if (!CommitAndComposite(gfx::FrameTime::Now(), device_viewport_damage_rect, true, // for_readback &frame)) @@ -254,6 +255,8 @@ void SingleThreadProxy::SetDeferCommits(bool defer_commits) { bool SingleThreadProxy::CommitRequested() const { return false; } +bool SingleThreadProxy::BeginMainFrameRequested() const { return false; } + size_t SingleThreadProxy::MaxPartialTextureUpdates() const { return std::numeric_limits<size_t>::max(); } @@ -329,11 +332,6 @@ bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread( limit_bytes, priority_cutoff, layer_tree_host_impl_->resource_provider()); } -void SingleThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() { - // Impl-side painting only. - NOTREACHED(); -} - void SingleThreadProxy::SendManagedMemoryStats() { DCHECK(Proxy::IsImplThread()); if (!layer_tree_host_impl_) @@ -455,7 +453,7 @@ bool SingleThreadProxy::CommitAndComposite( device_viewport_damage_rect, for_readback, frame); - layer_tree_host_->DidBeginFrame(); + layer_tree_host_->DidBeginMainFrame(); return result; } diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index 474fb1f110..843be729c4 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h @@ -39,6 +39,7 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient { virtual void NotifyInputThrottledUntilCommit() OVERRIDE {} virtual void SetDeferCommits(bool defer_commits) OVERRIDE; virtual bool CommitRequested() const OVERRIDE; + virtual bool BeginMainFrameRequested() const OVERRIDE; virtual void MainThreadHasStoppedFlinging() OVERRIDE {} virtual void Start(scoped_ptr<OutputSurface> first_output_surface) OVERRIDE; virtual void Stop() OVERRIDE; @@ -51,7 +52,7 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient { // LayerTreeHostImplClient implementation virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE; virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {} - virtual void BeginFrameOnImplThread(const BeginFrameArgs& args) + virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {} virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE; virtual void NotifyReadyToActivate() OVERRIDE; @@ -66,7 +67,6 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient { virtual bool ReduceContentsTextureMemoryOnImplThread( size_t limit_bytes, int priority_cutoff) OVERRIDE; - virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE; virtual void SendManagedMemoryStats() OVERRIDE; virtual bool IsInsideDraw() OVERRIDE; virtual void RenewTreePriority() OVERRIDE {} diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index e57def2c13..4f2f488eae 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc @@ -22,6 +22,7 @@ #include "cc/trees/blocking_task_runner.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" +#include "ui/gfx/frame_time.h" // Measured in seconds. const double kSmoothnessTakesPriorityExpirationDelay = 0.25; @@ -72,7 +73,7 @@ ThreadProxy::ThreadProxy( manage_tiles_pending_(false), commit_waits_for_activation_(false), inside_commit_(false), - begin_frame_sent_to_main_thread_completion_event_on_impl_thread_(NULL), + begin_main_frame_sent_completion_event_on_impl_thread_(NULL), readback_request_on_impl_thread_(NULL), commit_completion_event_on_impl_thread_(NULL), completion_event_for_commit_held_on_tree_activation_(NULL), @@ -80,8 +81,8 @@ ThreadProxy::ThreadProxy( next_frame_is_newly_committed_frame_on_impl_thread_(false), throttle_frame_production_( layer_tree_host->settings().throttle_frame_production), - begin_frame_scheduling_enabled_( - layer_tree_host->settings().begin_frame_scheduling_enabled), + begin_impl_frame_scheduling_enabled_( + layer_tree_host->settings().begin_impl_frame_scheduling_enabled), using_synchronous_renderer_compositor_( layer_tree_host->settings().using_synchronous_renderer_compositor), inside_draw_(false), @@ -90,7 +91,7 @@ ThreadProxy::ThreadProxy( input_throttled_until_commit_(false), renew_tree_priority_on_impl_thread_pending_(false), draw_duration_history_(kDurationHistorySize), - begin_frame_to_commit_duration_history_(kDurationHistorySize), + begin_main_frame_to_commit_duration_history_(kDurationHistorySize), commit_to_activate_duration_history_(kDurationHistorySize), weak_factory_on_impl_thread_(this), weak_factory_(this) { @@ -126,22 +127,22 @@ bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) { request.pixels = pixels; { DebugScopedSetMainThreadBlocked main_thread_blocked(this); - CompletionEvent begin_frame_sent_to_main_thread_completion; + CompletionEvent begin_main_frame_sent_completion; Proxy::ImplThreadTaskRunner() ->PostTask(FROM_HERE, base::Bind(&ThreadProxy::ForceCommitForReadbackOnImplThread, impl_thread_weak_ptr_, - &begin_frame_sent_to_main_thread_completion, + &begin_main_frame_sent_completion, &request)); - begin_frame_sent_to_main_thread_completion.Wait(); + begin_main_frame_sent_completion.Wait(); } in_composite_and_readback_ = true; // This is the forced commit. - // Note: The Impl thread also queues a separate BeginFrameOnMainThread on the + // Note: The Impl thread also queues a separate BeginMainFrame on the // main thread, which will be called after this CompositeAndReadback // completes, to replace the forced commit. - BeginFrameOnMainThread(scoped_ptr<BeginFrameAndCommitState>()); + BeginMainFrame(scoped_ptr<BeginMainFrameAndCommitState>()); in_composite_and_readback_ = false; // Composite and readback requires a second commit to undo any changes @@ -153,15 +154,15 @@ bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) { } void ThreadProxy::ForceCommitForReadbackOnImplThread( - CompletionEvent* begin_frame_sent_completion, + CompletionEvent* begin_main_frame_sent_completion, ReadbackRequest* request) { TRACE_EVENT0("cc", "ThreadProxy::ForceCommitForReadbackOnImplThread"); DCHECK(IsImplThread()); - DCHECK(!begin_frame_sent_to_main_thread_completion_event_on_impl_thread_); + DCHECK(!begin_main_frame_sent_completion_event_on_impl_thread_); DCHECK(!readback_request_on_impl_thread_); if (!layer_tree_host_impl_) { - begin_frame_sent_completion->Signal(); + begin_main_frame_sent_completion->Signal(); request->success = false; request->completion.Signal(); return; @@ -171,12 +172,12 @@ void ThreadProxy::ForceCommitForReadbackOnImplThread( scheduler_on_impl_thread_->SetNeedsForcedCommitForReadback(); if (scheduler_on_impl_thread_->CommitPending()) { - begin_frame_sent_completion->Signal(); + begin_main_frame_sent_completion->Signal(); return; } - begin_frame_sent_to_main_thread_completion_event_on_impl_thread_ = - begin_frame_sent_completion; + begin_main_frame_sent_completion_event_on_impl_thread_ = + begin_main_frame_sent_completion; } void ThreadProxy::FinishAllRendering() { @@ -342,6 +343,11 @@ void ThreadProxy::SetNeedsAnimate() { void ThreadProxy::SetNeedsUpdateLayers() { DCHECK(IsMainThread()); + + if (commit_request_sent_to_impl_thread_) + return; + TRACE_EVENT0("cc", "ThreadProxy::SetNeedsUpdateLayers"); + SendCommitRequestToImplThreadIfNeeded(); } @@ -387,13 +393,13 @@ void ThreadProxy::SetNeedsBeginImplFrame(bool enable) { DCHECK(IsImplThread()); TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginImplFrame", "enable", enable); - layer_tree_host_impl_->SetNeedsBeginFrame(enable); + layer_tree_host_impl_->SetNeedsBeginImplFrame(enable); UpdateBackgroundAnimateTicking(); } -void ThreadProxy::BeginFrameOnImplThread(const BeginFrameArgs& args) { +void ThreadProxy::BeginImplFrame(const BeginFrameArgs& args) { DCHECK(IsImplThread()); - TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnImplThread"); + TRACE_EVENT0("cc", "ThreadProxy::BeginImplFrame"); // Sample the frame time now. This time will be used for updating animations // when we draw. @@ -460,16 +466,6 @@ bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes, return true; } -void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() { - DCHECK(IsImplThread()); - - if (!layer_tree_host_->contents_texture_manager()) - return; - - layer_tree_host_->contents_texture_manager()->ReduceWastedMemoryOnImplThread( - layer_tree_host_impl_->resource_provider()); -} - void ThreadProxy::SendManagedMemoryStats() { DCHECK(IsImplThread()); if (!layer_tree_host_impl_) @@ -521,7 +517,7 @@ void ThreadProxy::SetDeferCommits(bool defer_commits) { if (!defer_commits_ && pending_deferred_commit_) Proxy::MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ThreadProxy::BeginFrameOnMainThread, + base::Bind(&ThreadProxy::BeginMainFrame, main_thread_weak_ptr_, base::Passed(&pending_deferred_commit_))); } @@ -531,6 +527,11 @@ bool ThreadProxy::CommitRequested() const { return commit_requested_; } +bool ThreadProxy::BeginMainFrameRequested() const { + DCHECK(IsMainThread()); + return commit_request_sent_to_impl_thread_; +} + void ThreadProxy::SetNeedsRedrawOnImplThread() { DCHECK(IsImplThread()); TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread"); @@ -685,52 +686,52 @@ void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) { void ThreadProxy::ScheduledActionSendBeginMainFrame() { TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginMainFrame"); - scoped_ptr<BeginFrameAndCommitState> begin_frame_state( - new BeginFrameAndCommitState); - begin_frame_state->monotonic_frame_begin_time = + scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state( + new BeginMainFrameAndCommitState); + begin_main_frame_state->monotonic_frame_begin_time = layer_tree_host_impl_->CurrentPhysicalTimeTicks(); - begin_frame_state->scroll_info = + begin_main_frame_state->scroll_info = layer_tree_host_impl_->ProcessScrollDeltas(); if (!layer_tree_host_impl_->settings().impl_side_painting) { DCHECK_GT(layer_tree_host_impl_->memory_allocation_limit_bytes(), 0u); } - begin_frame_state->memory_allocation_limit_bytes = + begin_main_frame_state->memory_allocation_limit_bytes = layer_tree_host_impl_->memory_allocation_limit_bytes(); - begin_frame_state->memory_allocation_priority_cutoff = + begin_main_frame_state->memory_allocation_priority_cutoff = layer_tree_host_impl_->memory_allocation_priority_cutoff(); - begin_frame_state->evicted_ui_resources = + begin_main_frame_state->evicted_ui_resources = layer_tree_host_impl_->EvictedUIResourcesExist(); Proxy::MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ThreadProxy::BeginFrameOnMainThread, + base::Bind(&ThreadProxy::BeginMainFrame, main_thread_weak_ptr_, - base::Passed(&begin_frame_state))); + base::Passed(&begin_main_frame_state))); - if (begin_frame_sent_to_main_thread_completion_event_on_impl_thread_) { - begin_frame_sent_to_main_thread_completion_event_on_impl_thread_->Signal(); - begin_frame_sent_to_main_thread_completion_event_on_impl_thread_ = NULL; + if (begin_main_frame_sent_completion_event_on_impl_thread_) { + begin_main_frame_sent_completion_event_on_impl_thread_->Signal(); + begin_main_frame_sent_completion_event_on_impl_thread_ = NULL; } - begin_frame_sent_to_main_thread_time_ = base::TimeTicks::HighResNow(); + begin_main_frame_sent_time_ = base::TimeTicks::HighResNow(); } -void ThreadProxy::BeginFrameOnMainThread( - scoped_ptr<BeginFrameAndCommitState> begin_frame_state) { - TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnMainThread"); +void ThreadProxy::BeginMainFrame( + scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) { + TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame"); DCHECK(IsMainThread()); if (!layer_tree_host_) return; if (defer_commits_) { - pending_deferred_commit_ = begin_frame_state.Pass(); + pending_deferred_commit_ = begin_main_frame_state.Pass(); layer_tree_host_->DidDeferCommit(); TRACE_EVENT0("cc", "EarlyOut_DeferCommits"); return; } // Do not notify the impl thread of commit requests that occur during - // the apply/animate/layout part of the BeginFrameAndCommit process since + // the apply/animate/layout part of the BeginMainFrameAndCommit process since // those commit requests will get painted immediately. Once we have done // the paint, commit_requested_ will be set to false to allow new commit // requests to be scheduled. @@ -750,22 +751,22 @@ void ThreadProxy::BeginFrameOnMainThread( bool did_handle = false; Proxy::ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread, + base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread, impl_thread_weak_ptr_, did_handle)); return; } - if (begin_frame_state) - layer_tree_host_->ApplyScrollAndScale(*begin_frame_state->scroll_info); + if (begin_main_frame_state) + layer_tree_host_->ApplyScrollAndScale(*begin_main_frame_state->scroll_info); - layer_tree_host_->WillBeginFrame(); + layer_tree_host_->WillBeginMainFrame(); - if (begin_frame_state) { + if (begin_main_frame_state) { layer_tree_host_->UpdateClientAnimations( - begin_frame_state->monotonic_frame_begin_time); + begin_main_frame_state->monotonic_frame_begin_time); layer_tree_host_->AnimateLayers( - begin_frame_state->monotonic_frame_begin_time); + begin_main_frame_state->monotonic_frame_begin_time); } // Unlink any backings that the impl thread has evicted, so that we know to @@ -774,18 +775,19 @@ void ThreadProxy::BeginFrameOnMainThread( layer_tree_host_->contents_texture_manager()-> UnlinkAndClearEvictedBackings(); - if (begin_frame_state) { + if (begin_main_frame_state) { layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( - begin_frame_state->memory_allocation_limit_bytes); + begin_main_frame_state->memory_allocation_limit_bytes); layer_tree_host_->contents_texture_manager()->SetExternalPriorityCutoff( - begin_frame_state->memory_allocation_priority_cutoff); + begin_main_frame_state->memory_allocation_priority_cutoff); } } // Recreate all UI resources if there were evicted UI resources when the impl // thread initiated the commit. - bool evicted_ui_resources = - begin_frame_state ? begin_frame_state->evicted_ui_resources : false; + bool evicted_ui_resources = begin_main_frame_state + ? begin_main_frame_state->evicted_ui_resources + : false; if (evicted_ui_resources) layer_tree_host_->RecreateUIResources(); @@ -818,7 +820,7 @@ void ThreadProxy::BeginFrameOnMainThread( bool did_handle = true; Proxy::ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread, + base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread, impl_thread_weak_ptr_, did_handle)); @@ -826,7 +828,7 @@ void ThreadProxy::BeginFrameOnMainThread( // detected to be a no-op. From the perspective of an embedder, this commit // went through, and input should no longer be throttled, etc. layer_tree_host_->CommitComplete(); - layer_tree_host_->DidBeginFrame(); + layer_tree_host_->DidBeginMainFrame(); return; } @@ -854,7 +856,7 @@ void ThreadProxy::BeginFrameOnMainThread( // point of view, but asynchronously performed on the impl thread, // coordinated by the Scheduler. { - TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnMainThread::commit"); + TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit"); DebugScopedSetMainThreadBlocked main_thread_blocked(this); @@ -881,7 +883,7 @@ void ThreadProxy::BeginFrameOnMainThread( } layer_tree_host_->CommitComplete(); - layer_tree_host_->DidBeginFrame(); + layer_tree_host_->DidBeginMainFrame(); } void ThreadProxy::StartCommitOnImplThread( @@ -933,8 +935,8 @@ void ThreadProxy::StartCommitOnImplThread( scheduler_on_impl_thread_->AnticipatedDrawTime()); } -void ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread(bool did_handle) { - TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread"); +void ThreadProxy::BeginMainFrameAbortedOnImplThread(bool did_handle) { + TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread"); DCHECK(IsImplThread()); DCHECK(scheduler_on_impl_thread_); DCHECK(scheduler_on_impl_thread_->CommitPending()); @@ -992,8 +994,8 @@ void ThreadProxy::ScheduledActionCommit() { commit_waits_for_activation_ = false; commit_complete_time_ = base::TimeTicks::HighResNow(); - begin_frame_to_commit_duration_history_.InsertSample( - commit_complete_time_ - begin_frame_sent_to_main_thread_time_); + begin_main_frame_to_commit_duration_history_.InsertSample( + commit_complete_time_ - begin_main_frame_sent_time_); // SetVisible kicks off the next scheduler action, so this must be last. scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); @@ -1243,7 +1245,7 @@ base::TimeDelta ThreadProxy::DrawDurationEstimate() { } base::TimeDelta ThreadProxy::BeginMainFrameToCommitDurationEstimate() { - return begin_frame_to_commit_duration_history_.Percentile( + return begin_main_frame_to_commit_duration_history_.Percentile( kCommitAndActivationDurationEstimationPercentile); } @@ -1254,7 +1256,7 @@ base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() { void ThreadProxy::PostBeginImplFrameDeadline(const base::Closure& closure, base::TimeTicks deadline) { - base::TimeDelta delta = deadline - base::TimeTicks::Now(); + base::TimeDelta delta = deadline - gfx::FrameTime::Now(); if (delta <= base::TimeDelta()) delta = base::TimeDelta(); Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, closure, delta); @@ -1398,7 +1400,7 @@ void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) { layer_tree_host_->DeleteContentsTexturesOnImplThread( layer_tree_host_impl_->resource_provider()); current_resource_update_controller_on_impl_thread_.reset(); - layer_tree_host_impl_->SetNeedsBeginFrame(false); + layer_tree_host_impl_->SetNeedsBeginImplFrame(false); scheduler_on_impl_thread_.reset(); layer_tree_host_impl_.reset(); weak_factory_on_impl_thread_.InvalidateWeakPtrs(); @@ -1409,12 +1411,12 @@ size_t ThreadProxy::MaxPartialTextureUpdates() const { return ResourceUpdateController::MaxPartialTextureUpdates(); } -ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState() +ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState() : memory_allocation_limit_bytes(0), memory_allocation_priority_cutoff(0), evicted_ui_resources(false) {} -ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {} +ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {} scoped_ptr<base::Value> ThreadProxy::AsValue() const { scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); @@ -1522,6 +1524,8 @@ void ThreadProxy::RenewTreePriority() { priority = NEW_CONTENT_TAKES_PRIORITY; layer_tree_host_impl_->SetTreePriority(priority); + scheduler_on_impl_thread_->SetSmoothnessTakesPriority( + priority == SMOOTHNESS_TAKES_PRIORITY); // Notify the the client of this compositor via the output surface. // TODO(epenner): Route this to compositor-thread instead of output-surface diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index 6badb03d00..3a213b90cd 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h @@ -56,6 +56,7 @@ class ThreadProxy : public Proxy, virtual void NotifyInputThrottledUntilCommit() OVERRIDE; virtual void SetDeferCommits(bool defer_commits) OVERRIDE; virtual bool CommitRequested() const OVERRIDE; + virtual bool BeginMainFrameRequested() const OVERRIDE; virtual void MainThreadHasStoppedFlinging() OVERRIDE; virtual void Start(scoped_ptr<OutputSurface> first_output_surface) OVERRIDE; virtual void Stop() OVERRIDE; @@ -69,7 +70,7 @@ class ThreadProxy : public Proxy, // LayerTreeHostImplClient implementation virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE; virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE; - virtual void BeginFrameOnImplThread(const BeginFrameArgs& args) OVERRIDE; + virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE; virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE; virtual void NotifyReadyToActivate() OVERRIDE; virtual void SetNeedsRedrawOnImplThread() OVERRIDE; @@ -83,7 +84,6 @@ class ThreadProxy : public Proxy, virtual bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes, int priority_cutoff) OVERRIDE; - virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE; virtual void SendManagedMemoryStats() OVERRIDE; virtual bool IsInsideDraw() OVERRIDE; virtual void RenewTreePriority() OVERRIDE; @@ -119,9 +119,9 @@ class ThreadProxy : public Proxy, ThreadProxy(LayerTreeHost* layer_tree_host, scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner); - struct BeginFrameAndCommitState { - BeginFrameAndCommitState(); - ~BeginFrameAndCommitState(); + struct BeginMainFrameAndCommitState { + BeginMainFrameAndCommitState(); + ~BeginMainFrameAndCommitState(); base::TimeTicks monotonic_frame_begin_time; scoped_ptr<ScrollAndScaleSet> scroll_info; @@ -131,8 +131,8 @@ class ThreadProxy : public Proxy, }; // Called on main thread. - void BeginFrameOnMainThread( - scoped_ptr<BeginFrameAndCommitState> begin_frame_state); + void BeginMainFrame( + scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state); void DidCommitAndDrawFrame(); void DidCompleteSwapBuffers(); void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue, @@ -150,13 +150,13 @@ class ThreadProxy : public Proxy, struct SchedulerStateRequest; void ForceCommitForReadbackOnImplThread( - CompletionEvent* begin_frame_sent_completion, + CompletionEvent* begin_main_frame_sent_completion, ReadbackRequest* request); void StartCommitOnImplThread( CompletionEvent* completion, ResourceUpdateQueue* queue, scoped_refptr<cc::ContextProvider> offscreen_context_provider); - void BeginFrameAbortedByMainThreadOnImplThread(bool did_handle); + void BeginMainFrameAbortedOnImplThread(bool did_handle); void RequestReadbackOnImplThread(ReadbackRequest* request); void FinishAllRenderingOnImplThread(CompletionEvent* completion); void InitializeImplOnImplThread(CompletionEvent* completion); @@ -198,9 +198,9 @@ class ThreadProxy : public Proxy, bool animate_requested_; // Set only when SetNeedsCommit is called. bool commit_requested_; - // Set by SetNeedsCommit and SetNeedsAnimate. + // Set by SetNeedsAnimate, SetNeedsUpdateLayers, and SetNeedsCommit. bool commit_request_sent_to_impl_thread_; - // Set by BeginFrameOnMainThread + // Set by BeginMainFrame bool created_offscreen_context_provider_; base::CancelableClosure output_surface_creation_callback_; LayerTreeHost* layer_tree_host_; @@ -226,7 +226,7 @@ class ThreadProxy : public Proxy, // Set when the main thread is waiting on a // ScheduledActionSendBeginMainFrame to be issued. CompletionEvent* - begin_frame_sent_to_main_thread_completion_event_on_impl_thread_; + begin_main_frame_sent_completion_event_on_impl_thread_; // Set when the main thread is waiting on a readback. ReadbackRequest* readback_request_on_impl_thread_; @@ -248,7 +248,7 @@ class ThreadProxy : public Proxy, bool next_frame_is_newly_committed_frame_on_impl_thread_; bool throttle_frame_production_; - bool begin_frame_scheduling_enabled_; + bool begin_impl_frame_scheduling_enabled_; bool using_synchronous_renderer_compositor_; bool inside_draw_; @@ -257,19 +257,19 @@ class ThreadProxy : public Proxy, bool defer_commits_; bool input_throttled_until_commit_; - scoped_ptr<BeginFrameAndCommitState> pending_deferred_commit_; + scoped_ptr<BeginMainFrameAndCommitState> pending_deferred_commit_; base::TimeTicks smoothness_takes_priority_expiration_time_; bool renew_tree_priority_on_impl_thread_pending_; RollingTimeDeltaHistory draw_duration_history_; - RollingTimeDeltaHistory begin_frame_to_commit_duration_history_; + RollingTimeDeltaHistory begin_main_frame_to_commit_duration_history_; RollingTimeDeltaHistory commit_to_activate_duration_history_; // Used for computing samples added to - // begin_frame_to_commit_draw_duration_history_ and + // begin_main_frame_to_commit_duration_history_ and // activation_duration_history_. - base::TimeTicks begin_frame_sent_to_main_thread_time_; + base::TimeTicks begin_main_frame_sent_time_; base::TimeTicks commit_complete_time_; base::WeakPtr<ThreadProxy> main_thread_weak_ptr_; diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc index 4e0c89fca5..3910bc051c 100644 --- a/cc/trees/tree_synchronizer_unittest.cc +++ b/cc/trees/tree_synchronizer_unittest.cc @@ -552,11 +552,8 @@ TEST_F(TreeSynchronizerTest, SynchronizeAnimations) { FakeProxy proxy; DebugScopedSetImplThread impl(&proxy); FakeRenderingStatsInstrumentation stats_instrumentation; - scoped_ptr<LayerTreeHostImpl> host_impl = - LayerTreeHostImpl::Create(settings, - NULL, - &proxy, - &stats_instrumentation); + scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( + settings, NULL, &proxy, &stats_instrumentation, NULL); scoped_refptr<Layer> layer_tree_root = Layer::Create(); host_->SetRootLayer(layer_tree_root); @@ -587,11 +584,8 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollParent) { FakeProxy proxy; DebugScopedSetImplThread impl(&proxy); FakeRenderingStatsInstrumentation stats_instrumentation; - scoped_ptr<LayerTreeHostImpl> host_impl = - LayerTreeHostImpl::Create(settings, - NULL, - &proxy, - &stats_instrumentation); + scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( + settings, NULL, &proxy, &stats_instrumentation, NULL); scoped_refptr<Layer> layer_tree_root = Layer::Create(); scoped_refptr<Layer> scroll_parent = Layer::Create(); @@ -665,11 +659,8 @@ TEST_F(TreeSynchronizerTest, SynchronizeClipParent) { FakeProxy proxy; DebugScopedSetImplThread impl(&proxy); FakeRenderingStatsInstrumentation stats_instrumentation; - scoped_ptr<LayerTreeHostImpl> host_impl = - LayerTreeHostImpl::Create(settings, - NULL, - &proxy, - &stats_instrumentation); + scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( + settings, NULL, &proxy, &stats_instrumentation, NULL); scoped_refptr<Layer> layer_tree_root = Layer::Create(); scoped_refptr<Layer> clip_parent = Layer::Create(); |