// Copyright 2014 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/hardware_renderer.h"

#include <algorithm>
#include <iterator>
#include <memory>
#include <utility>
#include <variant>

#include "android_webview/browser/gfx/aw_gl_surface.h"
#include "android_webview/browser/gfx/display_scheduler_webview.h"
#include "android_webview/browser/gfx/display_webview.h"
#include "android_webview/browser/gfx/gpu_service_webview.h"
#include "android_webview/browser/gfx/overlay_processor_webview.h"
#include "android_webview/browser/gfx/parent_compositor_draw_constraints.h"
#include "android_webview/browser/gfx/render_thread_manager.h"
#include "android_webview/browser/gfx/root_frame_sink.h"
#include "android_webview/browser/gfx/skia_output_surface_dependency_webview.h"
#include "android_webview/browser/gfx/task_queue_webview.h"
#include "android_webview/browser/gfx/viz_compositor_thread_runner_webview.h"
#include "android_webview/common/aw_features.h"
#include "android_webview/common/aw_switches.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/system/sys_info.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_timing_details_map.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/display/display_client.h"
#include "components/viz/service/display/display_scheduler.h"
#include "components/viz/service/display/frame_interval_decider.h"
#include "components/viz/service/display/overlay_processor_stub.h"
#include "components/viz/service/display_embedder/skia_output_surface_dependency.h"
#include "components/viz/service/display_embedder/skia_output_surface_impl.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "gpu/config/gpu_finch_features.h"
#include "third_party/abseil-cpp/absl/functional/overload.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/init/gl_factory.h"

namespace android_webview {
namespace {

BASE_FEATURE(DrawAndSwapInjectLatency, base::FEATURE_DISABLED_BY_DEFAULT);

class ScopedAcquireExternalContext {
 public:
  ScopedAcquireExternalContext(gpu::SharedContextState* state,
                               gl::GLSurface* surface,
                               bool is_angle)
      : state_(state), surface_(surface), is_angle_(is_angle) {
    if (is_angle_) {
      // When using ANGLE, need to make sure ANGLE's internals are in sync
      // with the external context.

      // If the context has changed, make sure it gets current now.
      if (!state_->context()->IsCurrent(surface_)) {
        state_->MakeCurrent(surface_);
      }

      eglAcquireExternalContextANGLE(state_->display()->GetDisplay(),
                                     surface_->GetHandle());
    } else {
      // When not using ANGLE, fake context and surface are used, so the
      // MakeCurrent calls are cheap.
      state_->MakeCurrent(surface_);
    }
  }
  ~ScopedAcquireExternalContext() {
    if (is_angle_) {
      eglReleaseExternalContextANGLE(state_->display()->GetDisplay());
    } else {
      state_->ReleaseCurrent(surface_);
    }
  }

 private:
  const raw_ptr<gpu::SharedContextState> state_;
  raw_ptr<gl::GLSurface> surface_;
  const bool is_angle_;
};

void MoveCopyRequests(CopyOutputRequestQueue* from,
                      CopyOutputRequestQueue* to) {
  std::move(from->begin(), from->end(), std::back_inserter(*to));
  from->clear();
}

viz::BeginFrameArgs NewerBeginFrameArgs(const viz::BeginFrameArgs& args1,
                                        const viz::BeginFrameArgs& args2) {
  return args1.frame_id.IsNextInSequenceTo(args2.frame_id) ? args1 : args2;
}

enum WebViewDrawAndSubmissionType : uint8_t {
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  kNoInvalidateNoSubmissionSameParams = 0,
  kNoInvalidateNoSubmissionDifferentParams = 1,
  kNoInvalidateSubmittedFrameSameParams = 2,
  kNoInvalidateSubmittedFrameDifferentParams = 3,
  kInvalidateNoSubmissionSameParams = 4,
  kInvalidateNoSubmissionDifferentParams = 5,
  kInvalidateSubmittedFrameSameParams = 6,
  kInvalidateSubmittedFrameDifferentParams = 7,
  kMaxValue = kInvalidateSubmittedFrameDifferentParams
};

WebViewDrawAndSubmissionType GetDrawAndSubmissionType(bool invalidated,
                                                      bool submitted_frame,
                                                      bool params_changed) {
  if (invalidated) {
    if (submitted_frame) {
      return params_changed ? kInvalidateSubmittedFrameDifferentParams
                            : kInvalidateSubmittedFrameSameParams;
    } else {
      return params_changed ? kInvalidateNoSubmissionDifferentParams
                            : kInvalidateNoSubmissionSameParams;
    }
  } else {
    if (submitted_frame) {
      return params_changed ? kNoInvalidateSubmittedFrameDifferentParams
                            : kNoInvalidateSubmittedFrameSameParams;
    } else {
      return params_changed ? kNoInvalidateNoSubmissionDifferentParams
                            : kNoInvalidateNoSubmissionSameParams;
    }
  }
}

}  // namespace

class HardwareRenderer::OnViz : public viz::DisplayClient {
 public:
  OnViz(OutputSurfaceProviderWebView* output_surface_provider,
        const scoped_refptr<RootFrameSink>& root_frame_sink);

