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

#ifndef ANDROID_DRM_HWC_TWO_H_
#define ANDROID_DRM_HWC_TWO_H_

#include <hardware/hwcomposer2.h>
#include <math.h>

#include <array>
#include <map>

#include "compositor/DrmDisplayCompositor.h"
#include "compositor/Planner.h"
#include "drm/DrmGenericImporter.h"
#include "drm/ResourceManager.h"
#include "drm/VSyncWorker.h"
#include "drmhwcomposer.h"

namespace android {

class Backend;

class DrmHwcTwo : public hwc2_device_t {
 public:
  static int HookDevOpen(const struct hw_module_t *module, const char *name,
                         struct hw_device_t **dev);

  DrmHwcTwo();

  HWC2::Error Init();

  hwc2_callback_data_t hotplug_callback_data_ = NULL;
  HWC2_PFN_HOTPLUG hotplug_callback_hook_ = NULL;
  std::mutex hotplug_callback_lock;

  void SetHotplugCallback(hwc2_callback_data_t data,
                          hwc2_function_pointer_t hook) {
    const std::lock_guard<std::mutex> lock(hotplug_callback_lock);
    hotplug_callback_data_ = data;
    hotplug_callback_hook_ = reinterpret_cast<HWC2_PFN_HOTPLUG>(hook);
  }

  class HwcLayer {
   public:
    HWC2::Composition sf_type() const {
      return sf_type_;
    }
    HWC2::Composition validated_type() const {
      return validated_type_;
    }
    void accept_type_change() {
      sf_type_ = validated_type_;
    }
    void set_validated_type(HWC2::Composition type) {
      validated_type_ = type;
    }
    bool type_changed() const {
      return sf_type_ != validated_type_;
    }

    uint32_t z_order() const {
      return z_order_;
    }

    buffer_handle_t buffer() {
      return buffer_;
    }
    void set_buffer(buffer_handle_t buffer) {
      buffer_ = buffer;
    }

    int take_acquire_fence() {
      return acquire_fence_.Release();
    }
    void set_acquire_fence(int acquire_fence) {
      acquire_fence_.Set(dup(acquire_fence));
    }

    int release_fence() {
      return release_fence_.get();
    }
    int take_release_fence() {
      return release_fence_.Release();
    }
    void manage_release_fence() {
      release_fence_.Set(release_fence_raw_);
      release_fence_raw_ = -1;
    }
    OutputFd release_fence_output() {
      return OutputFd(&release_fence_raw_);
    }

    hwc_rect_t display_frame() {
      return display_frame_;
    }

    void PopulateDrmLayer(DrmHwcLayer *layer);

    bool RequireScalingOrPhasing() {
      float src_width = source_crop_.right - source_crop_.left;
      float src_height = source_crop_.bottom - source_crop_.top;

      float dest_width = display_frame_.right - display_frame_.left;
      float dest_height = display_frame_.bottom - display_frame_.top;

      bool scaling = src_width != dest_width || src_height != dest_height;
      bool phasing = (source_crop_.left - floor(source_crop_.left) != 0) ||
                     (source_crop_.top - floor(source_crop_.top) != 0);
      return scaling || phasing;
    }

    // Layer hooks
    HWC2::Error SetCursorPosition(int32_t x, int32_t y);
    HWC2::Error SetLayerBlendMode(int32_t mode);
    HWC2::Error SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence);
    HWC2::Error SetLayerColor(hwc_color_t color);
    HWC2::Error SetLayerCompositionType(int32_t type);
    HWC2::Error SetLayerDataspace(int32_t dataspace);
    HWC2::Error SetLayerDisplayFrame(hwc_rect_t frame);
    HWC2::Error SetLayerPlaneAlpha(float alpha);
    HWC2::Error SetLayerSidebandStream(const native_handle_t *stream);
    HWC2::Error SetLayerSourceCrop(hwc_frect_t crop);
    HWC2::Error SetLayerSurfaceDamage(hwc_region_t damage);
    HWC2::Error SetLayerTransform(int32_t transform);
    HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
    HWC2::Error SetLayerZOrder(uint32_t z);

