| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CC_BASE_SYNCED_PROPERTY_H_ | 5 #ifndef CC_BASE_SYNCED_PROPERTY_H_ |
| 6 #define CC_BASE_SYNCED_PROPERTY_H_ | 6 #define CC_BASE_SYNCED_PROPERTY_H_ |
| 7 | 7 |
| 8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
| 9 | 9 |
| 10 namespace cc { | 10 namespace cc { |
| 11 | 11 |
| 12 // This class is the basic primitive used for impl-thread scrolling. Its job is | 12 // This class is the basic primitive used for impl-thread scrolling. Its job is |
| 13 // to sanely resolve the case where both the main and impl thread are | 13 // to sanely resolve the case where both the main and impl thread are |
| 14 // concurrently updating the same value (for example, when Javascript sets the | 14 // concurrently updating the same value (for example, when Javascript sets the |
| 15 // scroll offset during an ongoing impl-side scroll). | 15 // scroll offset during an ongoing impl-side scroll). |
| 16 // | 16 // |
| 17 // There are three trees (main, pending, and active) and therefore also three | 17 // There are three trees (main, pending, and active) and therefore also three |
| 18 // places with their own idea of the scroll offsets (and analogous properties | 18 // places with their own idea of the scroll offsets (and analogous properties |
| 19 // like page scale). Objects of this class are meant to be held on the Impl | 19 // like page scale). Objects of this class are meant to be held on the Impl |
| 20 // side, and contain the canonical reference for the pending and active trees, | 20 // side, and contain the canonical reference for the pending and active trees, |
| 21 // as well as keeping track of the latest delta sent to the main thread (which | 21 // as well as keeping track of the latest delta sent to the main thread (which |
| 22 // is necessary for conflict resolution). | 22 // is necessary for conflict resolution). |
| 23 | 23 |
| 24 template <typename T> | 24 template <typename T> |
| 25 class SyncedProperty : public base::RefCounted<SyncedProperty<T>> { | 25 class SyncedProperty : public base::RefCounted<SyncedProperty<T>> { |
| 26 public: | 26 public: |
| 27 SyncedProperty() {} | 27 SyncedProperty() : clobber_active_value_(false) {} |
| 28 | 28 |
| 29 // Returns the canonical value for the specified tree, including the sum of | 29 // Returns the canonical value for the specified tree, including the sum of |
| 30 // all deltas. The pending tree should use this for activation purposes and | 30 // all deltas. The pending tree should use this for activation purposes and |
| 31 // the active tree should use this for drawing. | 31 // the active tree should use this for drawing. |
| 32 typename T::ValueType Current(bool is_active_tree) const { | 32 typename T::ValueType Current(bool is_active_tree) const { |
| 33 if (is_active_tree) | 33 if (is_active_tree) |
| 34 return active_base_.Combine(active_delta_).get(); | 34 return active_base_.Combine(active_delta_).get(); |
| 35 else | 35 else |
| 36 return pending_base_.Combine(PendingDelta()).get(); | 36 return pending_base_.Combine(PendingDelta()).get(); |
| 37 } | 37 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 // delta (which will make the delta zero at steady state, or make it contain | 77 // delta (which will make the delta zero at steady state, or make it contain |
| 78 // only the difference since the last send). | 78 // only the difference since the last send). |
| 79 bool PushPendingToActive() { | 79 bool PushPendingToActive() { |
| 80 if (active_base_.get() == pending_base_.get() && | 80 if (active_base_.get() == pending_base_.get() && |
| 81 sent_delta_.get() == T::Identity().get()) | 81 sent_delta_.get() == T::Identity().get()) |
| 82 return false; | 82 return false; |
| 83 | 83 |
| 84 active_base_ = pending_base_; | 84 active_base_ = pending_base_; |
| 85 active_delta_ = PendingDelta(); | 85 active_delta_ = PendingDelta(); |
| 86 sent_delta_ = T::Identity(); | 86 sent_delta_ = T::Identity(); |
| 87 clobber_active_value_ = false; |
| 87 | 88 |
| 88 return true; | 89 return true; |
| 89 } | 90 } |
| 90 | 91 |
| 91 // This simulates the consequences of the sent value getting committed and | 92 // This simulates the consequences of the sent value getting committed and |
| 92 // activated. The value sent to the main thread ends up combined with the | 93 // activated. The value sent to the main thread ends up combined with the |
| 93 // active value, and the sent_delta is subtracted from the delta. | 94 // active value, and the sent_delta is subtracted from the delta. |
| 94 void AbortCommit() { | 95 void AbortCommit() { |
| 95 active_base_ = active_base_.Combine(sent_delta_); | 96 active_base_ = active_base_.Combine(sent_delta_); |
| 96 active_delta_ = PendingDelta(); | 97 active_delta_ = PendingDelta(); |
| 97 sent_delta_ = T::Identity(); | 98 sent_delta_ = T::Identity(); |
| 98 } | 99 } |
| 99 | 100 |
| 100 // Values as last pushed to the pending or active tree respectively, with no | 101 // Values as last pushed to the pending or active tree respectively, with no |
| 101 // impl-thread delta applied. | 102 // impl-thread delta applied. |
| 102 typename T::ValueType PendingBase() const { return pending_base_.get(); } | 103 typename T::ValueType PendingBase() const { return pending_base_.get(); } |
| 103 typename T::ValueType ActiveBase() const { return active_base_.get(); } | 104 typename T::ValueType ActiveBase() const { return active_base_.get(); } |
| 104 | 105 |
| 105 // The new delta we would use if we decide to activate now. This delta | 106 // The new delta we would use if we decide to activate now. This delta |
| 106 // excludes the amount that we expect the main thread to reflect back at the | 107 // excludes the amount that we expect the main thread to reflect back at the |
| 107 // impl thread during the commit. | 108 // impl thread during the commit. |
| 108 T PendingDelta() const { return active_delta_.InverseCombine(sent_delta_); } | 109 T PendingDelta() const { |
| 110 if (clobber_active_value_) |
| 111 return T::Identity(); |
| 112 return active_delta_.InverseCombine(sent_delta_); |
| 113 } |
| 114 |
| 115 void set_clobber_active_value() { clobber_active_value_ = true; } |
| 109 | 116 |
| 110 private: | 117 private: |
| 111 // Value last committed to the pending tree. | 118 // Value last committed to the pending tree. |
| 112 T pending_base_; | 119 T pending_base_; |
| 113 // Value last committed to the active tree (on the last activation). | 120 // Value last committed to the active tree (on the last activation). |
| 114 T active_base_; | 121 T active_base_; |
| 115 // The difference between the active_base_ and the user-perceived value. | 122 // The difference between the active_base_ and the user-perceived value. |
| 116 T active_delta_; | 123 T active_delta_; |
| 117 // The value sent to the main thread (on the last BeginFrame); this is always | 124 // The value sent to the main thread (on the last BeginFrame); this is always |
| 118 // identity outside of the BeginFrame-to-activation interval. | 125 // identity outside of the BeginFrame-to-activation interval. |
| 119 T sent_delta_; | 126 T sent_delta_; |
| 127 // When true the pending delta is always identity so that it does not change |
| 128 // and will clobber the active value on push. |
| 129 bool clobber_active_value_; |
| 120 | 130 |
| 121 friend class base::RefCounted<SyncedProperty<T>>; | 131 friend class base::RefCounted<SyncedProperty<T>>; |
| 122 ~SyncedProperty() {} | 132 ~SyncedProperty() {} |
| 123 }; | 133 }; |
| 124 | 134 |
| 125 // SyncedProperty's delta-based conflict resolution logic makes sense for any | 135 // SyncedProperty's delta-based conflict resolution logic makes sense for any |
| 126 // mathematical group. In practice, there are two that are useful: | 136 // mathematical group. In practice, there are two that are useful: |
| 127 // 1. Numbers/vectors with addition and identity = 0 (like scroll offsets) | 137 // 1. Numbers/vectors with addition and identity = 0 (like scroll offsets) |
| 128 // 2. Real numbers with multiplication and identity = 1 (like page scale) | 138 // 2. Real numbers with multiplication and identity = 1 (like page scale) |
| 129 | 139 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 return ScaleGroup(value_ / p.value_); | 178 return ScaleGroup(value_ / p.value_); |
| 169 } | 179 } |
| 170 | 180 |
| 171 private: | 181 private: |
| 172 float value_; | 182 float value_; |
| 173 }; | 183 }; |
| 174 | 184 |
| 175 } // namespace cc | 185 } // namespace cc |
| 176 | 186 |
| 177 #endif // CC_BASE_SYNCED_PROPERTY_H_ | 187 #endif // CC_BASE_SYNCED_PROPERTY_H_ |
| OLD | NEW |