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

#include "ui/gl/dc_layer_tree.h"

#include <d3d11_1.h>

#include <utility>

#include "base/check_is_test.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "base/types/expected.h"
#include "base/types/expected_macros.h"
#include "ui/gfx/color_space_win.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/transform_util.h"
#include "ui/gfx/overlay_layer_id.h"
#include "ui/gl/direct_composition_support.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/swap_chain_presenter.h"

namespace gl {
namespace {

constexpr size_t kVideoProcessorDimensionsWindowSize = 100;

bool NeedSwapChainPresenter(const DCLayerOverlayParams& overlay) {
  return overlay.overlay_image && overlay.overlay_image->type() !=
                                      DCLayerOverlayType::kDCompVisualContent;
}

// Unconditionally get a IDCompositionVisual2 as a IDCompositionVisual3.
//
// |IDCompositionVisual3| should be available since Windows 8.1, but we noticed
// crashes due to unconditionally casting to the interface on the earliest
// versions of Windows 10. This should only be used for features that are
// conditionally run above those versions of Windows.
//
// See: https://crbug.com/1455666
Microsoft::WRL::ComPtr<IDCompositionVisual3> CheckedCastToVisual3(
    const Microsoft::WRL::ComPtr<IDCompositionVisual2>& visual2) {
  Microsoft::WRL::ComPtr<IDCompositionVisual3> visual3;
  HRESULT hr = visual2.As(&visual3);
  CHECK_EQ(hr, S_OK);
  CHECK(visual3);
  return visual3;
}

D2D_MATRIX_3X2_F TransformToD2D_MATRIX_3X2_F(const gfx::Transform& transform) {
  DCHECK(transform.Is2dTransform());
  // See |TransformToD2D_MATRIX_4X4_F| for notes.
  return D2D1::Matrix3x2F(transform.rc(0, 0), transform.rc(1, 0),
                          transform.rc(0, 1), transform.rc(1, 1),
                          transform.rc(0, 3), transform.rc(1, 3));
}

D2D_MATRIX_4X4_F TransformToD2D_MATRIX_4X4_F(const gfx::Transform& transform) {
  // D2D matrices are stored with the translation portion in the last row,
  // whereas Skia matrices are stored with the translation in the last column.
  // We need to transpose the matrix during the conversion to account for this
  // difference.
  const gfx::Transform& t = transform;
  return D2D1::Matrix4x4F(t.rc(0, 0), t.rc(1, 0), t.rc(2, 0), t.rc(3, 0),
                          t.rc(0, 1), t.rc(1, 1), t.rc(2, 1), t.rc(3, 1),
                          t.rc(0, 2), t.rc(1, 2), t.rc(2, 2), t.rc(3, 2),
                          t.rc(0, 3), t.rc(1, 3), t.rc(2, 3), t.rc(3, 3));
}

// The size the surfaces in the pool. Used in |VisualSubtree::Update| to
// determine how to scale the background color visual. This can be any size
// since we need a non-empty surface to display the background fill, so 1x1
// is fine.
constexpr gfx::Size kSolidColorSurfaceSize = gfx::Size(1, 1);

#if DCHECK_IS_ON()
bool VisualTreeValid(
    std::vector<std::optional<size_t>>& subtree_index_to_overlay,
    const std::vector<bool>& prev_subtree_is_attached_to_root) {
  for (size_t i = 0; i < subtree_index_to_overlay.size(); i++) {
    // Unused subtrees must be removed from the root.
    if (!subtree_index_to_overlay[i] && prev_subtree_is_attached_to_root[i]) {
      return false;
    }
  }
  return true;
}
#endif  // DCHECK_IS_ON()
}  // namespace

VideoProcessorWrapper::VideoProcessorWrapper() = default;
VideoProcessorWrapper::~VideoProcessorWrapper() = default;

VideoProcessorWrapper::SizeSmoother::SizeSmoother()
    : width_(kVideoProcessorDimensionsWindowSize),
      height_(kVideoProcessorDimensionsWindowSize) {}
VideoProcessorWrapper::SizeSmoother::~SizeSmoother() = default;

void VideoProcessorWrapper::SizeSmoother::SizeSmoother::PutSize(
    gfx::Size size) {
  width_.AddSample(size.width());
  height_.AddSample(size.height());
}

gfx::Size VideoProcessorWrapper::SizeSmoother::GetSize() const {
  return gfx::Size(width_.Max(), height_.Max());
}

// Owns a |IDCompositionSurface| filled with a solid color.
class SolidColorSurface final {
 public:
  SolidColorSurface() = delete;
  SolidColorSurface(SolidColorSurface&&) = default;
  SolidColorSurface& operator=(SolidColorSurface&&) = default;
  ~SolidColorSurface() = default;

  IDCompositionSurface* surface() const { return surface_.Get(); }

 private:
  friend class SolidColorSurfacePool;

  explicit SolidColorSurface(
      Microsoft::WRL::ComPtr<IDCompositionSurface> surface)
      : surface_(std::move(surface)) {
    CHECK(surface_);
  }

  // Fill the surface with the opaque part of |color|.
  base::expected<void, CommitError> FillColor(ID3D11Device* d3d11_device,
                                              SkColor4f color) {
    HRESULT hr = S_OK;
    RECT update_rect = D2D1::Rect(0, 0, kSolidColorSurfaceSize.width(),
                                  kSolidColorSurfaceSize.height());
    Microsoft::WRL::ComPtr<ID3D11Texture2D> draw_texture;
    POINT update_offset;
    hr = surface_->BeginDraw(&update_rect, IID_PPV_ARGS(&draw_texture),
                             &update_offset);
    if (FAILED(hr)) {
      LOG(ERROR) << "BeginDraw failed: "
                 << logging::SystemErrorCodeToString(hr);
      return base::unexpected(
          CommitError{CommitError::Reason::kSolidColorSurfaceBeginDraw, hr});
    }

    Microsoft::WRL::ComPtr<ID3D11RenderTargetView> rtv;
    hr =
        d3d11_device->CreateRenderTargetView(draw_texture.Get(), nullptr, &rtv);
    if (FAILED(hr)) {
      LOG(ERROR) << "CreateRenderTargetView failed: "
                 << logging::SystemErrorCodeToString(hr);
      return base::unexpected(CommitError{
          CommitError::Reason::kSolidColorSurfaceCreateRenderTargetView, hr});
    }

    Microsoft::WRL::ComPtr<ID3D11DeviceContext> immediate_context;
    d3d11_device->GetImmediateContext(&immediate_context);
    immediate_context->ClearRenderTargetView(rtv.Get(),
                                             color.makeOpaque().vec());

    hr = surface_->EndDraw();
    if (FAILED(hr)) {
      LOG(ERROR) << "EndDraw failed: " << logging::SystemErrorCodeToString(hr);
      return base::unexpected(
          CommitError{CommitError::Reason::kSolidColorSurfaceEndDraw, hr});
    }

    color_ = color;

    return base::ok();
  }

  // A surface with |DXGI_ALPHA_MODE_IGNORE|, filled with the opaque parts of
  // |color_|.
  Microsoft::WRL::ComPtr<IDCompositionSurface> surface_;

