// Copyright 2018 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/lib/ui/gfx/gfx_system.h"

#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/logger.h>
#include <lib/vfs/cpp/pseudo_file.h>
#include <zircon/assert.h>

#include "garnet/lib/ui/gfx/engine/default_frame_scheduler.h"
#include "garnet/lib/ui/gfx/engine/session_handler.h"
#include "garnet/lib/ui/gfx/screenshotter.h"
#include "garnet/lib/ui/scenic/scenic.h"
#include "src/ui/lib/escher/escher_process_init.h"
#include "src/ui/lib/escher/fs/hack_filesystem.h"
#include "src/ui/lib/escher/util/check_vulkan_support.h"

namespace scenic_impl {
namespace gfx {

static const uint32_t kDumpScenesBufferCapacity = 1024 * 64;
const char* GfxSystem::kName = "GfxSystem";

GfxSystem::GfxSystem(SystemContext context,
                     std::unique_ptr<DisplayManager> display_manager)
    : TempSystemDelegate(std::move(context), false),
      display_manager_(std::move(display_manager)) {
  // TODO(SCN-1111): what are the intended implications of there being a test
  // display?  In this case, could we make DisplayManager signal that the
  // display is ready, even though it it is a test display?
  if (display_manager_->default_display() &&
      display_manager_->default_display()->is_test_display()) {
    async::PostTask(async_get_default_dispatcher(), DelayedInitClosure());
    return;
  }

  display_manager_->WaitForDefaultDisplay(DelayedInitClosure());
}

GfxSystem::~GfxSystem() {
  if (escher_) {
    // It's possible that |escher_| never got created (and therefore
    // escher::GlslangInitializeProcess() was never called).
    escher::GlslangFinalizeProcess();
  }
  if (vulkan_instance_) {
    vulkan_instance_->proc_addrs().DestroyDebugReportCallbackEXT(
        vulkan_instance_->vk_instance(), debug_report_callback_, nullptr);
  }
}

CommandDispatcherUniquePtr GfxSystem::CreateCommandDispatcher(
    CommandDispatcherContext context) {
  return engine_->session_manager()->CreateCommandDispatcher(
      std::move(context), engine_->session_context());
}

std::unique_ptr<Engine> GfxSystem::InitializeEngine() {
  return std::make_unique<Engine>(
      context()->app_context(),
      std::make_unique<DefaultFrameScheduler>(
          display_manager_->default_display(),
          context()->inspect_node()->CreateChild("FrameScheduler")),
      std::make_unique<SessionManager>(
          context()->inspect_node()->CreateChild("SessionManager")),
      display_manager_.get(), escher_->GetWeakPtr(),
      context()->inspect_node()->CreateChild("Engine"));
}

std::unique_ptr<escher::Escher> GfxSystem::InitializeEscher() {
  // TODO(SCN-1109): VulkanIsSupported() should not be used in production.
  // It tries to create a VkInstance and VkDevice, and immediately deletes them
  // regardless of success/failure.
  if (!escher::VulkanIsSupported()) {
    return nullptr;
  }

  if (!display_manager_->is_initialized()) {
    FXL_LOG(ERROR) << "No sysmem allocator available";
    return nullptr;
  }

  // Initialize Vulkan.
  constexpr bool kRequiresSurface = false;
  escher::VulkanInstance::Params instance_params(
      {{},
       {
           VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
           VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
           VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
           VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
           VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
       },
       kRequiresSurface});

// Only enable Vulkan validation layers when in debug mode.
#if !defined(NDEBUG)
  instance_params.layer_names.insert("VK_LAYER_LUNARG_standard_validation");
#endif
  vulkan_instance_ = escher::VulkanInstance::New(std::move(instance_params));

  // Tell Escher not to filter out queues that don't support presentation.
  // The display manager only supports a single connection, so none of the
  // available queues will support presentation.  This is OK, because we use
  // the display manager API to present frames directly, instead of using
  // Vulkan swapchains.
  escher::VulkanDeviceQueues::Params device_queues_params(
      {{VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
        VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME,
        VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
        VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
        VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME,
        VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
        VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
        VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME},
       surface_,
       escher::VulkanDeviceQueues::Params::kDisableQueueFilteringForPresent});
  vulkan_device_queues_ =
      escher::VulkanDeviceQueues::New(vulkan_instance_, device_queues_params);

  {
    VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
    dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
    dbgCreateInfo.pNext = NULL;
    dbgCreateInfo.pfnCallback = RedirectDebugReport;
    dbgCreateInfo.pUserData = this;
    dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
                          VK_DEBUG_REPORT_WARNING_BIT_EXT |
                          VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;

    // We use the C API here due to dynamically loading the extension function.
    VkResult result =
        vulkan_instance_->proc_addrs().CreateDebugReportCallbackEXT(
            vulkan_instance_->vk_instance(), &dbgCreateInfo, nullptr,
            &debug_report_callback_);
    FXL_CHECK(result == VK_SUCCESS);
  }

  // Provide a PseudoDir where the gfx system can register debugging services.
  auto debug_dir = std::make_shared<vfs::PseudoDir>();
  context()->app_context()->outgoing()->debug_dir()->AddSharedEntry("gfx",
                                                                    debug_dir);
  auto shader_fs = escher::HackFilesystem::New(debug_dir);
  {
    bool success = shader_fs->InitializeWithRealFiles(
        {"shaders/model_renderer/main.frag", "shaders/model_renderer/main.vert",
         "shaders/model_renderer/default_position.vert",
         "shaders/model_renderer/shadow_map_generation.frag",
         "shaders/model_renderer/shadow_map_lighting.frag",
         "shaders/model_renderer/wobble_position.vert",
         "shaders/paper/common/use.glsl",
         "shaders/paper/frag/main_ambient_light.frag",
         "shaders/paper/frag/main_point_light.frag",
         "shaders/paper/vert/compute_model_space_position.vert",
         "shaders/paper/vert/compute_world_space_position.vert",
         "shaders/paper/vert/main_shadow_volume_extrude.vert",
         "shaders/paper/vert/vertex_attributes.vert"});
    FXL_DCHECK(success) << "Failed to init shader files.";
  }

  // Initialize Escher.
  escher::GlslangInitializeProcess();
  return std::make_unique<escher::Escher>(vulkan_device_queues_,
                                          std::move(shader_fs));
}

fit::closure GfxSystem::DelayedInitClosure() {
  // This must *not* be executed  directly in the constructor, due to the use of
  // virtual methods, such as InitializeEscher() inside Initialize().
  return [this] {
    // Don't initialize Vulkan and the system until display is ready.
    Initialize();
    initialized_ = true;

    for (auto& closure : run_after_initialized_) {
      closure();
    }
    run_after_initialized_.clear();
  };
}

void GfxSystem::Initialize() {
  Display* display = display_manager_->default_display();
  if (!display) {
    FXL_LOG(ERROR) << "No default display, Graphics system exiting";
    context()->Quit();
    return;
  }

  // This is virtual, allowing tests to avoid instantiating an Escher.
  escher_ = InitializeEscher();
  if (!escher_ || !escher_->device()) {
    if (display->is_test_display()) {
      FXL_LOG(INFO) << "No Vulkan found, but using a test-only \"display\".";
    } else {
      FXL_LOG(ERROR) << "No Vulkan on device, Graphics system exiting.";
      context()->Quit();
      return;
    }
  }

  // Initialize the Scenic engine.
  engine_ = InitializeEngine();

  // Create a pseudo-file that dumps alls the Scenic scenes.
  context()->app_context()->outgoing()->debug_dir()->AddEntry(
      "dump-scenes",
      std::make_unique<vfs::PseudoFile>(
          kDumpScenesBufferCapacity,
          [this](std::vector<uint8_t>* output, size_t max_file_size) {
            auto out = engine_->DumpScenes();
            ZX_DEBUG_ASSERT(out.length() <= max_file_size);
            output->resize(out.length());
            std::copy(out.begin(), out.end(), output->begin());
            return ZX_OK;
          },
          nullptr));

  SetToInitialized();
};

void GfxSystem::GetDisplayInfoImmediately(
    fuchsia::ui::scenic::Scenic::GetDisplayInfoCallback callback) {
  FXL_DCHECK(initialized_);
  Display* display = display_manager_->default_display();
  FXL_CHECK(display) << "There must be a default display.";

  auto info = ::fuchsia::ui::gfx::DisplayInfo();
  info.width_in_px = display->width_in_px();
  info.height_in_px = display->height_in_px();

  callback(std::move(info));
}

void GfxSystem::GetDisplayInfo(
    fuchsia::ui::scenic::Scenic::GetDisplayInfoCallback callback) {
  if (initialized_) {
    GetDisplayInfoImmediately(std::move(callback));
  } else {
    run_after_initialized_.push_back(
        [this, callback = std::move(callback)]() mutable {
          GetDisplayInfoImmediately(std::move(callback));
        });
  }
};

void GfxSystem::TakeScreenshot(
    fuchsia::ui::scenic::Scenic::TakeScreenshotCallback callback) {
  if (initialized_) {
    Screenshotter::TakeScreenshot(engine_.get(), std::move(callback));
  } else {
    run_after_initialized_.push_back(
        [this, callback = std::move(callback)]() mutable {
          Screenshotter::TakeScreenshot(engine_.get(), std::move(callback));
        });
  }
}

void GfxSystem::GetDisplayOwnershipEventImmediately(
    fuchsia::ui::scenic::Scenic::GetDisplayOwnershipEventCallback callback) {
  FXL_DCHECK(initialized_);
  Display* display = display_manager_->default_display();

  // TODO(SCN-1109):VulkanIsSupported() should not be called by production code.
  if (escher::VulkanIsSupported()) {
    FXL_CHECK(display) << "There must be a default display.";
  }

  static_assert(fuchsia::ui::scenic::displayNotOwnedSignal == ZX_USER_SIGNAL_0,
                "Bad constant");
  static_assert(fuchsia::ui::scenic::displayOwnedSignal == ZX_USER_SIGNAL_1,
                "Bad constant");

  zx::event dup;
  if (display->ownership_event().duplicate(ZX_RIGHTS_BASIC, &dup) != ZX_OK) {
    FXL_LOG(ERROR) << "## Vulkan display event dup error";
  } else {
    callback(std::move(dup));
  }
}

void GfxSystem::GetDisplayOwnershipEvent(
    fuchsia::ui::scenic::Scenic::GetDisplayOwnershipEventCallback callback) {
  if (initialized_) {
    GetDisplayOwnershipEventImmediately(std::move(callback));
  } else {
    run_after_initialized_.push_back(
        [this, callback = std::move(callback)]() mutable {
          GetDisplayOwnershipEventImmediately(std::move(callback));
        });
  }
}

VkBool32 GfxSystem::HandleDebugReport(VkDebugReportFlagsEXT flags_in,
                                      VkDebugReportObjectTypeEXT object_type_in,
                                      uint64_t object, size_t location,
                                      int32_t message_code,
                                      const char* pLayerPrefix,
                                      const char* pMessage) {
  vk::DebugReportFlagsEXT flags(
      static_cast<vk::DebugReportFlagBitsEXT>(flags_in));
  vk::DebugReportObjectTypeEXT object_type(
      static_cast<vk::DebugReportObjectTypeEXT>(object_type_in));

  // TODO(SCN-704) remove this block
  if (object_type == vk::DebugReportObjectTypeEXT::eDeviceMemory &&
      message_code == 385878038) {
    FXL_LOG(WARNING) << "Ignoring Vulkan Memory Type Error, see SCN-704";
  }

#define VK_DEBUG_REPORT_MESSAGE                                         \
  pMessage << " (layer: " << pLayerPrefix << "  code: " << message_code \
           << "  object-type: " << vk::to_string(object_type)           \
           << "  object: " << object << ")" << std::endl;

  bool fatal = false;
  if (flags == vk::DebugReportFlagBitsEXT::eInformation) {
    FXL_LOG(INFO) << "## Vulkan Information: " << VK_DEBUG_REPORT_MESSAGE;
  } else if (flags == vk::DebugReportFlagBitsEXT::eWarning) {
    FXL_LOG(WARNING) << "## Vulkan Warning: " << VK_DEBUG_REPORT_MESSAGE;
  } else if (flags == vk::DebugReportFlagBitsEXT::ePerformanceWarning) {
    FXL_LOG(WARNING) << "## Vulkan Performance Warning: "
                     << VK_DEBUG_REPORT_MESSAGE;
  } else if (flags == vk::DebugReportFlagBitsEXT::eError) {
    // Treat all errors as fatal.
    fatal = true;
    FXL_LOG(ERROR) << "## Vulkan Error: " << VK_DEBUG_REPORT_MESSAGE;
  } else if (flags == vk::DebugReportFlagBitsEXT::eDebug) {
    FXL_LOG(INFO) << "## Vulkan Debug: " << VK_DEBUG_REPORT_MESSAGE;
  } else {
    // This should never happen, unless a new value has been added to
    // vk::DebugReportFlagBitsEXT.  In that case, add a new if-clause above.
    fatal = true;
    FXL_LOG(ERROR) << "## Vulkan Unknown Message Type (flags: "
                   << vk::to_string(flags) << "): ";
  }

  // Crash immediately on fatal errors.
  FX_CHECK(!fatal);

  return false;

#undef VK_DEBUG_REPORT_MESSAGE
}

CompositorWeakPtr GfxSystem::GetCompositor(GlobalId compositor_id) const {
  return engine_->scene_graph()->GetCompositor(compositor_id);
}

gfx::Session* GfxSystem::GetSession(SessionId session_id) const {
  SessionHandler* handler =
      engine_->session_manager()->FindSessionHandler(session_id);
  return handler ? handler->session() : nullptr;
}

void GfxSystem::AddInitClosure(fit::closure closure) {
  run_after_initialized_.push_back(std::move(closure));
}

}  // namespace gfx
}  // namespace scenic_impl
