blob: 38b065290d99533bd81bab5dc6368f5e3c5948f9 [file] [log] [blame]
// 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/embedder/flatland_connection.h"
#include <lib/fit/function.h>
#include <lib/syslog/global.h>
#include <zircon/status.h>
#include "src/embedder/logging.h"
namespace embedder {
FlatlandConnection::FlatlandConnection(std::string debug_name,
fuchsia::ui::composition::FlatlandHandle flatland,
std::function<void()> on_error_callback,
OnFramePresentedCallback on_frame_presented_callback)
: flatland_(flatland.Bind()),
on_error_callback_(on_error_callback),
on_frame_presented_callback_(std::move(on_frame_presented_callback)) {
flatland_.set_error_handler([callback = on_error_callback_](zx_status_t status) {
FX_LOGF(ERROR, kLogTag, "Flatland disconnected: %s", zx_status_get_string(status));
callback();
});
flatland_->SetDebugName(debug_name);
flatland_.events().OnError = fit::bind_member(this, &FlatlandConnection::OnError);
flatland_.events().OnFramePresented =
fit::bind_member(this, &FlatlandConnection::OnFramePresented);
flatland_.events().OnNextFrameBegin =
fit::bind_member(this, &FlatlandConnection::OnNextFrameBegin);
}
FlatlandConnection::~FlatlandConnection() = default;
// This method is called from the raster thread.
void FlatlandConnection::Present() {
if (present_credits_ > 0) {
DoPresent();
} else {
present_pending_ = true;
}
}
// This method is called from the raster thread.
void FlatlandConnection::DoPresent() {
if (present_credits_ == 0) {
FX_LOG(FATAL, kLogTag, "Tried to DoPresent() with 0 present credits.");
return;
}
--present_credits_;
fuchsia::ui::composition::PresentArgs present_args;
// TODO(http://fxbug.dev/94000): Compute a better presentation time.
present_args.set_requested_presentation_time(0);
present_args.set_acquire_fences(std::move(acquire_fences_));
present_args.set_release_fences(std::move(previous_present_release_fences_));
present_args.set_unsquashable(false);
flatland_->Present(std::move(present_args));
// In Flatland, release fences apply to the content of the previous present.
// Keeping track of the old frame's release fences and swapping ensure we set
// the correct ones for VulkanSurface's interpretation.
previous_present_release_fences_.clear();
previous_present_release_fences_.swap(current_present_release_fences_);
acquire_fences_.clear();
}
void FlatlandConnection::OnError(fuchsia::ui::composition::FlatlandError error) {
FX_LOGF(ERROR, kLogTag, "Flatland error: %d", static_cast<int>(error));
on_error_callback_();
}
// This method is called from the raster thread.
void FlatlandConnection::OnNextFrameBegin(fuchsia::ui::composition::OnNextFrameBeginValues values) {
present_credits_ += values.additional_present_credits();
if (present_pending_ && present_credits_ > 0) {
DoPresent();
present_pending_ = false;
}
// TODO(akbiggs): Implement vsyncing logic from
// https://github.com/flutter/engine/blob/83db012e3ff4e51588772067b59d499bfd44ad2e/shell/platform/fuchsia/flutter/flatland_connection.cc#L120.
}
// This method is called from the raster thread.
void FlatlandConnection::OnFramePresented(fuchsia::scenic::scheduling::FramePresentedInfo info) {
on_frame_presented_callback_(std::move(info));
}
// This method is called from the raster thread.
void FlatlandConnection::EnqueueAcquireFence(zx::event fence) {
acquire_fences_.push_back(std::move(fence));
}
// This method is called from the raster thread.
void FlatlandConnection::EnqueueReleaseFence(zx::event fence) {
current_present_release_fences_.push_back(std::move(fence));
}
} // namespace embedder