// Copyright 2022 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 "src/graphics/display/drivers/intel-display/intel-display.h"

#include <fidl/fuchsia.sysmem2/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async-loop/loop.h>
#include <lib/driver/testing/cpp/scoped_global_logger.h>
#include <lib/mmio-ptr/fake.h>

#include <gtest/gtest.h>

#include "src/devices/pci/testing/pci_protocol_fake.h"
#include "src/graphics/display/drivers/intel-display/registers.h"
#include "src/graphics/display/drivers/intel-display/testing/fake-buffer-collection.h"
#include "src/graphics/display/drivers/intel-display/testing/mock-allocator.h"
#include "src/graphics/display/lib/api-protocols/cpp/display-engine-events-fidl.h"
#include "src/graphics/display/lib/api-types/cpp/driver-buffer-collection-id.h"
#include "src/lib/fsl/handles/object_info.h"
#include "src/lib/testing/predicates/status.h"

namespace {

constexpr uint32_t kBytesPerRowDivisor = 1024;

}  // namespace

namespace intel_display {

namespace {

// Test fixture for tests that only uses fake sysmem but doesn't have any
// other dependency, so that we won't need a fully-fledged device tree.
class FakeSysmemSingleThreadedTest : public testing::Test {
 public:
  FakeSysmemSingleThreadedTest()
      : loop_(&kAsyncLoopConfigAttachToCurrentThread),
        sysmem_(loop_.dispatcher()),
        display_(&engine_events_, inspect::Inspector{}) {}

  void SetUp() override {
    auto [sysmem_client, sysmem_server] = fidl::Endpoints<fuchsia_sysmem2::Allocator>::Create();
    fidl::BindServer(loop_.dispatcher(), std::move(sysmem_server), &sysmem_);

    sysmem_.SetNewBufferCollectionConfig({
        .cpu_domain_supported = false,
        .ram_domain_supported = true,
        .inaccessible_domain_supported = false,
        .bytes_per_row_divisor = kBytesPerRowDivisor,
        .format_modifier = fuchsia_images2::wire::PixelFormatModifier::kLinear,
    });

    ASSERT_OK(display_.SetAndInitSysmemForTesting(fidl::WireSyncClient(std::move(sysmem_client))));
    EXPECT_OK(loop_.RunUntilIdle());
  }

  void TearDown() override {
    // Shutdown the loop before destroying the FakeSysmem and MockAllocator which
    // may still have pending callbacks.
    loop_.Shutdown();
  }

 protected:
  fdf_testing::ScopedGlobalLogger logger_;
  async::Loop loop_;

  MockAllocator sysmem_;

