/*
 * Copyright (C) 2015 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 "hwc-drm-display-composition"

#include "drmdisplaycomposition.h"
#include "drmcrtc.h"
#include "drmplane.h"
#include "drmresources.h"

#include <stdlib.h>

#include <cutils/log.h>
#include <sw_sync.h>
#include <sync/sync.h>
#include <xf86drmMode.h>

namespace android {

DrmCompositionLayer::DrmCompositionLayer(DrmCrtc *crtc, DrmHwcLayer &&l)
    : crtc(crtc),
      sf_handle(l.sf_handle),
      buffer(std::move(l.buffer)),
      handle(std::move(l.handle)),
      transform(l.transform),
      blending(l.blending),
      alpha(l.alpha),
      source_crop(l.source_crop),
      display_frame(l.display_frame),
      source_damage(l.source_damage),
      acquire_fence(std::move(l.acquire_fence)) {
}

DrmDisplayComposition::DrmDisplayComposition()
    : drm_(NULL),
      importer_(NULL),
      type_(DRM_COMPOSITION_TYPE_EMPTY),
      timeline_fd_(-1),
      timeline_(0),
      timeline_current_(0),
      timeline_pre_comp_done_(0),
      pre_composition_layer_index_(-1),
      dpms_mode_(DRM_MODE_DPMS_ON),
      frame_no_(0) {
}

DrmDisplayComposition::~DrmDisplayComposition() {
  if (timeline_fd_ >= 0) {
    FinishComposition();
    close(timeline_fd_);
    timeline_fd_ = -1;
  }
}

int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc,
                                Importer *importer, uint64_t frame_no) {
  drm_ = drm;
  crtc_ = crtc;  // Can be NULL if we haven't modeset yet
  importer_ = importer;
  frame_no_ = frame_no;

  int ret = sw_sync_timeline_create();
  if (ret < 0) {
    ALOGE("Failed to create sw sync timeline %d", ret);
    return ret;
  }
  timeline_fd_ = ret;
  return 0;
}

DrmCompositionType DrmDisplayComposition::type() const {
  return type_;
}

bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
  return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
}

static DrmPlane *TakePlane(DrmCrtc *crtc, std::vector<DrmPlane *> *planes) {
  for (auto iter = planes->begin(); iter != planes->end(); ++iter) {
    if ((*iter)->GetCrtcSupported(*crtc)) {
      DrmPlane *plane = *iter;
      planes->erase(iter);
      return plane;
    }
  }
  return NULL;
}

static DrmPlane *TakePlane(DrmCrtc *crtc,
                           std::vector<DrmPlane *> *primary_planes,
                           std::vector<DrmPlane *> *overlay_planes) {
  DrmPlane *plane = TakePlane(crtc, primary_planes);
  if (plane)
    return plane;
  return TakePlane(crtc, overlay_planes);
}

int DrmDisplayComposition::CreateNextTimelineFence() {
  ++timeline_;
  return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
}

int DrmDisplayComposition::IncreaseTimelineToPoint(int point) {
  int timeline_increase = point - timeline_current_;
  if (timeline_increase <= 0)
    return 0;

  int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
  if (ret)
    ALOGE("Failed to increment sync timeline %d", ret);
  else
    timeline_current_ = point;

  return ret;
}

int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers,
                                     std::vector<DrmPlane *> *primary_planes,
                                     std::vector<DrmPlane *> *overlay_planes) {
  int ret = 0;
  if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
    return -EINVAL;

  for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
    DrmHwcLayer *layer = &layers[layer_index];

    layers_.emplace_back(crtc_, std::move(*layer));
    DrmCompositionLayer *c_layer = &layers_.back();

    if (pre_composition_layer_index_ == -1) {
      c_layer->plane = TakePlane(crtc_, primary_planes, overlay_planes);
      if (c_layer->plane == NULL) {
        if (layers_.size() <= 1) {
          ALOGE("Failed to match any planes to the crtc of this display");
          ret = -ENODEV;
          goto fail;
        }

        layers_.emplace_back();
        // c_layer's address might have changed when we resized the vector
        c_layer = &layers_[layers_.size() - 2];
        DrmCompositionLayer &pre_comp_layer = layers_.back();
        pre_comp_layer.crtc = crtc_;

        pre_composition_layer_index_ = layers_.size() - 1;

        // This is all to fix up the previous layer, which has now become part
        // of the set of pre-composition layers because we are stealing its
        // plane.
        DrmCompositionLayer &last_c_layer = layers_[layers_.size() - 3];
        std::swap(pre_comp_layer.plane, last_c_layer.plane);
        OutputFd &last_release_fence = layers[layer_index - 1].release_fence;
        last_release_fence.Set(CreateNextTimelineFence());
        ret = last_release_fence.get();
        if (ret < 0) {
          ALOGE("Could not create release fence %d", ret);
          goto fail;
        }
      }
    }

    if (c_layer->plane == NULL) {
      // Layers to be pre composited all get the earliest release fences as they
      // will get released soonest.
      layer->release_fence.Set(CreateNextTimelineFence());
      ret = layer->release_fence.get();
      if (ret < 0) {
        ALOGE("Could not create release fence %d", ret);
        goto fail;
      }
    }
  }

  timeline_pre_comp_done_ = timeline_;

  for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
    DrmHwcLayer *layer = &layers[layer_index];
    if (layer->release_fence.get() >= 0)
      continue;

    ret = layer->release_fence.Set(CreateNextTimelineFence());
    if (ret < 0) {
      ALOGE("Could not create release fence %d", ret);
      goto fail;
    }
  }

  type_ = DRM_COMPOSITION_TYPE_FRAME;
  return 0;

fail:

  for (size_t c_layer_index = 0; c_layer_index < layers_.size();
       c_layer_index++) {
    DrmCompositionLayer &c_layer = layers_[c_layer_index];
    if (c_layer.plane != NULL) {
      std::vector<DrmPlane *> *return_to =
          (c_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY) ? primary_planes
                                                            : overlay_planes;
      return_to->insert(return_to->begin() + c_layer_index, c_layer.plane);
    }
  }

  layers_.clear();

  sw_sync_timeline_inc(timeline_fd_, timeline_ - timeline_current_);

  timeline_ = timeline_current_;
  return ret;
}

int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) {
  if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
    return -EINVAL;
  dpms_mode_ = dpms_mode;
  type_ = DRM_COMPOSITION_TYPE_DPMS;
  return 0;
}

int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
  layers_.emplace_back();
  DrmCompositionLayer &c_layer = layers_.back();
  c_layer.crtc = NULL;
  c_layer.plane = plane;
  return 0;
}

void DrmDisplayComposition::RemoveNoPlaneLayers() {
  layers_.erase(
      std::remove_if(layers_.begin(), layers_.end(),
                     [](DrmCompositionLayer &l) { return l.plane == NULL; }),
      layers_.end());
}

int DrmDisplayComposition::SignalPreCompositionDone() {
  return IncreaseTimelineToPoint(timeline_pre_comp_done_);
}

int DrmDisplayComposition::FinishComposition() {
  return IncreaseTimelineToPoint(timeline_);
}

std::vector<DrmCompositionLayer>
    *DrmDisplayComposition::GetCompositionLayers() {
  return &layers_;
}

int DrmDisplayComposition::pre_composition_layer_index() const {
  return pre_composition_layer_index_;
}

uint32_t DrmDisplayComposition::dpms_mode() const {
  return dpms_mode_;
}

uint64_t DrmDisplayComposition::frame_no() const {
  return frame_no_;
}

Importer *DrmDisplayComposition::importer() const {
  return importer_;
}
}
