blob: ebe65942dd6cf9c28ab3fc231ab97413fd2c66ed [file] [log] [blame] [edit]
// Copyright 2025 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/lib/api-protocols/cpp/display-engine-fidl-adapter.h"
#include <fidl/fuchsia.hardware.display.engine/cpp/driver/wire.h>
#include <fidl/fuchsia.hardware.display.engine/cpp/wire.h>
#include <fidl/fuchsia.sysmem2/cpp/wire.h>
#include <lib/async/cpp/task.h>
#include <lib/driver/testing/cpp/driver_runtime.h>
#include <lib/driver/testing/cpp/scoped_global_logger.h>
#include <lib/fdf/dispatcher.h>
#include <lib/fit/result.h>
#include <lib/sync/completion.h>
#include <lib/zx/result.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/types.h>
#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <optional>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "src/graphics/display/lib/api-protocols/cpp/mock-display-engine.h"
#include "src/graphics/display/lib/api-types/cpp/color-conversion.h"
#include "src/graphics/display/lib/api-types/cpp/config-check-result.h"
#include "src/graphics/display/lib/api-types/cpp/coordinate-transformation.h"
#include "src/graphics/display/lib/api-types/cpp/display-id.h"
#include "src/graphics/display/lib/api-types/cpp/driver-buffer-collection-id.h"
#include "src/graphics/display/lib/api-types/cpp/driver-capture-image-id.h"
#include "src/graphics/display/lib/api-types/cpp/driver-config-stamp.h"
#include "src/graphics/display/lib/api-types/cpp/driver-image-id.h"
#include "src/graphics/display/lib/api-types/cpp/driver-layer.h"
#include "src/graphics/display/lib/api-types/cpp/engine-info.h"
#include "src/graphics/display/lib/api-types/cpp/image-buffer-usage.h"
#include "src/graphics/display/lib/api-types/cpp/image-metadata.h"
#include "src/graphics/display/lib/api-types/cpp/image-tiling-type.h"
#include "src/graphics/display/lib/api-types/cpp/mode-id.h"
#include "src/graphics/display/lib/api-types/cpp/rectangle.h"
#include "src/lib/testing/predicates/status.h"
namespace display {
namespace {
class DisplayEngineFidlAdapterTest : public ::testing::Test {
public:
void SetUp() override {
auto [fidl_client, fidl_server] =
fdf::Endpoints<fuchsia_hardware_display_engine::Engine>::Create();
fidl_client_ =
fdf::WireSyncClient<fuchsia_hardware_display_engine::Engine>(std::move(fidl_client));
ASSERT_OK(async::PostTask(
dispatcher_->async_dispatcher(), [this, fidl_server = std::move(fidl_server)]() mutable {
engine_events_fidl_.emplace();
fidl_adapter_.emplace(&mock_, &engine_events_fidl_.value());
fidl::ProtocolHandler<fuchsia_hardware_display_engine::Engine> fidl_handler =
fidl_adapter_->CreateHandler(*(dispatcher_->get()));
fidl_handler(std::move(fidl_server));
}));
}
void TearDown() override {
driver_runtime_.ShutdownBackgroundDispatcher(dispatcher_->get(), [this] {
fidl_adapter_.reset();
engine_events_fidl_.reset();
});
mock_.CheckAllCallsReplayed();
}
protected:
fdf_testing::ScopedGlobalLogger logger_;
fdf_testing::DriverRuntime driver_runtime_;
fdf::UnownedSynchronizedDispatcher dispatcher_{driver_runtime_.StartBackgroundDispatcher()};
display::testing::MockDisplayEngine mock_;
fdf::WireSyncClient<fuchsia_hardware_display_engine::Engine> fidl_client_;
// Must be created and destroyed on the FIDL loop.
std::optional<display::DisplayEngineEventsFidl> engine_events_fidl_;
std::optional<display::DisplayEngineFidlAdapter> fidl_adapter_;
};
TEST_F(DisplayEngineFidlAdapterTest, CompleteCoordinatorConnection) {
static constexpr display::EngineInfo kEngineInfo({
.max_layer_count = 4,
.max_connected_display_count = 1,
.is_capture_supported = false,
});
mock_.ExpectCompleteCoordinatorConnection([&] { return kEngineInfo; });
auto [listener_client, listener_server] =
fdf::Endpoints<fuchsia_hardware_display_engine::EngineListener>::Create();
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::CompleteCoordinatorConnection>
fidl_transport_result =
fidl_client_.buffer(arena)->CompleteCoordinatorConnection(std::move(listener_client));
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fuchsia_hardware_display_engine::wire::EngineCompleteCoordinatorConnectionResponse&
fidl_domain_result = fidl_transport_result.value();
EXPECT_EQ(kEngineInfo, display::EngineInfo::From(fidl_domain_result.engine_info));
}
TEST_F(DisplayEngineFidlAdapterTest, ImportBufferCollectionSuccess) {
auto [buffer_collection_token_client, buffer_collection_token_server] =
fidl::Endpoints<fuchsia_sysmem2::BufferCollectionToken>::Create();
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
const zx_handle_t buffer_collection_token_client_handle =
buffer_collection_token_client.handle()->get();
mock_.ExpectImportBufferCollection(
[&](display::DriverBufferCollectionId buffer_collection_id,
fidl::ClientEnd<fuchsia_sysmem2::BufferCollectionToken> buffer_collection_token) {
EXPECT_EQ(kBufferCollectionId, buffer_collection_id);
EXPECT_EQ(buffer_collection_token_client_handle, buffer_collection_token.handle()->get());
return zx::ok();
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ImportBufferCollection>
fidl_transport_result = fidl_client_.buffer(arena)->ImportBufferCollection(
kBufferCollectionId.ToFidl(), std::move(buffer_collection_token_client));
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_OK(fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, ImportBufferCollectionEngineError) {
auto [buffer_collection_token_client, buffer_collection_token_server] =
fidl::Endpoints<fuchsia_sysmem2::BufferCollectionToken>::Create();
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
mock_.ExpectImportBufferCollection(
[&](display::DriverBufferCollectionId buffer_collection_id,
fidl::ClientEnd<fuchsia_sysmem2::BufferCollectionToken> buffer_collection_token) {
return zx::error(ZX_ERR_INTERNAL);
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ImportBufferCollection>
fidl_transport_result = fidl_client_.buffer(arena)->ImportBufferCollection(
kBufferCollectionId.ToFidl(), std::move(buffer_collection_token_client));
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_STATUS(zx::error(ZX_ERR_INTERNAL), fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, ReleaseBufferCollectionSuccess) {
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
mock_.ExpectReleaseBufferCollection([&](display::DriverBufferCollectionId buffer_collection_id) {
EXPECT_EQ(kBufferCollectionId, buffer_collection_id);
return zx::ok();
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ReleaseBufferCollection>
fidl_transport_result =
fidl_client_.buffer(arena)->ReleaseBufferCollection(kBufferCollectionId.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_OK(fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, ReleaseBufferCollectionEngineError) {
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
mock_.ExpectReleaseBufferCollection([&](display::DriverBufferCollectionId buffer_collection_id) {
return zx::error(ZX_ERR_INTERNAL);
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ReleaseBufferCollection>
fidl_transport_result =
fidl_client_.buffer(arena)->ReleaseBufferCollection(kBufferCollectionId.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_STATUS(zx::error(ZX_ERR_INTERNAL), fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, ImportImageSuccess) {
static constexpr display::ImageMetadata kImageMetadata(
{.width = 640, .height = 480, .tiling_type = display::ImageTilingType::kLinear});
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
static constexpr uint32_t kBufferIndex = 4242;
static constexpr display::DriverImageId kImageId(84);
mock_.ExpectImportImage([&](const display::ImageMetadata& image_metadata,
display::DriverBufferCollectionId buffer_collection_id,
uint32_t buffer_index) {
EXPECT_EQ(kImageMetadata, image_metadata);
EXPECT_EQ(kBufferCollectionId, buffer_collection_id);
EXPECT_EQ(kBufferIndex, buffer_index);
return zx::ok(kImageId);
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ImportImage>
fidl_transport_result = fidl_client_.buffer(arena)->ImportImage(
kImageMetadata.ToFidl(), kBufferCollectionId.ToFidl(), kBufferIndex);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t, fuchsia_hardware_display_engine::wire::EngineImportImageResponse*>&
fidl_domain_result = fidl_transport_result.value();
ASSERT_TRUE(fidl_domain_result.is_ok()) << fidl_domain_result.error_value();
EXPECT_EQ(kImageId, display::DriverImageId(fidl_domain_result.value()->image_id));
}
TEST_F(DisplayEngineFidlAdapterTest, ImportImageEngineError) {
static constexpr display::ImageMetadata kImageMetadata(
{.width = 640, .height = 480, .tiling_type = display::ImageTilingType::kLinear});
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
static constexpr uint32_t kBufferIndex = 4242;
mock_.ExpectImportImage([&](const display::ImageMetadata& image_metadata,
display::DriverBufferCollectionId buffer_collection_id,
uint32_t buffer_index) { return zx::error(ZX_ERR_INTERNAL); });
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ImportImage>
fidl_transport_result = fidl_client_.buffer(arena)->ImportImage(
kImageMetadata.ToFidl(), kBufferCollectionId.ToFidl(), kBufferIndex);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t, fuchsia_hardware_display_engine::wire::EngineImportImageResponse*>&
fidl_domain_result = fidl_transport_result.value();
ASSERT_TRUE(fidl_domain_result.is_error());
EXPECT_EQ(fidl_domain_result.error_value(), ZX_ERR_INTERNAL);
}
TEST_F(DisplayEngineFidlAdapterTest, ImportImageForCaptureSuccess) {
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
static constexpr uint32_t kBufferIndex = 4242;
static constexpr display::DriverCaptureImageId kCaptureImageId(84);
mock_.ExpectImportImageForCapture(
[&](display::DriverBufferCollectionId buffer_collection_id, uint32_t buffer_index) {
EXPECT_EQ(kBufferCollectionId, buffer_collection_id);
EXPECT_EQ(kBufferIndex, buffer_index);
return zx::ok(kCaptureImageId);
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ImportImageForCapture>
fidl_transport_result = fidl_client_.buffer(arena)->ImportImageForCapture(
kBufferCollectionId.ToFidl(), kBufferIndex);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t,
fuchsia_hardware_display_engine::wire::EngineImportImageForCaptureResponse*>&
fidl_domain_result = fidl_transport_result.value();
ASSERT_TRUE(fidl_domain_result.is_ok()) << fidl_domain_result.error_value();
EXPECT_EQ(kCaptureImageId,
display::DriverCaptureImageId(fidl_domain_result.value()->capture_image_id));
}
TEST_F(DisplayEngineFidlAdapterTest, ImportImageForCaptureEngineError) {
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
static constexpr uint32_t kBufferIndex = 4242;
mock_.ExpectImportImageForCapture(
[&](display::DriverBufferCollectionId buffer_collection_id, uint32_t buffer_index) {
return zx::error(ZX_ERR_INTERNAL);
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ImportImageForCapture>
fidl_transport_result = fidl_client_.buffer(arena)->ImportImageForCapture(
kBufferCollectionId.ToFidl(), kBufferIndex);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t,
fuchsia_hardware_display_engine::wire::EngineImportImageForCaptureResponse*>&
fidl_domain_result = fidl_transport_result.value();
ASSERT_TRUE(fidl_domain_result.is_error());
EXPECT_EQ(fidl_domain_result.error_value(), ZX_ERR_INTERNAL);
}
TEST_F(DisplayEngineFidlAdapterTest, ReleaseImageSuccess) {
static constexpr display::DriverImageId kImageId(42);
libsync::Completion release_image_called;
mock_.ExpectReleaseImage([&](display::DriverImageId image_id) {
EXPECT_EQ(kImageId, image_id);
release_image_called.Signal();
});
fdf::Arena arena('TEST');
fidl::OneWayStatus fidl_transport_status =
fidl_client_.buffer(arena)->ReleaseImage(kImageId.ToFidl());
ASSERT_TRUE(fidl_transport_status.ok()) << fidl_transport_status.FormatDescription();
// One-way calls complete before the FIDL call is processed on the other end.
release_image_called.Wait();
}
// Valid layer with properties aimed at testing API translation layers.
//
// The returned layer's properties are all different numbers. This is intended to
// help catch logic errors in API translation layers, such as swapping dimensions
// (width vs height) or size and position.
//
// `seed` is a small integer that results in small variations in the layer
// properties. This is intended to help catch logic errors in accessing and
// converting layers stored in arrays.
constexpr display::DriverLayer CreateValidLayerWithSeed(int seed) {
const uint8_t color_blue = 0x40 + static_cast<uint8_t>(seed % 16);
const uint8_t color_green = 0x50 + static_cast<uint8_t>((seed / 16) % 16);
const uint8_t color_red = 0x60 + static_cast<uint8_t>(seed % 16);
const uint8_t color_alpha = 0x70 + static_cast<uint8_t>((seed / 16) % 16);
return display::DriverLayer({
.display_destination = display::Rectangle(
{.x = 100 + seed, .y = 200 + seed, .width = 300 + seed, .height = 400 + seed}),
.image_source = display::Rectangle(
{.x = 500 + seed, .y = 600 + seed, .width = 700 + seed, .height = 800 + seed}),
.image_id = display::DriverImageId(8000 + seed),
.image_metadata = display::ImageMetadata({.width = 2000 + seed,
.height = 1000 + seed,
.tiling_type = display::ImageTilingType::kLinear}),
.fallback_color = display::Color(
{.format = display::PixelFormat::kB8G8R8A8,
.bytes = std::initializer_list<uint8_t>{color_blue, color_green, color_red, color_alpha,
0, 0, 0, 0}}),
.image_source_transformation = display::CoordinateTransformation::kIdentity,
});
}
TEST_F(DisplayEngineFidlAdapterTest, CheckConfigurationSingleLayerSuccess) {
static constexpr display::DisplayId kDisplayId(42);
static constexpr display::ModeId kModeId(24);
const display::ColorConversion kColorConversion = {
{
.preoffsets = {1.0f, 2.0f, 3.0f},
.coefficients =
{
std::array<float, 3>{4.0f, 5.0f, 6.0f},
std::array<float, 3>{7.0f, 8.0f, 9.0f},
std::array<float, 3>{10.0f, 11.0f, 12.0f},
},
.postoffsets = {13.0f, 14.0f, 15.0f},
},
};
static constexpr std::array<display::DriverLayer, 1> kLayers = {CreateValidLayerWithSeed(0)};
std::array<fuchsia_hardware_display_engine::wire::Layer, 1> fidl_layers = {kLayers[0].ToFidl()};
const fuchsia_hardware_display_engine::wire::DisplayConfig fidl_display_config = {
.display_id = kDisplayId.ToFidl(),
.mode_id = kModeId.ToFidl(),
.color_conversion = kColorConversion.ToFidl(),
.layers =
fidl::VectorView<fuchsia_hardware_display_engine::wire::Layer>::FromExternal(fidl_layers),
};
mock_.ExpectCheckConfiguration([&](display::DisplayId display_id, display::ModeId display_mode_id,
display::ColorConversion color_conversion,
cpp20::span<const display::DriverLayer> layers) {
EXPECT_EQ(kDisplayId, display_id);
EXPECT_EQ(kModeId, display_mode_id);
EXPECT_EQ(kColorConversion, color_conversion);
EXPECT_THAT(layers, ::testing::ElementsAreArray(kLayers));
return display::ConfigCheckResult::kOk;
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::CheckConfiguration>
fidl_transport_result = fidl_client_.buffer(arena)->CheckConfiguration(fidl_display_config);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<fuchsia_hardware_display_types::wire::ConfigResult>& fidl_domain_result =
fidl_transport_result.value();
EXPECT_TRUE(fidl_domain_result.is_ok());
}
TEST_F(DisplayEngineFidlAdapterTest, CheckConfigurationMultiLayerSuccess) {
static constexpr display::DisplayId kDisplayId(42);
static constexpr display::ModeId kModeId(24);
static constexpr std::array<display::DriverLayer, 4> kLayers = {
CreateValidLayerWithSeed(0), CreateValidLayerWithSeed(1), CreateValidLayerWithSeed(2),
CreateValidLayerWithSeed(3)};
std::array<fuchsia_hardware_display_engine::wire::Layer, 4> fidl_layers = {
kLayers[0].ToFidl(), kLayers[1].ToFidl(), kLayers[2].ToFidl(), kLayers[3].ToFidl()};
const fuchsia_hardware_display_engine::wire::DisplayConfig fidl_display_config = {
.display_id = kDisplayId.ToFidl(),
.mode_id = kModeId.ToFidl(),
.color_conversion = display::ColorConversion::kIdentity.ToFidl(),
.layers =
fidl::VectorView<fuchsia_hardware_display_engine::wire::Layer>::FromExternal(fidl_layers),
};
mock_.ExpectCheckConfiguration([&](display::DisplayId display_id, display::ModeId display_mode_id,
display::ColorConversion color_conversion,
cpp20::span<const display::DriverLayer> layers) {
EXPECT_EQ(kDisplayId, display_id);
EXPECT_EQ(kModeId, display_mode_id);
EXPECT_EQ(display::ColorConversion::kIdentity, color_conversion);
EXPECT_THAT(layers, ::testing::ElementsAreArray(kLayers));
return display::ConfigCheckResult::kOk;
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::CheckConfiguration>
fidl_transport_result = fidl_client_.buffer(arena)->CheckConfiguration(fidl_display_config);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<fuchsia_hardware_display_types::wire::ConfigResult>& fidl_domain_result =
fidl_transport_result.value();
EXPECT_TRUE(fidl_domain_result.is_ok());
}
TEST_F(DisplayEngineFidlAdapterTest, CheckConfigurationAdapterErrorLayerCountPastLimit) {
static constexpr display::DisplayId kDisplayId(42);
static constexpr display::ModeId kModeId(24);
static constexpr int kLayerCount = display::EngineInfo::kMaxAllowedMaxLayerCount + 1;
std::vector<fuchsia_hardware_display_engine::wire::Layer> fidl_layers;
fidl_layers.reserve(kLayerCount);
for (int i = 0; i < kLayerCount; ++i) {
fidl_layers.emplace_back(CreateValidLayerWithSeed(i).ToFidl());
}
const fuchsia_hardware_display_engine::wire::DisplayConfig fidl_display_config = {
.display_id = kDisplayId.ToFidl(),
.mode_id = kModeId.ToFidl(),
.color_conversion = display::ColorConversion::kIdentity.ToFidl(),
.layers =
fidl::VectorView<fuchsia_hardware_display_engine::wire::Layer>::FromExternal(fidl_layers),
};
// The adapter is expected to reject the CheckConfiguration() call without
// invoking the engine driver. So, the mock driver should not receive any
// calls.
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::CheckConfiguration>
fidl_transport_result = fidl_client_.buffer(arena)->CheckConfiguration(fidl_display_config);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<fuchsia_hardware_display_types::wire::ConfigResult>& fidl_domain_result =
fidl_transport_result.value();
EXPECT_EQ(display::ConfigCheckResult::kUnsupportedConfig,
display::ConfigCheckResult(fidl_domain_result.error_value()));
}
TEST_F(DisplayEngineFidlAdapterTest, CheckConfigurationEngineError) {
static constexpr display::DisplayId kDisplayId(42);
static constexpr display::ModeId kModeId(24);
const display::ColorConversion kColorConversion = {
{
.preoffsets = {1.0f, 2.0f, 3.0f},
.coefficients =
{
std::array<float, 3>{4.0f, 5.0f, 6.0f},
std::array<float, 3>{7.0f, 8.0f, 9.0f},
std::array<float, 3>{10.0f, 11.0f, 12.0f},
},
.postoffsets = {13.0f, 14.0f, 15.0f},
},
};
static constexpr std::array<display::DriverLayer, 1> kLayers = {CreateValidLayerWithSeed(0)};
std::array<fuchsia_hardware_display_engine::wire::Layer, 1> fidl_layers = {kLayers[0].ToFidl()};
const fuchsia_hardware_display_engine::wire::DisplayConfig fidl_display_config = {
.display_id = kDisplayId.ToFidl(),
.mode_id = kModeId.ToFidl(),
.color_conversion = kColorConversion.ToFidl(),
.layers =
fidl::VectorView<fuchsia_hardware_display_engine::wire::Layer>::FromExternal(fidl_layers),
};
mock_.ExpectCheckConfiguration([&](display::DisplayId display_id, display::ModeId display_mode_id,
display::ColorConversion color_conversion,
cpp20::span<const display::DriverLayer> layers) {
return display::ConfigCheckResult::kUnsupportedDisplayModes;
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::CheckConfiguration>
fidl_transport_result = fidl_client_.buffer(arena)->CheckConfiguration(fidl_display_config);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<fuchsia_hardware_display_types::wire::ConfigResult>& fidl_domain_result =
fidl_transport_result.value();
EXPECT_EQ(display::ConfigCheckResult::kUnsupportedDisplayModes,
display::ConfigCheckResult(fidl_domain_result.error_value()));
}
TEST_F(DisplayEngineFidlAdapterTest, CheckConfigurationAdapterErrorModeIdInvalid) {
static constexpr display::DisplayId kDisplayId(42);
static constexpr std::array<display::DriverLayer, 1> kLayers = {CreateValidLayerWithSeed(0)};
std::array<fuchsia_hardware_display_engine::wire::Layer, 1> fidl_layers = {kLayers[0].ToFidl()};
const fuchsia_hardware_display_engine::wire::DisplayConfig fidl_display_config = {
.display_id = kDisplayId.ToFidl(),
.mode_id = kInvalidModeId.ToFidl(),
.color_conversion = display::ColorConversion::kIdentity.ToFidl(),
.layers =
fidl::VectorView<fuchsia_hardware_display_engine::wire::Layer>::FromExternal(fidl_layers),
};
// The adapter is expected to reject the CheckConfiguration() call without
// invoking the engine driver. So, the mock driver should not receive any
// calls.
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::CheckConfiguration>
fidl_transport_result = fidl_client_.buffer(arena)->CheckConfiguration(fidl_display_config);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<fuchsia_hardware_display_types::wire::ConfigResult>& fidl_domain_result =
fidl_transport_result.value();
EXPECT_EQ(display::ConfigCheckResult::kInvalidConfig,
display::ConfigCheckResult(fidl_domain_result.error_value()));
}
TEST_F(DisplayEngineFidlAdapterTest, CheckConfigurationAdapterErrorInvalidColorConversion) {
static constexpr display::DisplayId kDisplayId(42);
static constexpr display::ModeId kModeId(24);
static constexpr std::array<display::DriverLayer, 1> kLayers = {CreateValidLayerWithSeed(0)};
std::array<fuchsia_hardware_display_engine::wire::Layer, 1> fidl_layers = {kLayers[0].ToFidl()};
const fuchsia_hardware_display_engine::wire::DisplayConfig fidl_display_config = {
.display_id = kDisplayId.ToFidl(),
.mode_id = kModeId.ToFidl(),
.color_conversion =
{
.preoffsets = {std::nanf("1"), 2.0f, 3.0f},
.coefficients =
{
fidl::Array<float, 3>{1.0f, 2.0f, 3.0f},
fidl::Array<float, 3>{4.0f, 5.0f, 6.0f},
fidl::Array<float, 3>{7.0f, 8.0f, 9.0f},
},
.postoffsets = {1.0f, 2.0f, 3.0f},
},
.layers =
fidl::VectorView<fuchsia_hardware_display_engine::wire::Layer>::FromExternal(fidl_layers),
};
// CheckConfiguration() is never called on the MockDisplayEngine, because the
// color conversion check in `DisplayEngineFidlAdapter` has failed.
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::CheckConfiguration>
fidl_transport_result = fidl_client_.buffer(arena)->CheckConfiguration(fidl_display_config);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<fuchsia_hardware_display_types::wire::ConfigResult>& fidl_domain_result =
fidl_transport_result.value();
ASSERT_TRUE(fidl_domain_result.is_error());
EXPECT_EQ(fidl_domain_result.error_value(),
fuchsia_hardware_display_types::wire::ConfigResult::kInvalidConfig);
}
TEST_F(DisplayEngineFidlAdapterTest, ApplyConfigurationSingleLayer) {
static constexpr display::DisplayId kDisplayId(42);
static constexpr display::ModeId kModeId(24);
const display::ColorConversion kColorConversion = {
{
.preoffsets = {1.0f, 2.0f, 3.0f},
.coefficients =
{
std::array<float, 3>{4.0f, 5.0f, 6.0f},
std::array<float, 3>{7.0f, 8.0f, 9.0f},
std::array<float, 3>{10.0f, 11.0f, 12.0f},
},
.postoffsets = {13.0f, 14.0f, 15.0f},
},
};
static constexpr std::array<display::DriverLayer, 1> kLayers = {CreateValidLayerWithSeed(0)};
static constexpr display::DriverConfigStamp kConfigStamp(4242);
std::array<fuchsia_hardware_display_engine::wire::Layer, 1> fidl_layers = {kLayers[0].ToFidl()};
const fuchsia_hardware_display_engine::wire::DisplayConfig fidl_display_config = {
.display_id = kDisplayId.ToFidl(),
.mode_id = kModeId.ToFidl(),
.color_conversion = kColorConversion.ToFidl(),
.layers =
fidl::VectorView<fuchsia_hardware_display_engine::wire::Layer>::FromExternal(fidl_layers),
};
mock_.ExpectApplyConfiguration([&](display::DisplayId display_id, display::ModeId display_mode_id,
display::ColorConversion color_conversion,
cpp20::span<const display::DriverLayer> layers,
display::DriverConfigStamp config_stamp) {
EXPECT_EQ(kDisplayId, display_id);
EXPECT_EQ(kModeId, display_mode_id);
EXPECT_EQ(kColorConversion, color_conversion);
EXPECT_THAT(layers, ::testing::ElementsAreArray(kLayers));
EXPECT_EQ(kConfigStamp, config_stamp);
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ApplyConfiguration>
fidl_transport_result = fidl_client_.buffer(arena)->ApplyConfiguration(fidl_display_config,
kConfigStamp.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
}
TEST_F(DisplayEngineFidlAdapterTest, ApplyConfigurationMultiLayer) {
static constexpr display::DisplayId kDisplayId(42);
static constexpr display::ModeId kModeId(24);
static constexpr std::array<display::DriverLayer, 4> kLayers = {
CreateValidLayerWithSeed(0), CreateValidLayerWithSeed(1), CreateValidLayerWithSeed(2),
CreateValidLayerWithSeed(3)};
static constexpr display::DriverConfigStamp kConfigStamp(4242);
std::array<fuchsia_hardware_display_engine::wire::Layer, 4> fidl_layers = {
kLayers[0].ToFidl(), kLayers[1].ToFidl(), kLayers[2].ToFidl(), kLayers[3].ToFidl()};
const fuchsia_hardware_display_engine::wire::DisplayConfig fidl_display_config = {
.display_id = kDisplayId.ToFidl(),
.mode_id = kModeId.ToFidl(),
.color_conversion = display::ColorConversion::kIdentity.ToFidl(),
.layers =
fidl::VectorView<fuchsia_hardware_display_engine::wire::Layer>::FromExternal(fidl_layers),
};
mock_.ExpectApplyConfiguration([&](display::DisplayId display_id, display::ModeId display_mode_id,
display::ColorConversion color_conversion,
cpp20::span<const display::DriverLayer> layers,
display::DriverConfigStamp config_stamp) {
EXPECT_EQ(kDisplayId, display_id);
EXPECT_EQ(kModeId, display_mode_id);
EXPECT_EQ(display::ColorConversion::kIdentity, color_conversion);
EXPECT_THAT(layers, ::testing::ElementsAreArray(kLayers));
EXPECT_EQ(kConfigStamp, config_stamp);
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ApplyConfiguration>
fidl_transport_result = fidl_client_.buffer(arena)->ApplyConfiguration(fidl_display_config,
kConfigStamp.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
}
TEST_F(DisplayEngineFidlAdapterTest, SetBufferCollectionConstraintsSuccess) {
static constexpr display::ImageBufferUsage kImageBufferUsage(
{.tiling_type = display::ImageTilingType::kLinear});
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
mock_.ExpectSetBufferCollectionConstraints(
[&](const display::ImageBufferUsage& image_buffer_usage,
display::DriverBufferCollectionId buffer_collection_id) {
EXPECT_EQ(kImageBufferUsage, image_buffer_usage);
EXPECT_EQ(kBufferCollectionId, buffer_collection_id);
return zx::ok();
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::SetBufferCollectionConstraints>
fidl_transport_result = fidl_client_.buffer(arena)->SetBufferCollectionConstraints(
kImageBufferUsage.ToFidl(), kBufferCollectionId.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_OK(fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, SetBufferCollectionConstraintsEngineError) {
static constexpr display::ImageBufferUsage kImageBufferUsage(
{.tiling_type = display::ImageTilingType::kLinear});
static constexpr display::DriverBufferCollectionId kBufferCollectionId(42);
mock_.ExpectSetBufferCollectionConstraints(
[&](const display::ImageBufferUsage& image_buffer_usage,
display::DriverBufferCollectionId buffer_collection_id) {
return zx::error(ZX_ERR_INTERNAL);
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::SetBufferCollectionConstraints>
fidl_transport_result = fidl_client_.buffer(arena)->SetBufferCollectionConstraints(
kImageBufferUsage.ToFidl(), kBufferCollectionId.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_STATUS(zx::error(ZX_ERR_INTERNAL), fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, SetDisplayPowerSuccess) {
static constexpr display::DisplayId kDisplayId(42);
mock_.ExpectSetDisplayPower([&](display::DisplayId display_id, bool power_on) {
EXPECT_EQ(kDisplayId, display_id);
EXPECT_EQ(true, power_on);
return zx::ok();
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::SetDisplayPower>
fidl_transport_result =
fidl_client_.buffer(arena)->SetDisplayPower(kDisplayId.ToFidl(), true);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_OK(fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, SetDisplayPowerEngineError) {
static constexpr display::DisplayId kDisplayId(42);
mock_.ExpectSetDisplayPower(
[&](display::DisplayId display_id, bool power_on) { return zx::error(ZX_ERR_INTERNAL); });
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::SetDisplayPower>
fidl_transport_result =
fidl_client_.buffer(arena)->SetDisplayPower(kDisplayId.ToFidl(), true);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_STATUS(zx::error(ZX_ERR_INTERNAL), fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, StartCaptureSuccess) {
static constexpr display::DriverCaptureImageId kCaptureImageId(42);
mock_.ExpectStartCapture([&](display::DriverCaptureImageId capture_image_id) {
EXPECT_EQ(kCaptureImageId, capture_image_id);
return zx::ok();
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::StartCapture>
fidl_transport_result = fidl_client_.buffer(arena)->StartCapture(kCaptureImageId.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_OK(fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, StartCaptureEngineError) {
static constexpr display::DriverCaptureImageId kCaptureImageId(42);
mock_.ExpectStartCapture(
[&](display::DriverCaptureImageId capture_image_id) { return zx::error(ZX_ERR_INTERNAL); });
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::StartCapture>
fidl_transport_result = fidl_client_.buffer(arena)->StartCapture(kCaptureImageId.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_STATUS(zx::error(ZX_ERR_INTERNAL), fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, ReleaseCaptureSuccess) {
static constexpr display::DriverCaptureImageId kCaptureImageId(42);
mock_.ExpectReleaseCapture([&](display::DriverCaptureImageId capture_image_id) {
EXPECT_EQ(kCaptureImageId, capture_image_id);
return zx::ok();
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ReleaseCapture>
fidl_transport_result = fidl_client_.buffer(arena)->ReleaseCapture(kCaptureImageId.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_OK(fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, ReleaseCaptureEngineError) {
static constexpr display::DriverCaptureImageId kCaptureImageId(42);
mock_.ExpectReleaseCapture(
[&](display::DriverCaptureImageId capture_image_id) { return zx::error(ZX_ERR_INTERNAL); });
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::ReleaseCapture>
fidl_transport_result = fidl_client_.buffer(arena)->ReleaseCapture(kCaptureImageId.ToFidl());
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_STATUS(zx::error(ZX_ERR_INTERNAL), fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, SetMinimumRgbSuccess) {
static constexpr uint8_t kMinimumRgb = 42;
mock_.ExpectSetMinimumRgb([&](uint8_t minimum_rgb) {
EXPECT_EQ(kMinimumRgb, minimum_rgb);
return zx::ok();
});
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::SetMinimumRgb>
fidl_transport_result = fidl_client_.buffer(arena)->SetMinimumRgb(kMinimumRgb);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_OK(fidl_domain_result);
}
TEST_F(DisplayEngineFidlAdapterTest, SetMinimumRgbEngineError) {
static constexpr uint8_t kMinimumRgb = 42;
mock_.ExpectSetMinimumRgb([&](uint8_t minimum_rgb) { return zx::error(ZX_ERR_IO_REFUSED); });
fdf::Arena arena('TEST');
fdf::WireUnownedResult<fuchsia_hardware_display_engine::Engine::SetMinimumRgb>
fidl_transport_result = fidl_client_.buffer(arena)->SetMinimumRgb(kMinimumRgb);
ASSERT_TRUE(fidl_transport_result.ok()) << fidl_transport_result.FormatDescription();
fit::result<zx_status_t>& fidl_domain_result = fidl_transport_result.value();
EXPECT_STATUS(zx::error(ZX_ERR_IO_REFUSED), fidl_domain_result);
}
} // namespace
} // namespace display