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

#include "src/virtualization/bin/vmm/controller/virtio_gpu.h"

namespace {

constexpr auto kComponentName = "virtio_gpu";
constexpr auto kComponentCollectionName = "virtio_gpu_devices";
constexpr auto kComponentUrl = "#meta/virtio_gpu.cm";

}  // namespace

VirtioGpu::VirtioGpu(const PhysMem& phys_mem)
    : VirtioComponentDevice("Virtio GPU", phys_mem, 0 /* device_features */,
                            fit::bind_member(this, &VirtioGpu::ConfigureQueue),
                            fit::bind_member(this, &VirtioGpu::Ready)) {
  config_.num_scanouts = 1;
}

zx_status_t VirtioGpu::Start(
    const zx::guest& guest,
    fidl::InterfaceHandle<fuchsia::ui::input3::KeyboardListener> keyboard_listener,
    fidl::InterfaceRequest<fuchsia::ui::pointer::MouseSource> mouse_source,
    ::sys::ComponentContext* context, async_dispatcher_t* dispatcher) {
  auto [client_end, server_end] =
      fidl::Endpoints<fuchsia_virtualization_hardware::VirtioGpu>::Create();
  fidl::InterfaceRequest<fuchsia::virtualization::hardware::VirtioGpu> gpu_request(
      server_end.TakeChannel());
  gpu_.Bind(std::move(client_end), dispatcher, this);

  zx_status_t status =
      CreateDynamicComponent(context, kComponentCollectionName, kComponentName, kComponentUrl,
                             [gpu_request = std::move(gpu_request)](
                                 std::shared_ptr<sys::ServiceDirectory> services) mutable {
                               return services->Connect(std::move(gpu_request));
                             });
  if (status != ZX_OK) {
    return status;
  }
  fuchsia_virtualization_hardware::wire::StartInfo start_info;
  status = PrepStart(guest, dispatcher, &start_info);
  if (status != ZX_OK) {
    return status;
  }

  fidl::ClientEnd<fuchsia_ui_input3::KeyboardListener> llcpp_keyboard_listener(
      keyboard_listener.TakeChannel());
  fidl::ServerEnd<fuchsia_ui_pointer::MouseSource> llcpp_mouse_source(mouse_source.TakeChannel());
  return gpu_.sync()
      ->Start(std::move(start_info), std::move(llcpp_keyboard_listener),
              std::move(llcpp_mouse_source))
      .status();
}

zx_status_t VirtioGpu::ConfigureQueue(uint16_t queue, uint16_t size, zx_gpaddr_t desc,
                                      zx_gpaddr_t avail, zx_gpaddr_t used) {
  return gpu_.sync()->ConfigureQueue(queue, size, desc, avail, used).status();
}

zx_status_t VirtioGpu::Ready(uint32_t negotiated_features) {
  State prev_state = state_;
  state_ = State::READY;
  if (prev_state == State::CONFIG_READY) {
    OnConfigChanged();
  }
  return gpu_.sync()->Ready(negotiated_features).status();
}

void VirtioGpu::on_fidl_error(fidl::UnbindInfo error) {
  FX_LOGS(ERROR) << "Connection to VirtioGpu lost: " << error;
}

void VirtioGpu::OnConfigChanged() {
  if (state_ != State::READY) {
    state_ = State::CONFIG_READY;
    return;
  }
  {
    std::lock_guard<std::mutex> lock(device_config_.mutex);
    config_.events_read |= VIRTIO_GPU_EVENT_DISPLAY;
  }
  // Send a config change interrupt to the guest.
  zx_status_t status = Interrupt(VirtioQueue::SET_CONFIG | VirtioQueue::TRY_INTERRUPT);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to generate configuration interrupt " << status;
  }
}
