// Copyright 2017 The Chromium 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 "media/gpu/test/local_gpu_memory_buffer_manager.h"

#include <drm_fourcc.h>
#include <gbm.h>
#include <stddef.h>
#include <stdint.h>
#include <xf86drm.h>

#include <vector>

#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/trace_event/memory_allocator_dump_guid.h"
#include "base/trace_event/process_memory_dump.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/buffer_usage_util.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_pixmap_handle.h"

namespace media {

namespace {

const int32_t kDrmNumNodes = 64;
const int32_t kMinNodeNumber = 128;

// TODO(https://crbug.com/1043007): use ui/gfx/linux/gbm_device.h instead.
gbm_device* CreateGbmDevice() {
  int fd;
  int32_t min_node = kMinNodeNumber;
  int32_t max_node = kMinNodeNumber + kDrmNumNodes;
  struct gbm_device* gbm = nullptr;

  for (int i = min_node; i < max_node; i++) {
    fd = drmOpenRender(i);
    if (fd < 0) {
      continue;
    }

    drmVersionPtr version = drmGetVersion(fd);
    if (!strcmp("vgem", version->name)) {
      drmFreeVersion(version);
      close(fd);
      continue;
    }

    gbm = gbm_create_device(fd);
    if (!gbm) {
      drmFreeVersion(version);
      close(fd);
      continue;
    }

    VLOG(1) << "Opened gbm device on render node " << version->name;
    drmFreeVersion(version);
    return gbm;
  }

  return nullptr;
}

uint32_t GetDrmFormat(gfx::BufferFormat gfx_format) {
  switch (gfx_format) {
    case gfx::BufferFormat::R_8:
      return DRM_FORMAT_R8;
    case gfx::BufferFormat::YVU_420:
      return DRM_FORMAT_YVU420;
    case gfx::BufferFormat::YUV_420_BIPLANAR:
      return DRM_FORMAT_NV12;
    // Add more formats when needed.
    default:
      return 0;
  }
}

uint32_t GetGbmUsage(gfx::BufferUsage usage) {
  switch (usage) {
    case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
    case gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE:
      return GBM_BO_USE_LINEAR | GBM_BO_USE_CAMERA_READ |
             GBM_BO_USE_CAMERA_WRITE | GBM_BO_USE_SW_READ_OFTEN;
    case gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE:
      return GBM_BO_USE_LINEAR | GBM_BO_USE_CAMERA_READ |
             GBM_BO_USE_CAMERA_WRITE | GBM_BO_USE_TEXTURING |
             GBM_BO_USE_HW_VIDEO_ENCODER | GBM_BO_USE_SW_READ_OFTEN;
    case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
      return GBM_BO_USE_LINEAR | GBM_BO_USE_SW_READ_OFTEN;
    default:
      return 0;
  }
}

class GpuMemoryBufferImplGbm : public gfx::GpuMemoryBuffer {
 public:
  GpuMemoryBufferImplGbm(gfx::BufferFormat format, gbm_bo* buffer_object)
      : format_(format), buffer_object_(buffer_object), mapped_(false) {
    handle_.type = gfx::NATIVE_PIXMAP;
    // Set a dummy id since this is for testing only.
    handle_.id = gfx::GpuMemoryBufferId(0);

    for (size_t i = 0;
         i < static_cast<size_t>(gbm_bo_get_plane_count(buffer_object)); ++i) {
      handle_.native_pixmap_handle.planes.push_back(gfx::NativePixmapPlane(
          gbm_bo_get_stride_for_plane(buffer_object, i),
          gbm_bo_get_offset(buffer_object, i),
          gbm_bo_get_plane_size(buffer_object, i),
          base::ScopedFD(gbm_bo_get_plane_fd(buffer_object, i))));
    }
  }

  ~GpuMemoryBufferImplGbm() override {
    if (mapped_) {
      Unmap();
    }

    gbm_bo_destroy(buffer_object_);
  }

