// Copyright 2018 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 "ui/gfx/linux/gbm_wrapper.h"

#include <gbm.h>
#include <memory>
#include <utility>

#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "skia/ext/legacy_display_globals.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/linux/drm_util_linux.h"
#include "ui/gfx/linux/gbm_buffer.h"
#include "ui/gfx/linux/gbm_device.h"

#if !defined(MINIGBM)
#include <dlfcn.h>
#include <fcntl.h>
#include <xf86drm.h>

#include "base/strings/stringize_macros.h"
#endif

namespace gbm_wrapper {

namespace {

// Function availability can be tested by checking if the address of gbm_* is
// not nullptr.
#define WEAK_GBM_FN(x) extern "C" __attribute__((weak)) decltype(x) x

// TODO(https://crbug.com/784010): Remove these once support for Ubuntu Trusty
// is dropped.
WEAK_GBM_FN(gbm_bo_map);
WEAK_GBM_FN(gbm_bo_unmap);

// TODO(https://crbug.com/784010): Remove these once support for Ubuntu Trusty
// and Debian Stretch are dropped.
WEAK_GBM_FN(gbm_bo_create_with_modifiers);
WEAK_GBM_FN(gbm_bo_get_handle_for_plane);
WEAK_GBM_FN(gbm_bo_get_modifier);
WEAK_GBM_FN(gbm_bo_get_offset);
WEAK_GBM_FN(gbm_bo_get_plane_count);
WEAK_GBM_FN(gbm_bo_get_stride_for_plane);

bool HaveGbmMap() {
  return gbm_bo_map && gbm_bo_unmap;
}

bool HaveGbmModifiers() {
  return gbm_bo_create_with_modifiers && gbm_bo_get_modifier;
}

bool HaveGbmMultiplane() {
  return gbm_bo_get_handle_for_plane && gbm_bo_get_offset &&
         gbm_bo_get_plane_count && gbm_bo_get_stride_for_plane;
}

uint32_t GetHandleForPlane(struct gbm_bo* bo, int plane) {
  CHECK(HaveGbmMultiplane() || plane == 0);
  return HaveGbmMultiplane() ? gbm_bo_get_handle_for_plane(bo, plane).u32
                             : gbm_bo_get_handle(bo).u32;
}

uint32_t GetStrideForPlane(struct gbm_bo* bo, int plane) {
  CHECK(HaveGbmMultiplane() || plane == 0);
  return HaveGbmMultiplane() ? gbm_bo_get_stride_for_plane(bo, plane)
                             : gbm_bo_get_stride(bo);
}

uint32_t GetOffsetForPlane(struct gbm_bo* bo, int plane) {
  CHECK(HaveGbmMultiplane() || plane == 0);
  return HaveGbmMultiplane() ? gbm_bo_get_offset(bo, plane) : 0;
}

int GetPlaneCount(struct gbm_bo* bo) {
  return HaveGbmMultiplane() ? gbm_bo_get_plane_count(bo) : 1;
}

int GetPlaneFdForBo(gbm_bo* bo, size_t plane) {
#if defined(MINIGBM)
  return gbm_bo_get_plane_fd(bo, plane);
#else
  const int plane_count = GetPlaneCount(bo);
  DCHECK(plane_count > 0 && plane < static_cast<size_t>(plane_count));

  // System linux gbm (or Mesa gbm) does not provide fds per plane basis. Thus,
  // get plane handle and use drm ioctl to get a prime fd out of it avoid having
  // two different branches for minigbm and Mesa gbm here.
  gbm_device* gbm_dev = gbm_bo_get_device(bo);
  int dev_fd = gbm_device_get_fd(gbm_dev);
  DCHECK_GE(dev_fd, 0);

  uint32_t plane_handle = GetHandleForPlane(bo, plane);

  int fd = -1;
  int ret;
  // Use DRM_RDWR to allow the fd to be mappable in another process.
  ret = drmPrimeHandleToFD(dev_fd, plane_handle, DRM_CLOEXEC | DRM_RDWR, &fd);

  // Older DRM implementations blocked DRM_RDWR, but gave a read/write mapping
  // anyways
  if (ret)
    ret = drmPrimeHandleToFD(dev_fd, plane_handle, DRM_CLOEXEC, &fd);

  return ret ? ret : fd;
#endif
}

size_t GetSizeOfPlane(gbm_bo* bo,
                      uint32_t format,
                      const gfx::Size& size,
                      size_t plane) {
#if defined(MINIGBM)
  return gbm_bo_get_plane_size(bo, plane);
#else
  DCHECK(!size.IsEmpty());

  // Get row size of the plane, stride and subsampled height to finally get the
  // size of a plane in bytes.
  const gfx::BufferFormat buffer_format =
      ui::GetBufferFormatFromFourCCFormat(format);
  const base::CheckedNumeric<size_t> stride_for_plane =
      GetStrideForPlane(bo, plane);
  const base::CheckedNumeric<size_t> subsampled_height =
      size.height() /
      gfx::SubsamplingFactorForBufferFormat(buffer_format, plane);

  // Apply subsampling factor to get size in bytes.
  const base::CheckedNumeric<size_t> checked_plane_size =
      subsampled_height * stride_for_plane;

  return checked_plane_size.ValueOrDie();
#endif
}

}  // namespace

class Buffer final : public ui::GbmBuffer {
 public:
  Buffer(struct gbm_bo* bo,
         uint32_t format,
         uint32_t flags,
         uint64_t modifier,
         const gfx::Size& size,
         gfx::NativePixmapHandle handle)
      : bo_(bo),
        format_(format),
        format_modifier_(modifier),
        flags_(flags),
        size_(size),
        handle_(std::move(handle)) {}

