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 |