// Copyright 2018 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 "lib/framebuffer/framebuffer.h"

#include <errno.h>
#include <fcntl.h>
#include <fuchsia/hardware/display/llcpp/fidl.h>
#include <fuchsia/sysmem/llcpp/fidl.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/coding.h>
#include <lib/fit/defer.h>
#include <lib/image-format-llcpp/image-format-llcpp.h>
#include <lib/image-format/image_format.h>
#include <lib/zx/vmo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/pixelformat.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <variant>

#include <ddk/protocol/display/controller.h>
#include <fbl/unique_fd.h>

namespace fhd = ::llcpp::fuchsia::hardware::display;
namespace sysmem = ::llcpp::fuchsia::sysmem;

static zx_handle_t device_handle = ZX_HANDLE_INVALID;

std::unique_ptr<fhd::Controller::SyncClient> dc_client;
std::unique_ptr<sysmem::Allocator::SyncClient> sysmem_allocator;

static uint64_t display_id;
static uint64_t layer_id;

static int32_t width;
static int32_t height;
static int32_t stride;
static zx_pixel_format_t format;
static bool type_set;
static uint32_t image_type;

static zx_handle_t vmo = ZX_HANDLE_INVALID;

static bool inited = false;
static bool in_single_buffer_mode;

static zx_status_t fb_import_image(uint64_t collection_id, uint32_t index, uint32_t type,
                                   uint64_t* id_out);

// Always import to collection id 1.
static const uint32_t kCollectionId = 1;

// Presents the image identified by |image_id|.
//
// If |wait_event_id| corresponds to an imported event, then driver will wait for
// for ZX_EVENT_SIGNALED before using the buffer. If |signal_event_id| corresponds
// to an imported event, then the driver will signal ZX_EVENT_SIGNALED when it is
// done with the image.
static zx_status_t fb_present_image(uint64_t image_id, uint64_t wait_event_id,
                                    uint64_t signal_event_id);

static zx_status_t set_layer_config(uint64_t layer_id, uint32_t width, uint32_t height,
                                    zx_pixel_format_t format, int32_t type) {
  fhd::ImageConfig config = {
      .width = width,
      .height = height,
      .pixel_format = format,
      .type = static_cast<uint32_t>(type),
  };
  return dc_client->SetLayerPrimaryConfig(layer_id, config).status();
}

template <typename T>
class EndpointOrError {
 public:
  static EndpointOrError<T> Create() {
    zx::channel token_server, token_client;
    zx_status_t status = zx::channel::create(0, &token_server, &token_client);
    if (status != ZX_OK) {
      return EndpointOrError<T>(status);
    }
    return EndpointOrError<T>(std::move(token_server), std::move(token_client));
  }

  EndpointOrError(zx_status_t status) : internal_(status) {}
  EndpointOrError(zx::channel server, zx::channel client)
      : internal_(std::make_pair(std::move(server), T(std::move(client)))) {}

  bool ok() { return internal_.index() == 1; }
  zx_status_t status() { return std::get<0>(internal_); }

  zx::channel TakeServer() { return std::move(std::get<1>(internal_).first); }
  T& operator*() { return std::get<1>(internal_).second; }
  T* operator->() { return &std::get<1>(internal_).second; }

 private:
  std::variant<zx_status_t, std::pair<zx::channel, T>> internal_;
};

#define CHECK_RSP(rsp, err_msg) \
  if (!(rsp).ok()) {            \
    *err_msg_out = err_msg;     \
    return (rsp).status();      \
  }

#define CHECKED_CALL(func, err_msg) \
  {                                 \
    auto rsp = func;                \
    CHECK_RSP(rsp, err_msg);        \
  }