  Buffer(const Buffer&) = delete;
  Buffer& operator=(const Buffer&) = delete;

  ~Buffer() override {
    DCHECK(!mmap_data_);
    gbm_bo_destroy(bo_);
  }

  uint32_t GetFormat() const override { return format_; }
  uint64_t GetFormatModifier() const override { return format_modifier_; }
  uint32_t GetFlags() const override { return flags_; }
  // TODO(reveman): This should not be needed once crbug.com/597932 is fixed,
  // as the size would be queried directly from the underlying bo.
  gfx::Size GetSize() const override { return size_; }
  gfx::BufferFormat GetBufferFormat() const override {
    return ui::GetBufferFormatFromFourCCFormat(format_);
  }
  bool AreFdsValid() const override {
    if (handle_.planes.empty())
      return false;

    for (const auto& plane : handle_.planes) {
      if (!plane.fd.is_valid())
        return false;
    }
    return true;
  }
  size_t GetNumPlanes() const override { return handle_.planes.size(); }
  int GetPlaneFd(size_t plane) const override {
    DCHECK_LT(plane, handle_.planes.size());
    return handle_.planes[plane].fd.get();
  }
  uint32_t GetPlaneStride(size_t plane) const override {
    DCHECK_LT(plane, handle_.planes.size());
    return handle_.planes[plane].stride;
  }
  size_t GetPlaneOffset(size_t plane) const override {
    DCHECK_LT(plane, handle_.planes.size());
    return handle_.planes[plane].offset;
  }
  size_t GetPlaneSize(size_t plane) const override {
    DCHECK_LT(plane, handle_.planes.size());
    return static_cast<size_t>(handle_.planes[plane].size);
  }
  uint32_t GetPlaneHandle(size_t plane) const override {
    DCHECK_LT(plane, handle_.planes.size());
    return GetHandleForPlane(bo_, plane);
  }
  uint32_t GetHandle() const override { return gbm_bo_get_handle(bo_).u32; }
  gfx::NativePixmapHandle ExportHandle() const override {
    return CloneHandleForIPC(handle_);
  }

  sk_sp<SkSurface> GetSurface() override {
    CHECK(HaveGbmMap());
    DCHECK(!mmap_data_);
    uint32_t stride;
    void* addr;
    addr =
#if defined(MINIGBM)
        gbm_bo_map2(bo_, 0, 0, gbm_bo_get_width(bo_), gbm_bo_get_height(bo_),
                    GBM_BO_TRANSFER_READ_WRITE, &stride, &mmap_data_, 0);
#else
        gbm_bo_map(bo_, 0, 0, gbm_bo_get_width(bo_), gbm_bo_get_height(bo_),
                   GBM_BO_TRANSFER_READ_WRITE, &stride, &mmap_data_);
#endif

    if (!addr)
      return nullptr;
    SkImageInfo info =
        SkImageInfo::MakeN32Premul(size_.width(), size_.height());
    SkSurfaceProps props = skia::LegacyDisplayGlobals::GetSkSurfaceProps();
    return SkSurface::MakeRasterDirectReleaseProc(
        info, addr, stride, &Buffer::UnmapGbmBo, this, &props);
  }

 private:
  static void UnmapGbmBo(void* pixels, void* context) {
    CHECK(HaveGbmMap());
    Buffer* buffer = static_cast<Buffer*>(context);
    gbm_bo_unmap(buffer->bo_, buffer->mmap_data_);
    buffer->mmap_data_ = nullptr;
  }

  gbm_bo* const bo_;
  void* mmap_data_ = nullptr;

  const uint32_t format_;
  const uint64_t format_modifier_;
  const uint32_t flags_;

  const gfx::Size size_;