  // Only set if |surface_| was successfully filled to this color.
  std::optional<SkColor4f> color_;
};

SolidColorSurfacePool::SolidColorSurfacePool(
    Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
    Microsoft::WRL::ComPtr<IDCompositionDevice3> dcomp_device)
    : d3d11_device_(std::move(d3d11_device)),
      dcomp_device_(std::move(dcomp_device)) {
  CHECK(d3d11_device_);
  CHECK(dcomp_device_);
}
SolidColorSurfacePool::~SolidColorSurfacePool() = default;

base::expected<IDCompositionSurface*, CommitError>
SolidColorSurfacePool::GetSolidColorSurface(const SkColor4f& color) {
  stats_since_last_trim_.num_surfaces_requested += 1;

  HRESULT hr = S_OK;

  auto first_unused_surface_it =
      std::next(tracked_surfaces_.begin(), num_used_this_frame_);

  if (auto found_color_it = std::ranges::find(tracked_surfaces_, color,
                                              &SolidColorSurface::color_);
      found_color_it != tracked_surfaces_.end()) {
    // We found an existing surface in the pool that already has the requested
    // color.

    if (found_color_it >= first_unused_surface_it) {
      // If the surface is in the "unused" portion of |tracked_surfaces_|, make
      // it be tracked now.
      std::swap(*first_unused_surface_it, *found_color_it);
      found_color_it = first_unused_surface_it;
      num_used_this_frame_++;
    } else {
      // The surface is already used by another overlay in this frame, so we can
      // just share it with no extra work.
    }

    return found_color_it->surface();
  }

  // There is no surface that already contains the requested |color|, so we'll
  // need to fill one.
  auto surface_to_fill_it = first_unused_surface_it;
  if (surface_to_fill_it == tracked_surfaces_.end()) {
    // If there are no existing allocations, we'll need to create a new one.
    Microsoft::WRL::ComPtr<IDCompositionSurface> dcomp_surface;
    hr = dcomp_device_->CreateSurface(
        kSolidColorSurfaceSize.width(), kSolidColorSurfaceSize.height(),
        gfx::ColorSpaceWin::GetDXGIFormat(gfx::ColorSpace::CreateSRGB()),
        DXGI_ALPHA_MODE_IGNORE, &dcomp_surface);
    if (FAILED(hr)) {
      LOG(ERROR) << "CreateSurface failed: "
                 << logging::SystemErrorCodeToString(hr);
      return base::unexpected(CommitError{
          CommitError::Reason::kSolidColorSurfacePoolCreateSurface, hr});
    }

    surface_to_fill_it = tracked_surfaces_.insert(
        first_unused_surface_it, SolidColorSurface(std::move(dcomp_surface)));
  }

  // The surface we want to use doesn't have the right color at this point.
  RETURN_IF_ERROR(surface_to_fill_it->FillColor(d3d11_device_.Get(), color));

  // Update the partitioning index after |FillColor| succeeds. In the case of
  // failure, |tracked_surfaces_[num_used_this_frame_]| will still have a valid
  // surface, just not filled to any color yet.
  num_used_this_frame_++;

  stats_since_last_trim_.num_surfaces_recolored += 1;

  return surface_to_fill_it->surface();
}

void SolidColorSurfacePool::TrimAfterCommit() {
  // The is the maximum number of solid color surfaces (both in use and not in
  // use) that we will retain between frames. If we are actively using more than
  // this, this value will be ignored.
  //
  // The value is copied from gbm_surfaceless_wayland.cc's
  // |kMaxSolidColorBuffers|, which picks this value based on observationally
  // seeing max 9 in-flight buffers + some margin. However, this can be any
  // value. If the value is smaller than the number of overlays commonly seen
  // in a frame, we may thrash on allocations. If the value is too large, we
  // will end up wasting space.
  static constexpr size_t kMaxSolidColorSurfacesToRetain = 12;

  // Preserve up to |kMaxSolidColorSurfacesToRetain| surfaces, even if they
  // aren't used this frame.
  size_t trim_target_size =
      std::max(num_used_this_frame_, kMaxSolidColorSurfacesToRetain);
  // Protect against the case where there are fewer tracked surfaces than
  // |kMaxSolidColorSurfacesToRetain|.
  trim_target_size = std::min(trim_target_size, tracked_surfaces_.size());

  DVLOG(3) << "SolidColorSurfacePool stats before trim: " << "requested="
           << stats_since_last_trim_.num_surfaces_requested << ", "
           << "recolored=" << stats_since_last_trim_.num_surfaces_recolored
           << ", " << "in-use/total=" << num_used_this_frame_ << "/"
           << tracked_surfaces_.size()
           << (num_used_this_frame_ > kMaxSolidColorSurfacesToRetain
                   ? " (in-use exceeds kMaxSolidColorSurfacesToRetain)"
                   : "")
           << ", will trim to " << trim_target_size;

  auto first_surface_to_remove =
      std::next(tracked_surfaces_.begin(), trim_target_size);
  tracked_surfaces_.erase(first_surface_to_remove, tracked_surfaces_.end());

  // Reset for the next frame.
  num_used_this_frame_ = 0;
  stats_since_last_trim_ = {};
}

size_t SolidColorSurfacePool::GetNumSurfacesInPoolForTesting() const {
  CHECK_IS_TEST();
  return tracked_surfaces_.size();
}

DCLayerTree::DCLayerTree(bool disable_nv12_dynamic_textures,
                         bool disable_vp_auto_hdr,
                         bool disable_vp_scaling,
                         bool disable_vp_super_resolution,
                         bool disable_dc_letterbox_video_optimization,
                         bool force_dcomp_triple_buffer_video_swap_chain,
                         bool no_downscaled_overlay_promotion)
    : disable_nv12_dynamic_textures_(disable_nv12_dynamic_textures),
      disable_vp_auto_hdr_(disable_vp_auto_hdr),
      disable_vp_scaling_(disable_vp_scaling),
      disable_vp_super_resolution_(disable_vp_super_resolution),
      disable_dc_letterbox_video_optimization_(
          disable_dc_letterbox_video_optimization),
      force_dcomp_triple_buffer_video_swap_chain_(
          force_dcomp_triple_buffer_video_swap_chain),
      no_downscaled_overlay_promotion_(no_downscaled_overlay_promotion),
      tint_video_layer_(base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kTintDcLayer)),
      ink_renderer_(std::make_unique<DelegatedInkRenderer>()) {}

DCLayerTree::~DCLayerTree() = default;

void DCLayerTree::Initialize(
    HWND window,
    Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device) {
  window_ = window;
  DCHECK(window_);

  d3d11_device_ = std::move(d3d11_device);
  DCHECK(d3d11_device_);

  dcomp_device_ = GetDirectCompositionDevice();
  DCHECK(dcomp_device_);

  d3d12_command_queue_ = GetDirectCompositionD3D12CommandQueue();

  if (d3d12_command_queue_) {
    Microsoft::WRL::ComPtr<EXPERIMENTAL_IDCompositionDevice6> dcomp_device6;
    HRESULT hr = dcomp_device_.As(&dcomp_device6);
    CHECK_EQ(hr, S_OK);
    dcomp_device_6_ = std::move(dcomp_device6);
  }

  solid_color_surface_pool_ =
      std::make_unique<SolidColorSurfacePool>(d3d11_device_, dcomp_device_);

  Microsoft::WRL::ComPtr<IDCompositionDesktopDevice> desktop_device;
  dcomp_device_.As(&desktop_device);
  DCHECK(desktop_device);

  HRESULT hr =
      desktop_device->CreateTargetForHwnd(window_, TRUE, &dcomp_target_);
  // |CreateTargetForHwnd| can fail if |window_| belongs to a different process
  // (DCOMPOSITION_ERROR_ACCESS_DENIED) or we have already called
  // |CreateTargetForHwnd| for this window
  // (DCOMPOSITION_ERROR_WINDOW_ALREADY_COMPOSED). We don't expect either to be
  // the case here.
  CHECK_EQ(hr, S_OK);

  hr = dcomp_device_->CreateVisual(&dcomp_root_visual_);
  CHECK_EQ(hr, S_OK);

  if (base::FeatureList::IsEnabled(features::kDCompDebugVisualization)) {
    Microsoft::WRL::ComPtr<IDCompositionDeviceDebug> debug_device;
    hr = dcomp_device_.As(&debug_device);
    CHECK_EQ(hr, S_OK);
    CHECK(debug_device);
    DLOG(WARNING) << "DComp debug counters enabled, visible in the top right.";
    DLOG(WARNING) << "  - left: The composition engine FPS, averaged over the "
                     "last 60 composition frames";
    DLOG(WARNING) << "  - right: The overall CPU usage of the composition "
                     "thread, in milliseconds";
    hr = debug_device->EnableDebugCounters();
    CHECK_EQ(hr, S_OK);

    Microsoft::WRL::ComPtr<IDCompositionVisualDebug> debug_visual;
    hr = dcomp_root_visual_.As(&debug_visual);
    CHECK_EQ(hr, S_OK);
    CHECK(debug_visual);
    hr = debug_visual->EnableRedrawRegions();
    CHECK_EQ(hr, S_OK);
  }

  dcomp_target_->SetRoot(dcomp_root_visual_.Get());
  // A visual inherits the interpolation mode of the parent visual by default.
  // If no visuals set the interpolation mode, the default for the entire visual
  // tree is nearest neighbor interpolation.
  // Set the interpolation mode to Linear to get a better upscaling quality.
  dcomp_root_visual_->SetBitmapInterpolationMode(
      DCOMPOSITION_BITMAP_INTERPOLATION_MODE_LINEAR);

  hdr_metadata_helper_ = HDRMetadataHelperWin::Create();

  if (Microsoft::WRL::ComPtr<IDCompositionDevice5> dcomp_device5;
      SUCCEEDED(dcomp_device_.As(&dcomp_device5))) {
    hr = dcomp_device5->CreateDynamicTexture(&primary_plane_surface_);
    if (FAILED(hr)) {
      LOG(WARNING) << "Failed to create IDCompositionDynamicTexture: "
                   << logging::SystemErrorCodeToString(hr);
    }
  }
}

