// Copyright 2021 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 "render_command_streamer.h"

#include "device_id.h"
#include "instructions.h"
#include "registers.h"

std::unique_ptr<RenderInitBatch> RenderEngineCommandStreamer::CreateRenderInitBatch(
    uint32_t device_id) {
  std::unique_ptr<RenderInitBatch> batch;
  if (DeviceId::is_gen9(device_id)) {
    return std::unique_ptr<RenderInitBatch>(new RenderInitBatchGen9());
  }
  return DRETP(nullptr, "unhandled device id");
}

RenderEngineCommandStreamer::RenderEngineCommandStreamer(EngineCommandStreamer::Owner* owner,
                                                         std::unique_ptr<GpuMapping> hw_status_page)
    : EngineCommandStreamer(owner, RENDER_COMMAND_STREAMER, kRenderEngineMmioBase,
                            std::move(hw_status_page), Scheduler::CreateFifoScheduler()) {
  set_forcewake_domain(ForceWakeDomain::RENDER);
}

bool RenderEngineCommandStreamer::RenderInit(std::shared_ptr<MsdIntelContext> context,
                                             std::unique_ptr<RenderInitBatch> init_batch,
                                             std::shared_ptr<AddressSpace> address_space) {
  DASSERT(context);
  DASSERT(init_batch);
  DASSERT(address_space);

  auto buffer = std::unique_ptr<MsdIntelBuffer>(
      MsdIntelBuffer::Create(init_batch->size(), "render-init-batch"));
  if (!buffer)
    return DRETF(false, "failed to allocate render init buffer");

  auto mapping = init_batch->Init(std::move(buffer), address_space);
  if (!mapping)
    return DRETF(false, "batch init failed");

  std::unique_ptr<SimpleMappedBatch> mapped_batch(
      new SimpleMappedBatch(context, std::move(mapping)));

  return ExecBatch(std::move(mapped_batch));
}

std::unique_ptr<IndirectContextBatch> RenderEngineCommandStreamer::CreateIndirectContextBatch(
    std::shared_ptr<AddressSpace> address_space) {
  auto buffer = std::shared_ptr<MsdIntelBuffer>(
      MsdIntelBuffer::Create(magma::page_size(), "indirect-context-batch"));
  if (!buffer)
    return DRETP(nullptr, "failed to create buffer");

  gpu_addr_t gpu_addr =
      hardware_status_page()->gpu_addr() + GlobalHardwareStatusPage::kScratchOffset;

  constexpr uint32_t kFlags =
      MiPipeControl::kAddressSpaceGen9ClearEuBit | MiPipeControl::kCommandStreamerStallEnableBit;

  uint32_t length = 0;
  {
    void* ptr;
    if (!buffer->platform_buffer()->MapCpu(&ptr))
      return DRETP(nullptr, "failed to map");

    class Writer : public magma::InstructionWriter {
     public:
      Writer(uint32_t* ptr) : ptr_(ptr) {}

      void Write32(uint32_t dword) override {
        *ptr_++ = dword;
        length_ += sizeof(uint32_t);
      }

      uint32_t length() { return length_; }

     private:
      uint32_t* ptr_;
      uint32_t length_ = 0;
    };

    Writer writer(reinterpret_cast<uint32_t*>(ptr));

    MiPipeControl::write(&writer, Sequencer::kInvalidSequenceNumber, gpu_addr, kFlags);

    length = magma::round_up(writer.length(), DeviceId::cache_line_size());

    // Memory should already be zero, but to be sure we pad with no-ops
    static_assert(MiNoop::kDwordCount == 1);
    DASSERT((length - writer.length()) % sizeof(uint32_t) == 0);

    uint32_t noop_count = (length - writer.length()) / sizeof(uint32_t);

    for (uint32_t i = 0; i < noop_count; i++) {
      MiNoop::write(&writer);
    }
    DASSERT(writer.length() % DeviceId::cache_line_size() == 0);

    buffer->platform_buffer()->UnmapCpu();
  }

  auto mapping = AddressSpace::MapBufferGpu(address_space, buffer);
  if (!mapping)
    return DRETP(nullptr, "batch init failed");

  return std::make_unique<IndirectContextBatch>(std::move(mapping), length);
}

bool RenderEngineCommandStreamer::WriteBatchToRingBuffer(MappedBatch* mapped_batch,
                                                         uint32_t* sequence_number_out) {
  auto context = mapped_batch->GetContext().lock();
  DASSERT(context);

  {
    gpu_addr_t gpu_addr;
    // Some "mapped batches" have no batch
    if (mapped_batch->GetGpuAddress(&gpu_addr)) {
      if (!StartBatchBuffer(context.get(), gpu_addr, context->exec_address_space()->type()))
        return DRETF(false, "failed to emit batch");
    }
  }

  uint32_t sequence_number;
  if (!PipeControl(context.get(), mapped_batch->GetPipeControlFlags(), &sequence_number))
    return DRETF(false, "PipeControl failed");

  auto ringbuffer = context->get_ringbuffer(id());

  // TODO(https://fxbug.dev/42078195): don't allocate a sequence number if no space for the user interrupt
  if (!ringbuffer->HasSpace(MiUserInterrupt::kDwordCount * sizeof(uint32_t)))
    return DRETF(false, "ringbuffer has insufficient space");

  MiUserInterrupt::write(ringbuffer);

  *sequence_number_out = sequence_number;

  return true;
}

bool RenderEngineCommandStreamer::PipeControl(MsdIntelContext* context, uint32_t flags,
                                              uint32_t* sequence_number_out) {
  auto ringbuffer = context->get_ringbuffer(id());

  uint32_t dword_count = MiPipeControl::kDwordCount + MiNoop::kDwordCount;

  if (!ringbuffer->HasSpace(dword_count * sizeof(uint32_t)))
    return DRETF(false, "ringbuffer has insufficient space");

  gpu_addr_t gpu_addr =
      hardware_status_page()->gpu_addr() + GlobalHardwareStatusPage::kSequenceNumberOffset;

  uint32_t sequence_number = sequencer()->next_sequence_number();
  DLOG("writing sequence number update to 0x%x", sequence_number);

  MiPipeControl::write(ringbuffer, sequence_number, gpu_addr, flags);
  MiNoop::write(ringbuffer);

  *sequence_number_out = sequence_number;

  return true;
}