  OnViz(const OnViz&) = delete;
  OnViz& operator=(const OnViz&) = delete;

  ~OnViz() override;

  void DrawAndSwapOnViz(const gfx::Size& viewport,
                        const gfx::Rect& clip,
                        const gfx::Transform& transform,
                        const viz::SurfaceId& child_id,
                        float device_scale_factor,
                        const gfx::ColorSpace& color_space,
                        bool overlays_enabled_by_hwui,
                        ChildFrame* child_frame);
  void PostDrawOnViz(viz::FrameTimingDetailsMap* timing_details,
                     std::vector<pid_t>* rendering_thread_ids,
                     base::TimeDelta* preferred_frame_interval);
  void RemoveOverlaysOnViz();
  void MarkAllowContextLossOnViz();

  OverlayProcessorWebView* overlay_processor() {
    return overlay_processor_webview_;
  }

  // viz::DisplayClient overrides.
  void DisplayOutputSurfaceLost() override;
  void DisplayWillDrawAndSwap(
      bool will_draw_and_swap,
      viz::AggregatedRenderPassList* render_passes) override;
  void DisplayDidDrawAndSwap() override {}
  void DisplayDidReceiveCALayerParams(
      const gfx::CALayerParams& ca_layer_params) override {}
  void DisplayDidCompleteSwapWithSize(const gfx::Size& pixel_size) override {}
  void DisplayAddChildWindowToBrowser(
      gpu::SurfaceHandle child_window) override {}
  void SetWideColorEnabled(bool enabled) override {}

 private:
  viz::FrameSinkManagerImpl* GetFrameSinkManager();

  scoped_refptr<RootFrameSink> without_gpu_;

  const viz::FrameSinkId frame_sink_id_;
  viz::LocalSurfaceId root_local_surface_id_;
  std::unique_ptr<viz::BeginFrameSource> stub_begin_frame_source_;
  std::unique_ptr<DisplayWebView> display_;

  std::unique_ptr<viz::HitTestAggregator> hit_test_aggregator_;
  viz::SurfaceId child_surface_id_;
  const bool viz_frame_submission_;
  const bool use_new_invalidate_heuristic_;
  bool expect_context_loss_ = false;

  // Initialized in ctor and never changes, so it's safe to access from both
  // threads. Can be null, if overlays are disabled.
  raw_ptr<OverlayProcessorWebView> overlay_processor_webview_ = nullptr;

  base::PlatformThreadId browser_io_thread_id_ = base::kInvalidThreadId;

  base::TimeDelta preferred_frame_interval_;

  THREAD_CHECKER(viz_thread_checker_);
};

HardwareRenderer::OnViz::OnViz(
    OutputSurfaceProviderWebView* output_surface_provider,
    const scoped_refptr<RootFrameSink>& root_frame_sink)
    : without_gpu_(root_frame_sink),
      frame_sink_id_(without_gpu_->root_frame_sink_id()),
      viz_frame_submission_(::features::IsUsingVizFrameSubmissionForWebView()),
      use_new_invalidate_heuristic_(
          ::features::UseWebViewNewInvalidateHeuristic()) {
  DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);

  std::unique_ptr<viz::DisplayCompositorMemoryAndTaskController>
      display_controller = output_surface_provider->CreateDisplayController();
  std::unique_ptr<viz::OutputSurface> output_surface =
      output_surface_provider->CreateOutputSurface(display_controller.get());

  stub_begin_frame_source_ = std::make_unique<viz::StubBeginFrameSource>();

  display_ = DisplayWebView::Create(
      output_surface_provider->renderer_settings(),
      output_surface_provider->debug_settings(), frame_sink_id_,
      std::move(display_controller), std::move(output_surface),
      GetFrameSinkManager(), without_gpu_.get());
  display_->Initialize(this, GetFrameSinkManager()->surface_manager());
  overlay_processor_webview_ = display_->overlay_processor();

  display_->SetVisible(true);
  display_->DisableGPUAccessByDefault();

