blob: 7ac6857c37b60098fae3c51ec4578b002df4372b [file] [log] [blame]
// Copyright 2017 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 "garnet/lib/ui/gfx/tests/gfx_test.h"
#include "garnet/lib/ui/gfx/gfx_system.h"
#include "garnet/lib/ui/gfx/tests/util.h"
#include "gtest/gtest.h"
#include "src/ui/lib/escher/flib/release_fence_signaller.h"
#include "lib/ui/scenic/cpp/commands.h"
namespace scenic_impl {
namespace gfx {
namespace test {
TEST_F(GfxSystemTest, CreateAndDestroySession) {
EXPECT_EQ(0U, scenic()->num_sessions());
fuchsia::ui::scenic::SessionPtr session;
EXPECT_EQ(0U, scenic()->num_sessions());
scenic()->CreateSession(session.NewRequest(), nullptr);
RunLoopUntilIdle();
EXPECT_EQ(1U, scenic()->num_sessions());
session = nullptr;
RunLoopUntilIdle();
EXPECT_EQ(0U, scenic()->num_sessions());
}
TEST_F(GfxSystemTest, ScheduleUpdateInOrder) {
// Create a session.
fuchsia::ui::scenic::SessionPtr session;
EXPECT_EQ(0U, scenic()->num_sessions());
scenic()->CreateSession(session.NewRequest(), nullptr);
RunLoopUntilIdle();
EXPECT_EQ(1U, scenic()->num_sessions());
// Present on the session with presentation_time = 1.
session->Present(1, CreateEventArray(1), CreateEventArray(1), [](auto) {});
// Briefly pump the message loop. Expect that the session is not destroyed.
RunLoopUntilIdle();
EXPECT_EQ(1U, scenic()->num_sessions());
// Present with the same presentation time.
session->Present(1, CreateEventArray(1), CreateEventArray(1), [](auto) {});
// Briefly pump the message loop. Expect that the session is not destroyed.
RunLoopUntilIdle();
EXPECT_EQ(1U, scenic()->num_sessions());
}
bool IsFenceSignalled(const zx::event& fence) {
zx_signals_t signals = 0u;
zx_status_t status =
fence.wait_one(escher::kFenceSignalled, zx::time(), &signals);
FXL_DCHECK(status == ZX_OK || status == ZX_ERR_TIMED_OUT);
return signals & escher::kFenceSignalled;
}
TEST_F(GfxSystemTest, ReleaseFences) {
// Tests creating a session, and calling Present with two release fences.
// The release fences should be signalled after a subsequent Present.
fuchsia::ui::scenic::SessionPtr session;
EXPECT_EQ(0U, scenic()->num_sessions());
scenic()->CreateSession(session.NewRequest(), nullptr);
RunLoopUntilIdle();
EXPECT_EQ(1U, scenic()->num_sessions());
auto handler = static_cast<SessionHandlerForTest*>(
gfx_system()->engine()->session_manager()->FindSessionHandler(1));
{
std::vector<fuchsia::ui::scenic::Command> commands;
commands.push_back(scenic::NewCommand(scenic::NewCreateCircleCmd(1, 50.f)));
commands.push_back(scenic::NewCommand(scenic::NewCreateCircleCmd(2, 25.f)));
session->Enqueue(std::move(commands));
}
RunLoopUntilIdle();
EXPECT_EQ(2u, handler->command_count());
// Create release fences
std::vector<zx::event> release_fences = CreateEventArray(2);
zx::event release_fence1 = CopyEvent(release_fences.at(0));
zx::event release_fence2 = CopyEvent(release_fences.at(1));
EXPECT_FALSE(IsFenceSignalled(release_fence1));
EXPECT_FALSE(IsFenceSignalled(release_fence2));
// Call Present with release fences.
session->Present(0u, std::vector<zx::event>(), std::move(release_fences),
[](fuchsia::images::PresentationInfo info) {});
RunLoopFor(zx::sec(1));
EXPECT_EQ(1u, handler->present_count());
EXPECT_FALSE(IsFenceSignalled(release_fence1));
EXPECT_FALSE(IsFenceSignalled(release_fence2));
// Call Present again with no release fences.
session->Present(0u, std::vector<zx::event>(), std::vector<zx::event>(),
[](fuchsia::images::PresentationInfo info) {});
RunLoopFor(zx::sec(1));
EXPECT_EQ(2u, handler->present_count());
EXPECT_TRUE(IsFenceSignalled(release_fence2));
}
TEST_F(GfxSystemTest, AcquireAndReleaseFences) {
// Tests creating a session, and calling Present with an acquire and a release
// fence. The release fences should be signalled only after a subsequent
// Present, and not until the acquire fence has been signalled.
fuchsia::ui::scenic::SessionPtr session;
EXPECT_EQ(0U, scenic()->num_sessions());
scenic()->CreateSession(session.NewRequest(), nullptr);
RunLoopUntilIdle();
EXPECT_EQ(1U, scenic()->num_sessions());
auto handler = static_cast<SessionHandlerForTest*>(
gfx_system()->engine()->session_manager()->FindSessionHandler(1));
{
std::vector<fuchsia::ui::scenic::Command> commands;
commands.push_back(scenic::NewCommand(scenic::NewCreateCircleCmd(1, 50.f)));
commands.push_back(scenic::NewCommand(scenic::NewCreateCircleCmd(2, 25.f)));
session->Enqueue(std::move(commands));
}
RunLoopUntilIdle();
EXPECT_EQ(2u, handler->command_count());
// Create acquire and release fences
zx::event acquire_fence;
ASSERT_EQ(ZX_OK, zx::event::create(0, &acquire_fence));
zx::event release_fence;
ASSERT_EQ(ZX_OK, zx::event::create(0, &release_fence));
std::vector<zx::event> acquire_fences;
acquire_fences.push_back(CopyEvent(acquire_fence));
std::vector<zx::event> release_fences;
release_fences.push_back(CopyEvent(release_fence));
// Call Present with both the acquire and release fences.
session->Present(0u, std::move(acquire_fences), std::move(release_fences),
[](fuchsia::images::PresentationInfo info) {});
RunLoopFor(zx::sec(1));
EXPECT_EQ(1u, handler->present_count());
EXPECT_FALSE(IsFenceSignalled(release_fence));
// Call Present again with no fences.
session->Present(0u, std::vector<zx::event>(), std::vector<zx::event>(),
[](fuchsia::images::PresentationInfo info) {});
RunLoopFor(zx::sec(1));
EXPECT_EQ(2u, handler->present_count());
EXPECT_FALSE(IsFenceSignalled(release_fence));
// Now signal the acquire fence.
acquire_fence.signal(0u, escher::kFenceSignalled);
// Now expect that the first frame was presented, and its release fence was
// signalled.
RunLoopFor(zx::sec(1));
EXPECT_TRUE(IsFenceSignalled(release_fence));
}
} // namespace test
} // namespace gfx
} // namespace scenic_impl