/*
 * 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-composition"

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

#include <stdlib.h>

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

namespace android {

DrmComposition::DrmComposition(DrmResources *drm, Importer *importer)
    : drm_(drm), importer_(importer) {
  char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
  property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1");
  bool use_overlay_planes = atoi(use_overlay_planes_prop);

  for (auto &plane : drm->planes()) {
    if (plane->type() == DRM_PLANE_TYPE_PRIMARY)
      primary_planes_.push_back(plane.get());
    else if (use_overlay_planes && plane->type() == DRM_PLANE_TYPE_OVERLAY)
      overlay_planes_.push_back(plane.get());
  }
}

int DrmComposition::Init(uint64_t frame_no) {
  for (auto &conn : drm_->connectors()) {
    int display = conn->display();
    composition_map_[display].reset(new DrmDisplayComposition());
    if (!composition_map_[display]) {
      ALOGE("Failed to allocate new display composition\n");
      return -ENOMEM;
    }

    // If the display hasn't been modeset yet, this will be NULL
    DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);

    int ret = composition_map_[display]->Init(drm_, crtc, importer_, frame_no);
    if (ret) {
      ALOGE("Failed to init display composition for %d", display);
      return ret;
    }
  }
  return 0;
}

int DrmComposition::SetLayers(size_t num_displays,
                              DrmCompositionDisplayLayersMap *maps) {
  int ret = 0;
  for (size_t display_index = 0; display_index < num_displays;
       display_index++) {
    DrmCompositionDisplayLayersMap &map = maps[display_index];
    int display = map.display;

    if (!drm_->GetConnectorForDisplay(display)) {
      ALOGE("Invalid display given to SetLayers %d", display);
      continue;
    }

    ret = composition_map_[display]->SetLayers(
        map.layers.data(), map.layers.size(), map.geometry_changed);
    if (ret)
      return ret;
  }

  return 0;
}

int DrmComposition::SetDpmsMode(int display, uint32_t dpms_mode) {
  return composition_map_[display]->SetDpmsMode(dpms_mode);
}

int DrmComposition::SetDisplayMode(int display, const DrmMode &display_mode) {
  return composition_map_[display]->SetDisplayMode(display_mode);
}

std::unique_ptr<DrmDisplayComposition> DrmComposition::TakeDisplayComposition(
    int display) {
  return std::move(composition_map_[display]);
}

int DrmComposition::Plan(std::map<int, DrmDisplayCompositor> &compositor_map) {
  int ret = 0;
  for (auto &conn : drm_->connectors()) {
    int display = conn->display();
    DrmDisplayComposition *comp = GetDisplayComposition(display);
    ret = comp->Plan(compositor_map[display].squash_state(), &primary_planes_,
                     &overlay_planes_);
    if (ret) {
      ALOGE("Failed to plan composition for dislay %d", display);
      return ret;
    }
  }

  return 0;
}

int DrmComposition::DisableUnusedPlanes() {
  for (auto &conn : drm_->connectors()) {
    int display = conn->display();
    DrmDisplayComposition *comp = GetDisplayComposition(display);

    /*
     * Leave empty compositions alone
     * TODO: re-visit this and potentially disable leftover planes after the
     *       active compositions have gobbled up all they can
     */
    if (comp->type() == DRM_COMPOSITION_TYPE_EMPTY ||
        comp->type() == DRM_COMPOSITION_TYPE_MODESET)
      continue;

    DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
    if (!crtc) {
      ALOGE("Failed to find crtc for display %d", display);
      continue;
    }

    for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin();
         iter != primary_planes_.end(); ++iter) {
      if ((*iter)->GetCrtcSupported(*crtc)) {
        comp->AddPlaneDisable(*iter);
        primary_planes_.erase(iter);
        break;
      }
    }
    for (std::vector<DrmPlane *>::iterator iter = overlay_planes_.begin();
         iter != overlay_planes_.end();) {
      if ((*iter)->GetCrtcSupported(*crtc)) {
        comp->AddPlaneDisable(*iter);
        iter = overlay_planes_.erase(iter);
      } else {
        iter++;
      }
    }
  }
  return 0;
}

DrmDisplayComposition *DrmComposition::GetDisplayComposition(int display) {
  return composition_map_[display].get();
}
}
