/*
 * 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 ATRACE_TAG ATRACE_TAG_GRAPHICS
#define LOG_TAG "hwc-drm-display-compositor"

#include "drmdisplaycompositor.h"
#include "drmcrtc.h"
#include "drmplane.h"
#include "drmresources.h"
#include "glworker.h"

#include <algorithm>
#include <pthread.h>
#include <sstream>
#include <stdlib.h>
#include <time.h>
#include <vector>

#include <drm/drm_mode.h>
#include <cutils/log.h>
#include <sync/sync.h>
#include <utils/Trace.h>

namespace android {

DrmDisplayCompositor::DrmDisplayCompositor()
    : drm_(NULL),
      display_(-1),
      worker_(this),
      initialized_(false),
      active_(false),
      framebuffer_index_(0),
      dump_frames_composited_(0),
      dump_last_timestamp_ns_(0) {
  struct timespec ts;
  if (clock_gettime(CLOCK_MONOTONIC, &ts))
    return;
  dump_last_timestamp_ns_ = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
}

DrmDisplayCompositor::~DrmDisplayCompositor() {
  if (!initialized_)
    return;

  worker_.Exit();

  int ret = pthread_mutex_lock(&lock_);
  if (ret)
    ALOGE("Failed to acquire compositor lock %d", ret);

  while (!composite_queue_.empty()) {
    composite_queue_.front().reset();
    composite_queue_.pop();
  }
  active_composition_.reset();

  ret = pthread_mutex_unlock(&lock_);
  if (ret)
    ALOGE("Failed to acquire compositor lock %d", ret);

  pthread_mutex_destroy(&lock_);
}

int DrmDisplayCompositor::Init(DrmResources *drm, int display) {
  drm_ = drm;
  display_ = display;

  int ret = pthread_mutex_init(&lock_, NULL);
  if (ret) {
    ALOGE("Failed to initialize drm compositor lock %d\n", ret);
    return ret;
  }
  ret = worker_.Init();
  if (ret) {
    pthread_mutex_destroy(&lock_);
    ALOGE("Failed to initialize compositor worker %d\n", ret);
    return ret;
  }

  initialized_ = true;
  return 0;
}

int DrmDisplayCompositor::QueueComposition(
    std::unique_ptr<DrmDisplayComposition> composition) {
  switch (composition->type()) {
    case DRM_COMPOSITION_TYPE_FRAME:
      if (!active_)
        return -ENODEV;
      break;
    case DRM_COMPOSITION_TYPE_DPMS:
      /*
       * Update the state as soon as we get it so we can start/stop queuing
       * frames asap.
       */
      active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON);
      break;
    case DRM_COMPOSITION_TYPE_EMPTY:
      return 0;
    default:
      ALOGE("Unknown composition type %d/%d", composition->type(), display_);
      return -ENOENT;
  }

  int ret = pthread_mutex_lock(&lock_);
  if (ret) {
    ALOGE("Failed to acquire compositor lock %d", ret);
    return ret;
  }

  composite_queue_.push(std::move(composition));

  ret = pthread_mutex_unlock(&lock_);
  if (ret) {
    ALOGE("Failed to release compositor lock %d", ret);
    return ret;
  }

  worker_.Signal();
  return 0;
}

static bool drm_composition_layer_has_plane(
    const DrmCompositionLayer_t &comp_layer) {
  if (comp_layer.plane != NULL)
    if (comp_layer.plane->type() == DRM_PLANE_TYPE_OVERLAY ||
        comp_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY)
      return true;
  return false;
}

static bool drm_composition_layer_has_no_plane(
    const DrmCompositionLayer_t &comp_layer) {
  return comp_layer.plane == NULL;
}

