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 b6453a6e887128451f8c9600b08034adfdd2e136..d6f47c0acfab16824597f569a6e8eaa58e0b2998 100644 |
--- a/content/browser/renderer_host/compositor_impl_android.cc |
+++ b/content/browser/renderer_host/compositor_impl_android.cc |
@@ -142,8 +142,7 @@ class OutputSurfaceWithoutParent : public cc::OutputSurface, |
OutputSurface::OnSwapBuffersComplete(); |
} |
- void OnUpdateVSyncParameters(base::TimeTicks timebase, |
- base::TimeDelta interval) override { |
+ void OnVSync(base::TimeTicks timebase, base::TimeDelta interval) override { |
CommitVSyncParameters(timebase, interval); |
} |
@@ -155,6 +154,38 @@ class OutputSurfaceWithoutParent : public cc::OutputSurface, |
scoped_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator_; |
}; |
+class ExternalBeginFrameSource : public cc::BeginFrameSourceBase, |
+ public CompositorImpl::VSyncObserver { |
+ public: |
+ ExternalBeginFrameSource(CompositorImpl* compositor) |
+ : compositor_(compositor) { |
+ compositor_->AddObserver(this); |
+ } |
+ |
+ ~ExternalBeginFrameSource() { |
+ compositor_->RemoveObserver(this); |
+ } |
+ |
+ // cc::BeginFrameSourceBase implementation: |
+ void OnNeedsBeginFramesChange( |
+ bool needs_begin_frames) override { |
+ compositor_->OnNeedsBeginFramesChange(needs_begin_frames); |
+ } |
+ |
+ // CompositorImpl::VSyncObserver implementation: |
+ void OnVSync(base::TimeTicks frame_time, |
+ base::TimeDelta vsync_period) override { |
+ if (NeedsBeginFrames()) { |
brianderson
2015/12/12 01:41:46
This check shouldn't be needed. The scheduler shou
no sievers
2015/12/17 00:52:32
Done.
|
+ CallOnBeginFrame(cc::BeginFrameArgs::Create( |
+ BEGINFRAME_FROM_HERE, frame_time, base::TimeTicks::Now(), |
+ vsync_period, cc::BeginFrameArgs::NORMAL)); |
+ } |
+ } |
+ |
+ private: |
+ CompositorImpl* compositor_; |
+}; |
+ |
static bool g_initialized = false; |
bool g_use_surface_manager = false; |
@@ -237,15 +268,11 @@ CompositorImpl::CompositorImpl(CompositorClient* client, |
surface_id_(0), |
client_(client), |
root_window_(root_window), |
- did_post_swapbuffers_(false), |
- ignore_schedule_composite_(false), |
- needs_composite_(false), |
needs_animate_(false), |
- will_composite_immediately_(false), |
- composite_on_vsync_trigger_(DO_NOT_COMPOSITE), |
pending_swapbuffers_(0U), |
num_successive_context_creation_failures_(0), |
output_surface_request_pending_(false), |
+ needs_begin_frames_(false), |
weak_factory_(this) { |
DCHECK(client); |
DCHECK(root_window); |
@@ -260,111 +287,6 @@ CompositorImpl::~CompositorImpl() { |
SetSurface(NULL); |
} |
-void CompositorImpl::PostComposite(CompositingTrigger trigger) { |
- DCHECK(host_->visible()); |
- DCHECK(needs_composite_); |
- DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY); |
- |
- if (will_composite_immediately_ || |
- (trigger == COMPOSITE_EVENTUALLY && WillComposite())) { |
- // We will already composite soon enough. |
- DCHECK(WillComposite()); |
- return; |
- } |
- |
- if (DidCompositeThisFrame()) { |
- DCHECK(!WillCompositeThisFrame()); |
- if (composite_on_vsync_trigger_ != COMPOSITE_IMMEDIATELY) { |
- composite_on_vsync_trigger_ = trigger; |
- root_window_->RequestVSyncUpdate(); |
- } |
- DCHECK(WillComposite()); |
- return; |
- } |
- |
- base::TimeDelta delay; |
- if (trigger == COMPOSITE_IMMEDIATELY) { |
- will_composite_immediately_ = true; |
- composite_on_vsync_trigger_ = DO_NOT_COMPOSITE; |
- } else { |
- DCHECK(!WillComposite()); |
- const base::TimeDelta estimated_composite_time = vsync_period_ / 4; |
- const base::TimeTicks now = base::TimeTicks::Now(); |
- |
- if (!last_vsync_.is_null() && (now - last_vsync_) < vsync_period_) { |
- base::TimeTicks next_composite = |
- last_vsync_ + vsync_period_ - estimated_composite_time; |
- if (next_composite < now) { |
- // It's too late, we will reschedule composite as needed on the next |
- // vsync. |
- composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY; |
- root_window_->RequestVSyncUpdate(); |
- DCHECK(WillComposite()); |
- return; |
- } |
- |
- delay = next_composite - now; |
- } |
- } |
- TRACE_EVENT2("cc,benchmark", "CompositorImpl::PostComposite", |
- "trigger", trigger, |
- "delay", delay.InMillisecondsF()); |
- |
- DCHECK(composite_on_vsync_trigger_ == DO_NOT_COMPOSITE); |
- if (current_composite_task_) |
- current_composite_task_->Cancel(); |
- |
- // Unretained because we cancel the task on shutdown. |
- current_composite_task_.reset(new base::CancelableClosure( |
- base::Bind(&CompositorImpl::Composite, base::Unretained(this), trigger))); |
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
- FROM_HERE, current_composite_task_->callback(), delay); |
-} |
- |
-void CompositorImpl::Composite(CompositingTrigger trigger) { |
- if (trigger == COMPOSITE_IMMEDIATELY) |
- will_composite_immediately_ = false; |
- |
- DCHECK(host_->visible()); |
- DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY); |
- DCHECK(needs_composite_); |
- DCHECK(!DidCompositeThisFrame()); |
- |
- DCHECK_LE(pending_swapbuffers_, kMaxUiSwapBuffers); |
- // Swap Ack accounting is unreliable if the OutputSurface was lost. |
- // In that case still attempt to composite, which will cause creation of a |
- // new OutputSurface and reset pending_swapbuffers_. |
- if (pending_swapbuffers_ == kMaxUiSwapBuffers && |
- !host_->output_surface_lost()) { |
- TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit"); |
- return; |
- } |
- |
- // Reset state before Layout+Composite since that might create more |
- // requests to Composite that we need to respect. |
- needs_composite_ = false; |
- |
- // Only allow compositing once per vsync. |
- current_composite_task_->Cancel(); |
- DCHECK(DidCompositeThisFrame() && !WillComposite()); |
- |
- const base::TimeTicks frame_time = base::TimeTicks::Now(); |
- if (needs_animate_) { |
- base::AutoReset<bool> auto_reset_ignore_schedule( |
- &ignore_schedule_composite_, true); |
- needs_animate_ = false; |
- root_window_->Animate(frame_time); |
- } |
- |
- did_post_swapbuffers_ = false; |
- host_->Composite(frame_time); |
- if (did_post_swapbuffers_) |
- pending_swapbuffers_++; |
- |
- // Need to track vsync to avoid compositing more than once per frame. |
- root_window_->RequestVSyncUpdate(); |
-} |
- |
ui::UIResourceProvider& CompositorImpl::GetUIResourceProvider() { |
return *this; |
} |
@@ -425,27 +347,20 @@ void CompositorImpl::SetSurface(jobject surface) { |
void CompositorImpl::CreateLayerTreeHost() { |
DCHECK(!host_); |
- DCHECK(!WillCompositeThisFrame()); |
- |
- // Just in case, since we immediately hide the LTH in this function, |
- // and we do not want to end up with a pending Composite task when the |
- // host is hidden. |
- base::AutoReset<bool> auto_reset_ignore_schedule(&ignore_schedule_composite_, |
- true); |
cc::LayerTreeSettings settings; |
settings.renderer_settings.refresh_rate = 60.0; |
settings.renderer_settings.allow_antialiasing = false; |
settings.renderer_settings.highp_threshold_min = 2048; |
settings.use_zero_copy = true; |
+ settings.use_external_begin_frame_source = true; |
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
settings.initial_debug_state.SetRecordRenderingStats( |
command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); |
if (command_line->HasSwitch(cc::switches::kDisableCompositorPropertyTrees)) |
settings.use_property_trees = false; |
- // TODO(enne): Update this this compositor to use the scheduler. |
- settings.single_thread_proxy_scheduler = false; |
+ settings.single_thread_proxy_scheduler = true; |
settings.use_compositor_animation_timelines = !command_line->HasSwitch( |
switches::kDisableAndroidCompositorAnimationTimelines); |
@@ -457,6 +372,7 @@ void CompositorImpl::CreateLayerTreeHost() { |
params.task_graph_runner = g_task_graph_runner.Pointer(); |
params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); |
params.settings = &settings; |
+ params.external_begin_frame_source.reset(new ExternalBeginFrameSource(this)); |
host_ = cc::LayerTreeHost::CreateSingleThreaded(this, ¶ms); |
DCHECK(!host_->visible()); |
host_->SetRootLayer(root_layer_); |
@@ -472,39 +388,17 @@ void CompositorImpl::SetVisible(bool visible) { |
TRACE_EVENT1("cc", "CompositorImpl::SetVisible", "visible", visible); |
if (!visible) { |
DCHECK(host_->visible()); |
- // Look for any layers that were attached to the root for readback |
- // and are waiting for Composite() to happen. |
- bool readback_pending = false; |
- for (size_t i = 0; i < root_layer_->children().size(); ++i) { |
- if (root_layer_->children()[i]->HasCopyRequest()) { |
- readback_pending = true; |
- break; |
- } |
- } |
- if (readback_pending) { |
brianderson
2015/12/12 01:41:46
Does this break readbacks at all?
no sievers
2015/12/17 00:52:32
The pending requests will still signal completion
|
- base::AutoReset<bool> auto_reset_ignore_schedule( |
- &ignore_schedule_composite_, true); |
- host_->Composite(base::TimeTicks::Now()); |
- } |
- if (WillComposite()) |
- CancelComposite(); |
host_->SetVisible(false); |
if (!host_->output_surface_lost()) |
host_->ReleaseOutputSurface(); |
pending_swapbuffers_ = 0; |
- needs_composite_ = false; |
- composite_on_vsync_trigger_ = DO_NOT_COMPOSITE; |
establish_gpu_channel_timeout_.Stop(); |
display_client_.reset(); |
- if (current_composite_task_) { |
- current_composite_task_->Cancel(); |
- current_composite_task_.reset(); |
- } |
} else { |
host_->SetVisible(true); |
if (output_surface_request_pending_) |
RequestNewOutputSurface(); |
- SetNeedsComposite(); |
+ host_->SetNeedsCommit(); |
brianderson
2015/12/12 01:41:46
Is this needed? I think the impl side requests it
no sievers
2015/12/17 00:52:32
You're right, not needed. Removed.
|
} |
} |
@@ -535,10 +429,7 @@ void CompositorImpl::SetHasTransparentBackground(bool flag) { |
void CompositorImpl::SetNeedsComposite() { |
if (!host_->visible()) |
return; |
- DCHECK(!needs_composite_ || WillComposite()); |
- |
- needs_composite_ = true; |
- PostComposite(COMPOSITE_IMMEDIATELY); |
+ host_->SetNeedsCommit(); |
brianderson
2015/12/12 01:41:46
Was this why the SetNeedsCommit was needed above?
no sievers
2015/12/17 00:52:32
This is actually what the browser will call if it
|
} |
static scoped_ptr<WebGraphicsContext3DCommandBufferImpl> |
@@ -572,9 +463,11 @@ CreateGpuProcessViewContext( |
} |
void CompositorImpl::UpdateLayerTreeHost() { |
- base::AutoReset<bool> auto_reset_ignore_schedule(&ignore_schedule_composite_, |
- true); |
client_->UpdateLayerTreeHost(); |
+ if (needs_animate_) { |
+ needs_animate_ = false; |
+ root_window_->Animate(base::TimeTicks::Now()); |
+ } |
} |
void CompositorImpl::OnGpuChannelEstablished() { |
@@ -704,44 +597,15 @@ bool CompositorImpl::SupportsETC1NonPowerOfTwo() const { |
return gpu_capabilities_.texture_format_etc1_npot; |
} |
-void CompositorImpl::ScheduleComposite() { |
- if (ignore_schedule_composite_ || !host_->visible()) |
- return; |
- |
- DCHECK(!needs_composite_ || WillComposite()); |
- needs_composite_ = true; |
- // We currently expect layer tree invalidations at most once per frame |
- // during normal operation and therefore try to composite immediately |
- // to minimize latency. |
- PostComposite(COMPOSITE_IMMEDIATELY); |
-} |
- |
-void CompositorImpl::ScheduleAnimation() { |
- needs_animate_ = true; |
- |
- if (!host_->visible()) |
- return; |
- |
- if (needs_composite_) { |
- DCHECK(WillComposite()); |
- return; |
- } |
- |
- TRACE_EVENT0("cc", "CompositorImpl::ScheduleAnimation"); |
- needs_composite_ = true; |
- PostComposite(COMPOSITE_EVENTUALLY); |
-} |
- |
void CompositorImpl::DidPostSwapBuffers() { |
TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers"); |
- did_post_swapbuffers_ = true; |
+ pending_swapbuffers_++; |
} |
void CompositorImpl::DidCompleteSwapBuffers() { |
TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers"); |
DCHECK_GT(pending_swapbuffers_, 0U); |
- if (pending_swapbuffers_-- == kMaxUiSwapBuffers && needs_composite_) |
- PostComposite(COMPOSITE_IMMEDIATELY); |
+ pending_swapbuffers_--; |
client_->OnSwapBuffersCompleted(pending_swapbuffers_); |
brianderson
2015/12/12 01:41:46
It doesn't look like any implementers look at pend
no sievers
2015/12/17 00:52:32
Unfortunately this is used in CompositorViewHolder
brianderson
2015/12/17 06:14:53
Ok. I see where it's used now and am okay keeping
|
} |
@@ -769,28 +633,19 @@ void CompositorImpl::RequestCopyOfOutputOnRootLayer( |
void CompositorImpl::OnVSync(base::TimeTicks frame_time, |
base::TimeDelta vsync_period) { |
- vsync_period_ = vsync_period; |
- last_vsync_ = frame_time; |
- |
- if (WillCompositeThisFrame()) { |
- // We somehow missed the last vsync interval, so reschedule for deadline. |
- // We cannot schedule immediately, or will get us out-of-phase with new |
- // renderer frames. |
- CancelComposite(); |
- composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY; |
- } else { |
- current_composite_task_.reset(); |
- } |
+ FOR_EACH_OBSERVER(VSyncObserver, observer_list_, |
+ OnVSync(frame_time, vsync_period)); |
+ if (needs_begin_frames_) |
+ root_window_->RequestVSyncUpdate(); |
+} |
- DCHECK(!DidCompositeThisFrame() && !WillCompositeThisFrame()); |
- if (composite_on_vsync_trigger_ != DO_NOT_COMPOSITE) { |
- CompositingTrigger trigger = composite_on_vsync_trigger_; |
- composite_on_vsync_trigger_ = DO_NOT_COMPOSITE; |
- PostComposite(trigger); |
- } |
+void CompositorImpl::OnNeedsBeginFramesChange(bool needs_begin_frames) { |
+ if (needs_begin_frames_ == needs_begin_frames) |
+ return; |
- FOR_EACH_OBSERVER(VSyncObserver, observer_list_, |
- OnUpdateVSyncParameters(frame_time, vsync_period)); |
+ needs_begin_frames_ = needs_begin_frames; |
+ if (needs_begin_frames_) |
+ root_window_->RequestVSyncUpdate(); |
} |
void CompositorImpl::SetNeedsAnimate() { |