  if (viz::FrameIntervalDecider* decider = display_->frame_interval_decider()) {
    viz::FrameIntervalDecider::Settings settings;
    std::vector<std::unique_ptr<viz::FrameIntervalMatcher>> matchers;
    matchers.push_back(std::make_unique<viz::InputBoostMatcher>());
    matchers.push_back(std::make_unique<viz::OnlyVideoMatcher>());
    matchers.push_back(std::make_unique<viz::OnlyAnimatingImageMatcher>());

    // Raw `self` pointer is safe because this owns viz::Display which owns
    // viz::FrameIntervalDecider. So this pointer is guaranteed to be valid for
    // the lifetime of viz::FrameIntervalDecider.
    settings.result_callback = base::BindRepeating(
        [](HardwareRenderer::OnViz* self,
           viz::FrameIntervalDecider::Result result,
           viz::FrameIntervalMatcherType matcher_type) {
          self->preferred_frame_interval_ = std::visit(
              absl::Overload(
                  [](viz::FrameIntervalDecider::FrameIntervalClass
                         frame_interval_class) {
                    // Zero currently is interpreted by WebView as no
                    // opinion, which allows system to use its
                    // default heuristics.
                    return base::Milliseconds(0);
                  },
                  [](viz::FrameIntervalDecider::ResultInterval interval) {
                    return interval.interval;
                  }),
              result);
        },
        this);
    decider->UpdateSettings(std::move(settings), std::move(matchers));
  }
}

HardwareRenderer::OnViz::~OnViz() {
  DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
  if (child_surface_id_.is_valid()) {
    without_gpu_->EvictChildSurface(child_surface_id_);
  }

  if (root_local_surface_id_.is_valid()) {
    without_gpu_->EvictRootSurface(root_local_surface_id_);
  }

  GetFrameSinkManager()->surface_manager()->GarbageCollectSurfaces();
}

void HardwareRenderer::OnViz::DrawAndSwapOnViz(
    const gfx::Size& viewport,
    const gfx::Rect& clip,
    const gfx::Transform& transform,
    const viz::SurfaceId& child_id,
    float device_scale_factor,
    const gfx::ColorSpace& color_space,
    bool overlays_enabled_by_hwui,
    ChildFrame* child_frame) {
  TRACE_EVENT1("android_webview", "HardwareRenderer::DrawAndSwap", "child_id",
               child_id.ToString());
  DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
  DCHECK(child_id.is_valid());
  DCHECK(child_frame);

  if (child_frame->frame) {
    DCHECK(!viz_frame_submission_);
    DCHECK(!child_frame->rendered);
    // Browser thread is trusted, and can be saved straight away.
    // Renderer threads are not trusted, and need to go through verification
    // in SubmitChildCompositorFrame before being reported to the ADPF session.
    browser_io_thread_id_ = child_frame->browser_io_thread_id;
    without_gpu_->SubmitChildCompositorFrame(child_frame);
  }

  gfx::Size frame_size = without_gpu_->GetChildFrameSize();

  if (!child_frame->copy_requests.empty()) {
    viz::FrameSinkManagerImpl* manager = GetFrameSinkManager();
    CopyOutputRequestQueue requests;
    requests.swap(child_frame->copy_requests);
    for (auto& copy_request : requests) {
      manager->RequestCopyOfOutput(child_id, std::move(copy_request),
                                   /*capture_exact_surface_id=*/false);
    }
  }

  if (overlay_processor_webview_) {
    overlay_processor_webview_->SetOverlaysEnabledByHWUI(
        overlays_enabled_by_hwui);
  }

  gfx::DisplayColorSpaces display_color_spaces(
      color_space.IsValid() ? color_space : gfx::ColorSpace::CreateSRGB());
  display_->SetDisplayColorSpaces(display_color_spaces);

  // Create a frame with a single SurfaceDrawQuad referencing the child
  // Surface and transformed using the given transform.
  auto render_pass = viz::CompositorRenderPass::Create();
  render_pass->SetNew(viz::CompositorRenderPassId{1}, gfx::Rect(viewport), clip,
                      gfx::Transform());
  render_pass->has_transparent_background = false;

  viz::SharedQuadState* quad_state =
      render_pass->CreateAndAppendSharedQuadState();
  quad_state->quad_to_target_transform = transform;
  quad_state->quad_layer_rect = gfx::Rect(frame_size);
  quad_state->visible_quad_layer_rect = gfx::Rect(frame_size);
  quad_state->opacity = 1.f;

  viz::SurfaceDrawQuad* surface_quad =
      render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
  surface_quad->SetNew(quad_state, gfx::Rect(quad_state->quad_layer_rect),
                       gfx::Rect(quad_state->quad_layer_rect),
                       viz::SurfaceRange(std::nullopt, child_id),
                       SkColors::kWhite,
                       /*stretch_content_to_fill_bounds=*/false);

  viz::CompositorFrame frame;
  // We draw synchronously, so acknowledge a manual BeginFrame.
  frame.metadata.begin_frame_ack =
      viz::BeginFrameAck::CreateManualAckWithDamage();
  frame.render_pass_list.push_back(std::move(render_pass));
  frame.metadata.device_scale_factor = device_scale_factor;

  if (child_surface_id_ != child_id) {
    if (child_surface_id_.frame_sink_id() != child_id.frame_sink_id()) {
      hit_test_aggregator_ = std::make_unique<viz::HitTestAggregator>(
          GetFrameSinkManager()->hit_test_manager(), GetFrameSinkManager(),
          display_.get(), child_id.frame_sink_id());
    }
    child_surface_id_ = child_id;
    GetFrameSinkManager()->surface_manager()->GarbageCollectSurfaces();
  }

  {
    std::vector<viz::SurfaceRange> child_ranges;
    child_ranges.emplace_back(child_surface_id_);
    frame.metadata.referenced_surfaces = std::move(child_ranges);
  }

  const auto& local_surface_id =
      without_gpu_->SubmitRootCompositorFrame(std::move(frame));

  if (use_new_invalidate_heuristic_) {
    auto root_surface_id =
        viz::SurfaceId(without_gpu_->root_frame_sink_id(), local_surface_id);

    const auto& current_frame_id = child_frame->begin_frame_args.frame_id;
    const auto& root_frame_sink_id = root_surface_id.frame_sink_id();
    const auto& child_frame_sink_id = child_surface_id_.frame_sink_id();

    // Each OnDraw on UI we get new ChildFrame. Without OnDraw we can't modify
    // contents of the webview or it will break HWUI damage tracking, so only
    // commit if the frame is new.
    const bool commit_child_frames = !child_frame->rendered;

    base::flat_set<viz::SurfaceId> manual_surfaces;
    auto commit_predicate = [&](const viz::SurfaceId& surface_id,
                                const viz::BeginFrameId& frame_id) {
      const bool is_root_surface =
          surface_id.frame_sink_id() == root_frame_sink_id;
      const bool is_main_renderer_surface =
          surface_id.frame_sink_id() == child_frame_sink_id;

      // If we have uncommitted main renderer frame, `commit_child_frames`
      // must be true.
      CHECK(!is_main_renderer_surface || commit_child_frames);

      if (!commit_child_frames) {
        // Commit only root frame, all child surfaces can be committed only
        // if we did have Draw on UI thread.
        return is_root_surface;
      }

      // Always commit frame from different begin frame sources, because we
      // can't order with them.
      if (frame_id.source_id != current_frame_id.source_id) {
        // We always should have single source_id except for the manual
        // acks.
        DCHECK_EQ(frame_id.source_id, viz::BeginFrameArgs::kManualSourceId);

        // For manual acks commit only one frame at time to avoid excessive
        // frame drops.
        auto [_, inserted] = manual_surfaces.insert(surface_id);
        return inserted;
      }

      // Commit all frames that are older than current one.
      if (frame_id.sequence_number < current_frame_id.sequence_number) {
        return true;
      }

      // All clients except main renderer and root surface are frame behind.
      const bool is_frame_behind =
          !is_main_renderer_surface && !is_root_surface;

      // If this surface is not frame behind, commit it for current frame
      // too.
      if (!is_frame_behind &&
          frame_id.sequence_number == current_frame_id.sequence_number) {
        return true;
      }

      return false;
    };

    GetFrameSinkManager()->surface_manager()->CommitFramesInRangeRecursively(
        viz::SurfaceRange(root_surface_id), commit_predicate);
  }

  if (root_local_surface_id_ != local_surface_id) {
    root_local_surface_id_ = local_surface_id;
    display_->SetLocalSurfaceId(local_surface_id, device_scale_factor);
  }

  display_->Resize(viewport);
  display_->SetOutputSurfaceClipRect(clip);

  auto now = base::TimeTicks::Now();
  display_->DrawAndSwap({now, now});

  child_frame->rendered = true;
  without_gpu_->SetContainedSurfaces(display_->GetContainedSurfaceIds());
}

void HardwareRenderer::OnViz::PostDrawOnViz(
    viz::FrameTimingDetailsMap* timing_details,
    std::vector<pid_t>* rendering_thread_ids,
    base::TimeDelta* preferred_frame_interval) {
  *timing_details = without_gpu_->TakeChildFrameTimingDetailsMap();

  auto renderer_thread_ids = without_gpu_->GetChildFrameRendererThreadIds();
  *rendering_thread_ids = std::vector<pid_t>();
  rendering_thread_ids->reserve(renderer_thread_ids.size());
  std::transform(renderer_thread_ids.begin(), renderer_thread_ids.end(),
                 std::back_inserter(*rendering_thread_ids),
                 [](const base::PlatformThreadId& tid) { return tid.raw(); });

  auto gpu_thread_ids =
      VizCompositorThreadRunnerWebView::GetInstance()->GetThreadIds();
  std::transform(gpu_thread_ids.begin(), gpu_thread_ids.end(),
                 std::back_inserter(*rendering_thread_ids),
                 [](const base::PlatformThreadId& tid) { return tid.raw(); });

  if (browser_io_thread_id_ != base::kInvalidThreadId) {
    rendering_thread_ids->push_back(browser_io_thread_id_.raw());
  }

  *preferred_frame_interval = preferred_frame_interval_;
}