static zx_status_t create_buffer_collection(
    const char** err_msg_out,
    std::unique_ptr<sysmem::BufferCollection::SyncClient>* collection_client) {
  auto token = EndpointOrError<sysmem::BufferCollectionToken::SyncClient>::Create();
  CHECK_RSP(token, "Failed to create collection channel");
  CHECKED_CALL(sysmem_allocator->AllocateSharedCollection(token.TakeServer()),
               "Failed to allocate shared collection");
  auto display_token = EndpointOrError<sysmem::BufferCollectionToken::SyncClient>::Create();
  CHECK_RSP(display_token, "Failed to allocate display token");
  CHECKED_CALL(token->Duplicate(ZX_RIGHT_SAME_RIGHTS, display_token.TakeServer()),
               "Failed to duplicate token");
  CHECKED_CALL(token->Sync(), "Failed to sync token");

  auto import_rsp = dc_client->ImportBufferCollection(kCollectionId,
                                                      std::move(*display_token->mutable_channel()));
  CHECK_RSP(import_rsp, "Failed to import buffer collection");
  if (import_rsp->res != ZX_OK) {
    *err_msg_out = "Import buffer collection error";
    return import_rsp->res;
  }

  fhd::ImageConfig config = {
      .width = static_cast<uint32_t>(width),
      .height = static_cast<uint32_t>(height),
      .pixel_format = format,
      .type = IMAGE_TYPE_SIMPLE,
  };
  auto set_display_constraints = dc_client->SetBufferCollectionConstraints(kCollectionId, config);
  CHECK_RSP(set_display_constraints, "Failed to set display constraints");
  if (set_display_constraints->res != ZX_OK) {
    *err_msg_out = "Display constraints error";
    return set_display_constraints->res;
  }

  auto collection = EndpointOrError<sysmem::BufferCollection::SyncClient>::Create();
  CHECK_RSP(collection, "Failed to create collection channel");

  CHECKED_CALL(sysmem_allocator->BindSharedCollection(std::move(*token->mutable_channel()),
                                                      collection.TakeServer()),
               "Failed to bind collection");

  sysmem::BufferCollectionConstraints constraints;
  constraints.usage.cpu = sysmem::cpuUsageWriteOften | sysmem::cpuUsageRead;
  constraints.min_buffer_count = 1;
  constraints.image_format_constraints_count = 1;
  auto& image_constraints = constraints.image_format_constraints[0];
  image_constraints = image_format::GetDefaultImageFormatConstraints();
  image_constraints.pixel_format.type = sysmem::PixelFormatType::BGRA32;
  image_constraints.pixel_format.has_format_modifier = true;
  image_constraints.pixel_format.format_modifier.value = sysmem::FORMAT_MODIFIER_LINEAR;
  image_constraints.color_spaces_count = 1;
  image_constraints.color_space[0].type = sysmem::ColorSpaceType::SRGB;
  image_constraints.min_coded_width = width;
  image_constraints.min_coded_height = height;
  image_constraints.max_coded_width = 0xffffffff;
  image_constraints.max_coded_height = 0xffffffff;
  image_constraints.min_bytes_per_row = 0;
  image_constraints.max_bytes_per_row = 0xffffffff;

  constraints.has_buffer_memory_constraints = true;
  constraints.buffer_memory_constraints = image_format::GetDefaultBufferMemoryConstraints();
  constraints.buffer_memory_constraints.ram_domain_supported = true;

  collection->SetConstraints(true, constraints);
  *collection_client =
      std::make_unique<sysmem::BufferCollection::SyncClient>(std::move(*collection));
  return ZX_OK;
}

// Not static because this function is also called from unit tests.
zx_status_t fb_bind_with_channel(bool single_buffer, const char** err_msg_out,
                                 zx::channel dc_client_channel);

zx_status_t fb_bind(bool single_buffer, const char** err_msg_out) {
  const char* err_msg;
  if (!err_msg_out) {
    err_msg_out = &err_msg;
  }
  *err_msg_out = "";

  if (inited) {
    *err_msg_out = "framebufer already initialzied";
    return ZX_ERR_ALREADY_BOUND;
  }

  // TODO(stevensd): Don't hardcode display controller 0
  fbl::unique_fd dc_fd(open("/dev/class/display-controller/000", O_RDWR));
  if (!dc_fd) {
    *err_msg_out = "Failed to open display controller";
    return ZX_ERR_NO_RESOURCES;
  }

  zx::channel device_server, device_client;
  zx_status_t status = zx::channel::create(0, &device_server, &device_client);
  if (status != ZX_OK) {
    *err_msg_out = "Failed to create device channel";
    return status;
  }

  zx::channel dc_server, dc_client_channel;
  status = zx::channel::create(0, &dc_server, &dc_client_channel);
  if (status != ZX_OK) {
    *err_msg_out = "Failed to create controller channel";
    return status;
  }

  fdio_cpp::FdioCaller caller(std::move(dc_fd));
  auto open_status = fhd::Provider::Call::OpenController(caller.channel(), std::move(device_server),
                                                         std::move(dc_server));
  if (open_status.status() != ZX_OK) {
    *err_msg_out = "Failed to call service handle";
    return open_status.status();
  }
  if (status != ZX_OK) {
    *err_msg_out = "Failed to open controller";
    return status;
  }

  device_handle = device_client.release();
  return fb_bind_with_channel(single_buffer, err_msg_out, std::move(dc_client_channel));
}

