| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "android_webview/browser/gfx/display_scheduler_webview.h" |
| |
| #include "android_webview/browser/gfx/root_frame_sink.h" |
| #include "android_webview/browser/gfx/viz_compositor_thread_runner_webview.h" |
| #include "base/trace_event/trace_event.h" |
| #include "components/viz/common/features.h" |
| #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" |
| |
| namespace android_webview { |
| DisplaySchedulerWebView::DisplaySchedulerWebView( |
| RootFrameSink* root_frame_sink, |
| OverlaysInfoProvider* overlays_info_provider) |
| : root_frame_sink_(root_frame_sink), |
| overlays_info_provider_(overlays_info_provider), |
| use_new_invalidate_heuristic_(base::FeatureList::IsEnabled( |
| features::kWebViewNewInvalidateHeuristic)) { |
| auto* frame_sink_manager = |
| VizCompositorThreadRunnerWebView::GetInstance()->GetFrameSinkManager(); |
| |
| surface_manager_observation_.Observe(frame_sink_manager->surface_manager()); |
| frame_sink_manager_observation_.Observe(frame_sink_manager); |
| } |
| |
| DisplaySchedulerWebView::~DisplaySchedulerWebView() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| } |
| |
| void DisplaySchedulerWebView::ForceImmediateSwapIfPossible() { |
| // We can't swap immediately |
| NOTREACHED(); |
| } |
| void DisplaySchedulerWebView::SetNeedsOneBeginFrame(bool needs_draw) { |
| NOTREACHED(); |
| } |
| void DisplaySchedulerWebView::DidSwapBuffers() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| // Code below is part of old invalidation heuristic. |
| if (use_new_invalidate_heuristic_) |
| return; |
| |
| bool needs_draw = false; |
| for (auto it = damaged_frames_.begin(); it != damaged_frames_.end();) { |
| DCHECK_GT(it->second, 0); |
| if (!--it->second) { |
| it = damaged_frames_.erase(it); |
| } else { |
| if (!needs_draw) { |
| TRACE_EVENT_INSTANT2( |
| "android_webview", |
| "DisplaySchedulerWebView::DidSwapBuffers first needs_draw", |
| TRACE_EVENT_SCOPE_THREAD, "frame_sink_id", it->first.ToString(), |
| "damage_count", it->second); |
| } |
| needs_draw = true; |
| ++it; |
| } |
| } |
| |
| root_frame_sink_->SetNeedsDraw(needs_draw); |
| } |
| void DisplaySchedulerWebView::OutputSurfaceLost() { |
| } |
| |
| bool DisplaySchedulerWebView::IsFrameSinkOverlayed( |
| viz::FrameSinkId frame_sink_id) { |
| return overlays_info_provider_ && |
| overlays_info_provider_->IsFrameSinkOverlayed(frame_sink_id); |
| } |
| |
| void DisplaySchedulerWebView::OnDisplayDamaged(viz::SurfaceId surface_id) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| // Code below is part of old invalidation heuristic. |
| if (use_new_invalidate_heuristic_) |
| return; |
| |
| // We don't need to track damage of root frame sink as we submit frame to it |
| // at DrawAndSwap and Root Renderer sink because Android View.Invalidation is |
| // handled by SynchronousCompositorHost. |
| |
| if (surface_id.frame_sink_id() != root_frame_sink_->root_frame_sink_id() && |
| !root_frame_sink_->IsChildSurface(surface_id.frame_sink_id()) && |
| !IsFrameSinkOverlayed(surface_id.frame_sink_id())) { |
| int count = damaged_frames_[surface_id.frame_sink_id()] + 1; |
| |
| TRACE_EVENT_INSTANT2( |
| "android_webview", "DisplaySchedulerWebView::OnDisplayDamaged", |
| TRACE_EVENT_SCOPE_THREAD, "frame_sink_id", |
| surface_id.frame_sink_id().ToString(), "damage_count", count); |
| |
| // Clamp value to max two frames. Two is enough to keep invalidation |
| // working, but will prevent number going too high in case if kModeDraw |
| // doesn't happen for some time. |
| damaged_frames_[surface_id.frame_sink_id()] = std::min(2, count); |
| |
| root_frame_sink_->SetNeedsDraw(true); |
| } |
| } |
| |
| void DisplaySchedulerWebView::OnSurfaceHasNewUncommittedFrame( |
| const viz::SurfaceId& surface_id) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| // We don't need to track damage of root frame sink as we submit frame to it |
| // at DrawAndSwap and Root Renderer sink because Android View.Invalidation is |
| // handled by SynchronousCompositorHost. |
| if (surface_id.frame_sink_id() != root_frame_sink_->root_frame_sink_id() && |
| !root_frame_sink_->IsChildSurface(surface_id.frame_sink_id()) && |
| !IsFrameSinkOverlayed(surface_id.frame_sink_id())) { |
| root_frame_sink_->OnNewUncommittedFrame(surface_id); |
| } |
| } |
| |
| void DisplaySchedulerWebView::OnCaptureStarted( |
| const viz::FrameSinkId& frame_sink_id) { |
| root_frame_sink_->OnCaptureStarted(frame_sink_id); |
| } |
| |
| } // namespace android_webview |