void HardwareRenderer::OnViz::RemoveOverlaysOnViz() {
  if (overlay_processor_webview_) {
    overlay_processor_webview_->RemoveOverlays();
  }
}

void HardwareRenderer::OnViz::MarkAllowContextLossOnViz() {
  DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
  expect_context_loss_ = true;
}

viz::FrameSinkManagerImpl* HardwareRenderer::OnViz::GetFrameSinkManager() {
  DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
  return VizCompositorThreadRunnerWebView::GetInstance()->GetFrameSinkManager();
}

void HardwareRenderer::OnViz::DisplayOutputSurfaceLost() {
  DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
  if (!expect_context_loss_) {
    // Android WebView does not handle real context loss.
    LOG(FATAL) << "Render thread context loss";
  }
}

void HardwareRenderer::OnViz::DisplayWillDrawAndSwap(
    bool will_draw_and_swap,
    viz::AggregatedRenderPassList* render_passes) {
  DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
  hit_test_aggregator_->Aggregate(child_surface_id_);
}

// static
ChildFrameQueue HardwareRenderer::WaitAndPruneFrameQueue(
    ChildFrameQueue* child_frames_ptr) {
  ChildFrameQueue& child_frames = *child_frames_ptr;
  ChildFrameQueue pruned_frames;
  if (child_frames.empty()) {
    return pruned_frames;
  }

  // First find the last non-empty frame.
  int remaining_frame_index = -1;
  for (size_t i = 0; i < child_frames.size(); ++i) {
    auto& child_frame = *child_frames[i];
    child_frame.WaitOnFutureIfNeeded();
    if (child_frame.frame) {
      remaining_frame_index = i;
    }
  }
  // If all empty, keep the last one.
  if (remaining_frame_index < 0) {
    remaining_frame_index = child_frames.size() - 1;
  }

  // Prune end.
  while (child_frames.size() > static_cast<size_t>(remaining_frame_index + 1)) {
    std::unique_ptr<ChildFrame> frame = std::move(child_frames.back());
    child_frames.pop_back();
    MoveCopyRequests(&frame->copy_requests,
                     &child_frames[remaining_frame_index]->copy_requests);

    // If we're dropping frames at the end, we need update begin frame args.
    child_frames[remaining_frame_index]->begin_frame_args = NewerBeginFrameArgs(
        child_frames[remaining_frame_index]->begin_frame_args,
        frame->begin_frame_args);
    // We shouldn't get rendered frames here.
    DCHECK(!frame->frame);
    DCHECK(!frame->rendered);
  }
  DCHECK_EQ(static_cast<size_t>(remaining_frame_index),
            child_frames.size() - 1);

  // Prune front.
  while (child_frames.size() > 1) {
    std::unique_ptr<ChildFrame> frame = std::move(child_frames.front());
    child_frames.pop_front();
    MoveCopyRequests(&frame->copy_requests,
                     &child_frames.back()->copy_requests);
    // We shouldn't drop newer frames.
    DCHECK(!frame->begin_frame_args.frame_id.IsNextInSequenceTo(
        child_frames.back()->begin_frame_args.frame_id));
    // We shouldn't get rendered frames here.
    DCHECK(!frame->rendered);
    if (frame->frame) {
      pruned_frames.emplace_back(std::move(frame));
    }
  }
  return pruned_frames;
}

bool HardwareRendererDrawParams::operator==(
    const HardwareRendererDrawParams& other) const {
  return clip_left == other.clip_left && clip_top == other.clip_top &&
         clip_right == other.clip_right && clip_bottom == other.clip_bottom &&
         width == other.width && height == other.height &&
         color_space == other.color_space &&
         UNSAFE_TODO(!memcmp(transform, other.transform, sizeof(transform)));
}

bool HardwareRendererDrawParams::operator!=(
    const HardwareRendererDrawParams& other) const {
  return !(*this == other);
}

HardwareRenderer::HardwareRenderer(RenderThreadManager* state,
                                   RootFrameSinkGetter root_frame_sink_getter,
                                   AwVulkanContextProvider* context_provider)
    : render_thread_manager_(state),
      last_egl_context_(eglGetCurrentContext()),
      output_surface_provider_(context_provider) {
  DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);

  if (base::FeatureList::IsEnabled(::features::kWebViewEnableADPF)) {
    std::string soc_allowlist =
        ::features::kWebViewADPFSocManufacturerAllowlist.Get();
    std::string soc_blocklist =
        ::features::kWebViewADPFSocManufacturerBlocklist.Get();
    std::string soc = base::SysInfo::SocManufacturer();
    report_rendering_threads_ =
        ::features::ShouldUseAdpfForSoc(soc_allowlist, soc_blocklist, soc);
  }

  VizCompositorThreadRunnerWebView::GetInstance()->ScheduleOnVizAndBlock(
      base::BindOnce(&HardwareRenderer::InitializeOnViz, base::Unretained(this),
                     std::move(root_frame_sink_getter)));
}

