Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Unified Diff: ui/android/window_android.cc

Issue 2527283003: cc: Introduce BeginFrame sequence numbers and acknowledgements.
Patch Set: Address Brian's comments. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/android/window_android.h ('k') | ui/android/window_android_compositor.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/android/window_android.cc
diff --git a/ui/android/window_android.cc b/ui/android/window_android.cc
index cff32ba6f571def1c787cd219296027d86f1cbc8..49374511ecf588155ad3268ad07d14bfe1729f0d 100644
--- a/ui/android/window_android.cc
+++ b/ui/android/window_android.cc
@@ -4,12 +4,19 @@
#include "ui/android/window_android.h"
+#include <stdint.h>
+#include <unordered_set>
+
#include "base/android/context_utils.h"
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
+#include "base/auto_reset.h"
+#include "base/stl_util.h"
+#include "cc/output/begin_frame_args.h"
+#include "cc/scheduler/begin_frame_source.h"
#include "jni/WindowAndroid_jni.h"
#include "ui/android/window_android_compositor.h"
#include "ui/android/window_android_observer.h"
@@ -21,8 +28,106 @@ using base::android::JavaParamRef;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
+class WindowAndroid::WindowBeginFrameSource : public cc::BeginFrameSource {
+ public:
+ explicit WindowBeginFrameSource(WindowAndroid* window)
+ : window_(window),
+ next_sequence_number_(cc::BeginFrameArgs::kStartingFrameNumber),
+ in_on_vsync_(false) {}
+ ~WindowBeginFrameSource() override {}
+
+ // cc::BeginFrameSource implementation.
+ void AddObserver(cc::BeginFrameObserver* obs) override;
+ void RemoveObserver(cc::BeginFrameObserver* obs) override;
+ void DidFinishFrame(cc::BeginFrameObserver* obs,
+ const cc::BeginFrameAck& ack) override {}
+ bool IsThrottled() const override { return true; }
+
+ void OnVSync(base::TimeTicks frame_time,
+ base::TimeDelta vsync_period);
+
+ private:
+ WindowAndroid* const window_;
+ std::unordered_set<cc::BeginFrameObserver*> observers_;
+ cc::BeginFrameArgs last_begin_frame_args_;
+ uint64_t next_sequence_number_;
+ bool in_on_vsync_;
+};
+
+void WindowAndroid::WindowBeginFrameSource::AddObserver(
+ cc::BeginFrameObserver* obs) {
+ DCHECK(obs);
+ DCHECK(observers_.find(obs) == observers_.end());
+
+ observers_.insert(obs);
+ obs->OnBeginFrameSourcePausedChanged(false);
+ window_->OnNeedsBeginFramesChange(true);
+
+ // Send a MISSED BeginFrame if possible and necessary. If an observer is added
+ // during OnVSync(), it will get a NORMAL BeginFrame from OnVSync() instead.
+ if (!in_on_vsync_ && last_begin_frame_args_.IsValid()) {
+ cc::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
+ if (!last_args.IsValid() ||
+ last_args.sequence_number < last_begin_frame_args_.sequence_number) {
+ last_begin_frame_args_.type = cc::BeginFrameArgs::MISSED;
+ // TODO(crbug.com/602485): A deadline doesn't make too much sense
+ // for a missed BeginFrame (the intention rather is 'immediately'),
+ // but currently the retro frame logic is very strict in discarding
+ // BeginFrames.
+ last_begin_frame_args_.deadline =
+ base::TimeTicks::Now() + last_begin_frame_args_.interval;
+ obs->OnBeginFrame(last_begin_frame_args_);
+ }
+ }
+}
+
+void WindowAndroid::WindowBeginFrameSource::RemoveObserver(
+ cc::BeginFrameObserver* obs) {
+ DCHECK(obs);
+ DCHECK(observers_.find(obs) != observers_.end());
+
+ observers_.erase(obs);
+ if (observers_.empty())
+ window_->OnNeedsBeginFramesChange(false);
+}
+
+void WindowAndroid::WindowBeginFrameSource::OnVSync(
+ base::TimeTicks frame_time,
+ base::TimeDelta vsync_period) {
+ base::AutoReset<bool> auto_reset(&in_on_vsync_, true);
+
+ // frame time is in the past, so give the next vsync period as the deadline.
+ base::TimeTicks deadline = frame_time + vsync_period;
+ last_begin_frame_args_ = cc::BeginFrameArgs::Create(
+ BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_++, frame_time,
+ deadline, vsync_period, cc::BeginFrameArgs::NORMAL);
+ DCHECK(last_begin_frame_args_.IsValid());
+
+ // Support SynchronousCompositorBrowserFilter: Observers added during vsync
+ // distribution receive a NORMAL args in addition to the missed ones, after
+ // all current observers were notified. We also have to support observers
+ // removing themselves during OnBeginFrame, so we iterate on set copies until
+ // all observers were notified once.
+ std::unordered_set<cc::BeginFrameObserver*> notified_observers;
+ bool observer_was_notified = true;
+ while (observer_was_notified) {
+ observer_was_notified = false;
+ std::unordered_set<cc::BeginFrameObserver*> observers(observers_);
+ for (auto* obs : observers) {
+ if (notified_observers.find(obs) == notified_observers.end()) {
+ obs->OnBeginFrame(last_begin_frame_args_);
+ notified_observers.insert(obs);
+ observer_was_notified = true;
+ }
+ }
+ }
+}
+
WindowAndroid::WindowAndroid(JNIEnv* env, jobject obj, int display_id)
- : display_id_(display_id), compositor_(NULL) {
+ : display_id_(display_id),
+ compositor_(NULL),
+ begin_frame_source_(new WindowBeginFrameSource(this)),
+ needs_begin_frames_(false) {
java_window_.Reset(env, obj);
}
@@ -69,6 +174,10 @@ void WindowAndroid::RemoveObserver(WindowAndroidObserver* observer) {
observer_list_.RemoveObserver(observer);
}
+cc::BeginFrameSource* WindowAndroid::GetBeginFrameSource() {
+ return begin_frame_source_.get();
+}
+
void WindowAndroid::AttachCompositor(WindowAndroidCompositor* compositor) {
if (compositor_ && compositor != compositor_)
DetachCompositor();
@@ -107,10 +216,9 @@ void WindowAndroid::OnVSync(JNIEnv* env,
base::TimeTicks frame_time(base::TimeTicks::FromInternalValue(time_micros));
base::TimeDelta vsync_period(
base::TimeDelta::FromMicroseconds(period_micros));
- for (WindowAndroidObserver& observer : observer_list_)
- observer.OnVSync(frame_time, vsync_period);
- if (compositor_)
- compositor_->OnVSync(frame_time, vsync_period);
+ begin_frame_source_->OnVSync(frame_time, vsync_period);
+ if (needs_begin_frames_)
+ RequestVSyncUpdate();
}
void WindowAndroid::OnVisibilityChanged(JNIEnv* env,
@@ -146,6 +254,15 @@ bool WindowAndroid::CanRequestPermission(const std::string& permission) {
base::android::ConvertUTF8ToJavaString(env, permission));
}
+void WindowAndroid::OnNeedsBeginFramesChange(bool needs_begin_frames) {
+ if (needs_begin_frames_ == needs_begin_frames)
+ return;
+
+ needs_begin_frames_ = needs_begin_frames;
+ if (needs_begin_frames_)
+ RequestVSyncUpdate();
+}
+
WindowAndroid* WindowAndroid::GetWindowAndroid() const {
DCHECK(parent_ == nullptr);
return const_cast<WindowAndroid*>(this);
« no previous file with comments | « ui/android/window_android.h ('k') | ui/android/window_android_compositor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698