| // Copyright 2013 The Flutter 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 "flutter/fml/synchronization/waitable_event.h" | |
| #include "flutter/testing/testing.h" | |
| #include "impeller/toolkit/android/choreographer.h" | |
| #include "impeller/toolkit/android/hardware_buffer.h" | |
| #include "impeller/toolkit/android/proc_table.h" | |
| #include "impeller/toolkit/android/surface_control.h" | |
| #include "impeller/toolkit/android/surface_transaction.h" | |
| namespace impeller::android::testing { | |
| #define DISABLE_ANDROID_PROC(name) \ | |
| struct Disable##name { \ | |
| Disable##name() { \ | |
| real_proc = GetMutableProcTable().name.proc; \ | |
| GetMutableProcTable().name.proc = nullptr; \ | |
| } \ | |
| ~Disable##name() { \ | |
| GetMutableProcTable().name.proc = real_proc; \ | |
| } \ | |
| decltype(name)* real_proc; \ | |
| } disable##name; | |
| TEST(ToolkitAndroidTest, CanCreateProcTable) { | |
| ProcTable proc_table; | |
| ASSERT_TRUE(proc_table.IsValid()); | |
| } | |
| TEST(ToolkitAndroidTest, GuardsAgainstZeroSizedDescriptors) { | |
| auto desc = HardwareBufferDescriptor::MakeForSwapchainImage({0, 0}); | |
| ASSERT_GT(desc.size.width, 0u); | |
| ASSERT_GT(desc.size.height, 0u); | |
| } | |
| TEST(ToolkitAndroidTest, CanCreateHardwareBuffer) { | |
| if (!HardwareBuffer::IsAvailableOnPlatform()) { | |
| GTEST_SKIP() << "Hardware buffers are not supported on this platform."; | |
| } | |
| ASSERT_TRUE(HardwareBuffer::IsAvailableOnPlatform()); | |
| auto desc = HardwareBufferDescriptor::MakeForSwapchainImage({100, 100}); | |
| ASSERT_TRUE(desc.IsAllocatable()); | |
| HardwareBuffer buffer(desc); | |
| ASSERT_TRUE(buffer.IsValid()); | |
| } | |
| TEST(ToolkitAndroidTest, CanGetHardwareBufferIDs) { | |
| if (!HardwareBuffer::IsAvailableOnPlatform()) { | |
| GTEST_SKIP() << "Hardware buffers are not supported on this platform."; | |
| } | |
| ASSERT_TRUE(HardwareBuffer::IsAvailableOnPlatform()); | |
| if (!GetProcTable().AHardwareBuffer_getId.IsAvailable()) { | |
| GTEST_SKIP() << "Hardware buffer IDs are not available on this platform."; | |
| } | |
| auto desc = HardwareBufferDescriptor::MakeForSwapchainImage({100, 100}); | |
| ASSERT_TRUE(desc.IsAllocatable()); | |
| HardwareBuffer buffer(desc); | |
| ASSERT_TRUE(buffer.IsValid()); | |
| ASSERT_TRUE(buffer.GetSystemUniqueID().has_value()); | |
| } | |
| TEST(ToolkitAndroidTest, HardwareBufferNullIDIfAPIUnavailable) { | |
| DISABLE_ANDROID_PROC(AHardwareBuffer_getId); | |
| ASSERT_FALSE(HardwareBuffer::GetSystemUniqueID(nullptr).has_value()); | |
| } | |
| TEST(ToolkitAndroidTest, CanDescribeHardwareBufferHandles) { | |
| if (!HardwareBuffer::IsAvailableOnPlatform()) { | |
| GTEST_SKIP() << "Hardware buffers are not supported on this platform."; | |
| } | |
| ASSERT_TRUE(HardwareBuffer::IsAvailableOnPlatform()); | |
| auto desc = HardwareBufferDescriptor::MakeForSwapchainImage({100, 100}); | |
| ASSERT_TRUE(desc.IsAllocatable()); | |
| HardwareBuffer buffer(desc); | |
| ASSERT_TRUE(buffer.IsValid()); | |
| auto a_desc = HardwareBuffer::Describe(buffer.GetHandle()); | |
| ASSERT_TRUE(a_desc.has_value()); | |
| ASSERT_EQ(a_desc->width, 100u); // NOLINT | |
| ASSERT_EQ(a_desc->height, 100u); // NOLINT | |
| } | |
| TEST(ToolkitAndroidTest, CanApplySurfaceTransaction) { | |
| if (!SurfaceTransaction::IsAvailableOnPlatform()) { | |
| GTEST_SKIP() << "Surface controls are not supported on this platform."; | |
| } | |
| ASSERT_TRUE(SurfaceTransaction::IsAvailableOnPlatform()); | |
| SurfaceTransaction transaction; | |
| ASSERT_TRUE(transaction.IsValid()); | |
| fml::AutoResetWaitableEvent event; | |
| ASSERT_TRUE(transaction.Apply([&event]() { event.Signal(); })); | |
| event.Wait(); | |
| } | |
| TEST(ToolkitAndroidTest, SurfacControlsAreAvailable) { | |
| if (!SurfaceControl::IsAvailableOnPlatform()) { | |
| GTEST_SKIP() << "Surface controls are not supported on this platform."; | |
| } | |
| ASSERT_TRUE(SurfaceControl::IsAvailableOnPlatform()); | |
| } | |
| TEST(ToolkitAndroidTest, ChoreographerIsAvailable) { | |
| if (!Choreographer::IsAvailableOnPlatform()) { | |
| GTEST_SKIP() << "Choreographer is not supported on this platform."; | |
| } | |
| ASSERT_TRUE(Choreographer::IsAvailableOnPlatform()); | |
| } | |
| TEST(ToolkitAndroidTest, CanPostAndNotWaitForFrameCallbacks) { | |
| if (!Choreographer::IsAvailableOnPlatform()) { | |
| GTEST_SKIP() << "Choreographer is not supported on this platform."; | |
| } | |
| const auto& choreographer = Choreographer::GetInstance(); | |
| ASSERT_TRUE(choreographer.IsValid()); | |
| ASSERT_TRUE(choreographer.PostFrameCallback([](auto) {})); | |
| } | |
| TEST(ToolkitAndroidTest, CanPostAndWaitForFrameCallbacks) { | |
| if (!Choreographer::IsAvailableOnPlatform()) { | |
| GTEST_SKIP() << "Choreographer is not supported on this platform."; | |
| } | |
| if ((true)) { | |
| GTEST_SKIP() | |
| << "Disabled till the test harness is in an Android activity. " | |
| "Running it without one will hang because the choreographer " | |
| "frame callback will never execute."; | |
| } | |
| const auto& choreographer = Choreographer::GetInstance(); | |
| ASSERT_TRUE(choreographer.IsValid()); | |
| fml::AutoResetWaitableEvent event; | |
| ASSERT_TRUE(choreographer.PostFrameCallback( | |
| [&event](auto point) { event.Signal(); })); | |
| event.Wait(); | |
| } | |
| } // namespace impeller::android::testing |