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

#include "drmdisplaycompositor.h"
#include "drmhwcomposer.h"
#include "platform.h"
#include "resourcemanager.h"
#include "vsyncworker.h"

#include <hardware/hwcomposer2.h>

#include <map>

namespace android {

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();

 private:
  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_);
    }

    void PopulateDrmLayer(DrmHwcLayer *layer);

    // 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_;
    HWC2::Transform transform_ = HWC2::Transform::None;
    uint32_t z_order_ = 0;
    android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN;
  };

  struct HwcCallback {
    HwcCallback(hwc2_callback_data_t d, hwc2_function_pointer_t f)
        : data(d), func(f) {
    }
    hwc2_callback_data_t data;
    hwc2_function_pointer_t func;
  };

  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);

    HWC2::Error RegisterVsyncCallback(hwc2_callback_data_t data,
                                      hwc2_function_pointer_t func);
    void ClearDisplay();

    // 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);
    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 *retire_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) {
      return layers_.at(layer);
    }

   private:
    HWC2::Error CreateComposition(bool test);
    void AddFenceToRetireFence(int fd);

    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_;

    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 retire_fence_;
    UniqueFd next_retire_fence_;
    int32_t color_mode_;

    uint32_t frame_no_ = 0;
  };

  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_;
  };

  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)...));
  }

  template <typename HookType, HookType func, typename... Args>
  static int32_t DisplayHook(hwc2_device_t *dev, hwc2_display_t display_handle,
                             Args... args) {
    DrmHwcTwo *hwc = toDrmHwcTwo(dev);
    HwcDisplay &display = hwc->displays_.at(display_handle);
    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) {
    DrmHwcTwo *hwc = toDrmHwcTwo(dev);
    HwcDisplay &display = hwc->displays_.at(display_handle);
    HwcLayer &layer = display.get_layer(layer_handle);
    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 *size, char *buffer);
  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::map<HWC2::Callback, HwcCallback> callbacks_;
};
}  // namespace android
