/*
 * Copyright (C) 2014 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.
 */

#include "graphics_adf.h"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>

#include <adf/adf.h>
#include <sync/sync.h>

#include "minui/minui.h"

MinuiBackendAdf::MinuiBackendAdf()
    : intf_fd(-1), dev(), current_surface(0), n_surfaces(0), surfaces() {}

int MinuiBackendAdf::SurfaceInit(const drm_mode_modeinfo* mode, GRSurfaceAdf* surf) {
  *surf = {};
  surf->fence_fd = -1;
  surf->fd = adf_interface_simple_buffer_alloc(intf_fd, mode->hdisplay, mode->vdisplay, format,
                                               &surf->offset, &surf->pitch);
  if (surf->fd < 0) {
    return surf->fd;
  }

  surf->width = mode->hdisplay;
  surf->height = mode->vdisplay;
  surf->row_bytes = surf->pitch;
  surf->pixel_bytes = (format == DRM_FORMAT_RGB565) ? 2 : 4;

  auto mmapped =
      mmap(nullptr, surf->pitch * surf->height, PROT_WRITE, MAP_SHARED, surf->fd, surf->offset);
  if (mmapped == MAP_FAILED) {
    int saved_errno = errno;
    close(surf->fd);
    return -saved_errno;
  }
  surf->mmapped_buffer_ = static_cast<uint8_t*>(mmapped);
  return 0;
}

int MinuiBackendAdf::InterfaceInit() {
  adf_interface_data intf_data;
  int err = adf_get_interface_data(intf_fd, &intf_data);
  if (err < 0) return err;

  int ret = 0;
  err = SurfaceInit(&intf_data.current_mode, &surfaces[0]);
  if (err < 0) {
    fprintf(stderr, "allocating surface 0 failed: %s\n", strerror(-err));
    ret = err;
    goto done;
  }

  err = SurfaceInit(&intf_data.current_mode, &surfaces[1]);
  if (err < 0) {
    fprintf(stderr, "allocating surface 1 failed: %s\n", strerror(-err));
    surfaces[1] = {};
    n_surfaces = 1;
  } else {
    n_surfaces = 2;
  }

done:
  adf_free_interface_data(&intf_data);
  return ret;
}

int MinuiBackendAdf::DeviceInit(adf_device* dev) {
  adf_id_t intf_id;
  int err = adf_find_simple_post_configuration(dev, &format, 1, &intf_id, &eng_id);
  if (err < 0) return err;

  err = adf_device_attach(dev, eng_id, intf_id);
  if (err < 0 && err != -EALREADY) return err;

  intf_fd = adf_interface_open(dev, intf_id, O_RDWR);
  if (intf_fd < 0) return intf_fd;

  err = InterfaceInit();
  if (err < 0) {
    close(intf_fd);
    intf_fd = -1;
  }

  return err;
}

GRSurface* MinuiBackendAdf::Init() {
  PixelFormat pixel_format = gr_pixel_format();
  if (pixel_format == PixelFormat::ABGR) {
    format = DRM_FORMAT_ABGR8888;
  } else if (pixel_format == PixelFormat::BGRA) {
    format = DRM_FORMAT_BGRA8888;
  } else if (pixel_format == PixelFormat::RGBX) {
    format = DRM_FORMAT_RGBX8888;
  } else {
    format = DRM_FORMAT_RGB565;
  }

  adf_id_t* dev_ids = nullptr;
  ssize_t n_dev_ids = adf_devices(&dev_ids);
  if (n_dev_ids == 0) {
    return nullptr;
  } else if (n_dev_ids < 0) {
    fprintf(stderr, "enumerating adf devices failed: %s\n", strerror(-n_dev_ids));
    return nullptr;
  }

  intf_fd = -1;

  for (ssize_t i = 0; i < n_dev_ids && intf_fd < 0; i++) {
    int err = adf_device_open(dev_ids[i], O_RDWR, &dev);
    if (err < 0) {
      fprintf(stderr, "opening adf device %u failed: %s\n", dev_ids[i], strerror(-err));
      continue;
    }

    err = DeviceInit(&dev);
    if (err < 0) {
      fprintf(stderr, "initializing adf device %u failed: %s\n", dev_ids[i], strerror(-err));
      adf_device_close(&dev);
    }
  }

  free(dev_ids);

  if (intf_fd < 0) return nullptr;

  GRSurface* ret = Flip();

  Blank(true);
  Blank(false);

  return ret;
}

void MinuiBackendAdf::Sync(GRSurfaceAdf* surf) {
  static constexpr unsigned int warningTimeout = 3000;

  if (surf == nullptr) return;

  if (surf->fence_fd >= 0) {
    int err = sync_wait(surf->fence_fd, warningTimeout);
    if (err < 0) {
      perror("adf sync fence wait error\n");
    }

    close(surf->fence_fd);
    surf->fence_fd = -1;
  }
}

GRSurface* MinuiBackendAdf::Flip() {
  GRSurfaceAdf* surf = &surfaces[current_surface];

  int fence_fd = adf_interface_simple_post(intf_fd, eng_id, surf->width, surf->height, format,
                                           surf->fd, surf->offset, surf->pitch, -1);
  if (fence_fd >= 0) surf->fence_fd = fence_fd;

  current_surface = (current_surface + 1) % n_surfaces;
  Sync(&surfaces[current_surface]);
  return &surfaces[current_surface];
}

void MinuiBackendAdf::Blank(bool blank) {
  adf_interface_blank(intf_fd, blank ? DRM_MODE_DPMS_OFF : DRM_MODE_DPMS_ON);
}

void MinuiBackendAdf::SurfaceDestroy(GRSurfaceAdf* surf) {
  if (surf->mmapped_buffer_) {
    munmap(surf->mmapped_buffer_, surf->pitch * surf->height);
  }
  close(surf->fence_fd);
  close(surf->fd);
}

MinuiBackendAdf::~MinuiBackendAdf() {
  adf_device_close(&dev);
  for (unsigned int i = 0; i < n_surfaces; i++) {
    SurfaceDestroy(&surfaces[i]);
  }
  if (intf_fd >= 0) close(intf_fd);
}