int DrmDisplayCompositor::ApplyPreComposite(
    DrmDisplayComposition *display_comp) {
  int ret = 0;
  DrmCompositionLayerVector_t *layers = display_comp->GetCompositionLayers();

  DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
  if (connector == NULL) {
    ALOGE("Failed to determine display mode: no connector for display %d",
          display_);
    return -ENODEV;
  }

  const DrmMode &mode = connector->active_mode();
  DrmFramebuffer &fb = framebuffers_[framebuffer_index_];
  ret = fb.WaitReleased(-1);
  if (ret) {
    ALOGE("Failed to wait for framebuffer release %d", ret);
    return ret;
  }
  fb.set_release_fence_fd(-1);
  if (!fb.Allocate(mode.h_display(), mode.v_display())) {
    ALOGE("Failed to allocate framebuffer with size %dx%d", mode.h_display(),
          mode.v_display());
    return -ENOMEM;
  }

  std::vector<hwc_layer_1_t> pre_comp_layers;
  for (auto &comp_layer : *layers) {
    if (comp_layer.plane == NULL) {
      pre_comp_layers.push_back(comp_layer.layer);
      pre_comp_layers.back().handle = comp_layer.handle;
      comp_layer.layer.acquireFenceFd = -1;
    }
  }

  ret = pre_compositor_->Composite(pre_comp_layers.data(),
                                   pre_comp_layers.size(), fb.buffer());
  pre_compositor_->Finish();

  for (auto &pre_comp_layer : pre_comp_layers) {
    if (pre_comp_layer.acquireFenceFd >= 0) {
      close(pre_comp_layer.acquireFenceFd);
      pre_comp_layer.acquireFenceFd = -1;
    }
  }

  if (ret) {
    ALOGE("Failed to composite layers");
    return ret;
  }

  DrmCompositionLayer_t &pre_comp_layer =
      layers->at(display_comp->pre_composition_layer_index());
  ret = display_comp->importer()->ImportBuffer(fb.buffer()->handle,
                                               &pre_comp_layer.bo);
  if (ret) {
    ALOGE("Failed to import handle of layer %d", ret);
    return ret;
  }
  hwc_layer_1_t &pre_comp_output_layer = pre_comp_layer.layer;
  pre_comp_output_layer.handle = fb.buffer()->handle;
  pre_comp_output_layer.visibleRegionScreen.rects =
      &pre_comp_output_layer.displayFrame;
  pre_comp_output_layer.sourceCropf.right =
      pre_comp_output_layer.displayFrame.right = fb.buffer()->getWidth();
  pre_comp_output_layer.sourceCropf.bottom =
      pre_comp_output_layer.displayFrame.bottom = fb.buffer()->getHeight();

  fb.set_release_fence_fd(pre_comp_output_layer.releaseFenceFd);
  framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;

  display_comp->RemoveNoPlaneLayers();
  display_comp->SignalPreCompositionDone();
  return ret;
}

