blob: 3a5ac8a392109e6e637f254617b1e3ddf983b1fa [file] [log] [blame]
// Copyright 2020 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/ui/scenic/lib/utils/helpers.h"
#include <fidl/fuchsia.sysmem/cpp/fidl.h>
#include <fidl/fuchsia.sysmem/cpp/hlcpp_conversion.h>
#include <fidl/fuchsia.sysmem/cpp/wire.h>
#include <lib/fdio/directory.h>
#include <lib/image-format/image_format.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <fbl/algorithm.h>
#include "fuchsia/sysmem/cpp/fidl.h"
#include "src/lib/fsl/handles/object_info.h"
#include <glm/gtc/constants.hpp>
using fuchsia::ui::composition::Orientation;
namespace utils {
fuchsia::ui::scenic::Present2Args CreatePresent2Args(zx_time_t requested_presentation_time,
std::vector<zx::event> acquire_fences,
std::vector<zx::event> release_fences,
zx_duration_t requested_prediction_span) {
fuchsia::ui::scenic::Present2Args args;
args.set_requested_presentation_time(requested_presentation_time);
args.set_acquire_fences(std::move(acquire_fences));
args.set_release_fences(std::move(release_fences));
args.set_requested_prediction_span(requested_prediction_span);
return args;
}
zx_koid_t ExtractKoid(const fuchsia::ui::views::ViewRef& view_ref) {
return fsl::GetKoid(view_ref.reference.get());
}
template <typename ZX_T>
static auto CopyZxHandle(const ZX_T& handle) -> ZX_T {
ZX_T handle_copy;
if (handle.duplicate(ZX_RIGHT_SAME_RIGHTS, &handle_copy) != ZX_OK) {
FX_LOGS(ERROR) << "Copying zx object handle failed.";
FX_DCHECK(false);
}
return handle_copy;
}
zx::event CopyEvent(const zx::event& event) { return CopyZxHandle(event); }
zx::eventpair CopyEventpair(const zx::eventpair& eventpair) { return CopyZxHandle(eventpair); }
std::vector<zx::event> CopyEventArray(const std::vector<zx::event>& events) {
std::vector<zx::event> result;
const size_t count = events.size();
result.reserve(count);
for (size_t i = 0; i < count; i++) {
result.push_back(CopyEvent(events[i]));
}
return result;
}
bool IsEventSignalled(const zx::event& event, zx_signals_t signal) {
zx_signals_t pending = 0u;
event.wait_one(signal, zx::time(), &pending);
return (pending & signal) != 0u;
}
zx::event CreateEvent() {
TRACE_DURATION("gfx", "CreateEvent");
zx::event event;
FX_CHECK(zx::event::create(0, &event) == ZX_OK);
return event;
}
std::vector<zx::event> CreateEventArray(size_t n) {
std::vector<zx::event> events;
events.reserve(n);
for (size_t i = 0; i < n; i++) {
events.push_back(CreateEvent());
}
return events;
}
std::vector<zx_koid_t> ExtractKoids(const std::vector<zx::event>& events) {
std::vector<zx_koid_t> result;
result.reserve(events.size());
for (auto& evt : events) {
zx_info_handle_basic_t info;
zx_status_t status = evt.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
FX_DCHECK(status == ZX_OK);
result.push_back(info.koid);
}
return result;
}
fuchsia::sysmem::AllocatorSyncPtr CreateSysmemAllocatorSyncPtr(
const std::string& debug_name_suffix) {
FX_CHECK(!debug_name_suffix.empty());
fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator;
zx_status_t status = fdio_service_connect("/svc/fuchsia.sysmem.Allocator",
sysmem_allocator.NewRequest().TakeChannel().release());
FX_DCHECK(status == ZX_OK);
auto debug_name = fsl::GetCurrentProcessName() + " " + debug_name_suffix;
constexpr size_t kMaxNameLength = 64; // from fuchsia.sysmem/allocator.fidl
FX_DCHECK(debug_name.length() <= kMaxNameLength)
<< "Sysmem client debug name exceeded max length of " << kMaxNameLength << " (\""
<< debug_name << "\")";
sysmem_allocator->SetDebugClientInfo(std::move(debug_name), fsl::GetCurrentProcessKoid());
return sysmem_allocator;
}
SysmemTokens CreateSysmemTokens(fuchsia::sysmem::Allocator_Sync* sysmem_allocator) {
FX_DCHECK(sysmem_allocator);
fuchsia::sysmem::BufferCollectionTokenSyncPtr local_token;
zx_status_t status = sysmem_allocator->AllocateSharedCollection(local_token.NewRequest());
FX_DCHECK(status == ZX_OK);
fuchsia::sysmem::BufferCollectionTokenSyncPtr dup_token;
status = local_token->Duplicate(std::numeric_limits<uint32_t>::max(), dup_token.NewRequest());
FX_DCHECK(status == ZX_OK);
status = local_token->Sync();
FX_DCHECK(status == ZX_OK);
return {std::move(local_token), std::move(dup_token)};
}
fuchsia::sysmem::BufferCollectionConstraints CreateDefaultConstraints(uint32_t buffer_count,
uint32_t width,
uint32_t height) {
fuchsia::sysmem::BufferCollectionConstraints constraints;
constraints.has_buffer_memory_constraints = true;
constraints.buffer_memory_constraints.cpu_domain_supported = true;
constraints.buffer_memory_constraints.ram_domain_supported = true;
constraints.usage.cpu = fuchsia::sysmem::cpuUsageReadOften | fuchsia::sysmem::cpuUsageWriteOften;
constraints.min_buffer_count = buffer_count;
constraints.image_format_constraints_count = 1;
auto& image_constraints = constraints.image_format_constraints[0];
image_constraints.color_spaces_count = 1;
image_constraints.color_space[0] =
fuchsia::sysmem::ColorSpace{.type = fuchsia::sysmem::ColorSpaceType::SRGB};
image_constraints.pixel_format.type = fuchsia::sysmem::PixelFormatType::BGRA32;
image_constraints.pixel_format.has_format_modifier = true;
image_constraints.pixel_format.format_modifier.value = fuchsia::sysmem::FORMAT_MODIFIER_LINEAR;
image_constraints.required_min_coded_width = width;
image_constraints.required_min_coded_height = height;
image_constraints.required_max_coded_width = width;
image_constraints.required_max_coded_height = height;
image_constraints.bytes_per_row_divisor = 4;
return constraints;
}
bool RectFContainsPoint(const fuchsia::math::RectF& rect, float x, float y) {
constexpr float kEpsilon = 1e-3f;
return rect.x - kEpsilon <= x && x <= rect.x + rect.width + kEpsilon && rect.y - kEpsilon <= y &&
y <= rect.y + rect.height + kEpsilon;
}
fuchsia::math::RectF ConvertRectToRectF(const fuchsia::math::Rect& rect) {
return {.x = static_cast<float>(rect.x),
.y = static_cast<float>(rect.y),
.width = static_cast<float>(rect.width),
.height = static_cast<float>(rect.height)};
}
// Prints in row-major order.
void PrettyPrintMat3(std::string name, const std::array<float, 9>& mat3) {
FX_LOGS(INFO) << "\n"
<< name << ":\n"
<< mat3[0] << "," << mat3[3] << "," << mat3[6] << "\n"
<< mat3[1] << "," << mat3[4] << "," << mat3[7] << "\n"
<< mat3[2] << "," << mat3[5] << "," << mat3[8];
}
float GetOrientationAngle(fuchsia::ui::composition::Orientation orientation) {
switch (orientation) {
case Orientation::CCW_0_DEGREES:
return 0.f;
case Orientation::CCW_90_DEGREES:
return -glm::half_pi<float>();
case Orientation::CCW_180_DEGREES:
return -glm::pi<float>();
case Orientation::CCW_270_DEGREES:
return -glm::three_over_two_pi<float>();
}
}
namespace {
uint32_t GetBytesPerRow(const fuchsia::sysmem::ImageFormatConstraints& image_format_constraints,
uint32_t image_width, uint32_t bytes_per_pixel) {
uint32_t bytes_per_row_divisor = image_format_constraints.bytes_per_row_divisor;
uint32_t min_bytes_per_row = image_format_constraints.min_bytes_per_row;
uint32_t bytes_per_row = fbl::round_up(std::max(image_width * bytes_per_pixel, min_bytes_per_row),
bytes_per_row_divisor);
return bytes_per_row;
}
} // namespace
uint32_t GetBytesPerPixel(const fuchsia::sysmem::SingleBufferSettings& settings) {
return GetBytesPerPixel(settings.image_format_constraints);
}
uint32_t GetBytesPerPixel(const fuchsia::sysmem::ImageFormatConstraints& image_format_constraints) {
auto hlcpp_pixel_format = image_format_constraints.pixel_format;
fidl::Arena arena;
auto wire_pixel_format = fidl::ToWire(arena, fidl::HLCPPToNatural(hlcpp_pixel_format));
return ImageFormatStrideBytesPerWidthPixel(wire_pixel_format);
}
uint32_t GetBytesPerRow(const fuchsia::sysmem::SingleBufferSettings& settings,
uint32_t image_width) {
return GetBytesPerRow(settings.image_format_constraints, image_width);
}
uint32_t GetBytesPerRow(const fuchsia::sysmem::ImageFormatConstraints& image_format_constraints,
uint32_t image_width) {
uint32_t bytes_per_pixel = GetBytesPerPixel(image_format_constraints);
return GetBytesPerRow(image_format_constraints, image_width, bytes_per_pixel);
}
uint32_t GetPixelsPerRow(const fuchsia::sysmem::SingleBufferSettings& settings,
uint32_t image_width) {
return GetPixelsPerRow(settings.image_format_constraints, image_width);
}
uint32_t GetPixelsPerRow(const fuchsia::sysmem::ImageFormatConstraints& image_format_constraints,
uint32_t image_width) {
uint32_t bytes_per_pixel = GetBytesPerPixel(image_format_constraints);
return GetBytesPerRow(image_format_constraints, image_width, bytes_per_pixel) / bytes_per_pixel;
}
} // namespace utils