From 378ddc66c7fc121df701055502e1533bb81300e3 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 28 Dec 2021 18:45:40 +0100 Subject: [PATCH] Mac impl progress --- Source/Engine/Platform/ConditionVariable.h | 2 + Source/Engine/Platform/CriticalSection.h | 2 + .../Engine/Platform/Mac/MacCriticalSection.h | 1 - Source/Engine/Platform/Mac/MacFile.cpp | 3 - Source/Engine/Platform/Mac/MacFileSystem.cpp | 44 +-- Source/Engine/Platform/Mac/MacPlatform.cpp | 33 ++- Source/Engine/Platform/Mac/MacStringUtils.cpp | 267 +----------------- Source/Engine/Platform/Mac/MacThread.cpp | 49 +++- Source/Engine/Platform/Mac/MacThread.h | 12 +- Source/Engine/Platform/Mac/MacWindow.cpp | 10 +- Source/Tools/Flax.Build/Configuration.cs | 2 + .../Flax.Build/Platforms/Mac/MacToolchain.cs | 12 +- 12 files changed, 111 insertions(+), 326 deletions(-) diff --git a/Source/Engine/Platform/ConditionVariable.h b/Source/Engine/Platform/ConditionVariable.h index 3d9989b18..f9a3de919 100644 --- a/Source/Engine/Platform/ConditionVariable.h +++ b/Source/Engine/Platform/ConditionVariable.h @@ -8,6 +8,8 @@ #include "Unix/UnixConditionVariable.h" #elif PLATFORM_SWITCH #include "Platforms/Switch/Engine/Platform/SwitchConditionVariable.h" +#elif PLATFORM_MAC +#include "Mac/MacConditionVariable.h" #else #error Missing Condition Variable implementation! #endif diff --git a/Source/Engine/Platform/CriticalSection.h b/Source/Engine/Platform/CriticalSection.h index f3e9c27f0..7b0ed971b 100644 --- a/Source/Engine/Platform/CriticalSection.h +++ b/Source/Engine/Platform/CriticalSection.h @@ -8,6 +8,8 @@ #include "Unix/UnixCriticalSection.h" #elif PLATFORM_SWITCH #include "Platforms/Switch/Engine/Platform/SwitchCriticalSection.h" +#elif PLATFORM_MAC +#include "Mac/MacCriticalSection.h" #else #error Missing Critical Section implementation! #endif diff --git a/Source/Engine/Platform/Mac/MacCriticalSection.h b/Source/Engine/Platform/Mac/MacCriticalSection.h index 2f83260f1..e6254706f 100644 --- a/Source/Engine/Platform/Mac/MacCriticalSection.h +++ b/Source/Engine/Platform/Mac/MacCriticalSection.h @@ -15,7 +15,6 @@ class MacConditionVariable; class FLAXENGINE_API MacCriticalSection { friend MacConditionVariable; - private: pthread_mutex_t _mutex; diff --git a/Source/Engine/Platform/Mac/MacFile.cpp b/Source/Engine/Platform/Mac/MacFile.cpp index 109306ad7..2e8456d9e 100644 --- a/Source/Engine/Platform/Mac/MacFile.cpp +++ b/Source/Engine/Platform/Mac/MacFile.cpp @@ -73,7 +73,6 @@ MacFile* MacFile::Open(const StringView& path, FileMode mode, FileAccess access, auto handle = open(pathANSI.Get(), flags, omode); if (handle == -1) { - LOG_Mac_LAST_ERROR; return nullptr; } @@ -91,7 +90,6 @@ bool MacFile::Read(void* buffer, uint32 bytesToRead, uint32* bytesRead) } if (bytesRead) *bytesRead = 0; - LOG_Mac_LAST_ERROR; return true; } @@ -106,7 +104,6 @@ bool MacFile::Write(const void* buffer, uint32 bytesToWrite, uint32* bytesWritte } if (bytesWritten) *bytesWritten = 0; - LOG_Mac_LAST_ERROR; return true; } diff --git a/Source/Engine/Platform/Mac/MacFileSystem.cpp b/Source/Engine/Platform/Mac/MacFileSystem.cpp index 165fa2bfb..a64da4d0e 100644 --- a/Source/Engine/Platform/Mac/MacFileSystem.cpp +++ b/Source/Engine/Platform/Mac/MacFileSystem.cpp @@ -12,7 +12,6 @@ #include "Engine/Utilities/StringConverter.h" #include #include -#include #include #include #include @@ -309,37 +308,24 @@ bool MacFileSystem::CopyFile(const StringView& dst, const StringView& src) if (dstFile < 0) goto out_error; - // first try the kernel method - struct stat statBuf; - fstat(srcFile, &statBuf); - readSize = 1; - while (readSize > 0) + while (readSize = read(srcFile, buffer, sizeof(buffer)), readSize > 0) { - readSize = sendfile(dstFile, srcFile, 0, statBuf.st_size); - } - // sendfile could fail for example if the input file is not nmap'able - // in this case we fall back to the read/write loop - if (readSize < 0) - { - while (readSize = read(srcFile, buffer, sizeof(buffer)), readSize > 0) - { - char* ptr = buffer; - ssize_t writeSize; + char* ptr = buffer; + ssize_t writeSize; - do + do + { + writeSize = write(dstFile, ptr, readSize); + if (writeSize >= 0) { - writeSize = write(dstFile, ptr, readSize); - if (writeSize >= 0) - { - readSize -= writeSize; - ptr += writeSize; - } - else if (errno != EINTR) - { - goto out_error; - } - } while (readSize > 0); - } + readSize -= writeSize; + ptr += writeSize; + } + else if (errno != EINTR) + { + goto out_error; + } + } while (readSize > 0); } if (readSize == 0) diff --git a/Source/Engine/Platform/Mac/MacPlatform.cpp b/Source/Engine/Platform/Mac/MacPlatform.cpp index c2dc09307..5fb09ecf4 100644 --- a/Source/Engine/Platform/Mac/MacPlatform.cpp +++ b/Source/Engine/Platform/Mac/MacPlatform.cpp @@ -32,17 +32,21 @@ #include #include #include +#include +#include CPUInfo MacCpu; Guid DeviceId; String UserLocale, ComputerName; byte MacAddress[6]; +double SecondsPerCycle; DialogResult MessageBox::Show(Window* parent, const StringView& text, const StringView& caption, MessageBoxButtons buttons, MessageBoxIcon icon) { if (CommandLine::Options.Headless) return DialogResult::None; - todo; + // TODO: impl message box on Mac + return DialogResult::None; } class MacKeyboard : public Keyboard @@ -147,7 +151,7 @@ ProcessMemoryStats MacPlatform::GetProcessMemoryStats() return ProcessMemoryStats(); // TODO: platform stats on Mac } -uint64 UnixPlatform::GetCurrentProcessId() +uint64 MacPlatform::GetCurrentProcessId() { return getpid(); } @@ -176,20 +180,17 @@ void MacPlatform::Sleep(int32 milliseconds) double MacPlatform::GetTimeSeconds() { - MISSING_CODE("MacPlatform::GetTimeSeconds"); - return 0.0; // TODO: clock on Mac + return SecondsPerCycle * mach_absolute_time(); } uint64 MacPlatform::GetTimeCycles() { - MISSING_CODE("MacPlatform::GetTimeCycles"); - return 0; // TODO: clock on Mac + return mach_absolute_time(); } uint64 MacPlatform::GetClockFrequency() { - MISSING_CODE("MacPlatform::GetClockFrequency"); - return 0; // TODO: clock on Mac + return (uint64)(1.0 / SecondsPerCycle); } void MacPlatform::GetSystemTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& minute, int32& second, int32& millisecond) @@ -238,7 +239,14 @@ bool MacPlatform::Init() { if (PlatformBase::Init()) return true; - + + // Init timing + { + mach_timebase_info_data_t info; + mach_timebase_info(&info); + SecondsPerCycle = 1e-9 * (double)info.numer / (double)info.denom; + } + // TODO: get MacCpu // TODO: get MacAddress @@ -250,8 +258,8 @@ bool MacPlatform::Init() // TODO: get UserLocale // TODO: get ComputerName - Input::Mouse = Impl::Mouse = New(); - Input::Keyboard = Impl::Keyboard = New(); + Input::Mouse = New(); + Input::Keyboard = New(); return false; } @@ -275,7 +283,8 @@ void MacPlatform::Exit() int32 MacPlatform::GetDpi() { - return todo; + // TODO: Screen DPI on Mac + return 96; } String MacPlatform::GetUserLocaleName() diff --git a/Source/Engine/Platform/Mac/MacStringUtils.cpp b/Source/Engine/Platform/Mac/MacStringUtils.cpp index f84026c46..f7a6ca15c 100644 --- a/Source/Engine/Platform/Mac/MacStringUtils.cpp +++ b/Source/Engine/Platform/Mac/MacStringUtils.cpp @@ -9,269 +9,8 @@ #include #include -bool StringUtils::IsUpper(char c) -{ - return isupper(c) != 0; -} - -bool StringUtils::IsLower(char c) -{ - return islower(c) != 0; -} - -bool StringUtils::IsAlpha(char c) -{ - return iswalpha(c) != 0; -} - -bool StringUtils::IsPunct(char c) -{ - return ispunct(c) != 0; -} - -bool StringUtils::IsAlnum(char c) -{ - return isalnum(c) != 0; -} - -bool StringUtils::IsDigit(char c) -{ - return isdigit(c) != 0; -} - -bool StringUtils::IsHexDigit(char c) -{ - return isxdigit(c) != 0; -} - -bool StringUtils::IsWhitespace(char c) -{ - return isspace(c) != 0; -} - -char StringUtils::ToUpper(char c) -{ - return toupper(c); -} - -char StringUtils::ToLower(char c) -{ - return tolower(c); -} - -bool StringUtils::IsUpper(Char c) -{ - return iswupper(c) != 0; -} - -bool StringUtils::IsLower(Char c) -{ - return iswlower(c) != 0; -} - -bool StringUtils::IsAlpha(Char c) -{ - return iswalpha(c) != 0; -} - -bool StringUtils::IsPunct(Char c) -{ - return iswpunct(c) != 0; -} - -bool StringUtils::IsAlnum(Char c) -{ - return iswalnum(c) != 0; -} - -bool StringUtils::IsDigit(Char c) -{ - return iswdigit(c) != 0; -} - -bool StringUtils::IsHexDigit(Char c) -{ - return iswxdigit(c) != 0; -} - -bool StringUtils::IsWhitespace(Char c) -{ - return iswspace(c) != 0; -} - -Char StringUtils::ToUpper(Char c) -{ - return towupper(c); -} - -Char StringUtils::ToLower(Char c) -{ - return towlower(c); -} - -int32 StringUtils::Compare(const Char* str1, const Char* str2) -{ - Char c1, c2; - int32 i; - do - { - c1 = *str1++; - c2 = *str2++; - i = (int32)c1 - (int32)c2; - } while (i == 0 && c1 && c2); - return i; -} - -int32 StringUtils::Compare(const Char* str1, const Char* str2, int32 maxCount) -{ - Char c1, c2; - int32 i; - if (maxCount == 0) - return 0; - do - { - c1 = *str1++; - c2 = *str2++; - i = (int32)c1 - (int32)c2; - maxCount--; - } while (i == 0 && c1 && c2 && maxCount); - return i; -} - -int32 StringUtils::CompareIgnoreCase(const Char* str1, const Char* str2) -{ - Char c1, c2; - int32 i; - do - { - c1 = ToLower(*str1++); - c2 = ToLower(*str2++); - i = (int32)c1 - (int32)c2; - } while (i == 0 && c1 && c2); - return i; -} - -int32 StringUtils::CompareIgnoreCase(const Char* str1, const Char* str2, int32 maxCount) -{ - Char c1, c2; - int32 i; - if (maxCount == 0) - return 0; - do - { - c1 = ToLower(*str1++); - c2 = ToLower(*str2++); - i = (int32)c1 - (int32)c2; - maxCount--; - } while (i == 0 && c1 && c2 && maxCount); - return i; -} - -int32 StringUtils::Length(const Char* str) -{ - if (!str) - return 0; - const Char* ptr = str; - for (; *ptr; ++ptr) - { - } - return ptr - str; -} - -int32 StringUtils::Length(const char* str) -{ - if (!str) - return 0; - return static_cast(strlen(str)); -} - -int32 StringUtils::Compare(const char* str1, const char* str2) -{ - return strcmp(str1, str2); -} - -int32 StringUtils::Compare(const char* str1, const char* str2, int32 maxCount) -{ - return strncmp(str1, str2, maxCount); -} - -int32 StringUtils::CompareIgnoreCase(const char* str1, const char* str2) -{ - return strcasecmp(str1, str2); -} - -int32 StringUtils::CompareIgnoreCase(const char* str1, const char* str2, int32 maxCount) -{ - return strncasecmp(str1, str2, maxCount); -} - -Char* StringUtils::Copy(Char* dst, const Char* src) -{ - Char* q = dst; - const Char* p = src; - Char ch; - do - { - *q++ = ch = *p++; - } while (ch); - return dst; -} - -Char* StringUtils::Copy(Char* dst, const Char* src, int32 count) -{ - Char* q = dst; - const Char* p = src; - char ch; - while (count) - { - count--; - *q++ = ch = *p++; - if (!ch) - break; - } - *q = 0; - return dst; -} - -const Char* StringUtils::Find(const Char* str, const Char* toFind) -{ - while (*str) - { - const Char* start = str; - const Char* sub = toFind; - - // If first character of sub string match, check for whole string - while (*str && *sub && *str == *sub) - { - str++; - sub++; - } - - // If complete substring match, return starting address - if (!*sub) - return (Char*)start; - - // Increment main string - str = start + 1; - } - - // No matches - return nullptr; -} - -const char* StringUtils::Find(const char* str, const char* toFind) -{ - return strstr(str, toFind); -} - -void StringUtils::ConvertANSI2UTF16(const char* from, Char* to, int32 len) -{ - todo; -} - -void StringUtils::ConvertUTF162ANSI(const Char* from, char* to, int32 len) -{ - todo; -} +// Reuse Unix-impl +#define PLATFORM_UNIX 1 +#include "../Unix/UnixStringUtils.cpp" #endif diff --git a/Source/Engine/Platform/Mac/MacThread.cpp b/Source/Engine/Platform/Mac/MacThread.cpp index dba77dda6..edfe7a128 100644 --- a/Source/Engine/Platform/Mac/MacThread.cpp +++ b/Source/Engine/Platform/Mac/MacThread.cpp @@ -3,21 +3,66 @@ #if PLATFORM_MAC #include "MacThread.h" +#include "Engine/Core/Log.h" #include "Engine/Threading/IRunnable.h" #include "Engine/Threading/ThreadRegistry.h" MacThread::MacThread(IRunnable* runnable, const String& name, ThreadPriority priority) : ThreadBase(runnable, name, priority) + , _thread(0) { } MacThread::~MacThread() { + ASSERT(_thread == 0); } -MacThread* Create(IRunnable* runnable, const String& name, ThreadPriority priority = ThreadPriority::Normal, uint32 stackSize = 0) +MacThread* MacThread::Create(IRunnable* runnable, const String& name, ThreadPriority priority, uint32 stackSize) { - // TODO: imp this + auto thread = New(runnable, name, priority); + pthread_attr_t attr; + pthread_attr_init(&attr); + if (stackSize != 0) + pthread_attr_setstacksize(&attr, stackSize); + const int32 result = pthread_create(&thread->_thread, &attr, ThreadProc, thread); + if (result != 0) + { + LOG(Warning, "Failed to spawn a thread. Result code: {0}", result); + Delete(thread); + return nullptr; + } + thread->SetPriorityInternal(thread->GetPriority()); + return thread; +} + +void MacThread::Join() +{ + pthread_join(_thread, nullptr); +} + +void* MacThread::ThreadProc(void* pThis) +{ + auto thread = (MacThread*)pThis; + const int32 exitCode = thread->Run(); + return (void*)(uintptr)exitCode; +} + +void MacThread::ClearHandleInternal() +{ + _thread = 0; +} + +void MacThread::SetPriorityInternal(ThreadPriority priority) +{ + // TODO: impl this +} + +void MacThread::KillInternal(bool waitForJoin) +{ + if (waitForJoin) + pthread_join(_thread, nullptr); + pthread_kill(_thread, SIGKILL); } #endif diff --git a/Source/Engine/Platform/Mac/MacThread.h b/Source/Engine/Platform/Mac/MacThread.h index d30ba696b..bc1b87deb 100644 --- a/Source/Engine/Platform/Mac/MacThread.h +++ b/Source/Engine/Platform/Mac/MacThread.h @@ -11,6 +11,10 @@ /// class MacThread : public ThreadBase { +protected: + + pthread_t _thread; + public: MacThread(IRunnable* runnable, const String& name, ThreadPriority priority); @@ -22,10 +26,12 @@ public: protected: + static void* ThreadProc(void* pThis); + // [ThreadBase] - void ClearHandleInternal(); - void SetPriorityInternal(ThreadPriority priority); - void KillInternal(bool waitForJoin); + void ClearHandleInternal() override; + void SetPriorityInternal(ThreadPriority priority) override; + void KillInternal(bool waitForJoin) override; }; #endif diff --git a/Source/Engine/Platform/Mac/MacWindow.cpp b/Source/Engine/Platform/Mac/MacWindow.cpp index 7afa8176e..5fc5a6d03 100644 --- a/Source/Engine/Platform/Mac/MacWindow.cpp +++ b/Source/Engine/Platform/Mac/MacWindow.cpp @@ -3,6 +3,7 @@ #if PLATFORM_MAC #include "../Window.h" +#include "Engine/Graphics/RenderTask.h" MacWindow::MacWindow(const CreateWindowSettings& settings) : WindowBase(settings) @@ -91,13 +92,4 @@ void MacWindow::SetIsFullscreen(bool isFullscreen) { } -void MacWindow::GetScreenInfo(int32& x, int32& y, int32& width, int32& height) const -{ - // TODO: proper screen info - x = 0; - y = 0; - width = (int32)_clientSize.X; - height = (int32)_clientSize.Y; -} - #endif diff --git a/Source/Tools/Flax.Build/Configuration.cs b/Source/Tools/Flax.Build/Configuration.cs index 7abd39e09..b4cad184e 100644 --- a/Source/Tools/Flax.Build/Configuration.cs +++ b/Source/Tools/Flax.Build/Configuration.cs @@ -234,6 +234,8 @@ namespace Flax.Build { if (options.Platform.Target == TargetPlatform.PS5) return false; // TODO: mono for ps5 + if (options.Platform.Target == TargetPlatform.Mac) + return false; // TODO: mono for Mac return UseCSharp || options.Target.IsEditor; } } diff --git a/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs b/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs index 714551952..8f3f39e55 100644 --- a/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs @@ -14,6 +14,8 @@ namespace Flax.Build.Platforms /// public sealed class MacToolchain : Toolchain { + private string MinMacOSXVer = "10.14"; + public string ToolchainPath; public string SdkPath; public string ClangPath; @@ -118,12 +120,16 @@ namespace Flax.Build.Platforms commonArgs.Add("c++"); commonArgs.Add("-std=c++14"); commonArgs.Add("-stdlib=libc++"); + commonArgs.Add("-mmacosx-version-min=" + MinMacOSXVer); commonArgs.Add("-Wdelete-non-virtual-dtor"); commonArgs.Add("-fno-math-errno"); commonArgs.Add("-fasm-blocks"); commonArgs.Add("-fdiagnostics-format=msvc"); + commonArgs.Add("-Wno-absolute-value"); + commonArgs.Add("-Wno-nullability-completeness"); + // Hide all symbols by default commonArgs.Add("-fvisibility-inlines-hidden"); commonArgs.Add("-fvisibility-ms-compat"); @@ -218,14 +224,12 @@ namespace Flax.Build.Platforms { var linkEnvironment = options.LinkEnv; var task = graph.Add(); - Console.WriteLine("Linking " + outputFilePath + " as " + linkEnvironment.Output); - foreach (var f in linkEnvironment.InputFiles) - Console.WriteLine(f); // Setup arguments var args = new List(); { args.Add(string.Format("-o \"{0}\"", outputFilePath)); + args.Add("-mmacosx-version-min=" + MinMacOSXVer); if (!options.LinkEnv.DebugInformation) args.Add("-Wl,--strip-debug"); @@ -233,7 +237,9 @@ namespace Flax.Build.Platforms switch (linkEnvironment.Output) { case LinkerOutput.Executable: + break; case LinkerOutput.SharedLibrary: + args.Add("-dynamiclib"); break; case LinkerOutput.StaticLibrary: case LinkerOutput.ImportLibrary: