// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/viz/service/surfaces/surface.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>

#include "base/stl_util.h"
#include "base/time/tick_clock.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/surfaces/referenced_surface_tracker.h"
#include "components/viz/service/surfaces/surface_client.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/service/viz_service_export.h"
#include "ui/gfx/presentation_feedback.h"

namespace viz {

Surface::Surface(const SurfaceInfo& surface_info,
                 SurfaceManager* surface_manager,
                 base::WeakPtr<SurfaceClient> surface_client,
                 bool needs_sync_tokens)
    : surface_info_(surface_info),
      surface_manager_(surface_manager),
      surface_client_(std::move(surface_client)),
      needs_sync_tokens_(needs_sync_tokens) {
  TRACE_EVENT_ASYNC_BEGIN1(TRACE_DISABLED_BY_DEFAULT("viz.surface_lifetime"),
                           "Surface", this, "surface_info",
                           surface_info.ToString());
}

Surface::~Surface() {
  ClearCopyRequests();

  if (surface_client_)
    surface_client_->OnSurfaceDiscarded(this);
  surface_manager_->SurfaceDiscarded(this);

  UnrefFrameResourcesAndRunCallbacks(std::move(pending_frame_data_));
  UnrefFrameResourcesAndRunCallbacks(std::move(active_frame_data_));

  if (deadline_)
    deadline_->Cancel();

  TRACE_EVENT_ASYNC_END1(TRACE_DISABLED_BY_DEFAULT("viz.surface_lifetime"),
                         "Surface", this, "surface_info",
                         surface_info_.ToString());
}

void Surface::SetDependencyDeadline(
    std::unique_ptr<SurfaceDependencyDeadline> deadline) {
  deadline_ = std::move(deadline);
}

void Surface::Reset(base::WeakPtr<SurfaceClient> client) {
  seen_first_frame_activation_ = false;
  if (surface_client_.get() == client.get()) {
    UnrefFrameResourcesAndRunCallbacks(std::move(pending_frame_data_));
    UnrefFrameResourcesAndRunCallbacks(std::move(active_frame_data_));
  }
  surface_client_ = client;
  pending_frame_data_.reset();
  active_frame_data_.reset();
}

void Surface::InheritActivationDeadlineFrom(Surface* surface) {
  TRACE_EVENT1("viz", "Surface::InheritActivationDeadlineFrom", "FrameSinkId",
               surface_id().frame_sink_id().ToString());
  if (!deadline_ || !surface->deadline_)
    return;

  deadline_->InheritFrom(*surface->deadline_);
}

void Surface::SetPreviousFrameSurface(Surface* surface) {
  DCHECK(surface && (HasActiveFrame() || HasPendingFrame()));
  previous_frame_surface_id_ = surface->surface_id();
  CompositorFrame& frame = active_frame_data_ ? active_frame_data_->frame
                                              : pending_frame_data_->frame;
  surface->TakeLatencyInfo(&frame.metadata.latency_info);
  surface->TakeLatencyInfoFromPendingFrame(&frame.metadata.latency_info);
}

void Surface::RefResources(const std::vector<TransferableResource>& resources) {
  if (surface_client_)
    surface_client_->RefResources(resources);
}

void Surface::UnrefResources(const std::vector<ReturnedResource>& resources) {
  if (surface_client_)
    surface_client_->UnrefResources(resources);
}

void Surface::UpdateSurfaceReferences() {
  const base::flat_set<SurfaceId>& existing_referenced_surfaces =
      surface_manager_->GetSurfacesReferencedByParent(surface_id());
  base::flat_set<SurfaceId> new_referenced_surfaces(
      active_referenced_surfaces().begin(), active_referenced_surfaces().end(),
      base::KEEP_FIRST_OF_DUPES);

  // Populate list of surface references to add and remove by getting the
  // difference between existing surface references and surface references for
  // latest activated CompositorFrame.
  std::vector<SurfaceReference> references_to_add;
  std::vector<SurfaceReference> references_to_remove;
  GetSurfaceReferenceDifference(surface_id(), existing_referenced_surfaces,
                                new_referenced_surfaces, &references_to_add,
                                &references_to_remove);

  // Modify surface references stored in SurfaceManager.
  if (!references_to_add.empty())
    surface_manager_->AddSurfaceReferences(references_to_add);
  if (!references_to_remove.empty())
    surface_manager_->RemoveSurfaceReferences(references_to_remove);
}

void Surface::RejectCompositorFramesToFallbackSurfaces() {
  const std::vector<SurfaceId>& activation_dependencies =
      GetPendingFrame().metadata.activation_dependencies;

  for (const SurfaceRange& surface_range :
       GetPendingFrame().metadata.referenced_surfaces) {
    if (!surface_range.start())
      continue;
    const SurfaceId& surface_id = *surface_range.start();
    // A surface ID in |referenced_surfaces| that has a corresponding surface
    // ID in |activation_dependencies| with the same frame sink ID is said to
    // be a fallback surface that can be used in place of the primary surface
    // if the deadline passes before the dependency becomes available.
    auto it = std::find_if(
        activation_dependencies.begin(), activation_dependencies.end(),
        [surface_id](const SurfaceId& dependency) {
          return dependency.frame_sink_id() == surface_id.frame_sink_id();
        });
    bool is_fallback_surface = it != activation_dependencies.end();
    if (!is_fallback_surface)
      continue;

    Surface* fallback_surface =
        surface_manager_->GetLatestInFlightSurface(*it, surface_id);

    // A misbehaving client may report a non-existent surface ID as a
    // |referenced_surface|. In that case, |surface| would be nullptr, and
    // there is nothing to do here.
    if (fallback_surface)
      fallback_surface->Close();
  }
}

void Surface::Close() {
  closed_ = true;
}

bool Surface::QueueFrame(
    CompositorFrame frame,
    uint64_t frame_index,
    base::ScopedClosureRunner frame_rejected_callback,
    PresentedCallback presented_callback) {
  late_activation_dependencies_.clear();

  if (frame.size_in_pixels() != surface_info_.size_in_pixels() ||
      frame.device_scale_factor() != surface_info_.device_scale_factor()) {
    TRACE_EVENT_INSTANT0("viz", "Surface invariants violation",
                         TRACE_EVENT_SCOPE_THREAD);
    return false;
  }

  if (closed_)
    return true;

  if (active_frame_data_ || pending_frame_data_)
    previous_frame_surface_id_ = surface_id();

  TakeLatencyInfoFromPendingFrame(&frame.metadata.latency_info);

  base::Optional<FrameData> previous_pending_frame_data =
      std::move(pending_frame_data_);
  pending_frame_data_.reset();

  FrameDeadline deadline = UpdateActivationDependencies(frame);

  // Receive and track the resources referenced from the CompositorFrame
  // regardless of whether it's pending or active.
  surface_client_->ReceiveFromChild(frame.resource_list);

  if (activation_dependencies_.empty() ||
      (deadline_ && !deadline.deadline_in_frames())) {
    // If there are no blockers, then immediately activate the frame.
    ActivateFrame(
        FrameData(std::move(frame), frame_index, std::move(presented_callback)),
        base::nullopt);
  } else {
    pending_frame_data_ =
        FrameData(std::move(frame), frame_index, std::move(presented_callback));
    RejectCompositorFramesToFallbackSurfaces();

    // If the deadline is in the past, then we will activate immediately.
    if (!deadline_ || deadline_->Set(deadline)) {
      // Ask the SurfaceDependencyTracker to inform |this| when its dependencies
      // are resolved.
      surface_manager_->dependency_tracker()->RequestSurfaceResolution(this);
    }
  }

  // Returns resources for the previous pending frame.
  UnrefFrameResourcesAndRunCallbacks(std::move(previous_pending_frame_data));

  // The frame should not fail to display beyond this point. Release the
  // callback so it is not called.
  (void)frame_rejected_callback.Release();

  return true;
}

void Surface::RequestCopyOfOutput(
    std::unique_ptr<CopyOutputRequest> copy_request) {
  if (!active_frame_data_)
    return;  // |copy_request| auto-sends empty result on out-of-scope.

  std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests =
      active_frame_data_->frame.render_pass_list.back()->copy_requests;

  if (copy_request->has_source()) {
    const base::UnguessableToken& source = copy_request->source();
    // Remove existing CopyOutputRequests made on the Surface by the same
    // source.
    base::EraseIf(copy_requests,
                  [&source](const std::unique_ptr<CopyOutputRequest>& x) {
                    return x->has_source() && x->source() == source;
                  });
  }
  copy_requests.push_back(std::move(copy_request));
}

void Surface::NotifySurfaceIdAvailable(const SurfaceId& surface_id) {
  auto it = frame_sink_id_dependencies_.find(surface_id.frame_sink_id());
  if (it == frame_sink_id_dependencies_.end())
    return;

  if (surface_id.local_surface_id().parent_sequence_number() >=
          it->second.parent_sequence_number &&
      surface_id.local_surface_id().child_sequence_number() >=
          it->second.child_sequence_number) {
    frame_sink_id_dependencies_.erase(it);
    surface_manager_->SurfaceDependenciesChanged(this, {},
                                                 {surface_id.frame_sink_id()});
  }

  // LocalSurfaceIds of a given FrameSinkId are monotonically increasing in time
  // so if LocalSurfaceId j arrives then all LocalSurfaceIds i<j will never
  // arrive and so we just drop these invalid activation dependencies here.
  // TODO(fsamuel): This is a linear scan which is probably fine today because
  // a given surface has a small number of dependencies. We might need to
  // revisit this in the future if the number of dependencies grows
  // significantly.
  base::EraseIf(
      activation_dependencies_, [surface_id](const SurfaceId& dependency) {
        return dependency.frame_sink_id() == surface_id.frame_sink_id() &&
               dependency.local_surface_id() <= surface_id.local_surface_id();
      });

  if (!activation_dependencies_.empty())
    return;

  DCHECK(frame_sink_id_dependencies_.empty());

  // All blockers have been cleared. The surface can be activated now.
  ActivatePendingFrame(base::nullopt);
}

void Surface::ActivatePendingFrameForDeadline(
    base::Optional<base::TimeDelta> duration) {
  if (!pending_frame_data_)
    return;

  // If a frame is being activated because of a deadline, then clear its set
  // of blockers.
  late_activation_dependencies_ = std::move(activation_dependencies_);
  activation_dependencies_.clear();
  frame_sink_id_dependencies_.clear();
  ActivatePendingFrame(duration);
}

Surface::FrameData::FrameData(CompositorFrame&& frame,
                              uint64_t frame_index,
                              PresentedCallback presented_callback)
    : frame(std::move(frame)),
      frame_index(frame_index),
      frame_processed(false),
      presented_callback(std::move(presented_callback)) {}

Surface::FrameData::FrameData(FrameData&& other) = default;

Surface::FrameData& Surface::FrameData::operator=(FrameData&& other) = default;

Surface::FrameData::~FrameData() = default;

void Surface::ActivatePendingFrame(base::Optional<base::TimeDelta> duration) {
  DCHECK(pending_frame_data_);
  FrameData frame_data = std::move(*pending_frame_data_);
  pending_frame_data_.reset();

  DCHECK(!duration || !deadline_ || !deadline_->has_deadline());
  if (!duration && deadline_)
    duration = deadline_->Cancel();

  ActivateFrame(std::move(frame_data), duration);
}

// A frame is activated if all its Surface ID dependences are active or a
// deadline has hit and the frame was forcibly activated. |duration| is a
// measure of the time the frame has spent waiting on dependencies to arrive.
// If |duration| is base::nullopt, then that indicates that this frame was not
// blocked on dependencies.
void Surface::ActivateFrame(FrameData frame_data,
                            base::Optional<base::TimeDelta> duration) {
  TRACE_EVENT1("viz", "Surface::ActivateFrame", "FrameSinkId",
               surface_id().frame_sink_id().ToString());

  // Save root pass copy requests.
  std::vector<std::unique_ptr<CopyOutputRequest>> old_copy_requests;
  if (active_frame_data_) {
    std::swap(old_copy_requests,
              active_frame_data_->frame.render_pass_list.back()->copy_requests);
  }

  ClearCopyRequests();

  TakeLatencyInfo(&frame_data.frame.metadata.latency_info);

  base::Optional<FrameData> previous_frame_data = std::move(active_frame_data_);

  active_frame_data_ = std::move(frame_data);

  active_referenced_surfaces_.clear();
  for (SurfaceRange surface_range :
       active_frame_data_->frame.metadata.referenced_surfaces) {
    if (surface_range.start())
      active_referenced_surfaces_.emplace_back(*surface_range.start());
  }

  for (auto& copy_request : old_copy_requests)
    RequestCopyOfOutput(std::move(copy_request));

  UnrefFrameResourcesAndRunCallbacks(std::move(previous_frame_data));

  // This should happen before calling SurfaceManager::FirstSurfaceActivation(),
  // as that notifies observers which may have side effects for
  // |surface_client_|. See https://crbug.com/821855.
  if (surface_client_)
    surface_client_->OnSurfaceActivated(this);

  if (!seen_first_frame_activation_) {
    TRACE_EVENT_WITH_FLOW2(
        TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"),
        "LocalSurfaceId.Submission.Flow",
        TRACE_ID_GLOBAL(
            surface_info_.id().local_surface_id().submission_trace_id()),
        TRACE_EVENT_FLAG_FLOW_IN, "step", "FirstSurfaceActivation",
        "surface_id", surface_info_.id().ToString());

    seen_first_frame_activation_ = true;
    surface_manager_->FirstSurfaceActivation(surface_info_);
  }

  surface_manager_->SurfaceActivated(this, duration);

  // Defer notifying the embedder of an updated token until the frame has been
  // completely processed.
  const auto& metadata = GetActiveFrame().metadata;
  if (surface_client_ && metadata.send_frame_token_to_embedder)
    surface_client_->OnFrameTokenChanged(metadata.frame_token);
}

FrameDeadline Surface::UpdateActivationDependencies(
    const CompositorFrame& current_frame) {
  const base::Optional<uint32_t>& default_deadline =
      surface_manager_->activation_deadline_in_frames();
  FrameDeadline deadline = current_frame.metadata.deadline;

  uint32_t deadline_in_frames = deadline.deadline_in_frames();
  if (default_deadline && deadline.use_default_lower_bound_deadline())
    deadline_in_frames = std::max(deadline_in_frames, *default_deadline);

  deadline = FrameDeadline(deadline.frame_start_time(), deadline_in_frames,
                           deadline.frame_interval(),
                           false /* use_default_lower_bound_deadline */);

  bool track_dependencies = !default_deadline || deadline_in_frames > 0;

  base::flat_map<FrameSinkId, SequenceNumbers> new_frame_sink_id_dependencies;
  base::flat_set<SurfaceId> new_activation_dependencies;

  for (const SurfaceId& surface_id :
       current_frame.metadata.activation_dependencies) {
    Surface* dependency = surface_manager_->GetSurfaceForId(surface_id);
    // If a activation dependency does not have a corresponding active frame in
    // the display compositor, then it blocks this frame.
    if (!dependency || !dependency->HasActiveFrame()) {
      new_activation_dependencies.insert(surface_id);
      if (!track_dependencies)
        continue;

      // Record the latest |parent_sequence_number| this surface is interested
      // in observing for the provided FrameSinkId.
      uint32_t& parent_sequence_number =
          new_frame_sink_id_dependencies[surface_id.frame_sink_id()]
              .parent_sequence_number;
      parent_sequence_number =
          std::max(parent_sequence_number,
                   surface_id.local_surface_id().parent_sequence_number());

      uint32_t& child_sequence_number =
          new_frame_sink_id_dependencies[surface_id.frame_sink_id()]
              .child_sequence_number;
      child_sequence_number =
          std::max(child_sequence_number,
                   surface_id.local_surface_id().child_sequence_number());
    }
  }

  // If this Surface has a previous pending frame, then we must determine the
  // changes in dependencies so that we can update the SurfaceDependencyTracker
  // map.
  ComputeChangeInDependencies(new_frame_sink_id_dependencies);

  if (track_dependencies) {
    activation_dependencies_ = std::move(new_activation_dependencies);
  } else {
    // If the deadline is zero, then all dependencies are late.
    activation_dependencies_.clear();
    late_activation_dependencies_ = std::move(new_activation_dependencies);
  }

  frame_sink_id_dependencies_ = std::move(new_frame_sink_id_dependencies);
  return deadline;
}

void Surface::ComputeChangeInDependencies(
    const base::flat_map<FrameSinkId, SequenceNumbers>& new_dependencies) {
  base::flat_set<FrameSinkId> added_dependencies;
  base::flat_set<FrameSinkId> removed_dependencies;

  for (const auto& kv : frame_sink_id_dependencies_) {
    if (!new_dependencies.count(kv.first))
      removed_dependencies.insert(kv.first);
  }

  for (const auto& kv : new_dependencies) {
    if (!frame_sink_id_dependencies_.count(kv.first))
      added_dependencies.insert(kv.first);
  }

  // If there is a change in the dependency set, then inform SurfaceManager.
  if (!added_dependencies.empty() || !removed_dependencies.empty()) {
    surface_manager_->SurfaceDependenciesChanged(this, added_dependencies,
                                                 removed_dependencies);
  }
}

void Surface::TakeCopyOutputRequests(Surface::CopyRequestsMap* copy_requests) {
  DCHECK(copy_requests->empty());
  if (!active_frame_data_)
    return;

  for (const auto& render_pass : active_frame_data_->frame.render_pass_list) {
    for (auto& request : render_pass->copy_requests) {
      copy_requests->insert(
          std::make_pair(render_pass->id, std::move(request)));
    }
    render_pass->copy_requests.clear();
  }
}

void Surface::TakeCopyOutputRequestsFromClient() {
  if (!surface_client_)
    return;
  for (std::unique_ptr<CopyOutputRequest>& request :
       surface_client_->TakeCopyOutputRequests(
           surface_id().local_surface_id())) {
    RequestCopyOfOutput(std::move(request));
  }
}

bool Surface::HasCopyOutputRequests() {
  if (!active_frame_data_)
    return false;
  for (const auto& render_pass : active_frame_data_->frame.render_pass_list) {
    if (!render_pass->copy_requests.empty())
      return true;
  }
  return false;
}

const CompositorFrame& Surface::GetActiveFrame() const {
  DCHECK(active_frame_data_);
  return active_frame_data_->frame;
}

const CompositorFrame& Surface::GetPendingFrame() {
  DCHECK(pending_frame_data_);
  return pending_frame_data_->frame;
}

void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) {
  if (!active_frame_data_)
    return;
  TakeLatencyInfoFromFrame(&active_frame_data_->frame, latency_info);
}