void HardwareRenderer::InitializeOnViz(
    RootFrameSinkGetter root_frame_sink_getter) {
  scoped_refptr<RootFrameSink> root_frame_sink =
      std::move(root_frame_sink_getter).Run();
  if (root_frame_sink) {
    on_viz_ = std::make_unique<OnViz>(&output_surface_provider_,
                                      std::move(root_frame_sink));
  }
}

HardwareRenderer::~HardwareRenderer() {
  DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  // Do not crash for context loss during destruction. It's possible functor is
  // being destroyed due to an already-detected lost context.
  MarkAllowContextLoss();
  output_surface_provider_.shared_context_state()->MakeCurrent(nullptr);
  VizCompositorThreadRunnerWebView::GetInstance()->ScheduleOnVizAndBlock(
      base::DoNothingWithBoundArgs(std::move(on_viz_)));

  // Reset draw constraints.
  if (child_frame_) {
    render_thread_manager_->PostParentDrawDataToChildCompositorOnRT(
        ParentCompositorDrawConstraints(), child_frame_->frame_sink_id,
        viz::FrameTimingDetailsMap(), 0u, preferred_frame_interval_);
  }
  for (auto& child_frame : child_frame_queue_) {
    child_frame->WaitOnFutureIfNeeded();
    ReturnChildFrame(std::move(child_frame));
  }
}

bool HardwareRenderer::IsUsingVulkan() const {
  DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
  DCHECK(output_surface_provider_.shared_context_state());
  return output_surface_provider_.shared_context_state()->GrContextIsVulkan();
}

bool HardwareRenderer::IsUsingANGLEOverGL() const {
  return !IsUsingVulkan() && gl::GLSurfaceEGL::GetGLDisplayEGL()
                                 ->IsANGLEExternalContextAndSurfaceSupported();
}

