| 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..eaf4bcd4e906e0b557b66e319336af226c150aae 100644
|
| --- a/content/browser/renderer_host/compositor_impl_android.cc
|
| +++ b/content/browser/renderer_host/compositor_impl_android.cc
|
| @@ -69,7 +69,6 @@ namespace content {
|
|
|
| namespace {
|
|
|
| -const unsigned int kMaxUiSwapBuffers = 1U;
|
| const unsigned int kMaxDisplaySwapBuffers = 1U;
|
|
|
| // Used to override capabilities_.adjust_deadline_for_parent to false
|
| @@ -142,8 +141,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 +153,36 @@ 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() 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;
|
|
|
| bool g_use_surface_manager = false;
|
| @@ -237,15 +265,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 +284,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 +344,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 +369,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 +385,16 @@ 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) {
|
| - 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();
|
| }
|
| }
|
|
|
| @@ -535,10 +425,7 @@ void CompositorImpl::SetHasTransparentBackground(bool flag) {
|
| void CompositorImpl::SetNeedsComposite() {
|
| if (!host_->visible())
|
| return;
|
| - DCHECK(!needs_composite_ || WillComposite());
|
| -
|
| - needs_composite_ = true;
|
| - PostComposite(COMPOSITE_IMMEDIATELY);
|
| + host_->SetNeedsAnimate();
|
| }
|
|
|
| static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
|
| @@ -572,9 +459,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 +593,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_);
|
| }
|
|
|
| @@ -750,7 +610,8 @@ void CompositorImpl::DidAbortSwapBuffers() {
|
| // This really gets called only once from
|
| // SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() when the
|
| // context was lost.
|
| - ScheduleComposite();
|
| + if (host_->visible())
|
| + host_->SetNeedsCommit();
|
| client_->OnSwapBuffersCompleted(0);
|
| }
|
|
|
| @@ -769,28 +630,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() {
|
|
|