VideoProcessorWrapper* DCLayerTree::InitializeVideoProcessor(
    const gfx::Size& input_size,
    const gfx::Size& output_size,
    bool is_hdr_output,
    bool& video_processor_recreated) {
  video_processor_recreated = false;
  auto& video_processor_wrapper = is_hdr_output ? video_processor_wrapper_hdr_
                                                : video_processor_wrapper_sdr_;
  if (!video_processor_wrapper.video_device) {
    // This can fail if the D3D device is "Microsoft Basic Display Adapter".
    if (FAILED(d3d11_device_.As(&video_processor_wrapper.video_device))) {
      LOG(ERROR) << "Failed to retrieve video device from D3D11 device";
      DCHECK(false);
      DisableDirectCompositionOverlays();
      return nullptr;
    }
    DCHECK(video_processor_wrapper.video_device);

    Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
    d3d11_device_->GetImmediateContext(&context);
    DCHECK(context);
    context.As(&video_processor_wrapper.video_context);
    DCHECK(video_processor_wrapper.video_context);
  }

  // Calculate input and output size to be maximum in a sliding window.
  video_processor_wrapper.input_size_smoother.PutSize(input_size);
  video_processor_wrapper.output_size_smoother.PutSize(output_size);

  gfx::Size effective_input_size =
      video_processor_wrapper.input_size_smoother.GetSize();
  gfx::Size effective_output_size =
      video_processor_wrapper.output_size_smoother.GetSize();

  // Reuse existing video processor only if it has exactly the computed size.
  // Even if it may have bigger dimensions and may be reusable for requested
  // sizes we will recreate it to reduce resource usage. Sliding window max
  // above guarantees that this reduction will only happen after prolonged usage
  // with smaller texture sizes.
  if (video_processor_wrapper.video_processor &&
      video_processor_wrapper.video_input_size == effective_input_size &&
      video_processor_wrapper.video_output_size == effective_output_size) {
    return &video_processor_wrapper;
  }

  TRACE_EVENT2("gpu", "DCLayerTree::InitializeVideoProcessor", "input_size",
               input_size.ToString(), "output_size", output_size.ToString());

  video_processor_wrapper.video_input_size = effective_input_size;
  video_processor_wrapper.video_output_size = effective_output_size;
  video_processor_wrapper.video_processor.Reset();
  video_processor_wrapper.video_processor_enumerator.Reset();
  D3D11_VIDEO_PROCESSOR_CONTENT_DESC desc = {};
  desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
  desc.InputFrameRate.Numerator = 60;
  desc.InputFrameRate.Denominator = 1;
  desc.InputWidth = input_size.width();
  desc.InputHeight = input_size.height();
  desc.OutputFrameRate.Numerator = 60;
  desc.OutputFrameRate.Denominator = 1;
  desc.OutputWidth = output_size.width();
  desc.OutputHeight = output_size.height();
  desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
  HRESULT hr =
      video_processor_wrapper.video_device->CreateVideoProcessorEnumerator(
          &desc, &video_processor_wrapper.video_processor_enumerator);
  if (FAILED(hr)) {
    LOG(ERROR) << "CreateVideoProcessorEnumerator failed:"
               << logging::SystemErrorCodeToString(hr);
    // It might fail again next time. Disable overlay support so
    // overlay processor will stop sending down overlay frames.
    DisableDirectCompositionOverlays();
    return nullptr;
  }
  hr = video_processor_wrapper.video_device->CreateVideoProcessor(
      video_processor_wrapper.video_processor_enumerator.Get(), 0,
      &video_processor_wrapper.video_processor);
  if (FAILED(hr)) {
    LOG(ERROR) << "CreateVideoProcessor failed:"
               << logging::SystemErrorCodeToString(hr);
    // It might fail again next time. Disable overlay support so
    // overlay processor will stop sending down overlay frames.
    DisableDirectCompositionOverlays();
    return nullptr;
  }
  // Auto stream processing (the default) can hurt power consumption.
  video_processor_wrapper.video_context
      ->VideoProcessorSetStreamAutoProcessingMode(
          video_processor_wrapper.video_processor.Get(), 0, FALSE);

  video_processor_recreated = true;
  return &video_processor_wrapper;
}

IDXGISwapChain1* DCLayerTree::GetLayerSwapChainForTesting(
    const gfx::OverlayLayerId& layer_id) const {
  CHECK_IS_TEST();
  if (video_swap_chains_.contains(layer_id)) {
    return video_swap_chains_.at(layer_id)->swap_chain().Get();
  }
  return nullptr;
}

DCLayerTree::VisualTree::VisualSubtree*
DCLayerTree::GetFrontMostVideoVisualSubtreeForTesting() const {
  CHECK_IS_TEST();
  VisualTree::VisualSubtree* front_sub_tree =
      visual_tree_->GetFrontMostVisualSubtreeForTesting();  // IN-TEST
  // `dcomp_visual_content` on front-most subtree should match
  // SwapChainPresenter::content() in `video_swap_chains`
  for (const auto& video_swap_chain : video_swap_chains_) {
    const auto& swap_chain_presenter = video_swap_chain.second;
    if (swap_chain_presenter->content_for_testing().Get() ==  // IN-TEST
        front_sub_tree->dcomp_visual_content()) {
      return front_sub_tree;
    }
  }

  return nullptr;
}

DCLayerTree::VisualTree::VisualSubtree::VisualSubtree() = default;
DCLayerTree::VisualTree::VisualSubtree::~VisualSubtree() {
  if (content_visual_) {
    // Explicitly null out the `content_visual_`'s content to ensure there are
    // no unexpected references to e.g. `IDCompositionTexture`, in case there
    // are lingering references to `content_visual_`.
    HRESULT hr = content_visual_->SetContent(nullptr);
    CHECK_EQ(S_OK, hr);
  }
}

