blob: 029c8130ae2b7efa4c79992e690af61a421383d3 [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 "gtest/gtest.h"
#include "lib/fxl/synchronization/waitable_event.h"
#include "garnet/bin/ui/scene_manager/resources/nodes/entity_node.h"
#include "garnet/bin/ui/scene_manager/tests/mocks.h"
#include "garnet/bin/ui/scene_manager/tests/scene_manager_test.h"
#include "garnet/bin/ui/scene_manager/tests/util.h"
#include "lib/ui/scenic/fidl_helpers.h"
#include "lib/ui/tests/test_with_message_loop.h"
namespace scene_manager {
namespace test {
TEST_F(SceneManagerTest, CreateAndDestroySession) {
scenic::SessionPtr session;
EXPECT_EQ(0U, engine()->GetSessionCount());
manager_->CreateSession(session.NewRequest(), nullptr);
RUN_MESSAGE_LOOP_UNTIL(engine()->GetSessionCount() == 1);
session = nullptr;
RUN_MESSAGE_LOOP_UNTIL(engine()->GetSessionCount() == 0);
}
TEST_F(SceneManagerTest, ScheduleUpdateOutOfOrder) {
// Create a session.
scenic::SessionPtr session;
EXPECT_EQ(0U, engine()->GetSessionCount());
manager_->CreateSession(session.NewRequest(), nullptr);
RUN_MESSAGE_LOOP_UNTIL(engine()->GetSessionCount() == 1);
// Present on the session with presentation_time = 1.
scenic::Session::PresentCallback callback = [](auto) {};
session->Present(1, CreateEventArray(1), CreateEventArray(1), callback);
// Briefly pump the message loop. Expect that the session is not destroyed.
::mozart::test::RunLoopWithTimeout(kPumpMessageLoopDuration);
// Present with an older presentation time.
session->Present(0, CreateEventArray(1), CreateEventArray(1), callback);
// Expect the session is destroyed.
RUN_MESSAGE_LOOP_UNTIL(engine()->GetSessionCount() == 0);
}
TEST_F(SceneManagerTest, ScheduleUpdateInOrder) {
// Create a session.
scenic::SessionPtr session;
EXPECT_EQ(0U, engine()->GetSessionCount());
manager_->CreateSession(session.NewRequest(), nullptr);
RUN_MESSAGE_LOOP_UNTIL(engine()->GetSessionCount() == 1);
// Present on the session with presentation_time = 1.
scenic::Session::PresentCallback callback = [](auto) {};
session->Present(1, CreateEventArray(1), CreateEventArray(1), callback);
// Briefly pump the message loop. Expect that the session is not destroyed.
::mozart::test::RunLoopWithTimeout(kPumpMessageLoopDuration);
RUN_MESSAGE_LOOP_UNTIL(engine()->GetSessionCount() == 1);
// Present with the same presentation time.
session->Present(1, CreateEventArray(1), CreateEventArray(1), callback);
// Briefly pump the message loop. Expect that the session is not destroyed.
::mozart::test::RunLoopWithTimeout(kPumpMessageLoopDuration);
RUN_MESSAGE_LOOP_UNTIL(engine()->GetSessionCount() == 1);
}
bool IsFenceSignalled(const zx::event& fence) {
zx_signals_t signals = 0u;
zx_status_t status = fence.wait_one(kFenceSignalled, 0, &signals);
FXL_DCHECK(status == ZX_OK || status == ZX_ERR_TIMED_OUT);
return signals & kFenceSignalled;
}
TEST_F(SceneManagerTest, DISABLED_ReleaseFences) {
// Tests creating a session, and calling Present with two release fences.
// The release fences should be signalled after a subsequent Present.
EXPECT_EQ(0u, engine()->GetSessionCount());
scenic::SessionPtr session;
manager_->CreateSession(session.NewRequest(), nullptr);
RUN_MESSAGE_LOOP_UNTIL(engine()->GetSessionCount() == 1);
EXPECT_EQ(1u, engine()->GetSessionCount());
auto handler = static_cast<SessionHandlerForTest*>(engine()->FindSession(1));
{
::fidl::Array<scenic::OpPtr> ops;
ops.push_back(scenic_lib::NewCreateCircleOp(1, 50.f));
ops.push_back(scenic_lib::NewCreateCircleOp(2, 25.f));
session->Enqueue(std::move(ops));
}
RUN_MESSAGE_LOOP_UNTIL(handler->enqueue_count() == 1);
EXPECT_EQ(1u, handler->enqueue_count());
// Create release fences
::fidl::Array<zx::event> release_fences = CreateEventArray(2);
zx::event release_fence1 = CopyEvent(release_fences[0]);
zx::event release_fence2 = CopyEvent(release_fences[1]);
EXPECT_FALSE(IsFenceSignalled(release_fence1));
EXPECT_FALSE(IsFenceSignalled(release_fence2));
// Call Present with release fences.
session->Present(0u, ::fidl::Array<zx::event>::New(0),
std::move(release_fences),
[](scenic::PresentationInfoPtr info) {});
RUN_MESSAGE_LOOP_UNTIL(handler->present_count() == 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, ::fidl::Array<zx::event>::New(0),
::fidl::Array<zx::event>::New(0),
[](scenic::PresentationInfoPtr info) {});
RUN_MESSAGE_LOOP_UNTIL(handler->present_count() == 2);
EXPECT_EQ(2u, handler->present_count());
RUN_MESSAGE_LOOP_UNTIL(IsFenceSignalled(release_fence1));
EXPECT_TRUE(IsFenceSignalled(release_fence2));
}
TEST_F(SceneManagerTest, 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.
EXPECT_EQ(0u, engine()->GetSessionCount());
scenic::SessionPtr session;
manager_->CreateSession(session.NewRequest(), nullptr);
RUN_MESSAGE_LOOP_UNTIL(engine()->GetSessionCount() == 1);
EXPECT_EQ(1u, engine()->GetSessionCount());
auto handler = static_cast<SessionHandlerForTest*>(engine()->FindSession(1));
{
::fidl::Array<scenic::OpPtr> ops;
ops.push_back(scenic_lib::NewCreateCircleOp(1, 50.f));
ops.push_back(scenic_lib::NewCreateCircleOp(2, 25.f));
session->Enqueue(std::move(ops));
}
RUN_MESSAGE_LOOP_UNTIL(handler->enqueue_count() == 1);
EXPECT_EQ(1u, handler->enqueue_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));
::fidl::Array<zx::event> acquire_fences;
acquire_fences.push_back(CopyEvent(acquire_fence));
::fidl::Array<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),
[](scenic::PresentationInfoPtr info) {});
RUN_MESSAGE_LOOP_UNTIL(handler->present_count() == 1);
EXPECT_EQ(1u, handler->present_count());
EXPECT_FALSE(IsFenceSignalled(release_fence));
// Call Present again with no fences.
session->Present(0u, ::fidl::Array<zx::event>::New(0),
::fidl::Array<zx::event>::New(0),
[](scenic::PresentationInfoPtr info) {});
RUN_MESSAGE_LOOP_UNTIL(handler->present_count() == 2);
EXPECT_FALSE(IsFenceSignalled(release_fence));
// Now signal the acquire fence.
acquire_fence.signal(0u, kFenceSignalled);
// Now expect that the first frame was presented, and its release fence was
// signalled.
RUN_MESSAGE_LOOP_UNTIL(IsFenceSignalled(release_fence));
}
} // namespace test
} // namespace scene_manager