/*
 * 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 (DrmResources::PlaneIter iter = drm_->begin_planes();
       iter != drm_->end_planes(); ++iter) {
    if ((*iter)->type() == DRM_PLANE_TYPE_PRIMARY)
      primary_planes_.push_back(*iter);
    else if (use_overlay_planes && (*iter)->type() == DRM_PLANE_TYPE_OVERLAY)
      overlay_planes_.push_back(*iter);
  }
}

int DrmComposition::Init(uint64_t frame_no) {
  for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
       iter != drm_->end_connectors(); ++iter) {
    int display = (*iter)->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_[(*iter)->display()]->Init(drm_, crtc, importer_,
                                                         frame_no);
    if (ret) {
      ALOGE("Failed to init display composition for %d", (*iter)->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;

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

  return DisableUnusedPlanes();
}

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::DisableUnusedPlanes() {
  for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
       iter != drm_->end_connectors(); ++iter) {
    int display = (*iter)->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();
}
}
