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

Unified Diff: content/browser/renderer_host/compositor_impl_android.cc

Issue 1536323003: Revert of android: Remove custom browser compositor scheduling logic (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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 | « content/browser/renderer_host/compositor_impl_android.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 eaf4bcd4e906e0b557b66e319336af226c150aae..b6453a6e887128451f8c9600b08034adfdd2e136 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -69,6 +69,7 @@
namespace {
+const unsigned int kMaxUiSwapBuffers = 1U;
const unsigned int kMaxDisplaySwapBuffers = 1U;
// Used to override capabilities_.adjust_deadline_for_parent to false
@@ -141,7 +142,8 @@
OutputSurface::OnSwapBuffersComplete();
}
- void OnVSync(base::TimeTicks timebase, base::TimeDelta interval) override {
+ void OnUpdateVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) override {
CommitVSyncParameters(timebase, interval);
}
@@ -151,36 +153,6 @@
gfx::SwapResult)>
swap_buffers_completion_callback_;
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() override {
- 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 {
- 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;
@@ -265,11 +237,15 @@
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);
@@ -282,6 +258,111 @@
root_window_->DetachCompositor();
// Clean-up any surface references.
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() {
@@ -344,20 +425,27 @@
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;
- settings.single_thread_proxy_scheduler = true;
+ // TODO(enne): Update this this compositor to use the scheduler.
+ settings.single_thread_proxy_scheduler = false;
settings.use_compositor_animation_timelines = !command_line->HasSwitch(
switches::kDisableAndroidCompositorAnimationTimelines);
@@ -369,7 +457,6 @@
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, &params);
DCHECK(!host_->visible());
host_->SetRootLayer(root_layer_);
@@ -385,16 +472,39 @@
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) {
+ 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();
}
}
@@ -425,7 +535,10 @@
void CompositorImpl::SetNeedsComposite() {
if (!host_->visible())
return;
- host_->SetNeedsAnimate();
+ DCHECK(!needs_composite_ || WillComposite());
+
+ needs_composite_ = true;
+ PostComposite(COMPOSITE_IMMEDIATELY);
}
static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
@@ -459,11 +572,9 @@
}
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() {
@@ -593,15 +704,44 @@
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");
- pending_swapbuffers_++;
+ did_post_swapbuffers_ = true;
}
void CompositorImpl::DidCompleteSwapBuffers() {
TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers");
DCHECK_GT(pending_swapbuffers_, 0U);
- pending_swapbuffers_--;
+ if (pending_swapbuffers_-- == kMaxUiSwapBuffers && needs_composite_)
+ PostComposite(COMPOSITE_IMMEDIATELY);
client_->OnSwapBuffersCompleted(pending_swapbuffers_);
}
@@ -610,8 +750,7 @@
// This really gets called only once from
// SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() when the
// context was lost.
- if (host_->visible())
- host_->SetNeedsCommit();
+ ScheduleComposite();
client_->OnSwapBuffersCompleted(0);
}
@@ -630,19 +769,28 @@
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();
+ }
+
+ 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);
+ }
+
FOR_EACH_OBSERVER(VSyncObserver, observer_list_,
- 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();
+ OnUpdateVSyncParameters(frame_time, vsync_period));
}
void CompositorImpl::SetNeedsAnimate() {
« no previous file with comments | « content/browser/renderer_host/compositor_impl_android.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698