// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "screen-capture-utils/crtc.h"

#include <algorithm>
#include <map>
#include <string>
#include <utility>
#include <vector>

#include <base/check.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/stl_util.h>

namespace screenshot {

namespace {

constexpr const char kDrmDeviceDir[] = "/dev/dri";
constexpr const char kDrmDeviceGlob[] = "card?";

float FixedPoint1616ToFloat(uint32_t n) {
  float result = (n & 0xFFFF0000) >> 16;
  result += (n & 0xFFFF) / 65536.0f;
  return result;
}

bool PopulatePlaneConfiguration(int fd,
                                uint32_t plane_id,
                                PlaneConfiguration* conf) {
  // TODO(andrescj): Handle rotation.
  std::map<std::string, uint64_t> interesting_props{
      {"CRTC_X", 0}, {"CRTC_Y", 0}, {"CRTC_W", 0}, {"CRTC_H", 0},
      {"SRC_X", 0},  {"SRC_Y", 0},  {"SRC_W", 0},  {"SRC_H", 0}};

  ScopedDrmObjectPropertiesPtr props(
      drmModeObjectGetProperties(fd, plane_id, DRM_MODE_OBJECT_PLANE));
  if (!props) {
    return false;
  }

  int found = 0;
  for (int i = 0; i < props->count_props; i++) {
    ScopedDrmPropertyPtr prop(drmModeGetProperty(fd, props->props[i]));
    if (!prop) {
      continue;
    }

    if (interesting_props.find(prop->name) != interesting_props.end()) {
      interesting_props[prop->name] = props->prop_values[i];
      found++;
    }
  }

  if (found != interesting_props.size()) {
    return false;
  }

  conf->x = static_cast<int32_t>(interesting_props["CRTC_X"]);
  conf->y = static_cast<int32_t>(interesting_props["CRTC_Y"]);
  conf->w = static_cast<uint32_t>(interesting_props["CRTC_W"]);
  conf->h = static_cast<uint32_t>(interesting_props["CRTC_H"]);
  conf->crop_x = FixedPoint1616ToFloat(interesting_props["SRC_X"]);
  conf->crop_y = FixedPoint1616ToFloat(interesting_props["SRC_Y"]);
  conf->crop_w = FixedPoint1616ToFloat(interesting_props["SRC_W"]);
  conf->crop_h = FixedPoint1616ToFloat(interesting_props["SRC_H"]);
  return true;
}

std::vector<std::unique_ptr<Crtc>> GetConnectedCrtcs() {
  std::vector<std::unique_ptr<Crtc>> crtcs;

  std::vector<base::FilePath> paths;
  {
    base::FileEnumerator lister(base::FilePath(kDrmDeviceDir), false,
                                base::FileEnumerator::FILES, kDrmDeviceGlob);
    for (base::FilePath name = lister.Next(); !name.empty();
         name = lister.Next()) {
      paths.emplace_back(name);
    }
  }
  std::sort(paths.begin(), paths.end());

  for (base::FilePath path : paths) {
    base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ |
                              base::File::FLAG_WRITE);
    if (!file.IsValid())
      continue;

    // Set CAP_ATOMIC so we can query all planes and plane properties.
    bool atomic_modeset =
        drmSetClientCap(file.GetPlatformFile(), DRM_CLIENT_CAP_ATOMIC, 1) == 0;

    ScopedDrmModeResPtr resources(drmModeGetResources(file.GetPlatformFile()));
    if (!resources)
      continue;

    for (int index_connector = 0; index_connector < resources->count_connectors;
         ++index_connector) {
      ScopedDrmModeConnectorPtr connector(drmModeGetConnector(
          file.GetPlatformFile(), resources->connectors[index_connector]));
      if (!connector || connector->encoder_id == 0)
        continue;

      ScopedDrmModeEncoderPtr encoder(
          drmModeGetEncoder(file.GetPlatformFile(), connector->encoder_id));
      if (!encoder || encoder->crtc_id == 0)
        continue;

      ScopedDrmModeCrtcPtr crtc(
          drmModeGetCrtc(file.GetPlatformFile(), encoder->crtc_id));
      if (!crtc || !crtc->mode_valid || crtc->buffer_id == 0)
        continue;

      ScopedDrmModeFBPtr fb(
          drmModeGetFB(file.GetPlatformFile(), crtc->buffer_id));

      ScopedDrmModeFB2Ptr fb2(
          drmModeGetFB2(file.GetPlatformFile(), crtc->buffer_id));

      if (!fb && !fb2) {
        LOG(ERROR) << "getfb failed";
        continue;
      }

      std::unique_ptr<Crtc> res_crtc;

      // Multiplane is only handled by egl_capture, so don't bother if
      // GETFB2 isn't supported. Obtain the |plane_res_| for later use.
      //
      // TODO(andrescj): is it possible for |fb2| to be nullptr even if it's
      // possible to query multiple planes? i.e., is there a case where doing
      // drmModeGetFB2() for |crtc->buffer_id| fails but doing it for the planes
      // doesn't?
      if (fb2 && atomic_modeset) {
        ScopedDrmPlaneResPtr plane_res(
            drmModeGetPlaneResources(file.GetPlatformFile()));
        CHECK(plane_res) << " Failed to get plane resources";
        res_crtc = std::make_unique<Crtc>(
            file.Duplicate(), std::move(connector), std::move(encoder),
            std::move(crtc), std::move(fb), std::move(fb2),
            std::move(plane_res));
      }

      if (!res_crtc) {
        res_crtc = std::make_unique<Crtc>(
            file.Duplicate(), std::move(connector), std::move(encoder),
            std::move(crtc), std::move(fb), std::move(fb2), nullptr);
      }

      crtcs.emplace_back(std::move(res_crtc));
    }
  }

