cc: Use FrameMetrics in LTHI.

Tracks throughput, latency, and smoothness of the
compositor thread.

Will output a trace that includes a summary of the
stats every time a frame is displayed.

Bug: 790759
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I85c68bf28e6ce72be8c0b84eca25b839d2126198
Reviewed-on: https://chromium-review.googlesource.com/1074192
Commit-Queue: Brian Anderson <brianderson@chromium.org>
Reviewed-by: Timothy Dresser <tdresser@chromium.org>
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566141}
diff --git a/cc/DEPS b/cc/DEPS
index cd44e0c..7b0e07a0 100644
--- a/cc/DEPS
+++ b/cc/DEPS
@@ -29,7 +29,7 @@
   "+third_party/libyuv",
   "+third_party/skia/include",
   "+third_party/skia/src/core/SkRemoteGlyphCache.h",
-  "+ui/latency/latency_info.h",
+  "+ui/latency",
   "+ui/gfx",
   "+ui/gl",
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 228a230d..97135f3 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -229,6 +229,25 @@
   }
 }
 
+ui::FrameMetricsSettings LTHI_FrameMetricsSettings(
+    const LayerTreeSettings& settings) {
+  ui::FrameMetricsSource source =
+      settings.commit_to_active_tree
+          ? ui::FrameMetricsSource::UiCompositor
+          : ui::FrameMetricsSource::RendererCompositor;
+  ui::FrameMetricsSourceThread source_thread =
+      settings.commit_to_active_tree
+          ? ui::FrameMetricsSourceThread::UiCompositor
+          : ui::FrameMetricsSourceThread::RendererCompositor;
+  ui::FrameMetricsCompileTarget compile_target =
+      settings.using_synchronous_renderer_compositor
+          ? ui::FrameMetricsCompileTarget::SynchronousCompositor
+          : settings.wait_for_all_pipeline_stages_before_draw
+                ? ui::FrameMetricsCompileTarget::Headless
+                : ui::FrameMetricsCompileTarget::Chromium;
+  return ui::FrameMetricsSettings(source, source_thread, compile_target);
+}
+
 }  // namespace
 
 DEFINE_SCOPED_UMA_HISTOGRAM_TIMER(PendingTreeDurationHistogramTimer,
@@ -304,7 +323,9 @@
           base::BindRepeating(
               &LayerTreeHostImpl::RequestInvalidationForAnimatedImages,
               base::Unretained(this)),
-          settings_.enable_image_animation_resync) {
+          settings_.enable_image_animation_resync),
+      frame_metrics_(LTHI_FrameMetricsSettings(settings_)),
+      skipped_frame_tracker_(&frame_metrics_) {
   DCHECK(mutator_host_);
   mutator_host_->SetMutatorHostClient(this);
 
@@ -1236,6 +1257,8 @@
 void LayerTreeHostImpl::InvalidateLayerTreeFrameSink() {
   DCHECK(layer_tree_frame_sink());
   layer_tree_frame_sink()->Invalidate();
+
+  skipped_frame_tracker_.DidProduceFrame();
 }
 
 DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
@@ -1714,27 +1737,46 @@
   client_->DidReceiveCompositorFrameAckOnImplThread();
 }
 
