// 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 "screenshot/crtc.h"

#include <algorithm>
#include <utility>
#include <vector>

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

namespace screenshot {

namespace {

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

bool PopulatePlanePosition(int fd, uint32_t plane_id, PlanePosition* pos) {
  struct {
    const char* name;
    uint64_t val;
  } crtc_props[4] = {
      {"CRTC_X", 0}, {"CRTC_Y", 0}, {"CRTC_W", 0}, {"CRTC_H", 0},
      // TODO(dcastagna): Handle SRC_ and rotation
  };

  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;
    }

    for (int j = 0; j < base::size(crtc_props); j++) {
      if (strcmp(crtc_props[j].name, prop->name) == 0) {
        crtc_props[j].val = props->prop_values[i];
        found++;
      }
    }
  }

  if (found != base::size(crtc_props)) {
    return false;
  }

  pos->x = static_cast<int32_t>(crtc_props[0].val);
  pos->y = static_cast<int32_t>(crtc_props[1].val);
  pos->w = static_cast<uint32_t>(crtc_props[2].val);
  pos->h = static_cast<uint32_t>(crtc_props[3].val);
  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.push_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.
      if (fb2 && atomic_modeset) {
        ScopedDrmPlaneResPtr plane_res(
            drmModeGetPlaneResources(file.GetPlatformFile()));
        CHECK(plane_res) << " Failed to get plane resources";

        std::vector<Crtc::PlaneInfo> 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 != encoder->crtc_id) {
            continue;
          }

          PlanePosition pos{};
          bool res = PopulatePlanePosition(file.GetPlatformFile(),
                                           plane->plane_id, &pos);
          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.push_back(std::make_pair(std::move(fb_info), pos));
        }

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

      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));
      }

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

  return crtcs;
}

}  // namespace

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

Crtc::Crtc(base::File file,
           ScopedDrmModeConnectorPtr connector,
           ScopedDrmModeEncoderPtr encoder,
           ScopedDrmModeCrtcPtr crtc,
           std::vector<PlaneInfo> planes)
    : file_(std::move(file)),
      connector_(std::move(connector)),
      encoder_(std::move(encoder)),
      crtc_(std::move(crtc)),
      planes_(std::move(planes)) {}

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;
  }
}

// static
std::unique_ptr<Crtc> CrtcFinder::FindAnyDisplay() {
  auto crtcs = GetConnectedCrtcs();
  if (crtcs.empty())
    return nullptr;
  return std::move(crtcs[0]);
}

// static
std::unique_ptr<Crtc> CrtcFinder::FindInternalDisplay() {
  auto crtcs = GetConnectedCrtcs();
  for (auto& crtc : crtcs)
    if (crtc->IsInternalDisplay())
      return std::move(crtc);
  return nullptr;
}

// static
std::unique_ptr<Crtc> CrtcFinder::FindExternalDisplay() {
  auto crtcs = GetConnectedCrtcs();
  for (auto& crtc : crtcs)
    if (!crtc->IsInternalDisplay())
      return std::move(crtc);
  return nullptr;
}

// static
std::unique_ptr<Crtc> CrtcFinder::FindById(uint32_t crtc_id) {
  auto crtcs = GetConnectedCrtcs();
  for (auto& crtc : crtcs)
    if (crtc->crtc()->crtc_id == crtc_id)
      return std::move(crtc);
  return nullptr;
}

}  // namespace screenshot
