123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
- // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
- // SPDX-License-Identifier: MIT
- #include <Jolt/Jolt.h>
- #include <Jolt/ConfigurationString.h>
- #include <Jolt/Core/FPException.h>
- #include <Jolt/Core/Factory.h>
- #include <Jolt/RegisterTypes.h>
- #ifdef JPH_PLATFORM_WINDOWS
- #include <crtdbg.h>
- #endif // JPH_PLATFORM_WINDOWS
- #ifdef JPH_PLATFORM_ANDROID
- #include <Jolt/Core/Color.h>
- #include <android/log.h>
- #include <android_native_app_glue.h>
- #endif // JPH_PLATFORM_ANDROID
- JPH_SUPPRESS_WARNINGS_STD_BEGIN
- #include <cstdarg>
- JPH_SUPPRESS_WARNINGS_STD_END
- using namespace JPH;
- // Emit everything needed for the main function
- #define DOCTEST_CONFIG_IMPLEMENT
- #define DOCTEST_CONFIG_NO_WINDOWS_SEH
- JPH_SUPPRESS_WARNINGS_STD_BEGIN
- JPH_CLANG_16_PLUS_SUPPRESS_WARNING("-Wunsafe-buffer-usage")
- #include "doctest.h"
- JPH_SUPPRESS_WARNINGS_STD_END
- using namespace doctest;
- // Disable common warnings triggered by Jolt
- JPH_SUPPRESS_WARNINGS
- // Callback for traces
- static void TraceImpl(const char *inFMT, ...)
- {
- // Format the message
- va_list list;
- va_start(list, inFMT);
- char buffer[1024];
- vsnprintf(buffer, sizeof(buffer), inFMT, list);
- va_end(list);
- // Forward to doctest
- MESSAGE(buffer);
- }
- #ifdef JPH_ENABLE_ASSERTS
- // Callback for asserts
- static bool AssertFailedImpl(const char *inExpression, const char *inMessage, const char *inFile, uint inLine)
- {
- // Format message
- char buffer[1024];
- snprintf(buffer, sizeof(buffer), "%s:%u: (%s) %s", inFile, inLine, inExpression, inMessage != nullptr? inMessage : "");
- // Forward to doctest
- FAIL_CHECK(buffer);
- // No breakpoint
- return false;
- }
- #endif // JPH_ENABLE_ASSERTS
- #ifdef JPH_PLATFORM_WINDOWS_UWP
- JPH_SUPPRESS_WARNING_PUSH
- JPH_MSVC_SUPPRESS_WARNING(4265) // warning C4265: 'winrt::impl::implements_delegate<winrt::Windows::UI::Core::DispatchedHandler,H>': class has virtual functions, but its non-trivial destructor is not virtual; instances of this class may not be destructed correctly
- JPH_MSVC_SUPPRESS_WARNING(4668) // warning C4668: '_MANAGED' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
- JPH_MSVC_SUPPRESS_WARNING(4946) // warning C4946: reinterpret_cast used between related classes: 'winrt::impl::abi<winrt::Windows::ApplicationModel::Core::IFrameworkViewSource,void>::type' and 'winrt::impl::abi<winrt::Windows::Foundation::IUnknown,void>::type'
- JPH_MSVC_SUPPRESS_WARNING(5039) // winbase.h(13179): warning C5039: 'TpSetCallbackCleanupGroup': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception.
- JPH_MSVC_SUPPRESS_WARNING(5204) // warning C5204: 'winrt::impl::produce_base<D,winrt::Windows::ApplicationModel::Core::IFrameworkViewSource,void>': class has virtual functions, but its trivial destructor is not virtual; instances of objects derived from this class may not be destructed correctly
- JPH_MSVC_SUPPRESS_WARNING(5246) // warning C5246: '_Elems': the initialization of a subobject should be wrapped in braces
- #include <winrt/Windows.Foundation.h>
- #include <winrt/Windows.Foundation.Collections.h>
- #include <winrt/Windows.ApplicationModel.Core.h>
- #include <winrt/Windows.UI.Core.h>
- #include <winrt/Windows.UI.Composition.h>
- #include <winrt/Windows.UI.Input.h>
- JPH_SUPPRESS_WARNING_POP
- using namespace winrt;
- using namespace Windows;
- using namespace Windows::ApplicationModel::Core;
- using namespace Windows::UI;
- using namespace Windows::UI::Core;
- using namespace Windows::UI::Composition;
- struct App : implements<App, IFrameworkViewSource, IFrameworkView>
- {
- CompositionTarget mTarget { nullptr };
- IFrameworkView CreateView()
- {
- return *this;
- }
- void Initialize(CoreApplicationView const&)
- {
- }
- void Load(hstring const&)
- {
- }
- void Uninitialize()
- {
- }
- void Run()
- {
- CoreWindow window = CoreWindow::GetForCurrentThread();
- window.Activate();
- CoreDispatcher dispatcher = window.Dispatcher();
- dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit);
- }
- void SetWindow(CoreWindow const& inWindow)
- {
- // Register allocation hook
- RegisterDefaultAllocator();
- // Install callbacks
- Trace = TraceImpl;
- JPH_IF_ENABLE_ASSERTS(AssertFailed = AssertFailedImpl;)
- #ifdef _DEBUG
- // Enable leak detection
- _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
- #endif
- // Enable floating point exceptions
- FPExceptionsEnable enable_exceptions;
- JPH_UNUSED(enable_exceptions);
- // Create a factory
- Factory::sInstance = new Factory();
- // Register physics types
- RegisterTypes();
- // Run the tests
- int rv = Context().run();
- // Unregisters all types with the factory and cleans up the default material
- UnregisterTypes();
- // Destroy the factory
- delete Factory::sInstance;
- Factory::sInstance = nullptr;
- // Color the screen according to the result
- Compositor compositor;
- ContainerVisual root = compositor.CreateContainerVisual();
- mTarget = compositor.CreateTargetForCurrentView();
- mTarget.Root(root);
- SpriteVisual visual = compositor.CreateSpriteVisual();
- visual.Brush(compositor.CreateColorBrush(rv != 0 ? Windows::UI::Color { 0xff, 0xff, 0x00, 0x00 } : Windows::UI::Color { 0xff, 0x00, 0xff, 0x00 }));
- visual.Size({ inWindow.Bounds().Width, inWindow.Bounds().Height });
- visual.Offset({ 0, 0, 0, });
- root.Children().InsertAtTop(visual);
- }
- };
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
- {
- CoreApplication::Run(make<App>());
- }
- #elif !defined(JPH_PLATFORM_ANDROID)
- // Generic entry point
- int main(int argc, char** argv)
- {
- // Show used instruction sets
- std::cout << GetConfigurationString() << std::endl;
- // Register allocation hook
- RegisterDefaultAllocator();
- // Install callbacks
- Trace = TraceImpl;
- JPH_IF_ENABLE_ASSERTS(AssertFailed = AssertFailedImpl;)
- #if defined(JPH_PLATFORM_WINDOWS) && defined(_DEBUG)
- // Enable leak detection
- _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
- #endif
- // Enable floating point exceptions
- FPExceptionsEnable enable_exceptions;
- JPH_UNUSED(enable_exceptions);
- // Create a factory
- Factory::sInstance = new Factory();
- // Register physics types
- RegisterTypes();
- int rv = Context(argc, argv).run();
- // Unregisters all types with the factory and cleans up the default material
- UnregisterTypes();
- // Destroy the factory
- delete Factory::sInstance;
- Factory::sInstance = nullptr;
- return rv;
- }
- #else // !JPH_PLATFORM_ANDROID
- // Reporter that writes logs to the Android log
- struct LogReporter : public ConsoleReporter
- {
- LogReporter(const ContextOptions &inOptions) :
- ConsoleReporter(inOptions, mStream)
- {
- }
- #define REPORTER_OVERRIDE(func, type, arg) \
- void func(type arg) override \
- { \
- ConsoleReporter::func(arg); \
- string str = mStream.str(); \
- if (!str.empty()) \
- __android_log_write(ANDROID_LOG_INFO, "Jolt", str.c_str()); \
- mStream.str(""); \
- }
- REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY)
- REPORTER_OVERRIDE(test_run_end, const TestRunStats &, in)
- REPORTER_OVERRIDE(test_case_start, const TestCaseData &, in)
- REPORTER_OVERRIDE(test_case_reenter, const TestCaseData &, in)
- REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats &, in)
- REPORTER_OVERRIDE(test_case_exception, const TestCaseException &, in)
- REPORTER_OVERRIDE(subcase_start, const SubcaseSignature &, in)
- REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY)
- REPORTER_OVERRIDE(log_assert, const AssertData &, in)
- REPORTER_OVERRIDE(log_message, const MessageData &, in)
- REPORTER_OVERRIDE(test_case_skipped, const TestCaseData &, in)
- private:
- thread_local static std::ostringstream mStream;
- };
- thread_local std::ostringstream LogReporter::mStream;
- DOCTEST_REGISTER_REPORTER("android_log", 0, LogReporter);
- void AndroidInitialize(android_app *inApp)
- {
- // Log configuration
- __android_log_write(ANDROID_LOG_INFO, "Jolt", GetConfigurationString());
- // Register allocation hook
- RegisterDefaultAllocator();
- // Install callbacks
- Trace = TraceImpl;
- JPH_IF_ENABLE_ASSERTS(AssertFailed = AssertFailedImpl;)
- // Enable floating point exceptions
- FPExceptionsEnable enable_exceptions;
- JPH_UNUSED(enable_exceptions);
- // Create a factory
- Factory::sInstance = new Factory();
- // Register physics types
- RegisterTypes();
- // Run all tests
- Context context;
- context.addFilter("reporters", "android_log");
- int return_value = context.run();
- // Color the screen according to the test result
- JPH::Color color = return_value == 0? JPH::Color::sGreen : JPH::Color::sRed;
- ANativeWindow_acquire(inApp->window);
- ANativeWindow_Buffer buffer;
- ARect bounds;
- ANativeWindow_lock(inApp->window, &buffer, &bounds);
- switch (buffer.format)
- {
- case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
- case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
- {
- uint32 color_u32 = color.GetUInt32();
- for (int y = 0; y < buffer.height; ++y)
- {
- uint32 *dest = (uint32 *)((uint8 *)buffer.bits + y * buffer.stride * sizeof(uint32));
- for (int x = 0; x < buffer.width; ++x)
- *dest++ = color_u32;
- }
- break;
- }
- case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
- {
- uint16 color_u16 = (color.b >> 3) + ((color.g >> 2) << 5) + ((color.r >> 3) << 11);
- for (int y = 0; y < buffer.height; ++y)
- {
- uint16 *dest = (uint16 *) ((uint8 *) buffer.bits + y * buffer.stride * sizeof(uint16));
- for (int x = 0; x < buffer.width; ++x)
- *dest++ = color_u16;
- }
- break;
- }
- default:
- // TODO implement
- break;
- }
- ANativeWindow_unlockAndPost(inApp->window);
- ANativeWindow_release(inApp->window);
- // Unregisters all types with the factory and cleans up the default material
- UnregisterTypes();
- // Destroy the factory
- delete Factory::sInstance;
- Factory::sInstance = nullptr;
- }
- // Handle callback from Android
- void AndroidHandleCommand(android_app *inApp, int32_t inCmd)
- {
- switch (inCmd)
- {
- case APP_CMD_INIT_WINDOW:
- AndroidInitialize(inApp);
- break;
- }
- }
- // Main entry point for android
- void android_main(struct android_app *ioApp)
- {
- ioApp->onAppCmd = AndroidHandleCommand;
- int events;
- android_poll_source *source;
- do
- {
- if (ALooper_pollAll(1, nullptr, &events, (void **)&source) >= 0 && source != nullptr)
- source->process(ioApp, source);
- } while (ioApp->destroyRequested == 0);
- }
- #endif // JPH_PLATFORM_ANDROID
|