blob: ca61dab5b0250bf82f4e85a19381d3d0b3c9db35 [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/drivers/coordinator/added-display-info.h"
#include <fidl/fuchsia.hardware.display.engine/cpp/driver/wire.h>
#include <lib/driver/logging/cpp/logger.h>
#include <lib/zx/result.h>
#include <algorithm>
#include <cstdint>
#include <fbl/alloc_checker.h>
#include <fbl/vector.h>
#include "src/graphics/display/lib/api-types/cpp/display-id.h"
#include "src/graphics/display/lib/api-types/cpp/pixel-format.h"
namespace display_coordinator {
// static
zx::result<std::unique_ptr<AddedDisplayInfo>> AddedDisplayInfo::Create(
const fuchsia_hardware_display_engine::wire::RawDisplayInfo& fidl_display_info) {
const display::DisplayId display_id(fidl_display_info.display_id);
if (display_id == display::kInvalidDisplayId) {
fdf::error("AddedDisplayInfo creation failed: invalid display ID");
return zx::error(ZX_ERR_INVALID_ARGS);
}
if (fidl_display_info.pixel_formats.size() == 0) {
fdf::error("AddedDisplayInfo creation failed: empty pixel formats list");
return zx::error(ZX_ERR_INVALID_ARGS);
}
if (fidl_display_info.preferred_modes.empty()) {
fdf::error("AddedDisplayInfo creation failed: empty preferred modes list");
return zx::error(ZX_ERR_INVALID_ARGS);
}
fbl::Vector<display::PixelFormat> pixel_formats;
fbl::AllocChecker alloc_checker;
pixel_formats.reserve(fidl_display_info.pixel_formats.size(), &alloc_checker);
if (!alloc_checker.check()) {
fdf::error("AddedDisplayInfo creation failed: out of memory allocating pixel formats");
return zx::error(ZX_ERR_NO_MEMORY);
}
for (const fuchsia_images2::wire::PixelFormat& fidl_pixel_format :
fidl_display_info.pixel_formats) {
if (!display::PixelFormat::IsSupported(fidl_pixel_format)) {
fdf::error("AddedDisplayInfo creation failed: unsupported pixel format {}",
static_cast<uint32_t>(fidl_pixel_format));
return zx::error(ZX_ERR_INVALID_ARGS);
}
display::PixelFormat pixel_format(fidl_pixel_format);
ZX_DEBUG_ASSERT_MSG(pixel_formats.size() < fidl_display_info.pixel_formats.size(),
"The push_back() below was not supposed to allocate memory, but it might");
pixel_formats.push_back(pixel_format, &alloc_checker);
ZX_DEBUG_ASSERT_MSG(alloc_checker.check(),
"The push_back() above failed to allocate memory; "
"it was not supposed to allocate at all");
}
fbl::Vector<display::Mode> preferred_modes;
preferred_modes.reserve(fidl_display_info.preferred_modes.size(), &alloc_checker);
if (!alloc_checker.check()) {
fdf::error("AddedDisplayInfo creation failed: out of memory allocating display modes");
return zx::error(ZX_ERR_NO_MEMORY);
}
for (const fuchsia_hardware_display_types::wire::Mode& fidl_preferred_mode :
fidl_display_info.preferred_modes) {
ZX_DEBUG_ASSERT_MSG(preferred_modes.size() < fidl_display_info.preferred_modes.size(),
"The push_back() below was not supposed to allocate memory, but it might");
if (!display::Mode::IsValid(fidl_preferred_mode)) {
fdf::error("AddedDisplayInfo creation failed: invalid preferred mode for display ID {}",
display_id.value());
return zx::error(ZX_ERR_INVALID_ARGS);
}
preferred_modes.push_back(display::Mode::From(fidl_preferred_mode), &alloc_checker);
ZX_DEBUG_ASSERT_MSG(alloc_checker.check(),
"The push_back() above failed to allocate memory; "
"it was not supposed to allocate at all");
}
auto display_info = fbl::make_unique_checked<AddedDisplayInfo>(&alloc_checker);
if (!alloc_checker.check()) {
fdf::error("AddedDisplayInfo creation failed: out of memory allocating instance");
return zx::error(ZX_ERR_NO_MEMORY);
}
*display_info = {
.display_id = display_id,
.pixel_formats = std::move(pixel_formats),
.preferred_modes = std::move(preferred_modes),
};
return zx::ok(std::move(display_info));
}
} // namespace display_coordinator