bool DCLayerTree::VisualTree::VisualSubtree::Update(
    IDCompositionDevice3* dcomp_device,
    Microsoft::WRL::ComPtr<IUnknown> dcomp_visual_content,
    uint64_t dcomp_surface_serial,
    const gfx::Size& image_size,
    const gfx::RectF& content_rect,
    Microsoft::WRL::ComPtr<IDCompositionSurface> background_color_surface,
    const SkColor4f& background_color,
    const gfx::Rect& quad_rect,
    bool nearest_neighbor_filter,
    const gfx::Transform& quad_to_root_transform,
    const gfx::RRectF& rounded_corner_bounds,
    float opacity,
    const std::optional<gfx::Rect>& clip_rect_in_root,
    bool allow_antialiasing) {
  bool needs_commit = false;

  // Helper function to set |field| to |parameter| and return whether it
  // changed.
  auto SetField = [&needs_commit](auto& field, auto& parameter) -> bool {
    const bool changed = field != parameter;
    if (changed) {
      field = std::move(parameter);

      // We assume that any change to the input of |Update| will result in some
      // visual property change that requires a commit. If this is not true, an
      // input is not needed.
      needs_commit = true;
    }
    return changed;
  };

  // Fields on |VisualSubtree| should map 1:1 with parameters to |Update| (with
  // the exception of the DComp device pointer, DComp visuals, and Z-order). To
  // avoid issues with incremental computation, set fields to input parameters
  // here with the helper function and read the member fields below only if
  // guarded by the corresponding |*_changed| variable.
  const bool dcomp_visual_content_changed =
      SetField(dcomp_visual_content_, dcomp_visual_content);
  const bool dcomp_surface_serial_changed =
      SetField(dcomp_surface_serial_, dcomp_surface_serial);
  const bool image_size_changed = SetField(image_size_, image_size);
  const bool content_rect_changed = SetField(content_rect_, content_rect);
  const bool background_color_surface_changed =
      SetField(background_color_surface_, background_color_surface);
  const bool background_color_changed =
      SetField(background_color_, background_color);
  const bool quad_rect_changed = SetField(quad_rect_, quad_rect);
  const bool nearest_neighbor_filter_changed =
      SetField(nearest_neighbor_filter_, nearest_neighbor_filter);
  const bool quad_to_root_transform_changed =
      SetField(quad_to_root_transform_, quad_to_root_transform);
  const bool rounded_corner_bounds_changed =
      SetField(rounded_corner_bounds_, rounded_corner_bounds);
  const bool opacity_changed = SetField(opacity_, opacity);
  const bool clip_rect_in_root_changed =
      SetField(clip_rect_in_root_, clip_rect_in_root);
  const bool allow_antialiasing_changed =
      SetField(allow_antialiasing_, allow_antialiasing);

  // Methods that update the visual tree can only fail with OOM. We'll assert
  // success in this function to aid in debugging.
  HRESULT hr = S_OK;

  // All the visual are created together on the first |Update|.
  if (!clip_visual_) {
    needs_commit = true;

    CHECK(!rounded_corners_visual_);
    CHECK(!transform_visual_);
    CHECK(!background_color_visual_);
    CHECK(!content_visual_);

    hr = dcomp_device->CreateVisual(&clip_visual_);
    CHECK_EQ(hr, S_OK);
    hr = dcomp_device->CreateVisual(&rounded_corners_visual_);
    CHECK_EQ(hr, S_OK);
    hr = dcomp_device->CreateVisual(&transform_visual_);
    CHECK_EQ(hr, S_OK);
    hr = dcomp_device->CreateVisual(&background_color_visual_);
    CHECK_EQ(hr, S_OK);
    hr = dcomp_device->CreateVisual(&content_visual_);
    CHECK_EQ(hr, S_OK);

    hr = clip_visual_->AddVisual(rounded_corners_visual_.Get(), FALSE, nullptr);
    CHECK_EQ(hr, S_OK);
    hr = rounded_corners_visual_->AddVisual(transform_visual_.Get(), FALSE,
                                            nullptr);
    CHECK_EQ(hr, S_OK);
    hr = transform_visual_->AddVisual(background_color_visual_.Get(), FALSE,
                                      nullptr);
    CHECK_EQ(hr, S_OK);
    hr = transform_visual_->AddVisual(content_visual_.Get(), FALSE, nullptr);
    CHECK_EQ(hr, S_OK);

    // The default state for the border mode is INHERIT, so we need to force it
    // to HARD.
    hr = transform_visual_->SetBorderMode(DCOMPOSITION_BORDER_MODE_HARD);
    CHECK_EQ(hr, S_OK);
  }

  if (clip_rect_in_root_changed) {
    if (clip_rect_in_root_.has_value()) {
      // DirectComposition clips happen in the pre-transform visual space, while
      // cc/ clips happen post-transform. So the clip needs to go on a separate
      // parent visual that's untransformed.
      const gfx::Rect& clip_rect = clip_rect_in_root_.value();
      hr = clip_visual_->SetClip(D2D1::RectF(
          clip_rect.x(), clip_rect.y(), clip_rect.right(), clip_rect.bottom()));
      CHECK_EQ(hr, S_OK);
    } else {
      hr = clip_visual_->SetClip(nullptr);
      CHECK_EQ(hr, S_OK);
    }
  }

  if (opacity_changed) {
    if (opacity_ != 1) {
      hr = CheckedCastToVisual3(clip_visual_)->SetOpacity(opacity_);
      CHECK_EQ(hr, S_OK);

      // Let all of this subtree's visuals blend as one, instead of
      // individually
      hr = clip_visual_->SetOpacityMode(DCOMPOSITION_OPACITY_MODE_LAYER);
      CHECK_EQ(hr, S_OK);
    } else {
      hr = CheckedCastToVisual3(clip_visual_)->SetOpacity(1.0);
      CHECK_EQ(hr, S_OK);
      hr = clip_visual_->SetOpacityMode(DCOMPOSITION_OPACITY_MODE_MULTIPLY);
      CHECK_EQ(hr, S_OK);
    }
  }

  if (rounded_corner_bounds_changed) {
    if (!rounded_corner_bounds_.IsEmpty()) {
      Microsoft::WRL::ComPtr<IDCompositionRectangleClip> clip;
      hr = dcomp_device->CreateRectangleClip(&clip);
      CHECK_EQ(hr, S_OK);
      CHECK(clip);

      const gfx::RectF rect = rounded_corner_bounds_.rect();
      hr = clip->SetLeft(rect.x());
      CHECK_EQ(hr, S_OK);
      hr = clip->SetRight(rect.right());
      CHECK_EQ(hr, S_OK);
      hr = clip->SetBottom(rect.bottom());
      CHECK_EQ(hr, S_OK);
      hr = clip->SetTop(rect.y());
      CHECK_EQ(hr, S_OK);

      const gfx::Vector2dF top_left = rounded_corner_bounds_.GetCornerRadii(
          gfx::RRectF::Corner::kUpperLeft);
      hr = clip->SetTopLeftRadiusX(top_left.x());
      CHECK_EQ(hr, S_OK);
      hr = clip->SetTopLeftRadiusY(top_left.y());
      CHECK_EQ(hr, S_OK);

      const gfx::Vector2dF top_right = rounded_corner_bounds_.GetCornerRadii(
          gfx::RRectF::Corner::kUpperRight);
      hr = clip->SetTopRightRadiusX(top_right.x());
      CHECK_EQ(hr, S_OK);
      hr = clip->SetTopRightRadiusY(top_right.y());
      CHECK_EQ(hr, S_OK);

      const gfx::Vector2dF bottom_left = rounded_corner_bounds_.GetCornerRadii(
          gfx::RRectF::Corner::kLowerLeft);
      hr = clip->SetBottomLeftRadiusX(bottom_left.x());
      CHECK_EQ(hr, S_OK);
      hr = clip->SetBottomLeftRadiusY(bottom_left.y());
      CHECK_EQ(hr, S_OK);

      const gfx::Vector2dF bottom_right = rounded_corner_bounds_.GetCornerRadii(
          gfx::RRectF::Corner::kLowerRight);
      hr = clip->SetBottomRightRadiusX(bottom_right.x());
      CHECK_EQ(hr, S_OK);
      hr = clip->SetBottomRightRadiusY(bottom_right.y());
      CHECK_EQ(hr, S_OK);

      hr = rounded_corners_visual_->SetClip(clip.Get());
      CHECK_EQ(hr, S_OK);

      // Enable anti-aliasing of the rounded corners.
      hr =
          rounded_corners_visual_->SetBorderMode(DCOMPOSITION_BORDER_MODE_SOFT);
      CHECK_EQ(hr, S_OK);
    } else {
      hr = rounded_corners_visual_->SetClip(nullptr);
      CHECK_EQ(hr, S_OK);
      hr = rounded_corners_visual_->SetBorderMode(
          DCOMPOSITION_BORDER_MODE_INHERIT);
      CHECK_EQ(hr, S_OK);
    }
  }

  if (quad_to_root_transform_changed) {
    if (quad_to_root_transform_.Is2dTransform()) {
      const D2D_MATRIX_3X2_F matrix =
          TransformToD2D_MATRIX_3X2_F(quad_to_root_transform_);
      hr = Microsoft::WRL::ComPtr<IDCompositionVisual>(transform_visual_)
               ->SetTransform(matrix);
      CHECK_EQ(hr, S_OK);
    } else {
      const D2D_MATRIX_4X4_F matrix =
          TransformToD2D_MATRIX_4X4_F(quad_to_root_transform_);
      hr = CheckedCastToVisual3(transform_visual_)->SetTransform(matrix);
      CHECK_EQ(hr, S_OK);
    }
  }

  if (nearest_neighbor_filter_changed) {
    hr = transform_visual_->SetBitmapInterpolationMode(
        nearest_neighbor_filter_
            ? DCOMPOSITION_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
            : DCOMPOSITION_BITMAP_INTERPOLATION_MODE_LINEAR);
    CHECK_EQ(hr, S_OK);
  }

  if (image_size_changed || content_rect_changed || quad_rect_changed) {
    if (content_rect_.Contains(gfx::RectF(image_size_))) {
      // No need to set clip to content if the whole image is inside the content
      // rect region.
      hr = content_visual_->SetClip(nullptr);
      CHECK_EQ(hr, S_OK);
    } else {
      // Exclude content outside the content rect region.
      const auto content_clip =
          D2D1::RectF(content_rect_.x(), content_rect_.y(),
                      content_rect_.right(), content_rect_.bottom());
      hr = content_visual_->SetClip(content_clip);
      CHECK_EQ(hr, S_OK);
    }

    // Transform the (clipped) content so that it fills |quad_rect_|'s bounds.
    // |quad_rect_|'s offset is handled below, so we exclude it from the matrix.
    const bool needs_offset = !content_rect_.OffsetFromOrigin().IsZero();
    const bool needs_scale =
        static_cast<float>(quad_rect_.width()) != content_rect_.width() ||
        static_cast<float>(quad_rect_.height()) != content_rect_.height();
    if (needs_offset || needs_scale) {
      const float scale_x =
          static_cast<float>(quad_rect_.width()) / content_rect_.width();
      const float scale_y =
          static_cast<float>(quad_rect_.height()) / content_rect_.height();
      const D2D_MATRIX_3X2_F matrix =
          D2D1::Matrix3x2F::Translation(-content_rect_.x(),
                                        -content_rect_.y()) *
          D2D1::Matrix3x2F::Scale(scale_x, scale_y);
      hr = Microsoft::WRL::ComPtr<IDCompositionVisual>(content_visual_)
               ->SetTransform(matrix);
      CHECK_EQ(hr, S_OK);
    } else {
      hr = content_visual_->SetTransform(nullptr);
      CHECK_EQ(hr, S_OK);
    }

    // Visual offset is applied after transform so it is affected by the
    // transform, which is consistent with how the compositor maps quad rects to
    // their target space.
    hr = content_visual_->SetOffsetX(quad_rect_.x());
    CHECK_EQ(hr, S_OK);
    hr = content_visual_->SetOffsetY(quad_rect_.y());
    CHECK_EQ(hr, S_OK);
  }

  if (dcomp_visual_content_changed) {
    hr = content_visual_->SetContent(dcomp_visual_content_.Get());
    CHECK_EQ(hr, S_OK);
  }
#if DCHECK_IS_ON()
  dcomp_visual_content_changed_from_previous_frame_ =
      dcomp_visual_content_changed;
#endif

  if (dcomp_surface_serial_changed) {
    // The DComp surface has been drawn to and needs a commit to show its
    // update. No visual changes are needed in this case.
  }

  if (quad_rect_changed || background_color_surface_changed ||
      background_color_changed) {
    if (!background_color_surface_ || background_color.fA == 0.0) {
      // A fully transparent color is the same as no background fill.
      hr = background_color_visual_->SetContent(nullptr);
      CHECK_EQ(hr, S_OK);
    } else {
      const D2D_MATRIX_3X2_F matrix =
          TransformToD2D_MATRIX_3X2_F(gfx::TransformBetweenRects(
              gfx::RectF(kSolidColorSurfaceSize), gfx::RectF(quad_rect_)));
      hr = Microsoft::WRL::ComPtr<IDCompositionVisual>(background_color_visual_)
               ->SetTransform(matrix);
      CHECK_EQ(hr, S_OK);

      hr =
          background_color_visual_->SetContent(background_color_surface_.Get());
      CHECK_EQ(hr, S_OK);

      hr = CheckedCastToVisual3(background_color_visual_)
               ->SetOpacity(background_color.fA);
      CHECK_EQ(hr, S_OK);
    }
  }

  if (quad_to_root_transform_changed || quad_rect_changed ||
      allow_antialiasing_changed) {
    const float kNeedsSoftBorderTolerance = 0.001;
    const bool content_soft_borders =
        allow_antialiasing_ &&
        (!quad_to_root_transform_.Preserves2dAxisAlignment() ||
         !gfx::IsNearestRectWithinDistance(
             quad_to_root_transform_.MapRect(gfx::RectF(quad_rect_)),
             kNeedsSoftBorderTolerance));
    // The border mode of the transform visual is set (instead of the content
    // visual), so this setting can affect both the content and the background
    // color, since both are are children of the transform visual.
    hr = transform_visual_->SetBorderMode(content_soft_borders
                                              ? DCOMPOSITION_BORDER_MODE_SOFT
                                              : DCOMPOSITION_BORDER_MODE_HARD);
    CHECK_EQ(hr, S_OK);
  }

  return needs_commit;
}