zx_status_t fb_bind_with_channel(bool single_buffer, const char** err_msg_out,
                                 zx::channel dc_client_channel) {
  dc_client = std::make_unique<fhd::Controller::SyncClient>(std::move(dc_client_channel));
  auto close_dc_handle = fit::defer([]() {
    zx_handle_close(device_handle);
    dc_client.reset();
    device_handle = ZX_HANDLE_INVALID;
  });

  zx_status_t status;
  zx::channel sysmem_server, sysmem_client;
  status = zx::channel::create(0, &sysmem_server, &sysmem_client);
  if (status != ZX_OK) {
    *err_msg_out = "Failed to create sysmem channel";
    return status;
  }
  status = fdio_service_connect("/svc/fuchsia.sysmem.Allocator", sysmem_server.release());
  if (status != ZX_OK) {
    *err_msg_out = "Failed to connect to sysmem";
    return status;
  }

  sysmem_allocator = std::make_unique<sysmem::Allocator::SyncClient>(std::move(sysmem_client));
  auto close_sysmem_handle = fit::defer([]() { sysmem_allocator.reset(); });

  class EventHandler : public fhd::Controller::EventHandler {
   public:
    EventHandler() = default;

    zx_pixel_format_t pixel_format() const { return pixel_format_; }
    bool has_display() const { return has_display_; }
    fhd::Mode mode() const { return mode_; }

    void OnDisplaysChanged(fhd::Controller::OnDisplaysChangedResponse* event) override {
      has_display_ = true;
      // We're guaranteed that added contains at least one display, since we haven't
      // been notified of any displays to remove.
      display_id = event->added[0].id;
      mode_ = event->added[0].modes[0];
      pixel_format_ = event->added[0].pixel_format[0];
    }

    void OnVsync(fhd::Controller::OnVsyncResponse* event) override {}

    void OnClientOwnershipChange(fhd::Controller::OnClientOwnershipChangeResponse* event) override {
    }

    zx_status_t Unknown() override { return ZX_ERR_STOP; }

   private:
    zx_pixel_format_t pixel_format_;
    bool has_display_ = false;
    fhd::Mode mode_;
  };

  EventHandler event_handler;
  do {
    ::fidl::Result result = dc_client->HandleOneEvent(event_handler);

    if (!result.ok()) {
      return result.status();
    }
  } while (!event_handler.has_display());

  auto create_layer_rsp = dc_client->CreateLayer();
  if (!create_layer_rsp.ok()) {
    *err_msg_out = "Create layer call failed";
    return create_layer_rsp.status();
  }
  if (create_layer_rsp->res != ZX_OK) {
    *err_msg_out = "Failed to create layer";
    status = create_layer_rsp->res;
    return status;
  }

  auto layers_rsp = dc_client->SetDisplayLayers(
      display_id, fidl::VectorView<uint64_t>(fidl::unowned_ptr(&create_layer_rsp->layer_id), 1));
  if (!layers_rsp.ok()) {
    *err_msg_out = layers_rsp.error();
    return layers_rsp.status();
  }

  if ((status =
           set_layer_config(create_layer_rsp->layer_id, event_handler.mode().horizontal_resolution,
                            event_handler.mode().vertical_resolution, event_handler.pixel_format(),
                            IMAGE_TYPE_SIMPLE)) != ZX_OK) {
    *err_msg_out = "Failed to set layer config";
    return status;
  }

  layer_id = create_layer_rsp->layer_id;

  width = event_handler.mode().horizontal_resolution;
  height = event_handler.mode().vertical_resolution;
  format = event_handler.pixel_format();

  type_set = false;

  inited = true;

  auto clear_inited = fit::defer([]() { inited = false; });

  zx::vmo local_vmo;

  std::unique_ptr<sysmem::BufferCollection::SyncClient> collection_client;

  status = create_buffer_collection(err_msg_out, &collection_client);
  if (status != ZX_OK) {
    return status;
  }

  auto info_result = collection_client->WaitForBuffersAllocated();
  CHECK_RSP(info_result, "Couldn't wait for fidl buffers allocated");
  if (info_result->status != ZX_OK) {
    *err_msg_out = "Couldn't wait for buffers allocated";
    return info_result->status;
  }
  local_vmo = std::move(info_result->buffer_collection_info.buffers[0].vmo);

  uint32_t bytes_per_row;
  bool got_stride = image_format::GetMinimumRowBytes(
      info_result->buffer_collection_info.settings.image_format_constraints, width, &bytes_per_row);

  if (!got_stride) {
    *err_msg_out = "Couldn't get stride";
    return ZX_ERR_INVALID_ARGS;
  }
  stride = bytes_per_row / ZX_PIXEL_FORMAT_BYTES(event_handler.pixel_format());

  // Ignore error.
  collection_client->Close();

  // Failure to set the cache policy isn't a fatal error
  zx_vmo_set_cache_policy(local_vmo.get(), ZX_CACHE_POLICY_WRITE_COMBINING);

  uint64_t image_id;
  if ((status = fb_import_image(kCollectionId, 0, IMAGE_TYPE_SIMPLE, &image_id)) != ZX_OK) {
    *err_msg_out = "Couldn't import framebuffer";
    return status;
  }

  if ((status = fb_present_image(image_id, INVALID_ID, INVALID_ID)) != ZX_OK) {
    *err_msg_out = "Failed to present single_buffer mode framebuffer";
    return status;
  }

  in_single_buffer_mode = single_buffer;

  clear_inited.cancel();
  vmo = local_vmo.release();
  close_dc_handle.cancel();
  close_sysmem_handle.cancel();

  return ZX_OK;
}

