Index: content/browser/renderer_host/compositor_impl_android.cc |
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc |
index 0763bc63b44a4cf95acb905d83854160d0f7585a..95bc0d44539f51f451ec1ac7c4d3b5f41c578b6a 100644 |
--- a/content/browser/renderer_host/compositor_impl_android.cc |
+++ b/content/browser/renderer_host/compositor_impl_android.cc |
@@ -40,6 +40,7 @@ |
#include "cc/output/vulkan_in_process_context_provider.h" |
#include "cc/raster/single_thread_task_graph_runner.h" |
#include "cc/resources/ui_resource_manager.h" |
+#include "cc/scheduler/begin_frame_source.h" |
#include "cc/surfaces/direct_compositor_frame_sink.h" |
#include "cc/surfaces/display.h" |
#include "cc/surfaces/display_scheduler.h" |
@@ -137,6 +138,78 @@ |
return attributes; |
} |
+class ExternalBeginFrameSource : public cc::BeginFrameSource, |
+ public CompositorImpl::VSyncObserver { |
+ public: |
+ explicit ExternalBeginFrameSource(CompositorImpl* compositor) |
+ : compositor_(compositor) { |
+ compositor_->AddObserver(this); |
+ } |
+ ~ExternalBeginFrameSource() override { compositor_->RemoveObserver(this); } |
+ |
+ // cc::BeginFrameSource implementation. |
+ void AddObserver(cc::BeginFrameObserver* obs) override; |
+ void RemoveObserver(cc::BeginFrameObserver* obs) override; |
+ void DidFinishFrame(cc::BeginFrameObserver* obs, |
+ size_t remaining_frames) override {} |
+ bool IsThrottled() const override { return true; } |
+ |
+ // CompositorImpl::VSyncObserver implementation. |
+ void OnVSync(base::TimeTicks frame_time, |
+ base::TimeDelta vsync_period) override; |
+ |
+ private: |
+ CompositorImpl* const compositor_; |
+ std::unordered_set<cc::BeginFrameObserver*> observers_; |
+ cc::BeginFrameArgs last_begin_frame_args_; |
+}; |
+ |
+void ExternalBeginFrameSource::AddObserver(cc::BeginFrameObserver* obs) { |
+ DCHECK(obs); |
+ DCHECK(observers_.find(obs) == observers_.end()); |
+ |
+ observers_.insert(obs); |
+ obs->OnBeginFrameSourcePausedChanged(false); |
+ compositor_->OnNeedsBeginFramesChange(true); |
+ |
+ if (last_begin_frame_args_.IsValid()) { |
+ // Send a MISSED begin frame if necessary. |
+ cc::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
+ if (!last_args.IsValid() || |
+ (last_begin_frame_args_.frame_time > last_args.frame_time)) { |
+ 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 ExternalBeginFrameSource::RemoveObserver(cc::BeginFrameObserver* obs) { |
+ DCHECK(obs); |
+ DCHECK(observers_.find(obs) != observers_.end()); |
+ |
+ observers_.erase(obs); |
+ if (observers_.empty()) |
+ compositor_->OnNeedsBeginFramesChange(false); |
+} |
+ |
+void ExternalBeginFrameSource::OnVSync(base::TimeTicks frame_time, |
+ base::TimeDelta vsync_period) { |
+ // 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, frame_time, deadline, |
+ vsync_period, cc::BeginFrameArgs::NORMAL); |
+ std::unordered_set<cc::BeginFrameObserver*> observers(observers_); |
+ for (auto* obs : observers) |
+ obs->OnBeginFrame(last_begin_frame_args_); |
+} |
+ |
class AndroidOutputSurface : public cc::OutputSurface { |
public: |
explicit AndroidOutputSurface( |
@@ -333,6 +406,7 @@ |
pending_swapbuffers_(0U), |
num_successive_context_creation_failures_(0), |
compositor_frame_sink_request_pending_(false), |
+ needs_begin_frames_(false), |
weak_factory_(this) { |
ui::ContextProviderFactory::GetInstance() |
->GetSurfaceManager() |
@@ -652,6 +726,7 @@ |
cc::SurfaceManager* manager = |
ui::ContextProviderFactory::GetInstance()->GetSurfaceManager(); |
auto* task_runner = base::ThreadTaskRunnerHandle::Get().get(); |
+ begin_frame_source_.reset(new ExternalBeginFrameSource(this)); |
std::unique_ptr<cc::DisplayScheduler> scheduler(new cc::DisplayScheduler( |
task_runner, display_output_surface->capabilities().max_frames_pending)); |
@@ -659,7 +734,7 @@ |
HostSharedBitmapManager::current(), |
BrowserGpuMemoryBufferManager::current(), |
host_->GetSettings().renderer_settings, frame_sink_id_, |
- root_window_->GetBeginFrameSource(), std::move(display_output_surface), |
+ begin_frame_source_.get(), std::move(display_output_surface), |
std::move(scheduler), |
base::MakeUnique<cc::TextureMailboxDeleter>(task_runner))); |
@@ -678,6 +753,14 @@ |
host_->SetCompositorFrameSink(std::move(compositor_frame_sink)); |
} |
+void CompositorImpl::AddObserver(VSyncObserver* observer) { |
+ observer_list_.AddObserver(observer); |
+} |
+ |
+void CompositorImpl::RemoveObserver(VSyncObserver* observer) { |
+ observer_list_.RemoveObserver(observer); |
+} |
+ |
cc::UIResourceId CompositorImpl::CreateUIResource( |
cc::UIResourceClient* client) { |
TRACE_EVENT0("compositor", "CompositorImpl::CreateUIResource"); |
@@ -723,6 +806,23 @@ |
root_window_->GetLayer()->RequestCopyOfOutput(std::move(request)); |
} |
+void CompositorImpl::OnVSync(base::TimeTicks frame_time, |
+ base::TimeDelta vsync_period) { |
+ for (auto& observer : observer_list_) |
+ observer.OnVSync(frame_time, vsync_period); |
+ if (needs_begin_frames_) |
+ root_window_->RequestVSyncUpdate(); |
+} |
+ |
+void CompositorImpl::OnNeedsBeginFramesChange(bool needs_begin_frames) { |
+ if (needs_begin_frames_ == needs_begin_frames) |
+ return; |
+ |
+ needs_begin_frames_ = needs_begin_frames; |
+ if (needs_begin_frames_) |
+ root_window_->RequestVSyncUpdate(); |
+} |
+ |
void CompositorImpl::SetNeedsAnimate() { |
needs_animate_ = true; |
if (!host_->IsVisible()) |