/*
 * Copyright (C) 2021 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.
 */

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define LOG_TAG "hwc-platform-drm-generic"

#include "DrmFbImporter.h"

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

#include <cinttypes>
#include <system_error>

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

namespace android {

auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle,
                                   const std::shared_ptr<DrmDevice> &drm)
    -> std::shared_ptr<DrmFbIdHandle> {
  // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): priv. constructor usage
  std::shared_ptr<DrmFbIdHandle> local(new DrmFbIdHandle(drm));

  local->gem_handles_[0] = first_gem_handle;
  int32_t err = 0;

  /* Framebuffer object creation require gem handle for every used plane */
  for (int i = 1; i < local->gem_handles_.size(); i++) {
    if (bo->prime_fds[i] > 0) {
      if (bo->prime_fds[i] != bo->prime_fds[0]) {
        err = drmPrimeFDToHandle(drm->fd(), bo->prime_fds[i],
                                 &local->gem_handles_.at(i));
        if (err != 0) {
          ALOGE("failed to import prime fd %d errno=%d", bo->prime_fds[i],
                errno);
        }
      } else {
        local->gem_handles_.at(i) = local->gem_handles_[0];
      }
    }
  }

  bool has_modifiers = bo->modifiers[0] != DRM_FORMAT_MOD_NONE &&
                       bo->modifiers[0] != DRM_FORMAT_MOD_INVALID;

  if (!drm->HasAddFb2ModifiersSupport() && has_modifiers) {
    ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64,
          bo->modifiers[0]);
    local.reset();
    return local;
  }

  /* Create framebuffer object */
  if (!has_modifiers) {
    err = drmModeAddFB2(drm->fd(), bo->width, bo->height, bo->format,
                        &local->gem_handles_[0], &bo->pitches[0],
                        &bo->offsets[0], &local->fb_id_, 0);
  } else {
    err = drmModeAddFB2WithModifiers(drm->fd(), bo->width, bo->height,
                                     bo->format, &local->gem_handles_[0],
                                     &bo->pitches[0], &bo->offsets[0],
                                     &bo->modifiers[0], &local->fb_id_,
                                     DRM_MODE_FB_MODIFIERS);
  }
  if (err != 0) {
    ALOGE("could not create drm fb %d", err);
    local.reset();
  }

  return local;
}

DrmFbIdHandle::~DrmFbIdHandle() {
  /* Destroy framebuffer object */
  if (drmModeRmFB(drm_->fd(), fb_id_) != 0) {
    ALOGE("Failed to rm fb");
  }

  /* Close GEM handles.
   *
   * WARNING: TODO(nobody):
   * From Linux side libweston relies on libgbm to get KMS handle and never
   * closes it (handle is closed by libgbm on buffer destruction)
   * Probably we should offer similar approach to users (at least on user
   * request via system properties)
   */
  struct drm_gem_close gem_close {};
  for (int i = 0; i < gem_handles_.size(); i++) {
    /* Don't close invalid handle. Close handle only once in cases
     * where several YUV planes located in the single buffer. */
    if (gem_handles_[i] == 0 ||
        (i != 0 && gem_handles_[i] == gem_handles_[0])) {
      continue;
    }
    gem_close.handle = gem_handles_[i];
    int32_t err = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
    if (err != 0) {
      ALOGE("Failed to close gem handle %d, errno: %d", gem_handles_[i], errno);
    }
  }
}

auto DrmFbImporter::GetOrCreateFbId(hwc_drm_bo_t *bo)
    -> std::shared_ptr<DrmFbIdHandle> {
  /* Lookup DrmFbIdHandle in cache first. First handle serves as a cache key. */
  GemHandle first_handle = 0;
  int32_t err = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &first_handle);

  if (err != 0) {
    ALOGE("Failed to import prime fd %d ret=%d", bo->prime_fds[0], err);
    return std::shared_ptr<DrmFbIdHandle>();
  }

  auto drm_fb_id_cached = drm_fb_id_handle_cache_.find(first_handle);

  if (drm_fb_id_cached != drm_fb_id_handle_cache_.end()) {
    if (auto drm_fb_id_handle_shared = drm_fb_id_cached->second.lock()) {
      return drm_fb_id_handle_shared;
    }
    drm_fb_id_handle_cache_.erase(drm_fb_id_cached);
  }

  /* Cleanup cached empty weak pointers */
  const int minimal_cleanup_size = 128;
  if (drm_fb_id_handle_cache_.size() > minimal_cleanup_size) {
    CleanupEmptyCacheElements();
  }

  /* No DrmFbIdHandle found in cache, create framebuffer object */
  auto fb_id_handle = DrmFbIdHandle::CreateInstance(bo, first_handle, drm_);
  if (fb_id_handle) {
    drm_fb_id_handle_cache_[first_handle] = fb_id_handle;
  }

  return fb_id_handle;
}

}  // namespace android