bool Surface::TakePresentedCallback(PresentedCallback* callback) {
  if (active_frame_data_ && active_frame_data_->presented_callback) {
    *callback = std::move(active_frame_data_->presented_callback);
    return true;
  }
  return false;
}

void Surface::RunDrawCallback() {
  if (!active_frame_data_ || active_frame_data_->frame_processed)
    return;
  active_frame_data_->frame_processed = true;
  if (surface_client_)
    surface_client_->OnSurfaceProcessed(this);
}

void Surface::NotifyAggregatedDamage(const gfx::Rect& damage_rect,
                                     base::TimeTicks expected_display_time) {
  if (!active_frame_data_ || !surface_client_)
    return;
  surface_client_->OnSurfaceAggregatedDamage(
      this, surface_id().local_surface_id(), active_frame_data_->frame,
      damage_rect, expected_display_time);
}

void Surface::OnDeadline(base::TimeDelta duration) {
  TRACE_EVENT1("viz", "Surface::OnDeadline", "FrameSinkId",
               surface_id().frame_sink_id().ToString());
  ActivatePendingFrameForDeadline(duration);
}

void Surface::UnrefFrameResourcesAndRunCallbacks(
    base::Optional<FrameData> frame_data) {
  if (!frame_data || !surface_client_)
    return;

  std::vector<ReturnedResource> resources =
      TransferableResource::ReturnResources(frame_data->frame.resource_list);
  // No point in returning same sync token to sender.
  for (auto& resource : resources)
    resource.sync_token.Clear();
  surface_client_->UnrefResources(resources);

  if (!frame_data->frame_processed)
    surface_client_->OnSurfaceProcessed(this);

  if (frame_data->presented_callback) {
    std::move(frame_data->presented_callback)
        .Run(gfx::PresentationFeedback::Failure());
  }
}