int DrmDisplayCompositor::ApplyFrame(DrmDisplayComposition *display_comp) {
  int ret = 0;

  if (display_comp->pre_composition_layer_index() >= 0) {
    ret = ApplyPreComposite(display_comp);
    if (ret)
      return ret;
  }

  drmModePropertySetPtr pset = drmModePropertySetAlloc();
  if (!pset) {
    ALOGE("Failed to allocate property set");
    return -ENOMEM;
  }

  DrmCompositionLayerVector_t *layers = display_comp->GetCompositionLayers();
  for (DrmCompositionLayerVector_t::iterator iter = layers->begin();
       iter != layers->end(); ++iter) {
    hwc_layer_1_t *layer = &iter->layer;

    if (layer->acquireFenceFd >= 0) {
      ret = sync_wait(layer->acquireFenceFd, -1);
      if (ret) {
        ALOGE("Failed to wait for acquire %d/%d", layer->acquireFenceFd, ret);
        drmModePropertySetFree(pset);
        return ret;
      }
      close(layer->acquireFenceFd);
      layer->acquireFenceFd = -1;
    }

    DrmPlane *plane = iter->plane;
    DrmCrtc *crtc = iter->crtc;

    // Disable the plane if there's no crtc
    if (!crtc) {
      ret = drmModePropertySetAdd(pset, plane->id(),
                                  plane->crtc_property().id(), 0) ||
            drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
                                  0);
      if (ret) {
        ALOGE("Failed to add plane %d disable to pset", plane->id());
        break;
      }
      continue;
    }

    uint64_t rotation;
    switch (layer->transform) {
      case HWC_TRANSFORM_FLIP_H:
        rotation = 1 << DRM_REFLECT_X;
        break;
      case HWC_TRANSFORM_FLIP_V:
        rotation = 1 << DRM_REFLECT_Y;
        break;
      case HWC_TRANSFORM_ROT_90:
        rotation = 1 << DRM_ROTATE_90;
        break;
      case HWC_TRANSFORM_ROT_180:
        rotation = 1 << DRM_ROTATE_180;
        break;
      case HWC_TRANSFORM_ROT_270:
        rotation = 1 << DRM_ROTATE_270;
        break;
      case 0:
        rotation = 0;
        break;
      default:
        ALOGE("Invalid transform value 0x%x given", layer->transform);
        ret = -EINVAL;
        break;
    }
    if (ret)
      break;

    // TODO: Once we have atomic test, this should fall back to GL
    if (rotation && plane->rotation_property().id() == 0) {
      ALOGE("Rotation is not supported on plane %d", plane->id());
      ret = -EINVAL;
      break;
    }

    ret =
        drmModePropertySetAdd(pset, plane->id(), plane->crtc_property().id(),
                              crtc->id()) ||
        drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
                              iter->bo.fb_id) ||
        drmModePropertySetAdd(pset, plane->id(), plane->crtc_x_property().id(),
                              layer->displayFrame.left) ||
        drmModePropertySetAdd(pset, plane->id(), plane->crtc_y_property().id(),
                              layer->displayFrame.top) ||
        drmModePropertySetAdd(
            pset, plane->id(), plane->crtc_w_property().id(),
            layer->displayFrame.right - layer->displayFrame.left) ||
        drmModePropertySetAdd(
            pset, plane->id(), plane->crtc_h_property().id(),
            layer->displayFrame.bottom - layer->displayFrame.top) ||
        drmModePropertySetAdd(pset, plane->id(), plane->src_x_property().id(),
                              (int)(layer->sourceCropf.left) << 16) ||
        drmModePropertySetAdd(pset, plane->id(), plane->src_y_property().id(),
                              (int)(layer->sourceCropf.top) << 16) ||
        drmModePropertySetAdd(
            pset, plane->id(), plane->src_w_property().id(),
            (int)(layer->sourceCropf.right - layer->sourceCropf.left) << 16) ||
        drmModePropertySetAdd(
            pset, plane->id(), plane->src_h_property().id(),
            (int)(layer->sourceCropf.bottom - layer->sourceCropf.top) << 16);
    if (ret) {
      ALOGE("Failed to add plane %d to set", plane->id());
      break;
    }

    if (plane->rotation_property().id()) {
      ret = drmModePropertySetAdd(pset, plane->id(),
                                  plane->rotation_property().id(), rotation);
      if (ret) {
        ALOGE("Failed to add rotation property %d to plane %d",
              plane->rotation_property().id(), plane->id());
        break;
      }
    }
  }

  if (!ret) {
    ret = drmModePropertySetCommit(drm_->fd(), 0, drm_, pset);
    if (ret)
      ALOGE("Failed to commit pset ret=%d\n", ret);
  }
  if (pset)
    drmModePropertySetFree(pset);

  return ret;
}

int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
  DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
  if (!conn) {
    ALOGE("Failed to get DrmConnector for display %d", display_);
    return -ENODEV;
  }

  const DrmProperty &prop = conn->dpms_property();
  int ret = drmModeConnectorSetProperty(drm_->fd(), conn->id(), prop.id(),
                                        display_comp->dpms_mode());
  if (ret) {
    ALOGE("Failed to set DPMS property for connector %d", conn->id());
    return ret;
  }
  return 0;
}

