/*
 * 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,
        .output_type = 1,  // OutputType::SYSTEM
    };

    /* 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