void Surface::ClearCopyRequests() {
  if (active_frame_data_) {
    for (const auto& render_pass : active_frame_data_->frame.render_pass_list) {
      // When the container is cleared, all copy requests within it will
      // auto-send an empty result as they are being destroyed.
      render_pass->copy_requests.clear();
    }
  }
}

void Surface::TakeLatencyInfoFromPendingFrame(
    std::vector<ui::LatencyInfo>* latency_info) {
  if (!pending_frame_data_)
    return;
  TakeLatencyInfoFromFrame(&pending_frame_data_->frame, latency_info);
}

// static
void Surface::TakeLatencyInfoFromFrame(
    CompositorFrame* frame,
    std::vector<ui::LatencyInfo>* latency_info) {
  if (latency_info->empty()) {
    frame->metadata.latency_info.swap(*latency_info);
    return;
  }
  std::copy(frame->metadata.latency_info.begin(),
            frame->metadata.latency_info.end(),
            std::back_inserter(*latency_info));
  frame->metadata.latency_info.clear();
  if (!ui::LatencyInfo::Verify(*latency_info,
                               "Surface::TakeLatencyInfoFromFrame")) {
    latency_info->clear();
  }
}

void Surface::OnWillBeDrawn() {
  if (!seen_first_surface_embedding_) {
    seen_first_surface_embedding_ = true;

    TRACE_EVENT_WITH_FLOW2(
        TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"),
        "LocalSurfaceId.Embed.Flow",
        TRACE_ID_GLOBAL(surface_info_.id().local_surface_id().embed_trace_id()),
        TRACE_EVENT_FLAG_FLOW_IN, "step", "FirstSurfaceEmbedding", "surface_id",
        surface_info_.id().ToString());
  }
  surface_manager_->SurfaceWillBeDrawn(this);
}

}  // namespace viz
