blob: a78371c0288c7cbd37a20a67b6d4b9bab8ee99c1 [file] [log] [blame]
// 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 <fidl/fuchsia.ui.composition/cpp/fidl.h>
#include <fidl/fuchsia.ui.display.singleton/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/fit/function.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/ui/scenic/cpp/view_creation_tokens.h>
#include <lib/ui/scenic/cpp/view_identity.h>
#include <zxtest/zxtest.h>
#include "src/ui/scenic/tests/utils/blocking_present.h"
#include "src/ui/scenic/tests/utils/scenic_ctf_test_base.h"
namespace integration_tests {
namespace {
using fuds_VsyncSource = fuchsia_ui_display_singleton::VsyncSource;
class VsyncSourceIntegrationTest
: public ScenicCtfTest,
public fidl::AsyncEventHandler<fuchsia_ui_display_singleton::VsyncSource> {
public:
VsyncSourceIntegrationTest() = default;
void SetUp() override {
ScenicCtfTest::SetUp();
// Fake display only triggers vsyncs after a config is applied. Drawing a solid fill here to
// trigger vsyncs.
{
FlatlandClientWithEventHandler root_flatland(
ConnectIntoRealm<fuchsia_ui_composition::Flatland>(), dispatcher());
auto [child_token, parent_token] = scenic::cpp::ViewCreationTokenPair::New();
SetFlatlandDisplayContent(std::move(parent_token));
auto parent_viewport_watcher_endpoints =
fidl::CreateEndpoints<fuchsia_ui_composition::ParentViewportWatcher>();
fuchsia::ui::composition::FlatlandCreateView2Request request;
auto res = root_flatland->CreateView2(
{{.token = std::move(child_token),
.view_identity = scenic::cpp::NewViewIdentityOnCreation(),
.parent_viewport_watcher = std::move(parent_viewport_watcher_endpoints->server)}});
ASSERT_TRUE(res.is_ok());
const fuchsia_ui_composition::TransformId kRootTransform = {1};
res = root_flatland->CreateTransform(kRootTransform);
ASSERT_TRUE(res.is_ok());
res = root_flatland->SetRootTransform(kRootTransform);
ASSERT_TRUE(res.is_ok());
const fuchsia_ui_composition::ContentId kFilledRectContentId = {1};
res = root_flatland->CreateFilledRect(kFilledRectContentId);
ASSERT_TRUE(res.is_ok());
res = root_flatland->SetSolidFill(
{{.rect_id = kFilledRectContentId,
.color = {{.red = 1.f, .green = 0.f, .blue = 0.f, .alpha = 1.f}},
.size = {{.width = 100, .height = 100}}}});
ASSERT_TRUE(res.is_ok());
res = root_flatland->SetContent(
{{.transform_id = kRootTransform, .content_id = kFilledRectContentId}});
ASSERT_TRUE(res.is_ok());
BlockingPresent(this, root_flatland);
ASSERT_TRUE(res.is_ok());
}
vsync_source_.Bind(ConnectIntoRealm<fuds_VsyncSource>(), dispatcher(), this);
}
// fuchsia_ui_display_singleton::VsyncSource
void OnVsync(fidl::Event<fuds_VsyncSource::OnVsync>& event) override {
on_vsync_called_ = true;
on_vsync_timestamp_ = event.timestamp();
}
fidl::Client<fuds_VsyncSource> vsync_source_;
bool on_vsync_called_ = false;
bool on_vsync_timestamp_ = 0;
};
TEST_F(VsyncSourceIntegrationTest, OnVsyncAfterEnabled) {
auto res = vsync_source_->SetVsyncEnabled(true);
EXPECT_TRUE(res.is_ok());
RunLoopUntil([this] { return on_vsync_called_; });
EXPECT_GT(on_vsync_timestamp_, 0);
res = vsync_source_->SetVsyncEnabled(false);
EXPECT_TRUE(res.is_ok());
}
TEST_F(VsyncSourceIntegrationTest, NoOnVsyncWhenDisabled) {
// Run the loop for a few frames and check that we don't receive OnVsync.
// A bit racy, but there is no easy way to test for absence of events.
RunLoopWithTimeout(zx::msec(200));
EXPECT_FALSE(on_vsync_called_);
}
} // namespace
} // namespace integration_tests