/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "hwc-bufferinfo-libdrm"

#include "BufferInfoLibdrm.h"

#include <gralloc_handle.h>
#include <hardware/gralloc.h>
#include <xf86drm.h>
#include <xf86drmMode.h>

#include <mutex>

#include "utils/log.h"
#include "utils/properties.h"

namespace android {

LEGACY_BUFFER_INFO_GETTER(BufferInfoLibdrm);

enum chroma_order {
  kYCbCr,
  kYCrCb,
};

struct DroidYuvFormat {
  /* Lookup keys */
  uint32_t native;                /* HAL_PIXEL_FORMAT_ */
  enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
  size_t chroma_step; /* Distance in bytes between subsequent chroma pixels. */

  /* Result */
  int fourcc; /* DRM_FORMAT_ */
};

/* The following table is used to look up a DRI image FourCC based
 * on native format and information contained in android_ycbcr struct. */
static const struct DroidYuvFormat kDroidYuvFormats[] = {
    /* Native format, YCrCb, Chroma step, DRI image FourCC */
    {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 2, DRM_FORMAT_NV12},
    {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 1, DRM_FORMAT_YUV420},
    {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCrCb, 1, DRM_FORMAT_YVU420},
    {HAL_PIXEL_FORMAT_YV12, kYCrCb, 1, DRM_FORMAT_YVU420},
    /* HACK: See droid_create_image_from_prime_fds() and
     * https://issuetracker.google.com/32077885. */
    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 2, DRM_FORMAT_NV12},
    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 1, DRM_FORMAT_YUV420},
    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_YVU420},
    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_AYUV},
    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_XYUV8888},
};

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

static uint32_t get_fourcc_yuv(uint32_t native, enum chroma_order chroma_order,
                               size_t chroma_step) {
  for (auto droid_yuv_format : kDroidYuvFormats)
    if (droid_yuv_format.native == native &&
        droid_yuv_format.chroma_order == chroma_order &&
        droid_yuv_format.chroma_step == chroma_step)
      return droid_yuv_format.fourcc;

  return UINT32_MAX;
}

static bool is_yuv(uint32_t native) {
  for (auto droid_yuv_format : kDroidYuvFormats)
    if (droid_yuv_format.native == native)
      return true;

  return false;
}

bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle,
                                       hwc_drm_bo_t *bo) {
  struct android_ycbcr ycbcr {};
  enum chroma_order chroma_order {};
  int ret = 0;

  if (!gralloc_->lock_ycbcr) {
    static std::once_flag once;
    std::call_once(once,
                   []() { ALOGW("Gralloc does not support lock_ycbcr()"); });
    return false;
  }

  memset(&ycbcr, 0, sizeof(ycbcr));
  ret = gralloc_->lock_ycbcr(gralloc_, handle, 0, 0, 0, 0, 0, &ycbcr);
  if (ret) {
    ALOGW("gralloc->lock_ycbcr failed: %d", ret);
    return false;
  }
  gralloc_->unlock(gralloc_, handle);

  /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
   * it will return the .y/.cb/.cr pointers based on a NULL pointer,
   * so they can be interpreted as offsets. */
  bo->offsets[0] = (size_t)ycbcr.y;
  /* We assume here that all the planes are located in one DMA-buf. */
  if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) {
    chroma_order = kYCrCb;
    bo->offsets[1] = (size_t)ycbcr.cr;
    bo->offsets[2] = (size_t)ycbcr.cb;
  } else {
    chroma_order = kYCbCr;
    bo->offsets[1] = (size_t)ycbcr.cb;
    bo->offsets[2] = (size_t)ycbcr.cr;
  }

  /* .ystride is the line length (in bytes) of the Y plane,
   * .cstride is the line length (in bytes) of any of the remaining
   * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
   * planar formats. */
  bo->pitches[0] = ycbcr.ystride;
  bo->pitches[1] = bo->pitches[2] = ycbcr.cstride;

  /* .chroma_step is the byte distance between the same chroma channel
   * values of subsequent pixels, assumed to be the same for Cb and Cr. */
  bo->format = get_fourcc_yuv(bo->hal_format, chroma_order, ycbcr.chroma_step);
  if (bo->format == UINT32_MAX) {
    ALOGW(
        "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = "
        "%d",
        bo->hal_format, chroma_order == kYCbCr ? "YCbCr" : "YCrCb",
        (int)ycbcr.chroma_step);
    return false;
  }

  /*
   * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
   * the single-fd case cannot happen.  So handle eithe single
   * fd or fd-per-plane case:
   */
  if (num_fds == 1) {
    bo->prime_fds[2] = bo->prime_fds[1] = bo->prime_fds[0];
  } else {
    int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3;
    if (num_fds != expected_planes)
      return false;
  }

  return true;
}

int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
  gralloc_handle_t *gr_handle = gralloc_handle(handle);
  if (!gr_handle)
    return -EINVAL;

  bo->width = gr_handle->width;
  bo->height = gr_handle->height;
  bo->hal_format = gr_handle->format;

#if GRALLOC_HANDLE_VERSION < 4
  static std::once_flag once;
  std::call_once(once, []() {
    ALOGE(
        "libdrm < v2.4.97 has broken gralloc_handle structure. Please update.");
  });
#endif
#if GRALLOC_HANDLE_VERSION == 4
  bo->modifiers[0] = gr_handle->modifier;
#endif

  bo->usage = gr_handle->usage;
  bo->prime_fds[0] = gr_handle->prime_fd;

  if (is_yuv(gr_handle->format)) {
    if (!GetYuvPlaneInfo(handle->numFds, handle, bo))
      return -EINVAL;
  } else {
    bo->pitches[0] = gr_handle->stride;
    bo->offsets[0] = 0;

    /* FOSS graphic components (gbm_gralloc, mesa3d) are translating
     * HAL_PIXEL_FORMAT_RGB_565 to DRM_FORMAT_RGB565 without swapping
     * the R and B components. Same must be done here. */
    switch (bo->hal_format) {
      case HAL_PIXEL_FORMAT_RGB_565:
        bo->format = DRM_FORMAT_RGB565;
        break;
      default:
        bo->format = ConvertHalFormatToDrm(gr_handle->format);
    }

    if (bo->format == DRM_FORMAT_INVALID)
      return -EINVAL;
  }

  return 0;
}

constexpr char gbm_gralloc_module_name[] = "GBM Memory Allocator";
constexpr char drm_gralloc_module_name[] = "DRM Memory Allocator";

int BufferInfoLibdrm::ValidateGralloc() {
  if (strcmp(gralloc_->common.name, drm_gralloc_module_name) != 0 &&
      strcmp(gralloc_->common.name, gbm_gralloc_module_name) != 0) {
    ALOGE(
        "Gralloc name isn't valid: Expected: \"%s\" or \"%s\", Actual: \"%s\"",
        gbm_gralloc_module_name, drm_gralloc_module_name,
        gralloc_->common.name);
    return -EINVAL;
  }

  return 0;
}

}  // namespace android
