// Copyright 2019 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/camera/drivers/hw_accel/task/task.h"

#include <fuchsia/sysmem/c/fidl.h>
#include <lib/syslog/global.h>
#include <stdint.h>
#include <zircon/pixelformat.h>
#include <zircon/types.h>

#include <memory>

constexpr auto kTag = "GenericTask";

namespace generictask {

// Validates the buffer collection.
static bool IsBufferCollectionValid(const buffer_collection_info_2_t* buffer_collection,
                                    const image_format_2_t* image_format) {
  return !(buffer_collection == nullptr || buffer_collection->buffer_count == 0 ||
           (image_format->pixel_format.type != fuchsia_sysmem_PixelFormatType_NV12 &&
            image_format->pixel_format.type != fuchsia_sysmem_PixelFormatType_R8G8B8A8));
}

zx_status_t GenericTask::GetInputBufferPhysAddr(uint32_t input_buffer_index,
                                                zx_paddr_t* out) const {
  if (input_buffer_index >= input_buffers_.size() || out == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }
  *out = input_buffers_[input_buffer_index].region(0).phys_addr;

  return ZX_OK;
}

zx_status_t GenericTask::GetInputBufferPhysSize(uint32_t input_buffer_index, uint64_t* out) const {
  if (input_buffer_index >= input_buffers_.size() || out == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }
  *out = input_buffers_[input_buffer_index].region(0).size;
  return ZX_OK;
}

zx_status_t GenericTask::InitBuffers(const buffer_collection_info_2_t* input_buffer_collection,
                                     const buffer_collection_info_2_t* output_buffer_collection,
                                     const image_format_2_t* input_image_format_table_list,
                                     size_t input_image_format_table_count,
                                     uint32_t input_image_format_index,
                                     const image_format_2_t* output_image_format_table_list,
                                     size_t output_image_format_table_count,
                                     uint32_t output_image_format_index, const zx::bti& bti,
                                     const hw_accel_frame_callback_t* frame_callback,
                                     const hw_accel_res_change_callback_t* res_callback,
                                     const hw_accel_remove_task_callback_t* remove_task_callback) {
  if (!IsBufferCollectionValid(output_buffer_collection,
                               &output_image_format_table_list[output_image_format_index])) {
    return ZX_ERR_INVALID_ARGS;
  }

  // Make a copy of the output image_format_table.
  output_image_format_list_ = std::make_unique<image_format_2_t[]>(output_image_format_table_count);
  for (uint32_t i = 0; i < output_image_format_table_count; i++) {
    output_image_format_list_.get()[i] = output_image_format_table_list[i];
  }
  output_image_format_count_ = output_image_format_table_count;
  cur_output_image_format_index_ = output_image_format_index;

  // Initialize the VMOPool and pin the output buffers
  zx::vmo output_vmos[output_buffer_collection->buffer_count];
  for (uint32_t i = 0; i < output_buffer_collection->buffer_count; ++i) {
    output_vmos[i] = zx::vmo(output_buffer_collection->buffers[i].vmo);
  }

  zx_status_t status = output_buffers_.Init(output_vmos, output_buffer_collection->buffer_count);
  if (status != ZX_OK) {
    FX_LOG(ERROR, kTag, "Unable to Init VmoPool");
    return status;
  }

  // Release the vmos so that the buffer collection could be reused.
  for (uint32_t i = 0; i < output_buffer_collection->buffer_count; ++i) {
    // output_buffer_collection already has the handle so its okay to discard
    // this one.
    __UNUSED zx_handle_t vmo = output_vmos[i].release();
  }

  status = output_buffers_.PinVmos(bti, fzl::VmoPool::RequireContig::Yes,
                                   fzl::VmoPool::RequireLowMem::Yes);
  if (status != ZX_OK) {
    FX_LOG(ERROR, kTag, "Unable to pin buffers");
    return status;
  }

  return InitInputBuffers(input_buffer_collection, input_image_format_table_list,
                          input_image_format_table_count, input_image_format_index, bti,
                          frame_callback, res_callback, remove_task_callback);
}

zx_status_t GenericTask::InitInputBuffers(
    const buffer_collection_info_2_t* input_buffer_collection,
    const image_format_2_t* input_image_format_table_list, size_t input_image_format_table_count,
    uint32_t input_image_format_index, const zx::bti& bti,
    const hw_accel_frame_callback_t* frame_callback,
    const hw_accel_res_change_callback_t* res_callback,
    const hw_accel_remove_task_callback_t* remove_task_callback) {
  if (!IsBufferCollectionValid(input_buffer_collection,
                               &input_image_format_table_list[input_image_format_index])) {
    return ZX_ERR_INVALID_ARGS;
  }

  input_image_format_list_ = std::make_unique<image_format_2_t[]>(input_image_format_table_count);
  for (uint32_t i = 0; i < input_image_format_table_count; i++) {
    input_image_format_list_.get()[i] = input_image_format_table_list[i];
  }
  input_image_format_count_ = input_image_format_table_count;
  cur_input_image_format_index_ = input_image_format_index;
  zx_status_t status = ZX_OK;

  // Pin the input buffers.
  input_buffers_ =
      fbl::Array<fzl::PinnedVmo>(new fzl::PinnedVmo[input_buffer_collection->buffer_count],
                                 input_buffer_collection->buffer_count);
  for (uint32_t i = 0; i < input_buffer_collection->buffer_count; ++i) {
    zx::vmo vmo(input_buffer_collection->buffers[i].vmo);
    status = input_buffers_[i].Pin(vmo, bti, ZX_BTI_CONTIGUOUS | ZX_VM_PERM_READ);

    // Release the vmos so that the buffer collection could be reused.
    // input_buffer_collection already has the handle so its okay to discard
    // this one.
    __UNUSED zx_handle_t handle = vmo.release();

    if (status != ZX_OK) {
      FX_LOG(ERROR, kTag, "Unable to pin buffers");
      return status;
    }
    if (input_buffers_[i].region_count() != 1) {
      FX_LOG(ERROR, kTag, "buffer is not contiguous");
      return ZX_ERR_NO_MEMORY;
    }
  }

  frame_callback_ = frame_callback;
  res_callback_ = res_callback;
  remove_task_callback_ = remove_task_callback;

  return status;
}

}  // namespace generictask