void DCLayerTree::VisualTree::VisualSubtree::GetSwapChainVisualInfoForTesting(
    gfx::Transform* out_transform,
    gfx::Point* out_offset,
    gfx::Rect* out_clip_rect) const {
  CHECK_IS_TEST();
  *out_transform = quad_to_root_transform_;
  *out_offset = quad_rect_.origin();
  *out_clip_rect = clip_rect_in_root_.value_or(gfx::Rect());
}

DCLayerTree::VisualTree::VisualTree(DCLayerTree* dc_layer_tree)
    : dc_layer_tree_(dc_layer_tree) {}

DCLayerTree::VisualTree::~VisualTree() = default;

base::expected<void, CommitError> DCLayerTree::VisualTree::BuildTree(
    const std::vector<DCLayerOverlayParams>& overlays) {
#if EXPENSIVE_DCHECKS_ARE_ON()
  CHECK(std::ranges::is_sorted(overlays, {}, &DCLayerOverlayParams::z_order));
#endif
  // Index into the subtree from the previous frame that is being reused in the
  // current frame for the given overlay index.
  // |overlay_index_to_reused_subtree| has an entry for every overlay in the
  // current frame. Each entry indexes into |visual_subtrees_|, which are the
  // subtrees for the previous frame. Initialized with std::nullopt,
  // meaning not reused.
  std::vector<std::optional<size_t>> overlay_index_to_reused_subtree(
      overlays.size(), std::nullopt);

  // Index into the current frame overlay that uses the subtree of the previous
  // frame for the given subtree index. |subtree_index_to_overlay| has an entry
  // for every subtree in the previous frame. Each entry indexes into |overlays|
  // of the current frame. Initialized with std::nullopt, meaning the subtree
  // is not being reused in the current frame.
  std::vector<std::optional<size_t>> subtree_index_to_overlay(
      visual_subtrees_.size(), std::nullopt);

  // |visual_subtrees| will become |visual_subtrees_| of the current frame;
  std::vector<std::unique_ptr<VisualSubtree>> visual_subtrees;
  visual_subtrees.resize(overlays.size());

  decltype(layer_ids_for_testing_) layer_ids_for_testing;
  layer_ids_for_testing.reserve(overlays.size());

  // Populate the map with visual content and assign matching subtrees to the
  // overlays.
  VisualSubtreeMap subtree_map = BuildMapAndAssignMatchingSubtrees(
      overlays, visual_subtrees, overlay_index_to_reused_subtree,
      subtree_index_to_overlay);

  // Assign unused subtrees to the overlays that don't have a match.
  const size_t first_prev_frame_subtree_unused_index =
      ReuseUnmatchedSubtrees(visual_subtrees, overlay_index_to_reused_subtree,
                             subtree_index_to_overlay);

  // Status for each subtree of the previous frame if it's attached to the root.
  // Initialized with true, meaning attached.
  std::vector<bool> prev_subtree_is_attached_to_root(visual_subtrees_.size(),
                                                     true);

  bool needs_commit = DetachUnusedSubtreesFromRoot(
      first_prev_frame_subtree_unused_index, prev_subtree_is_attached_to_root);

  // Remove unused subtrees from the root that need repositioning.
  needs_commit |= DetachReusedSubtreesThatNeedRepositioningFromRoot(
      visual_subtrees, overlay_index_to_reused_subtree,
      subtree_index_to_overlay, prev_subtree_is_attached_to_root);

#if DCHECK_IS_ON()
  VisualTreeValid(subtree_index_to_overlay, prev_subtree_is_attached_to_root);
#endif  // DCHECK_IS_ON()

  IDCompositionVisual2* left_sibling_visual = nullptr;

  base::flat_set<std::optional<gfx::OverlayLayerId::SharedQuadStateLayerId>>
      layers_with_multiple_overlays;
  for (size_t i = 1; i < overlays.size(); i++) {
    const decltype(layers_with_multiple_overlays)::key_type sqs_layer_id =
        overlays[i].layer_id.shared_quad_state_layer_id();
    if (sqs_layer_id == decltype(layers_with_multiple_overlays)::key_type()) {
      // A default layer ID implies no explicit layer, which should be treated
      // as different from every other layer ID, including itself.
      continue;
    }

    if (overlays[i].layer_id == overlays[i - 1].layer_id) {
      // There were at least two contiguous quads in the same layer.
      layers_with_multiple_overlays.emplace(sqs_layer_id);
    }
  }

  size_t num_layers_modified = 0;

  // This loop walks the overlays and builds or updates the visual subtree for
  // each overlay. |left_sibling_visual| is required to properly stack visual
  // subtrees that are detached from the root visual.
  for (unsigned int i = 0; i < overlays.size(); i++) {
    bool subtree_attached_to_root = false;
    if (visual_subtrees[i]) {
      DCHECK(overlay_index_to_reused_subtree[i]);
      subtree_attached_to_root =
          prev_subtree_is_attached_to_root[overlay_index_to_reused_subtree[i]
                                               .value()];
    } else {
      // This overlay does not reuse a subtree from the previous frame.
      // Instantiate a new one.
      visual_subtrees[i] = std::make_unique<VisualSubtree>();
    }

    const uint64_t dcomp_surface_serial =
        overlays[i].overlay_image.has_value()
            ? overlays[i].overlay_image->dcomp_surface_serial()
            : 0;
    const gfx::Size image_size = overlays[i].overlay_image.has_value()
                                     ? overlays[i].overlay_image->size()
                                     : gfx::Size();

    // Only get a background color surface if we have a non-transparent
    // background color.
    IDCompositionSurface* background_color_surface = nullptr;
    if (overlays[i].background_color &&
        overlays[i].background_color->fA != 0.0) {
      // TODO(http://crbug.com/1380822): Refactor to remove early exits. They
      // may leave visual_subtrees_ corrupted.
      ASSIGN_OR_RETURN(
          background_color_surface,
          dc_layer_tree_->solid_color_surface_pool_->GetSolidColorSurface(
              overlays[i].background_color.value()));
    }

    VisualSubtree* visual_subtree = visual_subtrees[i].get();
    visual_subtree->set_z_order(overlays[i].z_order);
    IUnknown* dcomp_visual_content =
        overlays[i].overlay_image
            ? overlays[i].overlay_image->dcomp_visual_content()
            : nullptr;

    // TODO(crbug.com/324460866): We turn off overlay edge antialiasing when
    // there are multiple overlays in the same layer. This is a workaround to
    // avoid seams when there is e.g. a complex transform applied to the layer.
    // This works for partial delegation because we only expect non-trivial
    // transforms in ephemeral (i.e. animation) states. To support arbitrary
    // content in full delegation, we'll need to parent overlays in the same
    // layer under the same transform visual.
    const bool allow_antialiasing = !layers_with_multiple_overlays.contains(
        overlays[i].layer_id.shared_quad_state_layer_id());

    const bool visual_needs_commit = visual_subtrees[i]->Update(
        dc_layer_tree_->dcomp_device_.Get(), dcomp_visual_content,
        dcomp_surface_serial, image_size, overlays[i].content_rect,
        background_color_surface,
        overlays[i].background_color.value_or(SkColors::kTransparent),
        overlays[i].quad_rect, overlays[i].nearest_neighbor_filter,
        overlays[i].transform, overlays[i].rounded_corner_bounds,
        overlays[i].opacity, overlays[i].clip_rect, allow_antialiasing);

    if (!subtree_attached_to_root) {
      HRESULT hr = dc_layer_tree_->dcomp_root_visual_.Get()->AddVisual(
          visual_subtree->container_visual(), TRUE, left_sibling_visual);
      CHECK_EQ(hr, S_OK);
    }
    left_sibling_visual = visual_subtree->container_visual();

    if (visual_needs_commit || !subtree_attached_to_root) {
      num_layers_modified++;
      needs_commit = true;
    }

    layer_ids_for_testing.push_back(overlays[i].layer_id);
  }

  // Update subtree_map_ and visual_subtrees_ with new values.
  subtree_map_ = std::move(subtree_map);
  visual_subtrees_ = std::move(visual_subtrees);
  layer_ids_for_testing_ = std::move(layer_ids_for_testing);

  UMA_HISTOGRAM_COUNTS("GPU.OsCompositor.NumLayersModified",
                       num_layers_modified);

  if (needs_commit) {
    if (dc_layer_tree_->dcomp_device_6_) {
      // First call `PresentCompositionTextures` to specify the queue that the
      // next `Commit` call uses to actually present the composition textures.
      IUnknown* command_queue_unk = dc_layer_tree_->d3d12_command_queue_.Get();
      HRESULT hr = dc_layer_tree_->dcomp_device_6_->PresentCompositionTextures(
          &command_queue_unk, 1);
      if (FAILED(hr)) {
        LOG(ERROR) << "PresentCompositionTextures failed with error: "
                   << logging::SystemErrorCodeToString(hr);
        return base::unexpected(
            CommitError{CommitError::Reason::
                            kIDCompositionDevice6PresentCompositionTextures,
                        hr});
      }
    }

    TRACE_EVENT0("gpu", "DCLayerTree::CommitAndClearPendingOverlays::Commit");
    base::ScopedUmaHistogramTimer scoped_timer(
        "GPU.DirectComposition.DCompCommitDuration",
        base::ScopedUmaHistogramTimer::ScopedHistogramTiming::
            kMicrosecondTimes);
    HRESULT hr = dc_layer_tree_->dcomp_device_->Commit();
    if (FAILED(hr)) {
      DLOG(ERROR) << "Commit failed with error 0x" << std::hex << hr;
      return base::unexpected(
          CommitError{CommitError::Reason::kIDCompositionDeviceCommit, hr});
    }
  }
  return base::ok();
}