  bool Map() override {
    if (mapped_) {
      return true;
    }
    size_t num_planes = gbm_bo_get_plane_count(buffer_object_);
    uint32_t stride;
    mapped_planes_.resize(num_planes);
    for (size_t i = 0; i < num_planes; ++i) {
      void* mapped_data;
      void* addr =
          gbm_bo_map2(buffer_object_, 0, 0, gbm_bo_get_width(buffer_object_),
                      gbm_bo_get_height(buffer_object_),
                      GBM_BO_TRANSFER_READ_WRITE, &stride, &mapped_data, i);
      if (!addr) {
        LOG(ERROR) << "Failed to map GpuMemoryBufferImplGbm plane " << i;
        Unmap();
        return false;
      }
      mapped_planes_[i].addr = addr;
      mapped_planes_[i].mapped_data = mapped_data;
    }
    mapped_ = true;
    return true;
  }

  void* memory(size_t plane) override {
    if (!mapped_) {
      LOG(ERROR) << "Buffer is not mapped";
      return nullptr;
    }
    if (plane > mapped_planes_.size()) {
      LOG(ERROR) << "Invalid plane: " << plane;
      return nullptr;
    }
    return mapped_planes_[plane].addr;
  }

  void Unmap() override {
    for (size_t i = 0; i < mapped_planes_.size(); ++i) {
      if (mapped_planes_[i].addr) {
        gbm_bo_unmap(buffer_object_, mapped_planes_[i].mapped_data);
        mapped_planes_[i].addr = nullptr;
        mapped_planes_[i].mapped_data = nullptr;
      }
    }
    mapped_planes_.clear();
    mapped_ = false;
  }

  gfx::Size GetSize() const override {
    return gfx::Size(gbm_bo_get_width(buffer_object_),
                     gbm_bo_get_height(buffer_object_));
  }

  gfx::BufferFormat GetFormat() const override { return format_; }

  int stride(size_t plane) const override {
    return gbm_bo_get_stride_for_plane(buffer_object_, plane);
  }

  void SetColorSpace(const gfx::ColorSpace& color_space) override {}

  gfx::GpuMemoryBufferId GetId() const override { return handle_.id; }

  gfx::GpuMemoryBufferType GetType() const override {
    return gfx::NATIVE_PIXMAP;
  }

  gfx::GpuMemoryBufferHandle CloneHandle() const override {
    DCHECK_EQ(handle_.type, gfx::NATIVE_PIXMAP);
    gfx::GpuMemoryBufferHandle handle;
    handle.type = gfx::NATIVE_PIXMAP;
    handle.id = handle_.id;
    handle.native_pixmap_handle =
        gfx::CloneHandleForIPC(handle_.native_pixmap_handle);
    return handle;
  }

  ClientBuffer AsClientBuffer() override {
    return reinterpret_cast<ClientBuffer>(this);
  }

  void OnMemoryDump(
      base::trace_event::ProcessMemoryDump* pmd,
      const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
      uint64_t tracing_process_id,
      int importance) const override {
    auto shared_buffer_guid = gfx::GetGenericSharedGpuMemoryGUIDForTracing(
        tracing_process_id, GetId());
    pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid);
    pmd->AddOwnershipEdge(buffer_dump_guid, shared_buffer_guid, importance);
  }

 private:
  struct MappedPlane {
    void* addr;
    void* mapped_data;
  };

  gfx::BufferFormat format_;
  gbm_bo* buffer_object_;
  gfx::GpuMemoryBufferHandle handle_;
  bool mapped_;
  std::vector<MappedPlane> mapped_planes_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(GpuMemoryBufferImplGbm);
};

}  // namespace

LocalGpuMemoryBufferManager::LocalGpuMemoryBufferManager()
    : gbm_device_(CreateGbmDevice()) {}

LocalGpuMemoryBufferManager::~LocalGpuMemoryBufferManager() {
  if (gbm_device_) {
    close(gbm_device_get_fd(gbm_device_));
    gbm_device_destroy(gbm_device_);
  }
}