  // Must outlive `display_`.
  display::DisplayEngineEventsFidl engine_events_;
  Controller display_;
};

using ControllerWithFakeSysmemTest = FakeSysmemSingleThreadedTest;

TEST_F(ControllerWithFakeSysmemTest, ImportBufferCollection) {
  const MockAllocator& allocator = sysmem_;

  zx::result token1_endpoints = fidl::CreateEndpoints<fuchsia_sysmem2::BufferCollectionToken>();
  ASSERT_TRUE(token1_endpoints.is_ok());
  zx::result token2_endpoints = fidl::CreateEndpoints<fuchsia_sysmem2::BufferCollectionToken>();
  ASSERT_TRUE(token2_endpoints.is_ok());

  // Test ImportBufferCollection().
  constexpr display::DriverBufferCollectionId kValidBufferCollectionId(1);
  EXPECT_OK(display_.ImportBufferCollection(kValidBufferCollectionId,
                                            std::move(token1_endpoints->client)));

  // `collection_id` must be unused.
  EXPECT_STATUS(display_.ImportBufferCollection(kValidBufferCollectionId,
                                                std::move(token2_endpoints->client)),
                zx::error(ZX_ERR_ALREADY_EXISTS));

  loop_.RunUntilIdle();

  // Verify that the current buffer collection token is used.
  {
    auto active_buffer_token_clients = allocator.GetActiveBufferCollectionTokenClients();
    EXPECT_EQ(active_buffer_token_clients.size(), 1u);

    auto inactive_buffer_token_clients = allocator.GetInactiveBufferCollectionTokenClients();
    EXPECT_EQ(inactive_buffer_token_clients.size(), 0u);

    auto [client_koid, client_related_koid] =
        fsl::GetKoids(active_buffer_token_clients[0].channel()->get());
    auto [server_koid, server_related_koid] =
        fsl::GetKoids(token1_endpoints->server.channel().get());

    EXPECT_NE(client_koid, ZX_KOID_INVALID);
    EXPECT_NE(client_related_koid, ZX_KOID_INVALID);
    EXPECT_NE(server_koid, ZX_KOID_INVALID);
    EXPECT_NE(server_related_koid, ZX_KOID_INVALID);

    EXPECT_EQ(client_koid, server_related_koid);
    EXPECT_EQ(server_koid, client_related_koid);
  }

  // Test ReleaseBufferCollection().
  constexpr display::DriverBufferCollectionId kInvalidBufferCollectionId(2);
  EXPECT_STATUS(display_.ReleaseBufferCollection(kInvalidBufferCollectionId),
                zx::error(ZX_ERR_NOT_FOUND));
  EXPECT_OK(display_.ReleaseBufferCollection(kValidBufferCollectionId));

  loop_.RunUntilIdle();

  // Verify that the current buffer collection token is released.
  {
    auto active_buffer_token_clients = allocator.GetActiveBufferCollectionTokenClients();
    EXPECT_EQ(active_buffer_token_clients.size(), 0u);

    auto inactive_buffer_token_clients = allocator.GetInactiveBufferCollectionTokenClients();
    EXPECT_EQ(inactive_buffer_token_clients.size(), 1u);

    auto [client_koid, client_related_koid] =
        fsl::GetKoids(inactive_buffer_token_clients[0].channel()->get());
    auto [server_koid, server_related_koid] =
        fsl::GetKoids(token1_endpoints->server.channel().get());

    EXPECT_NE(client_koid, ZX_KOID_INVALID);
    EXPECT_NE(client_related_koid, ZX_KOID_INVALID);
    EXPECT_NE(server_koid, ZX_KOID_INVALID);
    EXPECT_NE(server_related_koid, ZX_KOID_INVALID);

    EXPECT_EQ(client_koid, server_related_koid);
    EXPECT_EQ(server_koid, client_related_koid);
  }
}

fdf::MmioBuffer MakeMmioBuffer(uint8_t* buffer, size_t size) {
  return fdf::MmioBuffer({
      .vaddr = FakeMmioPtr(buffer),
      .offset = 0,
      .size = size,
      .vmo = ZX_HANDLE_INVALID,
  });
}

TEST(IntelDisplay, ImportImage) {
  fdf_testing::ScopedGlobalLogger logger;
  async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
  loop.StartThread("fidl-loop");

  // Prepare fake sysmem.
  MockAllocator fake_sysmem(loop.dispatcher());
  auto [sysmem_client, sysmem_server] = fidl::Endpoints<fuchsia_sysmem2::Allocator>::Create();
  fidl::BindServer(loop.dispatcher(), std::move(sysmem_server), &fake_sysmem);

  // Prepare fake PCI.
  pci::FakePciProtocol fake_pci;
  ddk::Pci pci = fake_pci.SetUpFidlServer(loop);

  fake_sysmem.SetNewBufferCollectionConfig({
      .cpu_domain_supported = false,
      .ram_domain_supported = true,
      .inaccessible_domain_supported = false,

      .width_fallback_px = 32,
      .height_fallback_px = 32,
      .bytes_per_row_divisor = kBytesPerRowDivisor,
      .format_modifier = fuchsia_images2::wire::PixelFormatModifier::kLinear,
  });

  // Initialize display controller and sysmem allocator.

  // Must outlive `display`.
  display::DisplayEngineEventsFidl display_events;
  Controller display(&display_events, inspect::Inspector{});
  ASSERT_OK(display.SetAndInitSysmemForTesting(fidl::WireSyncClient(std::move(sysmem_client))));

  // Initialize the GTT to the smallest allowed size (which is 2MB with the |gtt_size| bits of the
  // graphics control register set to 0x01.
  constexpr size_t kGraphicsTranslationTableSizeBytes = (1 << 21);
  ASSERT_OK(pci.WriteConfig16(registers::GmchGfxControl::kAddr,
                              registers::GmchGfxControl().set_gtt_size(0x01).reg_value()));
  auto buffer = std::make_unique<uint8_t[]>(kGraphicsTranslationTableSizeBytes);
  memset(buffer.get(), 0, kGraphicsTranslationTableSizeBytes);
  fdf::MmioBuffer mmio = MakeMmioBuffer(buffer.get(), kGraphicsTranslationTableSizeBytes);
  ASSERT_OK(display.InitGttForTesting(pci, std::move(mmio), /*fb_offset=*/0));

  // Import buffer collection.
  constexpr display::DriverBufferCollectionId kBufferCollectionId(1);
  zx::result token_endpoints = fidl::CreateEndpoints<fuchsia_sysmem2::BufferCollectionToken>();
  ASSERT_TRUE(token_endpoints.is_ok());
  EXPECT_OK(
      display.ImportBufferCollection(kBufferCollectionId, std::move(token_endpoints->client)));

  static constexpr display::ImageBufferUsage kDisplayUsage({
      .tiling_type = display::ImageTilingType::kLinear,
  });
  EXPECT_OK(display.SetBufferCollectionConstraints(kDisplayUsage, kBufferCollectionId));

  // Invalid import: bad collection id
  static constexpr display::ImageMetadata kDisplayImageMetadata = {{
      .width = 32,
      .height = 32,
      .tiling_type = display::ImageTilingType::kLinear,
  }};
  static constexpr display::DriverBufferCollectionId kInvalidCollectionId(100);

  zx::result<display::DriverImageId> import_result =
      display.ImportImage(kDisplayImageMetadata, kInvalidCollectionId, 0);
  EXPECT_STATUS(import_result, zx::error(ZX_ERR_NOT_FOUND));

  // Invalid import: bad index
  static constexpr uint32_t kInvalidIndex = 100;
  import_result = display.ImportImage(kDisplayImageMetadata, kBufferCollectionId, kInvalidIndex);
  EXPECT_STATUS(import_result, zx::error(ZX_ERR_OUT_OF_RANGE));

  // Invalid import: bad type
  static constexpr display::ImageMetadata kInvalidTilingTypeMetadata = {{
      .width = 32,
      .height = 32,
      .tiling_type = display::ImageTilingType::kCapture,
  }};
  import_result = display.ImportImage(kInvalidTilingTypeMetadata, kBufferCollectionId,
                                      /*index=*/0);
  EXPECT_STATUS(import_result, zx::error(ZX_ERR_INVALID_ARGS));

  // Valid import
  import_result = display.ImportImage(kDisplayImageMetadata, kBufferCollectionId, 0);
  ASSERT_OK(import_result);

  display::DriverImageId image_id = import_result.value();
  EXPECT_NE(image_id.value(), 0u);

  display.ReleaseImage(image_id);

  // Release buffer collection.
  EXPECT_OK(display.ReleaseBufferCollection(kBufferCollectionId));

  // Shutdown the loop before destroying the FakeSysmem and MockAllocator which
  // may still have pending callbacks.
  loop.Shutdown();
}

TEST_F(ControllerWithFakeSysmemTest, SysmemRequirements) {
  zx::result token_endpoints = fidl::CreateEndpoints<fuchsia_sysmem2::BufferCollectionToken>();
  ASSERT_TRUE(token_endpoints.is_ok());

  constexpr display::DriverBufferCollectionId kBufferCollectionId(1);
  EXPECT_OK(
      display_.ImportBufferCollection(kBufferCollectionId, std::move(token_endpoints->client)));

  loop_.RunUntilIdle();

  static constexpr display::ImageBufferUsage kDisplayUsage({
      .tiling_type = display::ImageTilingType::kLinear,
  });
  EXPECT_OK(display_.SetBufferCollectionConstraints(kDisplayUsage, kBufferCollectionId));

  loop_.RunUntilIdle();

  MockAllocator& allocator = sysmem_;
  FakeBufferCollection* collection = allocator.GetMostRecentBufferCollection();
  ASSERT_TRUE(collection);
  EXPECT_TRUE(collection->HasConstraints());
}

TEST_F(ControllerWithFakeSysmemTest, SysmemInvalidType) {
  zx::result token_endpoints = fidl::CreateEndpoints<fuchsia_sysmem2::BufferCollectionToken>();
  ASSERT_TRUE(token_endpoints.is_ok());

  constexpr display::DriverBufferCollectionId kBufferCollectionId(1);
  EXPECT_OK(
      display_.ImportBufferCollection(kBufferCollectionId, std::move(token_endpoints->client)));

  loop_.RunUntilIdle();

  static constexpr display::ImageBufferUsage kInvalidTilingUsage({
      .tiling_type = display::ImageTilingType(1000000),
  });
  EXPECT_STATUS(zx::error(ZX_ERR_INVALID_ARGS),
                display_.SetBufferCollectionConstraints(kInvalidTilingUsage, kBufferCollectionId));

  loop_.RunUntilIdle();

  MockAllocator& allocator = sysmem_;
  FakeBufferCollection* collection = allocator.GetMostRecentBufferCollection();
  ASSERT_TRUE(collection);
  EXPECT_FALSE(collection->HasConstraints());
}

}  // namespace

}  // namespace intel_display
