OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #include "ui/android/window_android.h" | 5 #include "ui/android/window_android.h" |
6 | 6 |
7 #include <stdint.h> | |
8 #include <unordered_set> | |
9 | |
7 #include "base/android/context_utils.h" | 10 #include "base/android/context_utils.h" |
8 #include "base/android/jni_android.h" | 11 #include "base/android/jni_android.h" |
9 #include "base/android/jni_array.h" | 12 #include "base/android/jni_array.h" |
10 #include "base/android/jni_string.h" | 13 #include "base/android/jni_string.h" |
11 #include "base/android/jni_weak_ref.h" | 14 #include "base/android/jni_weak_ref.h" |
12 #include "base/android/scoped_java_ref.h" | 15 #include "base/android/scoped_java_ref.h" |
16 #include "base/auto_reset.h" | |
17 #include "cc/output/begin_frame_args.h" | |
18 #include "cc/scheduler/begin_frame_source.h" | |
13 #include "jni/WindowAndroid_jni.h" | 19 #include "jni/WindowAndroid_jni.h" |
14 #include "ui/android/window_android_compositor.h" | 20 #include "ui/android/window_android_compositor.h" |
15 #include "ui/android/window_android_observer.h" | 21 #include "ui/android/window_android_observer.h" |
16 | 22 |
17 namespace ui { | 23 namespace ui { |
18 | 24 |
19 using base::android::AttachCurrentThread; | 25 using base::android::AttachCurrentThread; |
20 using base::android::JavaParamRef; | 26 using base::android::JavaParamRef; |
21 using base::android::JavaRef; | 27 using base::android::JavaRef; |
22 using base::android::ScopedJavaLocalRef; | 28 using base::android::ScopedJavaLocalRef; |
23 | 29 |
30 class WindowAndroid::WindowBeginFrameSource : public cc::BeginFrameSource { | |
31 public: | |
32 explicit WindowBeginFrameSource(WindowAndroid* window) | |
33 : window_(window), | |
34 in_on_vsync_(false) {} | |
35 ~WindowBeginFrameSource() override {} | |
36 | |
37 // cc::BeginFrameSource implementation. | |
38 void AddObserver(cc::BeginFrameObserver* obs) override; | |
39 void RemoveObserver(cc::BeginFrameObserver* obs) override; | |
40 void DidFinishFrame(cc::BeginFrameObserver* obs, | |
41 size_t remaining_frames) override {} | |
42 bool IsThrottled() const override { return true; } | |
43 | |
44 void OnVSync(base::TimeTicks frame_time, | |
45 base::TimeDelta vsync_period); | |
46 | |
47 private: | |
48 WindowAndroid* const window_; | |
49 std::unordered_set<cc::BeginFrameObserver*> observers_; | |
50 cc::BeginFrameArgs last_begin_frame_args_; | |
51 bool in_on_vsync_; | |
52 }; | |
53 | |
54 void WindowAndroid::WindowBeginFrameSource::AddObserver( | |
55 cc::BeginFrameObserver* obs) { | |
56 DCHECK(obs); | |
57 DCHECK(observers_.find(obs) == observers_.end()); | |
boliu
2016/12/12 21:41:48
nit: use base::ContainsKey? more readable
Eric Seckler
2016/12/13 10:03:56
Done.
| |
58 | |
59 observers_.insert(obs); | |
60 obs->OnBeginFrameSourcePausedChanged(false); | |
61 window_->SetNeedsBeginFrames(true); | |
62 | |
63 // Send a MISSED BeginFrame if possible and necessary. If an observer is added | |
boliu
2016/12/12 21:41:48
any reason this is needed?
Eric Seckler
2016/12/13 10:03:56
I'm somewhat new to BeginFrames myself, so briande
boliu
2016/12/13 18:07:47
Sorry, typed that comment before I realized this c
| |
64 // during OnVSync(), it will get a NORMAL BeginFrame from OnVSync() instead. | |
65 if (!in_on_vsync_ && last_begin_frame_args_.IsValid()) { | |
66 cc::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | |
67 if (!last_args.IsValid() || | |
68 last_args.frame_time < last_begin_frame_args_.frame_time) { | |
69 last_begin_frame_args_.type = cc::BeginFrameArgs::MISSED; | |
70 // TODO(crbug.com/602485): A deadline doesn't make too much sense | |
71 // for a missed BeginFrame (the intention rather is 'immediately'), | |
72 // but currently the retro frame logic is very strict in discarding | |
73 // BeginFrames. | |
74 last_begin_frame_args_.deadline = | |
75 base::TimeTicks::Now() + last_begin_frame_args_.interval; | |
76 obs->OnBeginFrame(last_begin_frame_args_); | |
77 } | |
78 } | |
79 } | |
80 | |
81 void WindowAndroid::WindowBeginFrameSource::RemoveObserver( | |
82 cc::BeginFrameObserver* obs) { | |
83 DCHECK(obs); | |
84 DCHECK(observers_.find(obs) != observers_.end()); | |
boliu
2016/12/12 21:41:48
ditto ContainsKey
Eric Seckler
2016/12/13 10:03:56
Done.
| |
85 | |
86 observers_.erase(obs); | |
87 if (observers_.empty()) | |
88 window_->SetNeedsBeginFrames(false); | |
89 } | |
90 | |
91 void WindowAndroid::WindowBeginFrameSource::OnVSync( | |
92 base::TimeTicks frame_time, | |
93 base::TimeDelta vsync_period) { | |
94 base::AutoReset<bool> auto_reset(&in_on_vsync_, true); | |
95 | |
96 // frame time is in the past, so give the next vsync period as the deadline. | |
97 base::TimeTicks deadline = frame_time + vsync_period; | |
98 last_begin_frame_args_ = | |
99 cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline, | |
100 vsync_period, cc::BeginFrameArgs::NORMAL); | |
101 DCHECK(last_begin_frame_args_.IsValid()); | |
102 | |
103 // Support SynchronousCompositorBrowserFilter: Observers added during vsync | |
104 // distribution receive a NORMAL args in addition to the missed ones, after | |
105 // all current observers were notified. We also have to support observers | |
106 // removing themselves during OnBeginFrame, so we iterate on set copies until | |
107 // all observers were notified once. | |
108 std::unordered_set<cc::BeginFrameObserver*> notified_observers; | |
109 bool observer_was_notified = true; | |
110 while (observer_was_notified) { | |
boliu
2016/12/12 21:41:48
any reason we don't keep using base::ObserverList
Eric Seckler
2016/12/13 10:03:56
For two (rather subjective) reasons:
1) This makes
boliu
2016/12/13 18:07:47
Or you can just keep a count of the number of obse
Eric Seckler
2016/12/14 15:36:57
Sounds good, done.
| |
111 observer_was_notified = false; | |
112 std::unordered_set<cc::BeginFrameObserver*> observers(observers_); | |
113 for (auto* obs : observers) { | |
114 if (notified_observers.find(obs) == notified_observers.end()) { | |
115 obs->OnBeginFrame(last_begin_frame_args_); | |
116 notified_observers.insert(obs); | |
117 observer_was_notified = true; | |
118 } | |
119 } | |
120 } | |
121 } | |
122 | |
24 WindowAndroid::WindowAndroid(JNIEnv* env, jobject obj, int display_id) | 123 WindowAndroid::WindowAndroid(JNIEnv* env, jobject obj, int display_id) |
25 : display_id_(display_id), compositor_(NULL) { | 124 : display_id_(display_id), |
125 compositor_(NULL), | |
126 begin_frame_source_(new WindowBeginFrameSource(this)), | |
127 needs_begin_frames_(false) { | |
26 java_window_.Reset(env, obj); | 128 java_window_.Reset(env, obj); |
27 } | 129 } |
28 | 130 |
29 void WindowAndroid::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) { | 131 void WindowAndroid::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
30 delete this; | 132 delete this; |
31 } | 133 } |
32 | 134 |
33 ScopedJavaLocalRef<jobject> WindowAndroid::GetJavaObject() { | 135 ScopedJavaLocalRef<jobject> WindowAndroid::GetJavaObject() { |
34 return base::android::ScopedJavaLocalRef<jobject>(java_window_); | 136 return base::android::ScopedJavaLocalRef<jobject>(java_window_); |
35 } | 137 } |
(...skipping 26 matching lines...) Expand all Loading... | |
62 | 164 |
63 void WindowAndroid::AddObserver(WindowAndroidObserver* observer) { | 165 void WindowAndroid::AddObserver(WindowAndroidObserver* observer) { |
64 if (!observer_list_.HasObserver(observer)) | 166 if (!observer_list_.HasObserver(observer)) |
65 observer_list_.AddObserver(observer); | 167 observer_list_.AddObserver(observer); |
66 } | 168 } |
67 | 169 |
68 void WindowAndroid::RemoveObserver(WindowAndroidObserver* observer) { | 170 void WindowAndroid::RemoveObserver(WindowAndroidObserver* observer) { |
69 observer_list_.RemoveObserver(observer); | 171 observer_list_.RemoveObserver(observer); |
70 } | 172 } |
71 | 173 |
174 cc::BeginFrameSource* WindowAndroid::GetBeginFrameSource() { | |
175 return begin_frame_source_.get(); | |
176 } | |
177 | |
72 void WindowAndroid::AttachCompositor(WindowAndroidCompositor* compositor) { | 178 void WindowAndroid::AttachCompositor(WindowAndroidCompositor* compositor) { |
73 if (compositor_ && compositor != compositor_) | 179 if (compositor_ && compositor != compositor_) |
74 DetachCompositor(); | 180 DetachCompositor(); |
75 | 181 |
76 compositor_ = compositor; | 182 compositor_ = compositor; |
77 for (WindowAndroidObserver& observer : observer_list_) | 183 for (WindowAndroidObserver& observer : observer_list_) |
78 observer.OnAttachCompositor(); | 184 observer.OnAttachCompositor(); |
79 } | 185 } |
80 | 186 |
81 void WindowAndroid::DetachCompositor() { | 187 void WindowAndroid::DetachCompositor() { |
82 compositor_ = NULL; | 188 compositor_ = NULL; |
83 for (WindowAndroidObserver& observer : observer_list_) | 189 for (WindowAndroidObserver& observer : observer_list_) |
84 observer.OnDetachCompositor(); | 190 observer.OnDetachCompositor(); |
85 observer_list_.Clear(); | 191 observer_list_.Clear(); |
86 } | 192 } |
87 | 193 |
88 void WindowAndroid::RequestVSyncUpdate() { | 194 void WindowAndroid::RequestVSyncUpdate() { |
89 JNIEnv* env = AttachCurrentThread(); | 195 JNIEnv* env = AttachCurrentThread(); |
90 Java_WindowAndroid_requestVSyncUpdate(env, GetJavaObject()); | 196 Java_WindowAndroid_requestVSyncUpdate(env, GetJavaObject()); |
91 } | 197 } |
92 | 198 |
199 void WindowAndroid::SetNeedsBeginFrames(bool needs_begin_frames) { | |
200 if (needs_begin_frames_ == needs_begin_frames) | |
201 return; | |
202 | |
203 needs_begin_frames_ = needs_begin_frames; | |
204 if (needs_begin_frames_) | |
205 RequestVSyncUpdate(); | |
206 } | |
207 | |
93 void WindowAndroid::SetNeedsAnimate() { | 208 void WindowAndroid::SetNeedsAnimate() { |
94 if (compositor_) | 209 if (compositor_) |
95 compositor_->SetNeedsAnimate(); | 210 compositor_->SetNeedsAnimate(); |
96 } | 211 } |
97 | 212 |
98 void WindowAndroid::Animate(base::TimeTicks begin_frame_time) { | 213 void WindowAndroid::Animate(base::TimeTicks begin_frame_time) { |
99 for (WindowAndroidObserver& observer : observer_list_) | 214 for (WindowAndroidObserver& observer : observer_list_) |
100 observer.OnAnimate(begin_frame_time); | 215 observer.OnAnimate(begin_frame_time); |
101 } | 216 } |
102 | 217 |
103 void WindowAndroid::OnVSync(JNIEnv* env, | 218 void WindowAndroid::OnVSync(JNIEnv* env, |
104 const JavaParamRef<jobject>& obj, | 219 const JavaParamRef<jobject>& obj, |
105 jlong time_micros, | 220 jlong time_micros, |
106 jlong period_micros) { | 221 jlong period_micros) { |
107 base::TimeTicks frame_time(base::TimeTicks::FromInternalValue(time_micros)); | 222 base::TimeTicks frame_time(base::TimeTicks::FromInternalValue(time_micros)); |
108 base::TimeDelta vsync_period( | 223 base::TimeDelta vsync_period( |
109 base::TimeDelta::FromMicroseconds(period_micros)); | 224 base::TimeDelta::FromMicroseconds(period_micros)); |
110 for (WindowAndroidObserver& observer : observer_list_) | 225 begin_frame_source_->OnVSync(frame_time, vsync_period); |
111 observer.OnVSync(frame_time, vsync_period); | 226 if (needs_begin_frames_) |
112 if (compositor_) | 227 RequestVSyncUpdate(); |
113 compositor_->OnVSync(frame_time, vsync_period); | |
114 } | 228 } |
115 | 229 |
116 void WindowAndroid::OnVisibilityChanged(JNIEnv* env, | 230 void WindowAndroid::OnVisibilityChanged(JNIEnv* env, |
117 const JavaParamRef<jobject>& obj, | 231 const JavaParamRef<jobject>& obj, |
118 bool visible) { | 232 bool visible) { |
119 for (WindowAndroidObserver& observer : observer_list_) | 233 for (WindowAndroidObserver& observer : observer_list_) |
120 observer.OnRootWindowVisibilityChanged(visible); | 234 observer.OnRootWindowVisibilityChanged(visible); |
121 } | 235 } |
122 | 236 |
123 void WindowAndroid::OnActivityStopped(JNIEnv* env, | 237 void WindowAndroid::OnActivityStopped(JNIEnv* env, |
(...skipping 30 matching lines...) Expand all Loading... | |
154 // ---------------------------------------------------------------------------- | 268 // ---------------------------------------------------------------------------- |
155 // Native JNI methods | 269 // Native JNI methods |
156 // ---------------------------------------------------------------------------- | 270 // ---------------------------------------------------------------------------- |
157 | 271 |
158 jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj, int sdk_display_id) { | 272 jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj, int sdk_display_id) { |
159 WindowAndroid* window = new WindowAndroid(env, obj, sdk_display_id); | 273 WindowAndroid* window = new WindowAndroid(env, obj, sdk_display_id); |
160 return reinterpret_cast<intptr_t>(window); | 274 return reinterpret_cast<intptr_t>(window); |
161 } | 275 } |
162 | 276 |
163 } // namespace ui | 277 } // namespace ui |
OLD | NEW |