void HardwareRenderer::DrawAndSwap(
    const HardwareRendererDrawParams& params,
    const OverlaysParams& overlays_params,
    ReportRenderingThreadsCallback report_rendering_threads_callback) {
  TRACE_EVENT1("android_webview", "HardwareRenderer::Draw", "vulkan",
               IsUsingVulkan());

  DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);

  if (base::FeatureList::IsEnabled(kDrawAndSwapInjectLatency)) {
    usleep(1000);
  }

  // Ensure that the context is synced from external and synced back before
  // returning. This is only necessary when using ANGLE to keep its internals
  // synced with the external context
  ScopedAcquireExternalContext scoped_acquire(
      output_surface_provider_.shared_context_state().get(),
      output_surface_provider_.gl_surface().get(), IsUsingANGLEOverGL());

  viz::FrameTimingDetailsMap timing_details;

  gfx::Transform transform = gfx::Transform::ColMajorF(params.transform);
  transform.Translate(scroll_offset_.x(), scroll_offset_.y());

  gfx::Size viewport(params.width, params.height);
  // Need to post the new transform matrix back to child compositor
  // because there is no onDraw during a Render Thread animation, and child
  // compositor might not have the tiles rasterized as the animation goes on.
  ParentCompositorDrawConstraints draw_constraints =
      ParentCompositorDrawConstraints(viewport, transform);
  bool need_to_update_draw_constraints =
      !child_frame_.get() || draw_constraints.NeedUpdate(*child_frame_);

  if (child_frame_) {
    viz::SurfaceId child_surface_id = child_frame_->GetSurfaceId();
    if (child_surface_id.is_valid() && child_surface_id != surface_id_) {
      surface_id_ = child_surface_id;
      device_scale_factor_ = child_frame_->device_scale_factor;
    }
  }

  if (!surface_id_.is_valid()) {
    if (need_to_update_draw_constraints) {
      // FrameSinkId is used only for FrameTimingDetails and we want to update
      // only draw constraints here.
      // TODO(vasilyt): Move frame timing details delivery over to
      // RootFrameSink.
      render_thread_manager_->PostParentDrawDataToChildCompositorOnRT(
          draw_constraints, viz::FrameSinkId(), viz::FrameTimingDetailsMap(), 0,
          preferred_frame_interval_);
    }
    return;
  }

  gfx::Rect clip(params.clip_left, params.clip_top,
                 params.clip_right - params.clip_left,
                 params.clip_bottom - params.clip_top);

  output_surface_provider_.gl_surface()->RecalculateClipAndTransform(
      &viewport, &clip, &transform);

  // Reset Skia's state if not using ANGLE. For ANGLE, it is in general not
  // necessary as ANGLE will restore GL context state for us as long as Chrome
  // hasn't mucked with it outside ANGLE's knowledge. There is only one case
  // where Chrome does so: the complex clip case. That case is rare and
  // we can't know a priori whether we are going to hit it for this frame.
  // Hence, rather than resetting Skia state on every frame for ANGLE, we
  // instead detect whether this frame has hit the complex clip case at the end
  // of this function and reset the GR context as needed for ANGLE there.
  if (!gl::GLSurfaceEGL::GetGLDisplayEGL()
           ->IsANGLEExternalContextAndSurfaceSupported()) {
    DCHECK(output_surface_provider_.shared_context_state());
    output_surface_provider_.shared_context_state()
        ->PessimisticallyResetGrContext();
  }

  std::optional<OverlayProcessorWebView::ScopedSurfaceControlAvailable>
      allow_surface_control;

  auto* overlay_processor = on_viz_->overlay_processor();
  const bool can_use_overlays =
      overlays_params.overlays_mode == OverlaysParams::Mode::Enabled &&
      !output_surface_provider_.gl_surface()->IsDrawingToFBO();
  if (can_use_overlays && overlay_processor) {
    DCHECK(overlays_params.get_surface_control);
    allow_surface_control.emplace(overlay_processor,
                                  overlays_params.get_surface_control);
  }

  VizCompositorThreadRunnerWebView::GetInstance()->ScheduleOnVizAndBlock(
      base::BindOnce(&HardwareRenderer::OnViz::DrawAndSwapOnViz,
                     base::Unretained(on_viz_.get()), viewport, clip, transform,
                     surface_id_, device_scale_factor_, params.color_space,
                     can_use_overlays, child_frame_.get()));

  MergeTransactionIfNeeded(overlays_params.merge_transaction);

  output_surface_provider_.gl_surface()->MaybeDidPresent(
      gfx::PresentationFeedback(base::TimeTicks::Now(), base::TimeDelta(),
                                0 /* flags */));

  // Implement proper damage tracking, then deliver FrameTimingDetails
  // through the common begin frame path.
  std::vector<pid_t> rendering_thread_ids;
  base::TimeDelta preferred_frame_interval;
  VizCompositorThreadRunnerWebView::GetInstance()->ScheduleOnVizAndBlock(
      base::BindOnce(&HardwareRenderer::OnViz::PostDrawOnViz,
                     base::Unretained(on_viz_.get()), &timing_details,
                     &rendering_thread_ids, &preferred_frame_interval));
  if (report_rendering_threads_ && report_rendering_threads_callback) {
    std::move(report_rendering_threads_callback)
        .Run(rendering_thread_ids.data(), rendering_thread_ids.size());
  }

  bool frame_interval_changed =
      preferred_frame_interval_ != preferred_frame_interval;
  preferred_frame_interval_ = preferred_frame_interval;

  if (need_to_update_draw_constraints || !timing_details.empty() ||
      frame_interval_changed) {
    // |frame_token| will be reported through the FrameSinkManager so we pass 0
    // here.
    render_thread_manager_->PostParentDrawDataToChildCompositorOnRT(
        draw_constraints, child_frame_->frame_sink_id,
        std::move(timing_details), 0, preferred_frame_interval_);
  }

  // If using ANGLE we have not reset Skia's state at the beginning of the draw,
  // as in general ANGLE will take care of saving/restoring GL state. However,
  // it is necessary to reset Skia's state in the complex clip case, as Chrome
  // mucks with GL state outside of ANGLE's knowledge in handling this case. We
  // need to do this check at the end of the frame as it is only at this point
  // that we know whether this frame hit the complex clip case. (For non-ANGLE
  // we need to reset Skia's state at the beginning of each draw in any case, so
  // doing it here would be redundant).
  if (gl::GLSurfaceEGL::GetGLDisplayEGL()
          ->IsANGLEExternalContextAndSurfaceSupported() &&
      output_surface_provider_.gl_surface()->IsDrawingToFBO()) {
    DCHECK(output_surface_provider_.shared_context_state());
    output_surface_provider_.shared_context_state()
        ->PessimisticallyResetGrContext();
  }
}

void HardwareRenderer::RemoveOverlays(
    OverlaysParams::MergeTransactionFn merge_transaction) {
  VizCompositorThreadRunnerWebView::GetInstance()->ScheduleOnVizAndBlock(
      base::BindOnce(&HardwareRenderer::OnViz::RemoveOverlaysOnViz,
                     base::Unretained(on_viz_.get())));

  MergeTransactionIfNeeded(merge_transaction);
}

void HardwareRenderer::MergeTransactionIfNeeded(
    OverlaysParams::MergeTransactionFn merge_transaction) {
  auto* overlay_processor = on_viz_->overlay_processor();
  if (overlay_processor) {
    auto transaction = overlay_processor->TakeSurfaceTransactionOnRT();
    if (transaction) {
      DCHECK(merge_transaction);
      merge_transaction(transaction->GetTransaction());
    }
  }
}

void HardwareRenderer::AbandonContext() {
  MarkAllowContextLoss();
  output_surface_provider_.shared_context_state()->MarkContextLost(
      gpu::error::ContextLostReason::kUnknown);
}