+LayerTreeHostImpl::FrameTokenInfo::FrameTokenInfo(
+    uint32_t token,
+    base::TimeTicks cc_frame_time,
+    std::vector<LayerTreeHost::PresentationTimeCallback> callbacks)
+    : token(token),
+      cc_frame_time(cc_frame_time),
+      callbacks(std::move(callbacks)) {}
+
+LayerTreeHostImpl::FrameTokenInfo::FrameTokenInfo(FrameTokenInfo&&) = default;
+LayerTreeHostImpl::FrameTokenInfo::~FrameTokenInfo() = default;
+
 void LayerTreeHostImpl::DidPresentCompositorFrame(
     uint32_t frame_token,
     const gfx::PresentationFeedback& feedback) {
   TRACE_EVENT_MARK_WITH_TIMESTAMP0("cc,benchmark", "FramePresented",
                                    feedback.timestamp);
   std::vector<LayerTreeHost::PresentationTimeCallback> all_callbacks;
-  while (!presentation_callbacks_.empty()) {
-    auto iter = presentation_callbacks_.begin();
-    if (PresentationTokenGT(iter->first, frame_token))
+  while (!frame_token_infos_.empty()) {
+    auto info = frame_token_infos_.begin();
+    if (PresentationTokenGT(info->token, frame_token))
       break;
-    auto& callbacks = iter->second;
-    std::copy(std::make_move_iterator(callbacks.begin()),
-              std::make_move_iterator(callbacks.end()),
+
+    // Update compositor frame latency and smoothness stats only for frames
+    // that caused on-screen damage.
+    if (info->token == frame_token)
+      frame_metrics_.AddFrameDisplayed(info->cc_frame_time, feedback.timestamp);
+
+    std::copy(std::make_move_iterator(info->callbacks.begin()),
+              std::make_move_iterator(info->callbacks.end()),
               std::back_inserter(all_callbacks));
-    presentation_callbacks_.erase(iter);
+    frame_token_infos_.erase(info);
   }
   client_->DidPresentCompositorFrameOnImplThread(
       frame_token, std::move(all_callbacks), feedback);
 }
 
-void LayerTreeHostImpl::DidDiscardCompositorFrame(uint32_t frame_token) {}
+void LayerTreeHostImpl::DidDiscardCompositorFrame(uint32_t frame_token) {
+  TRACE_EVENT_INSTANT0("cc,benchmark", "FrameDiscarded",
+                       TRACE_EVENT_SCOPE_THREAD);
+}
 
 void LayerTreeHostImpl::ReclaimResources(
     const std::vector<viz::ReturnedResource>& resources) {
@@ -1815,8 +1857,6 @@
   metadata.frame_token = next_frame_token_++;
   if (!next_frame_token_)
     next_frame_token_ = 1u;
-  if (active_tree_->has_presentation_callbacks())
-    metadata.request_presentation_feedback = true;
 
   metadata.device_scale_factor = active_tree_->painted_device_scale_factor() *
                                  active_tree_->device_scale_factor();
@@ -1838,10 +1878,15 @@
   metadata.content_source_id = active_tree_->content_source_id();
 
   active_tree_->GetViewportSelection(&metadata.selection);
-  if (active_tree_->has_presentation_callbacks()) {
-    presentation_callbacks_.push_back(
-        {metadata.frame_token, active_tree_->TakePresentationCallbacks()});
-    DCHECK_LE(presentation_callbacks_.size(), 25u);
+
+  if (active_tree_->has_presentation_callbacks() ||
+      settings_.always_request_presentation_time) {
+    metadata.request_presentation_feedback = true;
+    frame_token_infos_.emplace_back(metadata.frame_token,
+                                    CurrentBeginFrameArgs().frame_time,
+                                    active_tree_->TakePresentationCallbacks());
+
+    DCHECK_LE(frame_token_infos_.size(), 25u);
   }
 
   if (const auto* outer_viewport_scroll_node = OuterViewportScrollNode()) {
@@ -1924,6 +1969,7 @@
   TRACE_EVENT0("cc,benchmark", "LayerTreeHostImpl::DrawLayers");
 
   ResetRequiresHighResToDraw();
+  skipped_frame_tracker_.DidProduceFrame();
 
   if (frame->has_no_damage) {
     DCHECK(!resourceless_software_draw_);
@@ -2271,6 +2317,7 @@
 }
 
 bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
+  impl_thread_phase_ = ImplThreadPhase::INSIDE_IMPL_FRAME;
   current_begin_frame_tracker_.Start(args);
 
   if (is_likely_to_require_a_draw_) {
@@ -2288,7 +2335,7 @@
   for (auto* it : video_frame_controllers_)
     it->OnBeginFrame(args);
 
-  impl_thread_phase_ = ImplThreadPhase::INSIDE_IMPL_FRAME;
+  skipped_frame_tracker_.BeginFrame(args.frame_time, args.interval);
 
   bool recent_frame_had_no_damage =
       consecutive_frame_with_damage_count_ < settings_.damaged_frame_limit;
@@ -2313,6 +2360,7 @@
 }
 
 void LayerTreeHostImpl::DidFinishImplFrame() {
+  skipped_frame_tracker_.FinishFrame();
   impl_thread_phase_ = ImplThreadPhase::IDLE;
   current_begin_frame_tracker_.Finish();
   tile_manager_.decoded_image_tracker().NotifyFrameFinished();
@@ -2747,6 +2795,7 @@
 void LayerTreeHostImpl::SetNeedsRedraw() {
   NotifySwapPromiseMonitorsOfSetNeedsRedraw();
   client_->SetNeedsRedrawOnImplThread();
+  skipped_frame_tracker_.WillProduceFrame();
 }
 
 ManagedMemoryPolicy LayerTreeHostImpl::ActualManagedMemoryPolicy() const {
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 20f6818..015bd1d9 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -53,6 +53,7 @@
 #include "components/viz/common/surfaces/local_surface_id.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/latency/frame_metrics.h"
 
 namespace gfx {
 class ScrollOffset;
@@ -1076,9 +1077,30 @@
 
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
-  base::circular_deque<
-      std::pair<uint32_t, std::vector<LayerTreeHost::PresentationTimeCallback>>>
-      presentation_callbacks_;
+  // Stores information needed once we get a response for a particular
+  // presentation token.
+  struct FrameTokenInfo {
+    FrameTokenInfo(
+        uint32_t token,
+        base::TimeTicks cc_frame_time,
+        std::vector<LayerTreeHost::PresentationTimeCallback> callbacks);
+    FrameTokenInfo(FrameTokenInfo&&);
+    ~FrameTokenInfo();
+
+    uint32_t token;
+
+    // The compositor frame time used to produce the frame.
+    base::TimeTicks cc_frame_time;
+
+    // The callbacks to send back to the main thread.
+    std::vector<LayerTreeHost::PresentationTimeCallback> callbacks;
+
+    DISALLOW_COPY_AND_ASSIGN(FrameTokenInfo);
+  };
+
+  base::circular_deque<FrameTokenInfo> frame_token_infos_;
+  ui::FrameMetrics frame_metrics_;
+  ui::SkippedFrameTracker skipped_frame_tracker_;
 
   DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
 };
diff --git a/ui/latency/frame_metrics.cc b/ui/latency/frame_metrics.cc
index 6bf4afa..7a1c5ed 100644
--- a/ui/latency/frame_metrics.cc
+++ b/ui/latency/frame_metrics.cc
@@ -121,8 +121,10 @@
   switch (source) {
     case FrameMetricsSource::UnitTest:
       return "UnitTest";
-    case FrameMetricsSource::Thread:
-      return "Thread";
+    case FrameMetricsSource::RendererCompositor:
+      return "RendererCompositor";
+    case FrameMetricsSource::UiCompositor:
+      return "UiCompositor";
     case FrameMetricsSource::Unknown:
       break;
   };
diff --git a/ui/latency/frame_metrics.h b/ui/latency/frame_metrics.h
index d9dbaf0..d680541 100644
--- a/ui/latency/frame_metrics.h
+++ b/ui/latency/frame_metrics.h
@@ -39,7 +39,8 @@
 enum class FrameMetricsSource {
   Unknown = 0,
   UnitTest = 1,
-  Thread = 2,
+  RendererCompositor = 2,
+  UiCompositor = 3,
 };
 
 enum class FrameMetricsSourceThread {