/*
 * Copyright (C) 2022 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 "drmhwc"

#include "HwcDisplayConfigs.h"

#include <cmath>
#include <cstring>

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

constexpr uint32_t kHeadlessModeDisplayWidthMm = 163;
constexpr uint32_t kHeadlessModeDisplayHeightMm = 122;
constexpr uint32_t kHeadlessModeDisplayWidthPx = 1024;
constexpr uint32_t kHeadlessModeDisplayHeightPx = 768;
constexpr uint32_t kHeadlessModeDisplayVRefresh = 60;
constexpr uint32_t kSyncLen = 10;
constexpr uint32_t kBackPorch = 10;
constexpr uint32_t kFrontPorch = 10;
constexpr uint32_t kHzInKHz = 1000;

namespace android {

// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
uint32_t HwcDisplayConfigs::last_config_id = 1;

void HwcDisplayConfigs::GenFakeMode(uint16_t width, uint16_t height) {
  hwc_configs.clear();

  last_config_id++;
  preferred_config_id = active_config_id = last_config_id;
  auto headless_drm_mode_info = (drmModeModeInfo){
      .hdisplay = width,
      .vdisplay = height,
      .vrefresh = kHeadlessModeDisplayVRefresh,
      .name = "VIRTUAL-MODE",
  };

  if (width == 0 || height == 0) {
    strcpy(headless_drm_mode_info.name, "HEADLESS-MODE");
    headless_drm_mode_info.hdisplay = kHeadlessModeDisplayWidthPx;
    headless_drm_mode_info.vdisplay = kHeadlessModeDisplayHeightPx;
  }

  /* We need a valid mode to pass the kernel validation */

  headless_drm_mode_info.hsync_start = headless_drm_mode_info.hdisplay +
                                       kFrontPorch;
  headless_drm_mode_info.hsync_end = headless_drm_mode_info.hsync_start +
                                     kSyncLen;
  headless_drm_mode_info.htotal = headless_drm_mode_info.hsync_end + kBackPorch;

  headless_drm_mode_info.vsync_start = headless_drm_mode_info.vdisplay +
                                       kFrontPorch;
  headless_drm_mode_info.vsync_end = headless_drm_mode_info.vsync_start +
                                     kSyncLen;
  headless_drm_mode_info.vtotal = headless_drm_mode_info.vsync_end + kBackPorch;

  headless_drm_mode_info.clock = (headless_drm_mode_info.htotal *
                                  headless_drm_mode_info.vtotal *
                                  headless_drm_mode_info.vrefresh) /
                                 kHzInKHz;

  hwc_configs[active_config_id] = (HwcDisplayConfig){
      .id = active_config_id,
      .group_id = 1,
      .mode = DrmMode(&headless_drm_mode_info),
  };

  mm_width = kHeadlessModeDisplayWidthMm;
  mm_height = kHeadlessModeDisplayHeightMm;
}

// NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme
HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
  /* In case UpdateModes will fail we will still have one mode for headless
   * mode
   */
  GenFakeMode(0, 0);
  /* Read real configs */
  auto ret = connector.UpdateModes();
  if (ret != 0) {
    ALOGE("Failed to update display modes %d", ret);
    return HWC2::Error::BadDisplay;
  }

  if (connector.GetModes().empty()) {
    ALOGE("No modes reported by KMS");
    return HWC2::Error::BadDisplay;
  }

  hwc_configs.clear();
  mm_width = connector.GetMmWidth();
  mm_height = connector.GetMmHeight();

  preferred_config_id = 0;
  uint32_t preferred_config_group_id = 0;

  auto first_config_id = last_config_id;
  uint32_t last_group_id = 1;
  const bool use_config_groups = Properties::UseConfigGroups();

  /* Group modes */
  for (const auto &mode : connector.GetModes()) {
    /* Find group for the new mode or create new group */
    uint32_t group_found = 0;
    if (use_config_groups) {
      for (auto &hwc_config : hwc_configs) {
        if (mode.GetRawMode().hdisplay ==
                hwc_config.second.mode.GetRawMode().hdisplay &&
            mode.GetRawMode().vdisplay ==
                hwc_config.second.mode.GetRawMode().vdisplay) {
          group_found = hwc_config.second.group_id;
        }
      }
    }
    if (group_found == 0) {
      group_found = last_group_id++;
    }

    bool disabled = false;
    if ((mode.GetRawMode().flags & DRM_MODE_FLAG_3D_MASK) != 0) {
      ALOGI("Disabling display mode %s (Modes with 3D flag aren't supported)",
            mode.GetName().c_str());
      disabled = true;
    }

    /* Add config */
    hwc_configs[last_config_id] = {
        .id = last_config_id,
        .group_id = group_found,
        .mode = mode,
        .disabled = disabled,
    };

    /* Chwck if the mode is preferred */
    if ((mode.GetRawMode().type & DRM_MODE_TYPE_PREFERRED) != 0 &&
        preferred_config_id == 0) {
      preferred_config_id = last_config_id;
      preferred_config_group_id = group_found;
    }

    last_config_id++;
  }

  /* We must have preferred mode. Set first mode as preferred
   * in case KMS haven't reported anything. */
  if (preferred_config_id == 0) {
    preferred_config_id = first_config_id;
    preferred_config_group_id = 1;
  }

  for (uint32_t group = 1; group < last_group_id; group++) {
    bool has_interlaced = false;
    bool has_progressive = false;
    for (auto &hwc_config : hwc_configs) {
      if (hwc_config.second.group_id != group || hwc_config.second.disabled) {
        continue;
      }

      if (hwc_config.second.IsInterlaced()) {
        has_interlaced = true;
      } else {
        has_progressive = true;
      }
    }

    auto has_both = has_interlaced && has_progressive;
    if (!has_both) {
      continue;
    }

    bool group_contains_preferred_interlaced = false;
    if (group == preferred_config_group_id &&
        hwc_configs[preferred_config_id].IsInterlaced()) {
      group_contains_preferred_interlaced = true;
    }

    for (auto &hwc_config : hwc_configs) {
      if (hwc_config.second.group_id != group || hwc_config.second.disabled) {
        continue;
      }

      auto disable = group_contains_preferred_interlaced
                         ? !hwc_config.second.IsInterlaced()
                         : hwc_config.second.IsInterlaced();

      if (disable) {
        ALOGI(
            "Group %i: Disabling display mode %s (This group should consist "
            "of %s modes)",
            group, hwc_config.second.mode.GetName().c_str(),
            group_contains_preferred_interlaced ? "interlaced" : "progressive");

        hwc_config.second.disabled = true;
      }
    }
  }

  /* Group should not contain 2 modes with FPS delta less than ~1HZ
   * otherwise android.graphics.cts.SetFrameRateTest CTS will fail
   */
  constexpr float kMinFpsDelta = 1.0;  // FPS
  for (uint32_t m1 = first_config_id; m1 < last_config_id; m1++) {
    for (uint32_t m2 = first_config_id; m2 < last_config_id; m2++) {
      if (m1 != m2 && hwc_configs[m1].group_id == hwc_configs[m2].group_id &&
          !hwc_configs[m1].disabled && !hwc_configs[m2].disabled &&
          fabsf(hwc_configs[m1].mode.GetVRefresh() -
                hwc_configs[m2].mode.GetVRefresh()) < kMinFpsDelta) {
        ALOGI(
            "Group %i: Disabling display mode %s (Refresh rate value is "
            "too close to existing mode %s)",
            hwc_configs[m2].group_id, hwc_configs[m2].mode.GetName().c_str(),
            hwc_configs[m1].mode.GetName().c_str());

        hwc_configs[m2].disabled = true;
      }
    }
  }

  return HWC2::Error::None;
}

}  // namespace android