DCLayerTree::VisualTree::VisualSubtreeMap
DCLayerTree::VisualTree::BuildMapAndAssignMatchingSubtrees(
    const std::vector<DCLayerOverlayParams>& overlays,
    std::vector<std::unique_ptr<VisualSubtree>>& new_visual_subtrees,
    std::vector<std::optional<size_t>>& overlay_index_to_reused_subtree,
    std::vector<std::optional<size_t>>& subtree_index_to_overlay) {
  CHECK_EQ(overlay_index_to_reused_subtree.size(), overlays.size());
  CHECK_EQ(new_visual_subtrees.size(), overlays.size());
  CHECK_EQ(subtree_index_to_overlay.size(), visual_subtrees_.size());

  // Contains {visual content, overlay index} pairs for this frame overlays.
  // This structure has entries for overlays that have visual content.
  // No entry is inserted for the overlays with no visual content.
  std::vector<std::pair<raw_ptr<IUnknown>, size_t>> map_results;
  // For each overlay populate |map_results| with visual content and indices
  // of overlays from this frame and find the matching subtree from the
  // previous frame.
  for (size_t i = 0; i < overlays.size(); i++) {
    if (!overlays[i].overlay_image) {
      continue;
    }
    IUnknown* dcomp_visual_content =
        overlays[i].overlay_image->dcomp_visual_content();
    if (!dcomp_visual_content) {
      continue;
    }
    map_results.emplace_back(dcomp_visual_content, i);

    // Find matching visual content from the previous frame.
    auto it = subtree_map_.find(dcomp_visual_content);
    if (it == subtree_map_.end()) {
      continue;
    }
    size_t matched_index = it->second;
    if (visual_subtrees_[matched_index]) {
      // Assign the matched index to the corresponding overlay.
      overlay_index_to_reused_subtree[i] = matched_index;
      // Assign overlay index to the matched subtree.
      subtree_index_to_overlay[matched_index] = i;
      // Move visual subtree from the old subtrees to new subtrees.
      new_visual_subtrees[i] = std::move(visual_subtrees_[matched_index]);
    }
  }
  // This converts to a flat_map on returning. We're doing this on purpose to
  // go from O(N^2) to O(N*logN) for building the map.
  return map_results;
}

size_t DCLayerTree::VisualTree::ReuseUnmatchedSubtrees(
    std::vector<std::unique_ptr<VisualSubtree>>& new_visual_subtrees,
    std::vector<std::optional<size_t>>& overlay_index_to_reused_subtree,
    std::vector<std::optional<size_t>>& subtree_index_to_overlay) {
  CHECK_EQ(new_visual_subtrees.size(), overlay_index_to_reused_subtree.size());
  CHECK_EQ(subtree_index_to_overlay.size(), visual_subtrees_.size());

  // No further actions are needed if the previous frame is empty.
  if (visual_subtrees_.empty()) {
    return 0;
  }
  // Index into |visual_subtrees_|.
  size_t prev_frame_subtree_index = 0;
  // Assign unused subtrees from previous frames to overlays that don't have
  // a match.
  for (size_t i = 0; i < new_visual_subtrees.size() &&
                     prev_frame_subtree_index < visual_subtrees_.size();
       i++) {
    if (new_visual_subtrees[i]) {
      // Skip overlay that has a match.
      continue;
    }
    // Find next unused subtree and assign it to the overlay at index |i|.
    for (; prev_frame_subtree_index < visual_subtrees_.size();
         prev_frame_subtree_index++) {
      if (!visual_subtrees_[prev_frame_subtree_index]) {
        continue;
      }
      // Assign the found index to the corresponding overlay.
      overlay_index_to_reused_subtree[i] = prev_frame_subtree_index;
      // Assign the overlay index to the found subtree.
      subtree_index_to_overlay[prev_frame_subtree_index] = i;
      // Move visual subtree from the old subtrees to new subtrees.
      new_visual_subtrees[i] =
          std::move(visual_subtrees_[prev_frame_subtree_index]);
      prev_frame_subtree_index++;
      break;
    }
  }
  return prev_frame_subtree_index;
}

