// Copyright 2017 The Fuchsia 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 "garnet/bin/guest/vmm/device/gpu_scanout.h"

#include <zx/vmar.h>

#include "garnet/bin/guest/vmm/device/gpu_resource.h"

void GpuScanout::SetConfigChangedHandler(fit::closure config_changed_handler) {
  config_changed_handler_ = std::move(config_changed_handler);
}

void GpuScanout::SetUpdateSourceHandler(
    fit::function<void(uint32_t, uint32_t)> update_source_handler) {
  update_source_handler_ = std::move(update_source_handler);
}

void GpuScanout::SetFlushHandler(
    fit::function<void(virtio_gpu_rect_t)> flush_handler) {
  flush_handler_ = std::move(flush_handler);
}

zx_status_t GpuScanout::SetFlushTarget(zx::vmo vmo, uint64_t size,
                                       uint32_t width, uint32_t height,
                                       uint32_t stride) {
  // Bind the target and map its memory into our process.
  target_vmo_ = std::move(vmo);
  target_size_ = size;
  target_width_ = width;
  target_height_ = height;
  target_stride_ = stride;
  zx_status_t status = zx::vmar::root_self()->map(
      0, target_vmo_, 0, target_size_,
      ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, &target_vmo_addr_);
  if (status != ZX_OK) {
    return status;
  }

  // Notify the client of the current guest source dimensions, in case this is
  // the first time it has attached.
  if (update_source_handler_) {
    update_source_handler_(extents_.width, extents_.height);
  }

  // Update the scanout extents to match the target.
  extents_.width = width;
  extents_.height = height;
  config_changed_handler_();

  // Force a flush of the entire source region to populate the new target.
  if (source_resource_) {
    OnResourceFlush(source_resource_, source_rect_);
  }
  return ZX_OK;
}

void GpuScanout::OnSetScanout(const GpuResource* source_resource,
                              const virtio_gpu_rect_t& source_rect) {
  source_resource_ = source_resource;
  source_rect_ = source_rect;
  if (update_source_handler_) {
    update_source_handler_(source_rect.width, source_rect.height);
  }
}

static bool overlaps(virtio_gpu_rect_t a, virtio_gpu_rect_t b) {
  if (a.x > (b.x + b.width) || b.x > (a.x + a.width)) {
    return false;
  } else if (a.y > (b.y + b.height) || b.y > (a.y + a.height)) {
    return false;
  } else {
    return true;
  }
}

static virtio_gpu_rect_t clip(virtio_gpu_rect_t rect, virtio_gpu_rect_t clip) {
  if (rect.x < clip.x) {
    rect.width -= clip.x - rect.x;
    rect.x = clip.x;
  }
  if (rect.y < clip.y) {
    rect.height -= clip.y - rect.y;
    rect.y = clip.y;
  }
  if (rect.x + rect.width > clip.x + clip.width) {
    rect.width = clip.x + clip.width - rect.x;
  }
  if (rect.y + rect.height > clip.y + clip.height) {
    rect.height = clip.y + clip.height - rect.y;
  }
  return rect;
}

void GpuScanout::OnResourceFlush(const GpuResource* resource,
                                 const virtio_gpu_rect_t& rect) {
  if (resource != source_resource_ || !overlaps(rect, source_rect_)) {
    return;
  }
  virtio_gpu_rect_t flush_rect = clip(rect, extents_);
  if (target_vmo_) {
    // Copy the flushed region to the target.
    uint32_t row_begin = flush_rect.y;
    uint32_t row_end =
        std::min(flush_rect.y + flush_rect.height, target_height_);
    uint32_t row_bytes =
        std::min(flush_rect.width, target_width_ - flush_rect.x) *
        resource->pixel_size();
    for (uint32_t row = row_begin; row < row_end; ++row) {
      uint8_t* dest = reinterpret_cast<uint8_t*>(target_vmo_addr_) +
                      target_stride_ * row +
                      flush_rect.x * resource->pixel_size();
      const uint8_t* src = source_resource_->data() +
                           source_resource_->stride() * row +
                           flush_rect.x * resource->pixel_size();
      memcpy(dest, src, row_bytes);
    }
  }
  if (flush_handler_) {
    flush_handler_(flush_rect);
  }
}

void GpuScanout::OnUpdateCursor(const GpuResource* cursor_resource,
                                uint32_t hot_x, uint32_t hot_y) {
  cursor_resource_ = cursor_resource;
  cursor_hot_x_ = hot_x;
  cursor_hot_y_ = hot_y;
}

void GpuScanout::OnMoveCursor(uint32_t x, uint32_t y) {
  cursor_x_ = x;
  cursor_y_ = y;
}
