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

#include "Backend.h"

#include <climits>

#include "BackendManager.h"
#include "bufferinfo/BufferInfoGetter.h"

namespace android {

HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
                                     uint32_t *num_types,
                                     uint32_t *num_requests) {
  *num_types = 0;
  *num_requests = 0;
  size_t avail_planes = display->primary_planes().size() +
                        display->overlay_planes().size();

  /*
   * If more layers then planes, save one plane
   * for client composited layers
   */
  if (avail_planes < display->layers().size())
    avail_planes--;

  std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map;
  std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map_tmp;
  uint32_t z_index = 0;
  // First create a map of layers and z_order values
  for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l :
       display->layers())
    z_map_tmp.emplace(std::make_pair(l.second.z_order(), &l.second));
  // normalise the map so that the lowest z_order layer has key 0
  for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map_tmp)
    z_map.emplace(std::make_pair(z_index++, l.second));

  uint32_t total_pixops = display->CalcPixOps(z_map, 0, z_map.size());
  uint32_t gpu_pixops = 0;

  int client_start = -1;
  size_t client_size = 0;

  if (display->compositor().ShouldFlattenOnClient()) {
    client_start = 0;
    client_size = z_map.size();
    display->MarkValidated(z_map, client_start, client_size);
  } else {
    std::tie(client_start, client_size) = GetClientLayers(display, z_map);

    int extra_client = int(z_map.size() - client_size) - int(avail_planes);
    if (extra_client > 0) {
      int start = 0;
      size_t steps = 0;
      if (client_size != 0) {
        int prepend = std::min(client_start, extra_client);
        int append = std::min(int(z_map.size()) -
                                  int(client_start + client_size),
                              extra_client);
        start = client_start - (int)prepend;
        client_size += extra_client;
        steps = 1 + std::min(std::min(append, prepend),
                             int(z_map.size()) - int(start + client_size));
      } else {
        client_size = extra_client;
        steps = 1 + z_map.size() - extra_client;
      }

      gpu_pixops = INT_MAX;
      for (int i = 0; i < steps; i++) {
        uint32_t po = display->CalcPixOps(z_map, start + i, client_size);
        if (po < gpu_pixops) {
          gpu_pixops = po;
          client_start = start + i;
        }
      }
    }

    display->MarkValidated(z_map, client_start, client_size);

    bool testing_needed = !(client_start == 0 && client_size == z_map.size());

    if (testing_needed &&
        display->CreateComposition(true) != HWC2::Error::None) {
      ++display->total_stats().failed_kms_validate_;
      gpu_pixops = total_pixops;
      client_size = z_map.size();
      display->MarkValidated(z_map, 0, client_size);
    }
  }

  *num_types = client_size;

  display->total_stats().frames_flattened_ = display->compositor()
                                                 .GetFlattenedFramesCount();
  display->total_stats().gpu_pixops_ += gpu_pixops;
  display->total_stats().total_pixops_ += total_pixops;

  return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
}

std::tuple<int, size_t> Backend::GetClientLayers(
    DrmHwcTwo::HwcDisplay *display,
    const std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map) {
  int client_start = -1;
  size_t client_size = 0;

  for (const auto &[z_order, layer] : z_map) {
    if (IsClientLayer(display, layer)) {
      if (client_start < 0)
        client_start = (int)z_order;
      client_size = (z_order - client_start) + 1;
    }
  }

  return std::make_tuple(client_start, client_size);
}

bool Backend::IsClientLayer(DrmHwcTwo::HwcDisplay *display,
                            DrmHwcTwo::HwcLayer *layer) {
  return !display->HardwareSupportsLayerType(layer->sf_type()) ||
         !BufferInfoGetter::GetInstance()->IsHandleUsable(layer->buffer()) ||
         display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY ||
         (layer->RequireScalingOrPhasing() &&
          display->resource_manager()->ForcedScalingWithGpu());
}

// clang-format off
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp)
REGISTER_BACKEND("generic", Backend);
// clang-format on

}  // namespace android
