// 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