  const gfx::NativePixmapHandle handle_;
};

std::unique_ptr<Buffer> CreateBufferForBO(struct gbm_bo* bo,
                                          uint32_t format,
                                          const gfx::Size& size,
                                          uint32_t flags) {
  DCHECK(bo);
  gfx::NativePixmapHandle handle;

  const uint64_t modifier = HaveGbmModifiers() ? gbm_bo_get_modifier(bo) : 0;
  const int plane_count = GetPlaneCount(bo);
  // The Mesa's gbm implementation explicitly checks whether plane count <= and
  // returns 1 if the condition is true. Nevertheless, use a DCHECK here to make
  // sure the condition is not broken there.
  DCHECK_GT(plane_count, 0);
  // Ensure there are no differences in integer signs by casting any possible
  // values to size_t.
  for (size_t i = 0; i < static_cast<size_t>(plane_count); ++i) {
    // The fd returned by gbm_bo_get_fd is not ref-counted and need to be
    // kept open for the lifetime of the buffer.
    base::ScopedFD fd(GetPlaneFdForBo(bo, i));

    if (!fd.is_valid()) {
      PLOG(ERROR) << "Failed to export buffer to dma_buf";
      gbm_bo_destroy(bo);
      return nullptr;
    }

    handle.planes.emplace_back(
        GetStrideForPlane(bo, i), GetOffsetForPlane(bo, i),
        GetSizeOfPlane(bo, format, size, i), std::move(fd));
  }

  handle.modifier = modifier;
  return std::make_unique<Buffer>(bo, format, flags, modifier, size,
                                  std::move(handle));
}

class Device final : public ui::GbmDevice {
 public:
  Device(gbm_device* device) : device_(device) {}

  Device(const Device&) = delete;
  Device& operator=(const Device&) = delete;

  ~Device() override { gbm_device_destroy(device_); }

  std::unique_ptr<ui::GbmBuffer> CreateBuffer(uint32_t format,
                                              const gfx::Size& size,
                                              uint32_t flags) override {
    struct gbm_bo* bo =
        gbm_bo_create(device_, size.width(), size.height(), format, flags);
    if (!bo) {
#if DCHECK_IS_ON()
      const char fourcc_as_string[5] = {
          static_cast<char>(format), static_cast<char>(format >> 8),
          static_cast<char>(format >> 16), static_cast<char>(format >> 24), 0};

      DVLOG(2) << "Failed to create GBM BO, " << fourcc_as_string << ", "
               << size.ToString() << ", flags: 0x" << std::hex << flags
               << "; gbm_device_is_format_supported() = "
               << gbm_device_is_format_supported(device_, format, flags);
#endif
      return nullptr;
    }

    return CreateBufferForBO(bo, format, size, flags);
  }

  std::unique_ptr<ui::GbmBuffer> CreateBufferWithModifiers(
      uint32_t format,
      const gfx::Size& size,
      uint32_t flags,
      const std::vector<uint64_t>& modifiers) override {
    if (modifiers.empty())
      return CreateBuffer(format, size, flags);
    CHECK(HaveGbmModifiers());
    struct gbm_bo* bo = gbm_bo_create_with_modifiers(
        device_, size.width(), size.height(), format, modifiers.data(),
        modifiers.size());
    if (!bo)
      return nullptr;

    return CreateBufferForBO(bo, format, size, flags);
  }

  std::unique_ptr<ui::GbmBuffer> CreateBufferFromHandle(
      uint32_t format,
      const gfx::Size& size,
      gfx::NativePixmapHandle handle) override {
    DCHECK_EQ(handle.planes[0].offset, 0u);

    // Try to use scanout if supported.
    int gbm_flags = GBM_BO_USE_SCANOUT;
#if defined(MINIGBM)
    gbm_flags |= GBM_BO_USE_TEXTURING;
#endif
    if (!gbm_device_is_format_supported(device_, format, gbm_flags))
      gbm_flags &= ~GBM_BO_USE_SCANOUT;

    struct gbm_bo* bo = nullptr;
    if (!gbm_device_is_format_supported(device_, format, gbm_flags)) {
      LOG(ERROR) << "gbm format not supported: " << format;
      return nullptr;
    }

    struct gbm_import_fd_modifier_data fd_data;
    fd_data.width = size.width();
    fd_data.height = size.height();
    fd_data.format = format;
    fd_data.num_fds = handle.planes.size();
    fd_data.modifier = handle.modifier;

    DCHECK_LE(handle.planes.size(), 3u);
    for (size_t i = 0; i < handle.planes.size(); ++i) {
      fd_data.fds[i] = handle.planes[i < handle.planes.size() ? i : 0].fd.get();
      fd_data.strides[i] = handle.planes[i].stride;
      fd_data.offsets[i] = handle.planes[i].offset;
    }

    // The fd passed to gbm_bo_import is not ref-counted and need to be
    // kept open for the lifetime of the buffer.
    bo = gbm_bo_import(device_, GBM_BO_IMPORT_FD_MODIFIER, &fd_data, gbm_flags);
    if (!bo) {
      LOG(ERROR) << "nullptr returned from gbm_bo_import";
      return nullptr;
    }

    return std::make_unique<Buffer>(bo, format, gbm_flags, handle.modifier,
                                    size, std::move(handle));
  }

 private:
  gbm_device* const device_;
};

}  // namespace gbm_wrapper

namespace ui {

std::unique_ptr<GbmDevice> CreateGbmDevice(int fd) {
  gbm_device* device = gbm_create_device(fd);
  if (!device)
    return nullptr;
  return std::make_unique<gbm_wrapper::Device>(device);
}

}  // namespace ui