void fb_release() {
  if (!inited) {
    return;
  }

  dc_client->ReleaseBufferCollection(kCollectionId);

  zx_handle_close(device_handle);
  dc_client.reset();
  sysmem_allocator.reset();
  device_handle = ZX_HANDLE_INVALID;

  if (in_single_buffer_mode) {
    zx_handle_close(vmo);
    vmo = ZX_HANDLE_INVALID;
  }

  inited = false;
}

void fb_get_config(uint32_t* width_out, uint32_t* height_out, uint32_t* linear_stride_px_out,
                   zx_pixel_format_t* format_out) {
  ZX_ASSERT(inited);

  *width_out = width;
  *height_out = height;
  *format_out = format;
  *linear_stride_px_out = stride;
}

zx_handle_t fb_get_single_buffer() {
  ZX_ASSERT(inited && in_single_buffer_mode);
  return vmo;
}

zx_status_t fb_import_image(uint64_t collection_id, uint32_t index, uint32_t type,
                            uint64_t* id_out) {
  zx_status_t status;

  if (type_set && type != image_type) {
    return ZX_ERR_BAD_STATE;
  } else if (!type_set && type != IMAGE_TYPE_SIMPLE) {
    if ((status = set_layer_config(layer_id, width, height, format, type)) != ZX_OK) {
      return status;
    }
    image_type = type;
    type_set = true;
  }

  fhd::ImageConfig config = {
      .width = static_cast<uint32_t>(width),
      .height = static_cast<uint32_t>(height),
      .pixel_format = format,
      .type = type,
  };

  auto import_rsp = dc_client->ImportImage(config, collection_id, index);
  if (!import_rsp.ok()) {
    return import_rsp.status();
  }

  if (import_rsp->res != ZX_OK) {
    return import_rsp->res;
  }

  *id_out = import_rsp->image_id;
  return ZX_OK;
}

zx_status_t fb_present_image(uint64_t image_id, uint64_t wait_event_id, uint64_t signal_event_id) {
  auto rsp = dc_client->SetLayerImage(layer_id, image_id, wait_event_id, signal_event_id);
  if (!rsp.ok()) {
    return rsp.status();
  }

  return dc_client->ApplyConfig().status();
}
