diff --git a/internal/glfw/api_darwin.go b/internal/glfw/api_darwin.go new file mode 100644 index 000000000..90d70f921 --- /dev/null +++ b/internal/glfw/api_darwin.go @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2009-2016 Camilla Löwy +// SPDX-FileCopyrightText: 2024 The Ebitengine Authors + +package glfw + +// #include "internal_unix.h" +import "C" + +import ( + "fmt" + + "github.com/ebitengine/purego" +) + +type mach_timebase_info_data_t struct { + numer uint32 + denom uint32 +} + +var mach_absolute_time func() uint64 +var mach_timebase_info func(*mach_timebase_info_data_t) +var pthread_key_create func(key *C.pthread_key_t, destructor uintptr) int32 +var pthread_key_delete func(key C.pthread_key_t) int32 +var pthread_getspecific func(key C.pthread_key_t) uintptr +var pthread_setspecific func(key C.pthread_key_t, value uintptr) int32 +var pthread_mutex_init func(mutex *C.pthread_mutex_t, attr *C.pthread_mutexattr_t) int32 +var pthread_mutex_destroy func(mutex *C.pthread_mutex_t) int32 +var pthread_mutex_lock func(mutex *C.pthread_mutex_t) int32 +var pthread_mutex_unlock func(mutex *C.pthread_mutex_t) int32 + +// TODO: replace with Go error handling +var _glfwInputError func(code int32, format *C.char) + +func init() { + purego.RegisterLibFunc(&_glfwInputError, purego.RTLD_DEFAULT, "_glfwInputError") + + libSystem, err := purego.Dlopen("/usr/lib/libSystem.B.dylib", purego.RTLD_LAZY|purego.RTLD_GLOBAL) + if err != nil { + panic(fmt.Errorf("glfw: failed to dlopen: %w", err)) + } + purego.RegisterLibFunc(&mach_absolute_time, libSystem, "mach_absolute_time") + purego.RegisterLibFunc(&mach_timebase_info, libSystem, "mach_timebase_info") + purego.RegisterLibFunc(&pthread_key_create, libSystem, "pthread_key_create") + purego.RegisterLibFunc(&pthread_key_delete, libSystem, "pthread_key_delete") + purego.RegisterLibFunc(&pthread_getspecific, libSystem, "pthread_getspecific") + purego.RegisterLibFunc(&pthread_setspecific, libSystem, "pthread_setspecific") + purego.RegisterLibFunc(&pthread_mutex_init, libSystem, "pthread_mutex_init") + purego.RegisterLibFunc(&pthread_mutex_destroy, libSystem, "pthread_mutex_destroy") + purego.RegisterLibFunc(&pthread_mutex_lock, libSystem, "pthread_mutex_lock") + purego.RegisterLibFunc(&pthread_mutex_unlock, libSystem, "pthread_mutex_unlock") +} diff --git a/internal/glfw/cocoa_time_darwin.c b/internal/glfw/cocoa_time_darwin.c deleted file mode 100644 index 8aac85d88..000000000 --- a/internal/glfw/cocoa_time_darwin.c +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2009-2016 Camilla Löwy -// SPDX-FileCopyrightText: 2023 The Ebitengine Authors - -#include "internal_unix.h" - -#include - - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -// Initialise timer -// -void _glfwInitTimerNS(void) -{ - mach_timebase_info_data_t info; - mach_timebase_info(&info); - - _glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer; -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - -uint64_t _glfwPlatformGetTimerValue(void) -{ - return mach_absolute_time(); -} - -uint64_t _glfwPlatformGetTimerFrequency(void) -{ - return _glfw.timer.ns.frequency; -} - diff --git a/internal/glfw/cocoa_time_darwin.go b/internal/glfw/cocoa_time_darwin.go new file mode 100644 index 000000000..cdf938aa0 --- /dev/null +++ b/internal/glfw/cocoa_time_darwin.go @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2009-2016 Camilla Löwy +// SPDX-FileCopyrightText: 2024 The Ebitengine Authors + +package glfw + +// #include "internal_unix.h" +import "C" + +//export _glfwInitTimerNS +func _glfwInitTimerNS() { + var info mach_timebase_info_data_t + mach_timebase_info(&info) + C._glfw.timer.ns.frequency = C.ulonglong(info.denom*1e9) / C.ulonglong(info.numer) +} + +//export _glfwPlatformGetTimerValue +func _glfwPlatformGetTimerValue() uint64 { + return mach_absolute_time() +} + +//export _glfwPlatformGetTimerFrequency +func _glfwPlatformGetTimerFrequency() uint64 { + return uint64(C._glfw.timer.ns.frequency) +} diff --git a/internal/glfw/posix_thread_darwin.go b/internal/glfw/posix_thread_darwin.go new file mode 100644 index 000000000..51b4deb5e --- /dev/null +++ b/internal/glfw/posix_thread_darwin.go @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2002-2006 Marcus Geelnard +// SPDX-FileCopyrightText: 2006-2017 Camilla Löwy +// SPDX-FileCopyrightText: 2024 The Ebitengine Authors + +package glfw + +// #include "internal_unix.h" +import "C" + +import "unsafe" + +// TODO: make these methods on GLFWtls like on windows +// TODO: use uintptr instead of unsafe.Pointer once matching C API is no longer needed + +//export _glfwPlatformCreateTls +func _glfwPlatformCreateTls(tls *C._GLFWtls) C.GLFWbool { + if tls.posix.allocated != False { + panic("glfw: TLS must not be allocated") + } + if pthread_key_create(&tls.posix.key, 0) != 0 { + _glfwInputError(int32(PlatformError), + C.CString("POSIX: Failed to create context TLS")) + return False + } + tls.posix.allocated = True + return True +} + +//export _glfwPlatformDestroyTls +func _glfwPlatformDestroyTls(tls *C._GLFWtls) { + if tls.posix.allocated != 0 { + pthread_key_delete(tls.posix.key) + } + *tls = C._GLFWtls{} +} + +//export _glfwPlatformGetTls +func _glfwPlatformGetTls(tls *C._GLFWtls) unsafe.Pointer { + if tls.posix.allocated != True { + panic("glfw: TLS must be allocated") + } + var p = pthread_getspecific(tls.posix.key) + return *(*unsafe.Pointer)(unsafe.Pointer(&p)) // TODO: replace with uintptr +} + +//export _glfwPlatformSetTls +func _glfwPlatformSetTls(tls *C._GLFWtls, value unsafe.Pointer) { + if tls.posix.allocated != True { + panic("glfw: TLS must be allocated") + } + pthread_setspecific(tls.posix.key, uintptr(value)) +} + +//export _glfwPlatformCreateMutex +func _glfwPlatformCreateMutex(mutex *C._GLFWmutex) C.GLFWbool { + if mutex.posix.allocated != False { + panic("glfw: mutex must not be allocated") + } + if pthread_mutex_init(&mutex.posix.handle, nil) != 0 { + _glfwInputError(int32(PlatformError), C.CString("POSIX: Failed to create mutex")) + return False + } + mutex.posix.allocated = True + return True +} + +//export _glfwPlatformDestroyMutex +func _glfwPlatformDestroyMutex(mutex *C._GLFWmutex) { + if mutex.posix.allocated != 0 { + pthread_mutex_destroy(&mutex.posix.handle) + } + *mutex = C._GLFWmutex{} +} + +//export _glfwPlatformLockMutex +func _glfwPlatformLockMutex(mutex *C._GLFWmutex) { + if mutex.posix.allocated != True { + panic("glfw: mutex must be allocated") + } + pthread_mutex_lock(&mutex.posix.handle) +} + +//export _glfwPlatformUnlockMutex +func _glfwPlatformUnlockMutex(mutex *C._GLFWmutex) { + if mutex.posix.allocated != True { + panic("glfw: mutex must be allocated") + } + pthread_mutex_unlock(&mutex.posix.handle) +} diff --git a/internal/glfw/posix_thread_unix.c b/internal/glfw/posix_thread_unix.c index 7776a80ee..5ed6c046b 100644 --- a/internal/glfw/posix_thread_unix.c +++ b/internal/glfw/posix_thread_unix.c @@ -3,7 +3,7 @@ // SPDX-FileCopyrightText: 2006-2017 Camilla Löwy // SPDX-FileCopyrightText: 2023 The Ebitengine Authors -//go:build darwin || freebsd || linux || netbsd || openbsd +//go:build freebsd || linux || netbsd || openbsd #include "internal_unix.h"