std::unique_ptr<gfx::GpuMemoryBuffer>
LocalGpuMemoryBufferManager::CreateGpuMemoryBuffer(
    const gfx::Size& size,
    gfx::BufferFormat format,
    gfx::BufferUsage usage,
    gpu::SurfaceHandle surface_handle,
    base::WaitableEvent* shutdown_event) {
  if (!gbm_device_) {
    LOG(ERROR) << "Invalid GBM device";
    return nullptr;
  }

  const uint32_t drm_format = GetDrmFormat(format);
  if (!drm_format) {
    LOG(ERROR) << "Unable to convert gfx::BufferFormat "
               << static_cast<int>(format) << " to DRM format";
    return nullptr;
  }

  const uint32_t gbm_usage = GetGbmUsage(usage);
  if (gbm_usage == 0) {
    LOG(ERROR) << "Unsupported usage " << gfx::BufferUsageToString(usage);
    return nullptr;
  }

  if (!gbm_device_is_format_supported(gbm_device_, drm_format, gbm_usage)) {
    return nullptr;
  }

  gbm_bo* buffer_object = gbm_bo_create(gbm_device_, size.width(),
                                        size.height(), drm_format, gbm_usage);
  if (!buffer_object) {
    LOG(ERROR) << "Failed to create GBM buffer object";
    return nullptr;
  }

  return std::make_unique<GpuMemoryBufferImplGbm>(format, buffer_object);
}

void LocalGpuMemoryBufferManager::SetDestructionSyncToken(
    gfx::GpuMemoryBuffer* buffer,
    const gpu::SyncToken& sync_token) {}

void LocalGpuMemoryBufferManager::CopyGpuMemoryBufferAsync(
    gfx::GpuMemoryBufferHandle buffer_handle,
    base::UnsafeSharedMemoryRegion memory_region,
    base::OnceCallback<void(bool)> callback) {
  std::move(callback).Run(false);
}

bool LocalGpuMemoryBufferManager::CopyGpuMemoryBufferSync(
    gfx::GpuMemoryBufferHandle buffer_handle,
    base::UnsafeSharedMemoryRegion memory_region) {
  return false;
}

std::unique_ptr<gfx::GpuMemoryBuffer> LocalGpuMemoryBufferManager::ImportDmaBuf(
    const gfx::NativePixmapHandle& handle,
    const gfx::Size& size,
    gfx::BufferFormat format) {
  if (handle.planes.size() !=
      gfx::NumberOfPlanesForLinearBufferFormat(format)) {
    // This could happen if e.g., we get a compressed RGBA buffer where one
    // plane is for metadata. We don't support this case.
    LOG(ERROR) << "Cannot import " << gfx::BufferFormatToString(format)
               << " with " << handle.planes.size() << " plane(s) (expected "
               << gfx::NumberOfPlanesForLinearBufferFormat(format)
               << " plane(s))";
    return nullptr;
  }
  const uint32_t drm_format = GetDrmFormat(format);
  if (!drm_format) {
    LOG(ERROR) << "Unsupported format " << gfx::BufferFormatToString(format);
    return nullptr;
  }
  gbm_import_fd_modifier_data import_data{
      base::checked_cast<uint32_t>(size.width()),
      base::checked_cast<uint32_t>(size.height()), drm_format,
      base::checked_cast<uint32_t>(handle.planes.size())};
  for (size_t plane = 0; plane < handle.planes.size(); plane++) {
    if (!handle.planes[plane].fd.is_valid()) {
      LOG(ERROR) << "Invalid file descriptor for plane " << plane;
      return nullptr;
    }
    import_data.fds[plane] = handle.planes[plane].fd.get();
    import_data.strides[plane] =
        base::checked_cast<int>(handle.planes[plane].stride);
    import_data.offsets[plane] =
        base::checked_cast<int>(handle.planes[plane].offset);
  }
  import_data.modifier = handle.modifier;
  gbm_bo* buffer_object = gbm_bo_import(gbm_device_, GBM_BO_IMPORT_FD_MODIFIER,
                                        &import_data, GBM_BO_USE_SW_READ_OFTEN);
  if (!buffer_object) {
    PLOG(ERROR) << "Could not import the DmaBuf into gbm";
    return nullptr;
  }
  return std::make_unique<GpuMemoryBufferImplGbm>(format, buffer_object);
}

bool LocalGpuMemoryBufferManager::IsFormatAndUsageSupported(
    gfx::BufferFormat format,
    gfx::BufferUsage usage) {
  const uint32_t drm_format = GetDrmFormat(format);
  if (!drm_format)
    return false;
  const uint32_t gbm_usage = GetGbmUsage(usage);
  if (gbm_usage == 0)
    return false;
  return gbm_device_is_format_supported(gbm_device_, drm_format, gbm_usage);
}

}  // namespace media