bool DCLayerTree::VisualTree::DetachUnusedSubtreesFromRoot(
    size_t first_prev_frame_subtree_unused_index,
    std::vector<bool>& prev_subtree_is_attached_to_root) {
  CHECK_EQ(prev_subtree_is_attached_to_root.size(), visual_subtrees_.size());
  bool needs_commit = false;
  // Detach the remaining unused subtrees from the root.
  for (size_t i = first_prev_frame_subtree_unused_index;
       i < visual_subtrees_.size(); i++) {
    if (!visual_subtrees_[i]) {
      continue;
    }
    DetachSubtreeFromRoot(visual_subtrees_[i].get());
    prev_subtree_is_attached_to_root[i] = false;
    needs_commit = true;
  }
  return needs_commit;
}

bool DCLayerTree::VisualTree::DetachReusedSubtreesThatNeedRepositioningFromRoot(
    const std::vector<std::unique_ptr<VisualSubtree>>& new_visual_subtrees,
    const std::vector<std::optional<size_t>>& overlay_index_to_reused_subtree,
    const std::vector<std::optional<size_t>>& subtree_index_to_overlay,
    std::vector<bool>& prev_subtree_is_attached_to_root) {
  CHECK_EQ(new_visual_subtrees.size(), overlay_index_to_reused_subtree.size());
  CHECK_EQ(subtree_index_to_overlay.size(), visual_subtrees_.size());
  CHECK_EQ(prev_subtree_is_attached_to_root.size(), visual_subtrees_.size());

  // No further actions are needed if the previous frame is empty.
  if (visual_subtrees_.empty()) {
    return false;
  }
  bool needs_commit = false;
  // Index into |visual_subtrees_|.
  size_t prev_frame_subtree_index = 0;
  // This loop walks the overlay indices and detaches from the root any
  // subtrees that need repositioning in the current frame.
  for (size_t i = 0; i < overlay_index_to_reused_subtree.size(); i++) {
    if (!overlay_index_to_reused_subtree[i]) {
      continue;
    }
    size_t reused_subtree_index = overlay_index_to_reused_subtree[i].value();
    DCHECK_EQ(i, subtree_index_to_overlay[reused_subtree_index].value());
    // If the overlay at index |i| has a match, detach from the root any
    // subtrees that appear before the matching subtree and the previous match.
    for (; prev_frame_subtree_index < reused_subtree_index;
         prev_frame_subtree_index++) {
      if (!prev_subtree_is_attached_to_root[prev_frame_subtree_index]) {
        continue;
      }
      VisualSubtree* subtree =
          new_visual_subtrees[subtree_index_to_overlay[prev_frame_subtree_index]
                                  .value()]
              .get();
      DetachSubtreeFromRoot(subtree);
      prev_subtree_is_attached_to_root[prev_frame_subtree_index] = false;
      needs_commit = true;
    }
    if (reused_subtree_index == prev_frame_subtree_index) {
      ++prev_frame_subtree_index;
    }
  }
  return needs_commit;
}

void DCLayerTree::VisualTree::DetachSubtreeFromRoot(VisualSubtree* subtree) {
  HRESULT hr = dc_layer_tree_->dcomp_root_visual_.Get()->RemoveVisual(
      subtree->container_visual());
  CHECK_EQ(hr, S_OK);
}

DCLayerTree::VisualTree::VisualSubtree*
DCLayerTree::VisualTree::GetFrontMostVisualSubtreeForTesting() const {
  CHECK_IS_TEST();
  return visual_subtrees_.back().get();
}

base::expected<void, CommitError> DCLayerTree::CommitAndClearPendingOverlays(
    std::vector<DCLayerOverlayParams> overlays) {
  TRACE_EVENT1("gpu", "DCLayerTree::CommitAndClearPendingOverlays",
               "num_overlays", overlays.size());

  base::ScopedUmaHistogramTimer scoped_timer(
      "GPU.DirectComposition.CommitAndClearPendingOverlaysDuration",
      base::ScopedUmaHistogramTimer::ScopedHistogramTiming::kMicrosecondTimes);

  // If delegated ink metadata exists for this frame, attempt to make an overlay
  // so that a visual subtree can be created for a delegated ink visual.
  // TODO(crbug.com/335553727) Consider clearing ink_renderer_ when there's no
  // metadata.
  if (pending_delegated_ink_metadata_) {
    Microsoft::WRL::ComPtr<IDXGISwapChain1> root_swap_chain;
    auto it = std::ranges::find(overlays, 0, &DCLayerOverlayParams::z_order);
    if (it != overlays.end() && (*it).overlay_image) {
      Microsoft::WRL::ComPtr<IUnknown> root_visual_content =
          (*it).overlay_image->dcomp_visual_content();
      CHECK(root_visual_content);
      HRESULT hr = root_visual_content.As(&root_swap_chain);
      if (hr == E_NOINTERFACE) {
        DCHECK_EQ(root_swap_chain, nullptr);
      } else {
        CHECK_EQ(S_OK, hr);
        CHECK_NE(root_swap_chain, nullptr);
      }
    }

    if (auto ink_layer = ink_renderer_->MakeDelegatedInkOverlay(
            dcomp_device_.Get(), root_swap_chain.Get(),
            std::move(pending_delegated_ink_metadata_))) {
      overlays.push_back(std::move(*ink_layer));
    }
  }

  // Move unused video swap chains to `unused_video_swap_chains` for potential
  // reuse (when adjacent frames have a videos that have different layer IDs
  // which can sometimes happen when a video's src changes), then cleanup.
  decltype(video_swap_chains_) unused_video_swap_chains;
  {
    // Move all video swap chains to `unused_video_swap_chains` and the move
    // ones that are in the current frame back into `video_swap_chains_`.
    unused_video_swap_chains = std::move(video_swap_chains_);

    // We may be moving up to all of the swap chains back.
    video_swap_chains_.reserve(unused_video_swap_chains.size());

    size_t num_swap_chain_presenters = 0;
    for (auto& overlay : overlays) {
      if (NeedSwapChainPresenter(overlay)) {
        auto reused_video_swap_chain_it =
            unused_video_swap_chains.find(overlay.layer_id);
        if (reused_video_swap_chain_it != unused_video_swap_chains.end()) {
          video_swap_chains_.insert(std::move(*reused_video_swap_chain_it));
          unused_video_swap_chains.erase(reused_video_swap_chain_it);
        }
        num_swap_chain_presenters++;
      }
    }

    // If there are more videos this frame, reserve enough space for them.
    video_swap_chains_.reserve(num_swap_chain_presenters);
  }

  bool did_update_primary_plane_damage = false;
  bool need_background_layer = false;

  // Populate |overlays| with information required to build dcomp visual tree.
  for (auto it = overlays.begin(); it != overlays.end(); it++) {
    auto& overlay = *it;
    if (NeedSwapChainPresenter(overlay)) {
      // Present to swap chain and update the overlay with transform, clip
      // and content.
      auto& video_swap_chain = video_swap_chains_[overlay.layer_id];
      if (!video_swap_chain) {
        // TODO(sunnyps): Try to find a matching swap chain based on size, type
        // of swap chain, gl image, etc.
        auto unused_video_swap_chain_it = unused_video_swap_chains.begin();
        if (unused_video_swap_chain_it != unused_video_swap_chains.end()) {
          video_swap_chain = std::move(unused_video_swap_chain_it->second);
          unused_video_swap_chains.erase(unused_video_swap_chain_it);
        } else {
          video_swap_chain = std::make_unique<SwapChainPresenter>(
              this, d3d11_device_, dcomp_device_);
        }
      }

      std::optional<SwapChainPresenter::OverlayPositionAdjustment>
          overlay_position_adjustment;
      if (std::optional<DCLayerOverlayImage> video_image =
              video_swap_chain->PresentToSwapChain(
                  overlay, overlay_position_adjustment)) {
        overlay.overlay_image = std::move(video_image);
        overlay.content_rect = gfx::RectF(overlay.overlay_image->size());

        if (overlay_position_adjustment) {
          overlay.transform.MakeIdentity();
          overlay.quad_rect =
              gfx::Rect(overlay_position_adjustment->monitor_size);
          if (overlay.clip_rect) {
            overlay.clip_rect =
                gfx::Rect(overlay_position_adjustment->monitor_size);
          }
        }

        if (overlay.video_params.is_full_screen_video &&
            !overlay_position_adjustment) {
          // If we failed to disable the desktop plane, we need to manually add
          // a solid color layer to act as the video background mat.
          need_background_layer = true;
        }
      } else {
        DLOG(ERROR) << "PresentToSwapChain failed";
        return base::unexpected(
            CommitError{CommitError::Reason::kPresentToSwapChain});
      }

      if (tint_video_layer_) {
        SkColor4f tint_color;
        switch (video_swap_chain->GetLastPresentationMode()) {
          case SwapChainPresenter::PresentationMode::kDecodeSwapChain:
            tint_color = SkColors::kBlue;
            break;
          case SwapChainPresenter::PresentationMode::kVpBlt:
            tint_color = SkColors::kMagenta;
            break;
          case SwapChainPresenter::PresentationMode::kVpBltWithStagingTexture:
            tint_color = SkColor4f(1.0, 0.5, 0.0, 1.0);
            break;
          case SwapChainPresenter::PresentationMode::kMfSurfaceProxy:
            tint_color = SkColors::kGreen;
            break;
        }

        DCLayerOverlayParams tint_overlay;
        tint_overlay.quad_rect = it->quad_rect;
        tint_overlay.transform = it->transform;
        tint_overlay.clip_rect = it->clip_rect;
        tint_overlay.rounded_corner_bounds = it->rounded_corner_bounds;
        tint_overlay.z_order = it->z_order;
        tint_overlay.opacity = 0.25;
        tint_overlay.background_color = tint_color;
        tint_overlay.layer_id =
            it->layer_id.MakeForChildOfSharedQuadStateLayer(1);
        it = overlays.insert(std::next(it), std::move(tint_overlay));
        // Do not access `overlay` after this point since it is invalidated.
      }
    } else if (primary_plane_surface_) {
      // If supported, "present" the primary plane buffer to a surface with
      // incremental damage.
      if (overlay.z_order == 0 && overlay.overlay_image) {
        if (Microsoft::WRL::ComPtr<IDCompositionTexture> dcomp_texture;
            SUCCEEDED(Microsoft::WRL::ComPtr<IUnknown>(
                          overlay.overlay_image->dcomp_visual_content())
                          .As(&dcomp_texture))) {
          DVLOG(1) << "Set primary_plane_surface_ damage: "
                   << overlay.damage_rect.ToString();

          const RECT damage_rect =
              gfx::ToEnclosingRect(overlay.damage_rect).ToRECT();
          HRESULT hr = primary_plane_surface_->SetTexture(dcomp_texture.Get(),
                                                          &damage_rect, 1);
          CHECK_EQ(hr, S_OK);

          overlay.overlay_image = DCLayerOverlayImage(
              overlay.overlay_image->size(), primary_plane_surface_,
              primary_plane_surface_serial_++);
          did_update_primary_plane_damage = true;
        } else {
          // Primary plane is not backed by `BufferQueue`.
        }
      } else {
        // Overlay is not the primary plane.
      }
    }
  }

  if (primary_plane_surface_ && primary_plane_surface_serial_ &&
      !did_update_primary_plane_damage) {
    // We need to commit the visual tree after `SetTexture`. We expect the
    // primary plane overlay to be removed from the visual tree this frame,
    // which will cause commit to happen.
    DVLOG(1) << "Reset primary_plane_surface_ damage.";
    primary_plane_surface_->SetTexture(nullptr);
    primary_plane_surface_serial_ = 0;
  }

  if (need_background_layer) {
    DCLayerOverlayParams background_mat;
    background_mat.quad_rect = gfx::Rect(GetMonitorSizeForWindow(window()));
    background_mat.z_order = INT_MIN;
    background_mat.background_color = SkColors::kBlack;
    background_mat.layer_id = gfx::OverlayLayerId::MakeVizInternal(
        gfx::OverlayLayerId::VizInternalId::kBackgroundColorLayer);
    overlays.insert(overlays.begin(), std::move(background_mat));
  }

  if (!visual_tree_) {
    visual_tree_ = std::make_unique<VisualTree>(this);
  }

  const base::expected<void, CommitError> status =
      visual_tree_->BuildTree(overlays);

  ink_renderer_->ReportPointsDrawn();

  // Clean up excess surfaces so the pool will not grow unbounded.
  solid_color_surface_pool_->TrimAfterCommit();

  return status;
}