int DrmDisplayCompositor::Composite() {
  ATRACE_CALL();

  if (!pre_compositor_) {
    pre_compositor_.reset(new GLWorkerCompositor());
    int ret = pre_compositor_->Init();
    if (ret) {
      ALOGE("Failed to initialize OpenGL compositor %d", ret);
      return ret;
    }
  }

  int ret = pthread_mutex_lock(&lock_);
  if (ret) {
    ALOGE("Failed to acquire compositor lock %d", ret);
    return ret;
  }
  if (composite_queue_.empty()) {
    ret = pthread_mutex_unlock(&lock_);
    if (ret)
      ALOGE("Failed to release compositor lock %d", ret);
    return ret;
  }

  std::unique_ptr<DrmDisplayComposition> composition(
      std::move(composite_queue_.front()));
  composite_queue_.pop();

  ret = pthread_mutex_unlock(&lock_);
  if (ret) {
    ALOGE("Failed to release compositor lock %d", ret);
    return ret;
  }

  switch (composition->type()) {
    case DRM_COMPOSITION_TYPE_FRAME:
      ret = ApplyFrame(composition.get());
      if (ret) {
        ALOGE("Composite failed for display %d", display_);
        return ret;
      }
      ++dump_frames_composited_;
      break;
    case DRM_COMPOSITION_TYPE_DPMS:
      ret = ApplyDpms(composition.get());
      if (ret)
        ALOGE("Failed to apply dpms for display %d", display_);
      return ret;
    default:
      ALOGE("Unknown composition type %d", composition->type());
      return -EINVAL;
  }

  if (active_composition_)
    active_composition_->FinishComposition();

  ret = pthread_mutex_lock(&lock_);
  if (ret)
    ALOGE("Failed to acquire lock for active_composition swap");

  active_composition_.swap(composition);

  if (!ret)
    ret = pthread_mutex_unlock(&lock_);
  if (ret)
    ALOGE("Failed to release lock for active_composition swap");

  return ret;
}

bool DrmDisplayCompositor::HaveQueuedComposites() const {
  int ret = pthread_mutex_lock(&lock_);
  if (ret) {
    ALOGE("Failed to acquire compositor lock %d", ret);
    return false;
  }

  bool empty_ret = !composite_queue_.empty();

  ret = pthread_mutex_unlock(&lock_);
  if (ret) {
    ALOGE("Failed to release compositor lock %d", ret);
    return false;
  }

  return empty_ret;
}

void DrmDisplayCompositor::Dump(std::ostringstream *out) const {
  uint64_t cur_ts;

  int ret = pthread_mutex_lock(&lock_);
  if (ret)
    return;

  uint64_t num_frames = dump_frames_composited_;
  dump_frames_composited_ = 0;

  struct timespec ts;
  ret = clock_gettime(CLOCK_MONOTONIC, &ts);

  DrmCompositionLayerVector_t layers;
  if (active_composition_)
    layers = *active_composition_->GetCompositionLayers();
  else
    ret = -EAGAIN;

  ret |= pthread_mutex_unlock(&lock_);
  if (ret)
    return;

  cur_ts = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
  uint64_t num_ms = (cur_ts - dump_last_timestamp_ns_) / (1000 * 1000);
  float fps = num_ms ? (num_frames * 1000.0f) / (num_ms) : 0.0f;

  *out << "--DrmDisplayCompositor[" << display_
       << "]: num_frames=" << num_frames << " num_ms=" << num_ms
       << " fps=" << fps << "\n";

  dump_last_timestamp_ns_ = cur_ts;

  *out << "---- DrmDisplayCompositor Layers: num=" << layers.size() << "\n";
  for (DrmCompositionLayerVector_t::iterator iter = layers.begin();
       iter != layers.end(); ++iter) {
    hwc_layer_1_t *layer = &iter->layer;
    DrmPlane *plane = iter->plane;

    *out << "------ DrmDisplayCompositor Layer: plane=" << plane->id() << " ";

    DrmCrtc *crtc = iter->crtc;
    if (!crtc) {
      *out << "disabled\n";
      continue;
    }

    *out << "crtc=" << crtc->id()
         << " crtc[x/y/w/h]=" << layer->displayFrame.left << "/"
         << layer->displayFrame.top << "/"
         << layer->displayFrame.right - layer->displayFrame.left << "/"
         << layer->displayFrame.bottom - layer->displayFrame.top << " "
         << " src[x/y/w/h]=" << layer->sourceCropf.left << "/"
         << layer->sourceCropf.top << "/"
         << layer->sourceCropf.right - layer->sourceCropf.left << "/"
         << layer->sourceCropf.bottom - layer->sourceCropf.top
         << " transform=" << layer->transform << "\n";
  }
}
}