   private:
    // sf_type_ stores the initial type given to us by surfaceflinger,
    // validated_type_ stores the type after running ValidateDisplay
    HWC2::Composition sf_type_ = HWC2::Composition::Invalid;
    HWC2::Composition validated_type_ = HWC2::Composition::Invalid;

    HWC2::BlendMode blending_ = HWC2::BlendMode::None;
    buffer_handle_t buffer_ = NULL;
    UniqueFd acquire_fence_;
    int release_fence_raw_ = -1;
    UniqueFd release_fence_;
    hwc_rect_t display_frame_;
    float alpha_ = 1.0f;
    hwc_frect_t source_crop_;
    int32_t cursor_x_;
    int32_t cursor_y_;
    hwc_color_t layer_color_;
    HWC2::Transform transform_ = HWC2::Transform::None;
    uint32_t z_order_ = 0;
    android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN;
  };

  class HwcDisplay {
   public:
    HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
               std::shared_ptr<Importer> importer, hwc2_display_t handle,
               HWC2::DisplayType type);
    HwcDisplay(const HwcDisplay &) = delete;
    HWC2::Error Init(std::vector<DrmPlane *> *planes);

    void RegisterVsyncCallback(hwc2_callback_data_t data,
                               hwc2_function_pointer_t func);
    void RegisterRefreshCallback(hwc2_callback_data_t data,
                                 hwc2_function_pointer_t func);
    HWC2::Error CreateComposition(bool test);
    bool HardwareSupportsLayerType(HWC2::Composition comp_type);
    uint32_t CalcPixOps(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map,
                        size_t first_z, size_t size);
    void MarkValidated(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map,
                       size_t client_first_z, size_t client_size);

    void ClearDisplay();

    std::string Dump();