bool DCLayerTree::SupportsDelegatedInk() {
  return ink_renderer_->DelegatedInkIsSupported(dcomp_device_);
}

void DCLayerTree::SetDelegatedInkTrailStartPoint(
    std::unique_ptr<gfx::DelegatedInkMetadata> metadata) {
  DCHECK(SupportsDelegatedInk());
  pending_delegated_ink_metadata_ = std::move(metadata);
}

void DCLayerTree::InitDelegatedInkPointRendererReceiver(
    mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
        pending_receiver) {
  DCHECK(SupportsDelegatedInk());

  ink_renderer_->InitMessagePipeline(std::move(pending_receiver));
}

// Return properties of non root swap chain at given index.
void DCLayerTree::GetSwapChainVisualInfoForTesting(
    const gfx::OverlayLayerId& layer_id,
    gfx::Transform* out_transform,
    gfx::Point* out_offset,
    gfx::Rect* out_clip_rect) const {
  CHECK_IS_TEST();
  visual_tree_->GetSwapChainVisualInfoForTesting(  // IN-TEST
      layer_id, out_transform, out_offset, out_clip_rect);
}

size_t DCLayerTree::GetSwapChainPresenterCountForTesting() const {
  CHECK_IS_TEST();
  return video_swap_chains_.size();
}

size_t DCLayerTree::GetDcompLayerCountForTesting() const {
  CHECK_IS_TEST();
  return visual_tree_->GetDcompLayerCountForTesting();  // IN-TEST
}

IDCompositionVisual2* DCLayerTree::GetContentVisualForTesting(
    const gfx::OverlayLayerId& layer_id) const {
  CHECK_IS_TEST();
  return visual_tree_->GetContentVisualForTesting(layer_id);  // IN-TEST
}

IDCompositionSurface* DCLayerTree::GetBackgroundColorSurfaceForTesting(
    const gfx::OverlayLayerId& layer_id) const {
  CHECK_IS_TEST();
  return visual_tree_->GetBackgroundColorSurfaceForTesting(  // IN-TEST
      layer_id);
}

size_t DCLayerTree::GetNumSurfacesInPoolForTesting() const {
  CHECK_IS_TEST();
  return solid_color_surface_pool_
      ->GetNumSurfacesInPoolForTesting();  // IN-TEST
}

#if DCHECK_IS_ON()
bool DCLayerTree::DcompVisualContentChangedFromPreviousFrameForTesting(
    const gfx::OverlayLayerId& layer_id) const {
  CHECK_IS_TEST();
  return visual_tree_
      ->DcompVisualContentChangedFromPreviousFrameForTesting(  // IN-TEST
          layer_id);
}
#endif  // DCHECK_IS_ON()

const DCLayerTree::VisualTree::VisualSubtree*
DCLayerTree::VisualTree::GetSubtreeFromLayerIdForTesting(
    const gfx::OverlayLayerId& layer_id) const {
  CHECK_IS_TEST();
  const auto it = std::ranges::find(layer_ids_for_testing_, layer_id);
  CHECK(it != layer_ids_for_testing_.end());
  const size_t index =
      std::ranges::distance(layer_ids_for_testing_.begin(), it);
  return visual_subtrees_.at(index).get();
}

// Return properties of non root swap chain at given index.
void DCLayerTree::VisualTree::GetSwapChainVisualInfoForTesting(
    const gfx::OverlayLayerId& layer_id,
    gfx::Transform* out_transform,
    gfx::Point* out_offset,
    gfx::Rect* out_clip_rect) const {
  CHECK_IS_TEST();
  return GetSubtreeFromLayerIdForTesting(layer_id)                   // IN-TEST
      ->GetSwapChainVisualInfoForTesting(out_transform, out_offset,  // IN-TEST
                                         out_clip_rect);
}

size_t DCLayerTree::VisualTree::GetDcompLayerCountForTesting() const {
  CHECK_IS_TEST();
  return visual_subtrees_.size();
}

IDCompositionVisual2* DCLayerTree::VisualTree::GetContentVisualForTesting(
    const gfx::OverlayLayerId& layer_id) const {
  CHECK_IS_TEST();
  return GetSubtreeFromLayerIdForTesting(layer_id)  // IN-TEST
      ->container_visual();
}

IDCompositionSurface*
DCLayerTree::VisualTree::GetBackgroundColorSurfaceForTesting(
    const gfx::OverlayLayerId& layer_id) const {
  CHECK_IS_TEST();
  return GetSubtreeFromLayerIdForTesting(layer_id)  // IN-TEST
      ->background_color_surface_for_testing();     // IN-TEST
}

#if DCHECK_IS_ON()
bool DCLayerTree::VisualTree::
    DcompVisualContentChangedFromPreviousFrameForTesting(
        const gfx::OverlayLayerId& layer_id) const {
  CHECK_IS_TEST();
  return GetSubtreeFromLayerIdForTesting(layer_id)               // IN-TEST
      ->DcompVisualContentChangedFromPreviousFrameForTesting();  // IN-TEST
}
#endif  // DCHECK_IS_ON()

}  // namespace gl