  return crtcs;
}

}  // namespace

Crtc::Crtc(base::File file,
           ScopedDrmModeConnectorPtr connector,
           ScopedDrmModeEncoderPtr encoder,
           ScopedDrmModeCrtcPtr crtc,
           ScopedDrmModeFBPtr fb,
           ScopedDrmModeFB2Ptr fb2,
           ScopedDrmPlaneResPtr plane_res)
    : file_(std::move(file)),
      connector_(std::move(connector)),
      encoder_(std::move(encoder)),
      crtc_(std::move(crtc)),
      fb_(std::move(fb)),
      fb2_(std::move(fb2)),
      plane_res_(std::move(plane_res)) {}

bool Crtc::IsInternalDisplay() const {
  switch (connector_->connector_type) {
    case DRM_MODE_CONNECTOR_eDP:
    case DRM_MODE_CONNECTOR_LVDS:
    case DRM_MODE_CONNECTOR_DSI:
    case DRM_MODE_CONNECTOR_VIRTUAL:
      return true;
    default:
      return false;
  }
}

std::unique_ptr<Crtc> CrtcFinder::Find() const {
  auto crtcs = GetConnectedCrtcs();
  for (auto& crtc : crtcs) {
    if (MatchesSpec(crtc.get()))
      return std::move(crtc);
  }
  return nullptr;
}

bool CrtcFinder::MatchesSpec(const Crtc* crtc) const {
  switch (spec_) {
    case Spec::kAnyDisplay:
      return true;
    case Spec::kInternalDisplay:
      return crtc->IsInternalDisplay();
    case Spec::kExternalDisplay:
      return !crtc->IsInternalDisplay();
    case Spec::kById:
      return crtc->crtc()->crtc_id == crtc_id_;
  }
  NOTREACHED() << "Invalid spec";
  return false;
}

std::vector<Crtc::PlaneInfo> Crtc::GetConnectedPlanes() const {
  CHECK(fb2())
      << "This code path is supported only if drmModeGetFB2() succeeded "
         "for the CRTC.";
  std::vector<Crtc::PlaneInfo> planes;
  if (!plane_res_.get()) {
    // Return the empty list if we decided not to query the plane resources or
    // if doing so failed.
    return planes;
  }
  for (uint32_t i = 0; i < plane_res_->count_planes; i++) {
    ScopedDrmPlanePtr plane(
        drmModeGetPlane(file_.GetPlatformFile(), plane_res_->planes[i]));
    if (plane->crtc_id != crtc_->crtc_id) {
      continue;
    }

    PlaneConfiguration conf{};
    bool res = PopulatePlaneConfiguration(file_.GetPlatformFile(),
                                          plane->plane_id, &conf);
    if (!res) {
      LOG(WARNING) << "Failed to query plane position, skipping.\n";
      continue;
    }
    ScopedDrmModeFB2Ptr fb_info(
        drmModeGetFB2(file_.GetPlatformFile(), plane->fb_id));
    if (!fb_info) {
      LOG(WARNING) << "Failed to query plane fb info, skipping.\n";
      continue;
    }
    planes.emplace_back(std::make_pair(std::move(fb_info), conf));
  }
  return planes;
}

}  // namespace screenshot