void HardwareRenderer::MarkAllowContextLoss() {
  if (on_viz_) {
    VizCompositorThreadRunnerWebView::GetInstance()->task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&HardwareRenderer::OnViz::MarkAllowContextLossOnViz,
                       base::Unretained(on_viz_.get())));
  }
  output_surface_provider_.MarkAllowContextLoss();
}

void HardwareRenderer::CommitFrame() {
  TRACE_EVENT0("android_webview", "CommitFrame");
  scroll_offset_ = render_thread_manager_->GetScrollOffsetOnRT();
  ChildFrameQueue child_frames = render_thread_manager_->PassFramesOnRT();
  // |child_frames| should have at most one non-empty frame, and one current
  // and unwaited frame, in that order.
  DCHECK_LE(child_frames.size(), 2u);
  if (child_frames.empty()) {
    return;
  }
  // Insert all except last, ie current frame.
  while (child_frames.size() > 1u) {
    child_frame_queue_.emplace_back(std::move(child_frames.front()));
    child_frames.pop_front();
  }
  for (auto& pruned_frame : WaitAndPruneFrameQueue(&child_frame_queue_)) {
    ReturnChildFrame(std::move(pruned_frame));
  }
  DCHECK_LE(child_frame_queue_.size(), 1u);
  child_frame_queue_.emplace_back(std::move(child_frames.front()));
}

void HardwareRenderer::ReportDrawMetric(
    const HardwareRendererDrawParams& params) {
  const bool params_changed = last_draw_params_ == params;

  auto type = GetDrawAndSubmissionType(
      did_invalidate_, did_submit_compositor_frame_, params_changed);
  UMA_HISTOGRAM_ENUMERATION("Android.WebView.Gfx.HardwareDrawType", type);

  last_draw_params_ = params;
  did_invalidate_ = false;
  did_submit_compositor_frame_ = false;
}

void HardwareRenderer::Draw(
    const HardwareRendererDrawParams& params,
    const OverlaysParams& overlays_params,
    ReportRenderingThreadsCallback report_rendering_threads_callback) {
  TRACE_EVENT0("android_webview", "HardwareRenderer::Draw");

  for (auto& pruned_frame : WaitAndPruneFrameQueue(&child_frame_queue_)) {
    ReturnChildFrame(std::move(pruned_frame));
  }
  DCHECK_LE(child_frame_queue_.size(), 1u);
  if (!child_frame_queue_.empty()) {
    child_frame_ = std::move(child_frame_queue_.front());
    child_frame_queue_.clear();

    did_invalidate_ = child_frame_->did_invalidate;
    did_submit_compositor_frame_ = !!child_frame_->frame;
  }
  // 0u is not a valid frame_sink_id, but can happen when renderer did not
  // produce a frame. Keep the existing id in that case.
  if (child_frame_ && child_frame_->layer_tree_frame_sink_id > 0u) {
    last_committed_layer_tree_frame_sink_id_ =
        child_frame_->layer_tree_frame_sink_id;
  }

  ReportDrawMetric(params);

  if (last_egl_context_ && !IsUsingVulkan() && !IsUsingANGLEOverGL()) {
    // We need to watch if the current Android context has changed and enforce a
    // clean-up in the compositor.  This is only necessary for the validating
    // command decoder.
    EGLContext current_context = eglGetCurrentContext();
    DCHECK(current_context) << "Draw called without EGLContext";

    // TODO(boliu): Handle context loss.
    if (last_egl_context_ != current_context) {
      DLOG(WARNING) << "EGLContextChanged";
    }
  }

  DrawAndSwap(params, overlays_params,
              std::move(report_rendering_threads_callback));
}

void HardwareRenderer::ReturnChildFrame(
    std::unique_ptr<ChildFrame> child_frame) {
  if (!child_frame || !child_frame->frame) {
    return;
  }

  std::vector<viz::ReturnedResource> resources_to_return =
      viz::TransferableResource::ReturnResources(
          child_frame->frame->resource_list);

  // The child frame's frame_sink_id is not necessarily same as
  // |child_frame_sink_id_|.
  ReturnResourcesToCompositor(std::move(resources_to_return),
                              child_frame->frame_sink_id,
                              child_frame->layer_tree_frame_sink_id);
}

void HardwareRenderer::ReturnResourcesToCompositor(
    std::vector<viz::ReturnedResource> resources,
    const viz::FrameSinkId& frame_sink_id,
    uint32_t layer_tree_frame_sink_id) {
  render_thread_manager_->InsertReturnedResourcesOnRT(
      std::move(resources), frame_sink_id, layer_tree_frame_sink_id);
}

void HardwareRenderer::SetChildFrameForTesting(
    std::unique_ptr<ChildFrame> child_frame) {
  child_frame_ = std::move(child_frame);
}

}  // namespace android_webview