    // HWC Hooks
    HWC2::Error AcceptDisplayChanges();
    HWC2::Error CreateLayer(hwc2_layer_t *layer);
    HWC2::Error DestroyLayer(hwc2_layer_t layer);
    HWC2::Error GetActiveConfig(hwc2_config_t *config);
    HWC2::Error GetChangedCompositionTypes(uint32_t *num_elements,
                                           hwc2_layer_t *layers,
                                           int32_t *types);
    HWC2::Error GetClientTargetSupport(uint32_t width, uint32_t height,
                                       int32_t format, int32_t dataspace);
    HWC2::Error GetColorModes(uint32_t *num_modes, int32_t *modes);
    HWC2::Error GetDisplayAttribute(hwc2_config_t config, int32_t attribute,
                                    int32_t *value);
    HWC2::Error GetDisplayConfigs(uint32_t *num_configs,
                                  hwc2_config_t *configs);
    HWC2::Error GetDisplayName(uint32_t *size, char *name);
    HWC2::Error GetDisplayRequests(int32_t *display_requests,
                                   uint32_t *num_elements, hwc2_layer_t *layers,
                                   int32_t *layer_requests);
    HWC2::Error GetDisplayType(int32_t *type);
#if PLATFORM_SDK_VERSION > 27
    HWC2::Error GetRenderIntents(int32_t mode, uint32_t *outNumIntents,
                                 int32_t *outIntents);
    HWC2::Error SetColorModeWithIntent(int32_t mode, int32_t intent);
#endif
#if PLATFORM_SDK_VERSION > 28
    HWC2::Error GetDisplayIdentificationData(uint8_t *outPort,
                                             uint32_t *outDataSize,
                                             uint8_t *outData);
    HWC2::Error GetDisplayCapabilities(uint32_t *outNumCapabilities,
                                       uint32_t *outCapabilities);
    HWC2::Error GetDisplayBrightnessSupport(bool *supported);
    HWC2::Error SetDisplayBrightness(float);
#endif
    HWC2::Error GetDozeSupport(int32_t *support);
    HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types,
                                   float *max_luminance,
                                   float *max_average_luminance,
                                   float *min_luminance);
    HWC2::Error GetReleaseFences(uint32_t *num_elements, hwc2_layer_t *layers,
                                 int32_t *fences);
    HWC2::Error PresentDisplay(int32_t *present_fence);
    HWC2::Error SetActiveConfig(hwc2_config_t config);
    HWC2::Error ChosePreferredConfig();
    HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
                                int32_t dataspace, hwc_region_t damage);
    HWC2::Error SetColorMode(int32_t mode);
    HWC2::Error SetColorTransform(const float *matrix, int32_t hint);
    HWC2::Error SetOutputBuffer(buffer_handle_t buffer, int32_t release_fence);
    HWC2::Error SetPowerMode(int32_t mode);
    HWC2::Error SetVsyncEnabled(int32_t enabled);
    HWC2::Error ValidateDisplay(uint32_t *num_types, uint32_t *num_requests);
    HwcLayer *get_layer(hwc2_layer_t layer) {
      auto it = layers_.find(layer);
      if (it == layers_.end())
        return nullptr;
      return &it->second;
    }

    /* Statistics */
    struct Stats {
      Stats minus(Stats b) {
        return {total_frames_ - b.total_frames_,
                total_pixops_ - b.total_pixops_,
                gpu_pixops_ - b.gpu_pixops_,
                failed_kms_validate_ - b.failed_kms_validate_,
                failed_kms_present_ - b.failed_kms_present_,
                frames_flattened_ - b.frames_flattened_};
      }

      uint32_t total_frames_ = 0;
      uint64_t total_pixops_ = 0;
      uint64_t gpu_pixops_ = 0;
      uint32_t failed_kms_validate_ = 0;
      uint32_t failed_kms_present_ = 0;
      uint32_t frames_flattened_ = 0;
    };

    const Backend *backend() const {
      return backend_.get();
    }
    void set_backend(std::unique_ptr<Backend> backend) {
      backend_ = std::move(backend);
    }

    const std::vector<DrmPlane *> &primary_planes() const {
      return primary_planes_;
    }

    const std::vector<DrmPlane *> &overlay_planes() const {
      return overlay_planes_;
    }

    std::map<hwc2_layer_t, HwcLayer> &layers() {
      return layers_;
    }

    const DrmDisplayCompositor &compositor() const {
      return compositor_;
    }

    const DrmDevice *drm() const {
      return drm_;
    }

    const DrmConnector *connector() const {
      return connector_;
    }

    const std::shared_ptr<Importer> &importer() const {
      return importer_;
    }

    ResourceManager *resource_manager() const {
      return resource_manager_;
    }

    android_color_transform_t &color_transform_hint() {
      return color_transform_hint_;
    }

    Stats &total_stats() {
      return total_stats_;
    }

   private:
    void AddFenceToPresentFence(int fd);

    constexpr static size_t MATRIX_SIZE = 16;

    ResourceManager *resource_manager_;
    DrmDevice *drm_;
    DrmDisplayCompositor compositor_;
    std::shared_ptr<Importer> importer_;
    std::unique_ptr<Planner> planner_;

    std::vector<DrmPlane *> primary_planes_;
    std::vector<DrmPlane *> overlay_planes_;

    std::unique_ptr<Backend> backend_;

    VSyncWorker vsync_worker_;
    DrmConnector *connector_ = NULL;
    DrmCrtc *crtc_ = NULL;
    hwc2_display_t handle_;
    HWC2::DisplayType type_;
    uint32_t layer_idx_ = 0;
    std::map<hwc2_layer_t, HwcLayer> layers_;
    HwcLayer client_layer_;
    UniqueFd present_fence_;
    int32_t color_mode_;
    std::array<float, MATRIX_SIZE> color_transform_matrix_;
    android_color_transform_t color_transform_hint_;

    uint32_t frame_no_ = 0;
    Stats total_stats_;
    Stats prev_stats_;
    std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta);
  };

  class DrmHotplugHandler : public DrmEventHandler {
   public:
    DrmHotplugHandler(DrmHwcTwo *hwc2, DrmDevice *drm)
        : hwc2_(hwc2), drm_(drm) {
    }
    void HandleEvent(uint64_t timestamp_us);

   private:
    DrmHwcTwo *hwc2_;
    DrmDevice *drm_;
  };

 private:
  static DrmHwcTwo *toDrmHwcTwo(hwc2_device_t *dev) {
    return static_cast<DrmHwcTwo *>(dev);
  }

  template <typename PFN, typename T>
  static hwc2_function_pointer_t ToHook(T function) {
    static_assert(std::is_same<PFN, T>::value, "Incompatible fn pointer");
    return reinterpret_cast<hwc2_function_pointer_t>(function);
  }

  template <typename T, typename HookType, HookType func, typename... Args>
  static T DeviceHook(hwc2_device_t *dev, Args... args) {
    DrmHwcTwo *hwc = toDrmHwcTwo(dev);
    return static_cast<T>(((*hwc).*func)(std::forward<Args>(args)...));
  }

  static HwcDisplay *GetDisplay(DrmHwcTwo *hwc, hwc2_display_t display_handle) {
    auto it = hwc->displays_.find(display_handle);
    if (it == hwc->displays_.end())
      return nullptr;

    return &it->second;
  }

  template <typename HookType, HookType func, typename... Args>
  static int32_t DisplayHook(hwc2_device_t *dev, hwc2_display_t display_handle,
                             Args... args) {
    HwcDisplay *display = GetDisplay(toDrmHwcTwo(dev), display_handle);
    if (!display)
      return static_cast<int32_t>(HWC2::Error::BadDisplay);

    return static_cast<int32_t>((display->*func)(std::forward<Args>(args)...));
  }

  template <typename HookType, HookType func, typename... Args>
  static int32_t LayerHook(hwc2_device_t *dev, hwc2_display_t display_handle,
                           hwc2_layer_t layer_handle, Args... args) {
    HwcDisplay *display = GetDisplay(toDrmHwcTwo(dev), display_handle);
    if (!display)
      return static_cast<int32_t>(HWC2::Error::BadDisplay);

    HwcLayer *layer = display->get_layer(layer_handle);
    if (!layer)
      return static_cast<int32_t>(HWC2::Error::BadLayer);

    return static_cast<int32_t>((layer->*func)(std::forward<Args>(args)...));
  }

  // hwc2_device_t hooks
  static int HookDevClose(hw_device_t *dev);
  static void HookDevGetCapabilities(hwc2_device_t *dev, uint32_t *out_count,
                                     int32_t *out_capabilities);
  static hwc2_function_pointer_t HookDevGetFunction(struct hwc2_device *device,
                                                    int32_t descriptor);

  // Device functions
  HWC2::Error CreateVirtualDisplay(uint32_t width, uint32_t height,
                                   int32_t *format, hwc2_display_t *display);
  HWC2::Error DestroyVirtualDisplay(hwc2_display_t display);
  void Dump(uint32_t *outSize, char *outBuffer);
  uint32_t GetMaxVirtualDisplayCount();
  HWC2::Error RegisterCallback(int32_t descriptor, hwc2_callback_data_t data,
                               hwc2_function_pointer_t function);
  HWC2::Error CreateDisplay(hwc2_display_t displ, HWC2::DisplayType type);
  void HandleDisplayHotplug(hwc2_display_t displayid, int state);
  void HandleInitialHotplugState(DrmDevice *drmDevice);

  ResourceManager resource_manager_;
  std::map<hwc2_display_t, HwcDisplay> displays_;

  std::string mDumpString;
};
}  // namespace android

#endif
