81 // your code goes here
92-------------------------------------------------------------------------------
94-------------------------------------------------------------------------------
96Final Platform Layer is released under the following license:
100Copyright (c) 2017-2023 Torsten Spaete
102Permission is hereby granted, free of charge, to any person obtaining a copy
103of this software and associated documentation files (the "Software"), to deal
104in the Software without restriction, including without limitation the rights
105to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
106copies of the Software, and to permit persons to whom the Software is
107furnished to do so, subject to the following conditions:
109The above copyright notice and this permission notice shall be included in all
110copies or substantial portions of the Software.
112THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
113IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
114FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
115AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
116LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
117OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1538#if !defined(__cplusplus) && ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(_MSC_VER) && (_MSC_VER >= 1900)))
1541#elif defined(__cplusplus)
1544# if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || (__cplusplus >= 201103L) || (_MSC_VER >= 1900)
1546# define FPL_IS_CPP11
1549# error "This C/C++ compiler is not supported!"
1556#if defined(__x86_64__) || defined(_M_X64) || defined(__amd64__)
1557# define FPL_ARCH_X64
1558#elif defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_)
1559# define FPL_ARCH_X86
1560#elif defined(__aarch64__) || defined(_M_ARM64)
1561# define FPL_ARCH_ARM64
1562#elif defined(__arm__) || defined(_M_ARM)
1563# define FPL_ARCH_ARM32
1564#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || defined(_ARCH_PPC64)
1565# define FPL_ARCH_POWERPC64
1566#elif defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
1567# define FPL_ARCH_POWERPC32
1569# error "This architecture is not supported!"
1577# define FPL__M_CPU_64BIT
1579# define FPL__M_CPU_32BIT
1581#elif defined(__GNUC__)
1582# if defined(__LP64__)
1583# define FPL__M_CPU_64BIT
1585# define FPL__M_CPU_32BIT
1588# if (defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8) || (sizeof(void *) == 8)
1589# define FPL__M_CPU_64BIT
1591# define FPL__M_CPU_32BIT
1595#if defined(FPL__M_CPU_64BIT)
1597# define FPL_CPU_64BIT
1598#elif defined(FPL__M_CPU_32BIT)
1600# define FPL_CPU_32BIT
1608#if defined(__clang__)
1610# define FPL_COMPILER_CLANG
1611#elif defined(__INTEL_COMPILER)
1613# define FPL_COMPILER_INTEL
1614#elif defined(__MINGW32__)
1616# define FPL_COMPILER_MINGW
1617#elif defined(__CC_ARM)
1619# define FPL_COMPILER_ARM
1620#elif defined(__GNUC__)
1622# define FPL_COMPILER_GCC
1623#elif defined(_MSC_VER)
1625# define FPL_COMPILER_MSVC
1628#error "This compiler is not supported!"
1635#if defined(_WIN32) || defined(_WIN64)
1636# define FPL_PLATFORM_WINDOWS
1637# define FPL_PLATFORM_NAME "Windows"
1638#elif defined(__ANDROID__)
1639# define FPL_PLATFORM_ANDROID
1640# define FPL_PLATFORM_NAME "Android"
1641# define FPL_SUBPLATFORM_POSIX
1642# define FPL_SUBPLATFORM_STD_STRINGS
1643# define FPL_SUBPLATFORM_STD_CONSOLE
1644#elif defined(__linux__) || defined(__gnu_linux__)
1645# define FPL_PLATFORM_LINUX
1646# define FPL_PLATFORM_NAME "Linux"
1647# define FPL_SUBPLATFORM_POSIX
1648# define FPL_SUBPLATFORM_X11
1649# define FPL_SUBPLATFORM_STD_STRINGS
1650# define FPL_SUBPLATFORM_STD_CONSOLE
1651#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__bsdi__)
1653# define FPL_PLATFORM_UNIX
1654# define FPL_PLATFORM_NAME "BSD"
1655# define FPL_SUBPLATFORM_BSD
1656# define FPL_SUBPLATFORM_POSIX
1657# define FPL_SUBPLATFORM_X11
1658# define FPL_SUBPLATFORM_STD_STRINGS
1659# define FPL_SUBPLATFORM_STD_CONSOLE
1660#elif defined(unix) || defined(__unix) || defined(__unix__)
1661# define FPL_PLATFORM_UNIX
1662# define FPL_PLATFORM_NAME "Unix"
1663# define FPL_SUBPLATFORM_POSIX
1664# define FPL_SUBPLATFORM_X11
1665# define FPL_SUBPLATFORM_STD_STRINGS
1666# define FPL_SUBPLATFORM_STD_CONSOLE
1668# error "This platform is not supported!"
1672#if defined(FPL_COMPILER_CLANG) || defined(FPL_COMPILER_GCC)
1673#define fpl__m_Asm __asm__
1674#elif defined(FPL_COMPILER_MSVC)
1675#define fpl__m_Asm __asm
1677#define fpl__m_Asm asm
1681#define fplAsm fpl__m_Asm
1684#if defined(FPL_COMPILER_MSVC)
1685# define fpl__MinAlignment 8
1686#elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
1687# if defined(FPL_CPU_64BIT)
1688# define fpl__MinAlignment 8
1690# define fpl__MinAlignment 4
1693# define fpl__MinAlignment 8
1696#define fplMinAlignment fpl__MinAlignment
1699#if defined(FPL_IS_CPP11)
1700#define fpl__m_AlignAs(N) alignas(N)
1701#elif defined(FPL_COMPILER_MSVC)
1702#define fpl__m_AlignAs(N) __declspec(align(N))
1703#elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
1704#define fpl__m_AlignAs(N) __attribute__((aligned(N)))
1706#define fpl__m_AlignAs(N)
1708#define fpl__m_AlignAsAuto(N) fpl__m_AlignAs(((N) < fplMinAlignment ? fplMinAlignment : (N)))
1711#define fplAlignAs(N) fpl__m_AlignAsAuto(N)
1716#if defined(FPL_SUBPLATFORM_POSIX)
1717# if !defined(_XOPEN_SOURCE)
1718# define _XOPEN_SOURCE 600
1720# if !defined(_DEFAULT_SOURCE)
1721# define _DEFAULT_SOURCE 1
1723# if !defined(__STDC_FORMAT_MACROS)
1724# define __STDC_FORMAT_MACROS
1726# if !defined(__STDC_LIMIT_MACROS)
1727# define __STDC_LIMIT_MACROS
1729# if !defined(_LARGEFILE_SOURCE)
1730# define _LARGEFILE_SOURCE
1732# if !defined(_LARGEFILE64_SOURCE)
1733# define _LARGEFILE64_SOURCE
1735# if !defined(_FILE_OFFSET_BITS)
1736# define _FILE_OFFSET_BITS 64
1740#if defined(FPL_PLATFORM_LINUX)
1741# define FPL__INCLUDE_ALLOCA
1743# define FPL__INCLUDE_MALLOC
1747#if defined(FPL_PLATFORM_WINDOWS) && defined(FPL_COMPILER_MINGW)
1748# if !defined(_WIN32_WINNT)
1749# define _WIN32_WINNT 0x0600
1764#define fpl_globalvar static
1766#define fpl_localvar static
1768#define fpl_internal static
1770#define fpl_inline inline
1772#define fpl_internal_inline inline
1774#if defined(FPL_IS_CPP)
1777# define fpl_extern extern
1783#if defined(_WIN32) || defined(__CYGWIN__)
1785# define fpl__m_dllexport __attribute__ ((dllexport))
1786# define fpl__m_dllimport __attribute__ ((dllimport))
1788# define fpl__m_dllexport __declspec(dllexport)
1789# define fpl__m_dllimport __declspec(dllimport)
1791# define fpl__m_dlllocal
1794# define fpl__m_dllimport __attribute__((visibility("default")))
1795# define fpl__m_dllexport __attribute__((visibility("default")))
1796# define fpl__m_dlllocal __attribute__((visibility("hidden")))
1798# define fpl__m_dllimport
1799# define fpl__m_dllexport
1800# define fpl__m_dlllocal
1805#define fpl_dllimport fpl__m_dllimport
1807#define fpl_dllexport fpl__m_dllexport
1809#define fpl_dlllocal fpl__m_dlllocal
1814#if defined(FPL_API_AS_PRIVATE)
1815# define fpl__m_api static
1816#elif defined(FPL_DLLEXPORT)
1817# define fpl__m_api fpl_dllexport
1818#elif defined(FPL_DLLIMPORT)
1819# define fpl__m_api fpl_dllimport
1821# define fpl__m_api fpl_extern
1825#define fpl_api fpl__m_api
1830#if defined(FPL_IS_CPP)
1831# define fpl__m_platform_api extern "C" fpl_api
1832# define fpl__m_common_api extern "C" fpl_api
1834# define fpl__m_platform_api fpl_api
1835# define fpl__m_common_api fpl_api
1839#define fpl_platform_api fpl__m_platform_api
1841#define fpl_common_api fpl__m_common_api
1846#if defined(FPL_COMPILER_MSVC)
1847# define fpl__m_force_inline __forceinline
1848# define fpl__m_no_inline __declspec(noinline)
1849#elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
1850# define fpl__m_force_inline __attribute__((__always_inline__)) inline
1851# define fpl__m_no_inline __attribute__((noinline))
1853# define fpl__m_force_inline inline
1854# define fpl__m_no_inline
1858#define fpl_force_inline fpl__m_force_inline
1860#define fpl_no_inline fpl__m_no_inline
1867#if defined(FPL_NO_CRT)
1868# if defined(FPL_SUBPLATFORM_STD_CONSOLE)
1869# undef FPL_SUBPLATFORM_STD_CONSOLE
1871# if defined(FPL_SUBPLATFORM_STD_STRINGS)
1872# undef FPL_SUBPLATFORM_STD_STRINGS
1874# if !defined(FPL_USERFUNC_vsnprintf)
1875# error "You need to provide a replacement for vsnprintf() by defining FPL_USERFUNC_vsnprintf!"
1884#if defined(FPL_APPTYPE_CONSOLE) && defined(FPL_APPTYPE_WINDOW)
1885# error "Its now allowed to define both FPL_APPTYPE_CONSOLE and FPL_APPTYPE_WINDOW!"
1887#if defined(FPL_NO_CRT)
1888# if !defined(FPL_APPTYPE_CONSOLE) && !defined(FPL_APPTYPE_WINDOW)
1889# error "In 'No-CRT' mode you need to define either FPL_APPTYPE_CONSOLE or FPL_APPTYPE_WINDOW manually!"
1891#elif !defined(FPL_NO_APPTYPE) && !(defined(FPL_APPTYPE_CONSOLE) || defined(FPL_APPTYPE_WINDOW))
1892# if !defined(FPL_NO_WINDOW)
1894# define FPL_APPTYPE_WINDOW
1897# define FPL_APPTYPE_CONSOLE
1904#if defined(FPL_IMPLEMENTATION) && !defined(FPL_NO_ENTRYPOINT)
1905# define FPL_ENTRYPOINT
1911#if defined(FPL_DEBUG)
1912# define FPL__ENABLE_DEBUG
1913#elif defined(FPL_RELEASE)
1914# define FPL__ENABLE_RELEASE
1920#if defined(FPL_COMPILER_MSVC)
1922# if !defined(FPL__ENABLE_DEBUG) && !defined(FPL__ENABLE_RELEASE)
1923# if defined(_DEBUG) || (!defined(NDEBUG))
1924# define FPL__ENABLE_DEBUG
1926# define FPL__ENABLE_RELEASE
1931# define FPL__M_FUNCTION_NAME __FUNCTION__
1934# if defined(FPL_APPTYPE_WINDOW)
1935# pragma comment(linker, "/SUBSYSTEM:WINDOWS")
1936# elif defined(FPL_APPTYPE_CONSOLE)
1937# pragma comment(linker, "/SUBSYSTEM:CONSOLE")
1941# pragma comment(lib, "kernel32.lib")
1944# define FPL__M_FUNCTION_NAME __FUNCTION__
1948#if !defined(FPL__ENABLE_DEBUG) && !defined(FPL__ENABLE_RELEASE)
1949# define FPL__ENABLE_DEBUG
1953#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
1954# define FPL_IS_IDE 1
1956# define FPL_IS_IDE 0
1960#define FPL_FUNCTION_NAME FPL__M_FUNCTION_NAME
1969#if defined(__AVX512F__)
1970# define FPL__COMPILED_X86_CPU_INSTR_SET 9
1971#elif defined(__AVX2__)
1972# define FPL__COMPILED_X86_CPU_INSTR_SET 8
1973#elif defined(__AVX__)
1974# define FPL__COMPILED_X86_CPU_INSTR_SET 7
1975#elif defined(__SSE4_2__)
1976# define FPL__COMPILED_X86_CPU_INSTR_SET 6
1977#elif defined(__SSE4_1__)
1978# define FPL__COMPILED_X86_CPU_INSTR_SET 5
1979#elif defined(__SSSE3__)
1980# define FPL__COMPILED_X86_CPU_INSTR_SET 4
1981#elif defined(__SSE3__)
1982# define FPL__COMPILED_X86_CPU_INSTR_SET 3
1983#elif defined(__SSE2__) || (_M_IX86_FP >= 2)
1984# define FPL__COMPILED_X86_CPU_INSTR_SET 2
1985#elif defined(__SSE__) || (_M_IX86_FP >= 1)
1986# define FPL__COMPILED_X86_CPU_INSTR_SET 1
1987#elif defined(_M_IX86_FP)
1988# define FPL__COMPILED_X86_CPU_INSTR_SET _M_IX86_FP
1990# define FPL__COMPILED_X86_CPU_INSTR_SET 0
1996#if !defined(FPL_NO_ASSERTIONS)
1997# if !defined(FPL_FORCE_ASSERTIONS)
1998# if defined(FPL__ENABLE_DEBUG)
1999# define FPL__ENABLE_ASSERTIONS
2002# define FPL__ENABLE_ASSERTIONS
2005#if defined(FPL__ENABLE_ASSERTIONS)
2006# if !defined(FPL_NO_C_ASSERT) && !defined(FPL_NO_CRT)
2007# define FPL__ENABLE_C_ASSERT
2014#if defined(__has_include)
2015# define fpl__m_HasInclude(inc) __has_include(inc)
2017# define fpl__m_HasInclude(inc) (1)
2020#define fplHasInclude(inc) fpl__m_HasInclude(inc)
2025#if !defined(FPL_NO_WINDOW) && !defined(FPL_APPTYPE_CONSOLE)
2026# define FPL__SUPPORT_WINDOW
2032#if !defined(FPL_NO_VIDEO)
2033# define FPL__SUPPORT_VIDEO
2035#if defined(FPL__SUPPORT_VIDEO)
2036# if !defined(FPL_NO_VIDEO_OPENGL)
2037# define FPL__SUPPORT_VIDEO_OPENGL
2039# if !defined(FPL_NO_VIDEO_VULKAN)
2040# define FPL__SUPPORT_VIDEO_VULKAN
2042# if !defined(FPL_NO_VIDEO_SOFTWARE)
2043# define FPL__SUPPORT_VIDEO_SOFTWARE
2050#if !defined(FPL_NO_AUDIO)
2052# define FPL__SUPPORT_AUDIO
2054#if defined(FPL__SUPPORT_AUDIO)
2055# if !defined(FPL_NO_AUDIO_DIRECTSOUND) && defined(FPL_PLATFORM_WINDOWS)
2056# define FPL__SUPPORT_AUDIO_DIRECTSOUND
2058# if !defined(FPL_NO_AUDIO_ALSA) && defined(FPL_PLATFORM_LINUX)
2059# if fplHasInclude(<alsa/asoundlib.h>)
2060# define FPL__SUPPORT_AUDIO_ALSA
2062# warning "FPL-Warning: ALSA audio development library is missing. Please install 'libasound2-dev' and try again!"
2070#if !defined(FPL__SUPPORT_WINDOW)
2071# if defined(FPL_SUBPLATFORM_X11)
2072# undef FPL_SUBPLATFORM_X11
2075# if defined(FPL__SUPPORT_VIDEO)
2076# undef FPL__SUPPORT_VIDEO
2078# if defined(FPL__SUPPORT_VIDEO_OPENGL)
2079# undef FPL__SUPPORT_VIDEO_OPENGL
2081# if defined(FPL__SUPPORT_VIDEO_VULKAN)
2082# undef FPL__SUPPORT_VIDEO_VULKAN
2084# if defined(FPL__SUPPORT_VIDEO_SOFTWARE)
2085# undef FPL__SUPPORT_VIDEO_SOFTWARE
2092#if defined(FPL__SUPPORT_WINDOW)
2093# define FPL__ENABLE_WINDOW
2096#if defined(FPL__SUPPORT_VIDEO)
2097# define FPL__ENABLE_VIDEO
2098# if defined(FPL__SUPPORT_VIDEO_OPENGL)
2099# define FPL__ENABLE_VIDEO_OPENGL
2101# if defined(FPL__SUPPORT_VIDEO_VULKAN)
2102# define FPL__ENABLE_VIDEO_VULKAN
2104# if defined(FPL__SUPPORT_VIDEO_SOFTWARE)
2105# define FPL__ENABLE_VIDEO_SOFTWARE
2109#if defined(FPL__SUPPORT_AUDIO)
2110# define FPL__ENABLE_AUDIO
2111# if defined(FPL__SUPPORT_AUDIO_DIRECTSOUND)
2112# define FPL__ENABLE_AUDIO_DIRECTSOUND
2114# if defined(FPL__SUPPORT_AUDIO_ALSA)
2115# define FPL__ENABLE_AUDIO_ALSA
2119#if defined(FPL_LOGGING)
2120# define FPL__ENABLE_LOGGING
2121# if defined(FPL_LOG_MULTIPLE_WRITERS)
2122# define FPL__ENABLE_LOG_MULTIPLE_WRITERS
2136#if defined(FPL__ENABLE_ASSERTIONS)
2137# if defined(FPL__ENABLE_C_ASSERT) && !defined(FPL_FORCE_ASSERTIONS)
2138# define FPL__INCLUDE_ASSERT
2139# define fpl__m_Assert(exp) assert(exp)
2140# if defined(__cplusplus)
2141# define fpl__m_StaticAssert(exp) static_assert(exp, "fpl_static_assert")
2144# define fpl__m_Assert(exp) if(!(exp)) {*(int *)0 = 0;}
2146# if !defined(fpl__m_StaticAssert)
2147# define FPL__M_STATICASSERT_0(exp, line, counter) \
2148 int fpl__ct_assert_##line_##counter(int ct_assert_failed[(exp)?1:-1])
2149# define fpl__m_StaticAssert(exp) \
2150 FPL__M_STATICASSERT_0(exp, __LINE__, __COUNTER__)
2153# define fpl__m_Assert(exp)
2154# define fpl__m_StaticAssert(exp)
2158#define fplAssert(exp) fpl__m_Assert(exp)
2160#define fplStaticAssert(exp) fpl__m_StaticAssert(exp)
2162#define fplAlwaysAssert(exp) if(!(exp)) {*(int *)0 = 0;}
2164#define fplAssertPtr(ptr) fpl__m_Assert((ptr) != fpl_null)
2170#if defined(__has_builtin)
2171# if __has_builtin(__builtin_debugtrap)
2172# define fpl__m_DebugBreak() __builtin_debugtrap()
2173# elif __has_builtin(__debugbreak)
2174# define fpl__m_DebugBreak() __debugbreak()
2177#if !defined(fpl__m_DebugBreak)
2178# if defined(FPL_COMPILER_MSVC) || defined(FPL_COMPILER_INTEL)
2179# define fpl__m_DebugBreak() __debugbreak()
2180# elif defined(FPL_COMPILER_ARM)
2181# define fpl__m_DebugBreak() __breakpoint(42)
2182# elif defined(FPL_ARCH_X86) || defined(FPL_ARCH_X64)
2184# elif defined(__thumb__)
2186# elif defined(FPL_ARCH_ARM64)
2188# elif defined(FPL_ARCH_ARM32)
2190# elif defined(FPL_COMPILER_GCC)
2191# define fpl__m_DebugBreak() __builtin_trap()
2193# define FPL__INCLUDE_SIGNAL
2194# if defined(SIGTRAP)
2195# define fpl__m_DebugBreak() raise(SIGTRAP)
2197# define fpl__m_DebugBreak() raise(SIGABRT)
2203#define fplDebugBreak() fpl__m_DebugBreak()
2217#if !defined(FPL_NO_MEMORY_MACROS) || defined(FPL_FORCE_MEMORY_MACROS)
2218# define FPL__ENABLE_MEMORY_MACROS
2231#if defined(FPL__INCLUDE_ASSERT)
2234#if defined(FPL__INCLUDE_SIGNAL)
2237#if defined(FPL__INCLUDE_MALLOC)
2240#if defined(FPL__INCLUDE_ALLOCA)
2245#if !defined(UINT32_MAX)
2247# define UINT32_MAX ((uint32_t)-1)
2251#if defined(FPL_IS_CPP11)
2252# define fpl__m_null nullptr
2254# define fpl__m_null NULL
2256# define fpl__m_null 0
2259#define fpl_null fpl__m_null
2268#if defined(FPL_CPU_64BIT)
2271#elif defined(FPL_CPU_32BIT)
2288#define FPL_NOT_IMPLEMENTED {*(int *)0 = 0xBAD;}
2290#if defined(FPL_IS_C99)
2291# define fpl__m_ZeroInit {0}
2292# define fpl__m_StructSet(ptr, type, value) *(ptr) = (type)value
2293# define fpl__m_StructInit(type, ...) (type){__VA_ARGS__}
2295# define fpl__m_ZeroInit {}
2296# define fpl__m_StructSet(ptr, type, value) *(ptr) = value
2297# define fpl__m_StructInit(type, ...) {__VA_ARGS__}
2301#define fplZeroInit fpl__m_ZeroInit
2303#define fplStructSet fpl__m_StructSet
2305#define fplStructInit fpl__m_StructInit
2308#define fplGetAlignmentOffset(value, alignment) ( (((alignment) > 1) && (((value) & ((alignment) - 1)) != 0)) ? ((alignment) - ((value) & (alignment - 1))) : 0)
2310#define fplGetAlignedSize(size, alignment) (((size) > 0 && (alignment) > 0) ? ((size) + fplGetAlignmentOffset(size, alignment)) : (size))
2312#define fplIsAligned(ptr, alignment) (((uintptr_t)(const void *)(ptr)) % (alignment) == 0)
2314#define fplIsPowerOfTwo(value) (((value) != 0) && (((value) & (~(value) + 1)) == (value)))
2316#define fplIsBigEndian() (*(uint16_t *)"\0\xff" < 0x100)
2318#define fplIsLittleEndian() (!fplIsBigEndian())
2320#define fplIsBitSet(value, bit) (((value) >> (bit)) & 0x1)
2323#define fplKiloBytes(value) (((value) * 1024ull))
2325#define fplMegaBytes(value) ((fplKiloBytes(value) * 1024ull))
2327#define fplGigaBytes(value) ((fplMegaBytes(value) * 1024ull))
2329#define fplTeraBytes(value) ((fplGigaBytes(value) * 1024ull))
2332#define fplClearStruct(ptr) fplMemoryClear((void *)(ptr), sizeof(*(ptr)))
2334#define fplCopyStruct(src, dst) fplMemoryCopy(src, sizeof(*(src)), dst);
2337#if defined(FPL_COMPILER_MSVC) && !defined(FPL_NO_CRT)
2338# define fpl__m_ArrayCount(arr) _countof(arr)
2339#elif defined(ARRAY_SIZE)
2340# define fpl__m_ArrayCount(arr) ARRAY_SIZE(arr)
2343# define FPL__NO_ARRAYCOUNT_VALIDATION
2344# define fpl__m_ArrayCount(arr) (sizeof(arr) / sizeof((arr)[0]))
2347#define fplArrayCount(arr) fpl__m_ArrayCount(arr)
2350#define fplOffsetOf(type, field) ((size_t)(&(((type*)(0))->field)))
2353#define fplMin(a, b) ((a) < (b) ? (a) : (b))
2356#define fplMax(a, b) ((a) > (b) ? (a) : (b))
2358#if defined(FPL_PLATFORM_WINDOWS)
2359# define fpl__m_StackAllocate(size) _alloca(size)
2361# define fpl__m_StackAllocate(size) alloca(size)
2365#define fplStackAllocate(size) fpl__m_StackAllocate(size)
2369#if defined(FPL_IS_CPP)
2370# define FPL__M_ENUM_AS_FLAGS_OPERATORS(etype) \
2371 inline etype operator | (etype a, etype b) { \
2372 return static_cast<etype>(static_cast<int>(a) | static_cast<int>(b)); \
2374 inline etype& operator |= (etype &a, etype b) { \
2377 inline etype operator & (etype a, etype b) { \
2378 return static_cast<etype>(static_cast<int>(a) & static_cast<int>(b)); \
2380 inline etype& operator &= (etype &a, etype b) { \
2383 inline etype operator ~ (etype a) { \
2384 return static_cast<etype>(~static_cast<int>(a)); \
2386 inline etype operator ^ (etype a, etype b) { \
2387 return static_cast<etype>(static_cast<int>(a) ^ static_cast<int>(b)); \
2389 inline etype& operator ^= (etype &a, etype b) { \
2393# define FPL__M_ENUM_AS_FLAGS_OPERATORS(etype)
2397#define FPL_ENUM_AS_FLAGS_OPERATORS(type) FPL__M_ENUM_AS_FLAGS_OPERATORS(type)
2404#if !defined(FPL_NO_PLATFORM_INCLUDES) && !defined(FPL__HAS_PLATFORM_INCLUDES)
2405# define FPL__HAS_PLATFORM_INCLUDES
2407# if defined(FPL_PLATFORM_WINDOWS)
2409# if !defined(NOMINMAX)
2413# if !defined(WIN32_LEAN_AND_MEAN)
2414# define WIN32_LEAN_AND_MEAN 1
2418# include <windows.h>
2419# if _WIN32_WINNT < 0x0600
2420# error "Windows Vista or higher required!"
2424# if defined(FPL_SUBPLATFORM_POSIX)
2425# include <pthread.h>
2427# include <semaphore.h>
2431# if defined(FPL_SUBPLATFORM_X11)
2433# include <X11/Xlib.h>
2434# include <X11/Xutil.h>
2435# include <X11/Xatom.h>
2443#if !defined(FPL__HAS_PLATFORM_INCLUDES) || defined(FPL_OPAQUE_HANDLES)
2445# if defined(FPL_PLATFORM_WINDOWS)
2448typedef uint64_t fpl__Win32Guid[4];
2450typedef void *fpl__Win32Handle;
2452typedef fpl__Win32Handle fpl__Win32InstanceHandle;
2454typedef fpl__Win32Handle fpl__Win32LibraryHandle;
2456typedef fpl__Win32Handle fpl__Win32FileHandle;
2458typedef fpl__Win32Handle fpl__Win32ThreadHandle;
2460typedef uint64_t fpl__Win32MutexHandle[16];
2462typedef fpl__Win32Handle fpl__Win32SignalHandle;
2464typedef void *fpl__Win32ConditionVariable;
2466typedef fpl__Win32Handle fpl__Win32SemaphoreHandle;
2468typedef fpl__Win32Handle fpl__Win32WindowHandle;
2470typedef fpl__Win32Handle fpl__Win32DeviceContext;
2472typedef fpl__Win32Handle fpl__Win32RenderingContext;
2474typedef union fpl__Win32LargeInteger {
2483} fpl__Win32LargeInteger;
2487# if defined(FPL_SUBPLATFORM_POSIX)
2490typedef void *fpl__POSIXLibraryHandle;
2492typedef int fpl__POSIXFileHandle;
2494typedef void *fpl__POSIXDirHandle;
2496typedef uint64_t fpl__POSIXThreadHandle;
2498typedef uint64_t fpl__POSIXMutexHandle[16];
2500typedef uint64_t fpl__POSIXSemaphoreHandle[8];
2502typedef uint64_t fpl__POSIXConditionVariable[16];
2506# if defined(FPL_SUBPLATFORM_X11)
2509typedef void *fpl__X11Display;
2511typedef int fpl__X11Window;
2513typedef void *fpl__X11Visual;
2515typedef void *fpl__X11GC;
2517typedef void *fpl__X11Image;
2519typedef void *fpl__GLXContext;
2523# if defined(FPL_PLATFORM_LINUX)
2526typedef int fpl__LinuxSignalHandle;
2532# if defined(FPL_PLATFORM_WINDOWS)
2535typedef GUID fpl__Win32Guid;
2537typedef HANDLE fpl__Win32Handle;
2539typedef HINSTANCE fpl__Win32InstanceHandle;
2541typedef HMODULE fpl__Win32LibraryHandle;
2543typedef HANDLE fpl__Win32ThreadHandle;
2545typedef HANDLE fpl__Win32FileHandle;
2547typedef CRITICAL_SECTION fpl__Win32MutexHandle;
2549typedef HANDLE fpl__Win32SignalHandle;
2551typedef CONDITION_VARIABLE fpl__Win32ConditionVariable;
2553typedef HANDLE fpl__Win32SemaphoreHandle;
2555typedef HWND fpl__Win32WindowHandle;
2557typedef HDC fpl__Win32DeviceContext;
2559typedef HGLRC fpl__Win32RenderingContext;
2561typedef LARGE_INTEGER fpl__Win32LargeInteger;
2565# if defined(FPL_SUBPLATFORM_POSIX)
2568typedef void *fpl__POSIXLibraryHandle;
2570typedef int fpl__POSIXFileHandle;
2572typedef DIR *fpl__POSIXDirHandle;
2574typedef pthread_t fpl__POSIXThreadHandle;
2576typedef pthread_mutex_t fpl__POSIXMutexHandle;
2578typedef sem_t fpl__POSIXSemaphoreHandle;
2580typedef pthread_cond_t fpl__POSIXConditionVariable;
2584# if defined(FPL_SUBPLATFORM_X11)
2587typedef Display *fpl__X11Display;
2589typedef Window fpl__X11Window;
2591typedef Visual *fpl__X11Visual;
2593typedef GC fpl__X11GC;
2595typedef XImage *fpl__X11Image;
2597typedef void *fpl__GLXContext;
2602# if defined(FPL_PLATFORM_LINUX)
2605typedef int fpl__LinuxSignalHandle;
2621#if defined(FPL_PLATFORM_WINDOWS)
2622# if defined(MAX_PATH)
2623# define FPL__M_MAX_FILENAME_LENGTH (MAX_PATH)
2624# define FPL__M_MAX_PATH_LENGTH (MAX_PATH * 2)
2626# define FPL__M_MAX_FILENAME_LENGTH (260)
2627# define FPL__M_MAX_PATH_LENGTH (260 * 2)
2629# define FPL__M_PATH_SEPARATOR '\\'
2630# define FPL__M_FILE_EXT_SEPARATOR '.'
2632# define FPL__M_MAX_FILENAME_LENGTH (512)
2633# define FPL__M_MAX_PATH_LENGTH (2048)
2634# define FPL__M_PATH_SEPARATOR '/'
2635# define FPL__M_FILE_EXT_SEPARATOR '.'
2639#define FPL_MAX_FILENAME_LENGTH FPL__M_MAX_FILENAME_LENGTH
2641#define FPL_MAX_PATH_LENGTH FPL__M_MAX_PATH_LENGTH
2643#define FPL_PATH_SEPARATOR FPL__M_PATH_SEPARATOR
2645#define FPL_FILE_EXT_SEPARATOR FPL__M_FILE_EXT_SEPARATOR
2647#define FPL_MAX_NAME_LENGTH (256)
2649#define FPL_MAX_BUFFER_LENGTH (2048)
3568#if defined(FPL__ENABLE_VIDEO_OPENGL)
3596#if defined(FPL__ENABLE_VIDEO_VULKAN)
3599typedef void (
fplVulkanValidationLayerCallback)(
void *userData,
const char *message,
const uint32_t messageSeverity,
const uint32_t messageType,
const void *debugUtilsMessengerCallbackData);
3658#if defined(FPL__ENABLE_VIDEO_OPENGL)
3662#if defined(FPL__ENABLE_VIDEO_VULKAN)
3800#if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
3802 fpl__Win32Guid dshow;
3804#if defined(FPL__ENABLE_AUDIO_ALSA)
3820#if defined(FPL__ENABLE_AUDIO_ALSA)
3822typedef struct fplAlsaAudioSettings {
3825} fplAlsaAudioSettings;
3830#if defined(FPL__ENABLE_AUDIO_ALSA)
3832 fplAlsaAudioSettings alsa;
4196#if defined(FPL__ENABLE_LOGGING)
4247#if defined(FPL__ENABLE_LOG_MULTIPLE_WRITERS)
4271 fplLogLevel maxLevel;
4357#if defined(FPL_PLATFORM_WINDOWS)
4359 fpl__Win32LibraryHandle win32LibraryHandle;
4360#elif defined(FPL_SUBPLATFORM_POSIX)
4362 fpl__POSIXLibraryHandle posixLibraryHandle;
4478#if defined(FPL_PLATFORM_WINDOWS)
4482 fpl__Win32LargeInteger qpc;
4486#elif defined(FPL_SUBPLATFORM_POSIX)
4492 int64_t nanoSeconds;
4502#define FPL_TIMEOUT_INFINITE UINT32_MAX
4591#if defined(FPL_PLATFORM_WINDOWS)
4593 fpl__Win32ThreadHandle win32ThreadHandle;
4594#elif defined(FPL_SUBPLATFORM_POSIX)
4596 fpl__POSIXThreadHandle posixThread;
4628#if defined(FPL_PLATFORM_WINDOWS)
4629typedef struct fpl__Win32InternalSemaphore {
4631 fpl__Win32SemaphoreHandle handle;
4633 volatile int32_t value;
4634} fpl__Win32InternalSemaphore;
4639#if defined(FPL_PLATFORM_WINDOWS)
4641 fpl__Win32InternalSemaphore win32;
4642#elif defined(FPL_SUBPLATFORM_POSIX)
4644 fpl__POSIXSemaphoreHandle posixHandle;
4658#if defined(FPL_PLATFORM_WINDOWS)
4660 fpl__Win32MutexHandle win32CriticalSection;
4661#elif defined(FPL_SUBPLATFORM_POSIX)
4663 fpl__POSIXMutexHandle posixMutex;
4677#if defined(FPL_PLATFORM_WINDOWS)
4679 fpl__Win32SignalHandle win32EventHandle;
4680#elif defined(FPL_PLATFORM_LINUX)
4682 fpl__LinuxSignalHandle linuxEventHandle;
4704#if defined(FPL_PLATFORM_WINDOWS)
4706 fpl__Win32ConditionVariable win32Condition;
4707#elif defined(FPL_SUBPLATFORM_POSIX)
4709 fpl__POSIXConditionVariable posixCondition;
5178#if defined(FPL_PLATFORM_WINDOWS)
5180 fpl__Win32FileHandle win32FileHandle;
5181#elif defined(FPL_SUBPLATFORM_POSIX)
5183 fpl__POSIXFileHandle posixFileHandle;
5277#if defined(FPL_PLATFORM_WINDOWS)
5279 fpl__Win32FileHandle win32FileHandle;
5280#elif defined(FPL_SUBPLATFORM_POSIX)
5282 fpl__POSIXDirHandle posixDirHandle;
5679#if defined(FPL__ENABLE_WINDOW)
5694 fplKey_Backspace = 0x08,
5699 fplKey_Clear = 0x0C,
5700 fplKey_Return = 0x0D,
5704 fplKey_Shift = 0x10,
5705 fplKey_Control = 0x11,
5707 fplKey_Pause = 0x13,
5708 fplKey_CapsLock = 0x14,
5715 fplKey_Escape = 0x1B,
5719 fplKey_Space = 0x20,
5720 fplKey_PageUp = 0x21,
5721 fplKey_PageDown = 0x22,
5726 fplKey_Right = 0x27,
5728 fplKey_Select = 0x29,
5729 fplKey_Print = 0x2A,
5730 fplKey_Execute = 0x2B,
5731 fplKey_Snapshot = 0x2C,
5732 fplKey_Insert = 0x2D,
5733 fplKey_Delete = 0x2E,
5776 fplKey_LeftSuper = 0x5B,
5777 fplKey_RightSuper = 0x5C,
5782 fplKey_Sleep = 0x5F,
5783 fplKey_NumPad0 = 0x60,
5784 fplKey_NumPad1 = 0x61,
5785 fplKey_NumPad2 = 0x62,
5786 fplKey_NumPad3 = 0x63,
5787 fplKey_NumPad4 = 0x64,
5788 fplKey_NumPad5 = 0x65,
5789 fplKey_NumPad6 = 0x66,
5790 fplKey_NumPad7 = 0x67,
5791 fplKey_NumPad8 = 0x68,
5792 fplKey_NumPad9 = 0x69,
5793 fplKey_Multiply = 0x6A,
5795 fplKey_Separator = 0x6C,
5796 fplKey_Substract = 0x6D,
5797 fplKey_Decimal = 0x6E,
5798 fplKey_Divide = 0x6F,
5826 fplKey_NumLock = 0x90,
5827 fplKey_Scroll = 0x91,
5832 fplKey_LeftShift = 0xA0,
5833 fplKey_RightShift = 0xA1,
5834 fplKey_LeftControl = 0xA2,
5835 fplKey_RightControl = 0xA3,
5836 fplKey_LeftAlt = 0xA4,
5837 fplKey_RightAlt = 0xA5,
5841 fplKey_VolumeMute = 0xAD,
5842 fplKey_VolumeDown = 0xAE,
5843 fplKey_VolumeUp = 0xAF,
5844 fplKey_MediaNextTrack = 0xB0,
5845 fplKey_MediaPrevTrack = 0xB1,
5846 fplKey_MediaStop = 0xB2,
5847 fplKey_MediaPlayPause = 0xB3,
6228#define FPL_MAX_KEYBOARD_STATE_COUNT 256
6241#define FPL_MAX_GAMEPAD_STATE_COUNT 4
6564#if defined(FPL__ENABLE_VIDEO)
6594 fplVideoRect result = { left, top, (right - left) + 1, (bottom - top) + 1 };
6616#if defined(FPL__ENABLE_VIDEO_VULKAN)
6626#if defined(FPL__ENABLE_VIDEO_OPENGL)
6634#if defined(FPL_PLATFORM_WINDOWS)
6636typedef struct fplVideoWindowWin32 {
6638 fpl__Win32WindowHandle windowHandle;
6640 fpl__Win32DeviceContext deviceContext;
6641} fplVideoWindowWin32;
6644#if defined(FPL_SUBPLATFORM_X11)
6646typedef struct fplVideoWindowX11 {
6648 fpl__X11Window window;
6650 fpl__X11Display display;
6652 fpl__X11Visual visual;
6660#if defined(FPL_PLATFORM_WINDOWS)
6661 fplVideoWindowWin32 win32;
6662#elif defined(FPL_SUBPLATFORM_X11)
6663 fplVideoWindowX11 x11;
6674#if defined(FPL__ENABLE_VIDEO_VULKAN)
6679#if defined(FPL__ENABLE_VIDEO_OPENGL)
6688#if defined(FPL__ENABLE_VIDEO_VULKAN)
6701#if defined(FPL__ENABLE_VIDEO_VULKAN)
6763#if defined(FPL__ENABLE_AUDIO)
6960#if defined(FPL_PLATFORM_WINDOWS)
6961# if defined(FPL_ENTRYPOINT)
6963fpl_main int main(
int argc,
char **args);
7034#if (defined(FPL_IMPLEMENTATION) || FPL_IS_IDE) && !defined(FPL__IMPLEMENTED)
7035#define FPL__IMPLEMENTED
7042#if !defined(FPL__COMPILER_CONFIG_DEFINED)
7043#define FPL__COMPILER_CONFIG_DEFINED
7048#if defined(FPL_COMPILER_MSVC)
7051# pragma warning( push )
7054# pragma warning( disable : 4577 )
7056# pragma warning( disable : 4065 )
7058# pragma warning( disable : 4127 )
7060# pragma warning( disable : 4100 )
7062# pragma warning( disable : 4201 )
7064# pragma warning( disable : 4189 )
7066# pragma warning( disable : 4204 )
7068#elif defined(FPL_COMPILER_GCC)
7071# pragma GCC diagnostic push
7073# pragma GCC diagnostic ignored "-Wunused-variable"
7075# pragma GCC diagnostic ignored "-Wunused-function"
7077#elif defined(FPL_COMPILER_CLANG)
7080# pragma clang diagnostic push
7083# pragma clang diagnostic ignored "-Wunused-variable"
7085# pragma clang diagnostic ignored "-Wunused-function"
7096#if !defined(FPL__PLATFORM_INCLUDES_DEFINED)
7097#define FPL__PLATFORM_INCLUDES_DEFINED
7099#if !defined(FPL__HAS_PLATFORM_INCLUDES)
7100# define FPL__HAS_PLATFORM_INCLUDES
7102# if defined(FPL_PLATFORM_WINDOWS)
7104# if !defined(NOMINMAX)
7108# if !defined(WIN32_LEAN_AND_MEAN)
7109# define WIN32_LEAN_AND_MEAN 1
7113# include <windows.h>
7114# if _WIN32_WINNT < 0x0600
7115# error "Windows Vista or higher required!"
7119# if defined(FPL_SUBPLATFORM_POSIX)
7120# include <pthread.h>
7122# include <semaphore.h>
7126# if defined(FPL_SUBPLATFORM_X11)
7128# include <X11/Xlib.h>
7129# include <X11/Xutil.h>
7130# include <X11/Xatom.h>
7138#if defined(FPL_PLATFORM_WINDOWS)
7143fplStaticAssert(
sizeof(fpl__Win32MutexHandle) >=
sizeof(CRITICAL_SECTION));
7145fplStaticAssert(
sizeof(fpl__Win32ConditionVariable) >=
sizeof(CONDITION_VARIABLE));
7146#elif defined(FPL_SUBPLATFORM_POSIX)
7151fplStaticAssert(
sizeof(fpl__POSIXMutexHandle) >=
sizeof(pthread_mutex_t));
7153fplStaticAssert(
sizeof(fpl__POSIXConditionVariable) >=
sizeof(pthread_cond_t));
7155#if defined(FPL_PLATFORM_LINUX)
7162#if defined(FPL_COMPILER_MSVC)
7164#elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
7165# if defined(FPL_ARCH_X86) || defined(FPL_ARCH_X64)
7171#if !defined(FPL_NO_CRT)
7184#if !defined(FPL__INTERNAL_TOP_DEFINED)
7185#define FPL__INTERNAL_TOP_DEFINED
7188#define FPL__MODULE_CORE "Core"
7189#define FPL__MODULE_FILES "Files"
7190#define FPL__MODULE_THREADING "Threading"
7191#define FPL__MODULE_MEMORY "Memory"
7192#define FPL__MODULE_WINDOW "Window"
7193#define FPL__MODULE_LIBRARIES "Libraries"
7194#define FPL__MODULE_OS "OS"
7195#define FPL__MODULE_HARDWARE "Hardware"
7196#define FPL__MODULE_STRINGS "Strings"
7197#define FPL__MODULE_PATHS "Paths"
7198#define FPL__MODULE_ARGS "Arguments"
7200#define FPL__MODULE_AUDIO "Audio"
7201#define FPL__MODULE_AUDIO_DIRECTSOUND "DirectSound"
7202#define FPL__MODULE_AUDIO_ALSA "ALSA"
7204#define FPL__MODULE_VIDEO "Video"
7205#define FPL__MODULE_VIDEO_OPENGL "OpenGL"
7206#define FPL__MODULE_VIDEO_VULKAN "Vulkan"
7207#define FPL__MODULE_VIDEO_SOFTWARE "Software"
7209#define FPL__MODULE_WIN32 "Win32"
7210#define FPL__MODULE_XINPUT "XInput"
7212#define FPL__MODULE_LINUX "Linux"
7213#define FPL__MODULE_UNIX "Unix"
7214#define FPL__MODULE_POSIX "POSIX"
7215#define FPL__MODULE_PTHREAD "pthread"
7216#define FPL__MODULE_X11 "X11"
7217#define FPL__MODULE_GLX "GLX"
7222#define FPL__ENUM_COUNT(first, last) ((last) - (first) + 1)
7223#define FPL__ENUM_VALUE_TO_ARRAY_INDEX(value, first, last) (((value) >= (first) && (value) <= (last)) ? ((value) - (first)) : 0)
7238#if !defined(FPL__INTERNAL_LOGGING_DEFINED)
7239#define FPL__INTERNAL_LOGGING_DEFINED
7241#define FPL__MODULE_CONCAT(mod, format) "[" mod "] " format
7243#if defined(FPL__ENABLE_LOGGING)
7246#define FPL__LOGLEVEL_COUNT FPL__ENUM_COUNT(fplLogLevel_First, fplLogLevel_Last)
7261 const char *result = fpl__LogLevelNameTable[index];
7265fpl_internal void fpl__LogWrite(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *message) {
7268#if defined(FPL_LOG_MULTIPLE_WRITERS)
7269 settings->criticalWriter.console.logToError =
true;
7271 settings->errorWriter = settings->criticalWriter;
7272 settings->warningWriter = settings->criticalWriter;
7274 settings->verboseWriter = settings->infoWriter;
7283 if ((settings->
maxLevel == -1) || (level <= settings->maxLevel)) {
7284#if defined(FPL_LOG_MULTIPLE_WRITERS)
7290 const char *levelStr = fpl__LogLevelToString(level);
7306fpl_internal void fpl__LogWriteArgs(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, va_list argList) {
7308 va_copy(listCopy, argList);
7311 if (formattedLen > 0) {
7312 fpl__LogWrite(funcName, lineNumber, level, buffer);
7317fpl_internal void fpl__LogWriteVarArgs(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, ...) {
7319 va_start(argList, format);
7320 fpl__LogWriteArgs(funcName, lineNumber, level, format, argList);
7324# define FPL_LOG(lvl, mod, format, ...) fpl__LogWriteVarArgs(FPL_FUNCTION_NAME, __LINE__, lvl, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
7325# define FPL_LOG_CRITICAL(mod, format, ...) FPL_LOG(fplLogLevel_Critical, mod, format, ## __VA_ARGS__)
7326# define FPL_LOG_ERROR(mod, format, ...) FPL_LOG(fplLogLevel_Error, mod, format, ## __VA_ARGS__)
7327# define FPL_LOG_WARN(mod, format, ...) FPL_LOG(fplLogLevel_Warning, mod, format, ## __VA_ARGS__)
7328# define FPL_LOG_INFO(mod, format, ...) FPL_LOG(fplLogLevel_Info, mod, format, ## __VA_ARGS__)
7329# define FPL_LOG_VERBOSE(mod, format, ...) FPL_LOG(fplLogLevel_Verbose, mod, format, ## __VA_ARGS__)
7330# define FPL_LOG_DEBUG(mod, format, ...) FPL_LOG(fplLogLevel_Debug, mod, format, ## __VA_ARGS__)
7331# define FPL_LOG_TRACE(mod, format, ...) FPL_LOG(fplLogLevel_Trace, mod, format, ## __VA_ARGS__)
7333# define FPL__LOG_FUNCTION_N(mod, name) FPL_LOG(fplLogLevel_Debug, mod, "-> %s()", name)
7334# define FPL_LOG_FUNCTION(mod) FPL__LOG_FUNCTION_N(mod, FPL_FUNCTION_NAME)
7338# define FPL_LOG(lvl, mod, format, ...)
7339# define FPL_LOG_CRITICAL(mod, format, ...)
7340# define FPL_LOG_ERROR(mod, format, ...)
7341# define FPL_LOG_WARN(mod, format, ...)
7342# define FPL_LOG_INFO(mod, format, ...)
7343# define FPL_LOG_VERBOSE(mod, format, ...)
7344# define FPL_LOG_DEBUG(mod, format, ...)
7345# define FPL_LOG_FUNCTION(mod)
7353#define FPL__M_CRITICAL(funcName, line, mod, format, ...) fpl__HandleError(funcName, line, fplLogLevel_Critical, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
7354#define FPL__M_ERROR(funcName, line, mod, format, ...) fpl__HandleError(funcName, line, fplLogLevel_Error, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
7355#define FPL__M_WARNING(funcName, line, mod, format, ...) fpl__HandleError(funcName, line, fplLogLevel_Warning, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
7357#define FPL__CRITICAL(mod, format, ...) FPL__M_CRITICAL(FPL_FUNCTION_NAME, __LINE__, mod, format, ## __VA_ARGS__)
7358#define FPL__ERROR(mod, format, ...) FPL__M_ERROR(FPL_FUNCTION_NAME, __LINE__, mod, format, ## __VA_ARGS__)
7359#define FPL__WARNING(mod, format, ...) FPL__M_WARNING(FPL_FUNCTION_NAME, __LINE__, mod, format, ## __VA_ARGS__)
7368#if !defined(FPL__PLATFORM_CONSTANTS_DEFINED)
7369#define FPL__PLATFORM_CONSTANTS_DEFINED
7372#define FPL__ARBITARY_PADDING 64
7374#define FPL__MEMORY_PADDING sizeof(uintptr_t)
7378fpl_internal void fpl__HandleError(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, ...);
7406fpl_internal void *fpl__AllocateDynamicMemory(
const size_t size,
const size_t alignment);
7408fpl_internal void *fpl__AllocateTemporaryMemory(
const size_t size,
const size_t alignment);
7409fpl_internal void fpl__ReleaseTemporaryMemory(
void *ptr);
7411fpl_internal uint32_t fpl__NextPowerOfTwo(
const uint32_t input) {
7422fpl_internal uint32_t fpl__PrevPowerOfTwo(
const uint32_t input) {
7423 uint32_t result = fpl__NextPowerOfTwo(input) >> 1;
7427fpl_internal uint32_t fpl__RoundToPowerOfTwo(
const uint32_t input) {
7428 uint32_t prev = fpl__PrevPowerOfTwo(input);
7429 uint32_t next = fpl__NextPowerOfTwo(input);
7430 if ((next - input) < (input - prev)) {
7437fpl_internal bool fpl__AddLineWhenAnyMatches(
const char *line,
const char **wildcards,
const size_t maxWildcardCount,
const size_t maxLineSize,
const size_t maxLineCount,
char **outLines,
size_t *outCount) {
7438 for (
size_t i = 0; i < maxWildcardCount; ++i) {
7439 const char *wildcard = wildcards[i];
7441 size_t index = *outCount;
7442 char *target = outLines[index];
7444 *outCount = index + 1;
7448 bool result = *outCount < maxLineCount;
7452fpl_internal size_t fpl__ParseTextFile(
const char *filePath,
const char **wildcards,
const size_t maxWildcardCount,
const size_t maxLineSize,
const size_t maxLineCount,
char **outLines) {
7453 if (filePath ==
fpl_null || wildcards ==
fpl_null || maxWildcardCount == 0 || maxLineSize == 0 || maxLineCount == 0 || outLines ==
fpl_null) {
7462 char *line = (
char *)fpl__AllocateTemporaryMemory(maxLineSize, 8);
7465 size_t bytesRead = 0;
7466 size_t posLineBytes = 0;
7468 while (!done && ((bytesRead =
fplFileReadBlock(&fileHandle, maxBufferSize, &buffer[0], maxBufferSize)) > 0)) {
7469 buffer[bytesRead] = 0;
7470 char *start = &buffer[0];
7473 size_t lineSizeToRead = 0;
7474 while (readPos < bytesRead) {
7476 size_t remainingLineBytes = maxLineSize - posLineBytes;
7477 char *lineTargetP = line + posLineBytes;
7478 if (lineSizeToRead < remainingLineBytes) {
7481 fplCopyStringLen(start, remainingLineBytes - 1, lineTargetP, remainingLineBytes);
7483 if (!fpl__AddLineWhenAnyMatches(line, wildcards, maxWildcardCount, maxLineSize, maxLineCount, outLines, &result)) {
7500 if (lineSizeToRead > 0) {
7501 size_t remainingLineBytes = maxLineSize - posLineBytes;
7502 char *lineTargetP = line + posLineBytes;
7503 if (lineSizeToRead < remainingLineBytes) {
7505 posLineBytes += lineSizeToRead;
7506 if (bytesRead <= maxBufferSize) {
7507 if (!fpl__AddLineWhenAnyMatches(line, wildcards, maxWildcardCount, maxLineSize, maxLineCount, outLines, &result)) {
7512 fplCopyStringLen(start, remainingLineBytes - 1, lineTargetP, remainingLineBytes);
7516 if (!fpl__AddLineWhenAnyMatches(line, wildcards, maxWildcardCount, maxLineSize, maxLineCount, outLines, &result)) {
7522 fpl__ReleaseTemporaryMemory(line);
7531 const char *p = versionStr;
7532 for (
int i = 0; i < 4; ++i) {
7533 const char *digitStart = p;
7534 while (*p >=
'0' && *p <=
'9') {
7537 size_t len = p - digitStart;
7541 versionInfo->
values[i][0] = 0;
7543 if (*p !=
'.' && *p !=
'-')
break;
7563#if defined(FPL_PLATFORM_WINDOWS)
7564# include <windowsx.h>
7567# include <shellapi.h>
7569# if defined(FPL_IS_CPP)
7570# define fpl__Win32IsEqualGuid(a, b) InlineIsEqualGUID(a, b)
7572# define fpl__Win32IsEqualGuid(a, b) InlineIsEqualGUID(&a, &b)
7575fpl_internal const char *fpl__Win32FormatGuidString(
char *buffer,
const size_t maxBufferLen,
const GUID *guid) {
7576 fplStringFormat(buffer, maxBufferLen,
"{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
7577 guid->Data1, guid->Data2, guid->Data3,
7578 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
7579 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
7584#define FPL__WIN32_LOAD_LIBRARY_BREAK(mod, target, libName) \
7585 (target) = LoadLibraryA(libName); \
7586 if((target) == fpl_null) { \
7587 FPL__WARNING(mod, "Failed loading library '%s'", (libName)); \
7590#define FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK(mod, libHandle, libName, target, type, name) \
7591 (target)->name = (type *)GetProcAddress(libHandle, #name); \
7592 if ((target)->name == fpl_null) { \
7593 FPL__WARNING(mod, "Failed getting procedure address '%s' from library '%s'", #name, libName); \
7596#if !defined(FPL_NO_RUNTIME_LINKING)
7597# define FPL__WIN32_LOAD_LIBRARY FPL__WIN32_LOAD_LIBRARY_BREAK
7598# define FPL__WIN32_GET_FUNCTION_ADDRESS FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK
7600# define FPL__WIN32_LOAD_LIBRARY(mod, target, libName)
7601# define FPL__WIN32_GET_FUNCTION_ADDRESS(mod, libHandle, libName, target, type, name) \
7602 (target)->name = name
7608#define FPL__FUNC_XINPUT_XInputGetState(name) DWORD WINAPI name(DWORD dwUserIndex, XINPUT_STATE *pState)
7609typedef FPL__FUNC_XINPUT_XInputGetState(fpl__win32_func_XInputGetState);
7610FPL__FUNC_XINPUT_XInputGetState(fpl__Win32XInputGetStateStub) {
7611 return(ERROR_DEVICE_NOT_CONNECTED);
7613#define FPL__FUNC_XINPUT_XInputGetCapabilities(name) DWORD WINAPI name(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
7614typedef FPL__FUNC_XINPUT_XInputGetCapabilities(fpl__win32_func_XInputGetCapabilities);
7615FPL__FUNC_XINPUT_XInputGetCapabilities(fpl__Win32XInputGetCapabilitiesStub) {
7616 return(ERROR_DEVICE_NOT_CONNECTED);
7618typedef struct fpl__Win32XInputApi {
7619 HMODULE xinputLibrary;
7620 fpl__win32_func_XInputGetState *XInputGetState;
7621 fpl__win32_func_XInputGetCapabilities *XInputGetCapabilities;
7622} fpl__Win32XInputApi;
7624fpl_internal void fpl__Win32UnloadXInputApi(fpl__Win32XInputApi *xinputApi) {
7626 if (xinputApi->xinputLibrary) {
7627 FPL_LOG_DEBUG(
"XInput",
"Unload XInput Library");
7628 FreeLibrary(xinputApi->xinputLibrary);
7629 xinputApi->xinputLibrary =
fpl_null;
7630 xinputApi->XInputGetState = fpl__Win32XInputGetStateStub;
7631 xinputApi->XInputGetCapabilities = fpl__Win32XInputGetCapabilitiesStub;
7635fpl_internal void fpl__Win32LoadXInputApi(fpl__Win32XInputApi *xinputApi) {
7637 const char *xinputFileNames[] = {
7642 bool result =
false;
7643 for (uint32_t index = 0; index <
fplArrayCount(xinputFileNames); ++index) {
7644 const char *libName = xinputFileNames[index];
7648 FPL__WIN32_LOAD_LIBRARY_BREAK(FPL__MODULE_XINPUT, libHandle, libName);
7649 xinputApi->xinputLibrary = libHandle;
7650 FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK(FPL__MODULE_XINPUT, libHandle, libName, xinputApi, fpl__win32_func_XInputGetState, XInputGetState);
7651 FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK(FPL__MODULE_XINPUT, libHandle, libName, xinputApi, fpl__win32_func_XInputGetCapabilities, XInputGetCapabilities);
7657 fpl__Win32UnloadXInputApi(xinputApi);
7661 xinputApi->XInputGetState = fpl__Win32XInputGetStateStub;
7662 xinputApi->XInputGetCapabilities = fpl__Win32XInputGetCapabilitiesStub;
7671#define FPL__FUNC_WIN32_ChoosePixelFormat(name) int WINAPI name(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd)
7672typedef FPL__FUNC_WIN32_ChoosePixelFormat(fpl__win32_func_ChoosePixelFormat);
7673#define FPL__FUNC_WIN32_SetPixelFormat(name) BOOL WINAPI name(HDC hdc, int format, CONST PIXELFORMATDESCRIPTOR *ppfd)
7674typedef FPL__FUNC_WIN32_SetPixelFormat(fpl__win32_func_SetPixelFormat);
7675#define FPL__FUNC_WIN32_DescribePixelFormat(name) int WINAPI name(HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd)
7676typedef FPL__FUNC_WIN32_DescribePixelFormat(fpl__win32_func_DescribePixelFormat);
7677#define FPL__FUNC_WIN32_GetDeviceCaps(name) int WINAPI name(HDC hdc, int index)
7678typedef FPL__FUNC_WIN32_GetDeviceCaps(fpl__win32_func_GetDeviceCaps);
7679#define FPL__FUNC_WIN32_StretchDIBits(name) int WINAPI name(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc, int SrcWidth, int SrcHeight, CONST VOID *lpBits, CONST BITMAPINFO *lpbmi, UINT iUsage, DWORD rop)
7680typedef FPL__FUNC_WIN32_StretchDIBits(fpl__win32_func_StretchDIBits);
7681#define FPL__FUNC_WIN32_DeleteObject(name) BOOL WINAPI name( _In_ HGDIOBJ ho)
7682typedef FPL__FUNC_WIN32_DeleteObject(fpl__win32_func_DeleteObject);
7683#define FPL__FUNC_WIN32_SwapBuffers(name) BOOL WINAPI name(HDC)
7684typedef FPL__FUNC_WIN32_SwapBuffers(fpl__win32_func_SwapBuffers);
7685#define FPL__FUNC_WIN32_CreateDIBSection(name) HBITMAP WINAPI name(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset)
7686typedef FPL__FUNC_WIN32_CreateDIBSection(fpl__win32_func_CreateDIBSection);
7687#define FPL__FUNC_WIN32_CreateBitmap(name) HBITMAP WINAPI name(int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID *lpBits)
7688typedef FPL__FUNC_WIN32_CreateBitmap(fpl__win32_func_CreateBitmap);
7689#define FPL__FUNC_WIN32_CreateSolidBrush(name) HBRUSH WINAPI name(COLORREF color)
7690typedef FPL__FUNC_WIN32_CreateSolidBrush(fpl__win32_func_CreateSolidBrush);
7693#define FPL__FUNC_WIN32_SHGetFolderPathW(name) HRESULT WINAPI name(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath)
7694typedef FPL__FUNC_WIN32_SHGetFolderPathW(fpl__win32_func_SHGetFolderPathW);
7695#define FPL__FUNC_WIN32_DragQueryFileW(name) UINT WINAPI name(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch)
7696typedef FPL__FUNC_WIN32_DragQueryFileW(fpl__win32_func_DragQueryFileW);
7697#define FPL__FUNC_WIN32_DragAcceptFiles(name) void WINAPI name(HWND hWnd, BOOL fAccept)
7698typedef FPL__FUNC_WIN32_DragAcceptFiles(fpl__win32_func_DragAcceptFiles);
7701#define FPL__FUNC_WIN32_RegisterClassExW(name) ATOM WINAPI name(CONST WNDCLASSEXW *)
7702typedef FPL__FUNC_WIN32_RegisterClassExW(fpl__win32_func_RegisterClassExW);
7703#define FPL__FUNC_WIN32_UnregisterClassW(name) BOOL WINAPI name(LPCWSTR lpClassName, HINSTANCE hInstance)
7704typedef FPL__FUNC_WIN32_UnregisterClassW(fpl__win32_func_UnregisterClassW);
7705#define FPL__FUNC_WIN32_ShowWindow(name) BOOL WINAPI name(HWND hWnd, int nCmdShow)
7706typedef FPL__FUNC_WIN32_ShowWindow(fpl__win32_func_ShowWindow);
7707#define FPL__FUNC_WIN32_DestroyWindow(name) BOOL WINAPI name(HWND hWnd)
7708typedef FPL__FUNC_WIN32_DestroyWindow(fpl__win32_func_DestroyWindow);
7709#define FPL__FUNC_WIN32_UpdateWindow(name) BOOL WINAPI name(HWND hWnd)
7710typedef FPL__FUNC_WIN32_UpdateWindow(fpl__win32_func_UpdateWindow);
7711#define FPL__FUNC_WIN32_TranslateMessage(name) BOOL WINAPI name(CONST MSG *lpMsg)
7712typedef FPL__FUNC_WIN32_TranslateMessage(fpl__win32_func_TranslateMessage);
7713#define FPL__FUNC_WIN32_DispatchMessageW(name) LRESULT WINAPI name(CONST MSG *lpMsg)
7714typedef FPL__FUNC_WIN32_DispatchMessageW(fpl__win32_func_DispatchMessageW);
7715#define FPL__FUNC_WIN32_PeekMessageW(name) BOOL WINAPI name(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg)
7716typedef FPL__FUNC_WIN32_PeekMessageW(fpl__win32_func_PeekMessageW);
7717#define FPL__FUNC_WIN32_DefWindowProcW(name) LRESULT WINAPI name(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
7718typedef FPL__FUNC_WIN32_DefWindowProcW(fpl__win32_func_DefWindowProcW);
7719#define FPL__FUNC_WIN32_CreateWindowExW(name) HWND WINAPI name(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
7720typedef FPL__FUNC_WIN32_CreateWindowExW(fpl__win32_func_CreateWindowExW);
7721#define FPL__FUNC_WIN32_SetWindowPos(name) BOOL WINAPI name(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
7722typedef FPL__FUNC_WIN32_SetWindowPos(fpl__win32_func_SetWindowPos);
7723#define FPL__FUNC_WIN32_GetWindowPlacement(name) BOOL WINAPI name(HWND hWnd, WINDOWPLACEMENT *lpwndpl)
7724typedef FPL__FUNC_WIN32_GetWindowPlacement(fpl__win32_func_GetWindowPlacement);
7725#define FPL__FUNC_WIN32_SetWindowPlacement(name) BOOL WINAPI name(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl)
7726typedef FPL__FUNC_WIN32_SetWindowPlacement(fpl__win32_func_SetWindowPlacement);
7727#define FPL__FUNC_WIN32_GetClientRect(name) BOOL WINAPI name(HWND hWnd, LPRECT lpRect)
7728typedef FPL__FUNC_WIN32_GetClientRect(fpl__win32_func_GetClientRect);
7729#define FPL__FUNC_WIN32_GetWindowRect(name) BOOL WINAPI name(HWND hWnd, LPRECT lpRect)
7730typedef FPL__FUNC_WIN32_GetWindowRect(fpl__win32_func_GetWindowRect);
7731#define FPL__FUNC_WIN32_AdjustWindowRect(name) BOOL WINAPI name(LPRECT lpRect, DWORD dwStyle, BOOL bMenu)
7732typedef FPL__FUNC_WIN32_AdjustWindowRect(fpl__win32_func_AdjustWindowRect);
7733#define FPL__FUNC_WIN32_ClientToScreen(name) BOOL WINAPI name(HWND hWnd, LPPOINT lpPoint)
7734typedef FPL__FUNC_WIN32_ClientToScreen(fpl__win32_func_ClientToScreen);
7735#define FPL__FUNC_WIN32_GetAsyncKeyState(name) SHORT WINAPI name(int vKey)
7736typedef FPL__FUNC_WIN32_GetAsyncKeyState(fpl__win32_func_GetAsyncKeyState);
7737#define FPL__FUNC_WIN32_GetKeyState(name) SHORT WINAPI name(int vKey)
7738typedef FPL__FUNC_WIN32_GetKeyState(fpl__win32_func_GetKeyState);
7739#define FPL__FUNC_WIN32_MapVirtualKeyW(name) UINT WINAPI name(UINT uCode, UINT uMapType)
7740typedef FPL__FUNC_WIN32_MapVirtualKeyW(fpl__win32_func_MapVirtualKeyW);
7741#define FPL__FUNC_WIN32_SetCursor(name) HCURSOR WINAPI name(HCURSOR hCursor)
7742typedef FPL__FUNC_WIN32_SetCursor(fpl__win32_func_SetCursor);
7743#define FPL__FUNC_WIN32_GetCursor(name) HCURSOR WINAPI name(VOID)
7744typedef FPL__FUNC_WIN32_GetCursor(fpl__win32_func_GetCursor);
7745#define FPL__FUNC_WIN32_GetCursorPos(name) BOOL WINAPI name(LPPOINT lpPoint)
7746typedef FPL__FUNC_WIN32_GetCursorPos(fpl__win32_func_GetCursorPos);
7747#define FPL__FUNC_WIN32_WindowFromPoint(name) HWND WINAPI name(POINT Point)
7748typedef FPL__FUNC_WIN32_WindowFromPoint(fpl__win32_func_WindowFromPoint);
7749#define FPL__FUNC_WIN32_PtInRect(name) BOOL WINAPI name(CONST RECT *lprc, POINT pt)
7750typedef FPL__FUNC_WIN32_PtInRect(fpl__win32_func_PtInRect);
7751#define FPL__FUNC_WIN32_LoadCursorA(name) HCURSOR WINAPI name(HINSTANCE hInstance, LPCSTR lpCursorName)
7752typedef FPL__FUNC_WIN32_LoadCursorA(fpl__win32_func_LoadCursorA);
7753#define FPL__FUNC_WIN32_LoadCursorW(name) HCURSOR WINAPI name(HINSTANCE hInstance, LPCWSTR lpCursorName)
7754typedef FPL__FUNC_WIN32_LoadCursorW(fpl__win32_func_LoadCursorW);
7755#define FPL__FUNC_WIN32_LoadIconA(name) HICON WINAPI name(HINSTANCE hInstance, LPCSTR lpIconName)
7756typedef FPL__FUNC_WIN32_LoadIconA(fpl__win32_func_LoadIconA);
7757#define FPL__FUNC_WIN32_LoadIconW(name) HICON WINAPI name(HINSTANCE hInstance, LPCWSTR lpIconName)
7758typedef FPL__FUNC_WIN32_LoadIconW(fpl__win32_func_LoadIconW);
7759#define FPL__FUNC_WIN32_SetWindowTextW(name) BOOL WINAPI name(HWND hWnd, LPCWSTR lpString)
7760typedef FPL__FUNC_WIN32_SetWindowTextW(fpl__win32_func_SetWindowTextW);
7761#define FPL__FUNC_WIN32_GetWindowTextW(name) int WINAPI name(HWND hWnd, LPWSTR lpString, int nMaxCount)
7762typedef FPL__FUNC_WIN32_GetWindowTextW(fpl__win32_func_GetWindowTextW);
7763#define FPL__FUNC_WIN32_SetWindowLongW(name) LONG WINAPI name(HWND hWnd, int nIndex, LONG dwNewLong)
7764typedef FPL__FUNC_WIN32_SetWindowLongW(fpl__win32_func_SetWindowLongW);
7765#define FPL__FUNC_WIN32_GetWindowLongW(name) LONG WINAPI name(HWND hWnd, int nIndex)
7766typedef FPL__FUNC_WIN32_GetWindowLongW(fpl__win32_func_GetWindowLongW);
7768#if defined(FPL_ARCH_X64)
7769#define FPL__FUNC_WIN32_SetWindowLongPtrW(name) LONG_PTR WINAPI name(HWND hWnd, int nIndex, LONG_PTR dwNewLong)
7770typedef FPL__FUNC_WIN32_SetWindowLongPtrW(fpl__win32_func_SetWindowLongPtrW);
7771#define FPL__FUNC_WIN32_GetWindowLongPtrW(name) LONG_PTR WINAPI name(HWND hWnd, int nIndex)
7772typedef FPL__FUNC_WIN32_GetWindowLongPtrW(fpl__win32_func_GetWindowLongPtrW);
7775#define FPL__FUNC_WIN32_ReleaseDC(name) int WINAPI name(HWND hWnd, HDC hDC)
7776typedef FPL__FUNC_WIN32_ReleaseDC(fpl__win32_func_ReleaseDC);
7777#define FPL__FUNC_WIN32_GetDC(name) HDC WINAPI name(HWND hWnd)
7778typedef FPL__FUNC_WIN32_GetDC(fpl__win32_func_GetDC);
7779#define FPL__FUNC_WIN32_ChangeDisplaySettingsW(name) LONG WINAPI name(DEVMODEW* lpDevMode, DWORD dwFlags)
7780typedef FPL__FUNC_WIN32_ChangeDisplaySettingsW(fpl__win32_func_ChangeDisplaySettingsW);
7781#define FPL__FUNC_WIN32_EnumDisplaySettingsW(name) BOOL WINAPI name(LPCWSTR lpszDeviceName, DWORD iModeNum, DEVMODEW* lpDevMode)
7782typedef FPL__FUNC_WIN32_EnumDisplaySettingsW(fpl__win32_func_EnumDisplaySettingsW);
7783#define FPL__FUNC_WIN32_OpenClipboard(name) BOOL WINAPI name(HWND hWndNewOwner)
7784typedef FPL__FUNC_WIN32_OpenClipboard(fpl__win32_func_OpenClipboard);
7785#define FPL__FUNC_WIN32_CloseClipboard(name) BOOL WINAPI name(VOID)
7786typedef FPL__FUNC_WIN32_CloseClipboard(fpl__win32_func_CloseClipboard);
7787#define FPL__FUNC_WIN32_EmptyClipboard(name) BOOL WINAPI name(VOID)
7788typedef FPL__FUNC_WIN32_EmptyClipboard(fpl__win32_func_EmptyClipboard);
7789#define FPL__FUNC_WIN32_IsClipboardFormatAvailable(name) BOOL WINAPI name(UINT format)
7790typedef FPL__FUNC_WIN32_IsClipboardFormatAvailable(fpl__win32_func_IsClipboardFormatAvailable);
7791#define FPL__FUNC_WIN32_SetClipboardData(name) HANDLE WINAPI name(UINT uFormat, HANDLE hMem)
7792typedef FPL__FUNC_WIN32_SetClipboardData(fpl__win32_func_SetClipboardData);
7793#define FPL__FUNC_WIN32_GetClipboardData(name) HANDLE WINAPI name(UINT uFormat)
7794typedef FPL__FUNC_WIN32_GetClipboardData(fpl__win32_func_GetClipboardData);
7795#define FPL__FUNC_WIN32_GetDesktopWindow(name) HWND WINAPI name(VOID)
7796typedef FPL__FUNC_WIN32_GetDesktopWindow(fpl__win32_func_GetDesktopWindow);
7797#define FPL__FUNC_WIN32_GetForegroundWindow(name) HWND WINAPI name(VOID)
7798typedef FPL__FUNC_WIN32_GetForegroundWindow(fpl__win32_func_GetForegroundWindow);
7799#define FPL__FUNC_WIN32_IsZoomed(name) BOOL WINAPI name(HWND hWnd)
7800typedef FPL__FUNC_WIN32_IsZoomed(fpl__win32_func_IsZoomed);
7801#define FPL__FUNC_WIN32_IsIconic(name) BOOL WINAPI name(HWND hWnd)
7802typedef FPL__FUNC_WIN32_IsIconic(fpl__win32_func_IsIconic);
7803#define FPL__FUNC_WIN32_SendMessageW(name) LRESULT WINAPI name(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
7804typedef FPL__FUNC_WIN32_SendMessageW(fpl__win32_func_SendMessageW);
7805#define FPL__FUNC_WIN32_GetMonitorInfoW(name) BOOL WINAPI name(HMONITOR hMonitor, LPMONITORINFO lpmi)
7806typedef FPL__FUNC_WIN32_GetMonitorInfoW(fpl__win32_func_GetMonitorInfoW);
7807#define FPL__FUNC_WIN32_EnumDisplayMonitors(name) BOOL WINAPI name(HDC hdc, LPCRECT lprcClip, MONITORENUMPROC lpfnEnum,LPARAM dwData)
7808typedef FPL__FUNC_WIN32_EnumDisplayMonitors(fpl__win32_func_EnumDisplayMonitors);
7809#define FPL__FUNC_WIN32_MonitorFromRect(name) HMONITOR WINAPI name(LPCRECT lprc, DWORD dwFlags)
7810typedef FPL__FUNC_WIN32_MonitorFromRect(fpl__win32_func_MonitorFromRect);
7811#define FPL__FUNC_WIN32_MonitorFromPoint(name) HMONITOR WINAPI name(POINT pt, DWORD dwFlags)
7812typedef FPL__FUNC_WIN32_MonitorFromPoint(fpl__win32_func_MonitorFromPoint);
7813#define FPL__FUNC_WIN32_MonitorFromWindow(name) HMONITOR WINAPI name(HWND hwnd, DWORD dwFlags)
7814typedef FPL__FUNC_WIN32_MonitorFromWindow(fpl__win32_func_MonitorFromWindow);
7815#define FPL__FUNC_WIN32_RegisterRawInputDevices(name) BOOL WINAPI name(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize)
7816typedef FPL__FUNC_WIN32_RegisterRawInputDevices(fpl__win32_func_RegisterRawInputDevices);
7817#define FPL__FUNC_WIN32_ClipCursor(name) BOOL WINAPI name(CONST RECT *lpRect)
7818typedef FPL__FUNC_WIN32_ClipCursor(fpl__win32_func_ClipCursor);
7819#define FPL__FUNC_WIN32_PostQuitMessage(name) VOID WINAPI name(int nExitCode)
7820typedef FPL__FUNC_WIN32_PostQuitMessage(fpl__win32_func_PostQuitMessage);
7821#define FPL__FUNC_WIN32_CreateIconIndirect(name) HICON WINAPI name(PICONINFO piconinfo)
7822typedef FPL__FUNC_WIN32_CreateIconIndirect(fpl__win32_func_CreateIconIndirect);
7823#define FPL__FUNC_WIN32_GetKeyboardLayout(name) HKL WINAPI name(DWORD idThread)
7824typedef FPL__FUNC_WIN32_GetKeyboardLayout(fpl__win32_func_GetKeyboardLayout);
7825#define FPL__FUNC_WIN32_SetCapture(name) HWND WINAPI name(HWND hWnd)
7826typedef FPL__FUNC_WIN32_SetCapture(fpl__win32_func_SetCapture);
7827#define FPL__FUNC_WIN32_ReleaseCapture(name) BOOL WINAPI name(VOID)
7828typedef FPL__FUNC_WIN32_ReleaseCapture(fpl__win32_func_ReleaseCapture);
7829#define FPL__FUNC_WIN32_ScreenToClient(name) BOOL WINAPI name(HWND hWnd, LPPOINT lpPoint)
7830typedef FPL__FUNC_WIN32_ScreenToClient(fpl__win32_func_ScreenToClient);
7831#define FPL__FUNC_WIN32_BeginPaint(name) HDC WINAPI name(_In_ HWND hWnd, _Out_ LPPAINTSTRUCT lpPaint)
7832typedef FPL__FUNC_WIN32_BeginPaint(fpl__win32_func_BeginPaint);
7833#define FPL__FUNC_WIN32_EndPaint(name) BOOL WINAPI name(_In_ HWND hWnd, _In_ CONST PAINTSTRUCT *lpPaint)
7834typedef FPL__FUNC_WIN32_EndPaint(fpl__win32_func_EndPaint);
7835#define FPL__FUNC_WIN32_SetForegroundWindow(name) BOOL WINAPI name(_In_ HWND hWnd)
7836typedef FPL__FUNC_WIN32_SetForegroundWindow(fpl__win32_func_SetForegroundWindow);
7837#define FPL__FUNC_WIN32_SetFocus(name) HWND WINAPI name(_In_opt_ HWND hWnd)
7838typedef FPL__FUNC_WIN32_SetFocus(fpl__win32_func_SetFocus);
7839#define FPL__FUNC_WIN32_SetTimer(name) UINT_PTR WINAPI name(_In_opt_ HWND hWnd, _In_ UINT_PTR nIDEvent, _In_ UINT uElapse, _In_opt_ TIMERPROC lpTimerFunc)
7840typedef FPL__FUNC_WIN32_SetTimer(fpl__win32_func_SetTimer);
7841#define FPL__FUNC_WIN32_GetSysColorBrush(name) HBRUSH WINAPI name(_In_ int nIndex)
7842typedef FPL__FUNC_WIN32_GetSysColorBrush(fpl__win32_func_GetSysColorBrush);
7843#define FPL__FUNC_WIN32_GetSysColorBrush(name) HBRUSH WINAPI name(_In_ int nIndex)
7844typedef FPL__FUNC_WIN32_GetSysColorBrush(fpl__win32_func_GetSysColorBrush);
7847#define FPL__FUNC_WIN32_CoInitializeEx(name) HRESULT WINAPI name(LPVOID pvReserved, DWORD dwCoInit)
7848typedef FPL__FUNC_WIN32_CoInitializeEx(fpl__win32_func_CoInitializeEx);
7849#define FPL__FUNC_WIN32_CoUninitialize(name) void WINAPI name(void)
7850typedef FPL__FUNC_WIN32_CoUninitialize(fpl__win32_func_CoUninitialize);
7851#define FPL__FUNC_WIN32_CoCreateInstance(name) HRESULT WINAPI name(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv)
7852typedef FPL__FUNC_WIN32_CoCreateInstance(fpl__win32_func_CoCreateInstance);
7853#define FPL__FUNC_WIN32_CoTaskMemFree(name) void WINAPI name(LPVOID pv)
7854typedef FPL__FUNC_WIN32_CoTaskMemFree(fpl__win32_func_CoTaskMemFree);
7855#define FPL__FUNC_WIN32_PropVariantClear(name) HRESULT WINAPI name(PROPVARIANT *pvar)
7856typedef FPL__FUNC_WIN32_PropVariantClear(fpl__win32_func_PropVariantClear);
7858typedef struct fpl__Win32GdiApi {
7860 fpl__win32_func_ChoosePixelFormat *ChoosePixelFormat;
7861 fpl__win32_func_SetPixelFormat *SetPixelFormat;
7862 fpl__win32_func_DescribePixelFormat *DescribePixelFormat;
7863 fpl__win32_func_GetDeviceCaps *GetDeviceCaps;
7864 fpl__win32_func_StretchDIBits *StretchDIBits;
7865 fpl__win32_func_DeleteObject *DeleteObject;
7866 fpl__win32_func_SwapBuffers *SwapBuffers;
7867 fpl__win32_func_CreateDIBSection *CreateDIBSection;
7868 fpl__win32_func_CreateBitmap *CreateBitmap;
7869 fpl__win32_func_CreateSolidBrush *CreateSolidBrush;
7872typedef struct fpl__Win32ShellApi {
7873 HMODULE shellLibrary;
7874 fpl__win32_func_SHGetFolderPathW *SHGetFolderPathW;
7875 fpl__win32_func_DragQueryFileW *DragQueryFileW;
7876 fpl__win32_func_DragAcceptFiles *DragAcceptFiles;
7877} fpl__Win32ShellApi;
7879typedef struct fpl__Win32UserApi {
7880 HMODULE userLibrary;
7881 fpl__win32_func_RegisterClassExW *RegisterClassExW;
7882 fpl__win32_func_UnregisterClassW *UnregisterClassW;
7883 fpl__win32_func_ShowWindow *ShowWindow;
7884 fpl__win32_func_DestroyWindow *DestroyWindow;
7885 fpl__win32_func_UpdateWindow *UpdateWindow;
7886 fpl__win32_func_TranslateMessage *TranslateMessage;
7887 fpl__win32_func_DispatchMessageW *DispatchMessageW;
7888 fpl__win32_func_PeekMessageW *PeekMessageW;
7889 fpl__win32_func_DefWindowProcW *DefWindowProcW;
7890 fpl__win32_func_CreateWindowExW *CreateWindowExW;
7891 fpl__win32_func_SetWindowPos *SetWindowPos;
7892 fpl__win32_func_GetWindowPlacement *GetWindowPlacement;
7893 fpl__win32_func_SetWindowPlacement *SetWindowPlacement;
7894 fpl__win32_func_GetClientRect *GetClientRect;
7895 fpl__win32_func_GetWindowRect *GetWindowRect;
7896 fpl__win32_func_AdjustWindowRect *AdjustWindowRect;
7897 fpl__win32_func_GetAsyncKeyState *GetAsyncKeyState;
7898 fpl__win32_func_MapVirtualKeyW *MapVirtualKeyW;
7899 fpl__win32_func_SetCursor *SetCursor;
7900 fpl__win32_func_GetCursor *GetCursor;
7901 fpl__win32_func_LoadCursorA *LoadCursorA;
7902 fpl__win32_func_LoadCursorW *LoadCursorW;
7903 fpl__win32_func_LoadIconA *LoadIconA;
7904 fpl__win32_func_LoadIconW *LoadIconW;
7905 fpl__win32_func_SetWindowTextW *SetWindowTextW;
7906 fpl__win32_func_GetWindowTextW *GetWindowTextW;
7907 fpl__win32_func_SetWindowLongW *SetWindowLongW;
7908 fpl__win32_func_GetWindowLongW *GetWindowLongW;
7909#if defined(FPL_ARCH_X64)
7910 fpl__win32_func_SetWindowLongPtrW *SetWindowLongPtrW;
7911 fpl__win32_func_GetWindowLongPtrW *GetWindowLongPtrW;
7913 fpl__win32_func_ReleaseDC *ReleaseDC;
7914 fpl__win32_func_GetDC *GetDC;
7915 fpl__win32_func_ChangeDisplaySettingsW *ChangeDisplaySettingsW;
7916 fpl__win32_func_EnumDisplaySettingsW *EnumDisplaySettingsW;
7917 fpl__win32_func_OpenClipboard *OpenClipboard;
7918 fpl__win32_func_CloseClipboard *CloseClipboard;
7919 fpl__win32_func_EmptyClipboard *EmptyClipboard;
7920 fpl__win32_func_IsClipboardFormatAvailable *IsClipboardFormatAvailable;
7921 fpl__win32_func_SetClipboardData *SetClipboardData;
7922 fpl__win32_func_GetClipboardData *GetClipboardData;
7923 fpl__win32_func_GetDesktopWindow *GetDesktopWindow;
7924 fpl__win32_func_GetForegroundWindow *GetForegroundWindow;
7925 fpl__win32_func_IsZoomed *IsZoomed;
7926 fpl__win32_func_IsIconic *IsIconic;
7927 fpl__win32_func_SendMessageW *SendMessageW;
7928 fpl__win32_func_GetMonitorInfoW *GetMonitorInfoW;
7929 fpl__win32_func_EnumDisplayMonitors *EnumDisplayMonitors;
7930 fpl__win32_func_MonitorFromRect *MonitorFromRect;
7931 fpl__win32_func_MonitorFromPoint *MonitorFromPoint;
7932 fpl__win32_func_MonitorFromWindow *MonitorFromWindow;
7933 fpl__win32_func_GetCursorPos *GetCursorPos;
7934 fpl__win32_func_WindowFromPoint *WindowFromPoint;
7935 fpl__win32_func_ClientToScreen *ClientToScreen;
7936 fpl__win32_func_PtInRect *PtInRect;
7937 fpl__win32_func_RegisterRawInputDevices *RegisterRawInputDevices;
7938 fpl__win32_func_ClipCursor *ClipCursor;
7939 fpl__win32_func_PostQuitMessage *PostQuitMessage;
7940 fpl__win32_func_CreateIconIndirect *CreateIconIndirect;
7941 fpl__win32_func_GetKeyboardLayout *GetKeyboardLayout;
7942 fpl__win32_func_GetKeyState *GetKeyState;
7943 fpl__win32_func_SetCapture *SetCapture;
7944 fpl__win32_func_ReleaseCapture *ReleaseCapture;
7945 fpl__win32_func_ScreenToClient *ScreenToClient;
7946 fpl__win32_func_BeginPaint *BeginPaint;
7947 fpl__win32_func_EndPaint *EndPaint;
7948 fpl__win32_func_SetForegroundWindow *SetForegroundWindow;
7949 fpl__win32_func_SetFocus *SetFocus;
7950 fpl__win32_func_SetTimer *SetTimer;
7951 fpl__win32_func_GetSysColorBrush *GetSysColorBrush;
7954typedef struct fpl__Win32OleApi {
7956 fpl__win32_func_CoInitializeEx *CoInitializeEx;
7957 fpl__win32_func_CoUninitialize *CoUninitialize;
7958 fpl__win32_func_CoCreateInstance *CoCreateInstance;
7959 fpl__win32_func_CoTaskMemFree *CoTaskMemFree;
7960 fpl__win32_func_PropVariantClear *PropVariantClear;
7963typedef struct fpl__Win32Api {
7964 fpl__Win32GdiApi gdi;
7965 fpl__Win32ShellApi shell;
7966 fpl__Win32UserApi user;
7967 fpl__Win32OleApi ole;
7971fpl_internal void fpl__Win32UnloadApi(fpl__Win32Api *wapi) {
7973 if (wapi->ole.oleLibrary !=
fpl_null) {
7974 FreeLibrary(wapi->ole.oleLibrary);
7977 if (wapi->gdi.gdiLibrary !=
fpl_null) {
7978 FreeLibrary(wapi->gdi.gdiLibrary);
7981 if (wapi->user.userLibrary !=
fpl_null) {
7982 FreeLibrary(wapi->user.userLibrary);
7985 if (wapi->shell.shellLibrary !=
fpl_null) {
7986 FreeLibrary(wapi->shell.shellLibrary);
7989 wapi->isValid =
false;
7992fpl_internal bool fpl__Win32LoadApi(fpl__Win32Api *wapi) {
7994 bool result =
false;
7998 const char *shellLibraryName =
"shell32.dll";
8000 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, shellLibrary, shellLibraryName);
8001 wapi->shell.shellLibrary = shellLibrary;
8002 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, shellLibrary, shellLibraryName, &wapi->shell, fpl__win32_func_SHGetFolderPathW, SHGetFolderPathW);
8003 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, shellLibrary, shellLibraryName, &wapi->shell, fpl__win32_func_DragQueryFileW, DragQueryFileW);
8004 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, shellLibrary, shellLibraryName, &wapi->shell, fpl__win32_func_DragAcceptFiles, DragAcceptFiles);
8007 const char *userLibraryName =
"user32.dll";
8009 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, userLibrary, userLibraryName);
8010 wapi->user.userLibrary = userLibrary;
8011 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_RegisterClassExW, RegisterClassExW);
8012 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_UnregisterClassW, UnregisterClassW);
8013 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ShowWindow, ShowWindow);
8014 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_DestroyWindow, DestroyWindow);
8015 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_UpdateWindow, UpdateWindow);
8016 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_TranslateMessage, TranslateMessage);
8017 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_DispatchMessageW, DispatchMessageW);
8018 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_PeekMessageW, PeekMessageW);
8019 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_DefWindowProcW, DefWindowProcW);
8020 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_CreateWindowExW, CreateWindowExW);
8021 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowPos, SetWindowPos);
8022 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowPlacement, GetWindowPlacement);
8023 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowPlacement, SetWindowPlacement);
8024 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetClientRect, GetClientRect);
8025 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowRect, GetWindowRect);
8026 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_AdjustWindowRect, AdjustWindowRect);
8027 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetAsyncKeyState, GetAsyncKeyState);
8028 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MapVirtualKeyW, MapVirtualKeyW);
8029 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetCursor, SetCursor);
8030 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetCursor, GetCursor);
8031 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadCursorA, LoadCursorA);
8032 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadCursorW, LoadCursorW);
8033 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetCursorPos, GetCursorPos);
8034 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_WindowFromPoint, WindowFromPoint);
8035 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadIconA, LoadIconA);
8036 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadIconW, LoadIconW);
8037 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowTextW, SetWindowTextW);
8038 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowLongW, SetWindowLongW);
8039 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowLongW, GetWindowLongW);
8041# if defined(FPL_ARCH_X64)
8042 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowLongPtrW, SetWindowLongPtrW);
8043 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowLongPtrW, GetWindowLongPtrW);
8046 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ReleaseDC, ReleaseDC);
8047 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetDC, GetDC);
8048 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ChangeDisplaySettingsW, ChangeDisplaySettingsW);
8049 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EnumDisplaySettingsW, EnumDisplaySettingsW);
8050 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_IsClipboardFormatAvailable, IsClipboardFormatAvailable);
8051 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_OpenClipboard, OpenClipboard);
8052 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_CloseClipboard, CloseClipboard);
8053 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EmptyClipboard, EmptyClipboard);
8054 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetClipboardData, SetClipboardData);
8055 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetClipboardData, GetClipboardData);
8056 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetDesktopWindow, GetDesktopWindow);
8057 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetForegroundWindow, GetForegroundWindow);
8058 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_IsZoomed, IsZoomed);
8059 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_IsIconic, IsIconic);
8060 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SendMessageW, SendMessageW);
8061 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetMonitorInfoW, GetMonitorInfoW);
8062 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EnumDisplayMonitors, EnumDisplayMonitors);
8063 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MonitorFromRect, MonitorFromRect);
8064 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MonitorFromPoint, MonitorFromPoint);
8065 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MonitorFromWindow, MonitorFromWindow);
8066 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ClientToScreen, ClientToScreen);
8067 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_PtInRect, PtInRect);
8068 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_RegisterRawInputDevices, RegisterRawInputDevices);
8069 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ClipCursor, ClipCursor);
8070 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_PostQuitMessage, PostQuitMessage);
8071 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_CreateIconIndirect, CreateIconIndirect);
8072 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetKeyboardLayout, GetKeyboardLayout);
8073 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetKeyState, GetKeyState);
8074 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetCapture, SetCapture);
8075 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ReleaseCapture, ReleaseCapture);
8076 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ScreenToClient, ScreenToClient);
8077 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_BeginPaint, BeginPaint);
8078 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EndPaint, EndPaint);
8079 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetForegroundWindow, SetForegroundWindow);
8080 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetFocus, SetFocus);
8081 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetTimer, SetTimer);
8082 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetSysColorBrush, GetSysColorBrush);
8085 const char *gdiLibraryName =
"gdi32.dll";
8087 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName);
8088 wapi->gdi.gdiLibrary = gdiLibrary;
8089 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_ChoosePixelFormat, ChoosePixelFormat);
8090 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_SetPixelFormat, SetPixelFormat);
8091 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_DescribePixelFormat, DescribePixelFormat);
8092 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_StretchDIBits, StretchDIBits);
8093 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_DeleteObject, DeleteObject);
8094 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_SwapBuffers, SwapBuffers);
8095 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_GetDeviceCaps, GetDeviceCaps);
8096 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_CreateDIBSection, CreateDIBSection);
8097 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_CreateBitmap, CreateBitmap);
8098 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_CreateSolidBrush, CreateSolidBrush);
8101 const char *oleLibraryName =
"ole32.dll";
8103 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, oleLibrary, oleLibraryName);
8104 wapi->ole.oleLibrary = oleLibrary;
8105 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoInitializeEx, CoInitializeEx);
8106 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoUninitialize, CoUninitialize);
8107 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoCreateInstance, CoCreateInstance);
8108 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoTaskMemFree, CoTaskMemFree);
8109 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_PropVariantClear, PropVariantClear);
8114 fpl__Win32UnloadApi(wapi);
8116 wapi->isValid = result;
8121#define FPL__WIN32_CLASSNAME L"FPLWindowClassW"
8122#define FPL__WIN32_UNNAMED_WINDOW L"Unnamed FPL Unicode Window"
8123#define FPL__WIN32_UNNAMED_CONSOLE L"Unnamed FPL Unicode Console"
8124#if defined(FPL_ARCH_X64)
8125# define fpl__win32_SetWindowLongPtr fpl__global__AppState->win32.winApi.user.SetWindowLongPtrW
8127# define fpl__win32_SetWindowLongPtr fpl__global__AppState->win32.winApi.user.SetWindowLongW
8129#define fpl__win32_SetWindowLong fpl__global__AppState->win32.winApi.user.SetWindowLongW
8130#define fpl__win32_GetWindowLong fpl__global__AppState->win32.winApi.user.GetWindowLongW
8132# define fpl__win32_LoadIcon fpl__global__AppState->win32.winApi.user.LoadIconW
8133# define fpl__win32_LoadCursor fpl__global__AppState->win32.winApi.user.LoadCursorW
8135# define fpl__win32_LoadIcon fpl__global__AppState->win32.winApi.user.LoadIconA
8136# define fpl__win32_LoadCursor fpl__global__AppState->win32.winApi.user.LoadCursorA
8141typedef struct fpl__Win32XInputState {
8142 fpl__GameControllerName deviceNames[XUSER_MAX_COUNT];
8143 fpl_b32 isConnected[XUSER_MAX_COUNT];
8144 fpl__Win32XInputApi xinputApi;
8145 LARGE_INTEGER lastDeviceSearchTime;
8146} fpl__Win32XInputState;
8148typedef struct fpl__Win32InitState {
8149 HINSTANCE appInstance;
8151} fpl__Win32InitState;
8153typedef struct fpl__Win32AppState {
8154 fpl__Win32XInputState xinput;
8155 fpl__Win32Api winApi;
8156} fpl__Win32AppState;
8158#if defined(FPL__ENABLE_WINDOW)
8159typedef struct fpl__Win32LastWindowInfo {
8160 WINDOWPLACEMENT placement;
8166} fpl__Win32LastWindowInfo;
8168typedef struct fpl__Win32WindowState {
8169 wchar_t windowClass[256];
8170 fpl__Win32LastWindowInfo lastFullscreenInfo;
8175 HBRUSH backgroundBrush;
8176 HCURSOR defaultCursor;
8180} fpl__Win32WindowState;
8190#if defined(FPL_SUBPLATFORM_POSIX)
8191# include <sys/types.h>
8192# include <sys/mman.h>
8193# include <sys/stat.h>
8194# include <sys/errno.h>
8195# include <sys/time.h>
8196# include <sys/utsname.h>
8206#if !defined(FPL_PLATFORM_ANDROID)
8207# define st_atime st_atim.tv_sec
8208# define st_mtime st_mtim.tv_sec
8209# define st_ctime st_ctim.tv_sec
8212#if defined(FPL_PLATFORM_LINUX)
8213# define fpl__lseek64 lseek64
8214# define fpl__off64_t off64_t
8216# define fpl__lseek64 lseek
8217# define fpl__off64_t off_t
8221#define FPL__POSIX_LOAD_LIBRARY_BREAK(mod, target, libName) \
8222 (target) = dlopen(libName, FPL__POSIX_DL_LOADTYPE); \
8223 if((target) == fpl_null) { \
8224 FPL__WARNING(mod, "Failed loading library '%s'", (libName)); \
8228#define FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(mod, libHandle, libName, target, type, name) \
8229 (target)->name = (type *)dlsym(libHandle, #name)
8231#define FPL__POSIX_GET_FUNCTION_ADDRESS_BREAK(mod, libHandle, libName, target, type, name) \
8232 (target)->name = (type *)dlsym(libHandle, #name); \
8233 if ((target)->name == fpl_null) { \
8234 FPL__WARNING(mod, "Failed getting procedure address '%s' from library '%s'", #name, libName); \
8237#if !defined(FPL_NO_RUNTIME_LINKING)
8238# define FPL__POSIX_LOAD_LIBRARY FPL__POSIX_LOAD_LIBRARY_BREAK
8239# define FPL__POSIX_GET_FUNCTION_ADDRESS FPL__POSIX_GET_FUNCTION_ADDRESS_BREAK
8241# define FPL__POSIX_LOAD_LIBRARY(mod, target, libName)
8242# define FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(mod, libHandle, libName, target, type, name) \
8243 (target)->name = name
8244# define FPL__POSIX_GET_FUNCTION_ADDRESS(mod, libHandle, libName, target, type, name) \
8245 (target)->name = name
8248#define FPL__FUNC_PTHREAD_pthread_self(name) pthread_t name(void)
8249typedef FPL__FUNC_PTHREAD_pthread_self(fpl__pthread_func_pthread_self);
8250#define FPL__FUNC_PTHREAD_pthread_setschedparam(name) int name(pthread_t thread, int policy, const struct sched_param *param)
8251typedef FPL__FUNC_PTHREAD_pthread_setschedparam(fpl__pthread_func_pthread_setschedparam);
8252#define FPL__FUNC_PTHREAD_pthread_getschedparam(name) int name(pthread_t thread, int *policy, struct sched_param *param)
8253typedef FPL__FUNC_PTHREAD_pthread_getschedparam(fpl__pthread_func_pthread_getschedparam);
8254#define FPL__FUNC_PTHREAD_pthread_setschedprio(name) int name(pthread_t thread, int prio)
8255typedef FPL__FUNC_PTHREAD_pthread_setschedprio(fpl__pthread_func_pthread_setschedprio);
8257#define FPL__FUNC_PTHREAD_pthread_attr_init(name) int name(pthread_attr_t *attr)
8258typedef FPL__FUNC_PTHREAD_pthread_attr_init(fpl__pthread_func_pthread_attr_init);
8259#define FPL__FUNC_PTHREAD_pthread_attr_getschedparam(name) int name(const pthread_attr_t *__restrict__ attr, struct sched_param *__restrict__ param)
8260typedef FPL__FUNC_PTHREAD_pthread_attr_getschedparam(fpl__pthread_func_pthread_attr_getschedparam);
8261#define FPL__FUNC_PTHREAD_pthread_attr_setschedparam(name) int name(pthread_attr_t *__restrict__ attr, const struct sched_param *__restrict__ param)
8262typedef FPL__FUNC_PTHREAD_pthread_attr_setschedparam(fpl__pthread_func_pthread_attr_setschedparam);
8263#define FPL__FUNC_PTHREAD_pthread_attr_setstacksize(name) int name(pthread_attr_t *attr, size_t stacksize)
8264typedef FPL__FUNC_PTHREAD_pthread_attr_setstacksize(fpl__pthread_func_pthread_attr_setstacksize);
8265#define FPL__FUNC_PTHREAD_pthread_attr_setdetachstate(name) int name(pthread_attr_t *attr, int detachstate);
8266typedef FPL__FUNC_PTHREAD_pthread_attr_setdetachstate(fpl__pthread_func_pthread_attr_setdetachstate);
8267#define FPL__FUNC_PTHREAD_pthread_attr_setschedpolicy(name) int name(pthread_attr_t *__attr, int __policy)
8268typedef FPL__FUNC_PTHREAD_pthread_attr_setschedpolicy(fpl__pthread_func_pthread_attr_setschedpolicy);
8270#define FPL__FUNC_PTHREAD_pthread_create(name) int name(pthread_t *, const pthread_attr_t *, void *(*__start_routine) (void *), void *)
8271typedef FPL__FUNC_PTHREAD_pthread_create(fpl__pthread_func_pthread_create);
8272#define FPL__FUNC_PTHREAD_pthread_kill(name) int name(pthread_t thread, int sig)
8273typedef FPL__FUNC_PTHREAD_pthread_kill(fpl__pthread_func_pthread_kill);
8274#define FPL__FUNC_PTHREAD_pthread_join(name) int name(pthread_t __th, void **retval)
8275typedef FPL__FUNC_PTHREAD_pthread_join(fpl__pthread_func_pthread_join);
8276#define FPL__FUNC_PTHREAD_pthread_exit(name) void name(void *__retval)
8277typedef FPL__FUNC_PTHREAD_pthread_exit(fpl__pthread_func_pthread_exit);
8278#define FPL__FUNC_PTHREAD_pthread_yield(name) int name(void)
8279typedef FPL__FUNC_PTHREAD_pthread_yield(fpl__pthread_func_pthread_yield);
8280#define FPL__FUNC_PTHREAD_pthread_timedjoin_np(name) int name(pthread_t thread, void **retval, const struct timespec *abstime)
8281typedef FPL__FUNC_PTHREAD_pthread_timedjoin_np(fpl__pthread_func_pthread_timedjoin_np);
8283#define FPL__FUNC_PTHREAD_pthread_mutex_init(name) int name(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
8284typedef FPL__FUNC_PTHREAD_pthread_mutex_init(fpl__pthread_func_pthread_mutex_init);
8285#define FPL__FUNC_PTHREAD_pthread_mutex_destroy(name) int name(pthread_mutex_t *mutex)
8286typedef FPL__FUNC_PTHREAD_pthread_mutex_destroy(fpl__pthread_func_pthread_mutex_destroy);
8287#define FPL__FUNC_PTHREAD_pthread_mutex_lock(name) int name(pthread_mutex_t *mutex)
8288typedef FPL__FUNC_PTHREAD_pthread_mutex_lock(fpl__pthread_func_pthread_mutex_lock);
8289#define FPL__FUNC_PTHREAD_pthread_mutex_trylock(name) int name(pthread_mutex_t *mutex)
8290typedef FPL__FUNC_PTHREAD_pthread_mutex_trylock(fpl__pthread_func_pthread_mutex_trylock);
8291#define FPL__FUNC_PTHREAD_pthread_mutex_unlock(name) int name(pthread_mutex_t *mutex)
8292typedef FPL__FUNC_PTHREAD_pthread_mutex_unlock(fpl__pthread_func_pthread_mutex_unlock);
8294#define FPL__FUNC_PTHREAD_pthread_cond_init(name) int name(pthread_cond_t *cond, const pthread_condattr_t *attr)
8295typedef FPL__FUNC_PTHREAD_pthread_cond_init(fpl__pthread_func_pthread_cond_init);
8296#define FPL__FUNC_PTHREAD_pthread_cond_destroy(name) int name(pthread_cond_t *cond)
8297typedef FPL__FUNC_PTHREAD_pthread_cond_destroy(fpl__pthread_func_pthread_cond_destroy);
8298#define FPL__FUNC_PTHREAD_pthread_cond_timedwait(name) int name(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
8299typedef FPL__FUNC_PTHREAD_pthread_cond_timedwait(fpl__pthread_func_pthread_cond_timedwait);
8300#define FPL__FUNC_PTHREAD_pthread_cond_wait(name) int name(pthread_cond_t *cond, pthread_mutex_t *mutex)
8301typedef FPL__FUNC_PTHREAD_pthread_cond_wait(fpl__pthread_func_pthread_cond_wait);
8302#define FPL__FUNC_PTHREAD_pthread_cond_broadcast(name) int name(pthread_cond_t *cond)
8303typedef FPL__FUNC_PTHREAD_pthread_cond_broadcast(fpl__pthread_func_pthread_cond_broadcast);
8304#define FPL__FUNC_PTHREAD_pthread_cond_signal(name) int name(pthread_cond_t *cond)
8305typedef FPL__FUNC_PTHREAD_pthread_cond_signal(fpl__pthread_func_pthread_cond_signal);
8307#define FPL__FUNC_PTHREAD_sem_init(name) int name(sem_t *__sem, int __pshared, unsigned int __value)
8308typedef FPL__FUNC_PTHREAD_sem_init(fpl__pthread_func_sem_init);
8309#define FPL__FUNC_PTHREAD_sem_destroy(name) int name(sem_t *__sem)
8310typedef FPL__FUNC_PTHREAD_sem_destroy(fpl__pthread_func_sem_destroy);
8311#define FPL__FUNC_PTHREAD_sem_wait(name) int name(sem_t *__sem)
8312typedef FPL__FUNC_PTHREAD_sem_wait(fpl__pthread_func_sem_wait);
8313#define FPL__FUNC_PTHREAD_sem_timedwait(name) int name(sem_t *__restrict __sem, const struct timespec *__restrict __abstime)
8314typedef FPL__FUNC_PTHREAD_sem_timedwait(fpl__pthread_func_sem_timedwait);
8315#define FPL__FUNC_PTHREAD_sem_trywait(name) int name(sem_t *__sem)
8316typedef FPL__FUNC_PTHREAD_sem_trywait(fpl__pthread_func_sem_trywait);
8317#define FPL__FUNC_PTHREAD_sem_post(name) int name(sem_t *__sem)
8318typedef FPL__FUNC_PTHREAD_sem_post(fpl__pthread_func_sem_post);
8319#define FPL__FUNC_PTHREAD_sem_getvalue(name) int name(sem_t *__restrict __sem, int *__restrict __sval)
8320typedef FPL__FUNC_PTHREAD_sem_getvalue(fpl__pthread_func_sem_getvalue);
8322typedef struct fpl__PThreadApi {
8326 fpl__pthread_func_pthread_self *pthread_self;
8327 fpl__pthread_func_pthread_setschedparam *pthread_setschedparam;
8328 fpl__pthread_func_pthread_getschedparam *pthread_getschedparam;
8329 fpl__pthread_func_pthread_setschedprio *pthread_setschedprio;
8331 fpl__pthread_func_pthread_create *pthread_create;
8332 fpl__pthread_func_pthread_kill *pthread_kill;
8333 fpl__pthread_func_pthread_join *pthread_join;
8334 fpl__pthread_func_pthread_exit *pthread_exit;
8335 fpl__pthread_func_pthread_yield *pthread_yield;
8336 fpl__pthread_func_pthread_timedjoin_np *pthread_timedjoin_np;
8339 fpl__pthread_func_pthread_attr_init *pthread_attr_init;
8340 fpl__pthread_func_pthread_attr_getschedparam *pthread_attr_getschedparam;
8341 fpl__pthread_func_pthread_attr_setschedparam *pthread_attr_setschedparam;
8342 fpl__pthread_func_pthread_attr_setstacksize *pthread_attr_setstacksize;
8343 fpl__pthread_func_pthread_attr_setdetachstate *pthread_attr_setdetachstate;
8344 fpl__pthread_func_pthread_attr_setschedpolicy *pthread_attr_setschedpolicy;
8347 fpl__pthread_func_pthread_mutex_init *pthread_mutex_init;
8348 fpl__pthread_func_pthread_mutex_destroy *pthread_mutex_destroy;
8349 fpl__pthread_func_pthread_mutex_lock *pthread_mutex_lock;
8350 fpl__pthread_func_pthread_mutex_trylock *pthread_mutex_trylock;
8351 fpl__pthread_func_pthread_mutex_unlock *pthread_mutex_unlock;
8354 fpl__pthread_func_pthread_cond_init *pthread_cond_init;
8355 fpl__pthread_func_pthread_cond_destroy *pthread_cond_destroy;
8356 fpl__pthread_func_pthread_cond_timedwait *pthread_cond_timedwait;
8357 fpl__pthread_func_pthread_cond_wait *pthread_cond_wait;
8358 fpl__pthread_func_pthread_cond_broadcast *pthread_cond_broadcast;
8359 fpl__pthread_func_pthread_cond_signal *pthread_cond_signal;
8362 fpl__pthread_func_sem_init *sem_init;
8363 fpl__pthread_func_sem_destroy *sem_destroy;
8364 fpl__pthread_func_sem_wait *sem_wait;
8365 fpl__pthread_func_sem_timedwait *sem_timedwait;
8366 fpl__pthread_func_sem_trywait *sem_trywait;
8367 fpl__pthread_func_sem_post *sem_post;
8368 fpl__pthread_func_sem_getvalue *sem_getvalue;
8371#define FPL__POSIX_DL_LOADTYPE RTLD_NOW
8373fpl_internal void fpl__PThreadUnloadApi(fpl__PThreadApi *pthreadApi) {
8375 if (pthreadApi->libHandle !=
fpl_null) {
8376 dlclose(pthreadApi->libHandle);
8381fpl_internal bool fpl__PThreadLoadApi(fpl__PThreadApi *pthreadApi) {
8382 const char *libpthreadFileNames[] = {
8386 bool result =
false;
8387 for (uint32_t index = 0; index <
fplArrayCount(libpthreadFileNames); ++index) {
8388 const char *libName = libpthreadFileNames[index];
8392 FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_PTHREAD, libHandle, libName);
8395 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_self, pthread_self);
8396 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_setschedparam, pthread_setschedparam);
8397 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_getschedparam, pthread_getschedparam);
8398 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_setschedprio, pthread_setschedprio);
8400 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_create, pthread_create);
8401 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_kill, pthread_kill);
8402 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_join, pthread_join);
8403 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_exit, pthread_exit);
8404 FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_yield, pthread_yield);
8405 FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_timedjoin_np, pthread_timedjoin_np);
8408 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_init, pthread_attr_init);
8409 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_getschedparam, pthread_attr_getschedparam);
8410 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setschedparam, pthread_attr_setschedparam);
8411 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setstacksize, pthread_attr_setstacksize);
8412 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setdetachstate, pthread_attr_setdetachstate);
8413 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
8416 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_init, pthread_mutex_init);
8417 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_destroy, pthread_mutex_destroy);
8418 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_lock, pthread_mutex_lock);
8419 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_trylock, pthread_mutex_trylock);
8420 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_unlock, pthread_mutex_unlock);
8423 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_init, pthread_cond_init);
8424 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_destroy, pthread_cond_destroy);
8425 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_timedwait, pthread_cond_timedwait);
8426 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_wait, pthread_cond_wait);
8427 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_broadcast, pthread_cond_broadcast);
8428 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_signal, pthread_cond_signal);
8431 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_init, sem_init);
8432 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_destroy, sem_destroy);
8433 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_wait, sem_wait);
8434 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_timedwait, sem_timedwait);
8435 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_trywait, sem_trywait);
8436 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_post, sem_post);
8437 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_getvalue, sem_getvalue);
8439 pthreadApi->libHandle = libHandle;
8445 fpl__PThreadUnloadApi(pthreadApi);
8450typedef struct fpl__PosixInitState {
8452} fpl__PosixInitState;
8454typedef struct fpl__PosixAppState {
8455 fpl__PThreadApi pthreadApi;
8456} fpl__PosixAppState;
8464#if defined(FPL_PLATFORM_LINUX)
8465typedef struct fpl__LinuxInitState {
8467} fpl__LinuxInitState;
8469#if defined(FPL__ENABLE_WINDOW)
8470#define FPL__LINUX_MAX_GAME_CONTROLLER_COUNT 4
8471typedef struct fpl__LinuxGameController {
8472 char deviceName[512 + 1];
8476 uint8_t buttonCount;
8478} fpl__LinuxGameController;
8480typedef struct fpl__LinuxGameControllersState {
8481 fpl__LinuxGameController controllers[FPL__LINUX_MAX_GAME_CONTROLLER_COUNT];
8482 uint64_t lastCheckTime;
8483} fpl__LinuxGameControllersState;
8486typedef struct fpl__LinuxAppState {
8487#if defined(FPL__ENABLE_WINDOW)
8488 fpl__LinuxGameControllersState controllersState;
8491} fpl__LinuxAppState;
8494#if defined(FPL__ENABLE_WINDOW)
8495fpl_internal void fpl__LinuxFreeGameControllers(fpl__LinuxGameControllersState *controllersState);
8496fpl_internal void fpl__LinuxPollGameControllers(
const fplSettings *settings, fpl__LinuxGameControllersState *controllersState,
const bool useEvents);
8506#if defined(FPL_PLATFORM_UNIX)
8507typedef struct fpl__UnixInitState {
8509} fpl__UnixInitState;
8511typedef struct fpl__UnixAppState {
8521#if defined(FPL_SUBPLATFORM_X11)
8523#include <X11/keysym.h>
8528#define FPL__FUNC_X11_XFree(name) int name(void *data)
8529typedef FPL__FUNC_X11_XFree(fpl__func_x11_XFree);
8530#define FPL__FUNC_X11_XFlush(name) int name(Display *display)
8531typedef FPL__FUNC_X11_XFlush(fpl__func_x11_XFlush);
8532#define FPL__FUNC_X11_XOpenDisplay(name) Display *name(char *display_name)
8533typedef FPL__FUNC_X11_XOpenDisplay(fpl__func_x11_XOpenDisplay);
8534#define FPL__FUNC_X11_XCloseDisplay(name) int name(Display *display)
8535typedef FPL__FUNC_X11_XCloseDisplay(fpl__func_x11_XCloseDisplay);
8536#define FPL__FUNC_X11_XDefaultScreen(name) int name(Display *display)
8537typedef FPL__FUNC_X11_XDefaultScreen(fpl__func_x11_XDefaultScreen);
8538#define FPL__FUNC_X11_XRootWindow(name) Window name(Display *display, int screen_number)
8539typedef FPL__FUNC_X11_XRootWindow(fpl__func_x11_XRootWindow);
8540#define FPL__FUNC_X11_XCreateWindow(name) Window name(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int clazz, Visual *visual, unsigned long valuemask, XSetWindowAttributes *attributes)
8541typedef FPL__FUNC_X11_XCreateWindow(fpl__func_x11_XCreateWindow);
8542#define FPL__FUNC_X11_XDestroyWindow(name) int name(Display *display, Window w)
8543typedef FPL__FUNC_X11_XDestroyWindow(fpl__func_x11_XDestroyWindow);
8544#define FPL__FUNC_X11_XCreateColormap(name) Colormap name(Display *display, Window w, Visual *visual, int alloc)
8545typedef FPL__FUNC_X11_XCreateColormap(fpl__func_x11_XCreateColormap);
8546#define FPL__FUNC_X11_XDefaultColormap(name) Colormap name(Display *display, int screen_number)
8547typedef FPL__FUNC_X11_XDefaultColormap(fpl__func_x11_XDefaultColormap);
8548#define FPL__FUNC_X11_XFreeColormap(name) int name(Display *display, Colormap colormap)
8549typedef FPL__FUNC_X11_XFreeColormap(fpl__func_x11_XFreeColormap);
8550#define FPL__FUNC_X11_XMapWindow(name) int name(Display *display, Window w)
8551typedef FPL__FUNC_X11_XMapWindow(fpl__func_x11_XMapWindow);
8552#define FPL__FUNC_X11_XUnmapWindow(name) int name(Display *display, Window w)
8553typedef FPL__FUNC_X11_XUnmapWindow(fpl__func_x11_XUnmapWindow);
8554#define FPL__FUNC_X11_XStoreName(name) int name(Display *display, Window w, _Xconst char *window_name)
8555typedef FPL__FUNC_X11_XStoreName(fpl__func_x11_XStoreName);
8556#define FPL__FUNC_X11_XDefaultVisual(name) Visual *name(Display *display, int screen_number)
8557typedef FPL__FUNC_X11_XDefaultVisual(fpl__func_x11_XDefaultVisual);
8558#define FPL__FUNC_X11_XDefaultDepth(name) int name(Display *display, int screen_number)
8559typedef FPL__FUNC_X11_XDefaultDepth(fpl__func_x11_XDefaultDepth);
8560#define FPL__FUNC_X11_XInternAtom(name) Atom name(Display *display, const char *atom_name, Bool only_if_exists)
8561typedef FPL__FUNC_X11_XInternAtom(fpl__func_x11_XInternAtom);
8562#define FPL__FUNC_X11_XSetWMProtocols(name) Status name(Display *display, Window w, Atom *protocols, int count)
8563typedef FPL__FUNC_X11_XSetWMProtocols(fpl__func_x11_XSetWMProtocols);
8564#define FPL__FUNC_X11_XPending(name) int name(Display *display)
8565typedef FPL__FUNC_X11_XPending(fpl__func_x11_XPending);
8566#define FPL__FUNC_X11_XSync(name) int name(Display *display, Bool discard)
8567typedef FPL__FUNC_X11_XSync(fpl__func_x11_XSync);
8568#define FPL__FUNC_X11_XNextEvent(name) int name(Display *display, XEvent *event_return)
8569typedef FPL__FUNC_X11_XNextEvent(fpl__func_x11_XNextEvent);
8570#define FPL__FUNC_X11_XPeekEvent(name) int name(Display *display, XEvent *event_return)
8571typedef FPL__FUNC_X11_XPeekEvent(fpl__func_x11_XPeekEvent);
8572#define FPL__FUNC_X11_XEventsQueued(name) int name(Display *display, int mode)
8573typedef FPL__FUNC_X11_XEventsQueued(fpl__func_x11_XEventsQueued);
8574#define FPL__FUNC_X11_XGetWindowAttributes(name) Status name(Display *display, Window w, XWindowAttributes *window_attributes_return)
8575typedef FPL__FUNC_X11_XGetWindowAttributes(fpl__func_x11_XGetWindowAttributes);
8576#define FPL__FUNC_X11_XResizeWindow(name) int name(Display *display, Window w, unsigned int width, unsigned int height)
8577typedef FPL__FUNC_X11_XResizeWindow(fpl__func_x11_XResizeWindow);
8578#define FPL__FUNC_X11_XMoveWindow(name) int name(Display *display, Window w, int x, int y)
8579typedef FPL__FUNC_X11_XMoveWindow(fpl__func_x11_XMoveWindow);
8580#define FPL__FUNC_X11_XGetKeyboardMapping(name) KeySym *name(Display *display, KeyCode first_keycode, int keycode_count, int *keysyms_per_keycode_return)
8581typedef FPL__FUNC_X11_XGetKeyboardMapping(fpl__func_x11_XGetKeyboardMapping);
8582#define FPL__FUNC_X11_XLookupString(name) int name(XKeyEvent* event_struct, char* buffer_return, int bytes_buffer, KeySym* keysym_return, XComposeStatus* status_in_out)
8583typedef FPL__FUNC_X11_XLookupString(fpl__func_x11_XLookupString);
8584#define FPL__FUNC_X11_XSendEvent(name) Status name(Display *display, Window w, Bool propagate, long event_mask, XEvent *event_send)
8585typedef FPL__FUNC_X11_XSendEvent(fpl__func_x11_XSendEvent);
8586#define FPL__FUNC_X11_XMatchVisualInfo(name) Status name(Display* display, int screen, int depth, int clazz, XVisualInfo* vinfo_return)
8587typedef FPL__FUNC_X11_XMatchVisualInfo(fpl__func_x11_XMatchVisualInfo);
8588#define FPL__FUNC_X11_XCreateGC(name) GC name(Display* display, Drawable d, unsigned long valuemask, XGCValues* values)
8589typedef FPL__FUNC_X11_XCreateGC(fpl__func_x11_XCreateGC);
8590#define FPL__FUNC_X11_XGetImage(name) XImage *name(Display* display, Drawable d, int x, int y, unsigned int width, unsigned int height, unsigned long plane_mask, int format)
8591typedef FPL__FUNC_X11_XGetImage(fpl__func_x11_XGetImage);
8592#define FPL__FUNC_X11_XCreateImage(name) XImage *name(Display *display, Visual *visual, unsigned int depth, int format, int offset, char *data, unsigned int width, unsigned int height, int bitmap_pad, int bytes_per_line)
8593typedef FPL__FUNC_X11_XCreateImage(fpl__func_x11_XCreateImage);
8594#define FPL__FUNC_X11_XPutImage(name) int name(Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)
8595typedef FPL__FUNC_X11_XPutImage(fpl__func_x11_XPutImage);
8596#define FPL__FUNC_X11_XMapRaised(name) int name(Display *display, Window w)
8597typedef FPL__FUNC_X11_XMapRaised(fpl__func_x11_XMapRaised);
8598#define FPL__FUNC_X11_XCreatePixmap(name) Pixmap name(Display * display, Drawable d, unsigned int width, unsigned int height, unsigned int depth)
8599typedef FPL__FUNC_X11_XCreatePixmap(fpl__func_x11_XCreatePixmap);
8600#define FPL__FUNC_X11_XSelectInput(name) int name(Display * display, Window w, long eventMask)
8601typedef FPL__FUNC_X11_XSelectInput(fpl__func_x11_XSelectInput);
8602#define FPL__FUNC_X11_XGetWindowProperty(name) int name(Display* display, Window w, Atom prop, long long_offset, long long_length, Bool del, Atom req_type, Atom* actual_type_return, int* actual_format_return, unsigned long* nitems_return, unsigned long* bytes_after_return, unsigned char** prop_return)
8603typedef FPL__FUNC_X11_XGetWindowProperty(fpl__func_x11_XGetWindowProperty);
8604#define FPL__FUNC_X11_XChangeProperty(name) int name(Display* display, Window w, Atom property, Atom type, int format, int mode, _Xconst unsigned char* data, int nelements)
8605typedef FPL__FUNC_X11_XChangeProperty(fpl__func_x11_XChangeProperty);
8606#define FPL__FUNC_X11_XDeleteProperty(name) int name(Display* display, Window w,Atom prop)
8607typedef FPL__FUNC_X11_XDeleteProperty(fpl__func_x11_XDeleteProperty);
8608#define FPL__FUNC_X11_XStringListToTextProperty(name) Status name(char** list, int count, XTextProperty* text_prop_return)
8609typedef FPL__FUNC_X11_XStringListToTextProperty(fpl__func_x11_XStringListToTextProperty);
8610#define FPL__FUNC_X11_XSetWMIconName(name) void name(Display* display, Window w, XTextProperty *text_prop)
8611typedef FPL__FUNC_X11_XSetWMIconName(fpl__func_x11_XSetWMIconName);
8612#define FPL__FUNC_X11_XSetWMName(name) void name(Display* display, Window w, XTextProperty *text_prop)
8613typedef FPL__FUNC_X11_XSetWMName(fpl__func_x11_XSetWMName);
8614#define FPL__FUNC_X11_XQueryKeymap(name) int name(Display* display, char [32])
8615typedef FPL__FUNC_X11_XQueryKeymap(fpl__func_x11_XQueryKeymap);
8616#define FPL__FUNC_X11_XQueryPointer(name) Bool name(Display* display, Window w, Window* root_return, Window* child_return, int* root_x_return, int* root_y_return, int* win_x_return, int* win_y_return, unsigned int* mask_return)
8617typedef FPL__FUNC_X11_XQueryPointer(fpl__func_x11_XQueryPointer);
8618#define FPL__FUNC_X11_XConvertSelection(name) int name(Display *display, Atom selection, Atom target, Atom property, Window requestor, Time time)
8619typedef FPL__FUNC_X11_XConvertSelection(fpl__func_x11_XConvertSelection);
8620#define FPL__FUNC_X11_XInitThreads(name) Status name(void)
8621typedef FPL__FUNC_X11_XInitThreads(fpl__func_x11_XInitThreads);
8622#define FPL__FUNC_X11_XSetErrorHandler(name) XErrorHandler name(XErrorHandler *handler)
8623typedef FPL__FUNC_X11_XSetErrorHandler(fpl__func_x11_XSetErrorHandler);
8625typedef struct fpl__X11Api {
8627 fpl__func_x11_XFlush *XFlush;
8628 fpl__func_x11_XFree *XFree;
8629 fpl__func_x11_XOpenDisplay *XOpenDisplay;
8630 fpl__func_x11_XCloseDisplay *XCloseDisplay;
8631 fpl__func_x11_XDefaultScreen *XDefaultScreen;
8632 fpl__func_x11_XRootWindow *XRootWindow;
8633 fpl__func_x11_XCreateWindow *XCreateWindow;
8634 fpl__func_x11_XDestroyWindow *XDestroyWindow;
8635 fpl__func_x11_XCreateColormap *XCreateColormap;
8636 fpl__func_x11_XFreeColormap *XFreeColormap;
8637 fpl__func_x11_XDefaultColormap *XDefaultColormap;
8638 fpl__func_x11_XMapWindow *XMapWindow;
8639 fpl__func_x11_XUnmapWindow *XUnmapWindow;
8640 fpl__func_x11_XStoreName *XStoreName;
8641 fpl__func_x11_XDefaultVisual *XDefaultVisual;
8642 fpl__func_x11_XDefaultDepth *XDefaultDepth;
8643 fpl__func_x11_XInternAtom *XInternAtom;
8644 fpl__func_x11_XSetWMProtocols *XSetWMProtocols;
8645 fpl__func_x11_XPending *XPending;
8646 fpl__func_x11_XSync *XSync;
8647 fpl__func_x11_XNextEvent *XNextEvent;
8648 fpl__func_x11_XPeekEvent *XPeekEvent;
8649 fpl__func_x11_XEventsQueued *XEventsQueued;
8650 fpl__func_x11_XGetWindowAttributes *XGetWindowAttributes;
8651 fpl__func_x11_XResizeWindow *XResizeWindow;
8652 fpl__func_x11_XMoveWindow *XMoveWindow;
8653 fpl__func_x11_XGetKeyboardMapping *XGetKeyboardMapping;
8654 fpl__func_x11_XLookupString *XLookupString;
8655 fpl__func_x11_XSendEvent *XSendEvent;
8656 fpl__func_x11_XMatchVisualInfo *XMatchVisualInfo;
8657 fpl__func_x11_XCreateGC *XCreateGC;
8658 fpl__func_x11_XGetImage *XGetImage;
8659 fpl__func_x11_XPutImage *XPutImage;
8660 fpl__func_x11_XMapRaised *XMapRaised;
8661 fpl__func_x11_XCreateImage *XCreateImage;
8662 fpl__func_x11_XCreatePixmap *XCreatePixmap;
8663 fpl__func_x11_XSelectInput *XSelectInput;
8664 fpl__func_x11_XGetWindowProperty *XGetWindowProperty;
8665 fpl__func_x11_XChangeProperty *XChangeProperty;
8666 fpl__func_x11_XDeleteProperty *XDeleteProperty;
8667 fpl__func_x11_XStringListToTextProperty *XStringListToTextProperty;
8668 fpl__func_x11_XSetWMIconName *XSetWMIconName;
8669 fpl__func_x11_XSetWMName *XSetWMName;
8670 fpl__func_x11_XQueryKeymap *XQueryKeymap;
8671 fpl__func_x11_XQueryPointer *XQueryPointer;
8672 fpl__func_x11_XConvertSelection *XConvertSelection;
8673 fpl__func_x11_XInitThreads *XInitThreads;
8674 fpl__func_x11_XSetErrorHandler *XSetErrorHandler;
8677fpl_internal void fpl__UnloadX11Api(fpl__X11Api *x11Api) {
8679 if (x11Api->libHandle !=
fpl_null) {
8680 dlclose(x11Api->libHandle);
8685fpl_internal bool fpl__LoadX11Api(fpl__X11Api *x11Api) {
8687 const char *libFileNames[] = {
8693 bool result =
false;
8694 for (uint32_t index = 0; index <
fplArrayCount(libFileNames); ++index) {
8695 const char *libName = libFileNames[index];
8699 FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_X11, libHandle, libName);
8700 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XFlush, XFlush);
8701 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XFree, XFree);
8702 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XOpenDisplay, XOpenDisplay);
8703 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCloseDisplay, XCloseDisplay);
8704 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultScreen, XDefaultScreen);
8705 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XRootWindow, XRootWindow);
8706 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateWindow, XCreateWindow);
8707 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDestroyWindow, XDestroyWindow);
8708 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateColormap, XCreateColormap);
8709 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XFreeColormap, XFreeColormap);
8710 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultColormap, XDefaultColormap);
8711 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMapWindow, XMapWindow);
8712 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XUnmapWindow, XUnmapWindow);
8713 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XStoreName, XStoreName);
8714 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultVisual, XDefaultVisual);
8715 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultDepth, XDefaultDepth);
8716 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XInternAtom, XInternAtom);
8717 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetWMProtocols, XSetWMProtocols);
8718 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XPending, XPending);
8719 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSync, XSync);
8720 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XNextEvent, XNextEvent);
8721 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XPeekEvent, XPeekEvent);
8722 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XEventsQueued, XEventsQueued);
8723 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetWindowAttributes, XGetWindowAttributes);
8724 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XResizeWindow, XResizeWindow);
8725 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMoveWindow, XMoveWindow);
8726 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetKeyboardMapping, XGetKeyboardMapping);
8727 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XLookupString, XLookupString);
8728 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSendEvent, XSendEvent);
8729 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMatchVisualInfo, XMatchVisualInfo);
8730 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateGC, XCreateGC);
8731 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetImage, XGetImage);
8732 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XPutImage, XPutImage);
8733 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMapRaised, XMapRaised);
8734 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateImage, XCreateImage);
8735 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreatePixmap, XCreatePixmap);
8736 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSelectInput, XSelectInput);
8737 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetWindowProperty, XGetWindowProperty);
8738 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XChangeProperty, XChangeProperty);
8739 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDeleteProperty, XDeleteProperty);
8740 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XStringListToTextProperty, XStringListToTextProperty);
8741 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetWMIconName, XSetWMIconName);
8742 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetWMName, XSetWMName);
8743 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XQueryKeymap, XQueryKeymap);
8744 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XQueryPointer, XQueryPointer);
8745 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XConvertSelection, XConvertSelection);
8746 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XInitThreads, XInitThreads);
8747 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetErrorHandler, XSetErrorHandler);
8748 x11Api->libHandle = libHandle;
8754 fpl__UnloadX11Api(x11Api);
8759typedef struct fpl__X11SubplatformState {
8761} fpl__X11SubplatformState;
8763typedef struct fpl__X11WindowStateInfo {
8768} fpl__X11WindowStateInfo;
8770typedef struct fpl__X11Xdnd {
8776#define FPL__FUNC_X11_ErrorHandlerCallback(name) int name(Display *display, XErrorEvent *ev)
8777typedef FPL__FUNC_X11_ErrorHandlerCallback(fpl__func_X11ErrorHandlerCallback);
8779typedef struct fpl__X11WindowState {
8780 fpl__X11WindowStateInfo lastWindowStateInfo;
8783 fpl__func_X11ErrorHandlerCallback *lastErrorHandler;
8789 Atom wmDeleteWindow;
8793 Atom netWMStateFocused;
8794 Atom netWMStateFullscreen;
8795 Atom netWMStateHidden;
8796 Atom netWMStateMaximizedVert;
8797 Atom netWMStateMaximizedHorz;
8809 Atom xdndActionCopy;
8817} fpl__X11WindowState;
8819#define FPL__XDND_VERSION 5
8831#if !defined(FPL__PLATFORM_STATES_DEFINED)
8832#define FPL__PLATFORM_STATES_DEFINED
8836typedef struct fpl__PlatformInitSettings {
8838} fpl__PlatformInitSettings;
8840typedef struct fpl__PlatformInitState {
8841#if defined(FPL_SUBPLATFORM_POSIX)
8842 fpl__PosixInitState posix;
8845 fpl__PlatformInitSettings initSettings;
8850# if defined(FPL_PLATFORM_WINDOWS)
8851 fpl__Win32InitState win32;
8852# elif defined(FPL_PLATFORM_LINUX)
8853 fpl__LinuxInitState plinux;
8854# elif defined(FPL_PLATFORM_UNIX)
8855 fpl__UnixInitState punix;
8858} fpl__PlatformInitState;
8861#if defined(FPL__ENABLE_WINDOW)
8862#define FPL__MAX_EVENT_COUNT 32768
8863typedef struct fpl__EventQueue {
8865 fplEvent events[FPL__MAX_EVENT_COUNT];
8870typedef struct fpl__PlatformWindowState {
8871 fpl__EventQueue eventQueue;
8874 uint64_t keyPressTimes[256];
8878#if defined(FPL_PLATFORM_WINDOWS)
8879 fpl__Win32WindowState win32;
8881#if defined(FPL_SUBPLATFORM_X11)
8882 fpl__X11WindowState x11;
8884} fpl__PlatformWindowState;
8887#if defined(FPL__ENABLE_VIDEO)
8888typedef struct fpl__PlatformVideoState {
8891} fpl__PlatformVideoState;
8894#if defined(FPL__ENABLE_AUDIO)
8895typedef struct fpl__PlatformAudioState {
8898} fpl__PlatformAudioState;
8904typedef struct fpl__PlatformAppState fpl__PlatformAppState;
8905struct fpl__PlatformAppState {
8907#if defined(FPL_SUBPLATFORM_POSIX)
8908 fpl__PosixAppState posix;
8910#if defined(FPL_SUBPLATFORM_X11)
8911 fpl__X11SubplatformState x11;
8915#if defined(FPL__ENABLE_WINDOW)
8916 fpl__PlatformWindowState window;
8918#if defined(FPL__ENABLE_VIDEO)
8919 fpl__PlatformVideoState video;
8921#if defined(FPL__ENABLE_AUDIO)
8922 fpl__PlatformAudioState audio;
8932# if defined(FPL_PLATFORM_WINDOWS)
8933 fpl__Win32AppState win32;
8934# elif defined(FPL_PLATFORM_LINUX)
8935 fpl__LinuxAppState plinux;
8936# elif defined(FPL_PLATFORM_UNIX)
8937 fpl__UnixAppState plinux;
8945#if defined(FPL__ENABLE_WINDOW)
8946fpl_internal fplKey fpl__GetMappedKey(
const fpl__PlatformWindowState *windowState,
const uint64_t keyCode) {
8949 result = windowState->keyMap[keyCode];
8951 result = fplKey_None;
8956 fpl__PlatformAppState *appState = fpl__global__AppState;
8958 fpl__EventQueue *eventQueue = &appState->window.eventQueue;
8960 uint32_t eventCount = eventQueue->pollIndex;
8961 eventQueue->pollIndex = 0;
8962 for (
size_t eventIndex = 0; eventIndex < eventCount; ++eventIndex) {
8963 fplEvent *ev = &eventQueue->events[eventIndex];
8969 eventQueue->pushCount = 0;
8973 fpl__PlatformAppState *appState = fpl__global__AppState;
8974 bool result =
false;
8976 fpl__EventQueue *eventQueue = &appState->window.eventQueue;
8978 if (eventQueue->pollIndex < eventQueue->pushCount) {
8979 uint32_t eventIndex = eventQueue->pollIndex++;
8980 *ev = eventQueue->events[eventIndex];
8982 }
else if (eventQueue->pushCount > 0) {
8983 eventQueue->pollIndex = 0;
8984 eventQueue->pushCount = 0;
8991 fpl__PlatformAppState *appState = fpl__global__AppState;
8993 fpl__EventQueue *eventQueue = &appState->window.eventQueue;
8995 if (eventQueue->pushCount < FPL__MAX_EVENT_COUNT) {
8996 uint32_t eventIndex = eventQueue->pushCount++;
8997 eventQueue->events[eventIndex] = *event;
9005 fpl__PushInternalEvent(&newEvent);
9014 fpl__PushInternalEvent(&newEvent);
9023 fpl__PushInternalEvent(&newEvent);
9026fpl_internal void fpl__PushWindowDropFilesEvent(
const char *filePath,
const size_t fileCount,
const char **files,
const fplMemoryBlock *memory) {
9033 fpl__PushInternalEvent(&newEvent);
9044 fpl__PushInternalEvent(&newEvent);
9047fpl_internal void fpl__PushKeyboardInputEvent(
const uint32_t textCode,
const fplKey mappedKey) {
9053 fpl__PushInternalEvent(&newEvent);
9064 fpl__PushInternalEvent(&newEvent);
9067fpl_internal void fpl__PushMouseWheelEvent(
const int32_t x,
const int32_t y,
const float wheelDelta) {
9075 fpl__PushInternalEvent(&newEvent);
9078fpl_internal void fpl__PushMouseMoveEvent(
const int32_t x,
const int32_t y) {
9085 fpl__PushInternalEvent(&newEvent);
9089#if defined(FPL_LOG_KEY_EVENTS)
9090 const char *buttonStateName =
"";
9092 buttonStateName =
"Press";
9094 buttonStateName =
"Repeat";
9096 buttonStateName =
"Released";
9097 FPL_LOG_INFO(FPL__MODULE_OS,
"[%llu] Keyboard button event with keycode: '%llu', state: '%s'", time, keyCode, buttonStateName);
9100 fplKey mappedKey = fpl__GetMappedKey(windowState, keyCode);
9101 bool repeat =
false;
9104 windowState->keyStates[keyCode] = buttonState;
9113 windowState->keyStates[keyCode] = buttonState;
9116 fpl__PushKeyboardButtonEvent(keyCode, mappedKey, modifiers, repeat ?
fplButtonState_Repeat : buttonState);
9119fpl_internal void fpl__HandleKeyboardInputEvent(fpl__PlatformWindowState *windowState,
const uint64_t keyCode,
const uint32_t textCode) {
9120 fplKey mappedKey = fpl__GetMappedKey(windowState, keyCode);
9121 fpl__PushKeyboardInputEvent(textCode, mappedKey);
9125 if (mouseButton <
fplArrayCount(windowState->mouseStates)) {
9126 windowState->mouseStates[(int)mouseButton] = buttonState;
9128 fpl__PushMouseButtonEvent(x, y, mouseButton, buttonState);
9131fpl_internal void fpl__HandleMouseMoveEvent(fpl__PlatformWindowState *windowState,
const int32_t x,
const int32_t y) {
9132 fpl__PushMouseMoveEvent(x, y);
9135fpl_internal void fpl__HandleMouseWheelEvent(fpl__PlatformWindowState *windowState,
const int32_t x,
const int32_t y,
const float wheelDelta) {
9136 fpl__PushMouseWheelEvent(x, y, wheelDelta);
9140#define FPL__FUNC_PREPARE_VIDEO_WINDOW(name) bool name(fpl__PlatformAppState *appState, const fplInitFlags initFlags, const fplSettings *initSettings)
9141typedef FPL__FUNC_PREPARE_VIDEO_WINDOW(callback_PreSetupWindow);
9144#define FPL__FUNC_FINALIZE_VIDEO_WINDOW(name) bool name(fpl__PlatformAppState *appState, const fplInitFlags initFlags, const fplSettings *initSettings)
9145typedef FPL__FUNC_FINALIZE_VIDEO_WINDOW(callback_PostSetupWindow);
9147typedef struct fpl__SetupWindowCallbacks {
9148 callback_PreSetupWindow *preSetup;
9149 callback_PostSetupWindow *postSetup;
9150} fpl__SetupWindowCallbacks;
9167#if !defined(FPL__COMMON_DEFINED)
9168#define FPL__COMMON_DEFINED
9173fpl_internal void *fpl__AllocateDynamicMemory(
const size_t size,
const size_t alignment) {
9174 void *result = fpl__AllocateMemory(&fpl__global__InitState.initSettings.memorySettings.dynamic, size, alignment);
9178fpl_internal void fpl__ReleaseDynamicMemory(
void *ptr) {
9179 fpl__ReleaseMemory(&fpl__global__InitState.initSettings.memorySettings.dynamic, ptr);
9182fpl_internal void *fpl__AllocateTemporaryMemory(
const size_t size,
const size_t alignment) {
9183 void *result = fpl__AllocateMemory(&fpl__global__InitState.initSettings.memorySettings.temporary, size, alignment);
9187fpl_internal void fpl__ReleaseTemporaryMemory(
void *ptr) {
9188 fpl__ReleaseMemory(&fpl__global__InitState.initSettings.memorySettings.temporary, ptr);
9194static const uint32_t FPL__DEFAULT_AUDIO_SAMPLERATE = 44100;
9196static const uint32_t FPL__DEFAULT_AUDIO_CHANNELS = 2;
9197static const uint32_t FPL__DEFAULT_AUDIO_PERIODS = 3;
9198static const uint32_t FPL__DEFAULT_AUDIO_BUFFERSIZE_LOWLATENCY_IN_MSECS = 10;
9199static const uint32_t FPL__DEFAULT_AUDIO_BUFFERSIZE_CONSERVATIVE_IN_MSECS = 25;
9204#define FPL__MAX_LAST_ERROR_STRING_LENGTH 256
9205#define FPL__MAX_ERRORSTATE_COUNT 256
9207typedef struct fpl__ErrorState {
9208 char errors[FPL__MAX_ERRORSTATE_COUNT][FPL__MAX_LAST_ERROR_STRING_LENGTH];
9214fpl_internal void fpl__PushError_Formatted(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, va_list argList) {
9218 fpl__ErrorState *state = &fpl__global__LastErrorState;
9219 char buffer[FPL__MAX_LAST_ERROR_STRING_LENGTH] =
fplZeroInit;
9221 if (formattedLen > 0) {
9222 fplAssert(state->count < FPL__MAX_ERRORSTATE_COUNT);
9223 size_t errorIndex = state->count;
9224 state->count = (state->count + 1) % FPL__MAX_ERRORSTATE_COUNT;
9225 fplCopyStringLen(buffer, formattedLen, state->errors[errorIndex], FPL__MAX_LAST_ERROR_STRING_LENGTH);
9229#if defined(FPL__ENABLE_LOGGING)
9231 va_copy(listCopy, argList);
9232 fpl__LogWriteArgs(funcName, lineNumber, level, format, listCopy);
9237fpl_internal void fpl__HandleError(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, ...) {
9239 va_start(valist, format);
9240 fpl__PushError_Formatted(funcName, lineNumber, level, format, valist);
9243#if defined(FPL_CRASH_ON_ERROR) || defined(FPL_CRASH_ON_WARNING)
9245# if defined(FPL_CRASH_ON_WARNING)
9248 if (level >= minErrorLevel) {
9262fpl_internal void fpl__ArgumentInvalidError(
const char *funcName,
const int line,
const char *paramName) {
9263 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter are not valid", paramName);
9265fpl_internal void fpl__ArgumentNullError(
const char *funcName,
const int line,
const char *paramName) {
9266 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter are not allowed to be null", paramName);
9268fpl_internal void fpl__ArgumentZeroError(
const char *funcName,
const int line,
const char *paramName) {
9269 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter must be greater than zero", paramName);
9271fpl_internal void fpl__ArgumentMinError(
const char *funcName,
const int line,
const char *paramName,
const size_t value,
const size_t minValue) {
9272 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter '%zu' must be greater or equal than '%zu'", paramName, value, minValue);
9274fpl_internal void fpl__ArgumentMaxError(
const char *funcName,
const int line,
const char *paramName,
const size_t value,
const size_t maxValue) {
9275 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter '%zu' must be less or equal than '%zu'", paramName, value, maxValue);
9277fpl_internal void fpl__ArgumentRangeError(
const char *funcName,
const int line,
const char *paramName,
const size_t value,
const size_t minValue,
const size_t maxValue) {
9278 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter '%zu' must be in range of '%zu' to '%zu'", paramName, value, minValue, maxValue);
9281#define FPL__CheckArgumentInvalid(arg, cond, ret) \
9283 fpl__ArgumentInvalidError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9287#define FPL__CheckArgumentInvalidNoRet(arg, cond) \
9289 fpl__ArgumentInvalidError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9292#define FPL__CheckArgumentNull(arg, ret) \
9293 if((arg) == fpl_null) { \
9294 fpl__ArgumentNullError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9297#define FPL__CheckArgumentNullNoRet(arg) \
9298 if((arg) == fpl_null) { \
9299 fpl__ArgumentNullError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9302#define FPL__CheckArgumentZero(arg, ret) \
9304 fpl__ArgumentZeroError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9307#define FPL__CheckArgumentZeroNoRet(arg) \
9309 fpl__ArgumentZeroError(FPL_FUNCTION_NAME, __LINE__, #arg); \
9312#define FPL__CheckArgumentMin(arg, minValue, ret) \
9313 if((arg) < (minValue)) { \
9314 fpl__ArgumentMinError(FPL_FUNCTION_NAME, __LINE__, #arg, arg, minValue); \
9317#define FPL__CheckArgumentMax(arg, maxValue, ret) \
9318 if((arg) > (maxValue)) { \
9319 fpl__ArgumentMaxError(FPL_FUNCTION_NAME, __LINE__, #arg, arg, maxValue); \
9322#define FPL__CheckPlatform(ret) \
9323 if(fpl__global__AppState == fpl_null) { \
9324 FPL__ERROR(FPL__MODULE_CORE, "[%s] Platform is not initialized", FPL_FUNCTION_NAME); \
9327#define FPL__CheckPlatformNoRet() \
9328 if(fpl__global__AppState == fpl_null) { \
9329 FPL__ERROR(FPL__MODULE_CORE, "[%s] Platform is not initialized", FPL_FUNCTION_NAME); \
9333#define FPL__CheckApi(cond, name, ret) \
9335 FPL__ERROR(FPL__MODULE_API, "The API '%s' is not loaded", (name)); \
9338#define FPL__CheckApiNoRet(cond, name) \
9340 FPL__ERROR(FPL__MODULE_API, "The API '%s' is not loaded", (name)); \
9344#if !defined(FPL_MAX_THREAD_COUNT)
9346# define FPL_MAX_THREAD_COUNT 256
9349#if !defined(FPL_MAX_SIGNAL_COUNT)
9351# define FPL_MAX_SIGNAL_COUNT 256
9354typedef struct fpl__ThreadState {
9363 for (uint32_t index = 0; index < FPL_MAX_THREAD_COUNT; ++index) {
9374fpl_internal bool fpl__IsEqualsMemory(
const void *a,
const void *b,
const size_t size) {
9375 const uint8_t *ptrA = (
const uint8_t *)a;
9376 const uint8_t *ptrB = (
const uint8_t *)b;
9382 if (*ptrA != *ptrB) {
9390 result = memcmp(a, b, size) == 0;
9395fpl_internal bool fpl__IsZeroMemory(
const void *memory,
const size_t size) {
9396 const uint8_t *ptr = (
const uint8_t *)memory;
9409 result = memcmp(a, b, size) == 0;
9417#if !defined(FPL__COMMON_STRINGS_DEFINED)
9418#define FPL__COMMON_STRINGS_DEFINED
9427 const char *s = source;
9428 const char *w = wildcard;
9435 }
else if (*w ==
'*') {
9439 if ((*s == nw) || (nw ==
'?') || (nw ==
'*')) {
9464 for (
size_t index = 0; index < aLen; ++index) {
9465 char aChar = a[index];
9466 char bChar = b[index];
9467 if (aChar != bChar) {
9481 const char aChar = *(a++);
9482 const char bChar = *(b++);
9483 if (aChar == 0 || bChar == 0) {
9484 result = (aChar == bChar);
9487 if (aChar != bChar) {
9496 FPL__CheckArgumentNull(path,
fpl_null);
9497 FPL__CheckArgumentZero(maxPathLen,
fpl_null);
9502 size_t len = end - path;
9506 if (len + 1 <= maxPathLen) {
9509 result = &path[len + 1];
9511 FPL__ERROR(FPL__MODULE_PATHS,
"Cannot append path separator: Max length '%zu' of path '%s' is exceeded", maxPathLen, path);
9514 result = &path[len];
9521 FPL__CheckArgumentNull(path,
fpl_null);
9526 size_t len = end - path;
9532 result = &path[len + 1];
9534 result = &path[len];
9541 FPL__CheckArgumentNull(appended,
fpl_null);
9542 FPL__CheckArgumentZero(maxBufferLen,
fpl_null);
9543 if (appendedLen == 0) {
9547 size_t requiredSize = curBufferLen + appendedLen + 1;
9548 FPL__CheckArgumentMin(maxBufferLen, requiredSize,
fpl_null);
9549 char *start = buffer + curBufferLen;
9550 size_t remainingBufferSize = maxBufferLen - (curBufferLen > 0 ? curBufferLen + 1 : 0);
9551 char *result =
fplCopyStringLen(appended, appendedLen, start, remainingBufferSize);
9562 uint32_t result = 0;
9573 size_t requiredLen = sourceLen + 1;
9574 FPL__CheckArgumentMin(maxDestLen, requiredLen,
fpl_null);
9576 char *result = dest + sourceLen;
9594 FPL__CheckArgumentNull(format, 0);
9597 va_copy(listCopy, argList);
9601 FPL__CheckArgumentMin(maxDestBufferLen, 1, 0);
9606# if defined(FPL_NO_CRT)
9607# if defined(FPL_USERFUNC_vsnprintf)
9608 charCount = FPL_USERFUNC_vsnprintf(destBuffer, maxDestBufferLen, format, listCopy);
9613 charCount = vsnprintf(destBuffer, maxDestBufferLen, format, listCopy);
9615 if (charCount < 0) {
9616 FPL__ERROR(FPL__MODULE_STRINGS,
"Format parameter are '%s' are invalid", format);
9619 size_t result = charCount;
9621 size_t requiredMaxDestBufferLen = charCount + 1;
9622 FPL__CheckArgumentMin(maxDestBufferLen, requiredMaxDestBufferLen, 0);
9623 destBuffer[charCount] = 0;
9630 FPL__CheckArgumentNull(format, 0);
9632 va_start(argList, format);
9641 bool isNegative =
false;
9648 size_t digitCount = 0;
9654 size_t result = digitCount + (isNegative ? 1 : 0);
9657 size_t requiredLen = result + 1;
9658 FPL__CheckArgumentMin(maxBufferLen, requiredLen, 0);
9667 const char *digits =
"0123456789";
9670 *--p = digits[tmp % 10];
9681 FPL__CheckArgumentNull(str, 0);
9682 FPL__CheckArgumentZero(len, 0);
9683 const char *p = str;
9684 bool isNegative =
false;
9693 while (*p && ((
size_t)(p - str) < len)) {
9695 if (c <
'0' || c >
'9') {
9698 int v = (int)(*p -
'0');
9700 value += (uint32_t)v;
9703 int32_t result = isNegative ? -(int32_t)value : (int32_t)value;
9717#if !defined(FPL__COMMON_CONSOLE_DEFINED)
9718#define FPL__COMMON_CONSOLE_DEFINED
9721 FPL__CheckArgumentNullNoRet(format);
9724 va_start(argList, format);
9733 FPL__CheckArgumentNullNoRet(format);
9736 va_start(argList, format);
9748#if !defined(FPL__COMMON_MEMORY_DEFINED)
9749#define FPL__COMMON_MEMORY_DEFINED
9752 FPL__CheckArgumentZero(size,
fpl_null);
9753 FPL__CheckArgumentZero(alignment,
fpl_null);
9754 if (alignment & (alignment - 1)) {
9755 FPL__ERROR(FPL__MODULE_MEMORY,
"Alignment parameter '%zu' must be a power of two", alignment);
9759 size_t newSize =
sizeof(
void *) + (alignment << 1) + size;
9762 void *alignedPtr = (
void *)((uint8_t *)basePtr +
sizeof(
void *));
9764 uintptr_t mask = alignment - 1;
9765 if ((alignment > 1) && (((uintptr_t)alignedPtr & mask) != 0)) {
9766 uintptr_t offset = ((uintptr_t)alignment - ((uintptr_t)alignedPtr & mask));
9767 alignedPtr = (uint8_t *)alignedPtr + offset;
9770 *(
void **)((
void *)((uint8_t *)alignedPtr -
sizeof(
void *))) = basePtr;
9777 FPL__CheckArgumentNullNoRet(ptr);
9779 void *basePtr = *(
void **)((
void *)((uint8_t *)ptr -
sizeof(
void *)));
9784#define FPL__MEM_SHIFT_64 3
9785#define FPL__MEM_MASK_64 0x00000007
9786#define FPL__MEM_SHIFT_32 2
9787#define FPL__MEM_MASK_32 0x00000003
9788#define FPL__MEM_SHIFT_16 1
9789#define FPL__MEM_MASK_16 0x0000000
9792#define FPL__MEMORY_SET(T, memory, size, shift, mask, value) \
9794 size_t setBytes = 0; \
9795 if (sizeof(T) > sizeof(uint8_t)) { \
9797 for (int bytesIncrement = 0; bytesIncrement < sizeof(T); ++bytesIncrement) { \
9798 int bitShift = bytesIncrement * 8; \
9799 setValue |= ((T)value << bitShift); \
9801 T *dataBlock = (T *)(memory); \
9802 T *dataBlockEnd = (T *)(memory) + (size >> shift); \
9803 while (dataBlock < dataBlockEnd) { \
9804 *dataBlock++ = setValue; \
9805 setBytes += sizeof(T); \
9808 uint8_t *data8 = (uint8_t *)memory + setBytes; \
9809 uint8_t *data8End = (uint8_t *)memory + size; \
9810 while (data8 < data8End) { \
9815#define FPL__MEMORY_CLEAR(T, memory, size, shift, mask) \
9817 size_t clearBytes = 0; \
9818 if (sizeof(T) > sizeof(uint8_t)) { \
9819 T *dataBlock = (T *)(memory); \
9820 T *dataBlockEnd = (T *)(memory) + (size >> shift); \
9821 while (dataBlock < dataBlockEnd) { \
9823 clearBytes += sizeof(T); \
9826 uint8_t *data8 = (uint8_t *)memory + clearBytes; \
9827 uint8_t *data8End = (uint8_t *)memory + size; \
9828 while (data8 < data8End) { \
9833#define FPL__MEMORY_COPY(T, source, sourceSize, dest, shift, mask) \
9835 size_t copiedBytes = 0; \
9836 if (sizeof(T) > sizeof(uint8_t)) { \
9837 const T *sourceDataBlock = (const T *)(source); \
9838 const T *sourceDataBlockEnd = (const T *)(source) + (sourceSize >> shift); \
9839 T *destDataBlock = (T *)(dest); \
9840 while (sourceDataBlock < sourceDataBlockEnd) { \
9841 *destDataBlock++ = *sourceDataBlock++; \
9842 copiedBytes += sizeof(T); \
9845 const uint8_t *sourceData8 = (const uint8_t *)source + copiedBytes; \
9846 const uint8_t *sourceData8End = (const uint8_t *)source + sourceSize; \
9847 uint8_t *destData8 = (uint8_t *)dest + copiedBytes; \
9848 while (sourceData8 < sourceData8End) { \
9849 *destData8++ = *sourceData8++; \
9854 FPL__CheckArgumentNullNoRet(mem);
9855 FPL__CheckArgumentZeroNoRet(size);
9856#if defined(FPL__ENABLE_MEMORY_MACROS)
9857 if (size % 8 == 0) {
9858 FPL__MEMORY_SET(uint64_t, mem, size, FPL__MEM_SHIFT_64, FPL__MEM_MASK_64, value);
9859 }
else if (size % 4 == 0) {
9860 FPL__MEMORY_SET(uint32_t, mem, size, FPL__MEM_SHIFT_32, FPL__MEM_MASK_32, value);
9861 }
else if (size % 2 == 0) {
9862 FPL__MEMORY_SET(uint16_t, mem, size, FPL__MEM_SHIFT_16, FPL__MEM_MASK_16, value);
9864 FPL__MEMORY_SET(uint8_t, mem, size, 0, 0, value);
9866#elif defined(FPL_PLATFORM_WINDOWS)
9867 FillMemory(mem, size, value);
9869 memset(mem, value, size);
9874 FPL__CheckArgumentNullNoRet(mem);
9875 FPL__CheckArgumentZeroNoRet(size);
9876#if defined(FPL__ENABLE_MEMORY_MACROS)
9877 if (size % 8 == 0) {
9878 FPL__MEMORY_CLEAR(uint64_t, mem, size, FPL__MEM_SHIFT_64, FPL__MEM_MASK_64);
9879 }
else if (size % 4 == 0) {
9880 FPL__MEMORY_CLEAR(uint32_t, mem, size, FPL__MEM_SHIFT_32, FPL__MEM_MASK_32);
9881 }
else if (size % 2 == 0) {
9882 FPL__MEMORY_CLEAR(uint16_t, mem, size, FPL__MEM_SHIFT_16, FPL__MEM_MASK_16);
9884 FPL__MEMORY_CLEAR(uint8_t, mem, size, 0, 0);
9886#elif defined(FPL_PLATFORM_WINDOWS)
9887 ZeroMemory(mem, size);
9889 memset(mem, 0, size);
9894 FPL__CheckArgumentNullNoRet(sourceMem);
9895 FPL__CheckArgumentZeroNoRet(sourceSize);
9896 FPL__CheckArgumentNullNoRet(targetMem);
9897#if defined(FPL__ENABLE_MEMORY_MACROS)
9898 if (sourceSize % 8 == 0) {
9899 FPL__MEMORY_COPY(uint64_t, sourceMem, sourceSize, targetMem, FPL__MEM_SHIFT_64, FPL__MEM_MASK_64);
9900 }
else if (sourceSize % 4 == 0) {
9901 FPL__MEMORY_COPY(uint32_t, sourceMem, sourceSize, targetMem, FPL__MEM_SHIFT_32, FPL__MEM_MASK_32);
9902 }
else if (sourceSize % 2 == 0) {
9903 FPL__MEMORY_COPY(uint16_t, sourceMem, sourceSize, targetMem, FPL__MEM_SHIFT_16, FPL__MEM_MASK_16);
9905 FPL__MEMORY_COPY(uint8_t, sourceMem, sourceSize, targetMem, 0, 0);
9907#elif defined(FPL_PLATFORM_WINDOWS)
9908 CopyMemory(targetMem, sourceMem, sourceSize);
9910 memcpy(targetMem, sourceMem, sourceSize);
9923#if defined(FPL_ARCH_X64) || defined(FPL_ARCH_X86)
9925# define FPL__CPU_BRAND_BUFFER_SIZE 0x40
9927# if defined(FPL_COMPILER_MSVC)
9930# if _MSC_VER >= 1400
9931# define fpl__m_CPUID(outLeaf, functionId) __cpuid((int *)(outLeaf)->raw, (int)(functionId))
9933# if _MSC_VER >= 1600
9934# define fpl__m_GetXCR0() ((uint64_t)_xgetbv(0))
9938# define fpl__m_RDTSC() ((uint64_t)__rdtsc())
9940# elif defined(FPL_COMPILER_GCC) ||defined(FPL_COMPILER_CLANG)
9944 int eax = 0, ebx = 0, ecx = 0, edx = 0;
9945 __cpuid_count(functionId, 0, eax, ebx, ecx, edx);
9955 __asm(
".byte 0x0F, 0x01, 0xd0" :
"=a"(eax),
"=d"(edx) :
"c"(0));
9960# if defined(FPL_ARCH_X86)
9962 unsigned long long int result;
9963 __asm__
volatile (
".byte 0x0f, 0x31" :
"=A" (result));
9964 return((uint64_t)result);
9966# elif defined(FPL_ARCH_X64)
9969 __asm__ __volatile__(
"rdtsc" :
"=a"(lo),
"=d"(hi));
9970 uint64_t result = (uint64_t)(((
unsigned long long)lo) | (((
unsigned long long)hi) << 32));
9977#if defined(fpl__m_CPUID)
9978 fpl__m_CPUID(outLeaf, functionId);
9983#if defined(fpl__m_GetXCR0)
9984 uint64_t result = fpl__m_GetXCR0();
9992#if defined(fpl__m_RDTSC)
9993 uint64_t result = fpl__m_RDTSC();
10008 uint32_t maxFunctionId = info0.
eax;
10010 if (1 <= maxFunctionId) {
10014 if (7 <= maxFunctionId) {
10019 uint64_t xcr0 = hasXSave ?
fplCPUXCR0() : 0;
10021 const uint32_t MASK_XMM = 0x2;
10022 const uint32_t MASK_YMM = 0x4;
10023 const uint32_t MASK_MASKREG = 0x20;
10024 const uint32_t MASK_ZMM0_15 = 0x40;
10025 const uint32_t MASK_ZMM16_31 = 0x80;
10027 const uint32_t MASK_SSE = MASK_XMM;
10028 const uint32_t MASK_AVX = MASK_XMM | MASK_YMM;
10029 const uint32_t MASK_AVX_512 = MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 | MASK_ZMM16_31;
10031 bool hasSSESupport = (xcr0 & MASK_SSE) == MASK_SSE;
10032 bool hasAVXSupport = (xcr0 & MASK_AVX) == MASK_AVX;
10033 bool hasAVX512Support = (xcr0 & MASK_AVX_512) == MASK_AVX_512;
10037 if (hasSSESupport) {
10046 if (hasAVXSupport) {
10051 if (hasAVX512Support) {
10062 uint32_t extendedIds = cpuInfo.
eax;
10065 char cpuBrandBuffer[FPL__CPU_BRAND_BUFFER_SIZE] =
fplZeroInit;
10066 uint32_t max =
fplMin(extendedIds, 0x80000004);
10067 for (uint32_t i = 0x80000002; i <= max; ++i) {
10069 uint32_t offset = (i - 0x80000002) << 4;
10076 size_t requiredDestBufferLen = result + 1;
10077 FPL__CheckArgumentMin(maxDestBufferLen, requiredDestBufferLen, 0);
10087#if defined(FPL_ARCH_ARM64)
10088 int64_t virtual_timer_value;
10089 fplAsm volatile(
"mrs %0, cntvct_el0" :
"=r"(virtual_timer_value));
10090 return (uint64_t)virtual_timer_value;
10091#elif defined(FPL_ARCH_ARM32) && (__ARM_ARCH >= 6)
10094 uint32_t pmcntenset;
10096 fplAsm volatile(
"mrc p15, 0, %0, c9, c14, 0" :
"=r"(pmuseren));
10097 if (pmuseren & 1) {
10099 fplAsm volatile(
"mrc p15, 0, %0, c9, c12, 1" :
"=r"(pmcntenset));
10100 if (pmcntenset & 0x80000000ul) {
10102 fplAsm volatile(
"mrc p15, 0, %0, c9, c13, 0" :
"=r"(pmccntr));
10104 return (uint64_t)pmccntr * 64ULL;
10110 return (uint64_t)tv.tv_sec * 1000000ULL + (uint64_t)tv.tv_usec;
10137#if !defined(FPL__COMMON_ATOMICS_DEFINED)
10138#define FPL__COMMON_ATOMICS_DEFINED
10142#if defined(FPL_CPU_64BIT)
10144#elif defined(FPL_CPU_32BIT)
10147# error "Unsupported architecture/platform!"
10154#if defined(FPL_CPU_64BIT)
10156#elif defined(FPL_CPU_32BIT)
10159# error "Unsupported architecture/platform!"
10166#if defined(FPL_CPU_64BIT)
10168#elif defined(FPL_CPU_32BIT)
10171# error "Unsupported architecture/platform!"
10178#if defined(FPL_CPU_64BIT)
10180#elif defined(FPL_CPU_32BIT)
10183# error "Unsupported architecture/platform!"
10190#if defined(FPL_CPU_64BIT)
10192#elif defined(FPL_CPU_32BIT)
10195# error "Unsupported architecture/platform!"
10202#if defined(FPL_CPU_64BIT)
10204#elif defined(FPL_CPU_32BIT)
10207# error "Unsupported architecture/platform!"
10214#if defined(FPL_CPU_64BIT)
10216#elif defined(FPL_CPU_32BIT)
10219# error "Unsupported architecture/platform!"
10225#if defined(FPL_CPU_64BIT)
10227#elif defined(FPL_CPU_32BIT)
10230# error "Unsupported architecture/platform!"
10237#if defined(FPL_CPU_64BIT)
10239#elif defined(FPL_CPU_32BIT)
10242# error "Unsupported architecture/platform!"
10248#if defined(FPL_CPU_64BIT)
10250#elif defined(FPL_CPU_32BIT)
10253# error "Unsupported architecture/platform!"
10260#if defined(FPL_CPU_64BIT)
10262#elif defined(FPL_CPU_32BIT)
10265# error "Unsupported architecture/platform!"
10271#if defined(FPL_CPU_64BIT)
10273#elif defined(FPL_CPU_32BIT)
10276# error "Unsupported architecture/platform!"
10282#if defined(FPL_CPU_64BIT)
10284#elif defined(FPL_CPU_32BIT)
10287# error "Unsupported architecture/platform!"
10292#if defined(FPL_CPU_64BIT)
10294#elif defined(FPL_CPU_32BIT)
10297# error "Unsupported architecture/platform!"
10302#if defined(FPL_CPU_64BIT)
10304#elif defined(FPL_CPU_32BIT)
10307# error "Unsupported architecture/platform!"
10312#if defined(FPL_CPU_64BIT)
10314#elif defined(FPL_CPU_32BIT)
10317# error "Unsupported architecture/platform!"
10335 const fplThreadHandle *result = &fpl__global__ThreadState.mainThread;
10341 for (
size_t threadIndex = 0; threadIndex < FPL_MAX_THREAD_COUNT; ++threadIndex) {
10352 for (
size_t threadIndex = 0; threadIndex < FPL_MAX_THREAD_COUNT; ++threadIndex) {
10364#if !defined(FPL__COMMON_FILES_DEFINED)
10365#define FPL__COMMON_FILES_DEFINED
10368#if defined(FPL_CPU_64BIT)
10369 return fplFileReadBlock64(fileHandle, sizeToRead, targetBuffer, maxTargetBufferSize);
10371 return fplFileReadBlock32(fileHandle, (uint32_t)sizeToRead, targetBuffer, (uint32_t)maxTargetBufferSize);
10376#if defined(FPL_CPU_64BIT)
10384#if defined(FPL_CPU_64BIT)
10392#if defined(FPL_CPU_64BIT)
10400#if defined(FPL_CPU_64BIT)
10408#if defined(FPL_CPU_64BIT)
10420#if !defined(FPL__COMMON_PATHS_DEFINED)
10421#define FPL__COMMON_PATHS_DEFINED
10424 FPL__CheckArgumentNull(sourcePath, 0);
10427 if (sourceLen > 0) {
10429 const char *chPtr = (
const char *)sourcePath;
10432 pathLen = (int)(chPtr - sourcePath);
10438 size_t requiredDestLen = pathLen + 1;
10439 FPL__CheckArgumentMin(maxDestLen, requiredDestLen, 0);
10449 const char *chPtr = sourcePath;
10451 const char *lastPathSep =
fpl_null;
10454 lastPathSep = chPtr;
10460 chPtr = lastPathSep;
10462 chPtr = sourcePath;
10481 result = sourcePath;
10482 const char *chPtr = sourcePath;
10485 result = chPtr + 1;
10494 FPL__CheckArgumentNull(filePath, 0);
10495 FPL__CheckArgumentNull(newFileExtension, 0);
10498 FPL__CheckArgumentZero(filePathLen, 0);
10505 const char *chPtr = (
const char *)filePath;
10506 const char *lastPathSeparatorPtr =
fpl_null;
10509 lastPathSeparatorPtr = chPtr;
10514 if (lastPathSeparatorPtr !=
fpl_null) {
10515 chPtr = lastPathSeparatorPtr + 1;
10517 chPtr = (
const char *)filePath;
10519 const char *lastExtSeparatorPtr =
fpl_null;
10522 lastExtSeparatorPtr = chPtr;
10527 size_t filenameLen;
10528 if (lastExtSeparatorPtr !=
fpl_null) {
10529 filenameLen = (size_t)((uintptr_t)lastExtSeparatorPtr - (uintptr_t)filePath);
10531 filenameLen = filePathLen;
10534 result = filenameLen + extLen;
10538 size_t requiredDestLen = result + 1;
10539 FPL__CheckArgumentMin(maxDestLen, requiredDestLen, 0);
10542 char *destExtPtr = destPath + filenameLen;
10543 fplCopyStringLen(newFileExtension, extLen, destExtPtr, maxDestLen - filenameLen);
10550 FPL__CheckArgumentZero(pathCount, 0);
10554 size_t curDestPosition = 0;
10555 char *currentDestPtr = destPath;
10558 va_start(vargs, pathCount);
10559 for (
size_t pathIndex = 0; pathIndex < pathCount; ++pathIndex) {
10560 const char *path = va_arg(vargs,
const char *);
10563 bool requireSeparator = pathIndex < (pathCount - 1);
10564 size_t requiredPathLen = requireSeparator ? pathLen + 1 : pathLen;
10566 result += requiredPathLen;
10569 size_t requiredDestLen = result + 1;
10570 FPL__CheckArgumentMin(maxDestPathLen, requiredDestLen, 0);
10572 fplCopyStringLen(path, pathLen, currentDestPtr, maxDestPathLen - curDestPosition);
10573 currentDestPtr += pathLen;
10574 if (requireSeparator) {
10577 curDestPosition += requiredPathLen;
10581 *currentDestPtr = 0;
10591#if !defined(FPL__COMMON_WINDOW_DEFINED)
10592#define FPL__COMMON_WINDOW_DEFINED
10595 fpl__PlatformAppState *appState = fpl__global__AppState;
10596 char *result =
fplCopyString(appState->currentSettings.window.title, outTitle, maxOutTitleLength);
10601 FPL__CheckPlatformNoRet();
10602 fpl__PlatformAppState *appState = fpl__global__AppState;
10603 appState->currentSettings.input.disabledEvents = !enabled;
10610#if defined(FPL__ENABLE_LOGGING)
10612 FPL__CheckArgumentNullNoRet(params);
10613 fpl__global__LogSettings = *params;
10617 return &fpl__global__LogSettings;
10620 fpl__global__LogSettings.
maxLevel = maxLevel;
10623 return fpl__global__LogSettings.maxLevel;
10628 const char *result =
"";
10629 const fpl__ErrorState *errorState = &fpl__global__LastErrorState;
10630 if (errorState->count > 0) {
10631 size_t index = errorState->count - 1;
10638 const char *result =
"";
10639 const fpl__ErrorState *errorState = &fpl__global__LastErrorState;
10640 if (index < errorState->count) {
10641 result = errorState->errors[index];
10643 result = errorState->errors[errorState->count - 1];
10650 const fpl__ErrorState *errorState = &fpl__global__LastErrorState;
10651 result = errorState->count;
10656 fpl__ErrorState *errorState = &fpl__global__LastErrorState;
10662 const fpl__PlatformAppState *appState = fpl__global__AppState;
10663 return &appState->currentSettings;
10667 FPL__CheckArgumentNullNoRet(video);
10672#if defined(FPL__ENABLE_VIDEO_OPENGL)
10677#if defined(FPL__ENABLE_VIDEO_VULKAN)
10686#if defined(FPL__ENABLE_VIDEO_OPENGL)
10688#elif defined(FPL__ENABLE_VIDEO_SOFTWARE)
10690#elif defined(FPL__ENABLE_VIDEO_VULKAN)
10698 FPL__CheckArgumentNullNoRet(targetFormat);
10701#if defined(FPL__ENABLE_AUDIO)
10710 targetFormat->
type = deviceFormat.
type;
10716 FPL__CheckArgumentNullNoRet(audio);
10721# if defined(FPL_PLATFORM_WINDOWS) && defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
10724# if defined(FPL_PLATFORM_LINUX) && defined(FPL__ENABLE_AUDIO_ALSA)
10733 FPL__CheckArgumentNullNoRet(window);
10735 window->
title[0] = 0;
10749 FPL__CheckArgumentNullNoRet(console);
10751 console->
title[0] = 0;
10755 FPL__CheckArgumentNullNoRet(input);
10761 FPL__CheckArgumentNullNoRet(settings);
10775#define FPL__PLATFORMRESULTTYPE_COUNT FPL__ENUM_COUNT(fplPlatformResultType_First, fplPlatformResultType_Last)
10776fpl_globalvar const char *fpl__global_platformResultTypeNameTable[] = {
10781 "Failed Allocating Memory",
10782 "Already Initialized",
10790 const char *result = fpl__global_platformResultTypeNameTable[index];
10794#define FPL__ARCHTYPE_COUNT FPL__ENUM_COUNT(fplCPUArchType_First, fplCPUArchType_Last)
10795fpl_globalvar const char *fpl__global_ArchTypeNameTable[] = {
10807 const char *result = fpl__global_ArchTypeNameTable[index];
10814#if defined(FPL_PLATFORM_WINDOWS)
10818 OutputDebugStringW(buffer);
10830 va_start(argList, format);
10843#if defined(FPL_PLATFORM_WINDOWS)
10845# if defined(FPL_ARCH_X86)
10846# define FPL_MEMORY_BARRIER() \
10848 _InterlockedOr(&barrier, 0);
10849# elif defined(FPL_ARCH_X64)
10851# define FPL_MEMORY_BARRIER()
10854#if defined(FPL__ENABLE_WINDOW)
10857 DWORD result = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
10859 result |= WS_POPUP;
10861 result |= WS_OVERLAPPEDWINDOW;
10863 result &= ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
10870 DWORD result = WS_EX_APPWINDOW;
10872 result |= WS_EX_TOPMOST;
10877fpl_internal void fpl__Win32SaveWindowState(
const fpl__Win32Api *wapi, fpl__Win32LastWindowInfo *target, HWND windowHandle) {
10878 target->isMaximized = !!wapi->user.IsZoomed(windowHandle);
10879 target->isMinimized = !!wapi->user.IsIconic(windowHandle);
10880 target->style = fpl__win32_GetWindowLong(windowHandle, GWL_STYLE);
10881 target->exStyle = fpl__win32_GetWindowLong(windowHandle, GWL_EXSTYLE);
10882 wapi->user.GetWindowPlacement(windowHandle, &target->placement);
10885fpl_internal void fpl__Win32RestoreWindowState(
const fpl__Win32Api *wapi,
const fpl__Win32LastWindowInfo *target, HWND windowHandle) {
10886 fplAssert(target->style > 0 && target->exStyle > 0);
10887 fpl__win32_SetWindowLong(windowHandle, GWL_STYLE, target->style);
10888 fpl__win32_SetWindowLong(windowHandle, GWL_EXSTYLE, target->exStyle);
10889 wapi->user.SetWindowPlacement(windowHandle, &target->placement);
10890 wapi->user.SetWindowPos(windowHandle,
fpl_null, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
10891 if (target->isMaximized) {
10892 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
10893 }
else if (target->isMinimized) {
10894 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
10899 const fpl__PlatformAppState *platState = fpl__global__AppState;
10901 const fpl__Win32AppState *win32State = &platState->win32;
10902 const fpl__Win32Api *wapi = &win32State->winApi;
10904 const fpl__Win32WindowState *win32Window = &platState->window.win32;
10905 const fpl__Win32LastWindowInfo *fullscreenInfo = &win32Window->lastFullscreenInfo;
10906 HWND windowHandle = win32Window->windowHandle;
10907 fpl__Win32RestoreWindowState(wapi, fullscreenInfo, windowHandle);
10909 if (fullscreenInfo->wasResolutionChanged) {
10910 result = (wapi->user.ChangeDisplaySettingsW(
fpl_null, CDS_RESET) == DISP_CHANGE_SUCCESSFUL);
10917fpl_internal bool fpl__Win32EnterFullscreen(
const int32_t xpos,
const int32_t ypos,
const int32_t fullscreenWidth,
const int32_t fullscreenHeight,
const uint32_t refreshRate,
const uint32_t colorBits,
const bool allowResolutionChange) {
10918 fpl__PlatformAppState *platState = fpl__global__AppState;
10920 fpl__Win32AppState *win32State = &platState->win32;
10921 const fpl__Win32Api *wapi = &win32State->winApi;
10923 fpl__Win32WindowState *win32Window = &platState->window.win32;
10924 fpl__Win32LastWindowInfo *fullscreenInfo = &win32Window->lastFullscreenInfo;
10926 HWND windowHandle = win32Window->windowHandle;
10927 HDC deviceContext = win32Window->deviceContext;
10929 fplAssert(fullscreenInfo->style > 0 && fullscreenInfo->exStyle > 0);
10930 fpl__win32_SetWindowLong(windowHandle, GWL_STYLE, fullscreenInfo->style & ~(WS_CAPTION | WS_THICKFRAME));
10931 fpl__win32_SetWindowLong(windowHandle, GWL_EXSTYLE, fullscreenInfo->exStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
10934 monitor.cbSize =
sizeof(monitor);
10935 wapi->user.GetMonitorInfoW(wapi->user.MonitorFromWindow(windowHandle, MONITOR_DEFAULTTONEAREST), &monitor);
10938 if (allowResolutionChange && (fullscreenWidth > 0) && (fullscreenHeight > 0)) {
10939 int32_t useFullscreenWidth = fullscreenWidth;
10940 int32_t useFullscreenHeight = fullscreenHeight;
10942 DWORD useRefreshRate = refreshRate;
10943 if (!useRefreshRate) {
10944 useRefreshRate = wapi->gdi.GetDeviceCaps(deviceContext, VREFRESH);
10947 DWORD useColourBits = colorBits;
10948 if (!useColourBits) {
10949 useColourBits = wapi->gdi.GetDeviceCaps(deviceContext, BITSPIXEL);
10954 windowRect.left = 0;
10955 windowRect.top = 0;
10956 windowRect.right = windowRect.left + useFullscreenWidth;
10957 windowRect.bottom = windowRect.top + useFullscreenHeight;
10960 placement.length =
sizeof(placement);
10961 placement.rcNormalPosition = windowRect;
10962 placement.showCmd = SW_SHOW;
10963 wapi->user.SetWindowPlacement(windowHandle, &placement);
10964 wapi->user.SetWindowPos(windowHandle,
fpl_null, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
10967 wapi->user.EnumDisplaySettingsW(
fpl_null, 0, &fullscreenSettings);
10968 fullscreenSettings.dmPelsWidth = useFullscreenWidth;
10969 fullscreenSettings.dmPelsHeight = useFullscreenHeight;
10970 fullscreenSettings.dmBitsPerPel = useColourBits;
10971 fullscreenSettings.dmDisplayFrequency = useRefreshRate;
10972 fullscreenSettings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
10973 result = (wapi->user.ChangeDisplaySettingsW(&fullscreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
10974 fullscreenInfo->wasResolutionChanged =
true;
10977 if ((xpos != INT32_MAX) && (ypos != INT32_MAX) && (fullscreenWidth != 0) && (fullscreenHeight != 0)) {
10978 windowRect.left = xpos;
10979 windowRect.top = ypos;
10980 windowRect.right = xpos + fullscreenWidth;
10981 windowRect.top = ypos + fullscreenHeight;
10983 windowRect = monitor.rcMonitor;
10986 placement.length =
sizeof(placement);
10987 placement.rcNormalPosition = windowRect;
10988 placement.showCmd = SW_SHOWNORMAL;
10989 wapi->user.SetWindowPlacement(windowHandle, &placement);
10990 wapi->user.SetWindowPos(windowHandle,
fpl_null, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
10992 fullscreenInfo->wasResolutionChanged =
false;
10998fpl_internal bool fpl__Win32SetWindowFullscreen(
const bool value,
const int32_t x,
const int32_t y,
const int32_t w,
const int32_t h,
const uint32_t refreshRate,
const bool allowResolutionChange) {
10999 FPL__CheckPlatform(
false);
11000 fpl__PlatformAppState *appState = fpl__global__AppState;
11001 fpl__Win32AppState *win32AppState = &appState->win32;
11002 fpl__Win32WindowState *windowState = &appState->window.win32;
11004 fpl__Win32LastWindowInfo *fullscreenState = &windowState->lastFullscreenInfo;
11005 const fpl__Win32Api *wapi = &win32AppState->winApi;
11007 HWND windowHandle = windowState->windowHandle;
11011 fpl__Win32SaveWindowState(wapi, fullscreenState, windowHandle);
11012 if (fullscreenState->isMaximized || fullscreenState->isMinimized) {
11013 wapi->user.ShowWindow(windowHandle, SW_RESTORE);
11019 windowSettings->
isFullscreen = fpl__Win32EnterFullscreen(x, y, w, h, refreshRate, 0, allowResolutionChange);
11021 fpl__Win32LeaveFullscreen();
11024 fpl__Win32LeaveFullscreen();
11031fpl_internal float fpl__Win32XInputProcessStickValue(
const SHORT value,
const SHORT deadZoneThreshold) {
11033 if (value < -deadZoneThreshold) {
11034 result = (float)((value + deadZoneThreshold) / (32768.0f - deadZoneThreshold));
11035 }
else if (value > deadZoneThreshold) {
11036 result = (float)((value - deadZoneThreshold) / (32767.0f - deadZoneThreshold));
11046 outState->
leftStickX = fpl__Win32XInputProcessStickValue(newState->sThumbLX, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
11047 outState->
leftStickY = fpl__Win32XInputProcessStickValue(newState->sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
11048 outState->
rightStickX = fpl__Win32XInputProcessStickValue(newState->sThumbRX, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
11049 outState->
rightStickY = fpl__Win32XInputProcessStickValue(newState->sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
11052 outState->
leftTrigger = (float)newState->bLeftTrigger / 255.0f;
11053 outState->rightTrigger = (float)newState->bRightTrigger / 255.0f;
11056 if (newState->wButtons & XINPUT_GAMEPAD_DPAD_UP)
11057 outState->dpadUp.isDown =
true;
11058 if (newState->wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
11059 outState->dpadDown.isDown =
true;
11060 if (newState->wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
11061 outState->dpadLeft.isDown =
true;
11062 if (newState->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
11063 outState->dpadRight.isDown =
true;
11066 if (newState->wButtons & XINPUT_GAMEPAD_A)
11067 outState->actionA.isDown =
true;
11068 if (newState->wButtons & XINPUT_GAMEPAD_B)
11069 outState->actionB.isDown =
true;
11070 if (newState->wButtons & XINPUT_GAMEPAD_X)
11071 outState->actionX.isDown =
true;
11072 if (newState->wButtons & XINPUT_GAMEPAD_Y)
11073 outState->actionY.isDown =
true;
11076 if (newState->wButtons & XINPUT_GAMEPAD_START)
11077 outState->start.isDown =
true;
11078 if (newState->wButtons & XINPUT_GAMEPAD_BACK)
11079 outState->back.isDown =
true;
11082 if (newState->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)
11083 outState->leftShoulder.isDown =
true;
11084 if (newState->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
11085 outState->rightShoulder.isDown =
true;
11088 if (newState->wButtons & XINPUT_GAMEPAD_LEFT_THUMB)
11089 outState->leftThumb.isDown =
true;
11090 if (newState->wButtons & XINPUT_GAMEPAD_RIGHT_THUMB)
11091 outState->rightThumb.isDown =
true;
11094 outState->isActive = !fpl__IsZeroMemory(newState,
sizeof(*newState));
11097fpl_internal void fpl__Win32UpdateGameControllers(
const fplSettings *settings,
const fpl__Win32InitState *initState, fpl__Win32XInputState *xinputState) {
11100 if (xinputState->xinputApi.XInputGetState !=
fpl_null) {
11104 if (xinputState->lastDeviceSearchTime.QuadPart == 0) {
11105 QueryPerformanceCounter(&xinputState->lastDeviceSearchTime);
11107 LARGE_INTEGER currentDeviceSearchTime, currentDeviceSearchFreq;
11108 QueryPerformanceCounter(¤tDeviceSearchTime);
11109 QueryPerformanceFrequency(¤tDeviceSearchFreq);
11110 uint64_t deviceSearchDifferenceTimeInMs = ((currentDeviceSearchTime.QuadPart - xinputState->lastDeviceSearchTime.QuadPart) / (currentDeviceSearchFreq.QuadPart / 1000));
11112 xinputState->lastDeviceSearchTime = currentDeviceSearchTime;
11113 for (DWORD controllerIndex = 0; controllerIndex < XUSER_MAX_COUNT; ++controllerIndex) {
11115 if (xinputState->xinputApi.XInputGetState(controllerIndex, &controllerState) == ERROR_SUCCESS) {
11116 if (!xinputState->isConnected[controllerIndex]) {
11118 xinputState->isConnected[controllerIndex] =
true;
11119 fplStringFormat(xinputState->deviceNames[controllerIndex],
fplArrayCount(xinputState->deviceNames[controllerIndex]),
"XInput-Device [%d]", controllerIndex);
11126 fpl__PushInternalEvent(&ev);
11129 if (xinputState->isConnected[controllerIndex]) {
11131 xinputState->isConnected[controllerIndex] =
false;
11138 fpl__PushInternalEvent(&ev);
11147 for (DWORD controllerIndex = 0; controllerIndex < XUSER_MAX_COUNT; ++controllerIndex) {
11148 if (xinputState->isConnected[controllerIndex]) {
11150 if (xinputState->xinputApi.XInputGetState(controllerIndex, &controllerState) == ERROR_SUCCESS) {
11157 const XINPUT_GAMEPAD *newPadState = &controllerState.Gamepad;
11158 fpl__Win32XInputGamepadToGamepadState(newPadState, &ev.
gamepad.
state);
11160 fpl__PushInternalEvent(&ev);
11167fpl_internal bool fpl__Win32IsKeyDown(
const fpl__Win32Api *wapi,
const int virtualKey) {
11168 bool result = (wapi->user.GetAsyncKeyState(virtualKey) & 0x8000) != 0;
11172fpl_internal bool fpl__Win32IsKeyActive(
const fpl__Win32Api *wapi,
const int virtualKey) {
11173 bool result = (wapi->user.GetKeyState(virtualKey) & 0x0001) != 0;
11177fpl_internal bool fpl__Win32IsCursorInWindow(
const fpl__Win32Api *wapi,
const fpl__Win32WindowState *win32Window) {
11179 if (!wapi->user.GetCursorPos(&pos)) {
11183 if (wapi->user.WindowFromPoint(pos) != win32Window->windowHandle) {
11188 wapi->user.GetClientRect(win32Window->windowHandle, &area);
11190 wapi->user.ClientToScreen(win32Window->windowHandle, (LPPOINT)&area.left);
11191 wapi->user.ClientToScreen(win32Window->windowHandle, (LPPOINT)&area.right);
11192 bool result = wapi->user.PtInRect(&area, pos) == TRUE;
11197fpl_internal void fpl__Win32LoadCursor(
const fpl__Win32Api *wapi,
const fpl__Win32WindowState *window) {
11198 if (window->isCursorActive) {
11199 wapi->user.SetCursor(fpl__win32_LoadCursor(
fpl_null, IDC_ARROW));
11205fpl_internal void fpl__Win32UpdateClipRect(
const fpl__Win32Api *wapi,
const fpl__Win32WindowState *window) {
11208 wapi->user.GetClientRect(window->windowHandle, &clipRect);
11209 wapi->user.ClientToScreen(window->windowHandle, (POINT *)&clipRect.left);
11210 wapi->user.ClientToScreen(window->windowHandle, (POINT *)&clipRect.right);
11211 wapi->user.ClipCursor(&clipRect);
11217fpl_internal void fpl__Win32SetCursorState(
const fpl__Win32Api *wapi, fpl__Win32WindowState *window,
const bool state) {
11220 const RAWINPUTDEVICE rid =
fplStructInit(RAWINPUTDEVICE, 0x01, 0x02, 0, window->windowHandle);
11221 if (!wapi->user.RegisterRawInputDevices(&rid, 1,
sizeof(rid))) {
11222 FPL__ERROR(FPL__MODULE_WINDOW,
"Failed register raw input mouse device for window handle '%p'", window->windowHandle);
11226 if (!wapi->user.RegisterRawInputDevices(&rid, 1,
sizeof(rid))) {
11227 FPL__ERROR(FPL__MODULE_WINDOW,
"Failed to unregister raw input mouse device");
11230 if (fpl__Win32IsCursorInWindow(wapi, window)) {
11231 fpl__Win32LoadCursor(wapi, window);
11235fpl_internal void fpl__Win32ShowCursor(
const fpl__Win32Api *wapi, fpl__Win32WindowState *window) {
11236 fpl__Win32SetCursorState(wapi, window,
false);
11238fpl_internal void fpl__Win32HideCursor(
const fpl__Win32Api *wapi, fpl__Win32WindowState *window) {
11239 fpl__Win32SetCursorState(wapi, window,
true);
11244 bool lAltKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_LMENU);
11245 bool rAltKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_RMENU);
11246 bool lShiftKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_LSHIFT);
11247 bool rShiftKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_RSHIFT);
11248 bool lCtrlKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_LCONTROL);
11249 bool rCtrlKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_RCONTROL);
11250 bool lSuperKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_LWIN);
11251 bool rSuperKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_RWIN);
11252 bool capsLockActive = fpl__Win32IsKeyActive(wapi, VK_CAPITAL);
11253 bool numLockActive = fpl__Win32IsKeyActive(wapi, VK_NUMLOCK);
11254 bool scrollLockActive = fpl__Win32IsKeyActive(wapi, VK_SCROLL);
11255 if (lAltKeyIsDown) {
11258 if (rAltKeyIsDown) {
11261 if (lShiftKeyIsDown) {
11264 if (rShiftKeyIsDown) {
11267 if (lCtrlKeyIsDown) {
11270 if (rCtrlKeyIsDown) {
11273 if (lSuperKeyIsDown) {
11276 if (rSuperKeyIsDown) {
11279 if (capsLockActive) {
11282 if (numLockActive) {
11285 if (scrollLockActive) {
11291fpl_internal void fpl__Win32HandleMessage(
const fpl__Win32Api *wapi, fpl__PlatformAppState *appState, fpl__Win32WindowState *windowState, MSG *msg) {
11292 if (appState->currentSettings.window.callbacks.eventCallback !=
fpl_null) {
11293 appState->currentSettings.window.callbacks.eventCallback(
fplGetPlatformType(), windowState, &msg, appState->currentSettings.window.callbacks.eventUserData);
11295 wapi->user.TranslateMessage(msg);
11296 wapi->user.DispatchMessageW(msg);
11299fpl_internal void CALLBACK fpl__Win32MessageFiberProc(
struct fpl__PlatformAppState *appState) {
11300 fpl__Win32AppState *win32State = &appState->win32;
11301 fpl__Win32WindowState *windowState = &appState->window.win32;
11302 const fpl__Win32Api *wapi = &win32State->winApi;
11303 wapi->user.SetTimer(appState->window.win32.windowHandle, 1, 1, 0);
11306 while (wapi->user.PeekMessageW(&message, 0, 0, 0, PM_REMOVE)) {
11307 fpl__Win32HandleMessage(wapi, appState, windowState, &message);
11309 SwitchToFiber(appState->window.win32.mainFiber);
11313LRESULT CALLBACK fpl__Win32MessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
11314 fpl__PlatformAppState *appState = fpl__global__AppState;
11317 fpl__Win32AppState *win32State = &appState->win32;
11318 fpl__Win32WindowState *win32Window = &appState->window.win32;
11319 const fpl__Win32Api *wapi = &win32State->winApi;
11321 if (!win32Window->windowHandle) {
11322 return wapi->user.DefWindowProcW(hwnd, msg, wParam, lParam);
11325 LRESULT result = 0;
11329 if (win32Window->mainFiber !=
fpl_null) {
11330 SwitchToFiber(win32Window->mainFiber);
11337 appState->window.isRunning =
false;
11342 DWORD newWidth = LOWORD(lParam);
11343 DWORD newHeight = HIWORD(lParam);
11344 if (wParam == SIZE_MAXIMIZED) {
11346 }
else if (wParam == SIZE_MINIMIZED) {
11348 }
else if (wParam == SIZE_RESTORED) {
11352# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
11354 if (appState->initSettings.video.isAutoSize) {
11367 HDROP dropHandle = (HDROP)wParam;
11371 fileCount = wapi->shell.DragQueryFileW(dropHandle, 0xFFFFFFFF, fileBufferW, 0);
11372 if (fileCount > 0) {
11373 size_t filesTableSize = fileCount *
sizeof(
char **);
11375 size_t filesMemorySize = filesTableSize + FPL__ARBITARY_PADDING + maxFileStride * fileCount;
11376 void *filesTableMemory = fpl__AllocateDynamicMemory(filesMemorySize, 16);
11377 char **filesTable = (
char **)filesTableMemory;
11378 for (UINT fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
11379 filesTable[fileIndex] = (
char *)((uint8_t *)filesTableMemory + filesTableSize + FPL__ARBITARY_PADDING + fileIndex * maxFileStride);
11381 for (UINT fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
11382 char *file = filesTable[fileIndex];
11383 fileBufferW[0] = 0;
11384 UINT dragResult = wapi->shell.DragQueryFileW(dropHandle, 0, fileBufferW,
fplArrayCount(fileBufferW));
11385 size_t sourceLen = lstrlenW(fileBufferW);
11389 memory.
size = filesMemorySize;
11390 memory.
base = filesTableMemory;
11391 fpl__PushWindowDropFilesEvent(fileBufferA, fileCount, (
const char **)filesTable, &memory);
11395 case WM_SYSKEYDOWN:
11400 if (!appState->currentSettings.input.disabledEvents) {
11401 uint64_t keyCode = wParam;
11402 bool isDown = (lParam & (1 << 31)) == 0;
11403 bool wasDown = (lParam & (1 << 30)) != 0;
11404 bool altKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_MENU);
11407 fpl__HandleKeyboardButtonEvent(&appState->window, GetTickCount(), keyCode, modifiers, keyState,
false);
11415 if ((msg == WM_UNICHAR) && (wParam == UNICODE_NOCHAR)) {
11419 fpl__HandleKeyboardInputEvent(&appState->window, (uint64_t)wParam, (uint32_t)wParam);
11427 case WM_MOUSEACTIVATE:
11429 if (HIWORD(lParam) == WM_LBUTTONDOWN) {
11430 if (LOWORD(lParam) == HTCLOSE || LOWORD(lParam) == HTMINBUTTON || LOWORD(lParam) == HTMAXBUTTON) {
11431 win32Window->isFrameInteraction =
true;
11436 case WM_CAPTURECHANGED:
11438 if (lParam == 0 && win32Window->isFrameInteraction) {
11439 if (!win32Window->isCursorActive) {
11440 fpl__Win32HideCursor(wapi, win32Window);
11442 win32Window->isFrameInteraction =
false;
11451 fpl__PushInternalEvent(&newEvent);
11452 if (win32Window->isFrameInteraction) {
11455 if (!win32Window->isCursorActive) {
11456 fpl__Win32HideCursor(wapi, win32Window);
11463 if (!win32Window->isCursorActive) {
11464 fpl__Win32ShowCursor(wapi, win32Window);
11469 fpl__PushInternalEvent(&newEvent);
11473 case WM_ENTERSIZEMOVE:
11474 case WM_ENTERMENULOOP:
11477 if (!win32Window->isCursorActive) {
11478 fpl__Win32ShowCursor(wapi, win32Window);
11482 case WM_EXITSIZEMOVE:
11483 case WM_EXITMENULOOP:
11485 if (!win32Window->isCursorActive) {
11486 fpl__Win32HideCursor(wapi, win32Window);
11490 case WM_LBUTTONDOWN:
11492 case WM_RBUTTONDOWN:
11494 case WM_MBUTTONDOWN:
11497 if (!appState->currentSettings.input.disabledEvents) {
11499 if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) {
11505 wapi->user.SetCapture(hwnd);
11507 wapi->user.ReleaseCapture();
11510 if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) {
11512 }
else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONUP) {
11514 }
else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONUP) {
11520 int32_t mouseX = GET_X_LPARAM(lParam);
11521 int32_t mouseY = GET_Y_LPARAM(lParam);
11522 fpl__HandleMouseButtonEvent(&appState->window, mouseX, mouseY, mouseButton, buttonState);
11528 if (!appState->currentSettings.input.disabledEvents) {
11529 int32_t mouseX = GET_X_LPARAM(lParam);
11530 int32_t mouseY = GET_Y_LPARAM(lParam);
11531 fpl__HandleMouseMoveEvent(&appState->window, mouseX, mouseY);
11534 case WM_MOUSEWHEEL:
11536 int32_t mouseX = GET_X_LPARAM(lParam);
11537 int32_t mouseY = GET_Y_LPARAM(lParam);
11538 short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
11539 float wheelDelta = zDelta / (float)WHEEL_DELTA;
11540 fpl__HandleMouseWheelEvent(&appState->window, mouseX, mouseY, wheelDelta);
11545 if (LOWORD(lParam) == HTCLIENT) {
11546 fpl__Win32LoadCursor(wapi, win32Window);
11553 if (appState->currentSettings.window.callbacks.exposedCallback !=
fpl_null) {
11555 msgData.message = msg;
11556 msgData.hwnd = hwnd;
11557 msgData.wParam = wParam;
11558 msgData.lParam = lParam;
11559 appState->currentSettings.window.callbacks.exposedCallback(
fplGetPlatformType(), win32Window, &msgData, appState->currentSettings.window.callbacks.exposedUserData);
11563 HDC hdc = wapi->user.BeginPaint(hwnd, &ps);
11564 wapi->user.EndPaint(hwnd, &ps);
11570 case WM_ERASEBKGND:
11579 case WM_SYSCOMMAND:
11581 WPARAM masked = wParam & 0xFFF0;
11583 case SC_SCREENSAVE:
11584 case SC_MONITORPOWER: {
11585 if (appState->currentSettings.window.isScreenSaverPrevented || appState->currentSettings.window.isMonitorPowerPrevented) {
11595 result = wapi->user.DefWindowProcW(hwnd, msg, wParam, lParam);
11599fpl_internal HICON fpl__Win32LoadIconFromImageSource(
const fpl__Win32Api *wapi,
const HINSTANCE appInstance,
const fplImageSource *imageSource) {
11604 bi.bV5Size =
sizeof(bi);
11605 bi.bV5Width = (LONG)imageSource->
width;
11606 bi.bV5Height = -(LONG)imageSource->
height;
11608 bi.bV5BitCount = 32;
11609 bi.bV5Compression = BI_BITFIELDS;
11610 bi.bV5RedMask = 0x00ff0000;
11611 bi.bV5GreenMask = 0x0000ff00;
11612 bi.bV5BlueMask = 0x000000ff;
11613 bi.bV5AlphaMask = 0xff000000;
11616 HDC dc = wapi->user.GetDC(
fpl_null);
11617 HBITMAP colorBitmap = wapi->gdi.CreateDIBSection(dc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (
void **)&targetData,
fpl_null, (DWORD)0);
11619 FPL__ERROR(FPL__MODULE_WIN32,
"Failed to create DIBSection from image with size %lu x %lu", imageSource->
width, imageSource->
height);
11621 wapi->user.ReleaseDC(
fpl_null, dc);
11623 HBITMAP maskBitmap = wapi->gdi.CreateBitmap(imageSource->
width, imageSource->
height, 1, 1,
fpl_null);
11625 FPL__ERROR(FPL__MODULE_WIN32,
"Failed to create Bitmap Mask from image with size %lu x %lu", imageSource->
width, imageSource->
height);
11629 uint8_t *dst = targetData;
11630 const uint8_t *src = imageSource->
data;
11632 for (uint32_t i = 0; i < imageSource->
width * imageSource->
height; ++i) {
11644 ii.hbmMask = maskBitmap;
11645 ii.hbmColor = colorBitmap;
11646 result = wapi->user.CreateIconIndirect(&ii);
11648 FPL__ERROR(FPL__MODULE_WIN32,
"Image source type '%d' for icon is not supported", imageSource->
type);
11652 wapi->gdi.DeleteObject(colorBitmap);
11655 wapi->gdi.DeleteObject(maskBitmap);
11659 result = fpl__win32_LoadIcon(appInstance, IDI_APPLICATION);
11664fpl_internal bool fpl__Win32InitWindow(
const fplSettings *initSettings,
fplWindowSettings *currentWindowSettings, fpl__PlatformAppState *platAppState, fpl__Win32AppState *appState, fpl__Win32WindowState *windowState,
const fpl__SetupWindowCallbacks *setupCallbacks) {
11666 const fpl__Win32Api *wapi = &appState->winApi;
11670 if (setupCallbacks->preSetup !=
fpl_null) {
11671 setupCallbacks->preSetup(platAppState, platAppState->initFlags, &platAppState->initSettings);
11676 windowClass.cbSize =
sizeof(windowClass);
11677 windowClass.hInstance = GetModuleHandleA(
fpl_null);
11681 windowState->backgroundBrush =
fpl_null;
11682 windowClass.hbrBackground = wapi->user.GetSysColorBrush(COLOR_BACKGROUND);
11685 windowState->backgroundBrush = wapi->gdi.CreateSolidBrush(brushColor);
11686 windowClass.hbrBackground = windowState->backgroundBrush;
11689 windowClass.cbSize =
sizeof(windowClass);
11690 windowClass.style = CS_HREDRAW | CS_VREDRAW;
11691 windowClass.hCursor = fpl__win32_LoadCursor(windowClass.hInstance, IDC_ARROW);
11692 windowClass.hIconSm = fpl__Win32LoadIconFromImageSource(wapi, windowClass.hInstance, &initWindowSettings->
icons[0]);
11693 windowClass.hIcon = fpl__Win32LoadIconFromImageSource(wapi, windowClass.hInstance, &initWindowSettings->
icons[1]);
11694 windowClass.lpszClassName = FPL__WIN32_CLASSNAME;
11695 windowClass.lpfnWndProc = fpl__Win32MessageProc;
11696 windowClass.style |= CS_OWNDC;
11697 lstrcpynW(windowState->windowClass, windowClass.lpszClassName,
fplArrayCount(windowState->windowClass));
11698 if (wapi->user.RegisterClassExW(&windowClass) == 0) {
11699 FPL__ERROR(FPL__MODULE_WINDOW,
"Failed registering window class '%s'", windowState->windowClass);
11708 const wchar_t *defaultTitle = FPL__WIN32_UNNAMED_WINDOW;
11709 lstrcpynW(windowTitleBuffer, defaultTitle,
fplArrayCount(windowTitleBuffer));
11711 wchar_t *windowTitle = windowTitleBuffer;
11715 windowState->mainFiber = ConvertThreadToFiber(0);
11716 windowState->messageFiber = CreateFiber(0, (PFIBER_START_ROUTINE)fpl__Win32MessageFiberProc, platAppState);
11719 DWORD style = fpl__Win32MakeWindowStyle(&initSettings->
window);
11720 DWORD exStyle = fpl__Win32MakeWindowExStyle(&initSettings->
window);
11726 int windowX = CW_USEDEFAULT;
11727 int windowY = CW_USEDEFAULT;
11733 windowRect.left = 0;
11734 windowRect.top = 0;
11737 wapi->user.AdjustWindowRect(&windowRect, style,
false);
11738 windowWidth = windowRect.right - windowRect.left;
11739 windowHeight = windowRect.bottom - windowRect.top;
11742 windowWidth = CW_USEDEFAULT;
11743 windowHeight = CW_USEDEFAULT;
11747 windowState->windowHandle = wapi->user.CreateWindowExW(exStyle, windowClass.lpszClassName, windowTitle, style, windowX, windowY, windowWidth, windowHeight,
fpl_null,
fpl_null, windowClass.hInstance,
fpl_null);
11748 if (windowState->windowHandle ==
fpl_null) {
11749 FPL__ERROR(FPL__MODULE_WINDOW,
"Failed creating window for class '%s' and position (%d x %d) with size (%d x %d)", windowState->windowClass, windowX, windowY, windowWidth, windowHeight);
11754 wapi->shell.DragAcceptFiles(windowState->windowHandle, TRUE);
11760 if (wapi->user.GetClientRect(windowState->windowHandle, &clientRect)) {
11761 currentWindowSettings->
windowSize.
width = clientRect.right - clientRect.left;
11762 currentWindowSettings->
windowSize.
height = clientRect.bottom - clientRect.top;
11766 windowState->deviceContext = wapi->user.GetDC(windowState->windowHandle);
11767 if (windowState->deviceContext ==
fpl_null) {
11768 FPL__ERROR(FPL__MODULE_WINDOW,
"Failed aquiring device context from window '%d'", windowState->windowHandle);
11773 if (setupCallbacks->postSetup !=
fpl_null) {
11774 setupCallbacks->postSetup(platAppState, platAppState->initFlags, initSettings);
11783 wapi->user.ShowWindow(windowState->windowHandle, SW_SHOW);
11784 wapi->user.SetForegroundWindow(windowState->windowHandle);
11785 wapi->user.SetFocus(windowState->windowHandle);
11788 windowState->defaultCursor = windowClass.hCursor;
11789 windowState->isCursorActive =
true;
11790 platAppState->window.isRunning =
true;
11795fpl_internal void fpl__Win32ReleaseWindow(
const fpl__Win32InitState *initState,
const fpl__Win32AppState *appState, fpl__Win32WindowState *windowState) {
11796 const fpl__Win32Api *wapi = &appState->winApi;
11797 if (windowState->deviceContext !=
fpl_null) {
11798 wapi->user.ReleaseDC(windowState->windowHandle, windowState->deviceContext);
11799 windowState->deviceContext =
fpl_null;
11801 if (windowState->windowHandle !=
fpl_null) {
11802 wapi->user.DestroyWindow(windowState->windowHandle);
11803 windowState->windowHandle =
fpl_null;
11804 wapi->user.UnregisterClassW(windowState->windowClass, initState->appInstance);
11806 if (windowState->backgroundBrush !=
fpl_null) {
11807 wapi->gdi.DeleteObject(windowState->backgroundBrush);
11808 windowState->backgroundBrush =
fpl_null;
11810 if (windowState->messageFiber !=
fpl_null) {
11811 DeleteFiber(windowState->messageFiber);
11812 windowState->messageFiber =
fpl_null;
11814 if (windowState->mainFiber !=
fpl_null) {
11815 ConvertFiberToThread();
11816 windowState->mainFiber =
fpl_null;
11823 FPL__CheckArgumentNull(threads,
false);
11824 FPL__CheckArgumentMax(count, FPL_MAX_THREAD_COUNT,
false);
11826 const size_t actualStride = stride > 0 ? stride :
sizeof(
fplThreadHandle *);
11827 for (
size_t index = 0; index < count; ++index) {
11830 FPL__ERROR(FPL__MODULE_THREADING,
"Thread for index '%d' are not allowed to be null", index);
11835 FPL__ERROR(FPL__MODULE_THREADING,
"Thread handle for index '%d' are not allowed to be null", index);
11844 size_t minThreads = waitForAll ? count : 1;
11845 size_t stoppedThreads = 0;
11846 while (stoppedThreads < minThreads) {
11847 stoppedThreads = 0;
11848 for (
size_t index = 0; index < count; ++index) {
11854 if (stoppedThreads >= minThreads) {
11864 bool result = stoppedThreads >= minThreads;
11869 FPL__CheckArgumentNull(signals,
false);
11870 FPL__CheckArgumentMax(count, FPL_MAX_SIGNAL_COUNT,
false);
11872 HANDLE signalHandles[FPL_MAX_SIGNAL_COUNT];
11873 const size_t actualStride = stride > 0 ? stride :
sizeof(
fplSignalHandle *);
11874 for (uint32_t index = 0; index < count; ++index) {
11876 if (availableSignal ==
fpl_null) {
11877 FPL__ERROR(FPL__MODULE_THREADING,
"Signal for index '%d' are not allowed to be null", index);
11881 FPL__ERROR(FPL__MODULE_THREADING,
"Signal handle for index '%d' are not allowed to be null", index);
11884 HANDLE handle = availableSignal->
internalHandle.win32EventHandle;
11885 signalHandles[index] = handle;
11888 DWORD code = WaitForMultipleObjects((DWORD)count, signalHandles, waitForAll ? TRUE : FALSE, t);
11889 bool result = (code >= WAIT_OBJECT_0);
11893fpl_internal void fpl__Win32ReleasePlatform(fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
11895 fpl__Win32AppState *win32AppState = &appState->win32;
11896 fpl__Win32InitState *win32InitState = &initState->win32;
11898 fpl__Win32UnloadXInputApi(&win32AppState->xinput.xinputApi);
11900 fpl__Win32UnloadApi(&win32AppState->winApi);
11903#if defined(FPL__ENABLE_WINDOW)
11904fpl_internal fplKey fpl__Win32TranslateVirtualKey(
const fpl__Win32Api *wapi,
const uint64_t virtualKey) {
11905 switch (virtualKey) {
11907 return fplKey_Backspace;
11912 return fplKey_Clear;
11914 return fplKey_Return;
11917 return fplKey_Shift;
11919 return fplKey_Control;
11923 return fplKey_Pause;
11925 return fplKey_CapsLock;
11928 return fplKey_Escape;
11930 return fplKey_Space;
11932 return fplKey_PageUp;
11934 return fplKey_PageDown;
11938 return fplKey_Home;
11940 return fplKey_Left;
11944 return fplKey_Right;
11946 return fplKey_Down;
11948 return fplKey_Select;
11950 return fplKey_Print;
11952 return fplKey_Execute;
11954 return fplKey_Snapshot;
11956 return fplKey_Insert;
11958 return fplKey_Delete;
11960 return fplKey_Help;
12037 return fplKey_LeftSuper;
12039 return fplKey_RightSuper;
12041 return fplKey_Apps;
12044 return fplKey_Sleep;
12046 return fplKey_NumPad0;
12048 return fplKey_NumPad1;
12050 return fplKey_NumPad2;
12052 return fplKey_NumPad3;
12054 return fplKey_NumPad4;
12056 return fplKey_NumPad5;
12058 return fplKey_NumPad6;
12060 return fplKey_NumPad7;
12062 return fplKey_NumPad8;
12064 return fplKey_NumPad9;
12066 return fplKey_Multiply;
12070 return fplKey_Separator;
12072 return fplKey_Substract;
12074 return fplKey_Decimal;
12076 return fplKey_Divide;
12127 return fplKey_LeftShift;
12129 return fplKey_RightShift;
12131 return fplKey_LeftControl;
12133 return fplKey_RightControl;
12135 return fplKey_LeftAlt;
12137 return fplKey_RightAlt;
12139 case VK_VOLUME_MUTE:
12140 return fplKey_VolumeMute;
12141 case VK_VOLUME_DOWN:
12142 return fplKey_VolumeDown;
12144 return fplKey_VolumeUp;
12145 case VK_MEDIA_NEXT_TRACK:
12146 return fplKey_MediaNextTrack;
12147 case VK_MEDIA_PREV_TRACK:
12148 return fplKey_MediaPrevTrack;
12149 case VK_MEDIA_STOP:
12150 return fplKey_MediaStop;
12151 case VK_MEDIA_PLAY_PAUSE:
12152 return fplKey_MediaPlayPause;
12160 case VK_OEM_PERIOD:
12178 return fplKey_Oem8;
12181 return fplKey_None;
12186fpl_internal bool fpl__Win32InitPlatform(
const fplInitFlags initFlags,
const fplSettings *initSettings, fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
12190 fpl__Win32InitState *win32InitState = &initState->win32;
12191 fpl__Win32AppState *win32AppState = &appState->win32;
12196 win32InitState->appInstance = GetModuleHandleA(
fpl_null);
12199 QueryPerformanceFrequency(&win32InitState->qpf);
12202 HANDLE mainThreadHandle = GetCurrentThread();
12203 DWORD mainThreadHandleId = GetCurrentThreadId();
12206 mainThread->
id = mainThreadHandleId;
12207 mainThread->
internalHandle.win32ThreadHandle = mainThreadHandle;
12211 if (!fpl__Win32LoadApi(&win32AppState->winApi)) {
12213 fpl__Win32ReleasePlatform(initState, appState);
12219 fpl__Win32LoadXInputApi(&win32AppState->xinput.xinputApi);
12224 HWND consoleWindow = GetConsoleWindow();
12225 if (!showConsole) {
12227 win32AppState->winApi.user.ShowWindow(consoleWindow, SW_HIDE);
12231 }
else if (consoleWindow !=
fpl_null) {
12240 const wchar_t *defaultTitle = FPL__WIN32_UNNAMED_CONSOLE;
12241 lstrcpynW(consoleTitleBuffer, defaultTitle,
fplArrayCount(consoleTitleBuffer));
12243 wchar_t *windowTitle = consoleTitleBuffer;
12245 SetConsoleTitleW(windowTitle);
12247 win32AppState->winApi.user.ShowWindow(consoleWindow, SW_SHOW);
12251# if defined(FPL__ENABLE_WINDOW)
12253 for (
int i = 0; i < 256; ++i) {
12254 int vk = win32AppState->winApi.user.MapVirtualKeyW(MAPVK_VSC_TO_VK, i);
12258 appState->window.keyMap[i] = fpl__Win32TranslateVirtualKey(&win32AppState->winApi, vk);
12263# if defined(FPL__ENABLE_WINDOW)
12265 SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
12267 SetThreadExecutionState(ES_CONTINUOUS);
12278 FPL_MEMORY_BARRIER();
12282 FPL_MEMORY_BARRIER();
12286 FPL_MEMORY_BARRIER();
12287 _ReadWriteBarrier();
12292 uint32_t result = InterlockedExchange((
volatile LONG *)target, value);
12297 int32_t result = InterlockedExchange((
volatile LONG *)target, value);
12302 uint64_t result = InterlockedExchange64((
volatile LONG64 *)target, value);
12307 int64_t result = InterlockedExchange64((
volatile LONG64 *)target, value);
12313 uint32_t result = InterlockedExchangeAdd((
volatile LONG *)value, addend);
12318 int32_t result = InterlockedExchangeAdd((
volatile LONG *)value, addend);
12323 uint64_t result = InterlockedExchangeAdd64((
volatile LONG64 *)value, addend);
12328 int64_t result = InterlockedExchangeAdd64((
volatile LONG64 *)value, addend);
12334 uint32_t result = InterlockedAdd((
volatile LONG *)value, addend);
12339 int32_t result = InterlockedAdd((
volatile LONG *)value, addend);
12344 uint64_t result = InterlockedAdd64((
volatile LONG64 *)value, addend);
12349 int64_t result = InterlockedAdd64((
volatile LONG64 *)value, addend);
12355 uint32_t result = InterlockedIncrement((
volatile LONG *)value);
12360 int32_t result = InterlockedIncrement((
volatile LONG *)value);
12365 uint64_t result = InterlockedIncrement64((
volatile LONG64 *)value);
12370 int64_t result = InterlockedIncrement64((
volatile LONG64 *)value);
12376 uint32_t result = InterlockedCompareExchange((
volatile LONG *)dest, exchange, comparand);
12381 int32_t result = InterlockedCompareExchange((
volatile LONG *)dest, exchange, comparand);
12386 uint64_t result = InterlockedCompareExchange64((
volatile LONG64 *)dest, exchange, comparand);
12391 int64_t result = InterlockedCompareExchange64((
volatile LONG64 *)dest, exchange, comparand);
12397 uint32_t value = InterlockedCompareExchange((
volatile LONG *)dest, exchange, comparand);
12398 bool result = (value == comparand);
12403 int32_t value = InterlockedCompareExchange((
volatile LONG *)dest, exchange, comparand);
12404 bool result = (value == comparand);
12409 uint64_t value = InterlockedCompareExchange64((
volatile LONG64 *)dest, exchange, comparand);
12410 bool result = (value == comparand);
12415 int64_t value = InterlockedCompareExchange64((
volatile LONG64 *)dest, exchange, comparand);
12416 bool result = (value == comparand);
12421 uint32_t result = InterlockedCompareExchange((
volatile LONG *)source, 0, 0);
12425 uint64_t result = InterlockedCompareExchange64((
volatile LONG64 *)source, 0, 0);
12429 int32_t result = InterlockedCompareExchange((
volatile LONG *)source, 0, 0);
12433 int64_t result = InterlockedCompareExchange64((
volatile LONG64 *)source, 0, 0);
12438 InterlockedExchange((
volatile LONG *)dest, value);
12441 InterlockedExchange64((
volatile LONG64 *)dest, value);
12444 InterlockedExchange((
volatile LONG *)dest, value);
12447 InterlockedExchange64((
volatile LONG64 *)dest, value);
12453fpl_internal const char *fpl__Win32GetVersionName(DWORD major, DWORD minor) {
12454 const char *result;
12455 if (major == 5 && minor == 0) {
12456 result =
"Windows 2000";
12457 }
else if (major == 5 && minor == 1) {
12458 result =
"Windows XP";
12459 }
else if (major == 5 && minor == 2) {
12460 result =
"Windows XP";
12461 }
else if (major == 6 && minor == 0) {
12462 result =
"Windows Vista";
12463 }
else if (major == 6 && minor == 1) {
12464 result =
"Windows 7";
12465 }
else if (major == 6 && minor == 2) {
12466 result =
"Windows 8";
12467 }
else if (major == 6 && minor == 3) {
12468 result =
"Windows 8.1";
12469 }
else if (major == 10) {
12470 result =
"Windows 10";
12472 result =
"Windows";
12477#define FPL__FUNC_NTDLL_RtlGetVersion(name) DWORD WINAPI name(PRTL_OSVERSIONINFOW lpVersionInformation)
12478typedef FPL__FUNC_NTDLL_RtlGetVersion(fpl__func_ntdll_RtlGetVersionProc);
12479#define FPL__FUNC_KERNEL32_GetVersion(name) DWORD WINAPI name()
12480typedef FPL__FUNC_KERNEL32_GetVersion(fpl__func_kernel32_GetVersion);
12481#define FPL__FUNC_KERNEL32_GetVersionExW(name) BOOL WINAPI name(LPOSVERSIONINFOEXW lpVersionInfo)
12482typedef FPL__FUNC_KERNEL32_GetVersionExW(fpl__func_kernel32_GetVersionExW);
12484 FPL__CheckArgumentNull(outInfos,
false);
12489 HMODULE ntdllModule = GetModuleHandleA(
"ntdll");
12490 fpl__func_ntdll_RtlGetVersionProc *rtlGetVersionProc = (fpl__func_ntdll_RtlGetVersionProc *)GetProcAddress(ntdllModule,
"RtlGetVersion");
12491 if (rtlGetVersionProc !=
fpl_null) {
12493 info.dwOSVersionInfoSize =
sizeof(info);
12494 if (rtlGetVersionProc(&info) == 0) {
12500 const char *versionName = fpl__Win32GetVersionName(info.dwMajorVersion, info.dwMinorVersion);
12507 HMODULE kernelLib = LoadLibraryA(
"kernel32.dll");
12509 FPL__ERROR(FPL__MODULE_WIN32,
"Kernel32 library could not be loaded");
12512 fpl__func_kernel32_GetVersion *getVersionProc = (fpl__func_kernel32_GetVersion *)GetProcAddress(kernelLib,
"GetVersion");
12513 fpl__func_kernel32_GetVersionExW *getVersionExProc = (fpl__func_kernel32_GetVersionExW *)GetProcAddress(kernelLib,
"GetVersionExW");
12514 FreeLibrary(kernelLib);
12516 if (getVersionExProc !=
fpl_null) {
12518 infoEx.dwOSVersionInfoSize =
sizeof(infoEx);
12519 if (getVersionExProc(&infoEx) == TRUE) {
12525 const char *versionName = fpl__Win32GetVersionName(infoEx.dwMajorVersion, infoEx.dwMinorVersion);
12532 DWORD dwVersion = getVersionProc();
12533 if (dwVersion > 0) {
12534 DWORD major = (DWORD)(LOBYTE(LOWORD(dwVersion)));
12535 DWORD minor = (DWORD)(HIBYTE(LOWORD(dwVersion)));
12537 if (dwVersion < 0x80000000) {
12538 build = (DWORD)((DWORD)(HIWORD(dwVersion)));
12545 const char *versionName = fpl__Win32GetVersionName(major, minor);
12554#define FPL__FUNC_ADV32_GetUserNameW(name) BOOL WINAPI name(LPWSTR lpBuffer, LPDWORD pcbBuffer)
12555typedef FPL__FUNC_ADV32_GetUserNameW(fpl__func_adv32_GetUserNameW);
12557 const char *libName =
"advapi32.dll";
12558 HMODULE adv32Lib = LoadLibraryA(libName);
12560 FPL__ERROR(FPL__MODULE_WIN32,
"Failed loading library '%s'", libName);
12563 fpl__func_adv32_GetUserNameW *getUserNameProc = (fpl__func_adv32_GetUserNameW *)GetProcAddress(adv32Lib,
"GetUserNameW");
12565 if (getUserNameProc !=
fpl_null) {
12568 if (getUserNameProc(wideBuffer, &size) == TRUE) {
12572 FreeLibrary(adv32Lib);
12581 GetSystemInfo(&sysInfo);
12583 size_t result = sysInfo.dwNumberOfProcessors;
12587#define FPL__WIN32_PROCESSOR_ARCHITECTURE_ARM64 12
12592 if (IsWow64Process(GetCurrentProcess(), &isWow64)) {
12594 GetNativeSystemInfo(&sysInfo);
12596 GetSystemInfo(&sysInfo);
12598 GetSystemInfo(&sysInfo);
12600 switch (sysInfo.wProcessorArchitecture) {
12601 case PROCESSOR_ARCHITECTURE_AMD64:
12604 case PROCESSOR_ARCHITECTURE_IA64:
12607 case PROCESSOR_ARCHITECTURE_ARM:
12610 case FPL__WIN32_PROCESSOR_ARCHITECTURE_ARM64:
12613 case PROCESSOR_ARCHITECTURE_UNKNOWN:
12616 case PROCESSOR_ARCHITECTURE_INTEL:
12624#define FPL__FUNC_WIN32_KERNEL32_GetPhysicallyInstalledSystemMemory(name) BOOL WINAPI name(PULONGLONG TotalMemoryInKilobytes)
12625typedef FPL__FUNC_WIN32_KERNEL32_GetPhysicallyInstalledSystemMemory(fpl__win32_kernel_func_GetPhysicallyInstalledSystemMemory);
12627 FPL__CheckArgumentNull(outInfos,
false);
12628 bool result =
false;
12630 HMODULE kernel32lib = LoadLibraryA(
"kernel32.dll");
12634 fpl__win32_kernel_func_GetPhysicallyInstalledSystemMemory *getPhysicallyInstalledSystemMemory = (fpl__win32_kernel_func_GetPhysicallyInstalledSystemMemory *)GetProcAddress(kernel32lib,
"GetPhysicallyInstalledSystemMemory");
12635 FreeLibrary(kernel32lib);
12637 ULONGLONG installedMemorySize = 0;
12638 if (getPhysicallyInstalledSystemMemory !=
fpl_null) {
12639 getPhysicallyInstalledSystemMemory(&installedMemorySize);
12643 GetSystemInfo(&systemInfo);
12646 statex.dwLength =
sizeof(statex);
12648 if (GlobalMemoryStatusEx(&statex)) {
12655 outInfos->
pageSize = systemInfo.dwPageSize;
12668fpl_internal DWORD WINAPI fpl__Win32ThreadProc(
void *data) {
12684 CloseHandle(handle);
12692 DWORD threadId = GetCurrentThreadId();
12693 uint32_t result = (uint32_t)threadId;
12698 int win32Priority = 0;
12699 switch (newPriority) {
12701 win32Priority = THREAD_PRIORITY_IDLE;
12704 win32Priority = THREAD_PRIORITY_LOWEST;
12707 win32Priority = THREAD_PRIORITY_NORMAL;
12710 win32Priority = THREAD_PRIORITY_HIGHEST;
12713 win32Priority = THREAD_PRIORITY_TIME_CRITICAL;
12716 FPL__ERROR(
"Threading",
"The thread priority %d is not supported", newPriority);
12719 bool result = SetThreadPriority(threadHandle, win32Priority) == TRUE;
12724 FPL__CheckArgumentNull(parameters,
fpl_null);
12729 DWORD creationFlags = 0;
12730 DWORD threadId = 0;
12731 SIZE_T stackSize = parameters->
stackSize;
12734 HANDLE handle = CreateThread(
fpl_null, stackSize, fpl__Win32ThreadProc, thread, creationFlags, &threadId);
12738 thread->
id = threadId;
12742 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating thread, error code: %d", GetLastError());
12745 FPL__ERROR(FPL__MODULE_THREADING,
"All %d threads are in use, you cannot create until you free one", FPL_MAX_THREAD_COUNT);
12751 FPL__CheckArgumentNull(runFunc,
fpl_null);
12754 parameters.
runFunc = runFunc;
12761 switch (win32ThreadPriority) {
12762 case THREAD_PRIORITY_IDLE:
12764 case THREAD_PRIORITY_LOWEST:
12765 case THREAD_PRIORITY_BELOW_NORMAL:
12767 case THREAD_PRIORITY_NORMAL:
12769 case THREAD_PRIORITY_ABOVE_NORMAL:
12770 case THREAD_PRIORITY_HIGHEST:
12772 case THREAD_PRIORITY_TIME_CRITICAL:
12784 int win32ThreadPriority = GetThreadPriority(threadHandle);
12785 result = fpl__Win32MapNativeThreadPriority(win32ThreadPriority);
12791 FPL__CheckArgumentNull(thread,
false);
12792 bool result =
false;
12795 result = fpl__Win32SetThreadPriority(threadHandle, newPriority);
12801 Sleep((DWORD)milliseconds);
12810 FPL__CheckArgumentNull(thread,
false);
12816 TerminateThread(handle, 0);
12817 CloseHandle(handle);
12828 FPL__CheckArgumentNull(thread,
false);
12832 FPL__ERROR(FPL__MODULE_THREADING,
"Win32 thread handle are not allowed to be null");
12837 result = (WaitForSingleObject(handle, t) == WAIT_OBJECT_0);
12845 bool result = fpl__Win32ThreadWaitForMultiple(threads, count, stride, timeout,
true);
12850 bool result = fpl__Win32ThreadWaitForMultiple(threads, count, stride, timeout,
false);
12855 FPL__CheckArgumentNull(mutex,
false);
12857 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex '%p' is already initialized", mutex);
12863 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
12864 InitializeCriticalSection(critSection);
12869 FPL__CheckArgumentNullNoRet(mutex);
12872 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
12873 DeleteCriticalSection(critSection);
12879 FPL__CheckArgumentNull(mutex,
false);
12881 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex parameter must be valid");
12885 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
12886 EnterCriticalSection(critSection);
12891 FPL__CheckArgumentNull(mutex,
false);
12893 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex parameter must be valid");
12897 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
12898 bool result = TryEnterCriticalSection(critSection) == TRUE;
12903 FPL__CheckArgumentNull(mutex,
false);
12905 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex parameter must be valid");
12909 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
12910 LeaveCriticalSection(critSection);
12915 FPL__CheckArgumentNull(signal,
false);
12917 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' is already initialized", signal);
12922 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating signal (Win32 event): %d", GetLastError());
12932 FPL__CheckArgumentNullNoRet(signal);
12935 CloseHandle(handle);
12941 FPL__CheckArgumentNull(signal,
false);
12943 FPL__ERROR(FPL__MODULE_THREADING,
"Signal handle are not allowed to be null");
12948 bool result = (WaitForSingleObject(handle, t) == WAIT_OBJECT_0);
12953 bool result = fpl__Win32SignalWaitForMultiple(signals, count, stride, timeout,
true);
12958 bool result = fpl__Win32SignalWaitForMultiple(signals, count, stride, timeout,
false);
12963 FPL__CheckArgumentNull(signal,
false);
12965 FPL__ERROR(FPL__MODULE_THREADING,
"Signal handle are not allowed to be null");
12969 bool result = SetEvent(handle) == TRUE;
12974 FPL__CheckArgumentNull(signal,
false);
12976 FPL__ERROR(FPL__MODULE_THREADING,
"Signal handle are not allowed to be null");
12980 bool result = ResetEvent(handle) == TRUE;
12985 FPL__CheckArgumentNull(condition,
false);
12988 CONDITION_VARIABLE *condVar = (CONDITION_VARIABLE *)&condition->
internalHandle.win32Condition;
12989 InitializeConditionVariable(condVar);
12995 FPL__CheckArgumentNullNoRet(condition);
13002 FPL__CheckArgumentNull(condition,
false);
13003 FPL__CheckArgumentNull(mutex,
false);
13005 FPL__ERROR(FPL__MODULE_THREADING,
"Condition '%p' is not valid", condition);
13009 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex '%p' is not valid", mutex);
13013 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
13014 CONDITION_VARIABLE *condVar = (CONDITION_VARIABLE *)&condition->
internalHandle.win32Condition;
13015 bool result = SleepConditionVariableCS(condVar, critSection, t) != 0;
13020 FPL__CheckArgumentNull(condition,
false);
13022 FPL__ERROR(FPL__MODULE_THREADING,
"Condition '%p' is not valid", condition);
13025 CONDITION_VARIABLE *critSection = (CONDITION_VARIABLE *)&condition->
internalHandle.win32Condition;
13026 WakeConditionVariable(critSection);
13031 FPL__CheckArgumentNull(condition,
false);
13033 FPL__ERROR(FPL__MODULE_THREADING,
"Condition '%p' is not valid", condition);
13036 CONDITION_VARIABLE *critSection = (CONDITION_VARIABLE *)&condition->
internalHandle.win32Condition;
13037 WakeAllConditionVariable(critSection);
13042 FPL__CheckArgumentNull(semaphore,
false);
13043 FPL__CheckArgumentMax(initialValue, INT32_MAX,
false);
13045 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is already initialized", semaphore);
13048 HANDLE handle = CreateSemaphoreA(
fpl_null, (LONG)initialValue, INT32_MAX,
fpl_null);
13050 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating semaphore");
13061 FPL__CheckArgumentNullNoRet(semaphore);
13069 FPL__CheckArgumentNull(semaphore,
false);
13071 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
13075 bool result =
false;
13076 if (WaitForSingleObject(semaphore->
internalHandle.win32.handle, timeout) == WAIT_OBJECT_0) {
13084 FPL__CheckArgumentNull(semaphore,
false);
13086 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
13089 bool result =
false;
13090 if (WaitForSingleObject(semaphore->
internalHandle.win32.handle, 0) == WAIT_OBJECT_0) {
13098 FPL__CheckArgumentNull(semaphore,
false);
13100 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
13108 FPL__CheckArgumentNull(semaphore,
false);
13110 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
13113 bool result =
true;
13117 FPL__ERROR(FPL__MODULE_THREADING,
"Failed releasing the semaphore '%p'", semaphore);
13129 DWORD writtenChars = 0;
13130 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
13133 WriteConsoleW(handle, wideBuffer, charsToWrite, &writtenChars,
fpl_null);
13138 DWORD writtenChars = 0;
13139 HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
13142 WriteConsoleW(handle, wideBuffer, charsToWrite, &writtenChars,
fpl_null);
13146 HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
13148 GetConsoleMode(handle, &savedMode);
13149 SetConsoleMode(handle, ENABLE_PROCESSED_INPUT);
13151 if (WaitForSingleObject(handle, INFINITE) == WAIT_OBJECT_0) {
13152 DWORD charsRead = 0;
13154 if (ReadFile(handle, inputBuffer, 1, &charsRead,
fpl_null) != 0) {
13155 result = inputBuffer[0];
13158 SetConsoleMode(handle, savedMode);
13166 FPL__CheckArgumentZero(size,
fpl_null);
13167 void *result = VirtualAlloc(
fpl_null, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
13169 FPL__ERROR(FPL__MODULE_MEMORY,
"Failed allocating memory of %xu bytes", size);
13175 FPL__CheckArgumentNullNoRet(ptr);
13176 VirtualFree(ptr, 0, MEM_RELEASE);
13182fpl_internal const uint64_t FPL__WIN32_TICKS_PER_SEC = 10000000ULL;
13183fpl_internal const uint64_t FPL__WIN32_UNIX_EPOCH_DIFFERENCE = 11644473600ULL;
13190 if (fileTime !=
fpl_null && (fileTime->dwLowDateTime > 0 || fileTime->dwHighDateTime > 0)) {
13192 SYSTEMTIME sysTime;
13193 FileTimeToSystemTime(fileTime, &sysTime);
13194 sysTime.wMilliseconds = 0;
13197 FILETIME withoutMSecs;
13198 SystemTimeToFileTime(&sysTime, &withoutMSecs);
13201 ULARGE_INTEGER ticks;
13202 ticks.LowPart = withoutMSecs.dwLowDateTime;
13203 ticks.HighPart = withoutMSecs.dwHighDateTime;
13206 result = (ticks.QuadPart / FPL__WIN32_TICKS_PER_SEC) - FPL__WIN32_UNIX_EPOCH_DIFFERENCE;
13216 if (unixTimeStamp > 0) {
13217 uint64_t ticks = (unixTimeStamp + FPL__WIN32_UNIX_EPOCH_DIFFERENCE) * FPL__WIN32_TICKS_PER_SEC;
13219 result.dwLowDateTime = (DWORD)ticks;
13220 result.dwHighDateTime = ticks >> 32;
13228 FPL__CheckArgumentNull(outHandle,
false);
13232 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_READ, FILE_SHARE_READ,
fpl_null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
fpl_null);
13233 if (win32FileHandle != INVALID_HANDLE_VALUE) {
13236 outHandle->
internalHandle.win32FileHandle = (
void *)win32FileHandle;
13244 FPL__CheckArgumentNull(outHandle,
false);
13248 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_WRITE, FILE_SHARE_WRITE,
fpl_null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
fpl_null);
13249 if (win32FileHandle != INVALID_HANDLE_VALUE) {
13252 outHandle->
internalHandle.win32FileHandle = (
void *)win32FileHandle;
13260 FPL__CheckArgumentNull(fileHandle, 0);
13261 FPL__CheckArgumentZero(sizeToRead, 0);
13262 FPL__CheckArgumentNull(targetBuffer, 0);
13264 FPL__ERROR(FPL__MODULE_FILES,
"Filehandle is not opened for reading");
13267 uint32_t result = 0;
13268 HANDLE win32FileHandle = (HANDLE)fileHandle->
internalHandle.win32FileHandle;
13269 DWORD bytesRead = 0;
13270 if (ReadFile(win32FileHandle, targetBuffer, (DWORD)sizeToRead, &bytesRead,
fpl_null) == TRUE) {
13271 result = bytesRead;
13277 FPL__CheckArgumentNull(fileHandle, 0);
13278 FPL__CheckArgumentZero(sizeToRead, 0);
13279 FPL__CheckArgumentNull(targetBuffer, 0);
13281 FPL__ERROR(FPL__MODULE_FILES,
"Filehandle is not opened for reading");
13285 uint64_t result = 0;
13286 HANDLE win32FileHandle = (HANDLE)fileHandle->
internalHandle.win32FileHandle;
13287 uint64_t remainingSize = sizeToRead;
13288 uint64_t bufferPos = 0;
13289 const uint64_t MaxDWORD = (uint64_t)(DWORD)-1;
13290 while (remainingSize > 0) {
13291 DWORD bytesRead = 0;
13292 uint8_t *target = (uint8_t *)targetBuffer + bufferPos;
13293 uint64_t size =
fplMin(remainingSize, MaxDWORD);
13295 if (ReadFile(win32FileHandle, target, (DWORD)size, &bytesRead,
fpl_null) == TRUE) {
13296 result = bytesRead;
13300 remainingSize -= bytesRead;
13301 bufferPos += bytesRead;
13307 FPL__CheckArgumentNull(fileHandle, 0);
13308 FPL__CheckArgumentZero(sourceSize, 0);
13309 FPL__CheckArgumentNull(sourceBuffer, 0);
13311 FPL__ERROR(FPL__MODULE_FILES,
"Filehandle is not opened for writing");
13314 HANDLE win32FileHandle = (HANDLE)fileHandle->
internalHandle.win32FileHandle;
13315 uint32_t result = 0;
13316 DWORD bytesWritten = 0;
13317 if (WriteFile(win32FileHandle, sourceBuffer, (DWORD)sourceSize, &bytesWritten,
fpl_null) == TRUE) {
13318 result = bytesWritten;
13324 FPL__CheckArgumentNull(fileHandle, 0);
13325 FPL__CheckArgumentZero(sourceSize, 0);
13326 FPL__CheckArgumentNull(sourceBuffer, 0);
13328 FPL__ERROR(FPL__MODULE_FILES,
"Filehandle is not opened for writing");
13331 HANDLE win32FileHandle = (HANDLE)fileHandle->
internalHandle.win32FileHandle;
13332 uint64_t result = 0;
13333 uint64_t bufferPos = 0;
13334 uint64_t remainingSize = sourceSize;
13335 const uint64_t MaxDWORD = (uint64_t)(DWORD)-1;
13336 while (remainingSize > 0) {
13337 uint8_t *source = (uint8_t *)sourceBuffer + bufferPos;
13338 uint64_t size =
fplMin(remainingSize, MaxDWORD);
13340 DWORD bytesWritten = 0;
13341 if (WriteFile(win32FileHandle, source, (DWORD)size, &bytesWritten,
fpl_null) == TRUE) {
13342 result = bytesWritten;
13346 remainingSize -= bytesWritten;
13347 bufferPos += bytesWritten;
13353 FPL__CheckArgumentNull(fileHandle, 0);
13354 uint32_t result = 0;
13355 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13356 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
13357 DWORD moveMethod = FILE_BEGIN;
13359 moveMethod = FILE_CURRENT;
13361 moveMethod = FILE_END;
13364 r = SetFilePointer(win32FileHandle, (LONG)position,
fpl_null, moveMethod);
13365 result = (uint32_t)r;
13371 FPL__CheckArgumentNull(fileHandle, 0);
13372 uint64_t result = 0;
13373 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13374 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
13375 DWORD moveMethod = FILE_BEGIN;
13377 moveMethod = FILE_CURRENT;
13379 moveMethod = FILE_END;
13383 li.QuadPart = position;
13384 if (SetFilePointerEx(win32FileHandle, li, &r, moveMethod) == TRUE) {
13385 result = (uint64_t)r.QuadPart;
13392 FPL__CheckArgumentNull(fileHandle, 0);
13393 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13394 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
13395 DWORD filePosition = SetFilePointer(win32FileHandle, 0L,
fpl_null, FILE_CURRENT);
13396 if (filePosition != INVALID_SET_FILE_POINTER) {
13397 return filePosition;
13404 FPL__CheckArgumentNull(fileHandle, 0);
13405 uint64_t result = 0;
13406 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13407 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
13411 if (SetFilePointerEx(win32FileHandle, li, &r, FILE_CURRENT) == TRUE) {
13412 result = (uint64_t)r.QuadPart;
13419 FPL__CheckArgumentNull(fileHandle,
false);
13420 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13421 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
13422 bool result = FlushFileBuffers(win32FileHandle) == TRUE;
13430 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
13431 CloseHandle(win32FileHandle);
13437 uint32_t result = 0;
13441 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_READ, FILE_SHARE_READ,
fpl_null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
fpl_null);
13442 if (win32FileHandle != INVALID_HANDLE_VALUE) {
13443 DWORD fileSize = GetFileSize(win32FileHandle,
fpl_null);
13444 result = (uint32_t)fileSize;
13445 CloseHandle(win32FileHandle);
13452 uint64_t result = 0;
13456 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_READ, FILE_SHARE_READ,
fpl_null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
fpl_null);
13457 if (win32FileHandle != INVALID_HANDLE_VALUE) {
13459 if (GetFileSizeEx(win32FileHandle, &li) == TRUE) {
13460 result = (uint64_t)li.QuadPart;
13462 CloseHandle(win32FileHandle);
13469 FPL__CheckArgumentNull(fileHandle, 0);
13470 uint32_t result = 0;
13471 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13472 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
13473 DWORD fileSize = GetFileSize(win32FileHandle,
fpl_null);
13474 result = (uint32_t)fileSize;
13480 FPL__CheckArgumentNull(fileHandle, 0);
13481 uint64_t result = 0;
13482 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13483 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
13485 if (GetFileSizeEx(win32FileHandle, &li) == TRUE) {
13486 result = (uint64_t)li.QuadPart;
13493 FPL__CheckArgumentNull(outStamps,
false);
13497 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_READ, FILE_SHARE_READ,
fpl_null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
fpl_null);
13498 bool result =
false;
13499 if (win32FileHandle != INVALID_HANDLE_VALUE) {
13501 if (GetFileTime(win32FileHandle, ×[0], ×[1], ×[2]) == TRUE) {
13503 outStamps->
creationTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[0]);
13504 outStamps->
lastAccessTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[1]);
13505 outStamps->
lastModifyTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[2]);
13508 CloseHandle(win32FileHandle);
13516 FPL__CheckArgumentNull(fileHandle, 0);
13517 FPL__CheckArgumentNull(outStamps, 0);
13518 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13519 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
13521 if (GetFileTime(win32FileHandle, ×[0], ×[1], ×[2]) == TRUE) {
13523 outStamps->
creationTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[0]);
13524 outStamps->
lastAccessTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[1]);
13525 outStamps->
lastModifyTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[2]);
13533 FPL__CheckArgumentNull(timeStamps,
false);
13537 HANDLE win32FileHandle = CreateFileW(filePathWide, FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE | FILE_SHARE_READ,
fpl_null, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
fpl_null);
13538 bool result =
false;
13539 if (win32FileHandle != INVALID_HANDLE_VALUE) {
13541 times[0] = fpl__Win32ConvertUnixTimestampToFileTime(timeStamps->
creationTime);
13542 times[1] = fpl__Win32ConvertUnixTimestampToFileTime(timeStamps->
lastAccessTime);
13543 times[2] = fpl__Win32ConvertUnixTimestampToFileTime(timeStamps->
lastModifyTime);
13544 if (SetFileTime(win32FileHandle, ×[0], NULL, NULL) == TRUE) {
13547 CloseHandle(win32FileHandle);
13555 bool result =
false;
13559 WIN32_FIND_DATAW findData;
13560 HANDLE searchHandle = FindFirstFileW(filePathWide, &findData);
13561 if (searchHandle != INVALID_HANDLE_VALUE) {
13562 result = !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
13563 FindClose(searchHandle);
13570 FPL__CheckArgumentNull(sourceFilePath,
false);
13571 FPL__CheckArgumentNull(targetFilePath,
false);
13576 bool result = (CopyFileW(sourceFilePathWide, targetFilePathWide, !overwrite) == TRUE);
13581 FPL__CheckArgumentNull(sourceFilePath,
false);
13582 FPL__CheckArgumentNull(targetFilePath,
false);
13587 bool result = (MoveFileW(sourceFilePathWide, targetFilePathWide) == TRUE);
13592 FPL__CheckArgumentNull(filePath,
false);
13595 bool result = (DeleteFileW(filePathWide) == TRUE);
13600 bool result =
false;
13604 WIN32_FIND_DATAW findData;
13605 HANDLE searchHandle = FindFirstFileW(pathWide, &findData);
13606 if (searchHandle != INVALID_HANDLE_VALUE) {
13607 result = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0;
13608 FindClose(searchHandle);
13615 FPL__CheckArgumentNull(path,
false);
13618 bool result = CreateDirectoryW(pathWide,
fpl_null) > 0;
13622 FPL__CheckArgumentNull(path,
false);
13625 bool result = RemoveDirectoryW(pathWide) > 0;
13628fpl_internal void fpl__Win32FillFileEntry(
const char *rootPath,
const WIN32_FIND_DATAW *findData,
fplFileEntry *entry) {
13633 if (findData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
13636 (findData->dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
13637 (findData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
13638 (findData->dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
13639 (findData->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ||
13640 (findData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
13647 if (findData->dwFileAttributes & FILE_ATTRIBUTE_NORMAL) {
13650 if (findData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
13653 if (findData->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
13656 if (findData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
13662 if ((findData->dwFileAttributes & FILE_ATTRIBUTE_READONLY) || (findData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
13668 ul.LowPart = findData->nFileSizeLow;
13669 ul.HighPart = findData->nFileSizeHigh;
13670 entry->
size = (size_t)ul.QuadPart;
13679 FPL__CheckArgumentNull(path,
false);
13680 FPL__CheckArgumentNull(entry,
false);
13688 wchar_t pathAndFilterWide[MAX_PATH + 1];
13690 WIN32_FIND_DATAW findData;
13691 HANDLE searchHandle = FindFirstFileW(pathAndFilterWide, &findData);
13692 bool result =
false;
13693 if (searchHandle != INVALID_HANDLE_VALUE) {
13698 bool foundFirst =
true;
13699 while (foundFirst) {
13700 if (lstrcmpW(findData.cFileName, L
".") == 0 || lstrcmpW(findData.cFileName, L
"..") == 0) {
13701 foundFirst = FindNextFileW(searchHandle, &findData) == TRUE;
13704 fpl__Win32FillFileEntry(path, &findData, entry);
13712 FPL__CheckArgumentNull(entry,
false);
13713 bool result =
false;
13714 if (entry->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13716 WIN32_FIND_DATAW findData;
13719 foundNext = FindNextFileW(searchHandle, &findData) == TRUE;
13721 if (lstrcmpW(findData.cFileName, L
".") == 0 || lstrcmpW(findData.cFileName, L
"..") == 0) {
13728 }
while (foundNext);
13733 FPL__CheckArgumentNullNoRet(entry);
13734 if (entry->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
13736 FindClose(searchHandle);
13745 wchar_t modulePath[MAX_PATH];
13746 GetModuleFileNameW(
fpl_null, modulePath, MAX_PATH);
13747 size_t modulePathLen = lstrlenW(modulePath);
13753 FPL__CheckPlatform(0);
13754 const fpl__Win32Api *wapi = &fpl__global__AppState->win32.winApi;
13755 wchar_t homePath[MAX_PATH];
13756 wapi->shell.SHGetFolderPathW(
fpl_null, CSIDL_PROFILE,
fpl_null, 0, homePath);
13757 size_t homePathLen = lstrlenW(homePath);
13766 const fpl__Win32InitState *initState = &fpl__global__InitState.win32;
13768 if (initState->qpf.QuadPart > 0) {
13769 LARGE_INTEGER time;
13770 QueryPerformanceCounter(&time);
13771 result.win32.qpc.QuadPart = time.QuadPart;
13773 result.win32.ticks = GetTickCount64();
13779 const fpl__Win32InitState *initState = &fpl__global__InitState.win32;
13781 LARGE_INTEGER freq = initState->qpf;
13782 if (freq.QuadPart > 0) {
13783 uint64_t delta = finish.win32.qpc.QuadPart - start.win32.qpc.QuadPart;
13784 result = (
fplSeconds)(delta / (
double)freq.QuadPart);
13786 uint64_t delta = finish.win32.ticks - start.win32.ticks;
13801 FPL__CheckArgumentNull(wideSource, 0);
13802 FPL__CheckArgumentZero(wideSourceLen, 0);
13805 size_t minRequiredLen = result + 1;
13806 FPL__CheckArgumentMin(maxUtf8DestLen, minRequiredLen, 0);
13807 WideCharToMultiByte(CP_UTF8, 0, wideSource, (
int)wideSourceLen, utf8Dest, (
int)maxUtf8DestLen,
fpl_null,
fpl_null);
13808 utf8Dest[result] = 0;
13813 FPL__CheckArgumentNull(utf8Source, 0);
13814 FPL__CheckArgumentZero(utf8SourceLen, 0);
13815 size_t result = MultiByteToWideChar(CP_UTF8, 0, utf8Source, (
int)utf8SourceLen,
fpl_null, 0);
13817 size_t minRequiredLen = result + 1;
13818 FPL__CheckArgumentMin(maxWideDestLen, minRequiredLen, 0);
13819 MultiByteToWideChar(CP_UTF8, 0, utf8Source, (
int)utf8SourceLen, wideDest, (
int)maxWideDestLen);
13820 wideDest[result] = 0;
13829 bool result =
false;
13833 HMODULE libModule = LoadLibraryW(libraryFilePathWide);
13845 HMODULE libModule = (HMODULE)handle->
internalHandle.win32LibraryHandle;
13846 return (
void *)GetProcAddress(libModule, name);
13852 HMODULE libModule = (HMODULE)handle->
internalHandle.win32LibraryHandle;
13853 FreeLibrary(libModule);
13858#if defined(FPL__ENABLE_WINDOW)
13863 FPL__CheckArgumentNull(outSize,
false);
13864 FPL__CheckPlatform(
false);
13865 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
13866 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
13867 const fpl__Win32Api *wapi = &appState->winApi;
13868 bool result =
false;
13870 if (wapi->user.GetClientRect(windowState->windowHandle, &windowRect)) {
13871 outSize->
width = windowRect.right - windowRect.left;
13872 outSize->
height = windowRect.bottom - windowRect.top;
13879 FPL__CheckPlatformNoRet();
13880 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
13881 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
13882 const fpl__Win32Api *wapi = &appState->winApi;
13883 RECT clientRect, windowRect;
13884 if (wapi->user.GetClientRect(windowState->windowHandle, &clientRect) &&
13885 wapi->user.GetWindowRect(windowState->windowHandle, &windowRect)) {
13886 int borderWidth = (windowRect.right - windowRect.left) - (clientRect.right - clientRect.left);
13887 int borderHeight = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
13888 int newWidth = width + borderWidth;
13889 int newHeight = height + borderHeight;
13890 wapi->user.SetWindowPos(windowState->windowHandle,
fpl_null, 0, 0, newWidth, newHeight, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
13895 FPL__CheckPlatform(
false);
13896 const fpl__PlatformAppState *appState = fpl__global__AppState;
13897 bool result = appState->currentSettings.window.isResizable != 0;
13902 FPL__CheckPlatformNoRet();
13903 fpl__PlatformAppState *appState = fpl__global__AppState;
13904 const fpl__Win32WindowState *windowState = &appState->window.win32;
13905 if (!appState->currentSettings.window.isFullscreen && appState->currentSettings.window.isDecorated) {
13906 DWORD style = fpl__win32_GetWindowLong(windowState->windowHandle, GWL_STYLE);
13907 DWORD exStyle = fpl__win32_GetWindowLong(windowState->windowHandle, GWL_EXSTYLE);
13909 style |= (WS_MAXIMIZEBOX | WS_THICKFRAME);
13911 style &= ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
13913 fpl__win32_SetWindowLong(windowState->windowHandle, GWL_STYLE, style);
13914 appState->currentSettings.window.isResizable = value;
13919 FPL__CheckPlatform(
false);
13920 const fpl__PlatformAppState *appState = fpl__global__AppState;
13921 bool result = appState->currentSettings.window.isDecorated != 0;
13926 FPL__CheckPlatformNoRet();
13927 fpl__PlatformAppState *appState = fpl__global__AppState;
13928 const fpl__Win32WindowState *windowState = &appState->window.win32;
13929 const fpl__Win32Api *wapi = &appState->win32.winApi;
13930 if (!appState->currentSettings.window.isFullscreen) {
13931 HWND windowHandle = windowState->windowHandle;
13932 DWORD style = fpl__win32_GetWindowLong(windowHandle, GWL_STYLE);
13933 DWORD exStyle = fpl__win32_GetWindowLong(windowHandle, GWL_EXSTYLE);
13935 style &= ~WS_POPUP;
13936 style |= WS_OVERLAPPEDWINDOW;
13937 if (!appState->currentSettings.window.isResizable) {
13938 style &= ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
13941 style &= ~WS_OVERLAPPEDWINDOW;
13944 fpl__win32_SetWindowLong(windowHandle, GWL_STYLE, style);
13945 wapi->user.SetWindowPos(windowHandle,
fpl_null, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
13946 appState->currentSettings.window.isDecorated = value;
13951 FPL__CheckPlatform(
false);
13952 const fpl__PlatformAppState *appState = fpl__global__AppState;
13953 bool result = appState->currentSettings.window.isFloating != 0;
13958 FPL__CheckPlatformNoRet();
13959 fpl__PlatformAppState *appState = fpl__global__AppState;
13960 const fpl__Win32WindowState *windowState = &appState->window.win32;
13961 const fpl__Win32Api *wapi = &appState->win32.winApi;
13962 if (!appState->currentSettings.window.isFullscreen) {
13964 wapi->user.SetWindowPos(windowState->windowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
13966 wapi->user.SetWindowPos(windowState->windowHandle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
13968 appState->currentSettings.window.isFloating = value;
13973 FPL__CheckPlatform(
false);
13974 fpl__PlatformAppState *appState = fpl__global__AppState;
13975 bool result = appState->currentSettings.window.isFullscreen != 0;
13981 bool result = fpl__Win32SetWindowFullscreen(value, INT32_MAX, INT32_MAX, fullscreenWidth, fullscreenHeight, refreshRate,
true);
13986 bool result = fpl__Win32SetWindowFullscreen(value, x, y, width, height, 0,
false);
13991 bool result = fpl__Win32SetWindowFullscreen(
true, INT32_MAX, INT32_MAX, 0, 0, 0,
false);
13996 bool result = fpl__Win32SetWindowFullscreen(
false, 0, 0, 0, 0, 0,
false);
14001 FPL__CheckArgumentNull(outPos,
false);
14002 FPL__CheckPlatform(
false);
14003 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14004 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14005 const fpl__Win32Api *wapi = &appState->winApi;
14006 bool result =
false;
14008 placement.length =
sizeof(WINDOWPLACEMENT);
14009 if (wapi->user.GetWindowPlacement(windowState->windowHandle, &placement) == TRUE) {
14010 switch (placement.showCmd) {
14013 outPos->
left = placement.ptMaxPosition.x;
14014 outPos->
top = placement.ptMaxPosition.y;
14018 outPos->
left = placement.ptMinPosition.x;
14019 outPos->
top = placement.ptMinPosition.y;
14023 outPos->
left = placement.rcNormalPosition.left;
14024 outPos->
top = placement.rcNormalPosition.top;
14033 FPL__CheckPlatformNoRet();
14034 fpl__PlatformAppState *appState = fpl__global__AppState;
14035 const fpl__Win32AppState *win32AppState = &fpl__global__AppState->win32;
14036 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14037 const fpl__Win32Api *wapi = &win32AppState->winApi;
14038 HWND handle = windowState->windowHandle;
14042 wapi->user.SetWindowTextW(handle, titleWide);
14046 FPL__CheckPlatformNoRet();
14047 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14048 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14049 const fpl__Win32Api *wapi = &appState->winApi;
14051 placement.length =
sizeof(WINDOWPLACEMENT);
14053 if (wapi->user.GetWindowPlacement(windowState->windowHandle, &placement) &&
14054 wapi->user.GetWindowRect(windowState->windowHandle, &windowRect)) {
14055 switch (placement.showCmd) {
14059 placement.rcNormalPosition.left = left;
14060 placement.rcNormalPosition.top = top;
14061 placement.rcNormalPosition.right = placement.rcNormalPosition.left + (windowRect.right - windowRect.left);
14062 placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + (windowRect.bottom - windowRect.top);
14063 wapi->user.SetWindowPlacement(windowState->windowHandle, &placement);
14071 const fpl__PlatformAppState *appState = fpl__global__AppState;
14072 const fpl__Win32AppState *win32AppState = &appState->win32;
14073 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14074 const fpl__Win32Api *wapi = &win32AppState->winApi;
14075 HWND windowHandle = windowState->windowHandle;
14077 if (appState->currentSettings.window.isFullscreen) {
14080 bool isMaximized = !!wapi->user.IsZoomed(windowHandle);
14081 bool isMinimized = !!wapi->user.IsIconic(windowHandle);
14084 }
else if (isMaximized) {
14094 FPL__CheckPlatform(
false);
14095 const fpl__PlatformAppState *appState = fpl__global__AppState;
14096 const fpl__Win32AppState *win32AppState = &appState->win32;
14097 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14098 const fpl__Win32Api *wapi = &win32AppState->winApi;
14099 HWND windowHandle = windowState->windowHandle;
14100 bool result =
false;
14101 switch (newState) {
14104 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
14110 if (!appState->currentSettings.window.isFullscreen && appState->currentSettings.window.isResizable) {
14111 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
14118 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
14129 FPL__CheckPlatformNoRet();
14130 fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14131 windowState->isCursorActive = value;
14134fpl_internal bool fpl__Win32ProcessNextEvent(
const fpl__Win32Api *wapi, fpl__PlatformAppState *appState, fpl__Win32WindowState *windowState) {
14135 bool result =
false;
14136 if (windowState->windowHandle != 0) {
14138 if (wapi->user.PeekMessageW(&msg, windowState->windowHandle, 0, 0, PM_REMOVE) == TRUE) {
14139 fpl__Win32HandleMessage(wapi, appState, windowState, &msg);
14147 FPL__CheckPlatform(
false);
14148 fpl__PlatformAppState *appState = fpl__global__AppState;
14149 fpl__Win32AppState *win32AppState = &appState->win32;
14150 fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14151 const fpl__Win32InitState *win32InitState = &fpl__global__InitState.win32;
14152 const fpl__Win32Api *wapi = &win32AppState->winApi;
14155 if (fpl__PollInternalEvent(ev)) {
14160 if (!fpl__Win32ProcessNextEvent(wapi, appState, windowState)) {
14165 if (fpl__PollInternalEvent(ev)) {
14174 FPL__CheckPlatformNoRet();
14175 fpl__PlatformAppState *appState = fpl__global__AppState;
14176 fpl__Win32AppState *win32AppState = &appState->win32;
14177 fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14178 const fpl__Win32InitState *win32InitState = &fpl__global__InitState.win32;
14179 const fpl__Win32Api *wapi = &win32AppState->winApi;
14180 if (windowState->windowHandle != 0) {
14181 if (windowState->mainFiber !=
fpl_null && windowState->messageFiber !=
fpl_null) {
14182 SwitchToFiber(windowState->messageFiber);
14185 while (wapi->user.PeekMessageW(&msg, windowState->windowHandle, 0, 0, PM_REMOVE)) {
14186 fpl__Win32HandleMessage(wapi, appState, windowState, &msg);
14190 fpl__ClearInternalEvents();
14194 FPL__CheckPlatform(
false);
14195 fpl__PlatformAppState *appState = fpl__global__AppState;
14196 fpl__Win32AppState *win32AppState = &appState->win32;
14197 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14198 const fpl__Win32InitState *win32InitState = &fpl__global__InitState.win32;
14199 const fpl__Win32Api *wapi = &win32AppState->winApi;
14200 fpl__ClearInternalEvents();
14202 fpl__Win32UpdateGameControllers(&appState->currentSettings, win32InitState, &win32AppState->xinput);
14204 bool result = appState->window.isRunning != 0;
14209 FPL__CheckPlatform(
false);
14210 bool result = fpl__global__AppState->window.isRunning != 0;
14215 FPL__CheckPlatformNoRet();
14216 fpl__PlatformAppState *appState = fpl__global__AppState;
14217 const fpl__Win32AppState *win32AppState = &appState->win32;
14218 if (appState->window.isRunning) {
14219 appState->window.isRunning =
false;
14220 const fpl__Win32Api *wapi = &win32AppState->winApi;
14221 wapi->user.PostQuitMessage(0);
14226 FPL__CheckPlatform(
false);
14227 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14228 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14229 const fpl__Win32Api *wapi = &appState->winApi;
14230 bool result =
false;
14231 if (wapi->user.OpenClipboard(windowState->windowHandle)) {
14232 if (wapi->user.IsClipboardFormatAvailable(CF_UNICODETEXT)) {
14233 HGLOBAL dataHandle = wapi->user.GetClipboardData(CF_UNICODETEXT);
14235 const wchar_t *stringValue = (
const wchar_t *)GlobalLock(dataHandle);
14237 GlobalUnlock(dataHandle);
14241 wapi->user.CloseClipboard();
14247 FPL__CheckPlatform(
false);
14248 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14249 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14250 const fpl__Win32Api *wapi = &appState->winApi;
14251 bool result =
false;
14252 if (wapi->user.OpenClipboard(windowState->windowHandle)) {
14254 const size_t bufferLen = textLen + 1;
14255 HGLOBAL handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)bufferLen *
sizeof(
wchar_t));
14257 wchar_t *target = (
wchar_t *)GlobalLock(handle);
14259 GlobalUnlock(handle);
14260 wapi->user.EmptyClipboard();
14261 wapi->user.SetClipboardData(CF_UNICODETEXT, handle);
14264 wapi->user.CloseClipboard();
14270 FPL__CheckArgumentNull(outState,
false);
14271 FPL__CheckPlatform(
false);
14272 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14273 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14274 const fpl__Win32Api *wapi = &appState->winApi;
14276 outState->
modifiers = fpl__Win32GetKeyboardModifiers(wapi);
14277 for (uint32_t keyCode = 0; keyCode < 256; ++keyCode) {
14278 int k = wapi->user.MapVirtualKeyW(MAPVK_VSC_TO_VK, keyCode);
14282 bool down = fpl__Win32IsKeyDown(wapi, k);
14283 fplKey key = fpl__GetMappedKey(&fpl__global__AppState->window, keyCode);
14291 FPL__CheckArgumentNull(outStates,
false);
14292 FPL__CheckPlatform(
false);
14293 fpl__PlatformAppState *platformAppState = fpl__global__AppState;
14295 fpl__Win32AppState *appState = &platformAppState->win32;
14296 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14297 const fpl__Win32Api *wapi = &appState->winApi;
14298 fpl__Win32XInputState *xinputState = &appState->xinput;
14300 if (xinputState->xinputApi.XInputGetState !=
fpl_null) {
14302 QueryPerformanceCounter(&xinputState->lastDeviceSearchTime);
14305 for (DWORD controllerIndex = 0; controllerIndex < XUSER_MAX_COUNT; ++controllerIndex) {
14307 if (xinputState->xinputApi.XInputGetState(controllerIndex, &controllerState) == ERROR_SUCCESS) {
14308 if (!xinputState->isConnected[controllerIndex]) {
14309 xinputState->isConnected[controllerIndex] =
true;
14310 fplStringFormat(xinputState->deviceNames[controllerIndex],
fplArrayCount(xinputState->deviceNames[controllerIndex]),
"XInput-Device [%d]", controllerIndex);
14312 const XINPUT_GAMEPAD *newPadState = &controllerState.Gamepad;
14314 fpl__Win32XInputGamepadToGamepadState(newPadState, targetPadState);
14315 targetPadState->
deviceName = xinputState->deviceNames[controllerIndex];
14317 if (xinputState->isConnected[controllerIndex]) {
14318 xinputState->isConnected[controllerIndex] =
false;
14329 FPL__CheckArgumentNull(outX,
false);
14330 FPL__CheckArgumentNull(outY,
false);
14331 FPL__CheckPlatform(
false);
14332 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14333 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14334 const fpl__Win32Api *wapi = &appState->winApi;
14336 if (wapi->user.GetCursorPos(&p) == TRUE) {
14338 HMONITOR monitor = wapi->user.MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST);
14341 info.cbSize =
sizeof(info);
14342 if (wapi->user.GetMonitorInfoW(monitor, (LPMONITORINFO)&info) != 0) {
14343 *outX = p.x - info.rcMonitor.left;
14344 *outY = p.y - info.rcMonitor.top;
14358 FPL__CheckArgumentNull(outState,
false);
14359 FPL__CheckPlatform(
false);
14360 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14361 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14362 const fpl__Win32Api *wapi = &appState->winApi;
14364 if ((wapi->user.GetCursorPos(&p) == TRUE) && (wapi->user.ScreenToClient(windowState->windowHandle, &p))) {
14369 bool leftDown = fpl__Win32IsKeyDown(wapi, VK_LBUTTON);
14370 bool rightDown = fpl__Win32IsKeyDown(wapi, VK_RBUTTON);
14371 bool middleDown = fpl__Win32IsKeyDown(wapi, VK_MBUTTON);
14381fpl_internal BOOL WINAPI fpl__Win32MonitorCountEnumProc(HMONITOR monitorHandle, HDC hdc, LPRECT rect, LPARAM userData) {
14382 size_t *count = (
size_t *)(uintptr_t)userData;
14383 *count = *count + 1;
14388 FPL__CheckPlatform(0);
14389 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14390 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14391 const fpl__Win32Api *wapi = &appState->winApi;
14393 LPARAM param = (LPARAM)&result;
14394 wapi->user.EnumDisplayMonitors(
fpl_null,
fpl_null, fpl__Win32MonitorCountEnumProc, param);
14400 size_t idLen = lstrlenW(info->szDevice);
14404 outInfo->
virtualSize.
width = info->rcMonitor.right - info->rcMonitor.left;
14406 outInfo->
physicalSize.
width = (info->rcMonitor.right > info->rcMonitor.left) ? (info->rcMonitor.right - info->rcMonitor.left) : (info->rcMonitor.left - info->rcMonitor.right);
14407 outInfo->
physicalSize.
height = (info->rcMonitor.bottom > info->rcMonitor.top) ? (info->rcMonitor.bottom - info->rcMonitor.top) : (info->rcMonitor.top - info->rcMonitor.bottom);
14408 outInfo->
isPrimary = (info->dwFlags & MONITORINFOF_PRIMARY) ? 1 : 0;
14411typedef struct fpl__Win32DisplayEnumState {
14413 const fpl__Win32Api *wapi;
14416} fpl__Win32DisplayEnumState;
14418fpl_internal BOOL WINAPI fpl__Win32MonitorInfoEnumProc(HMONITOR monitorHandle, HDC hdc, LPRECT rect, LPARAM userData) {
14419 fpl__Win32DisplayEnumState *enumState = (fpl__Win32DisplayEnumState *)(uintptr_t)userData;
14420 const fpl__Win32Api *wapi = enumState->wapi;
14421 if (enumState->count < enumState->maxCount) {
14422 fplDisplayInfo *targetInfo = enumState->baseInfo + enumState->count;
14425 info.cbSize =
sizeof(info);
14426 if (wapi->user.GetMonitorInfoW(monitorHandle, (LPMONITORINFO)&info) != 0) {
14427 fpl__Win32FillDisplayInfo(&info, targetInfo);
14429 ++enumState->count;
14430 BOOL result = enumState->count < enumState->maxCount;
14438 FPL__CheckArgumentNull(displays, 0);
14439 FPL__CheckArgumentZero(maxDisplayCount, 0);
14440 FPL__CheckPlatform(0);
14441 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14442 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14443 const fpl__Win32Api *wapi = &appState->winApi;
14444 fpl__Win32DisplayEnumState enumState =
fplZeroInit;
14445 enumState.baseInfo = displays;
14446 enumState.maxCount = maxDisplayCount;
14447 enumState.wapi = wapi;
14448 LPARAM param = (LPARAM)&enumState;
14449 wapi->user.EnumDisplayMonitors(
fpl_null,
fpl_null, fpl__Win32MonitorInfoEnumProc, param);
14450 return(enumState.count);
14453fpl_internal BOOL WINAPI fpl__Win32PrimaryMonitorEnumProc(HMONITOR monitorHandle, HDC hdc, LPRECT rect, LPARAM userData) {
14454 fpl__Win32DisplayEnumState *enumState = (fpl__Win32DisplayEnumState *)(uintptr_t)userData;
14455 const fpl__Win32Api *wapi = enumState->wapi;
14457 info.cbSize =
sizeof(info);
14458 if (wapi->user.GetMonitorInfoW(monitorHandle, (LPMONITORINFO)&info) != 0) {
14459 if (info.dwFlags & MONITORINFOF_PRIMARY) {
14461 fpl__Win32FillDisplayInfo(&info, enumState->baseInfo);
14462 enumState->count = 1;
14470 FPL__CheckArgumentNull(display,
false);
14471 FPL__CheckPlatform(
false);
14472 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14473 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14474 const fpl__Win32Api *wapi = &appState->winApi;
14475 fpl__Win32DisplayEnumState enumState =
fplZeroInit;
14476 enumState.baseInfo = display;
14477 enumState.maxCount = 1;
14478 enumState.wapi = wapi;
14479 LPARAM param = (LPARAM)&enumState;
14480 wapi->user.EnumDisplayMonitors(
fpl_null,
fpl_null, fpl__Win32PrimaryMonitorEnumProc, param);
14481 bool result = (enumState.count == 1);
14486 FPL__CheckArgumentNull(outDisplay,
false);
14487 FPL__CheckPlatform(
false);
14488 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14489 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14490 const fpl__Win32Api *wapi = &appState->winApi;
14491 HMONITOR foundMonitor = wapi->user.MonitorFromWindow(windowState->windowHandle, MONITOR_DEFAULTTONULL);
14492 bool result =
false;
14495 info.cbSize =
sizeof(info);
14496 if (wapi->user.GetMonitorInfoW(foundMonitor, (LPMONITORINFO)&info) != 0) {
14498 fpl__Win32FillDisplayInfo(&info, outDisplay);
14506 FPL__CheckArgumentNull(outDisplay,
false);
14507 FPL__CheckPlatform(
false);
14508 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14509 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14510 const fpl__Win32Api *wapi = &appState->winApi;
14514 bool result =
false;
14515 HMONITOR foundMonitor = wapi->user.MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
14518 info.cbSize =
sizeof(info);
14519 if (wapi->user.GetMonitorInfoW(foundMonitor, (LPMONITORINFO)&info) != 0) {
14521 fpl__Win32FillDisplayInfo(&info, outDisplay);
14529 FPL__CheckArgumentNull(
id, 0);
14530 FPL__CheckPlatform(0);
14531 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14532 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
14533 const fpl__Win32Api *wapi = &appState->winApi;
14534 wchar_t deviceName[CCHDEVICENAME + 1];
14538 while (wapi->user.EnumDisplaySettingsW(deviceName, (DWORD)result, &devMode)) {
14540 if (result == maxDisplayModeCount) {
14545 outMode->
width = devMode.dmPelsWidth;
14546 outMode->
height = devMode.dmPelsHeight;
14547 outMode->
colorBits = devMode.dmBitsPerPel;
14548 outMode->
refreshRate = devMode.dmDisplayFrequency;
14560 return LOCALE_SNAME;
14562 return LOCALE_SABBREVLANGNAME;
14568 LCTYPE lcType = fpl__Win32GetLocaleLCIDFromFormat(targetFormat);
14570 int r = GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, lcType, bufferWide,
fplArrayCount(bufferWide));
14577 LCTYPE lcType = fpl__Win32GetLocaleLCIDFromFormat(targetFormat);
14579 int r = GetLocaleInfoW(LOCALE_USER_DEFAULT, lcType, bufferWide,
fplArrayCount(bufferWide));
14586 FPL__CheckPlatform(
false);
14587 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
14588 const fpl__Win32Api *wapi = &appState->winApi;
14589 HKL kbLayout = wapi->user.GetKeyboardLayout(GetCurrentThreadId());
14590 LCID langId = (DWORD)(intptr_t)kbLayout & 0xFFFF;
14591 LCTYPE lcType = fpl__Win32GetLocaleLCIDFromFormat(targetFormat);
14593 int r = GetLocaleInfoW(langId, lcType, bufferWide,
fplArrayCount(bufferWide));
14604#if defined(FPL_SUBPLATFORM_POSIX)
14605fpl_internal void fpl__PosixReleaseSubplatform(fpl__PosixAppState *appState) {
14606 fpl__PThreadUnloadApi(&appState->pthreadApi);
14609fpl_internal bool fpl__PosixInitSubplatform(
const fplInitFlags initFlags,
const fplSettings *initSettings, fpl__PosixInitState *initState, fpl__PosixAppState *appState) {
14610 if (!fpl__PThreadLoadApi(&appState->pthreadApi)) {
14611 FPL__ERROR(FPL__MODULE_POSIX,
"Failed initializing PThread API");
14617fpl_internal void fpl__InitWaitTimeSpec(
const uint32_t milliseconds,
struct timespec *outSpec) {
14618 time_t secs = milliseconds / 1000;
14619 uint64_t nanoSecs = (milliseconds - (secs * 1000)) * 1000000;
14620 if (nanoSecs >= 1000000000) {
14621 time_t addonSecs = (time_t)(nanoSecs / 1000000000);
14622 nanoSecs -= (addonSecs * 1000000000);
14625 clock_gettime(CLOCK_REALTIME, outSpec);
14626 outSpec->tv_sec += secs;
14627 outSpec->tv_nsec += nanoSecs;
14630void *fpl__PosixThreadProc(
void *data) {
14632 const fpl__PThreadApi *pthreadApi = &fpl__global__AppState->posix.pthreadApi;
14646 pthreadApi->pthread_exit(data);
14650fpl_internal bool fpl__PosixMutexLock(
const fpl__PThreadApi *pthreadApi, pthread_mutex_t *handle) {
14653 lockRes = pthreadApi->pthread_mutex_lock(handle);
14654 }
while (lockRes == EAGAIN);
14655 bool result = (lockRes == 0);
14659fpl_internal bool fpl__PosixMutexTryLock(
const fpl__PThreadApi *pthreadApi, pthread_mutex_t *handle) {
14662 lockRes = pthreadApi->pthread_mutex_trylock(handle);
14663 }
while (lockRes == EAGAIN);
14664 bool result = (lockRes == 0);
14668fpl_internal bool fpl__PosixMutexUnlock(
const fpl__PThreadApi *pthreadApi, pthread_mutex_t *handle) {
14671 unlockRes = pthreadApi->pthread_mutex_unlock(handle);
14672 }
while (unlockRes == EAGAIN);
14673 bool result = (unlockRes == 0);
14677fpl_internal int fpl__PosixMutexCreate(
const fpl__PThreadApi *pthreadApi, pthread_mutex_t *handle) {
14680 mutexRes = pthreadApi->pthread_mutex_init(handle,
fpl_null);
14681 }
while (mutexRes == EAGAIN);
14686 FPL__CheckArgumentNull(threads,
false);
14687 FPL__CheckArgumentMax(maxCount, FPL_MAX_THREAD_COUNT,
false);
14688 const size_t actualStride = stride > 0 ? stride :
sizeof(
fplThreadHandle *);
14689 for (uint32_t index = 0; index < maxCount; ++index) {
14692 FPL__ERROR(FPL__MODULE_THREADING,
"Thread for index '%d' are not allowed to be null", index);
14697 uint32_t completeCount = 0;
14698 bool isRunning[FPL_MAX_THREAD_COUNT];
14699 for (uint32_t index = 0; index < maxCount; ++index) {
14702 if (!isRunning[index]) {
14708 bool result =
false;
14709 while (completeCount < minCount) {
14710 for (uint32_t index = 0; index < maxCount; ++index) {
14712 if (isRunning[index]) {
14715 isRunning[index] =
false;
14717 if (completeCount >= minCount) {
14736#if defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG) || defined(__GNUC__)
14740 __sync_synchronize();
14743 __sync_synchronize();
14746 __sync_synchronize();
14750 __sync_synchronize();
14751 uint32_t result = __sync_lock_test_and_set(target, value);
14755 __sync_synchronize();
14756 uint64_t result = __sync_lock_test_and_set(target, value);
14760 __sync_synchronize();
14761 int32_t result = __sync_lock_test_and_set(target, value);
14765 __sync_synchronize();
14766 int64_t result = __sync_lock_test_and_set(target, value);
14772 uint32_t result = __sync_fetch_and_add(value, addend);
14777 uint64_t result = __sync_fetch_and_add(value, addend);
14782 int32_t result = __sync_fetch_and_add(value, addend);
14787 int64_t result = __sync_fetch_and_add(value, addend);
14793 uint32_t result = __sync_add_and_fetch(value, addend);
14798 int32_t result = __sync_add_and_fetch(value, addend);
14803 uint64_t result = __sync_add_and_fetch(value, addend);
14808 int64_t result = __sync_add_and_fetch(value, addend);
14814 uint32_t result = __sync_add_and_fetch(value, 1);
14819 uint64_t result = __sync_add_and_fetch(value, 1);
14824 int32_t result = __sync_add_and_fetch(value, 1);
14829 int64_t result = __sync_add_and_fetch(value, 1);
14835 uint32_t result = __sync_val_compare_and_swap(dest, comparand, exchange);
14840 uint64_t result = __sync_val_compare_and_swap(dest, comparand, exchange);
14845 int32_t result = __sync_val_compare_and_swap(dest, comparand, exchange);
14850 int64_t result = __sync_val_compare_and_swap(dest, comparand, exchange);
14856 bool result = __sync_bool_compare_and_swap(dest, comparand, exchange);
14861 bool result = __sync_bool_compare_and_swap(dest, comparand, exchange);
14866 bool result = __sync_bool_compare_and_swap(dest, comparand, exchange);
14871 bool result = __sync_bool_compare_and_swap(dest, comparand, exchange);
14876 uint32_t result = __sync_add_and_fetch(source, 0);
14880 uint64_t result = __sync_add_and_fetch(source, 0);
14884 int32_t result = __sync_add_and_fetch(source, 0);
14888 int64_t result = __sync_add_and_fetch(source, 0);
14893 __sync_synchronize();
14894 __sync_lock_test_and_set(dest, value);
14897 __sync_synchronize();
14898 __sync_lock_test_and_set(dest, value);
14901 __sync_synchronize();
14902 __sync_lock_test_and_set(dest, value);
14905 __sync_synchronize();
14906 __sync_lock_test_and_set(dest, value);
14909# error "This POSIX compiler/platform is not supported!"
14918 clock_gettime(CLOCK_MONOTONIC, &t);
14919 result.posix.seconds = (uint64_t)t.tv_sec;
14920 result.posix.nanoSeconds = (int64_t)t.tv_nsec;
14925 uint64_t deltaSeconds = finish.posix.seconds - start.posix.seconds;
14926 int64_t deltaNanos = finish.posix.nanoSeconds - start.posix.nanoSeconds;
14927 if (deltaNanos < 0) {
14929 deltaNanos += 1000000000L;
14946 FPL__CheckArgumentNull(thread,
false);
14947 FPL__CheckPlatform(
false);
14948 const fpl__PlatformAppState *appState = fpl__global__AppState;
14949 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
14952 if (pthreadApi->pthread_kill(threadHandle, 0) == 0) {
14953 pthreadApi->pthread_join(threadHandle,
fpl_null);
14964 FPL__CheckPlatform(0);
14965 const fpl__PlatformAppState *appState = fpl__global__AppState;
14966 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
14967 pthread_t currentThread = pthreadApi->pthread_self();
14968 uint32_t result = (uint32_t)currentThread;
14973 FPL__CheckArgumentNull(parameters,
fpl_null);
14975 const fpl__PlatformAppState *appState = fpl__global__AppState;
14976 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
14988 pthread_attr_t *attrPtr =
fpl_null;
14989 pthread_attr_t attr;
14990 if (pthreadApi->pthread_attr_init(&attr) == 0) {
14992 int scheduler = -1;
14994#if defined(SCHED_IDLE)
14995 if (pthreadApi->pthread_attr_setschedpolicy(&attr, SCHED_IDLE) == 0) {
14996 scheduler = SCHED_IDLE;
15000#if defined(SCHED_FIFO)
15001 if ((scheduler == -1) && (pthreadApi->pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0)) {
15002 scheduler = SCHED_FIFO;
15005#if defined(SCHED_RR)
15006 if ((scheduler == -1) && (pthreadApi->pthread_attr_setschedpolicy(&attr, SCHED_RR) == 0)) {
15007 scheduler = SCHED_RR;
15012 scheduler = sched_getscheduler(0);
15017 pthreadApi->pthread_attr_setstacksize(&attr, parameters->
stackSize);
15021 if (scheduler != -1) {
15022 struct sched_param sched;
15023 if (pthreadApi->pthread_attr_getschedparam(&attr, &sched) == 0) {
15027 int minPrio = sched_get_priority_min(scheduler);
15028 int maxPrio = sched_get_priority_max(scheduler);
15029 int range = maxPrio - minPrio;
15030 int step = range / maxThreadPrioCount;
15034 priority = minPrio;
15036 priority = maxPrio;
15039 priority = minPrio + threadPrioNumber * step;
15040 if (priority < minPrio) {
15041 priority = minPrio;
15042 }
else if (priority > maxPrio) {
15043 priority = maxPrio;
15047 sched.sched_priority = priority;
15048 pthreadApi->pthread_attr_setschedparam(&attr, &sched);
15059 threadRes = pthreadApi->pthread_create(&thread->
internalHandle.posixThread, attrPtr, fpl__PosixThreadProc, (
void *)thread);
15060 }
while (threadRes == EAGAIN);
15061 if (threadRes != 0) {
15062 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating thread, error code: %d", threadRes);
15064 if (threadRes == 0) {
15072 FPL__ERROR(FPL__MODULE_THREADING,
"All %d threads are in use, you cannot create until you free one", FPL_MAX_THREAD_COUNT);
15078 FPL__CheckArgumentNull(runFunc,
fpl_null);
15080 parameters.
runFunc = runFunc;
15088 const fpl__PlatformAppState *appState = fpl__global__AppState;
15089 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15091 pthread_t curThread = pthreadApi->pthread_self();
15093 int currentSchedulerPolicy;
15094 struct sched_param params;
15095 if (pthreadApi->pthread_getschedparam(curThread, ¤tSchedulerPolicy, ¶ms) != 0) {
15096 FPL__ERROR(FPL__MODULE_THREADING,
"Failed getting scheduler parameters for pthread '%d'", curThread);
15103 int minPrio = sched_get_priority_min(currentSchedulerPolicy);
15104 int maxPrio = sched_get_priority_max(currentSchedulerPolicy);
15105 int range = maxPrio - minPrio;
15106 int step = range / maxThreadPrioCount;
15108 int currentPrio = params.sched_priority;
15111 if (minPrio == maxPrio || currentPrio == minPrio) {
15113 }
else if (currentPrio == maxPrio) {
15116 int index = (currentPrio - minPrio) / step;
15117 fplAssert(index >= 0 && index < maxThreadPrioCount);
15126 FPL__CheckPlatform(
false);
15127 const fpl__PlatformAppState *appState = fpl__global__AppState;
15128 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15130 pthread_t curThread = pthreadApi->pthread_self();
15132 int currentSchedulerPolicy;
15133 struct sched_param params;
15134 if (pthreadApi->pthread_getschedparam(curThread, ¤tSchedulerPolicy, ¶ms) != 0) {
15135 FPL__ERROR(FPL__MODULE_THREADING,
"Failed getting scheduler parameters for pthread '%d'", curThread);
15140 int newSchedulerPolicies[3];
15141 int schedulerPolicyCount = 0;
15142 switch (newPriority) {
15146 newSchedulerPolicies[schedulerPolicyCount++] = currentSchedulerPolicy;
15149#if defined(SCHED_RR)
15150 newSchedulerPolicies[schedulerPolicyCount++] = SCHED_RR;
15152 newSchedulerPolicies[schedulerPolicyCount++] = currentSchedulerPolicy;
15155#if defined(SCHED_FIFO)
15156 newSchedulerPolicies[schedulerPolicyCount++] = SCHED_FIFO;
15158#if defined(SCHED_RR)
15159 newSchedulerPolicies[schedulerPolicyCount++] = SCHED_RR;
15161 newSchedulerPolicies[schedulerPolicyCount++] = currentSchedulerPolicy;
15173 for (
int i = 0; i < schedulerPolicyCount; ++i) {
15174 int policy = newSchedulerPolicies[i];
15175 int minPrio = sched_get_priority_min(policy);
15176 int maxPrio = sched_get_priority_max(policy);
15177 int range = maxPrio - minPrio;
15178 int step = range / maxThreadPrioCount;
15182 priority = minPrio;
15184 priority = maxPrio;
15186 priority = minPrio + threadPrioNumber * step;
15187 if (priority < minPrio) {
15188 priority = minPrio;
15189 }
else if (priority > maxPrio) {
15190 priority = maxPrio;
15193 params.sched_priority = priority;
15194 if (pthreadApi->pthread_setschedparam(curThread, policy, ¶ms) == 0) {
15197 FPL__WARNING(FPL__MODULE_THREADING,
"Failed to set thread priority '%d' with policy '%d'", priority, policy);
15205 FPL__CheckPlatform(
false);
15206 const fpl__PlatformAppState *appState = fpl__global__AppState;
15207 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15208 bool result =
false;
15216 fpl__InitWaitTimeSpec(timeout, &t);
15217 joinRes = pthreadApi->pthread_timedjoin_np(threadHandle,
fpl_null, &t);
15219 joinRes = pthreadApi->pthread_join(threadHandle,
fpl_null);
15222 result = (joinRes == 0);
15228 bool result = fpl__PosixThreadWaitForMultiple(threads, count, count, stride, timeout);
15233 bool result = fpl__PosixThreadWaitForMultiple(threads, 1, count, stride, timeout);
15238 FPL__CheckPlatform(
false);
15239 const fpl__PlatformAppState *appState = fpl__global__AppState;
15240 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15242 if (pthreadApi->pthread_yield !=
fpl_null) {
15243 result = (pthreadApi->pthread_yield() == 0);
15245 result = (sched_yield() == 0);
15253 if (milliseconds > 1000) {
15254 s = milliseconds / 1000;
15255 ms = milliseconds % 1000;
15260 struct timespec input, output;
15262 input.tv_nsec = ms * 1000000;
15263 nanosleep(&input, &output);
15267 FPL__CheckArgumentNull(mutex,
false);
15269 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex '%p' is already initialized", mutex);
15272 FPL__CheckPlatform(
false);
15273 const fpl__PlatformAppState *appState = fpl__global__AppState;
15274 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15275 fplAssert(
sizeof(fpl__POSIXMutexHandle) >=
sizeof(pthread_mutex_t));
15276 pthread_mutex_t mutexHandle;
15277 int mutexRes = fpl__PosixMutexCreate(pthreadApi, &mutexHandle);
15278 if (mutexRes != 0) {
15279 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating POSIX condition");
15289 FPL__CheckPlatformNoRet();
15290 const fpl__PlatformAppState *appState = fpl__global__AppState;
15291 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15293 pthread_mutex_t *handle = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
15294 pthreadApi->pthread_mutex_destroy(handle);
15300 FPL__CheckArgumentNull(mutex,
false);
15301 FPL__CheckPlatform(
false);
15302 const fpl__PlatformAppState *appState = fpl__global__AppState;
15303 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15304 bool result =
false;
15306 pthread_mutex_t *handle = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
15307 result = fpl__PosixMutexLock(pthreadApi, handle);
15313 FPL__CheckArgumentNull(mutex,
false);
15314 FPL__CheckPlatform(
false);
15315 const fpl__PlatformAppState *appState = fpl__global__AppState;
15316 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15317 bool result =
false;
15319 pthread_mutex_t *handle = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
15320 result = fpl__PosixMutexTryLock(pthreadApi, handle);
15326 FPL__CheckArgumentNull(mutex,
false);
15327 FPL__CheckPlatform(
false);
15328 const fpl__PlatformAppState *appState = fpl__global__AppState;
15329 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15330 bool result =
false;
15332 pthread_mutex_t *handle = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
15333 result = fpl__PosixMutexUnlock(pthreadApi, handle);
15339 FPL__CheckArgumentNull(condition,
false);
15340 FPL__CheckPlatform(
false);
15341 const fpl__PlatformAppState *appState = fpl__global__AppState;
15342 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15343 fplAssert(
sizeof(fpl__POSIXConditionVariable) >=
sizeof(pthread_cond_t));
15344 pthread_cond_t handle = PTHREAD_COND_INITIALIZER;
15347 condRes = pthreadApi->pthread_cond_init(&handle,
fpl_null);
15348 }
while (condRes == EAGAIN);
15349 if (condRes == 0) {
15358 FPL__CheckPlatformNoRet();
15359 const fpl__PlatformAppState *appState = fpl__global__AppState;
15360 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15362 pthread_cond_t *handle = (pthread_cond_t *)&condition->
internalHandle.posixCondition;
15363 pthreadApi->pthread_cond_destroy(handle);
15369 FPL__CheckArgumentNull(condition,
false);
15370 FPL__CheckArgumentNull(mutex,
false);
15372 FPL__ERROR(FPL__MODULE_THREADING,
"Condition is not valid");
15376 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex is not valid");
15379 FPL__CheckPlatform(
false);
15380 const fpl__PlatformAppState *appState = fpl__global__AppState;
15381 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15382 pthread_cond_t *cond = (pthread_cond_t *)&condition->
internalHandle.posixCondition;
15383 pthread_mutex_t *mut = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
15386 result = pthreadApi->pthread_cond_wait(cond, mut) == 0;
15389 fpl__InitWaitTimeSpec(timeout, &t);
15390 result = pthreadApi->pthread_cond_timedwait(cond, mut, &t) == 0;
15396 FPL__CheckArgumentNull(condition,
false);
15398 FPL__ERROR(FPL__MODULE_THREADING,
"Condition is not valid");
15401 FPL__CheckPlatform(
false);
15402 const fpl__PlatformAppState *appState = fpl__global__AppState;
15403 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15404 pthread_cond_t *handle = (pthread_cond_t *)&condition->
internalHandle.posixCondition;
15405 bool result = pthreadApi->pthread_cond_signal(handle) == 0;
15410 FPL__CheckArgumentNull(condition,
false);
15412 FPL__ERROR(FPL__MODULE_THREADING,
"Condition is not valid");
15415 FPL__CheckPlatform(
false);
15416 const fpl__PlatformAppState *appState = fpl__global__AppState;
15417 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15418 pthread_cond_t *handle = (pthread_cond_t *)&condition->
internalHandle.posixCondition;
15419 bool result = pthreadApi->pthread_cond_broadcast(handle) == 0;
15424 FPL__CheckArgumentNull(semaphore,
false);
15425 FPL__CheckArgumentMax(initialValue, UINT32_MAX,
false);
15427 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is already initialized", semaphore);
15430 FPL__CheckPlatform(
false);
15432 const fpl__PlatformAppState *appState = fpl__global__AppState;
15433 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15435 int res = pthreadApi->sem_init(&handle, 0, (
int)initialValue);
15437 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating semaphore");
15447 FPL__CheckPlatformNoRet();
15448 const fpl__PlatformAppState *appState = fpl__global__AppState;
15449 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15452 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
15453 pthreadApi->sem_destroy(handle);
15460 FPL__CheckArgumentNull(semaphore,
false);
15462 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
15465 FPL__CheckPlatform(
false);
15466 const fpl__PlatformAppState *appState = fpl__global__AppState;
15467 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15468 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
15471 res = pthreadApi->sem_wait(handle);
15474 fpl__InitWaitTimeSpec(timeout, &t);
15475 res = pthreadApi->sem_timedwait(handle, &t);
15477 bool result = res == 0;
15482 FPL__CheckArgumentNull(semaphore,
false);
15484 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
15487 FPL__CheckPlatform(
false);
15488 const fpl__PlatformAppState *appState = fpl__global__AppState;
15489 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15490 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
15491 int res = pthreadApi->sem_trywait(handle);
15492 bool result = (res == 0);
15497 FPL__CheckArgumentNull(semaphore,
false);
15499 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
15502 FPL__CheckPlatform(0);
15503 const fpl__PlatformAppState *appState = fpl__global__AppState;
15504 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15505 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
15507 int res = pthreadApi->sem_getvalue(handle, &value);
15511 return((int32_t)value);
15515 FPL__CheckArgumentNull(semaphore,
false);
15517 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
15520 FPL__CheckPlatform(0);
15521 const fpl__PlatformAppState *appState = fpl__global__AppState;
15522 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
15523 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
15524 int res = pthreadApi->sem_post(handle);
15525 bool result = (res == 0);
15533 bool result =
false;
15535 void *p = dlopen(libraryFilePath, FPL__POSIX_DL_LOADTYPE);
15550 result = dlsym(p, name);
15567 FPL__CheckArgumentZero(size,
fpl_null);
15570 size_t newSize =
sizeof(size_t) + FPL__MEMORY_PADDING + size;
15571 void *basePtr = mmap(
fpl_null, newSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
15573 *(
size_t *)basePtr = newSize;
15575 void *result = (uint8_t *)basePtr +
sizeof(
size_t) + FPL__MEMORY_PADDING;
15580 FPL__CheckArgumentNullNoRet(ptr);
15582 void *basePtr = (
void *)((uint8_t *)ptr - (FPL__MEMORY_PADDING +
sizeof(size_t)));
15583 size_t storedSize = *(
size_t *)basePtr;
15584 munmap(basePtr, storedSize);
15591 FPL__CheckArgumentNull(outHandle,
false);
15593 int posixFileHandle;
15595 posixFileHandle = open(filePath, O_RDONLY);
15596 }
while (posixFileHandle == -1 && errno == EINTR);
15597 if (posixFileHandle != -1) {
15608 FPL__CheckArgumentNull(outHandle,
false);
15610 int posixFileHandle;
15612 posixFileHandle = open(filePath, O_WRONLY | O_CREAT | O_TRUNC, 0666);
15613 }
while (posixFileHandle == -1 && errno == EINTR);
15614 if (posixFileHandle != -1) {
15624 FPL__CheckArgumentNull(fileHandle, 0);
15625 FPL__CheckArgumentZero(sourceSize, 0);
15626 FPL__CheckArgumentNull(sourceBuffer, 0);
15628 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for writing");
15631 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15634 res = write(posixFileHandle, sourceBuffer, sourceSize);
15635 }
while (res == -1 && errno == EINTR);
15638 result = (size_t)res;
15644 FPL__CheckArgumentNull(fileHandle, 0);
15645 FPL__CheckArgumentZero(sizeToRead, 0);
15646 FPL__CheckArgumentNull(targetBuffer, 0);
15648 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for reading");
15651 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15654 res = read(posixFileHandle, targetBuffer, sizeToRead);
15655 }
while (res == -1 && errno == EINTR);
15656 uint32_t result = 0;
15658 result = (uint32_t)res;
15664 FPL__CheckArgumentNull(fileHandle, 0);
15665 FPL__CheckArgumentZero(sizeToRead, 0);
15666 FPL__CheckArgumentNull(targetBuffer, 0);
15668 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for reading");
15671 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15672 uint64_t result = 0;
15673 uint64_t remainingSize = sizeToRead;
15674 uint64_t bufferPos = 0;
15675 const uint64_t MaxValue = (uint64_t)(
size_t)-1;
15676 while (remainingSize > 0) {
15677 uint8_t *target = (uint8_t *)targetBuffer + bufferPos;
15678 size_t size =
fplMin(remainingSize, MaxValue);
15681 res = read(posixFileHandle, target, size);
15682 }
while (res == -1 && errno == EINTR);
15688 remainingSize -= res;
15695 FPL__CheckArgumentNull(fileHandle, 0);
15696 FPL__CheckArgumentZero(sourceSize, 0);
15697 FPL__CheckArgumentNull(sourceBuffer, 0);
15699 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for writing");
15702 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15705 res = write(posixFileHandle, sourceBuffer, sourceSize);
15706 }
while (res == -1 && errno == EINTR);
15707 uint32_t result = 0;
15709 result = (uint32_t)res;
15715 FPL__CheckArgumentNull(fileHandle, 0);
15716 FPL__CheckArgumentZero(sourceSize, 0);
15717 FPL__CheckArgumentNull(sourceBuffer, 0);
15719 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for writing");
15722 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15723 uint64_t result = 0;
15724 uint64_t remainingSize = sourceSize;
15725 uint64_t bufferPos = 0;
15726 const uint64_t MaxValue = (uint64_t)(
size_t)-1;
15727 while (remainingSize > 0) {
15728 uint8_t *source = (uint8_t *)sourceBuffer + bufferPos;
15729 size_t size =
fplMin(remainingSize, MaxValue);
15732 res = write(posixFileHandle, source, size);
15733 }
while (res == -1 && errno == EINTR);
15737 remainingSize -= res;
15744 FPL__CheckArgumentNull(fileHandle, 0);
15745 uint32_t result = 0;
15747 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15748 int whence = SEEK_SET;
15754 off_t r = lseek(posixFileHandle, position, whence);
15755 result = (uint32_t)r;
15761 FPL__CheckArgumentNull(fileHandle, 0);
15762 uint64_t result = 0;
15764 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15765 int whence = SEEK_SET;
15771 fpl__off64_t r = fpl__lseek64(posixFileHandle, position, whence);
15772 result = (uint64_t)r;
15778 FPL__CheckArgumentNull(fileHandle, 0);
15779 uint32_t result = 0;
15781 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15782 off_t res = lseek(posixFileHandle, 0, SEEK_CUR);
15784 result = (uint32_t)res;
15791 FPL__CheckArgumentNull(fileHandle, 0);
15792 uint64_t result = 0;
15794 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15795 fpl__off64_t r = fpl__lseek64(posixFileHandle, 0, SEEK_CUR);
15797 result = (uint64_t)r;
15804 FPL__CheckArgumentNull(fileHandle,
false);
15805 bool result =
false;
15807 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15808 result = fsync(posixFileHandle) == 0;
15815 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15816 close(posixFileHandle);
15822 uint32_t result = 0;
15824 int posixFileHandle;
15826 posixFileHandle = open(filePath, O_RDONLY);
15827 }
while (posixFileHandle == -1 && errno == EINTR);
15828 if (posixFileHandle != -1) {
15829 off_t res = lseek(posixFileHandle, 0, SEEK_END);
15831 result = (uint32_t)res;
15833 close(posixFileHandle);
15840 uint64_t result = 0;
15842 int posixFileHandle;
15844 posixFileHandle = open(filePath, O_RDONLY);
15845 }
while (posixFileHandle == -1 && errno == EINTR);
15846 if (posixFileHandle != -1) {
15847 fpl__off64_t r = fpl__lseek64(posixFileHandle, 0, SEEK_END);
15849 result = (uint64_t)r;
15851 close(posixFileHandle);
15858 uint32_t result = 0;
15860 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15861 off_t curPos = lseek(posixFileHandle, 0, SEEK_CUR);
15862 if (curPos != -1) {
15863 result = (uint32_t)lseek(posixFileHandle, 0, SEEK_END);
15864 lseek(posixFileHandle, curPos, SEEK_SET);
15871 uint64_t result = 0;
15873 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15874 fpl__off64_t curPos = fpl__lseek64(posixFileHandle, 0, SEEK_CUR);
15875 if (curPos != -1) {
15876 result = (uint64_t)fpl__lseek64(posixFileHandle, 0, SEEK_END);
15877 fpl__lseek64(posixFileHandle, curPos, SEEK_SET);
15883fpl_internal uint64_t fpl__PosixConvertTimeToUnixTimeStamp(
const time_t secs) {
15884 uint64_t result = (uint64_t)secs;
15889 FPL__CheckArgumentNull(outStamps,
false);
15890 bool result =
false;
15892 struct stat statBuf;
15893 if (stat(filePath, &statBuf) != -1) {
15894 outStamps->
creationTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_ctime);
15895 outStamps->
lastAccessTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_atime);
15896 outStamps->
lastModifyTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_mtime);
15904 FPL__CheckArgumentNull(fileHandle,
false);
15905 FPL__CheckArgumentNull(outStamps,
false);
15906 bool result =
false;
15908 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
15909 struct stat statBuf;
15910 if (fstat(posixFileHandle, &statBuf) != -1) {
15911 outStamps->
creationTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_ctime);
15912 outStamps->
lastAccessTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_atime);
15913 outStamps->
lastModifyTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_mtime);
15926 bool result =
false;
15928 result = access(filePath, F_OK) != -1;
15934 FPL__CheckArgumentNull(sourceFilePath,
false);
15935 FPL__CheckArgumentNull(targetFilePath,
false);
15936 if (access(sourceFilePath, F_OK) == -1) {
15937 FPL__ERROR(FPL__MODULE_FILES,
"Source file '%s' does not exits", sourceFilePath);
15940 if (!overwrite && access(sourceFilePath, F_OK) != -1) {
15941 FPL__ERROR(FPL__MODULE_FILES,
"Target file '%s' already exits", targetFilePath);
15944 int inputFileHandle;
15946 inputFileHandle = open(sourceFilePath, O_RDONLY);
15947 }
while (inputFileHandle == -1 && errno == EINTR);
15948 if (inputFileHandle == -1) {
15949 FPL__ERROR(FPL__MODULE_FILES,
"Failed open source file '%s', error code: %d", sourceFilePath, inputFileHandle);
15952 int outputFileHandle;
15954 outputFileHandle = open(targetFilePath, O_WRONLY | O_CREAT | O_TRUNC, 0666);
15955 }
while (outputFileHandle == -1 && errno == EINTR);
15956 if (outputFileHandle == -1) {
15957 close(inputFileHandle);
15958 FPL__ERROR(FPL__MODULE_FILES,
"Failed creating target file '%s', error code: %d", targetFilePath, inputFileHandle);
15961 uint8_t buffer[1024 * 10];
15965 readbytes = read(inputFileHandle, buffer,
fplArrayCount(buffer));
15966 }
while (readbytes == -1 && errno == EINTR);
15967 if (readbytes > 0) {
15968 ssize_t writtenBytes;
15970 writtenBytes = write(outputFileHandle, buffer, readbytes);
15971 }
while (writtenBytes == -1 && errno == EINTR);
15972 if (writtenBytes <= 0) {
15979 close(outputFileHandle);
15980 close(inputFileHandle);
15985 FPL__CheckArgumentNull(sourceFilePath,
false);
15986 FPL__CheckArgumentNull(targetFilePath,
false);
15987 bool result = rename(sourceFilePath, targetFilePath) == 0;
15992 FPL__CheckArgumentNull(filePath,
false);
15993 bool result = unlink(filePath) == 0;
15998 bool result =
false;
16001 result = (stat(path, &sb) == 0) && S_ISDIR(sb.st_mode);
16007 FPL__CheckArgumentNull(path,
false);
16008 bool result = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) == 0;
16012 FPL__CheckArgumentNull(path,
false);
16013 bool result = rmdir(path) == 0;
16029 if (stat(fullPath, &sb) == 0) {
16030 if (S_ISDIR(sb.st_mode)) {
16032 }
else if (S_ISREG(sb.st_mode)) {
16035 entry->
size = (size_t)sb.st_size;
16036 if (dp->d_name[0] ==
'.') {
16040 if (sb.st_mode & S_IRUSR) {
16043 if (sb.st_mode & S_IWUSR) {
16046 if (sb.st_mode & S_IXUSR) {
16049 if (sb.st_mode & S_IRGRP) {
16052 if (sb.st_mode & S_IWGRP) {
16055 if (sb.st_mode & S_IXGRP) {
16058 if (sb.st_mode & S_IROTH) {
16061 if (sb.st_mode & S_IWOTH) {
16064 if (sb.st_mode & S_IXOTH) {
16071 FPL__CheckArgumentNull(path,
false);
16072 FPL__CheckArgumentNull(entry,
false);
16073 DIR *dir = opendir(path);
16089 FPL__CheckArgumentNull(entry,
false);
16090 bool result =
false;
16093 struct dirent *dp = readdir(dirHandle);
16102 dp = readdir(dirHandle);
16105 closedir(dirHandle);
16108 fpl__PosixFillFileEntry(dp, entry);
16116 FPL__CheckArgumentNullNoRet(entry);
16119 closedir(dirHandle);
16128 uid_t uid = geteuid();
16129 struct passwd *pw = getpwuid(uid);
16133 if (nameLen > 0 && nameBuffer !=
fpl_null) {
16134 size_t requiredLen = nameLen + 1;
16135 FPL__CheckArgumentMin(maxNameBufferLen, requiredLen, 0);
16143 size_t result = sysconf(_SC_NPROCESSORS_ONLN);
16148 const char *procNames[] = {
16150 "/proc/curproc/exe",
16151 "/proc/curproc/file",
16156 const char *procName = procNames[i];
16160 char *lastP = buf + (len - 1);
16164 len = (lastP - buf) + 1;
16171 size_t requiredLen = len + 1;
16172 FPL__CheckArgumentMin(maxDestLen, requiredLen, 0);
16183 const char *homeDir = getenv(
"HOME");
16185 int userId = getuid();
16186 struct passwd *userPwd = getpwuid(userId);
16187 homeDir = userPwd->pw_dir;
16191 size_t requiredLen = result + 1;
16192 FPL__CheckArgumentMin(maxDestLen, requiredLen, 0);
16201 struct utsname nameInfos;
16202 if (uname(&nameInfos) == 0) {
16203 const char *machineName = nameInfos.machine;
16212 const char *m = machineName + 4;
16214 while (*p >=
'0' && *p <=
'9') {
16219 if (version == 6) {
16221 }
else if (version >= 7) {
16231 bool result =
false;
16232 struct utsname nameInfos;
16233 if (uname(&nameInfos) == 0) {
16234 const char *kernelName = nameInfos.sysname;
16235 const char *kernelVersion = nameInfos.release;
16236 const char *systemName = nameInfos.version;
16239 fpl__ParseVersionString(kernelVersion, &outInfos->
osVersion);
16257#if defined(FPL_SUBPLATFORM_STD_STRINGS)
16261 FPL__CheckArgumentNull(wideSource, 0);
16262 FPL__CheckArgumentZero(wideSourceLen, 0);
16263 size_t result = wcstombs(
fpl_null, wideSource, wideSourceLen);
16265 size_t requiredLen = result + 1;
16266 FPL__CheckArgumentMin(maxUtf8DestLen, requiredLen, 0);
16267 wcstombs(utf8Dest, wideSource, wideSourceLen);
16268 utf8Dest[result] = 0;
16274 FPL__CheckArgumentNull(utf8Source, 0);
16275 FPL__CheckArgumentZero(utf8SourceLen, 0);
16276 size_t result = mbstowcs(
fpl_null, utf8Source, utf8SourceLen);
16278 size_t requiredLen = result + 1;
16279 FPL__CheckArgumentMin(maxWideDestLen, requiredLen, 0);
16280 mbstowcs(wideDest, utf8Source, utf8SourceLen);
16281 wideDest[result] = 0;
16294#if defined(FPL_SUBPLATFORM_STD_CONSOLE)
16298 fprintf(stdout,
"%s", text);
16303 fprintf(stderr,
"%s", text);
16308 const char result = (c >= 0 && c < 256) ? (
char)c : 0;
16318#if defined(FPL_SUBPLATFORM_X11)
16320#define FPL__X11_DEFAULT_WINDOW_WIDTH 400
16321#define FPL__X11_DEFAULT_WINDOW_HEIGHT 400
16323fpl_internal void fpl__X11ReleaseSubplatform(fpl__X11SubplatformState *subplatform) {
16325 fpl__UnloadX11Api(&subplatform->api);
16328fpl_internal bool fpl__X11InitSubplatform(fpl__X11SubplatformState *subplatform) {
16330 if (!fpl__LoadX11Api(&subplatform->api)) {
16331 FPL__ERROR(FPL__MODULE_X11,
"Failed loading x11 api");
16337fpl_internal void fpl__X11ReleaseWindow(
const fpl__X11SubplatformState *subplatform, fpl__X11WindowState *windowState) {
16339 const fpl__X11Api *x11Api = &subplatform->api;
16340 if (windowState->window) {
16341 FPL_LOG_DEBUG(
"X11",
"Hide window '%d' from display '%p'", (
int)windowState->window, windowState->display);
16342 x11Api->XUnmapWindow(windowState->display, windowState->window);
16343 FPL_LOG_DEBUG(
"X11",
"Destroy window '%d' on display '%p'", (
int)windowState->window, windowState->display);
16344 x11Api->XDestroyWindow(windowState->display, windowState->window);
16345 x11Api->XFlush(windowState->display);
16346 windowState->window = 0;
16348 if (windowState->colorMap) {
16349 FPL_LOG_DEBUG(
"X11",
"Release color map '%d' from display '%p'", (
int)windowState->colorMap, windowState->display);
16350 x11Api->XFreeColormap(windowState->display, windowState->colorMap);
16351 windowState->colorMap = 0;
16353 if (windowState->display) {
16354 FPL_LOG_DEBUG(
"X11",
"Close display '%p'", windowState->display);
16355 x11Api->XCloseDisplay(windowState->display);
16359 FPL_LOG_DEBUG(
"X11",
"Restore previous error handler '%p'", windowState->lastErrorHandler);
16360 x11Api->XSetErrorHandler(windowState->lastErrorHandler);
16370 return fplKey_Backspace;
16375 return fplKey_Return;
16378 return fplKey_Pause;
16380 return fplKey_CapsLock;
16383 return fplKey_Escape;
16385 return fplKey_Space;
16387 return fplKey_PageUp;
16389 return fplKey_PageDown;
16393 return fplKey_Home;
16395 return fplKey_Left;
16399 return fplKey_Right;
16401 return fplKey_Down;
16403 return fplKey_Print;
16405 return fplKey_Insert;
16407 return fplKey_Delete;
16484 return fplKey_LeftSuper;
16486 return fplKey_RightSuper;
16489 return fplKey_NumPad0;
16491 return fplKey_NumPad1;
16493 return fplKey_NumPad2;
16495 return fplKey_NumPad3;
16497 return fplKey_NumPad4;
16499 return fplKey_NumPad5;
16501 return fplKey_NumPad6;
16503 return fplKey_NumPad7;
16505 return fplKey_NumPad8;
16507 return fplKey_NumPad9;
16508 case XK_KP_Multiply:
16509 return fplKey_Multiply;
16512 case XK_KP_Subtract:
16513 return fplKey_Substract;
16515 return fplKey_Decimal;
16517 return fplKey_Divide;
16568 return fplKey_LeftShift;
16570 return fplKey_RightShift;
16572 return fplKey_LeftControl;
16574 return fplKey_RightControl;
16577 return fplKey_LeftAlt;
16578 case XK_Mode_switch:
16579 case XK_ISO_Level3_Shift:
16582 return fplKey_RightAlt;
16596 return fplKey_None;
16603 int iconSourceCount = 0;
16607 iconSources[iconSourceCount++] = windowSettings->
icons[0];
16610 iconSources[iconSourceCount++] = windowSettings->
icons[1];
16613 if (iconSourceCount > 0) {
16614 int targetSize = 0;
16615 for (
int i = 0; i < iconSourceCount; ++i) {
16616 targetSize += 2 + iconSources[i].
width * iconSources[i].
height;
16619 long *data = (
long *)fpl__AllocateTemporaryMemory(
sizeof(
long) * targetSize, 16);
16620 long *target = data;
16622 for (
int i = 0; i < iconSourceCount; ++i) {
16625 *target++ = (int32_t)iconSource->
width;
16626 *target++ = (int32_t)iconSource->height;
16627 const uint32_t *source = (
const uint32_t *)iconSource->data;
16628 for (
int j = 0; j < iconSource->width * iconSource->height; ++j) {
16629 *target++ = (iconSource->data[j * 4 + 0] << 16) | (iconSource->data[j * 4 + 1] << 8) | (iconSource->data[j * 4 + 2] << 0) | (iconSource->data[j * 4 + 3] << 24);
16633 x11Api->XChangeProperty(x11WinState->display, x11WinState->window, x11WinState->netWMIcon, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *)data, targetSize);
16635 fpl__ReleaseTemporaryMemory(data);
16637 x11Api->XDeleteProperty(x11WinState->display, x11WinState->window, x11WinState->netWMIcon);
16640 x11Api->XFlush(x11WinState->display);
16644fpl_internal int fpl__X11ErrorHandler(Display *display, XErrorEvent *ev) {
16645 FPL__CheckPlatform(0);
16646 fpl__PlatformAppState *appState = fpl__global__AppState;
16647 const fpl__X11SubplatformState *subplatform = &appState->x11;
16648 const fpl__X11Api *x11Api = &subplatform->api;
16649 const fpl__X11WindowState *windowState = &appState->window.x11;
16651 if (windowState->lastErrorHandler !=
fpl_null) {
16652 return windowState->lastErrorHandler(display, ev);
16659fpl_internal bool fpl__X11InitWindow(
const fplSettings *initSettings,
fplWindowSettings *currentWindowSettings, fpl__PlatformAppState *appState, fpl__X11SubplatformState *subplatform, fpl__X11WindowState *windowState,
const fpl__SetupWindowCallbacks *setupCallbacks) {
16661 const fpl__X11Api *x11Api = &subplatform->api;
16663 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Set init threads");
16664 x11Api->XInitThreads();
16667 FPL_LOG_DEBUG(
"X11",
"Enable error handler");
16668 windowState->lastErrorHandler = x11Api->XSetErrorHandler(fpl__X11ErrorHandler);
16673 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Open default Display");
16674 windowState->display = x11Api->XOpenDisplay(
fpl_null);
16675 if (windowState->display ==
fpl_null) {
16676 FPL__ERROR(FPL__MODULE_X11,
"Failed opening default Display!");
16679 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Successfully opened default Display: %p", windowState->display);
16681 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Get default screen from display '%p'", windowState->display);
16682 windowState->screen = x11Api->XDefaultScreen(windowState->display);
16683 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Got default screen from display '%p': %d", windowState->display, windowState->screen);
16685 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Get root window from display '%p' and screen '%d'", windowState->display, windowState->screen);
16686 windowState->root = x11Api->XRootWindow(windowState->display, windowState->screen);
16687 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Got root window from display '%p' and screen '%d': %d", windowState->display, windowState->screen, (
int)windowState->root);
16689 bool usePreSetupWindow =
false;
16690 if (setupCallbacks->preSetup !=
fpl_null) {
16691 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Call Pre-Setup for Window");
16692 setupCallbacks->preSetup(appState, appState->initFlags, initSettings);
16695 Visual *visual = windowState->visual;
16696 int colorDepth = windowState->colorDepth;
16698 if (visual !=
fpl_null && colorDepth > 0) {
16699 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Got visual '%p' and color depth '%d' from pre-setup", visual, colorDepth);
16700 windowState->colorMap = colormap = x11Api->XCreateColormap(windowState->display, windowState->root, visual, AllocNone);
16702 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Using default visual, color depth, colormap");
16703 windowState->visual = visual = x11Api->XDefaultVisual(windowState->display, windowState->screen);
16704 windowState->colorDepth = colorDepth = x11Api->XDefaultDepth(windowState->display, windowState->screen);
16705 windowState->colorMap = colormap = x11Api->XDefaultColormap(windowState->display, windowState->screen);
16708 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Using visual: %p", visual);
16709 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Using color depth: %d", colorDepth);
16710 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Using color map: %d", (
int)colormap);
16712 int flags = CWColormap | CWBorderPixel | CWEventMask | CWBitGravity | CWWinGravity;
16715 unsigned long backgroundPixel;
16717 backgroundPixel = 0;
16719 flags |= CWBackPixel;
16720 backgroundPixel = (
unsigned long)((0xFF << 24) | (initWindowSettings->
background.
r << 16) | (initWindowSettings->
background.
g << 8) | initWindowSettings->
background.
b);
16724 swa.colormap = colormap;
16726 StructureNotifyMask |
16727 ExposureMask | FocusChangeMask | VisibilityChangeMask |
16728 EnterWindowMask | LeaveWindowMask | PropertyChangeMask |
16729 KeyPressMask | KeyReleaseMask |
16730 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask;
16731 swa.background_pixel = backgroundPixel;
16732 swa.border_pixel = 0;
16733 swa.bit_gravity = NorthWestGravity;
16734 swa.win_gravity = NorthWestGravity;
16745 windowWidth = FPL__X11_DEFAULT_WINDOW_WIDTH;
16746 windowHeight = FPL__X11_DEFAULT_WINDOW_HEIGHT;
16754 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Create window with (Display='%p', Root='%d', Size=%dx%d, Colordepth='%d', visual='%p', colormap='%d'", windowState->display, (
int)windowState->root, windowWidth, windowHeight, colorDepth, visual, (
int)swa.colormap);
16755 windowState->window = x11Api->XCreateWindow(windowState->display,
16767 if (!windowState->window) {
16768 FPL__ERROR(FPL__MODULE_X11,
"Failed creating window with (Display='%p', Root='%d', Size=%dx%d, Colordepth='%d', visual='%p', colormap='%d'!", windowState->display, (
int)windowState->root, windowWidth, windowHeight, colorDepth, visual, (
int)swa.colormap);
16769 fpl__X11ReleaseWindow(subplatform, windowState);
16772 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Successfully created window with (Display='%p', Root='%d', Size=%dx%d, Colordepth='%d', visual='%p', colormap='%d': %d", windowState->display, (
int)windowState->root, windowWidth, windowHeight, colorDepth, visual, (
int)swa.colormap, (
int)windowState->window);
16775 windowState->utf8String = x11Api->XInternAtom(windowState->display,
"UTF8_STRING", False);
16778 windowState->wmDeleteWindow = x11Api->XInternAtom(windowState->display,
"WM_DELETE_WINDOW", False);
16779 windowState->wmProtocols = x11Api->XInternAtom(windowState->display,
"WM_PROTOCOLS", False);
16780 windowState->wmState = x11Api->XInternAtom(windowState->display,
"WM_STATE", False);
16781 windowState->netWMPing = x11Api->XInternAtom(windowState->display,
"_NET_WM_PING", False);
16782 windowState->netWMState = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE", False);
16783 windowState->netWMStateFocused = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_FOCUSED", False);
16784 windowState->netWMStateFullscreen = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_FULLSCREEN", False);
16785 windowState->netWMStateHidden = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_HIDDEN", False);
16786 windowState->netWMStateMaximizedVert = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_MAXIMIZED_VERT", False);
16787 windowState->netWMStateMaximizedHorz = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_MAXIMIZED_HORZ", False);
16788 windowState->netWMPid = x11Api->XInternAtom(windowState->display,
"_NET_WM_PID", False);
16789 windowState->netWMIcon = x11Api->XInternAtom(windowState->display,
"_NET_WM_ICON", False);
16790 windowState->netWMName = x11Api->XInternAtom(windowState->display,
"_NET_WM_NAME", False);
16791 windowState->netWMIconName = x11Api->XInternAtom(windowState->display,
"_NET_WM_ICON_NAME", False);
16792 windowState->motifWMHints = x11Api->XInternAtom(windowState->display,
"_MOTIF_WM_HINTS", False);
16794 windowState->xdndAware = x11Api->XInternAtom(windowState->display,
"XdndAware", False);
16795 windowState->xdndEnter = x11Api->XInternAtom(windowState->display,
"XdndEnter", False);
16796 windowState->xdndPosition = x11Api->XInternAtom(windowState->display,
"XdndPosition", False);
16797 windowState->xdndStatus = x11Api->XInternAtom(windowState->display,
"XdndStatus", False);
16798 windowState->xdndActionCopy = x11Api->XInternAtom(windowState->display,
"XdndActionCopy", False);
16799 windowState->xdndDrop = x11Api->XInternAtom(windowState->display,
"XdndDrop", False);
16800 windowState->xdndFinished = x11Api->XInternAtom(windowState->display,
"XdndFinished", False);
16801 windowState->xdndSelection = x11Api->XInternAtom(windowState->display,
"XdndSelection", False);
16802 windowState->xdndTypeList = x11Api->XInternAtom(windowState->display,
"XdndTypeList", False);
16803 windowState->textUriList = x11Api->XInternAtom(windowState->display,
"text/uri-list", False);
16807 Atom protocols[] = {
16808 windowState->wmDeleteWindow,
16809 windowState->netWMPing
16811 x11Api->XSetWMProtocols(windowState->display, windowState->window, protocols,
fplArrayCount(protocols));
16816 const long pid = getpid();
16817 x11Api->XChangeProperty(windowState->display, windowState->window, windowState->netWMPid, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *)&pid, 1);
16826 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Show window '%d' on display '%p' with title '%s'", (
int)windowState->window, windowState->display, nameBuffer);
16827 fpl__X11LoadWindowIcon(x11Api, windowState, currentWindowSettings);
16829 x11Api->XMapWindow(windowState->display, windowState->window);
16830 x11Api->XFlush(windowState->display);
16835 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Build X11 Keymap");
16837 for (
int keyCode = 8; keyCode <= 255; ++keyCode) {
16839 KeySym *keySyms = x11Api->XGetKeyboardMapping(windowState->display, keyCode, 1, &dummy);
16840 KeySym keySym = keySyms[0];
16841 fplKey mappedKey = fpl__X11TranslateKeySymbol(keySym);
16842 appState->window.keyMap[keyCode] = mappedKey;
16843 x11Api->XFree(keySyms);
16852 const Atom version = FPL__XDND_VERSION;
16853 x11Api->XChangeProperty(windowState->display, windowState->window, windowState->xdndAware, XA_ATOM, 32, PropModeReplace, (
unsigned char *)&version, 1);
16856 appState->window.isRunning =
true;
16863 if (state & ShiftMask) {
16867 if (state & ControlMask) {
16871 if (state & Mod1Mask) {
16875 if (state & Mod4Mask) {
16882fpl_internal unsigned long fpl__X11GetWindowProperty(
const fpl__X11Api *x11Api, Display *display, Window window, Atom prop, Atom type,
unsigned char **value) {
16885 unsigned long itemCount, bytesAfter;
16886 x11Api->XGetWindowProperty(display, window, prop, 0, LONG_MAX, False, type, &actualType, &actualFormat, &itemCount, &bytesAfter, value);
16890fpl_internal const int fpl__X11GetWMState(
const fpl__X11Api *x11Api, fpl__X11WindowState *windowState) {
16891 struct {
int state; Window icon; } *value = NULL;
16892 unsigned long numItems = fpl__X11GetWindowProperty(x11Api, windowState->display, windowState->window, windowState->wmState, windowState->wmState, (
unsigned char **)&value);
16893 int state = WithdrawnState;
16895 state = value->state;
16896 x11Api->XFree(value);
16901#define fpl__X11NetWMStateHiddenFlag (1 << 0)
16902#define fpl__X11NetWMStateMaximizedFlag (1 << 1)
16903#define fpl__X11NetWMStateFullscreenFlag (1 << 2)
16905fpl_internal unsigned int fpl__X11GetNetWMState(
const fpl__X11Api *x11Api, fpl__X11WindowState *windowState) {
16906 Atom *atoms = NULL;
16907 unsigned long numItems = fpl__X11GetWindowProperty(x11Api, windowState->display, windowState->window, windowState->netWMState, XA_ATOM, (
unsigned char **)&atoms);
16908 unsigned int flags = 0;
16910 int i, maximized = 0;
16911 for (i = 0; i < numItems; ++i) {
16912 if (atoms[i] == windowState->netWMStateHidden) {
16913 flags |= fpl__X11NetWMStateHiddenFlag;
16914 }
else if (atoms[i] == windowState->netWMStateMaximizedVert) {
16916 }
else if (atoms[i] == windowState->netWMStateMaximizedHorz) {
16918 }
else if (atoms[i] == windowState->netWMStateFullscreen) {
16919 flags |= fpl__X11NetWMStateFullscreenFlag;
16922 if (maximized == 3) {
16923 flags |= fpl__X11NetWMStateMaximizedFlag;
16927 XWindowAttributes attr;
16929 x11Api->XGetWindowAttributes(windowState->display, windowState->window, &attr);
16930 if (attr.map_state == IsUnmapped) {
16931 flags |= fpl__X11NetWMStateHiddenFlag;
16934 x11Api->XFree(atoms);
16939fpl_internal fpl__X11WindowStateInfo fpl__X11GetWindowStateInfo(
const fpl__X11Api *x11Api, fpl__X11WindowState *windowState) {
16941 const int state = fpl__X11GetWMState(x11Api, windowState);
16942 unsigned int flags = fpl__X11GetNetWMState(x11Api, windowState);
16943 if (state == NormalState) {
16945 }
else if (state == IconicState) {
16950 if (flags & fpl__X11NetWMStateHiddenFlag) {
16953 if (flags & fpl__X11NetWMStateFullscreenFlag) {
16955 }
else if (state != IconicState && flags & fpl__X11NetWMStateMaximizedFlag) {
16961fpl_internal fpl__X11WindowStateInfo fpl__X11ReconcilWindowStateInfo(fpl__X11WindowStateInfo *last, fpl__X11WindowStateInfo *next) {
16963 if (last->state != next->state) {
16964 change.state = next->state;
16966 if (last->visibility != next->visibility) {
16967 change.visibility = next->visibility;
16972fpl_internal void *fpl__X11ParseUriPaths(
const char *text,
size_t *size,
int *count,
int textLength) {
16973 const char *textCursor = text;
16974 const char *textEnd = text + textLength;
16977 while (*textCursor !=
'\0' || textCursor != textEnd) {
16978 if (*textCursor ==
'\r' && *(textCursor + 1) ==
'\n')
16983 size_t filesTableSize = fileCount *
sizeof(
char **);
16985 size_t filesMemorySize = filesTableSize + FPL__ARBITARY_PADDING + maxFileStride * fileCount;
16986 void *filesTableMemory = fpl__AllocateDynamicMemory(filesMemorySize, 8);
16987 char **filesTable = (
char **)filesTableMemory;
16988 for (
int fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
16989 filesTable[fileIndex] = (
char *)((uint8_t *)filesTableMemory + filesTableSize + FPL__ARBITARY_PADDING + fileIndex * maxFileStride);
16991 for (
int fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
16992 char *file = filesTable[fileIndex];
16993 const char *line = textCursor;
16995 while (*textCursor !=
'\r' && (*textCursor !=
'\0' || textCursor != textEnd)) {
17005 *size = filesMemorySize;
17006 *count = fileCount;
17007 return filesTableMemory;
17010fpl_internal void fpl__X11HandleTextInputEvent(
const fpl__X11Api *x11Api, fpl__PlatformWindowState *winState,
const uint64_t keyCode, XEvent *ev) {
17013 if (x11Api->XLookupString(&ev->xkey, buf, 32, &keysym, NULL) != NoSymbol) {
17016 uint32_t textCode = (uint32_t)wideBuffer[0];
17017 if (textCode > 0) {
17018 fpl__HandleKeyboardInputEvent(winState, keyCode, textCode);
17023fpl_internal void fpl__X11HandleEvent(
const fpl__X11SubplatformState *subplatform, fpl__PlatformAppState *appState, XEvent *ev) {
17025 fpl__PlatformWindowState *winState = &appState->window;
17026 fpl__X11WindowState *x11WinState = &winState->x11;
17027 fpl__X11WindowStateInfo *lastX11WinInfo = &x11WinState->lastWindowStateInfo;
17028 const fpl__X11Api *x11Api = &appState->x11.api;
17030 if (appState->currentSettings.window.callbacks.eventCallback !=
fpl_null) {
17031 appState->currentSettings.window.callbacks.eventCallback(
fplGetPlatformType(), x11WinState, ev, appState->currentSettings.window.callbacks.eventUserData);
17034 switch (ev->type) {
17035 case ConfigureNotify:
17037# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
17039 if (appState->initSettings.video.isAutoSize) {
17040 uint32_t w = (uint32_t)ev->xconfigure.width;
17041 uint32_t h = (uint32_t)ev->xconfigure.height;
17047 if (ev->xconfigure.width != lastX11WinInfo->size.width || ev->xconfigure.height != lastX11WinInfo->size.height) {
17049 lastX11WinInfo->size.width = (int32_t)ev->xconfigure.width;
17050 lastX11WinInfo->size.height = (int32_t)ev->xconfigure.height;
17054 if (ev->xconfigure.x != lastX11WinInfo->position.left || ev->xconfigure.y != lastX11WinInfo->position.top) {
17056 lastX11WinInfo->position.left = (int32_t)ev->xconfigure.x;
17057 lastX11WinInfo->position.top = (int32_t)ev->xconfigure.y;
17061 case ClientMessage:
17063 if (ev->xclient.message_type == x11WinState->wmProtocols) {
17064 const Atom protocol = (Atom)ev->xclient.data.l[0];
17065 if (protocol != None) {
17066 if (protocol == x11WinState->wmDeleteWindow) {
17068 winState->isRunning =
false;
17070 }
else if (protocol == x11WinState->netWMPing) {
17072 XEvent reply = *ev;
17073 reply.xclient.window = x11WinState->root;
17074 x11Api->XSendEvent(x11WinState->display, x11WinState->root, False, SubstructureNotifyMask | SubstructureRedirectMask, &reply);
17077 }
else if (ev->xclient.message_type == x11WinState->xdndEnter) {
17079 unsigned long i, count;
17080 Atom *formats = NULL;
17081 bool list = ev->xclient.data.l[1] & 1;
17082 x11WinState->xdnd.source = ev->xclient.data.l[0];
17083 x11WinState->xdnd.version = ev->xclient.data.l[1] >> 24;
17084 x11WinState->xdnd.format = None;
17085 if (x11WinState->xdnd.version > FPL__XDND_VERSION) {
17089 count = fpl__X11GetWindowProperty(x11Api, x11WinState->display, x11WinState->xdnd.source, x11WinState->xdndTypeList, XA_ATOM, (
unsigned char **)&formats);
17092 formats = (Atom *)ev->xclient.data.l + 2;
17094 for (i = 0; i < count; ++i) {
17095 if (formats[i] == x11WinState->textUriList) {
17096 x11WinState->xdnd.format = x11WinState->textUriList;
17100 if (list && formats) {
17101 x11Api->XFree(formats);
17103 }
else if (ev->xclient.message_type == x11WinState->xdndDrop) {
17105 Time time = CurrentTime;
17106 if (x11WinState->xdnd.version > FPL__XDND_VERSION) {
17109 if (x11WinState->xdnd.format) {
17110 if (x11WinState->xdnd.version >= 1) {
17111 time = ev->xclient.data.l[2];
17114 x11Api->XConvertSelection(x11WinState->display, x11WinState->xdndSelection, x11WinState->xdnd.format, x11WinState->xdndSelection, x11WinState->window, time);
17115 }
else if (x11WinState->xdnd.version >= 2) {
17119 reply.type = ClientMessage;
17120 reply.xclient.window = x11WinState->xdnd.source;
17121 reply.xclient.message_type = x11WinState->xdndFinished;
17122 reply.xclient.format = 32;
17123 reply.xclient.data.l[0] = x11WinState->window;
17124 reply.xclient.data.l[1] = 0;
17125 reply.xclient.data.l[2] = None;
17127 x11Api->XSendEvent(x11WinState->display, x11WinState->xdnd.source, False, NoEventMask, &reply);
17128 x11Api->XFlush(x11WinState->display);
17130 }
else if (ev->xclient.message_type == x11WinState->xdndPosition) {
17134 const int xabs = (ev->xclient.data.l[2] >> 16) & 0xffff;
17135 const int yabs = (ev->xclient.data.l[2]) & 0xffff;
17136 if (x11WinState->xdnd.version > FPL__XDND_VERSION) {
17142 reply.type = ClientMessage;
17143 reply.xclient.window = x11WinState->xdnd.source;
17144 reply.xclient.message_type = x11WinState->xdndStatus;
17145 reply.xclient.format = 32;
17146 reply.xclient.data.l[0] = x11WinState->window;
17147 reply.xclient.data.l[2] = 0;
17148 reply.xclient.data.l[3] = 0;
17150 if (x11WinState->xdnd.format) {
17152 reply.xclient.data.l[1] = 1;
17153 if (x11WinState->xdnd.version >= 2)
17154 reply.xclient.data.l[4] = x11WinState->xdndActionCopy;
17156 x11Api->XSendEvent(x11WinState->display, x11WinState->xdnd.source, False, NoEventMask, &reply);
17157 x11Api->XFlush(x11WinState->display);
17161 case SelectionNotify:
17163 if (ev->xselection.property == x11WinState->xdndSelection) {
17166 const unsigned long result = fpl__X11GetWindowProperty(x11Api, x11WinState->display, ev->xselection.requestor, ev->xselection.property, ev->xselection.target, (
unsigned char **)&data);
17168 size_t filesTableSize;
17170 void *filesTable = fpl__X11ParseUriPaths(data, &filesTableSize, &fileCount, result);
17172 memory.
size = filesTableSize;
17173 memory.
base = filesTable;
17174 fpl__PushWindowDropFilesEvent(NULL, fileCount, (
const char **)filesTable, &memory);
17177 x11Api->XFree(data);
17179 if (x11WinState->xdnd.version >= 2) {
17183 reply.type = ClientMessage;
17184 reply.xclient.window = x11WinState->xdnd.source;
17185 reply.xclient.message_type = x11WinState->xdndFinished;
17186 reply.xclient.format = 32;
17187 reply.xclient.data.l[0] = x11WinState->window;
17188 reply.xclient.data.l[1] = result;
17189 reply.xclient.data.l[2] = x11WinState->xdndActionCopy;
17191 x11Api->XSendEvent(x11WinState->display, x11WinState->xdnd.source, False, NoEventMask, &reply);
17192 x11Api->XFlush(x11WinState->display);
17200 if (!appState->currentSettings.input.disabledEvents) {
17201 int keyState = ev->xkey.state;
17202 uint64_t keyCode = (uint64_t)ev->xkey.keycode;
17203 Time keyTime = ev->xkey.time;
17204 Time lastPressTime = winState->keyPressTimes[keyCode];
17205 Time diffTime = keyTime - lastPressTime;
17206 FPL_LOG_INFO(
"X11",
"Diff for key '%llu', time: %lu, diff: %lu, last: %lu", keyCode, keyTime, diffTime, lastPressTime);
17207 if (diffTime == keyTime || (diffTime > 0 && diffTime < (1 << 31))) {
17209 fpl__HandleKeyboardButtonEvent(winState, (uint64_t)keyTime, keyCode, fpl__X11TranslateModifierFlags(keyState),
fplButtonState_Press,
false);
17210 fpl__X11HandleTextInputEvent(x11Api, winState, keyCode, ev);
17212 winState->keyPressTimes[keyCode] = keyTime;
17220 if (!appState->currentSettings.input.disabledEvents) {
17221 bool isRepeat =
false;
17222 if (x11Api->XEventsQueued(x11WinState->display, QueuedAfterReading)) {
17224 x11Api->XPeekEvent(x11WinState->display, &nextEvent);
17225 if ((nextEvent.type == KeyPress) && (nextEvent.xkey.time == ev->xkey.time) && (nextEvent.xkey.keycode == ev->xkey.keycode)) {
17227 x11Api->XNextEvent(x11WinState->display, ev);
17232 int keyState = ev->xkey.state;
17233 uint64_t keyCode = (uint64_t)ev->xkey.keycode;
17236 fpl__X11HandleTextInputEvent(x11Api, winState, keyCode, ev);
17237 fpl__HandleKeyboardButtonEvent(winState, (uint64_t)ev->xkey.time, (uint64_t)keyCode, fpl__X11TranslateModifierFlags(keyState),
fplButtonState_Repeat,
false);
17239 fpl__HandleKeyboardButtonEvent(winState, (uint64_t)ev->xkey.time, (uint64_t)keyCode, fpl__X11TranslateModifierFlags(keyState),
fplButtonState_Release,
true);
17246 int x = ev->xbutton.x;
17247 int y = ev->xbutton.y;
17249 if (!appState->currentSettings.input.disabledEvents) {
17251 if (ev->xbutton.button == Button1) {
17253 }
else if (ev->xbutton.button == Button2) {
17255 }
else if (ev->xbutton.button == Button3) {
17261 if (ev->xbutton.button == Button4) {
17262 fpl__HandleMouseWheelEvent(winState, x, y, 1.0f);
17263 }
else if (ev->xbutton.button == Button5) {
17264 fpl__HandleMouseWheelEvent(winState, x, y, -1.0f);
17268 case ButtonRelease:
17271 if (!appState->currentSettings.input.disabledEvents) {
17272 int x = ev->xbutton.x;
17273 int y = ev->xbutton.y;
17274 if (ev->xbutton.button == Button1) {
17276 }
else if (ev->xbutton.button == Button2) {
17278 }
else if (ev->xbutton.button == Button3) {
17287 if (!appState->currentSettings.input.disabledEvents) {
17288 fpl__HandleMouseMoveEvent(winState, ev->xmotion.x, ev->xmotion.y);
17295 if (appState->currentSettings.window.callbacks.exposedCallback !=
fpl_null) {
17296 appState->currentSettings.window.callbacks.exposedCallback(
fplGetPlatformType(), x11WinState, ev, appState->currentSettings.window.callbacks.exposedUserData);
17304 if (ev->xfocus.mode == NotifyGrab || ev->xfocus.mode == NotifyUngrab) {
17314 if (ev->xfocus.mode == NotifyGrab || ev->xfocus.mode == NotifyUngrab) {
17320 case PropertyNotify:
17322 if (ev->xproperty.atom == x11WinState->netWMState || ev->xproperty.atom == x11WinState->wmState) {
17323 fpl__X11WindowStateInfo nextWindowStateInfo = fpl__X11GetWindowStateInfo(x11Api, x11WinState);
17324 fpl__X11WindowStateInfo changedWindowStateInfo = fpl__X11ReconcilWindowStateInfo(&x11WinState->lastWindowStateInfo, &nextWindowStateInfo);
17325 switch (changedWindowStateInfo.visibility) {
17335 switch (changedWindowStateInfo.state) {
17348 x11WinState->lastWindowStateInfo.state = nextWindowStateInfo.state;
17349 x11WinState->lastWindowStateInfo.visibility = nextWindowStateInfo.visibility;
17359 FPL__CheckPlatform(
false);
17360 bool result = fpl__global__AppState->window.isRunning;
17365 FPL__CheckPlatformNoRet();
17366 fpl__PlatformAppState *appState = fpl__global__AppState;
17367 if (appState->window.isRunning) {
17368 appState->window.isRunning =
false;
17369 const fpl__X11SubplatformState *subplatform = &appState->x11;
17370 const fpl__X11Api *x11Api = &subplatform->api;
17371 const fpl__X11WindowState *windowState = &appState->window.x11;
17373 ev.type = ClientMessage;
17374 ev.xclient.window = windowState->window;
17375 ev.xclient.message_type = windowState->wmProtocols;
17376 ev.xclient.format = 32;
17377 ev.xclient.data.l[0] = windowState->wmDeleteWindow;
17378 ev.xclient.data.l[1] = 0;
17379 x11Api->XSendEvent(windowState->display, windowState->root, False, SubstructureRedirectMask | SubstructureNotifyMask, &ev);
17383fpl_internal bool fpl__X11ProcessNextEvent(
const fpl__X11SubplatformState *subplatform, fpl__PlatformAppState *appState) {
17384 bool result =
false;
17385 const fpl__X11Api *x11Api = &subplatform->api;
17386 fpl__X11WindowState *windowState = &appState->window.x11;
17387 if (x11Api->XPending(windowState->display)) {
17389 x11Api->XNextEvent(windowState->display, &ev);
17390 fpl__X11HandleEvent(subplatform, appState, &ev);
17397 FPL__CheckPlatform(
false);
17398 fpl__PlatformAppState *appState = fpl__global__AppState;
17399 const fpl__X11SubplatformState *subplatform = &appState->x11;
17400 const fpl__X11Api *x11Api = &subplatform->api;
17401 const fpl__X11WindowState *windowState = &appState->window.x11;
17404 if (fpl__PollInternalEvent(ev)) {
17409 if (!fpl__X11ProcessNextEvent(subplatform, appState)) {
17414 if (fpl__PollInternalEvent(ev)) {
17423 FPL__CheckPlatformNoRet();
17424 fpl__PlatformAppState *appState = fpl__global__AppState;
17425 const fpl__X11SubplatformState *subplatform = &appState->x11;
17426 const fpl__X11Api *x11Api = &subplatform->api;
17427 const fpl__X11WindowState *windowState = &appState->window.x11;
17428 while (x11Api->XPending(windowState->display)) {
17430 x11Api->XNextEvent(windowState->display, &ev);
17431 fpl__X11HandleEvent(subplatform, appState, &ev);
17433 fpl__ClearInternalEvents();
17437 FPL__CheckPlatform(
false);
17438 fpl__PlatformAppState *appState = fpl__global__AppState;
17439 const fpl__X11SubplatformState *subplatform = &appState->x11;
17440 const fpl__X11Api *x11Api = &subplatform->api;
17441 const fpl__X11WindowState *windowState = &appState->window.x11;
17443 fpl__ClearInternalEvents();
17446#if defined(FPL_PLATFORM_LINUX)
17448 fpl__LinuxAppState *linuxAppState = &appState->plinux;
17449 fpl__LinuxPollGameControllers(&appState->currentSettings, &linuxAppState->controllersState,
true);
17453 bool result = appState->window.isRunning;
17462 FPL__CheckArgumentNull(outSize,
false);
17463 FPL__CheckPlatform(
false);
17464 fpl__PlatformAppState *appState = fpl__global__AppState;
17465 const fpl__X11SubplatformState *subplatform = &appState->x11;
17466 const fpl__X11Api *x11Api = &subplatform->api;
17467 const fpl__X11WindowState *windowState = &appState->window.x11;
17468 XWindowAttributes attribs;
17469 x11Api->XGetWindowAttributes(windowState->display, windowState->window, &attribs);
17470 outSize->
width = attribs.width;
17471 outSize->
height = attribs.height;
17476 fpl__PlatformAppState *appState = fpl__global__AppState;
17477 FPL__CheckPlatformNoRet();
17478 const fpl__X11SubplatformState *subplatform = &appState->x11;
17479 const fpl__X11Api *x11Api = &subplatform->api;
17480 const fpl__X11WindowState *windowState = &appState->window.x11;
17481 x11Api->XResizeWindow(windowState->display, windowState->window, width, height);
17482 x11Api->XFlush(windowState->display);
17495 FPL__CheckPlatform(
false);
17496 fpl__PlatformAppState *appState = fpl__global__AppState;
17497 bool result = appState->currentSettings.window.isDecorated;
17501#define FPL__MWM_HINTS_DECORATIONS (1L << 1)
17502#define FPL__MWM_HINTS_FUNCTIONS (1L << 0)
17503#define FPL__MWM_FUNC_ALL (1L<<0)
17504#define FPL__PROPERTY_MOTIF_WM_HINTS_ELEMENT_COUNT 5
17507 unsigned long flags;
17508 unsigned long functions;
17509 unsigned long decorations;
17511 unsigned long status;
17512} fpl__MotifWMHints;
17515 FPL__CheckPlatformNoRet();
17516 fpl__PlatformAppState *appState = fpl__global__AppState;
17517 const fpl__X11SubplatformState *subplatform = &appState->x11;
17518 const fpl__X11Api *x11Api = &subplatform->api;
17519 const fpl__X11WindowState *windowState = &appState->window.x11;
17522 hints.flags = FPL__MWM_HINTS_DECORATIONS | FPL__MWM_HINTS_FUNCTIONS;
17523 hints.decorations = value ? 1 : 0;
17524 hints.functions = value ? FPL__MWM_FUNC_ALL : 0;
17526 x11Api->XChangeProperty(windowState->display, windowState->window,
17527 windowState->motifWMHints,
17528 windowState->motifWMHints, 32,
17530 (
unsigned char *)&hints,
17531 FPL__PROPERTY_MOTIF_WM_HINTS_ELEMENT_COUNT);
17533 appState->currentSettings.window.isDecorated = value;
17586 FPL__CheckPlatform(
false);
17587 fpl__PlatformAppState *appState = fpl__global__AppState;
17588 const fpl__X11SubplatformState *subplatform = &appState->x11;
17589 const fpl__X11Api *x11Api = &subplatform->api;
17590 const fpl__X11WindowState *windowState = &appState->window.x11;
17594 xev.type = ClientMessage;
17595 xev.xclient.window = windowState->window;
17596 xev.xclient.message_type = windowState->netWMState;
17597 xev.xclient.format = 32;
17598 xev.xclient.data.l[0] = value ? 1 : 0;
17599 xev.xclient.data.l[1] = windowState->netWMStateFullscreen;
17600 xev.xclient.data.l[3] = 1l;
17604 bool result = x11Api->XSendEvent(windowState->display, windowState->root, 0, SubstructureRedirectMask | SubstructureNotifyMask, &xev) != 0;
17606 appState->currentSettings.window.isFullscreen = value;
17627 FPL__CheckPlatform(
false);
17628 fpl__PlatformAppState *appState = fpl__global__AppState;
17629 bool result = appState->currentSettings.window.isFullscreen;
17634 FPL__CheckArgumentNull(outPos,
false);
17635 FPL__CheckPlatform(
false);
17636 fpl__PlatformAppState *appState = fpl__global__AppState;
17637 const fpl__X11SubplatformState *subplatform = &appState->x11;
17638 const fpl__X11Api *x11Api = &subplatform->api;
17639 const fpl__X11WindowState *windowState = &appState->window.x11;
17640 XWindowAttributes attribs;
17641 x11Api->XGetWindowAttributes(windowState->display, windowState->window, &attribs);
17642 outPos->
left = attribs.x;
17643 outPos->
top = attribs.y;
17648 FPL__CheckPlatformNoRet();
17649 fpl__PlatformAppState *appState = fpl__global__AppState;
17650 const fpl__X11SubplatformState *subplatform = &appState->x11;
17651 const fpl__X11Api *x11Api = &subplatform->api;
17652 const fpl__X11WindowState *windowState = &appState->window.x11;
17653 x11Api->XMoveWindow(windowState->display, windowState->window, left, top);
17659 FPL__CheckArgumentNullNoRet(title);
17660 FPL__CheckPlatformNoRet();
17661 fpl__PlatformAppState *appState = fpl__global__AppState;
17662 const fpl__X11SubplatformState *subplatform = &appState->x11;
17663 const fpl__X11Api *x11Api = &subplatform->api;
17664 const fpl__X11WindowState *windowState = &appState->window.x11;
17668 x11Api->XChangeProperty(windowState->display, windowState->window,
17669 windowState->netWMName, windowState->utf8String, 8,
17673 x11Api->XChangeProperty(windowState->display, windowState->window,
17674 windowState->netWMIconName, windowState->utf8String, 8,
17678 x11Api->XFlush(windowState->display);
17692 FPL__CheckPlatform(
false);
17693 FPL__CheckArgumentNull(outState,
false);
17694 fpl__PlatformAppState *appState = fpl__global__AppState;
17695 const fpl__X11SubplatformState *subplatform = &appState->x11;
17696 const fpl__X11Api *x11Api = &subplatform->api;
17697 const fpl__X11WindowState *windowState = &appState->window.x11;
17698 bool result =
false;
17700 if (x11Api->XQueryKeymap(windowState->display, keysReturn)) {
17702 for (uint64_t keyCode = 0; keyCode < 256; ++keyCode) {
17703 bool isDown = (keysReturn[keyCode / 8] & (1 << (keyCode % 8))) != 0;
17705 fplKey mappedKey = fpl__GetMappedKey(&appState->window, keyCode);
17743 FPL__CheckPlatform(
false);
17744 FPL__CheckArgumentNull(outState,
false);
17745 fpl__PlatformAppState *appState = fpl__global__AppState;
17746 const fpl__X11SubplatformState *subplatform = &appState->x11;
17747 const fpl__X11Api *x11Api = &subplatform->api;
17748 const fpl__X11WindowState *windowState = &appState->window.x11;
17749 bool result =
false;
17750 Window root, child;
17751 int rootx, rooty, winx, winy;
17753 if (x11Api->XQueryPointer(windowState->display, windowState->window, &root, &child, &rootx, &rooty, &winx, &winy, &mask)) {
17754 outState->
x = winx;
17755 outState->
y = winy;
17775#if defined(FPL_PLATFORM_LINUX)
17776# include <locale.h>
17777# include <sys/eventfd.h>
17778# include <sys/epoll.h>
17779# include <sys/select.h>
17780# include <linux/joystick.h>
17782fpl_internal void fpl__LinuxReleasePlatform(fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
17783#if defined(FPL__ENABLE_WINDOW)
17785 fpl__LinuxFreeGameControllers(&appState->plinux.controllersState);
17790fpl_internal bool fpl__LinuxInitPlatform(
const fplInitFlags initFlags,
const fplSettings *initSettings, fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
17791 setlocale(LC_ALL,
"");
17803#if defined(FPL__ENABLE_WINDOW)
17804fpl_internal void fpl__LinuxFreeGameControllers(fpl__LinuxGameControllersState *controllersState) {
17805 for (
int controllerIndex = 0; controllerIndex <
fplArrayCount(controllersState->controllers); ++controllerIndex) {
17806 fpl__LinuxGameController *controller = controllersState->controllers + controllerIndex;
17807 if (controller->fd > 0) {
17808 close(controller->fd);
17809 controller->fd = 0;
17814fpl_internal float fpl__LinuxJoystickProcessStickValue(
const int16_t value,
const int16_t deadZoneThreshold) {
17816 if (value < -deadZoneThreshold) {
17817 result = (float)((value + deadZoneThreshold) / (32768.0f - deadZoneThreshold));
17818 }
else if (value > deadZoneThreshold) {
17819 result = (float)((value - deadZoneThreshold) / (32767.0f - deadZoneThreshold));
17824fpl_internal void fpl__LinuxPushGameControllerStateUpdateEvent(
const struct js_event *event, fpl__LinuxGameController *controller) {
17829 buttonMappingTable[0] = &padState->
actionA;
17830 buttonMappingTable[1] = &padState->
actionB;
17831 buttonMappingTable[2] = &padState->
actionX;
17832 buttonMappingTable[3] = &padState->
actionY;
17835 buttonMappingTable[6] = &padState->
back;
17836 buttonMappingTable[7] = &padState->
start;
17838 buttonMappingTable[9] = &padState->
leftThumb;
17839 buttonMappingTable[10] = &padState->
rightThumb;
17841 const int16_t deadZoneThresholdLeftStick = 5000;
17842 const int16_t deadZoneThresholdRightStick = 5000;
17844 switch (event->type & ~JS_EVENT_INIT) {
17845 case JS_EVENT_AXIS:
17847 switch (event->number) {
17851 padState->
leftStickX = fpl__LinuxJoystickProcessStickValue(event->value, deadZoneThresholdLeftStick);
17855 padState->
leftStickY = fpl__LinuxJoystickProcessStickValue(-event->value, deadZoneThresholdLeftStick);
17861 padState->
rightStickX = fpl__LinuxJoystickProcessStickValue(event->value, deadZoneThresholdRightStick);
17865 padState->
rightStickY = fpl__LinuxJoystickProcessStickValue(-event->value, deadZoneThresholdRightStick);
17871 padState->
leftTrigger = (float)((event->value + 32768) >> 8) / 255.0f;
17875 padState->
rightTrigger = (float)((event->value + 32768) >> 8) / 255.0f;
17881 if (event->value == -32767) {
17884 }
else if (event->value == 32767) {
17896 if (event->value == -32767) {
17899 }
else if (event->value == 32767) {
17913 case JS_EVENT_BUTTON:
17915 if ((event->number >= 0) && (
event->number <
fplArrayCount(buttonMappingTable))) {
17918 mappedButton->
isDown =
event->value != 0;
17928fpl_internal void fpl__LinuxPollGameControllers(
const fplSettings *settings, fpl__LinuxGameControllersState *controllersState,
const bool useEvents) {
17940 const char *deviceNames[] = {
17943 for (
int deviceNameIndex = 0; deviceNameIndex <
fplArrayCount(deviceNames); ++deviceNameIndex) {
17944 const char *deviceName = deviceNames[deviceNameIndex];
17945 bool alreadyFound =
false;
17946 int freeIndex = -1;
17947 for (uint32_t controllerIndex = 0; controllerIndex <
fplArrayCount(controllersState->controllers); ++controllerIndex) {
17948 fpl__LinuxGameController *controller = controllersState->controllers + controllerIndex;
17949 if ((controller->fd > 0) &&
fplIsStringEqual(deviceName, controller->deviceName)) {
17950 alreadyFound =
true;
17953 if (controller->fd == 0) {
17954 if (freeIndex == -1) {
17955 freeIndex = controllerIndex;
17959 if (!alreadyFound && freeIndex >= 0) {
17960 int fd = open(deviceName, O_RDONLY);
17962 FPL_LOG_ERROR(FPL__MODULE_LINUX,
"Failed opening joystick device '%s'", deviceName);
17965 uint8_t numAxis = 0;
17966 uint8_t numButtons = 0;
17967 ioctl(fd, JSIOCGAXES, &numAxis);
17968 ioctl(fd, JSIOCGBUTTONS, &numButtons);
17969 if (numAxis == 0 || numButtons == 0) {
17970 FPL_LOG_ERROR(FPL__MODULE_LINUX,
"Joystick device '%s' does not have enough buttons/axis to map to a XInput controller!", deviceName);
17976 struct js_event msg;
17977 if ((read(fd, &msg,
sizeof(
struct js_event)) !=
sizeof(
struct js_event)) || !((msg.type == JS_EVENT_INIT) || (msg.type == JS_EVENT_AXIS) || (msg.type == JS_EVENT_BUTTON))) {
17983 fpl__LinuxGameController *controller = controllersState->controllers + freeIndex;
17985 controller->fd = fd;
17986 controller->axisCount = numAxis;
17987 controller->buttonCount = numButtons;
17989 ioctl(fd, JSIOCGNAME(
fplArrayCount(controller->displayName)), controller->displayName);
17990 fcntl(fd, F_SETFL, O_NONBLOCK);
17999 fpl__PushInternalEvent(&ev);
18006 for (uint32_t controllerIndex = 0; controllerIndex <
fplArrayCount(controllersState->controllers); ++controllerIndex) {
18007 fpl__LinuxGameController *controller = controllersState->controllers + controllerIndex;
18008 if (controller->fd > 0) {
18010 struct js_event event;
18011 bool wasDisconnected =
false;
18014 if (read(controller->fd, &event,
sizeof(event)) < 0) {
18015 if (errno == ENODEV) {
18016 close(controller->fd);
18017 controller->fd = 0;
18019 wasDisconnected =
true;
18027 fpl__PushInternalEvent(&ev);
18032 fpl__LinuxPushGameControllerStateUpdateEvent(&event, controller);
18035 controller->state.isActive = !fpl__IsZeroMemory(&controller->state,
sizeof(
fplGamepadState));
18036 controller->state.isConnected = !wasDisconnected;
18037 controller->state.deviceName = controller->deviceName;
18039 if (controller->fd > 0) {
18048 fpl__PushInternalEvent(&ev);
18056 FPL__CheckPlatform(
false);
18057 FPL__CheckArgumentNull(outStates,
false);
18058 fpl__PlatformAppState *appState = fpl__global__AppState;
18060#if defined(FPL_PLATFORM_LINUX)
18061 fpl__LinuxGameControllersState *controllersState = &appState->plinux.controllersState;
18062 fpl__LinuxPollGameControllers(&appState->currentSettings, controllersState,
false);
18065 for (
int i = 0; i <
fplArrayCount(controllersState->controllers); ++i) {
18066 outStates->
deviceStates[i] = controllersState->controllers[i].state;
18080 FPL__CheckArgumentNull(signal,
false);
18082 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' is already valid", signal);
18085 int linuxEventHandle = eventfd((initialValue ==
fplSignalValue_Set) ? 1 : 0, EFD_CLOEXEC);
18086 if (linuxEventHandle == -1) {
18087 FPL__ERROR(FPL__MODULE_THREADING,
"Failed initializing signal '%p'", signal);
18104 FPL__CheckArgumentNull(signal,
false);
18106 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' is not valid", signal);
18112 read(ev, &value,
sizeof(value));
18118 struct timeval t = { 0, timeout * 1000 };
18119 int selectResult = select(1, &f, NULL, NULL, &t);
18120 if (selectResult == 0) {
18123 }
else if (selectResult == -1) {
18133 FPL__CheckArgumentNull(signals,
false);
18134 FPL__CheckArgumentMax(maxCount, FPL_MAX_SIGNAL_COUNT,
false);
18135 const size_t actualStride = stride > 0 ? stride :
sizeof(
fplSignalHandle *);
18136 for (uint32_t index = 0; index < maxCount; ++index) {
18139 FPL__ERROR(FPL__MODULE_THREADING,
"Signal for index '%d' are not allowed to be null", index);
18143 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' for index '%d' is not valid", signal, index);
18148 int e = epoll_create(maxCount);
18154 struct epoll_event events[FPL_MAX_SIGNAL_COUNT];
18155 for (
int index = 0; index < maxCount; index++) {
18156 events[index].events = EPOLLIN;
18157 events[index].data.u32 = index;
18159 int x = epoll_ctl(e, EPOLL_CTL_ADD, signal->
internalHandle.linuxEventHandle, events + index);
18165 int eventsResult = -1;
18166 int waiting = minCount;
18167 struct epoll_event revent[FPL_MAX_SIGNAL_COUNT];
18168 while (waiting > 0) {
18169 int ret = epoll_wait(e, revent, waiting, t);
18171 if (minCount == maxCount) {
18176 for (
int eventIndex = 0; eventIndex < ret; eventIndex++) {
18177 uint32_t signalIndex = revent[eventIndex].data.u32;
18179 epoll_ctl(e, EPOLL_CTL_DEL, signal->
internalHandle.linuxEventHandle, NULL);
18181 eventsResult = revent[0].data.u32;
18185 bool result = (waiting == 0);
18190 bool result = fpl__LinuxSignalWaitForMultiple(signals, count, count, stride, timeout);
18195 bool result = fpl__LinuxSignalWaitForMultiple(signals, 1, count, stride, timeout);
18200 FPL__CheckArgumentNull(signal,
false);
18202 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' is not valid", signal);
18205 uint64_t value = 1;
18206 int writtenBytes = write(signal->
internalHandle.linuxEventHandle, &value,
sizeof(value));
18207 bool result = writtenBytes ==
sizeof(value);
18215 FPL__CheckArgumentNull(outInfos,
false);
18216 bool result =
false;
18226fpl_internal size_t fpl__LinuxLocaleToISO639(
const char *source,
char *target,
const size_t maxTargetLen) {
18234 }
else if (*p ==
'.') {
18249 char *locale = setlocale(LC_CTYPE, NULL);
18250 size_t result = fpl__LinuxLocaleToISO639(locale, buffer, maxBufferLen);
18256 char *locale = setlocale(LC_ALL, NULL);
18257 size_t result = fpl__LinuxLocaleToISO639(locale, buffer, maxBufferLen);
18263 char *locale = setlocale(LC_ALL, NULL);
18264 size_t result = fpl__LinuxLocaleToISO639(locale, buffer, maxBufferLen);
18275#if defined(FPL_PLATFORM_UNIX)
18276fpl_internal void fpl__UnixReleasePlatform(fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
18279fpl_internal bool fpl__UnixInitPlatform(
const fplInitFlags initFlags,
const fplSettings *initSettings, fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
18315#if !defined(FPL__VIDEO_BACKENDS_IMPLEMENTED) && defined(FPL__ENABLE_VIDEO)
18316# define FPL__VIDEO_BACKENDS_IMPLEMENTED
18323typedef struct fpl__VideoData {
18324#if defined(FPL__ENABLE_VIDEO_SOFTWARE)
18330struct fpl__VideoBackend;
18332#define FPL__FUNC_VIDEO_BACKEND_LOAD(name) bool name(const fpl__PlatformAppState *appState, struct fpl__VideoBackend *backend)
18333typedef FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__func_VideoBackendLoad);
18335#define FPL__FUNC_VIDEO_BACKEND_UNLOAD(name) void name(const fpl__PlatformAppState *appState, struct fpl__VideoBackend *backend)
18336typedef FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__func_VideoBackendUnload);
18338#define FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(name) bool name(const fpl__PlatformAppState *appState, const fplVideoSettings *videoSettings, fpl__PlatformWindowState *windowState, struct fpl__VideoBackend *backend)
18339typedef FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__func_VideoBackendPrepareWindow);
18341#define FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(name) bool name(const fpl__PlatformAppState *appState, const fplVideoSettings *videoSettings, fpl__PlatformWindowState *windowState, struct fpl__VideoBackend *backend)
18342typedef FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(fpl__func_VideoBackendFinalizeWindow);
18344#define FPL__FUNC_VIDEO_BACKEND_DESTROYEDWINDOW(name) void name(const fpl__PlatformAppState *appState, struct fpl__VideoBackend *backend)
18345typedef FPL__FUNC_VIDEO_BACKEND_DESTROYEDWINDOW(fpl__func_VideoBackendDestroyedWindow);
18347#define FPL__FUNC_VIDEO_BACKEND_INITIALIZE(name) bool name(const fpl__PlatformAppState *appState, const fpl__PlatformWindowState *windowState, const fplVideoSettings *videoSettings, const fpl__VideoData *data, struct fpl__VideoBackend *backend)
18348typedef FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__func_VideoBackendInitialize);
18350#define FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(name) void name(const fpl__PlatformAppState *appState, const fpl__PlatformWindowState *windowState, struct fpl__VideoBackend *backend)
18351typedef FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__func_VideoBackendShutdown);
18353#define FPL__FUNC_VIDEO_BACKEND_PRESENT(name) void name(const fpl__PlatformAppState *appState, const fpl__PlatformWindowState *windowState, const fpl__VideoData *data, const struct fpl__VideoBackend *backend)
18354typedef FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__func_VideoBackendPresent);
18356#define FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(name) const void *name(const struct fpl__VideoBackend *backend, const char *procName)
18357typedef FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__func_VideoBackendGetProcedure);
18359#define FPL__FUNC_VIDEO_BACKEND_GETREQUIREMENTS(name) bool name(fplVideoRequirements *requirements)
18360typedef FPL__FUNC_VIDEO_BACKEND_GETREQUIREMENTS(fpl__func_VideoBackendGetRequirements);
18362typedef struct fpl__VideoContext {
18363 fpl__func_VideoBackendLoad *loadFunc;
18364 fpl__func_VideoBackendUnload *unloadFunc;
18365 fpl__func_VideoBackendInitialize *initializeFunc;
18366 fpl__func_VideoBackendShutdown *shutdownFunc;
18367 fpl__func_VideoBackendPrepareWindow *prepareWindowFunc;
18368 fpl__func_VideoBackendFinalizeWindow *finalizeWindowFunc;
18369 fpl__func_VideoBackendDestroyedWindow *destroyedWindowFunc;
18370 fpl__func_VideoBackendPresent *presentFunc;
18371 fpl__func_VideoBackendGetProcedure *getProcedureFunc;
18372 fpl__func_VideoBackendGetRequirements *getRequirementsFunc;
18374} fpl__VideoContext;
18377fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_Load_Stub) {
return(
true); }
18378fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_Unload_Stub) {}
18379fpl_internal FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__VideoBackend_PrepareWindow_Stub) {
return(
true); }
18380fpl_internal FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(fpl__VideoBackend_FinalizeWindow_Stub) {
return(
true); }
18381fpl_internal FPL__FUNC_VIDEO_BACKEND_DESTROYEDWINDOW(fpl__VideoBackend_DestroyedWindow_Stub) {}
18382fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_Initialize_Stub) {
return(
false); }
18383fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_Shutdown_Stub) {}
18384fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_Present_Stub) {}
18385fpl_internal FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__VideoBackend_GetProcedure_Stub) {
return(
fpl_null); }
18386fpl_internal FPL__FUNC_VIDEO_BACKEND_GETREQUIREMENTS(fpl__VideoBackend_GetRequirements_Stub) {
return(
false); }
18388fpl_internal fpl__VideoContext fpl__StubVideoContext() {
18390 result.loadFunc = fpl__VideoBackend_Load_Stub;
18391 result.unloadFunc = fpl__VideoBackend_Unload_Stub;
18392 result.prepareWindowFunc = fpl__VideoBackend_PrepareWindow_Stub;
18393 result.finalizeWindowFunc = fpl__VideoBackend_FinalizeWindow_Stub;
18394 result.destroyedWindowFunc = fpl__VideoBackend_DestroyedWindow_Stub;
18395 result.initializeFunc = fpl__VideoBackend_Initialize_Stub;
18396 result.shutdownFunc = fpl__VideoBackend_Shutdown_Stub;
18397 result.presentFunc = fpl__VideoBackend_Present_Stub;
18398 result.getProcedureFunc = fpl__VideoBackend_GetProcedure_Stub;
18399 result.getRequirementsFunc = fpl__VideoBackend_GetRequirements_Stub;
18404#define FPL__VIDEOBACKEND_MAGIC (uint64_t)0x564944454f535953
18406typedef struct fpl__VideoBackend {
18409} fpl__VideoBackend;
18416#if defined(FPL__ENABLE_VIDEO_OPENGL) && defined(FPL_PLATFORM_WINDOWS)
18418#define FPL__GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
18419#define FPL__GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
18420#define FPL__GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
18421#define FPL__GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008
18422#define FPL__GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
18423#define FPL__GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
18425#define FPL__WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
18426#define FPL__WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
18427#define FPL__WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
18428#define FPL__WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
18429#define FPL__WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
18430#define FPL__WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
18431#define FPL__WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
18432#define FPL__WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
18433#define FPL__WGL_CONTEXT_FLAGS_ARB 0x2094
18434#define FPL__WGL_DRAW_TO_WINDOW_ARB 0x2001
18435#define FPL__WGL_ACCELERATION_ARB 0x2003
18436#define FPL__WGL_SWAP_METHOD_ARB 0x2007
18437#define FPL__WGL_SUPPORT_OPENGL_ARB 0x2010
18438#define FPL__WGL_DOUBLE_BUFFER_ARB 0x2011
18439#define FPL__WGL_PIXEL_TYPE_ARB 0x2013
18440#define FPL__WGL_COLOR_BITS_ARB 0x2014
18441#define FPL__WGL_ALPHA_BITS_ARB 0x201B
18442#define FPL__WGL_DEPTH_BITS_ARB 0x2022
18443#define FPL__WGL_STENCIL_BITS_ARB 0x2023
18444#define FPL__WGL_FULL_ACCELERATION_ARB 0x2027
18445#define FPL__WGL_SWAP_EXCHANGE_ARB 0x2028
18446#define FPL__WGL_TYPE_RGBA_ARB 0x202B
18447#define FPL__WGL_SAMPLE_BUFFERS_ARB 0x2041
18448#define FPL__WGL_SAMPLES_ARB 0x2042
18450#define FPL__FUNC_WGL_wglMakeCurrent(name) BOOL WINAPI name(HDC deviceContext, HGLRC renderingContext)
18451typedef FPL__FUNC_WGL_wglMakeCurrent(fpl__win32_func_wglMakeCurrent);
18452#define FPL__FUNC_WGL_wglGetProcAddress(name) PROC WINAPI name(LPCSTR procedure)
18453typedef FPL__FUNC_WGL_wglGetProcAddress(fpl__win32_func_wglGetProcAddress);
18454#define FPL__FUNC_WGL_wglDeleteContext(name) BOOL WINAPI name(HGLRC renderingContext)
18455typedef FPL__FUNC_WGL_wglDeleteContext(fpl__win32_func_wglDeleteContext);
18456#define FPL__FUNC_WGL_wglCreateContext(name) HGLRC WINAPI name(HDC deviceContext)
18457typedef FPL__FUNC_WGL_wglCreateContext(fpl__win32_func_wglCreateContext);
18459#define FPL__FUNC_WGL_wglChoosePixelFormatARB(name) BOOL WINAPI name(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats)
18460typedef FPL__FUNC_WGL_wglChoosePixelFormatARB(fpl__win32_func_wglChoosePixelFormatARB);
18461#define FPL__FUNC_WGL_wglCreateContextAttribsARB(name) HGLRC WINAPI name(HDC hDC, HGLRC hShareContext, const int *attribList)
18462typedef FPL__FUNC_WGL_wglCreateContextAttribsARB(fpl__win32_func_wglCreateContextAttribsARB);
18463#define FPL__FUNC_WGL_wglSwapIntervalEXT(name) BOOL WINAPI name(int interval)
18464typedef FPL__FUNC_WGL_wglSwapIntervalEXT(fpl__win32_func_wglSwapIntervalEXT);
18466typedef struct fpl__Win32OpenGLApi {
18467 HMODULE openglLibrary;
18468 fpl__win32_func_wglMakeCurrent *wglMakeCurrent;
18469 fpl__win32_func_wglGetProcAddress *wglGetProcAddress;
18470 fpl__win32_func_wglDeleteContext *wglDeleteContext;
18471 fpl__win32_func_wglCreateContext *wglCreateContext;
18472 fpl__win32_func_wglChoosePixelFormatARB *wglChoosePixelFormatARB;
18473 fpl__win32_func_wglCreateContextAttribsARB *wglCreateContextAttribsARB;
18474 fpl__win32_func_wglSwapIntervalEXT *wglSwapIntervalEXT;
18475} fpl__Win32OpenGLApi;
18477fpl_internal void fpl__UnloadWin32OpenGLApi(fpl__Win32OpenGLApi *api) {
18478 if (api->openglLibrary !=
fpl_null) {
18479 FreeLibrary(api->openglLibrary);
18484fpl_internal bool fpl__LoadWin32OpenGLApi(fpl__Win32OpenGLApi *api,
const char *libraryName) {
18486 libraryName =
"opengl32.dll";
18488 bool result =
false;
18492 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName);
18493 api->openglLibrary = openglLibrary;
18494 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName, api, fpl__win32_func_wglGetProcAddress, wglGetProcAddress);
18495 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName, api, fpl__win32_func_wglCreateContext, wglCreateContext);
18496 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName, api, fpl__win32_func_wglDeleteContext, wglDeleteContext);
18497 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName, api, fpl__win32_func_wglMakeCurrent, wglMakeCurrent);
18501 fpl__UnloadWin32OpenGLApi(api);
18506typedef struct fpl__VideoBackendWin32OpenGL {
18507 fpl__VideoBackend base;
18508 fpl__Win32OpenGLApi api;
18509 HGLRC renderingContext;
18510} fpl__VideoBackendWin32OpenGL;
18512fpl_internal FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__VideoBackend_Win32OpenGL_GetProcedure) {
18513 const fpl__VideoBackendWin32OpenGL *nativeBackend = (
const fpl__VideoBackendWin32OpenGL *)backend;
18514 void *result = (
void *)GetProcAddress(nativeBackend->api.openglLibrary, procName);
18518fpl_internal LRESULT CALLBACK fpl__Win32OpenGLTemporaryWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
18519 fpl__Win32AppState *appState = &fpl__global__AppState->win32;
18520 const fpl__Win32Api *wapi = &appState->winApi;
18523 wapi->user.PostQuitMessage(0);
18526 return wapi->user.DefWindowProcW(hWnd, message, wParam, lParam);
18531fpl_internal FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__VideoBackend_Win32OpenGL_PrepareWindow) {
18532 const fpl__Win32AppState *nativeAppState = &appState->win32;
18533 const fpl__Win32Api *wapi = &nativeAppState->winApi;
18534 fpl__Win32WindowState *nativeWindowState = &windowState->win32;
18536 nativeWindowState->pixelFormat = 0;
18539 fpl__Win32OpenGLApi glApi;
18540 if (fpl__LoadWin32OpenGLApi(&glApi, videoSettings->graphics.opengl.libraryFile)) {
18543 windowClass.cbSize =
sizeof(windowClass);
18544 windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
18545 windowClass.lpfnWndProc = fpl__Win32OpenGLTemporaryWindowProc;
18546 windowClass.hInstance = GetModuleHandleW(
fpl_null);
18547 windowClass.hCursor = fpl__win32_LoadCursor(
fpl_null, IDC_ARROW);
18548 windowClass.lpszClassName = L
"FPL_Temp_GL_Window";
18549 if (wapi->user.RegisterClassExW(&windowClass)) {
18551 HWND tempWindowHandle = wapi->user.CreateWindowExW(0, windowClass.lpszClassName, L
"FPL Temp GL Window", 0, 0, 0, 1, 1,
fpl_null,
fpl_null, windowClass.hInstance,
fpl_null);
18552 if (tempWindowHandle !=
fpl_null) {
18554 HDC tempDC = wapi->user.GetDC(tempWindowHandle);
18558 fakePFD.nSize =
sizeof(fakePFD);
18559 fakePFD.nVersion = 1;
18560 fakePFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
18561 fakePFD.iPixelType = PFD_TYPE_RGBA;
18562 fakePFD.cColorBits = 32;
18563 fakePFD.cAlphaBits = 8;
18564 fakePFD.cDepthBits = 24;
18565 int fakePFDID = wapi->gdi.ChoosePixelFormat(tempDC, &fakePFD);
18566 if (fakePFDID != 0) {
18567 if (wapi->gdi.SetPixelFormat(tempDC, fakePFDID, &fakePFD)) {
18569 HGLRC tempCtx = glApi.wglCreateContext(tempDC);
18571 if (glApi.wglMakeCurrent(tempDC, tempCtx)) {
18572 glApi.wglChoosePixelFormatARB = (fpl__win32_func_wglChoosePixelFormatARB *)glApi.wglGetProcAddress(
"wglChoosePixelFormatARB");
18573 if (glApi.wglChoosePixelFormatARB !=
fpl_null) {
18574 int multisampleCount = (int)videoSettings->graphics.opengl.multiSamplingCount;
18575 const int pixelAttribs[] = {
18576 FPL__WGL_DRAW_TO_WINDOW_ARB, 1,
18577 FPL__WGL_SUPPORT_OPENGL_ARB, 1,
18578 FPL__WGL_DOUBLE_BUFFER_ARB, 1,
18579 FPL__WGL_PIXEL_TYPE_ARB, FPL__WGL_TYPE_RGBA_ARB,
18580 FPL__WGL_ACCELERATION_ARB, FPL__WGL_FULL_ACCELERATION_ARB,
18581 FPL__WGL_COLOR_BITS_ARB, 32,
18582 FPL__WGL_ALPHA_BITS_ARB, 8,
18583 FPL__WGL_DEPTH_BITS_ARB, 24,
18584 FPL__WGL_STENCIL_BITS_ARB, 8,
18585 FPL__WGL_SAMPLE_BUFFERS_ARB, (multisampleCount > 0) ? 1 : 0,
18586 FPL__WGL_SAMPLES_ARB, multisampleCount,
18591 if (glApi.wglChoosePixelFormatARB(tempDC, pixelAttribs, NULL, 1, &pixelFormat, &numFormats)) {
18592 nativeWindowState->pixelFormat = pixelFormat;
18597 glApi.wglDeleteContext(tempCtx);
18601 wapi->user.ReleaseDC(tempWindowHandle, tempDC);
18603 wapi->user.DestroyWindow(tempWindowHandle);
18606 fpl__UnloadWin32OpenGLApi(&glApi);
18612fpl_internal FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(fpl__VideoBackend_Win32OpenGL_FinalizeWindow) {
18613 const fpl__Win32AppState *nativeAppState = &appState->win32;
18614 const fpl__Win32Api *wapi = &nativeAppState->winApi;
18615 fpl__Win32WindowState *nativeWindowState = &windowState->win32;
18620 HDC deviceContext = nativeWindowState->deviceContext;
18621 HWND handle = nativeWindowState->windowHandle;
18625 bool pixelFormatSet =
false;
18626 if (nativeWindowState->pixelFormat != 0) {
18627 wapi->gdi.DescribePixelFormat(deviceContext, nativeWindowState->pixelFormat,
sizeof(pfd), &pfd);
18628 pixelFormatSet = wapi->gdi.SetPixelFormat(deviceContext, nativeWindowState->pixelFormat, &pfd) == TRUE;
18629 if (!pixelFormatSet) {
18630 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Failed setting Pixelformat '%d' from pre setup", nativeWindowState->pixelFormat);
18633 if (!pixelFormatSet) {
18635 pfd.nSize =
sizeof(pfd);
18637 pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
18638 pfd.iPixelType = PFD_TYPE_RGBA;
18639 pfd.cColorBits = 32;
18640 pfd.cDepthBits = 24;
18641 pfd.cAlphaBits = 8;
18642 pfd.cStencilBits = 8;
18643 pfd.iLayerType = PFD_MAIN_PLANE;
18644 int pixelFormat = wapi->gdi.ChoosePixelFormat(deviceContext, &pfd);
18645 if (!pixelFormat) {
18646 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Failed choosing RGBA Legacy Pixelformat for Color/Depth/Alpha (%d,%d,%d) and DC '%x'", pfd.cColorBits, pfd.cDepthBits, pfd.cAlphaBits, deviceContext);
18649 wapi->gdi.DescribePixelFormat(deviceContext, pixelFormat,
sizeof(pfd), &pfd);
18650 if (!wapi->gdi.SetPixelFormat(deviceContext, pixelFormat, &pfd)) {
18651 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Failed setting RGBA Pixelformat '%d' for Color/Depth/Alpha (%d,%d,%d and DC '%x')", pixelFormat, pfd.cColorBits, pfd.cDepthBits, pfd.cAlphaBits, deviceContext);
18658fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_Win32OpenGL_Shutdown) {
18659 const fpl__Win32AppState *nativeAppState = &appState->win32;
18661 fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
18662 const fpl__Win32OpenGLApi *glapi = &nativeBackend->api;
18664 if (nativeBackend->renderingContext) {
18666 glapi->wglDeleteContext(nativeBackend->renderingContext);
18667 nativeBackend->renderingContext =
fpl_null;
18671fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_Win32OpenGL_Initialize) {
18672 const fpl__Win32AppState *nativeAppState = &appState->win32;
18673 const fpl__Win32WindowState *nativeWindowState = &windowState->win32;
18674 const fpl__Win32Api *wapi = &nativeAppState->winApi;
18676 fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
18678 fpl__Win32OpenGLApi *glapi = &nativeBackend->api;
18683 HDC deviceContext = nativeWindowState->deviceContext;
18684 HGLRC legacyRenderingContext = glapi->wglCreateContext(deviceContext);
18685 if (!legacyRenderingContext) {
18686 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Failed creating Legacy OpenGL Rendering Context for DC '%x')", deviceContext);
18689 if (!glapi->wglMakeCurrent(deviceContext, legacyRenderingContext)) {
18690 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Failed activating Legacy OpenGL Rendering Context for DC '%x' and RC '%x')", deviceContext, legacyRenderingContext);
18691 glapi->wglDeleteContext(legacyRenderingContext);
18696 glapi->wglSwapIntervalEXT = (fpl__win32_func_wglSwapIntervalEXT *)glapi->wglGetProcAddress(
"wglSwapIntervalEXT");
18697 glapi->wglChoosePixelFormatARB = (fpl__win32_func_wglChoosePixelFormatARB *)glapi->wglGetProcAddress(
"wglChoosePixelFormatARB");
18698 glapi->wglCreateContextAttribsARB = (fpl__win32_func_wglCreateContextAttribsARB *)glapi->wglGetProcAddress(
"wglCreateContextAttribsARB");
18703 HGLRC activeRenderingContext;
18706 if (!(videoSettings->graphics.opengl.majorVersion >= 3 && videoSettings->graphics.opengl.minorVersion >= 0)) {
18707 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"You have not specified the 'majorVersion' and 'minorVersion' in the VideoSettings");
18710 if (glapi->wglChoosePixelFormatARB ==
fpl_null) {
18711 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"wglChoosePixelFormatARB is not available, modern OpenGL is not available for your video card");
18714 if (glapi->wglCreateContextAttribsARB ==
fpl_null) {
18715 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"wglCreateContextAttribsARB is not available, modern OpenGL is not available for your video card");
18722 profile = FPL__WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
18724 profile = FPL__WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
18726 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"No opengl compability profile selected, please specific Core fplOpenGLCompabilityFlags_Core or fplOpenGLCompabilityFlags_Compability");
18730 flags = FPL__WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
18733 int contextAttribIndex = 0;
18735 contextAttribList[contextAttribIndex++] = FPL__WGL_CONTEXT_MAJOR_VERSION_ARB;
18736 contextAttribList[contextAttribIndex++] = (int)videoSettings->graphics.opengl.majorVersion;
18737 contextAttribList[contextAttribIndex++] = FPL__WGL_CONTEXT_MINOR_VERSION_ARB;
18738 contextAttribList[contextAttribIndex++] = (int)videoSettings->graphics.opengl.minorVersion;
18739 contextAttribList[contextAttribIndex++] = FPL__WGL_CONTEXT_PROFILE_MASK_ARB;
18740 contextAttribList[contextAttribIndex++] = profile;
18742 contextAttribList[contextAttribIndex++] = FPL__WGL_CONTEXT_FLAGS_ARB;
18743 contextAttribList[contextAttribIndex++] = flags;
18747 HGLRC modernRenderingContext = glapi->wglCreateContextAttribsARB(deviceContext, 0, contextAttribList);
18748 if (modernRenderingContext) {
18749 if (!glapi->wglMakeCurrent(deviceContext, modernRenderingContext)) {
18750 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Warning: Failed activating Modern OpenGL Rendering Context for version (%d.%d) and compability flags (%d) and DC '%x') -> Fallback to legacy context", videoSettings->graphics.opengl.majorVersion, videoSettings->graphics.opengl.minorVersion, videoSettings->graphics.opengl.compabilityFlags, deviceContext);
18752 glapi->wglDeleteContext(modernRenderingContext);
18753 modernRenderingContext =
fpl_null;
18756 glapi->wglMakeCurrent(deviceContext, legacyRenderingContext);
18757 activeRenderingContext = legacyRenderingContext;
18760 glapi->wglDeleteContext(legacyRenderingContext);
18761 legacyRenderingContext =
fpl_null;
18762 activeRenderingContext = modernRenderingContext;
18765 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Warning: Failed creating Modern OpenGL Rendering Context for version (%d.%d) and compability flags (%d) and DC '%x') -> Fallback to legacy context", videoSettings->graphics.opengl.majorVersion, videoSettings->graphics.opengl.minorVersion, videoSettings->graphics.opengl.compabilityFlags, deviceContext);
18768 glapi->wglMakeCurrent(deviceContext, legacyRenderingContext);
18769 activeRenderingContext = legacyRenderingContext;
18773 glapi->wglMakeCurrent(deviceContext, legacyRenderingContext);
18774 activeRenderingContext = legacyRenderingContext;
18778 nativeBackend->renderingContext = activeRenderingContext;
18781 if (glapi->wglSwapIntervalEXT !=
fpl_null) {
18782 int swapInterval = videoSettings->isVSync ? 1 : 0;
18783 glapi->wglSwapIntervalEXT(swapInterval);
18786 backend->surface.window.win32.deviceContext = deviceContext;
18787 backend->surface.window.win32.windowHandle = nativeWindowState->windowHandle;
18788 backend->surface.opengl.renderingContext = (
void *)activeRenderingContext;
18793fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_Win32OpenGL_Unload) {
18794 fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
18795 fpl__UnloadWin32OpenGLApi(&nativeBackend->api);
18799fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_Win32OpenGL_Load) {
18800 fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
18803 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
18810fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_Win32OpenGL_Present) {
18811 const fpl__Win32AppState *win32AppState = &appState->win32;
18812 const fpl__Win32WindowState *win32WindowState = &appState->window.win32;
18813 const fpl__Win32Api *wapi = &win32AppState->winApi;
18814 const fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
18815 wapi->gdi.SwapBuffers(win32WindowState->deviceContext);
18818fpl_internal fpl__VideoContext fpl__VideoBackend_Win32OpenGL_Construct() {
18819 fpl__VideoContext result = fpl__StubVideoContext();
18820 result.loadFunc = fpl__VideoBackend_Win32OpenGL_Load;
18821 result.unloadFunc = fpl__VideoBackend_Win32OpenGL_Unload;
18822 result.getProcedureFunc = fpl__VideoBackend_Win32OpenGL_GetProcedure;
18823 result.initializeFunc = fpl__VideoBackend_Win32OpenGL_Initialize;
18824 result.shutdownFunc = fpl__VideoBackend_Win32OpenGL_Shutdown;
18825 result.prepareWindowFunc = fpl__VideoBackend_Win32OpenGL_PrepareWindow;
18826 result.finalizeWindowFunc = fpl__VideoBackend_Win32OpenGL_FinalizeWindow;
18827 result.presentFunc = fpl__VideoBackend_Win32OpenGL_Present;
18837#if defined(FPL__ENABLE_VIDEO_OPENGL) && defined(FPL_SUBPLATFORM_X11)
18839typedef uint8_t GLubyte;
18842typedef XID GLXDrawable;
18843typedef XID GLXWindow;
18844typedef void GLXContext_Void;
18845typedef GLXContext_Void *GLXContext;
18846typedef void GLXFBConfig_Void;
18847typedef GLXFBConfig_Void *GLXFBConfig;
18850#define GLX_DOUBLEBUFFER 5
18851#define GLX_RED_SIZE 8
18852#define GLX_GREEN_SIZE 9
18853#define GLX_BLUE_SIZE 10
18854#define GLX_ALPHA_SIZE 11
18855#define GLX_DEPTH_SIZE 12
18856#define GLX_STENCIL_SIZE 13
18857#define GLX_SAMPLE_BUFFERS 0x186a0
18858#define GLX_SAMPLES 0x186a1
18860#define GLX_X_VISUAL_TYPE 0x22
18861#define GLX_TRUE_COLOR 0x8002
18862#define GLX_RGBA_TYPE 0x8014
18865#define FPL__FUNC_GLX_glXQueryVersion(name) Bool name(Display *dpy, int *major, int *minor)
18866typedef FPL__FUNC_GLX_glXQueryVersion(fpl__func_glx_glXQueryVersion);
18867#define FPL__FUNC_GLX_glXChooseVisual(name) XVisualInfo* name(Display *dpy, int screen, int *attribList)
18868typedef FPL__FUNC_GLX_glXChooseVisual(fpl__func_glx_glXChooseVisual);
18869#define FPL__FUNC_GLX_glXCreateContext(name) GLXContext name(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct)
18870typedef FPL__FUNC_GLX_glXCreateContext(fpl__func_glx_glXCreateContext);
18871#define FPL__FUNC_GLX_glXCreateNewContext(name) GLXContext name(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct)
18872typedef FPL__FUNC_GLX_glXCreateNewContext(fpl__func_glx_glXCreateNewContext);
18873#define FPL__FUNC_GLX_glXDestroyContext(name) void name(Display *dpy, GLXContext ctx)
18874typedef FPL__FUNC_GLX_glXDestroyContext(fpl__func_glx_glXDestroyContext);
18875#define FPL__FUNC_GLX_glXMakeCurrent(name) Bool name(Display *dpy, GLXDrawable drawable, GLXContext ctx)
18876typedef FPL__FUNC_GLX_glXMakeCurrent(fpl__func_glx_glXMakeCurrent);
18877#define FPL__FUNC_GLX_glXSwapBuffers(name) void name(Display *dpy, GLXDrawable drawable)
18878typedef FPL__FUNC_GLX_glXSwapBuffers(fpl__func_glx_glXSwapBuffers);
18879#define FPL__FUNC_GLX_glXGetProcAddress(name) void *name(const GLubyte *procName)
18880typedef FPL__FUNC_GLX_glXGetProcAddress(fpl__func_glx_glXGetProcAddress);
18881#define FPL__FUNC_GLX_glXChooseFBConfig(name) GLXFBConfig *name(Display *dpy, int screen, const int *attrib_list, int *nelements)
18882typedef FPL__FUNC_GLX_glXChooseFBConfig(fpl__func_glx_glXChooseFBConfig);
18883#define FPL__FUNC_GLX_glXGetFBConfigs(name) GLXFBConfig *name(Display *dpy, int screen, int *nelements)
18884typedef FPL__FUNC_GLX_glXGetFBConfigs(fpl__func_glx_glXGetFBConfigs);
18885#define FPL__FUNC_GLX_glXGetVisualFromFBConfig(name) XVisualInfo *name(Display *dpy, GLXFBConfig config)
18886typedef FPL__FUNC_GLX_glXGetVisualFromFBConfig(fpl__func_glx_glXGetVisualFromFBConfig);
18887#define FPL__FUNC_GLX_glXGetFBConfigAttrib(name) int name(Display *dpy, GLXFBConfig config, int attribute, int *value)
18888typedef FPL__FUNC_GLX_glXGetFBConfigAttrib(fpl__func_glx_glXGetFBConfigAttrib);
18889#define FPL__FUNC_GLX_glXCreateWindow(name) GLXWindow name(Display *dpy, GLXFBConfig config, Window win, const int *attrib_list)
18890typedef FPL__FUNC_GLX_glXCreateWindow(fpl__func_glx_glXCreateWindow);
18891#define FPL__FUNC_GLX_glXQueryExtension(name) Bool name(Display *dpy, int *errorBase, int *eventBase)
18892typedef FPL__FUNC_GLX_glXQueryExtension(fpl__func_glx_glXQueryExtension);
18893#define FPL__FUNC_GLX_glXQueryExtensionsString(name) const char *name(Display *dpy, int screen)
18894typedef FPL__FUNC_GLX_glXQueryExtensionsString(fpl__func_glx_glXQueryExtensionsString);
18897#define FPL__FUNC_GLX_glXCreateContextAttribsARB(name) GLXContext name(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list)
18898typedef FPL__FUNC_GLX_glXCreateContextAttribsARB(fpl__func_glx_glXCreateContextAttribsARB);
18900#define FPL__GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
18901#define FPL__GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
18902#define FPL__GLX_CONTEXT_FLAGS_ARB 0x2094
18903#define FPL__GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
18905#define FPL__GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
18906#define FPL__GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
18907#define FPL__GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
18908#define FPL__GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
18910typedef struct fpl__X11VideoOpenGLApi {
18912 fpl__func_glx_glXQueryVersion *glXQueryVersion;
18913 fpl__func_glx_glXChooseVisual *glXChooseVisual;
18914 fpl__func_glx_glXCreateContext *glXCreateContext;
18915 fpl__func_glx_glXDestroyContext *glXDestroyContext;
18916 fpl__func_glx_glXCreateNewContext *glXCreateNewContext;
18917 fpl__func_glx_glXMakeCurrent *glXMakeCurrent;
18918 fpl__func_glx_glXSwapBuffers *glXSwapBuffers;
18919 fpl__func_glx_glXGetProcAddress *glXGetProcAddress;
18920 fpl__func_glx_glXChooseFBConfig *glXChooseFBConfig;
18921 fpl__func_glx_glXGetFBConfigs *glXGetFBConfigs;
18922 fpl__func_glx_glXGetVisualFromFBConfig *glXGetVisualFromFBConfig;
18923 fpl__func_glx_glXGetFBConfigAttrib *glXGetFBConfigAttrib;
18924 fpl__func_glx_glXCreateWindow *glXCreateWindow;
18925 fpl__func_glx_glXQueryExtension *glXQueryExtension;
18926 fpl__func_glx_glXQueryExtensionsString *glXQueryExtensionsString;
18927 fpl__func_glx_glXCreateContextAttribsARB *glXCreateContextAttribsARB;
18928} fpl__X11VideoOpenGLApi;
18930fpl_internal void fpl__UnloadX11OpenGLApi(fpl__X11VideoOpenGLApi *api) {
18932 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Unload Api (Library '%p')", api->libHandle);
18933 dlclose(api->libHandle);
18938fpl_internal bool fpl__LoadX11OpenGLApi(fpl__X11VideoOpenGLApi *api,
const char *libraryName) {
18939 uint32_t libFileCount = 0;
18941 const char *libFileNames[4];
18943 libFileNames[libFileCount++] = libraryName;
18945 libFileNames[libFileCount++] =
"libGL.so.1";
18946 libFileNames[libFileCount++] =
"libGL.so";
18949 bool result =
false;
18950 for (uint32_t index = 0; index < libFileCount; ++index) {
18951 const char *libName = libFileNames[index];
18952 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Load GLX Api from Library: %s", libName);
18955 FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_GLX, libHandle, libName);
18956 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXQueryVersion, glXQueryVersion);
18957 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXChooseVisual, glXChooseVisual);
18958 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXCreateContext, glXCreateContext);
18959 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXDestroyContext, glXDestroyContext);
18960 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXCreateNewContext, glXCreateNewContext);
18961 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXMakeCurrent, glXMakeCurrent);
18962 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXSwapBuffers, glXSwapBuffers);
18963 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXGetProcAddress, glXGetProcAddress);
18964 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXChooseFBConfig, glXChooseFBConfig);
18965 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXGetFBConfigs, glXGetFBConfigs);
18966 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXGetVisualFromFBConfig, glXGetVisualFromFBConfig);
18967 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXGetFBConfigAttrib, glXGetFBConfigAttrib);
18968 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXCreateWindow, glXCreateWindow);
18969 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXQueryExtension, glXQueryExtension);
18970 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXQueryExtensionsString, glXQueryExtensionsString);
18971 api->libHandle = libHandle;
18975 FPL_LOG_DEBUG(FPL__MODULE_GLX, ,
"Successfully loaded GLX Api from Library '%s'", libName);
18978 fpl__UnloadX11OpenGLApi(api);
18983typedef struct fpl__VideoBackendX11OpenGL {
18984 fpl__VideoBackend base;
18985 fpl__X11VideoOpenGLApi api;
18986 GLXFBConfig fbConfig;
18987 XVisualInfo *visualInfo;
18988 GLXContext context;
18989 bool isActiveContext;
18990} fpl__VideoBackendX11OpenGL;
18992fpl_internal FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__VideoBackend_X11OpenGL_GetProcedure) {
18993 const fpl__VideoBackendX11OpenGL *nativeBackend = (
const fpl__VideoBackendX11OpenGL *)backend;
18994 void *result = dlsym(nativeBackend->api.libHandle, procName);
18998fpl_internal FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__VideoBackend_X11OpenGL_PrepareWindow) {
18999 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
19000 const fpl__X11Api *x11Api = &nativeAppState->api;
19002 fpl__X11WindowState *nativeWindowState = &windowState->x11;
19003 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
19004 fpl__X11VideoOpenGLApi *glApi = &nativeBackend->api;
19006 Display *display = nativeWindowState->display;
19007 Window window = nativeWindowState->window;
19008 int screen = nativeWindowState->screen;
19010 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Query GLX version for display '%p'", display);
19011 int major = 0, minor = 0;
19012 if (!glApi->glXQueryVersion(display, &major, &minor)) {
19013 FPL_LOG_ERROR(FPL__MODULE_GLX,
"Failed querying GLX version for display '%p'", display);
19016 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully queried GLX version for display '%p': %d.%d", display, major, minor);
19020 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Query OpenGL extension on display '%p'", display);
19022 FPL__ERROR(FPL__MODULE_GLX,
"OpenGL GLX Extension is not supported by the active display '%p'", display);
19026 const char *extensionString = glApi->glXQueryExtensionsString(display, screen);
19027 if (extensionString !=
fpl_null) {
19028 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"OpenGL GLX extensions: %s", extensionString);
19031 bool isModern = major > 1 || (major == 1 && minor >= 3);
19036 attr[attrIndex++] = GLX_X_VISUAL_TYPE;
19037 attr[attrIndex++] = GLX_TRUE_COLOR;
19040 attr[attrIndex++] = GLX_RGBA;
19041 attr[attrIndex++] = True;
19044 attr[attrIndex++] = GLX_DOUBLEBUFFER;
19045 attr[attrIndex++] = True;
19047 attr[attrIndex++] = GLX_RED_SIZE;
19048 attr[attrIndex++] = 8;
19050 attr[attrIndex++] = GLX_GREEN_SIZE;
19051 attr[attrIndex++] = 8;
19053 attr[attrIndex++] = GLX_BLUE_SIZE;
19054 attr[attrIndex++] = 8;
19056 attr[attrIndex++] = GLX_ALPHA_SIZE;
19057 attr[attrIndex++] = 8;
19059 attr[attrIndex++] = GLX_DEPTH_SIZE;
19060 attr[attrIndex++] = 24;
19062 attr[attrIndex++] = GLX_STENCIL_SIZE;
19063 attr[attrIndex++] = 8;
19066 attr[attrIndex++] = GLX_SAMPLE_BUFFERS;
19067 attr[attrIndex++] = 1;
19069 attr[attrIndex++] = GLX_SAMPLES;
19073 attr[attrIndex] = 0;
19077 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Get framebuffer configuration from display '%p' and screen '%d'", display, screen);
19078 int configCount = 0;
19079 GLXFBConfig *configs = glApi->glXChooseFBConfig(display, screen, attr, &configCount);
19080 if (configs ==
fpl_null || !configCount) {
19081 FPL__ERROR(FPL__MODULE_GLX,
"No framebuffer configuration from display '%p' and screen '%d' found!", display, screen);
19082 nativeBackend->fbConfig =
fpl_null;
19085 nativeBackend->fbConfig = configs[0];
19086 nativeBackend->visualInfo =
fpl_null;
19087 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully got framebuffer configuration from display '%p' and screen '%d': %p", display, screen, nativeBackend->fbConfig);
19089 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Release %d framebuffer configurations", configCount);
19090 x11Api->XFree(configs);
19093 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Choose visual from display '%p' and screen '%d'", display, screen);
19094 XVisualInfo *visualInfo = glApi->glXChooseVisual(display, screen, attr);
19096 FPL__ERROR(FPL__MODULE_GLX,
"No visual info for display '%p' and screen '%d' found!", display, screen);
19099 nativeBackend->visualInfo = visualInfo;
19100 nativeBackend->fbConfig =
fpl_null;
19101 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully got visual info from display '%p' and screen '%d': %p", display, screen, nativeBackend->visualInfo);
19104 if (nativeBackend->fbConfig !=
fpl_null) {
19105 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Get visual info from display '%p' and frame buffer config '%p'", display, nativeBackend->fbConfig);
19106 XVisualInfo *visualInfo = glApi->glXGetVisualFromFBConfig(display, nativeBackend->fbConfig);
19108 FPL__ERROR(FPL__MODULE_GLX,
"Failed getting visual info from display '%p' and frame buffer config '%p'", display, nativeBackend->fbConfig);
19111 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully got visual info from display '%p' and frame buffer config '%p': %p", display, nativeBackend->fbConfig, visualInfo);
19113 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using visual: %p", visualInfo->visual);
19114 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using color depth: %d", visualInfo->depth);
19116 nativeWindowState->visual = visualInfo->visual;
19117 nativeWindowState->colorDepth = visualInfo->depth;
19119 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Release visual info '%p'", visualInfo);
19120 x11Api->XFree(visualInfo);
19121 }
else if (nativeBackend->visualInfo !=
fpl_null) {
19122 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using existing visual info: %p", nativeBackend->visualInfo);
19123 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using visual: %p", nativeBackend->visualInfo->visual);
19124 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using color depth: %d", nativeBackend->visualInfo->depth);
19125 nativeWindowState->visual = nativeBackend->visualInfo->visual;
19126 nativeWindowState->colorDepth = nativeBackend->visualInfo->depth;
19128 FPL__ERROR(FPL__MODULE_GLX,
"No visual info or frame buffer config defined!");
19135fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_X11OpenGL_Shutdown) {
19136 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
19137 const fpl__X11Api *x11Api = &nativeAppState->api;
19138 const fpl__X11WindowState *nativeWindowState = &windowState->x11;
19140 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
19141 fpl__X11VideoOpenGLApi *glApi = &nativeBackend->api;
19143 if (nativeBackend->isActiveContext) {
19144 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Deactivate GLX rendering context for display '%p'", nativeWindowState->display);
19145 glApi->glXMakeCurrent(nativeWindowState->display, 0,
fpl_null);
19146 nativeBackend->isActiveContext =
false;
19149 if (nativeBackend->context !=
fpl_null) {
19150 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Destroy GLX rendering context '%p' for display '%p'", nativeBackend->context, nativeWindowState->display);
19151 glApi->glXDestroyContext(nativeWindowState->display, nativeBackend->context);
19152 nativeBackend->context =
fpl_null;
19155 if (nativeBackend->visualInfo !=
fpl_null) {
19156 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Destroy visual info '%p' (Fallback)", nativeBackend->visualInfo);
19157 x11Api->XFree(nativeBackend->visualInfo);
19158 nativeBackend->visualInfo =
fpl_null;
19162fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_X11OpenGL_Initialize) {
19163 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
19164 const fpl__X11Api *x11Api = &nativeAppState->api;
19165 const fpl__X11WindowState *nativeWindowState = &windowState->x11;
19167 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
19168 fpl__X11VideoOpenGLApi *glApi = &nativeBackend->api;
19170 Display *display = nativeWindowState->display;
19171 Window window = nativeWindowState->window;
19176 GLXContext legacyRenderingContext;
19177 if (nativeBackend->fbConfig !=
fpl_null) {
19178 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Create GLX legacy rendering context on display '%p' and frame buffer config '%p'", display, nativeBackend->fbConfig);
19179 legacyRenderingContext = glApi->glXCreateNewContext(display, nativeBackend->fbConfig, GLX_RGBA_TYPE,
fpl_null, 1);
19180 if (!legacyRenderingContext) {
19181 FPL__ERROR(FPL__MODULE_GLX,
"Failed creating GLX legacy rendering context on display '%p' and frame buffer config '%p'", display, nativeBackend->fbConfig);
19182 goto failed_x11_glx;
19184 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully created GLX legacy rendering context '%p' on display '%p' and frame buffer config '%p'", legacyRenderingContext, display, nativeBackend->fbConfig);
19185 }
else if (nativeBackend->visualInfo !=
fpl_null) {
19186 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Create GLX legacy rendering context on display '%p' and visual info '%p'", display, nativeBackend->visualInfo);
19187 legacyRenderingContext = glApi->glXCreateContext(display, nativeBackend->visualInfo,
fpl_null, 1);
19188 if (!legacyRenderingContext) {
19189 FPL__ERROR(FPL__MODULE_GLX,
"Failed creating GLX legacy rendering context on display '%p' and visual info '%p'", display, nativeBackend->visualInfo);
19190 goto failed_x11_glx;
19193 FPL__ERROR(FPL__MODULE_GLX,
"No visual info or frame buffer config defined!");
19194 goto failed_x11_glx;
19200 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Activate GLX legacy rendering context '%p' on display '%p' and window '%d'", legacyRenderingContext, display, (
int)window);
19201 if (!glApi->glXMakeCurrent(display, window, legacyRenderingContext)) {
19202 FPL__ERROR(FPL__MODULE_GLX,
"Failed activating GLX legacy rendering context '%p' on display '%p' and window '%d'", legacyRenderingContext, display, (
int)window);
19203 goto failed_x11_glx;
19205 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully activated GLX legacy rendering context '%p' on display '%p' and window '%d'", legacyRenderingContext, display, (
int)window);
19211 glApi->glXCreateContextAttribsARB = (fpl__func_glx_glXCreateContextAttribsARB *)glApi->glXGetProcAddress((
const GLubyte *)
"glXCreateContextAttribsARB");
19214 glApi->glXMakeCurrent(display, 0,
fpl_null);
19216 GLXContext activeRenderingContext;
19221 FPL__ERROR(FPL__MODULE_GLX,
"You have not specified the 'majorVersion' and 'minorVersion' in the VideoSettings");
19222 goto failed_x11_glx;
19225 if (glApi->glXCreateContextAttribsARB ==
fpl_null) {
19226 FPL__ERROR(FPL__MODULE_GLX,
"glXCreateContextAttribsARB is not available, modern OpenGL is not available for your video card");
19227 goto failed_x11_glx;
19233 profile = FPL__GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
19235 profile = FPL__GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
19237 FPL__ERROR(FPL__MODULE_GLX,
"No opengl compability profile selected, please specific Core OpenGLCompabilityFlags_Core or OpenGLCompabilityFlags_Compability");
19238 goto failed_x11_glx;
19241 flags = FPL__GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
19244 int contextAttribIndex = 0;
19246 contextAttribList[contextAttribIndex++] = FPL__GLX_CONTEXT_MAJOR_VERSION_ARB;
19248 contextAttribList[contextAttribIndex++] = FPL__GLX_CONTEXT_MINOR_VERSION_ARB;
19250 contextAttribList[contextAttribIndex++] = FPL__GLX_CONTEXT_PROFILE_MASK_ARB;
19251 contextAttribList[contextAttribIndex++] = profile;
19253 contextAttribList[contextAttribIndex++] = FPL__GLX_CONTEXT_FLAGS_ARB;
19254 contextAttribList[contextAttribIndex++] = flags;
19256 contextAttribList[contextAttribIndex] = 0;
19258 GLXContext modernRenderingContext = glApi->glXCreateContextAttribsARB(display, nativeBackend->fbConfig,
fpl_null, True, contextAttribList);
19259 if (!modernRenderingContext) {
19263 glApi->glXMakeCurrent(display, window, legacyRenderingContext);
19264 activeRenderingContext = legacyRenderingContext;
19266 if (!glApi->glXMakeCurrent(display, window, modernRenderingContext)) {
19270 glApi->glXDestroyContext(display, modernRenderingContext);
19273 glApi->glXMakeCurrent(display, window, legacyRenderingContext);
19274 activeRenderingContext = legacyRenderingContext;
19277 glApi->glXDestroyContext(display, legacyRenderingContext);
19278 legacyRenderingContext =
fpl_null;
19279 activeRenderingContext = modernRenderingContext;
19284 glApi->glXMakeCurrent(display, window, legacyRenderingContext);
19285 activeRenderingContext = legacyRenderingContext;
19291 nativeBackend->context = activeRenderingContext;
19292 nativeBackend->isActiveContext =
true;
19294 backend->surface.window.x11.display = display;
19295 backend->surface.window.x11.window = window;
19296 backend->surface.window.x11.visual = nativeWindowState->visual;
19297 backend->surface.window.x11.screen = nativeWindowState->screen;
19298 backend->surface.opengl.renderingContext = (
void *)activeRenderingContext;
19308 if (nativeBackend->visualInfo !=
fpl_null) {
19310 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Destroy visual info '%p'", nativeBackend->visualInfo);
19311 x11Api->XFree(nativeBackend->visualInfo);
19312 nativeBackend->visualInfo =
fpl_null;
19316 if (legacyRenderingContext) {
19317 glApi->glXDestroyContext(display, legacyRenderingContext);
19319 fpl__VideoBackend_X11OpenGL_Shutdown(appState, windowState, backend);
19325fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_X11OpenGL_Unload) {
19326 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
19327 fpl__UnloadX11OpenGLApi(&nativeBackend->api);
19331fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_X11OpenGL_Load) {
19332 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
19335 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
19342fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_X11OpenGL_Present) {
19343 const fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
19344 const fpl__X11WindowState *x11WinState = &appState->window.x11;
19345 const fpl__X11VideoOpenGLApi *glApi = &nativeBackend->api;
19346 glApi->glXSwapBuffers(x11WinState->display, x11WinState->window);
19349fpl_internal fpl__VideoContext fpl__VideoBackend_X11OpenGL_Construct() {
19350 fpl__VideoContext result = fpl__StubVideoContext();
19351 result.loadFunc = fpl__VideoBackend_X11OpenGL_Load;
19352 result.unloadFunc = fpl__VideoBackend_X11OpenGL_Unload;
19353 result.getProcedureFunc = fpl__VideoBackend_X11OpenGL_GetProcedure;
19354 result.initializeFunc = fpl__VideoBackend_X11OpenGL_Initialize;
19355 result.shutdownFunc = fpl__VideoBackend_X11OpenGL_Shutdown;
19356 result.prepareWindowFunc = fpl__VideoBackend_X11OpenGL_PrepareWindow;
19357 result.presentFunc = fpl__VideoBackend_X11OpenGL_Present;
19367#if defined(FPL__ENABLE_VIDEO_SOFTWARE) && defined(FPL_SUBPLATFORM_X11)
19368typedef struct fpl__VideoBackendX11Software {
19369 fpl__VideoBackend base;
19370 GC graphicsContext;
19372} fpl__VideoBackendX11Software;
19374fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_X11Software_Shutdown) {
19375 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
19376 const fpl__X11Api *x11Api = &nativeAppState->api;
19377 const fpl__X11WindowState *nativeWindowState = &windowState->x11;
19379 fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
19381 if (nativeBackend->buffer !=
fpl_null) {
19386 if (nativeBackend->graphicsContext !=
fpl_null) {
19387 nativeBackend->graphicsContext =
fpl_null;
19391fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_X11Software_Initialize) {
19392 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
19393 const fpl__X11Api *x11Api = &nativeAppState->api;
19394 const fpl__X11WindowState *nativeWindowState = &windowState->x11;
19396 fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
19401 nativeBackend->graphicsContext = x11Api->XCreateGC(nativeWindowState->display, nativeWindowState->window, 0, 0);
19402 if (nativeBackend->graphicsContext ==
fpl_null) {
19406 nativeBackend->buffer = x11Api->XCreateImage(nativeWindowState->display, nativeWindowState->visual, 24, ZPixmap, 0, (
char *)backbuffer->
pixels, backbuffer->
width, backbuffer->
height, 32, (int)backbuffer->
lineWidth);
19407 if (nativeBackend->buffer ==
fpl_null) {
19408 fpl__VideoBackend_X11Software_Shutdown(appState, windowState, backend);
19413 x11Api->XPutImage(nativeWindowState->display, nativeWindowState->window, nativeBackend->graphicsContext, nativeBackend->buffer, 0, 0, 0, 0, backbuffer->
width, backbuffer->
height);
19414 x11Api->XSync(nativeWindowState->display, False);
19416 backend->surface.window.x11.display = nativeWindowState->display;
19417 backend->surface.window.x11.window = nativeWindowState->window;
19418 backend->surface.window.x11.visual = nativeWindowState->visual;
19419 backend->surface.window.x11.screen = nativeWindowState->screen;
19424fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_X11Software_Load) {
19425 fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
19427 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
19431fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_X11Software_Unload) {
19432 fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
19436fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_X11Software_Present) {
19437 const fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
19438 const fpl__X11WindowState *x11WinState = &appState->window.x11;
19439 const fpl__X11Api *x11Api = &appState->x11.api;
19441 x11Api->XPutImage(x11WinState->display, x11WinState->window, nativeBackend->graphicsContext, nativeBackend->buffer, 0, 0, 0, 0, backbuffer->
width, backbuffer->
height);
19442 x11Api->XSync(x11WinState->display, False);
19445fpl_internal fpl__VideoContext fpl__VideoBackend_X11Software_Construct() {
19446 fpl__VideoContext result = fpl__StubVideoContext();
19447 result.loadFunc = fpl__VideoBackend_X11Software_Load;
19448 result.unloadFunc = fpl__VideoBackend_X11Software_Unload;
19449 result.initializeFunc = fpl__VideoBackend_X11Software_Initialize;
19450 result.shutdownFunc = fpl__VideoBackend_X11Software_Shutdown;
19451 result.presentFunc = fpl__VideoBackend_X11Software_Present;
19452 result.recreateOnResize =
true;
19462#if defined(FPL__ENABLE_VIDEO_SOFTWARE) && defined(FPL_PLATFORM_WINDOWS)
19463typedef struct fpl__VideoBackendWin32Software {
19464 fpl__VideoBackend base;
19465 BITMAPINFO bitmapInfo;
19466} fpl__VideoBackendWin32Software;
19468fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_Win32Software_Shutdown) {
19469 fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
19470 BITMAPINFO *bitmapInfo = &nativeBackend->bitmapInfo;
19474fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_Win32Software_Initialize) {
19475 fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
19477 BITMAPINFO *bitmapInfo = &nativeBackend->bitmapInfo;
19479 bitmapInfo->bmiHeader.biSize =
sizeof(BITMAPINFOHEADER);
19480 bitmapInfo->bmiHeader.biWidth = (LONG)backbuffer->
width;
19482 bitmapInfo->bmiHeader.biHeight = -(LONG)backbuffer->
height;
19483 bitmapInfo->bmiHeader.biBitCount = 32;
19484 bitmapInfo->bmiHeader.biCompression = BI_RGB;
19485 bitmapInfo->bmiHeader.biPlanes = 1;
19486 bitmapInfo->bmiHeader.biSizeImage = (DWORD)(backbuffer->
height * backbuffer->
lineWidth);
19490fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_Win32Software_Unload) {
19491 fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
19495fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_Win32Software_Load) {
19496 fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
19498 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
19502fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_Win32Software_Present) {
19503 const fpl__Win32AppState *win32AppState = &appState->win32;
19504 const fpl__Win32WindowState *win32WindowState = &appState->window.win32;
19505 const fpl__Win32Api *wapi = &win32AppState->winApi;
19506 const fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
19510 int32_t targetX = 0;
19511 int32_t targetY = 0;
19512 int32_t targetWidth = area.
width;
19513 int32_t targetHeight = area.
height;
19514 int32_t sourceWidth = backbuffer->
width;
19515 int32_t sourceHeight = backbuffer->
height;
19521 wapi->gdi.StretchDIBits(win32WindowState->deviceContext, 0, 0, area.
width, area.
height, 0, 0, 0, 0,
fpl_null,
fpl_null, DIB_RGB_COLORS, BLACKNESS);
19523 wapi->gdi.StretchDIBits(win32WindowState->deviceContext, targetX, targetY, targetWidth, targetHeight, 0, 0, sourceWidth, sourceHeight, backbuffer->
pixels, &nativeBackend->bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
19527fpl_internal fpl__VideoContext fpl__VideoBackend_Win32Software_Construct() {
19528 fpl__VideoContext result = fpl__StubVideoContext();
19529 result.loadFunc = fpl__VideoBackend_Win32Software_Load;
19530 result.unloadFunc = fpl__VideoBackend_Win32Software_Unload;
19531 result.initializeFunc = fpl__VideoBackend_Win32Software_Initialize;
19532 result.shutdownFunc = fpl__VideoBackend_Win32Software_Shutdown;
19533 result.presentFunc = fpl__VideoBackend_Win32Software_Present;
19534 result.recreateOnResize =
true;
19544#if defined(FPL__ENABLE_VIDEO_VULKAN)
19546#if !fplHasInclude(<vulkan/vulkan.h>) || defined(FPL_NO_PLATFORM_INCLUDES)
19548#if defined(FPL_PLATFORM_WINDOWS)
19549# define fpl__VKAPI_CALL __stdcall
19550# define fpl__VKAPI_PTR fpl__VKAPI_CALL
19551# define fpl__VKAPI_ATTR
19553# define fpl__VKAPI_CALL
19554# define fpl__VKAPI_PTR fpl__VKAPI_CALL
19555# define fpl__VKAPI_ATTR
19558#define FPL__VK_NULL_HANDLE fpl_null
19560#define FPL__VK_MAX_EXTENSION_NAME_SIZE 256
19561#define FPL__VK_MAX_DESCRIPTION_SIZE 256
19563#define FPL__VK_MAKE_VERSION(major, minor, patch) \
19564 ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))
19566typedef enum fpl__VkResult {
19567 FPL__VK_ERROR_OUT_OF_HOST_MEMORY = -1,
19568 FPL__VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
19569 FPL__VK_ERROR_INITIALIZATION_FAILED = -3,
19570 FPL__VK_ERROR_DEVICE_LOST = -4,
19571 FPL__VK_ERROR_MEMORY_MAP_FAILED = -5,
19572 FPL__VK_ERROR_LAYER_NOT_PRESENT = -6,
19573 FPL__VK_ERROR_EXTENSION_NOT_PRESENT = -7,
19574 FPL__VK_ERROR_FEATURE_NOT_PRESENT = -8,
19575 FPL__VK_ERROR_INCOMPATIBLE_DRIVER = -9,
19576 FPL__VK_ERROR_TOO_MANY_OBJECTS = -10,
19577 FPL__VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
19578 FPL__VK_ERROR_FRAGMENTED_POOL = -12,
19579 FPL__VK_ERROR_UNKNOWN = -13,
19581 FPL__VK_SUCCESS = 0,
19583 FPL__VK_NOT_READY = 1,
19584 FPL__VK_TIMEOUT = 2,
19585 FPL__VK_EVENT_SET = 3,
19586 FPL__VK_EVENT_RESET = 4,
19587 FPL__VK_INCOMPLETE = 5,
19589 FPL__VK_RESULT_MAX_ENUM = 0x7FFFFFFF
19592typedef uint32_t fpl__VkFlags;
19593typedef uint32_t fpl__VkBool32;
19595typedef void fpl__VkAllocationCallbacks;
19597typedef void *fpl__VkInstance;
19598typedef void *fpl__VkSurfaceKHR;
19599typedef void *fpl__VkPhysicalDevice;
19601typedef enum fpl__VkStructureType {
19602 FPL__VK_STRUCTURE_TYPE_APPLICATION_INFO = 0,
19603 FPL__VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1,
19604 FPL__VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
19605 FPL__VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
19606 FPL__VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT = 1000128002,
19607 FPL__VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004,
19608 FPL__VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
19609} fpl__VkStructureType;
19611typedef struct fpl__VkApplicationInfo {
19612 fpl__VkStructureType sType;
19614 const char *pApplicationName;
19615 uint32_t applicationVersion;
19616 const char *pEngineName;
19617 uint32_t engineVersion;
19618 uint32_t apiVersion;
19619} fpl__VkApplicationInfo;
19621typedef fpl__VkFlags fpl__VkInstanceCreateFlags;
19623typedef struct fpl__VkInstanceCreateInfo {
19624 fpl__VkStructureType sType;
19626 fpl__VkInstanceCreateFlags flags;
19627 const fpl__VkApplicationInfo *pApplicationInfo;
19628 uint32_t enabledLayerCount;
19629 const char *
const *ppEnabledLayerNames;
19630 uint32_t enabledExtensionCount;
19631 const char *
const *ppEnabledExtensionNames;
19632} fpl__VkInstanceCreateInfo;
19634typedef struct fpl__VkExtensionProperties {
19635 char extensionName[FPL__VK_MAX_EXTENSION_NAME_SIZE];
19636 uint32_t specVersion;
19637} fpl__VkExtensionProperties;
19639typedef struct fpl__VkLayerProperties {
19640 char layerName[FPL__VK_MAX_EXTENSION_NAME_SIZE];
19641 uint32_t specVersion;
19642 uint32_t implementationVersion;
19643 char description[FPL__VK_MAX_DESCRIPTION_SIZE];
19644} fpl__VkLayerProperties;
19647typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkCreateInstance)(
const fpl__VkInstanceCreateInfo *pCreateInfo,
const fpl__VkAllocationCallbacks *pAllocator, fpl__VkInstance *pInstance);
19648typedef void (fpl__VKAPI_PTR *fpl__func_vkDestroyInstance)(fpl__VkInstance instance,
const fpl__VkAllocationCallbacks *pAllocator);
19649typedef void *(fpl__VKAPI_PTR *fpl__func_vkGetInstanceProcAddr)(fpl__VkInstance instance,
const char *pName);
19650typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkEnumerateInstanceExtensionProperties)(
const char *pLayerName, uint32_t *pPropertyCount, fpl__VkExtensionProperties *pProperties);
19651typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkEnumerateInstanceLayerProperties)(uint32_t *pPropertyCount, fpl__VkLayerProperties *pProperties);
19654typedef void (fpl__VKAPI_PTR *fpl__func_vkDestroySurfaceKHR)(fpl__VkInstance instance, fpl__VkSurfaceKHR surface,
const fpl__VkAllocationCallbacks *pAllocator);
19656#if defined(FPL_PLATFORM_WINDOWS)
19658typedef fpl__VkFlags fpl__VkWin32SurfaceCreateFlagsKHR;
19659typedef struct fpl__VkWin32SurfaceCreateInfoKHR {
19660 fpl__VkStructureType sType;
19662 fpl__VkWin32SurfaceCreateFlagsKHR flags;
19663 fpl__Win32InstanceHandle hinstance;
19664 fpl__Win32WindowHandle hwnd;
19665} fpl__VkWin32SurfaceCreateInfoKHR;
19667typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkCreateWin32SurfaceKHR)(fpl__VkInstance instance,
const fpl__VkWin32SurfaceCreateInfoKHR *pCreateInfo,
const fpl__VkAllocationCallbacks *pAllocator, fpl__VkSurfaceKHR *pSurface);
19668typedef fpl__VkBool32(fpl__VKAPI_PTR *fpl__func_vkGetPhysicalDeviceWin32PresentationSupportKHR)(fpl__VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
19670#elif defined(FPL_SUBPLATFORM_X11)
19672typedef fpl__VkFlags fpl__VkXlibSurfaceCreateFlagsKHR;
19673typedef struct fpl__VkXlibSurfaceCreateInfoKHR {
19674 fpl__VkStructureType sType;
19676 fpl__VkXlibSurfaceCreateFlagsKHR flags;
19677 fpl__X11Display *dpy;
19678 fpl__X11Window window;
19679} fpl__VkXlibSurfaceCreateInfoKHR;
19681typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkCreateXlibSurfaceKHR)(fpl__VkInstance instance,
const fpl__VkXlibSurfaceCreateInfoKHR *pCreateInfo,
const fpl__VkAllocationCallbacks *pAllocator, fpl__VkSurfaceKHR *pSurface);
19682typedef fpl__VkBool32(fpl__VKAPI_PTR *fpl__func_vkGetPhysicalDeviceXlibPresentationSupportKHR)(fpl__VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
19686typedef void *fpl__VkDebugUtilsMessengerEXT;
19688typedef enum fpl__VkDebugUtilsMessageSeverityFlagBitsEXT {
19689 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001,
19690 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010,
19691 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100,
19692 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000,
19693 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
19694} fpl__VkDebugUtilsMessageSeverityFlagBitsEXT;
19695typedef fpl__VkFlags fpl__VkDebugUtilsMessageSeverityFlagsEXT;
19697typedef enum fpl__VkDebugUtilsMessageTypeFlagBitsEXT {
19698 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001,
19699 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002,
19700 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004,
19701 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
19702} fpl__VkDebugUtilsMessageTypeFlagBitsEXT;
19703typedef fpl__VkFlags fpl__VkDebugUtilsMessageTypeFlagsEXT;
19705typedef struct fpl__VkDebugUtilsLabelEXT {
19706 fpl__VkStructureType sType;
19708 const char *pLabelName;
19710} fpl__VkDebugUtilsLabelEXT;
19712typedef void fpl__VkDebugUtilsObjectNameInfoEXT;
19713typedef fpl__VkFlags fpl__VkDebugUtilsMessengerCallbackDataFlagsEXT;
19714typedef struct fpl__VkDebugUtilsMessengerCallbackDataEXT {
19715 fpl__VkStructureType sType;
19717 fpl__VkDebugUtilsMessengerCallbackDataFlagsEXT flags;
19718 const char *pMessageIdName;
19719 int32_t messageIdNumber;
19720 const char *pMessage;
19721 uint32_t queueLabelCount;
19722 const fpl__VkDebugUtilsLabelEXT *pQueueLabels;
19723 uint32_t cmdBufLabelCount;
19724 const fpl__VkDebugUtilsLabelEXT *pCmdBufLabels;
19725 uint32_t objectCount;
19726 const fpl__VkDebugUtilsObjectNameInfoEXT *pObjects;
19727} fpl__VkDebugUtilsMessengerCallbackDataEXT;
19729typedef fpl__VkFlags fpl__VkDebugUtilsMessengerCreateFlagsEXT;
19731typedef fpl__VkBool32(fpl__VKAPI_PTR *fpl__func_vkDebugUtilsMessengerCallbackEXT) (
19732 fpl__VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
19733 fpl__VkDebugUtilsMessageTypeFlagsEXT messageTypes,
19734 const fpl__VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
19737typedef struct fpl__VkDebugUtilsMessengerCreateInfoEXT {
19738 fpl__VkStructureType sType;
19740 fpl__VkDebugUtilsMessengerCreateFlagsEXT flags;
19741 fpl__VkDebugUtilsMessageSeverityFlagsEXT messageSeverity;
19742 fpl__VkDebugUtilsMessageTypeFlagsEXT messageType;
19743 fpl__func_vkDebugUtilsMessengerCallbackEXT pfnUserCallback;
19745} fpl__VkDebugUtilsMessengerCreateInfoEXT;
19747typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkCreateDebugUtilsMessengerEXT)(fpl__VkInstance instance,
const fpl__VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
const fpl__VkAllocationCallbacks *pAllocator, fpl__VkDebugUtilsMessengerEXT *pMessenger);
19748typedef void (fpl__VKAPI_PTR *fpl__func_vkDestroyDebugUtilsMessengerEXT)(fpl__VkInstance instance, fpl__VkDebugUtilsMessengerEXT messenger,
const fpl__VkAllocationCallbacks *pAllocator);
19752# if defined(FPL_PLATFORM_WINDOWS)
19753# define VK_USE_PLATFORM_WIN32_KHR
19754# elif defined(FPL_SUBPLATFORM_X11)
19755# define VK_USE_PLATFORM_XLIB_KHR
19758# if !defined(FPL_NO_RUNTIME_LINKING)
19759# define VK_NO_PROTOTYPES
19761# include <vulkan/vulkan.h>
19763# define fpl__VKAPI_CALL VKAPI_CALL
19764# define fpl__VKAPI_PTR VKAPI_PTR
19765# define fpl__VKAPI_ATTR VKAPI_ATTR
19767# define FPL__VK_STRUCTURE_TYPE_APPLICATION_INFO VK_STRUCTURE_TYPE_APPLICATION_INFO
19768# define FPL__VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
19769# define FPL__VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR
19770# define FPL__VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR
19771# define FPL__VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
19773typedef enum fpl__VkResult {
19774 FPL__VK_ERROR_OUT_OF_HOST_MEMORY = VK_ERROR_OUT_OF_HOST_MEMORY,
19775 FPL__VK_ERROR_OUT_OF_DEVICE_MEMORY = VK_ERROR_OUT_OF_DEVICE_MEMORY,
19776 FPL__VK_ERROR_INITIALIZATION_FAILED = VK_ERROR_INITIALIZATION_FAILED,
19777 FPL__VK_ERROR_DEVICE_LOST = VK_ERROR_DEVICE_LOST,
19778 FPL__VK_ERROR_MEMORY_MAP_FAILED = VK_ERROR_MEMORY_MAP_FAILED,
19779 FPL__VK_ERROR_LAYER_NOT_PRESENT = VK_ERROR_LAYER_NOT_PRESENT,
19780 FPL__VK_ERROR_EXTENSION_NOT_PRESENT = VK_ERROR_EXTENSION_NOT_PRESENT,
19781 FPL__VK_ERROR_FEATURE_NOT_PRESENT = VK_ERROR_FEATURE_NOT_PRESENT,
19782 FPL__VK_ERROR_INCOMPATIBLE_DRIVER = VK_ERROR_INCOMPATIBLE_DRIVER,
19783 FPL__VK_ERROR_TOO_MANY_OBJECTS = VK_ERROR_TOO_MANY_OBJECTS,
19784 FPL__VK_ERROR_FORMAT_NOT_SUPPORTED = VK_ERROR_FORMAT_NOT_SUPPORTED,
19785 FPL__VK_ERROR_FRAGMENTED_POOL = VK_ERROR_FRAGMENTED_POOL,
19786 FPL__VK_ERROR_UNKNOWN = VK_ERROR_UNKNOWN,
19788 FPL__VK_SUCCESS = VK_SUCCESS,
19790 FPL__VK_NOT_READY = VK_NOT_READY,
19791 FPL__VK_TIMEOUT = VK_TIMEOUT,
19792 FPL__VK_EVENT_SET = VK_EVENT_SET,
19793 FPL__VK_EVENT_RESET = VK_EVENT_RESET,
19794 FPL__VK_INCOMPLETE = VK_INCOMPLETE,
19796 FPL__VK_RESULT_MAX_ENUM = VK_RESULT_MAX_ENUM
19799# define FPL__VK_NULL_HANDLE VK_NULL_HANDLE
19801# define FPL__VK_MAKE_VERSION(major, minor, patch) VK_MAKE_VERSION(major, minor, patch)
19803typedef VkFlags fpl__VkFlags;
19804typedef VkBool32 fpl__VkBool32;
19806typedef VkAllocationCallbacks fpl__VkAllocationCallbacks;
19808typedef VkInstance fpl__VkInstance;
19809typedef VkSurfaceKHR fpl__VkSurfaceKHR;
19810typedef VkPhysicalDevice fpl__VkPhysicalDevice;
19812typedef VkApplicationInfo fpl__VkApplicationInfo;
19813typedef VkInstanceCreateInfo fpl__VkInstanceCreateInfo;
19815typedef VkExtensionProperties fpl__VkExtensionProperties;
19816typedef VkLayerProperties fpl__VkLayerProperties;
19819typedef PFN_vkCreateInstance fpl__func_vkCreateInstance;
19820typedef PFN_vkDestroyInstance fpl__func_vkDestroyInstance;
19821typedef PFN_vkGetInstanceProcAddr fpl__func_vkGetInstanceProcAddr;
19822typedef PFN_vkEnumerateInstanceExtensionProperties fpl__func_vkEnumerateInstanceExtensionProperties;
19823typedef PFN_vkEnumerateInstanceLayerProperties fpl__func_vkEnumerateInstanceLayerProperties;
19826typedef PFN_vkDestroySurfaceKHR fpl__func_vkDestroySurfaceKHR;
19827#if defined(FPL_PLATFORM_WINDOWS)
19828typedef VkWin32SurfaceCreateInfoKHR fpl__VkWin32SurfaceCreateInfoKHR;
19829typedef PFN_vkCreateWin32SurfaceKHR fpl__func_vkCreateWin32SurfaceKHR;
19830typedef PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR fpl__func_vkGetPhysicalDeviceWin32PresentationSupportKHR;
19831#elif defined(FPL_SUBPLATFORM_X11)
19832typedef VkXlibSurfaceCreateInfoKHR fpl__VkXlibSurfaceCreateInfoKHR;
19833typedef PFN_vkCreateXlibSurfaceKHR fpl__func_vkCreateXlibSurfaceKHR;
19834typedef PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR fpl__func_vkGetPhysicalDeviceXlibPresentationSupportKHR;
19837typedef VkDebugUtilsMessageSeverityFlagBitsEXT fpl__VkDebugUtilsMessageSeverityFlagBitsEXT;
19838typedef VkDebugUtilsMessageSeverityFlagsEXT fpl__VkDebugUtilsMessageSeverityFlagsEXT;
19839# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
19840# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
19841# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
19842# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
19843# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT
19844typedef VkDebugUtilsMessageTypeFlagBitsEXT fpl__VkDebugUtilsMessageTypeFlagBitsEXT;
19845typedef VkDebugUtilsMessageTypeFlagsEXT fpl__VkDebugUtilsMessageTypeFlagsEXT;
19846# define FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
19847# define FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
19848# define FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
19849# define FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT
19850typedef VkDebugUtilsMessengerCallbackDataEXT fpl__VkDebugUtilsMessengerCallbackDataEXT;
19851typedef VkDebugUtilsMessengerEXT fpl__VkDebugUtilsMessengerEXT;
19852typedef PFN_vkDebugUtilsMessengerCallbackEXT fpl__func_vkDebugUtilsMessengerCallbackEXT;
19853typedef VkDebugUtilsMessengerCreateInfoEXT fpl__VkDebugUtilsMessengerCreateInfoEXT;
19855typedef PFN_vkCreateDebugUtilsMessengerEXT fpl__func_vkCreateDebugUtilsMessengerEXT;
19856typedef PFN_vkDestroyDebugUtilsMessengerEXT fpl__func_vkDestroyDebugUtilsMessengerEXT;
19860typedef struct fpl__VulkanApi {
19862 fpl__func_vkCreateInstance vkCreateInstance;
19863 fpl__func_vkDestroyInstance vkDestroyInstance;
19864 fpl__func_vkGetInstanceProcAddr vkGetInstanceProcAddr;
19865 fpl__func_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
19866 fpl__func_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties;
19869fpl_internal void fpl__UnloadVulkanApi(fpl__VulkanApi *api) {
19870 if (api->libraryHandle.isValid) {
19876fpl_internal bool fpl__LoadVulkanApi(fpl__VulkanApi *api,
const char *libraryName) {
19880#if defined(FPL_NO_RUNTIME_LINKING)
19881 api->vkCreateInstance = vkCreateInstance;
19882 api->vkDestroyInstance = vkDestroyInstance;
19883 api->vkGetInstanceProcAddr = vkGetInstanceProcAddr;
19884 api->vkEnumerateInstanceExtensionProperties = vkEnumerateInstanceExtensionProperties;
19885 api->vkEnumerateInstanceLayerProperties = vkEnumerateInstanceLayerProperties;
19889 uint32_t libraryCount = 0;
19891 const char *libraryNames[4];
19893 libraryNames[libraryCount++] = libraryName;
19896#if defined(FPL_PLATFORM_WINDOWS)
19897 libraryNames[libraryCount++] =
"vulkan-1.dll";
19898#elif defined(FPL_SUBPLATFORM_POSIX)
19899 libraryNames[libraryCount++] =
"libvulkan.so";
19900 libraryNames[libraryCount++] =
"libvulkan.so.1";
19902 FPL__WARNING(FPL__MODULE_VIDEO_VULKAN,
"Unsupported Platform!");
19907#define FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libName, target, type, name) \
19908 (target)->name = (type)fplGetDynamicLibraryProc(&libHandle, #name); \
19909 if ((target)->name == fpl_null) { \
19910 FPL__WARNING(FPL__MODULE_VIDEO_VULKAN, "Failed getting procedure address '%s' from library '%s'", #name, libName); \
19914 bool result =
false;
19915 for (uint32_t i = 0; i < libraryCount; ++i) {
19916 const char *libraryName = libraryNames[i];
19918 if (api->libraryHandle.isValid) {
19927 api->libraryHandle = libHandle;
19929 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkCreateInstance, vkCreateInstance);
19930 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkDestroyInstance, vkDestroyInstance);
19931 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkGetInstanceProcAddr, vkGetInstanceProcAddr);
19932 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkEnumerateInstanceExtensionProperties, vkEnumerateInstanceExtensionProperties);
19933 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkEnumerateInstanceLayerProperties, vkEnumerateInstanceLayerProperties);
19940 fpl__UnloadVulkanApi(api);
19943#undef FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE
19948typedef struct fpl__VulkanDebugMessengerUserData {
19952} fpl__VulkanDebugMessengerUserData;
19954typedef struct fpl__VideoBackendVulkan {
19955 fpl__VideoBackend base;
19956 fpl__VulkanApi api;
19957 fpl__VkInstance instanceHandle;
19958 fpl__VkSurfaceKHR surfaceHandle;
19959 fpl__VkDebugUtilsMessengerEXT debugMessenger;
19960 fpl__VulkanDebugMessengerUserData debugMessengerUserData;
19961 const fpl__VkAllocationCallbacks *allocator;
19962 fpl_b32 isInstanceUserDefined;
19963} fpl__VideoBackendVulkan;
19965fpl_internal const char *fpl__GetVulkanResultString(
const fpl__VkResult result) {
19967 case FPL__VK_ERROR_OUT_OF_HOST_MEMORY:
19968 return "Out of Host-Memory";
19969 case FPL__VK_ERROR_OUT_OF_DEVICE_MEMORY:
19970 return "Out of Device-Memory";
19971 case FPL__VK_ERROR_INITIALIZATION_FAILED:
19972 return "Initialization failed";
19973 case FPL__VK_ERROR_DEVICE_LOST:
19974 return "Device lost";
19975 case FPL__VK_ERROR_MEMORY_MAP_FAILED:
19976 return "Memory map failed";
19977 case FPL__VK_ERROR_LAYER_NOT_PRESENT:
19978 return "Layer not present";
19979 case FPL__VK_ERROR_EXTENSION_NOT_PRESENT:
19980 return "Extension not present";
19981 case FPL__VK_ERROR_FEATURE_NOT_PRESENT:
19982 return "Feature not present";
19983 case FPL__VK_ERROR_INCOMPATIBLE_DRIVER:
19984 return "Incompatible driver";
19985 case FPL__VK_ERROR_TOO_MANY_OBJECTS:
19986 return "Too many objects";
19987 case FPL__VK_ERROR_FORMAT_NOT_SUPPORTED:
19988 return "Format not supported";
19989 case FPL__VK_ERROR_FRAGMENTED_POOL:
19990 return "Fragmented pool";
19991 case FPL__VK_SUCCESS:
19993 case FPL__VK_NOT_READY:
19994 return "Not-Ready";
19995 case FPL__VK_TIMEOUT:
19997 case FPL__VK_EVENT_SET:
19998 return "Event-Set";
19999 case FPL__VK_EVENT_RESET:
20000 return "Event-Reset";
20001 case FPL__VK_INCOMPLETE:
20002 return "Incomplete";
20008fpl_internal FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__VideoBackend_Vulkan_GetProcedure) {
20009 const fpl__VideoBackendVulkan *nativeBackend = (
const fpl__VideoBackendVulkan *)backend;
20010 const fpl__VulkanApi *api = &nativeBackend->api;
20011 if (api->libraryHandle.isValid) {
20017fpl_internal FPL__FUNC_VIDEO_BACKEND_GETREQUIREMENTS(fpl__VideoBackend_Vulkan_GetRequirements) {
20018 FPL__CheckArgumentNull(requirements,
false);
20021 fplAssert(requirements->vulkan.instanceExtensionCount <
fplArrayCount(requirements->vulkan.instanceExtensions));
20022 requirements->vulkan.instanceExtensions[requirements->vulkan.instanceExtensionCount++] =
"VK_KHR_surface";
20023#if defined(FPL_PLATFORM_WINDOWS)
20024 fplAssert(requirements->vulkan.instanceExtensionCount <
fplArrayCount(requirements->vulkan.instanceExtensions));
20025 requirements->vulkan.instanceExtensions[requirements->vulkan.instanceExtensionCount++] =
"VK_KHR_win32_surface";
20026#elif defined(FPL_SUBPLATFORM_X11)
20027 fplAssert(requirements->vulkan.instanceExtensionCount <
fplArrayCount(requirements->vulkan.instanceExtensions));
20028 requirements->vulkan.instanceExtensions[requirements->vulkan.instanceExtensionCount++] =
"VK_KHR_xlib_surface";
20039 uint32_t result = FPL__VK_MAKE_VERSION(major, minor, patch);
20043fpl_internal const char *fpl__GetVulkanMessageSeverityName(
const fpl__VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity) {
20044 switch (messageSeverity) {
20045 case FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
return "ERROR";
20046 case FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
return "WARNING";
20047 case FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
return "INFO";
20048 case FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
return "VERBOSE";
20049 default:
return "Unknown";
20053fpl_internal fpl__VKAPI_ATTR fpl__VkBool32 fpl__VKAPI_CALL fpl__VulkanDebugCallback(fpl__VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, fpl__VkDebugUtilsMessageTypeFlagsEXT messageType,
const fpl__VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
void *pUserData) {
20054 fpl__VulkanDebugMessengerUserData *data = (fpl__VulkanDebugMessengerUserData *)pUserData;
20055 const char *message = pCallbackData->pMessage;
20056 if (data->userCallback !=
fpl_null) {
20057 data->userCallback(data->userData, message, messageSeverity, messageType, pCallbackData);
20059 if (messageSeverity == FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
20060 FPL_LOG_ERROR(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
20061 else if (messageSeverity == FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
20062 FPL_LOG_WARN(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
20063 else if (messageSeverity == FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
20064 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
20065 else if (messageSeverity == FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
20066 FPL_LOG_DEBUG(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
20068 FPL_LOG_DEBUG(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
20074fpl_internal void fpl__VulkanDestroyDebugMessenger(fpl__VideoBackendVulkan *nativeBackend) {
20075 if (nativeBackend->debugMessenger !=
fpl_null) {
20076 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Destroy Vulkan Debug Messenger '%p'", nativeBackend->debugMessenger);
20077 const fpl__VulkanApi *api = &nativeBackend->api;
20078 fpl__func_vkDestroyDebugUtilsMessengerEXT destroyFunc = (fpl__func_vkDestroyDebugUtilsMessengerEXT)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkDestroyDebugUtilsMessengerEXT");
20080 destroyFunc(nativeBackend->instanceHandle, nativeBackend->debugMessenger, nativeBackend->allocator);
20081 nativeBackend->debugMessenger =
fpl_null;
20087 fpl__VkDebugUtilsMessageSeverityFlagsEXT severities = 0;
20090 severities = FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
20093 severities = FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
20096 severities = FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
20100 severities = FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
20107 fpl__VulkanDebugMessengerUserData *userData = &nativeBackend->debugMessengerUserData;
20109 userData->userData = settings->
userData;
20113 fpl__VkDebugUtilsMessageTypeFlagsEXT messageTypes =
20114 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
20115 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
20116 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
20118 fpl__VkDebugUtilsMessengerCreateInfoEXT createInfo =
fplZeroInit;
20119 createInfo.sType = FPL__VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
20120 createInfo.messageSeverity = severities;
20121 createInfo.messageType = messageTypes;
20122 createInfo.pfnUserCallback = fpl__VulkanDebugCallback;
20123 createInfo.pUserData = userData;
20125 const fpl__VulkanApi *api = &nativeBackend->api;
20127 fpl__func_vkCreateDebugUtilsMessengerEXT createFunc = (fpl__func_vkCreateDebugUtilsMessengerEXT)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkCreateDebugUtilsMessengerEXT");
20129 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Vulkan instance proc 'vkCreateDebugUtilsMessengerEXT' not found! Maybe the instance extension 'VK_EXT_debug_utils' was not set?");
20133 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Create Vulkan Debug Messenger for Instance '%p' with severity flags of '%lu'", nativeBackend->instanceHandle, severities);
20134 fpl__VkResult creationResult = (fpl__VkResult)createFunc(nativeBackend->instanceHandle, &createInfo, nativeBackend->allocator, &nativeBackend->debugMessenger);
20135 if (creationResult != FPL__VK_SUCCESS) {
20136 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Failed creating Vulkan Debug Messenger for Instance '%p' with severity flags of '%lu' -> (VkResult: %d)!", nativeBackend->instanceHandle, severities, creationResult);
20143fpl_internal FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__VideoBackend_Vulkan_PrepareWindow) {
20144 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
20147 const fpl__VulkanApi *api = &nativeBackend->api;
20149 nativeBackend->allocator =
fpl_null;
20150 nativeBackend->instanceHandle =
fpl_null;
20151 nativeBackend->isInstanceUserDefined =
false;
20155 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Failed getting required instance extensions for creating an Vulkan instance!");
20164 bool supportsDebugUtils =
false;
20166 fpl__VkExtensionProperties *supportedInstanceExtensions =
fpl_null;
20167 uint32_t supportedInstanceExtensionCount = 0;
20168 api->vkEnumerateInstanceExtensionProperties(
fpl_null, &supportedInstanceExtensionCount,
fpl_null);
20169 if (supportedInstanceExtensionCount > 0) {
20170 supportedInstanceExtensions = (fpl__VkExtensionProperties *)fpl__AllocateTemporaryMemory(
sizeof(fpl__VkExtensionProperties) * supportedInstanceExtensionCount, 16);
20171 api->vkEnumerateInstanceExtensionProperties(
fpl_null, &supportedInstanceExtensionCount, supportedInstanceExtensions);
20172 for (uint32_t i = 0; i < supportedInstanceExtensionCount; ++i) {
20173 if (
fplIsStringEqual(supportedInstanceExtensions[i].extensionName,
"VK_EXT_debug_utils")) {
20174 supportsDebugUtils =
true;
20177 fpl__ReleaseTemporaryMemory(supportedInstanceExtensions);
20180 bool supportsValidationLayer =
false;
20182 fpl__VkLayerProperties *supportedLayers =
fpl_null;
20183 uint32_t supportedLayerCount = 0;
20184 api->vkEnumerateInstanceLayerProperties(&supportedLayerCount,
fpl_null);
20185 if (supportedLayerCount > 0) {
20186 supportedLayers = (fpl__VkLayerProperties *)fpl__AllocateTemporaryMemory(
sizeof(fpl__VkLayerProperties) * supportedLayerCount, 16);
20187 api->vkEnumerateInstanceLayerProperties(&supportedLayerCount, supportedLayers);
20188 for (uint32_t i = 0; i < supportedLayerCount; ++i) {
20189 if (
fplIsStringEqual(supportedLayers[i].layerName,
"VK_LAYER_KHRONOS_validation")) {
20190 supportsValidationLayer =
true;
20193 fpl__ReleaseTemporaryMemory(supportedInstanceExtensions);
20196 const char *enabledValidationLayers[4] =
fplZeroInit;
20197 const char *enabledInstanceExtensions[8] =
fplZeroInit;
20198 uint32_t enabledValidationLayerCount = 0;
20199 uint32_t enabledInstanceExtensionCount = 0;
20202 if (!supportsDebugUtils) {
20203 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"VK_EXT_debug_utils instance extension is not supported!");
20206 if (!supportsValidationLayer) {
20207 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"VK_LAYER_KHRONOS_validation instance layer is not supported!");
20211 if (supportsDebugUtils && supportsValidationLayer) {
20212 enabledValidationLayers[enabledValidationLayerCount++] =
"VK_LAYER_KHRONOS_validation";
20213 enabledInstanceExtensions[enabledInstanceExtensionCount++] =
"VK_EXT_debug_utils";
20221 fpl__VkApplicationInfo applicationInfo =
fplZeroInit;
20222 applicationInfo.sType = FPL__VK_STRUCTURE_TYPE_APPLICATION_INFO;
20229 fpl__VkInstanceCreateInfo instanceCreateInfo =
fplZeroInit;
20230 instanceCreateInfo.sType = FPL__VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
20231 instanceCreateInfo.pApplicationInfo = &applicationInfo;
20232 instanceCreateInfo.enabledExtensionCount = enabledInstanceExtensionCount;
20233 instanceCreateInfo.ppEnabledExtensionNames = enabledInstanceExtensions;
20234 instanceCreateInfo.enabledLayerCount = enabledValidationLayerCount;
20235 instanceCreateInfo.ppEnabledLayerNames = enabledValidationLayers;
20237 const fpl__VkAllocationCallbacks *allocator = (
const fpl__VkAllocationCallbacks *)videoSettings->
graphics.
vulkan.
allocator;
20239 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Create Vulkan Instance with %lu extensions and %lu layers", instanceCreateInfo.enabledExtensionCount, instanceCreateInfo.enabledLayerCount);
20240 fpl__VkInstance instance =
fpl_null;
20241 fpl__VkResult creationResult = (fpl__VkResult)api->vkCreateInstance(&instanceCreateInfo, allocator, &instance);
20242 if (creationResult != FPL__VK_SUCCESS) {
20243 const char *creationError = fpl__GetVulkanResultString(creationResult);
20244 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Failed creating Vulkan Instance with %lu extensions and %lu layers -> (VkResult: %d, Error: %s)!", instanceCreateInfo.enabledExtensionCount, instanceCreateInfo.enabledLayerCount, creationResult, creationError);
20248 nativeBackend->allocator = allocator;
20249 nativeBackend->instanceHandle = instance;
20250 nativeBackend->isInstanceUserDefined =
false;
20254 if (!fpl__VulkanCreateDebugMessenger(&videoSettings->
graphics.
vulkan, nativeBackend)) {
20256 FPL__WARNING(FPL__MODULE_VIDEO_VULKAN,
"The debug messenger could not be created, no validation message are printed");
20258 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"The debug messenger could not be created, stop vulkan initialization!");
20269 nativeBackend->isInstanceUserDefined =
true;
20274fpl_internal FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(fpl__VideoBackend_Vulkan_FinalizeWindow) {
20278fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_Vulkan_Shutdown) {
20279 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
20281 const fpl__VulkanApi *api = &nativeBackend->api;
20283 if (nativeBackend->surfaceHandle != FPL__VK_NULL_HANDLE) {
20284 fpl__func_vkDestroySurfaceKHR destroyProc = (fpl__func_vkDestroySurfaceKHR)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkDestroySurfaceKHR");
20287 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Destroy Vulkan Surface '%p'", nativeBackend->surfaceHandle);
20288 destroyProc(nativeBackend->instanceHandle, nativeBackend->surfaceHandle, nativeBackend->allocator);
20290 nativeBackend->surfaceHandle = FPL__VK_NULL_HANDLE;
20294fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_Vulkan_Initialize) {
20295 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
20297 const fpl__VulkanApi *api = &nativeBackend->api;
20299 if (nativeBackend->instanceHandle == FPL__VK_NULL_HANDLE) {
20300 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Cannot create a Vulkan surface without a Vulkan instance!");
20304 fpl__VkSurfaceKHR surfaceHandle = FPL__VK_NULL_HANDLE;
20306#if defined(FPL_PLATFORM_WINDOWS)
20307 FPL_LOG_DEBUG(FPL__MODULE_VIDEO_VULKAN,
"Query Vulkan Instance Proc 'vkCreateWin32SurfaceKHR' for instance '%p'", nativeBackend->instanceHandle);
20308 fpl__func_vkCreateWin32SurfaceKHR createProc = (fpl__func_vkCreateWin32SurfaceKHR)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkCreateWin32SurfaceKHR");
20310 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Vulkan instance proc 'vkCreateWin32SurfaceKHR' not found! Maybe the instance extension 'VK_KHR_win32_surface' was not set?");
20314 fpl__VkWin32SurfaceCreateInfoKHR creationInfo =
fplZeroInit;
20315 creationInfo.sType = FPL__VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
20316 creationInfo.hinstance = fpl__global__InitState.win32.appInstance;
20317 creationInfo.hwnd = windowState->win32.windowHandle;
20319 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Create Vulkan Win32 Surface for hwnd '%p', hinstance '%p' and Vulkan instance '%p'", creationInfo.hwnd, creationInfo.hinstance, nativeBackend->instanceHandle);
20320 fpl__VkResult creationResult = (fpl__VkResult)createProc(nativeBackend->instanceHandle, &creationInfo, nativeBackend->allocator, &surfaceHandle);
20321 if (creationResult != FPL__VK_SUCCESS) {
20322 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Failed creating vulkan surface KHR for Win32 -> (VkResult: %d)!", creationResult);
20325#elif defined(FPL_SUBPLATFORM_X11)
20326 FPL_LOG_DEBUG(FPL__MODULE_VIDEO_VULKAN,
"Query Vulkan Instance Proc 'vkCreateXlibSurfaceKHR' for instance '%p'", nativeBackend->instanceHandle);
20327 fpl__func_vkCreateXlibSurfaceKHR createProc = (fpl__func_vkCreateXlibSurfaceKHR)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkCreateXlibSurfaceKHR");
20329 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Vulkan instance proc 'vkCreateXlibSurfaceKHR' not found! Maybe the instance extension 'VK_KHR_xlib_surface' was not set?");
20333 fpl__VkXlibSurfaceCreateInfoKHR creationInfo =
fplZeroInit;
20334 creationInfo.sType = FPL__VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
20335 creationInfo.dpy = (fpl__X11Display *)windowState->x11.display;
20336 creationInfo.window = windowState->x11.window;
20338 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Create Vulkan X11 Surface for display '%p', window '%d' and Vulkan instance '%p'", creationInfo.dpy, creationInfo.window, nativeBackend->instanceHandle);
20339 fpl__VkResult creationResult = createProc(nativeBackend->instanceHandle, &creationInfo, nativeBackend->allocator, &surfaceHandle);
20340 if (creationResult != FPL__VK_SUCCESS) {
20341 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Failed creating vulkan surface KHR for X11 -> (VkResult: %d)!", creationResult);
20345 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Unsupported Platform!");
20349 fplAssert(surfaceHandle != FPL__VK_NULL_HANDLE);
20350 nativeBackend->surfaceHandle = surfaceHandle;
20352 backend->surface.vulkan.instance = nativeBackend->instanceHandle;
20353 backend->surface.vulkan.surfaceKHR = nativeBackend->surfaceHandle;
20355#if defined(FPL_PLATFORM_WINDOWS)
20356 backend->surface.window.win32.windowHandle = windowState->win32.windowHandle;
20357 backend->surface.window.win32.deviceContext = windowState->win32.deviceContext;
20358#elif defined(FPL_SUBPLATFORM_X11)
20359 backend->surface.window.x11.display = windowState->x11.display;
20360 backend->surface.window.x11.window = windowState->x11.window;
20361 backend->surface.window.x11.screen = windowState->x11.screen;
20362 backend->surface.window.x11.visual = windowState->x11.visual;
20368fpl_internal FPL__FUNC_VIDEO_BACKEND_DESTROYEDWINDOW(fpl__VideoBackend_Vulkan_DestroyedWindow) {
20369 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
20372 if (!nativeBackend->isInstanceUserDefined && nativeBackend->instanceHandle !=
fpl_null && nativeBackend->debugMessenger !=
fpl_null) {
20373 fpl__VulkanDestroyDebugMessenger(nativeBackend);
20377 const fpl__VulkanApi *api = &nativeBackend->api;
20378 if (!nativeBackend->isInstanceUserDefined && nativeBackend->instanceHandle !=
fpl_null) {
20379 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Destroy Vulkan Instance '%p'", nativeBackend->instanceHandle);
20380 api->vkDestroyInstance(nativeBackend->instanceHandle, nativeBackend->allocator);
20381 nativeBackend->instanceHandle =
fpl_null;
20385fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_Vulkan_Unload) {
20386 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
20389 fpl__UnloadVulkanApi(&nativeBackend->api);
20395fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_Vulkan_Load) {
20396 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
20401 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
20411fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_Vulkan_Present) {
20412 const fpl__VideoBackendVulkan *nativeBackend = (
const fpl__VideoBackendVulkan *)backend;
20415fpl_internal fpl__VideoContext fpl__VideoBackend_Vulkan_Construct() {
20416 fpl__VideoContext result = fpl__StubVideoContext();
20417 result.loadFunc = fpl__VideoBackend_Vulkan_Load;
20418 result.unloadFunc = fpl__VideoBackend_Vulkan_Unload;
20419 result.getProcedureFunc = fpl__VideoBackend_Vulkan_GetProcedure;
20420 result.initializeFunc = fpl__VideoBackend_Vulkan_Initialize;
20421 result.shutdownFunc = fpl__VideoBackend_Vulkan_Shutdown;
20422 result.prepareWindowFunc = fpl__VideoBackend_Vulkan_PrepareWindow;
20423 result.finalizeWindowFunc = fpl__VideoBackend_Vulkan_FinalizeWindow;
20424 result.destroyedWindowFunc = fpl__VideoBackend_Vulkan_DestroyedWindow;
20425 result.presentFunc = fpl__VideoBackend_Vulkan_Present;
20426 result.getRequirementsFunc = fpl__VideoBackend_Vulkan_GetRequirements;
20440#if !defined(FPL__AUDIO_BACKENDS_IMPLEMENTED) && defined(FPL__ENABLE_AUDIO)
20441# define FPL__AUDIO_BACKENDS_IMPLEMENTED
20443typedef enum fpl__AudioDeviceState {
20444 fpl__AudioDeviceState_Uninitialized = 0,
20445 fpl__AudioDeviceState_Stopped,
20446 fpl__AudioDeviceState_Started,
20447 fpl__AudioDeviceState_Starting,
20448 fpl__AudioDeviceState_Stopping,
20449} fpl__AudioDeviceState;
20451typedef struct fpl__CommonAudioState {
20454 void *clientUserData;
20455 volatile fpl__AudioDeviceState state;
20456} fpl__CommonAudioState;
20458fpl_internal uint32_t fpl__ReadAudioFramesFromClient(
const fpl__CommonAudioState *commonAudio, uint32_t frameCount,
void *pSamples) {
20459 uint32_t framesRead = 0;
20460 if (commonAudio->clientReadCallback !=
fpl_null) {
20461 framesRead = commonAudio->clientReadCallback(&commonAudio->internalFormat, frameCount, pSamples, commonAudio->clientUserData);
20463 uint32_t channels = commonAudio->internalFormat.channels;
20464 uint32_t samplesRead = framesRead * channels;
20466 uint32_t consumedBytes = samplesRead * sampleSize;
20467 uint32_t remainingBytes = ((frameCount * channels) - samplesRead) * sampleSize;
20468 if (remainingBytes > 0) {
20469 fplMemoryClear((uint8_t *)pSamples + consumedBytes, remainingBytes);
20471 return(samplesRead);
20475#if defined(FPL_PLATFORM_WINDOWS)
20476static GUID FPL__GUID_KSDATAFORMAT_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} };
20477static GUID FPL__GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} };
20481fpl_internal fpl__AudioDeviceState fpl__AudioGetDeviceState(fpl__CommonAudioState *audioState);
20482fpl_internal bool fpl__IsAudioDeviceInitialized(fpl__CommonAudioState *audioState);
20483fpl_internal bool fpl__IsAudioDeviceStarted(fpl__CommonAudioState *audioState);
20490#if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
20492# include <mmsystem.h>
20493# include <dsound.h>
20495#define FPL__FUNC_DSOUND_DirectSoundCreate(name) HRESULT WINAPI name(const GUID* pcGuidDevice, LPDIRECTSOUND *ppDS8, LPUNKNOWN pUnkOuter)
20496typedef FPL__FUNC_DSOUND_DirectSoundCreate(func_DirectSoundCreate);
20497#define FPL__FUNC_DSOUND_DirectSoundEnumerateW(name) HRESULT WINAPI name(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext)
20498typedef FPL__FUNC_DSOUND_DirectSoundEnumerateW(func_DirectSoundEnumerateW);
20499static GUID FPL__IID_IDirectSoundNotify = { 0xb0210783, 0x89cd, 0x11d0, {0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16} };
20500#define FPL__DIRECTSOUND_MAX_PERIODS 4
20502typedef struct fpl__DirectSoundApi {
20503 HMODULE dsoundLibrary;
20504 func_DirectSoundCreate *DirectSoundCreate;
20505 func_DirectSoundEnumerateW *DirectSoundEnumerateW;
20506} fpl__DirectSoundApi;
20508fpl_internal void fpl__UnloadDirectSoundApi(fpl__DirectSoundApi *dsoundApi) {
20510 if (dsoundApi->dsoundLibrary !=
fpl_null) {
20511 FreeLibrary(dsoundApi->dsoundLibrary);
20516fpl_internal bool fpl__LoadDirectSoundApi(fpl__DirectSoundApi *dsoundApi) {
20518 bool result =
false;
20519 const char *dsoundLibraryName =
"dsound.dll";
20523 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_AUDIO_DIRECTSOUND, dsoundLibrary, dsoundLibraryName);
20524 dsoundApi->dsoundLibrary = dsoundLibrary;
20525 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_DIRECTSOUND, dsoundLibrary, dsoundLibraryName, dsoundApi, func_DirectSoundCreate, DirectSoundCreate);
20526 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_DIRECTSOUND, dsoundLibrary, dsoundLibraryName, dsoundApi, func_DirectSoundEnumerateW, DirectSoundEnumerateW);
20530 fpl__UnloadDirectSoundApi(dsoundApi);
20535typedef struct fpl__DirectSoundAudioState {
20536 fpl__DirectSoundApi api;
20537 LPDIRECTSOUND directSound;
20538 LPDIRECTSOUNDBUFFER primaryBuffer;
20539 LPDIRECTSOUNDBUFFER secondaryBuffer;
20540 LPDIRECTSOUNDNOTIFY notify;
20541 HANDLE notifyEvents[FPL__DIRECTSOUND_MAX_PERIODS];
20543 uint32_t lastProcessedFrame;
20544 bool breakMainLoop;
20545} fpl__DirectSoundAudioState;
20547typedef struct fpl__DirectSoundDeviceInfos {
20549 uint32_t foundDeviceCount;
20550 uint32_t maxDeviceCount;
20551 uint32_t capacityOverflow;
20552} fpl__DirectSoundDeviceInfos;
20554fpl_internal BOOL CALLBACK fpl__GetDeviceCallbackDirectSound(LPGUID lpGuid, LPCWSTR lpwstrDescription, LPCWSTR lpwstrModule, LPVOID lpContext) {
20555 fpl__DirectSoundDeviceInfos *infos = (fpl__DirectSoundDeviceInfos *)lpContext;
20557 if (infos->deviceInfos !=
fpl_null) {
20558 uint32_t index = infos->foundDeviceCount++;
20559 if (index < infos->maxDeviceCount) {
20567 infos->capacityOverflow++;
20570 infos->foundDeviceCount++;
20575fpl_internal uint32_t fpl__GetAudioDevicesDirectSound(fpl__DirectSoundAudioState *dsoundState,
fplAudioDeviceInfo *deviceInfos, uint32_t maxDeviceCount) {
20576 uint32_t result = 0;
20577 const fpl__DirectSoundApi *dsoundApi = &dsoundState->api;
20579 infos.maxDeviceCount = maxDeviceCount;
20580 infos.deviceInfos = deviceInfos;
20581 infos.capacityOverflow = 0;
20582 dsoundApi->DirectSoundEnumerateW(fpl__GetDeviceCallbackDirectSound, &infos);
20583 result = infos.foundDeviceCount;
20584 if (infos.capacityOverflow > 0) {
20585 FPL__ERROR(FPL__MODULE_AUDIO_DIRECTSOUND,
"Capacity of '%lu' for audio device infos has been reached. '%lu' audio devices are not included in the result", maxDeviceCount, infos.capacityOverflow);
20590fpl_internal bool fpl__AudioReleaseDirectSound(
const fpl__CommonAudioState *commonAudio, fpl__DirectSoundAudioState *dsoundState) {
20591 if (dsoundState->stopEvent !=
fpl_null) {
20592 CloseHandle(dsoundState->stopEvent);
20595 for (uint32_t i = 0; i < commonAudio->internalFormat.periods; ++i) {
20596 if (dsoundState->notifyEvents[i]) {
20597 CloseHandle(dsoundState->notifyEvents[i]);
20601 if (dsoundState->notify !=
fpl_null) {
20602 IDirectSoundNotify_Release(dsoundState->notify);
20605 if (dsoundState->secondaryBuffer !=
fpl_null) {
20606 IDirectSoundBuffer_Release(dsoundState->secondaryBuffer);
20609 if (dsoundState->primaryBuffer !=
fpl_null) {
20610 IDirectSoundBuffer_Release(dsoundState->primaryBuffer);
20613 if (dsoundState->directSound !=
fpl_null) {
20614 IDirectSound_Release(dsoundState->directSound);
20617 fpl__UnloadDirectSoundApi(&dsoundState->api);
20626 GUID guid_IID_IDirectSoundNotify = FPL__IID_IDirectSoundNotify;
20628 GUID *guid_IID_IDirectSoundNotify = &FPL__IID_IDirectSoundNotify;
20631#define FPL__DSOUND_INIT_ERROR(ret, format, ...) do { \
20632 FPL__ERROR(FPL__MODULE_AUDIO_DIRECTSOUND, format, ## __VA_ARGS__); \
20633 fpl__AudioReleaseDirectSound(commonAudio, dsoundState); \
20638 fpl__PlatformAppState *appState = fpl__global__AppState;
20639 fpl__Win32AppState *win32AppState = &appState->win32;
20640 const fpl__Win32Api *apiFuncs = &win32AppState->winApi;
20643 fpl__DirectSoundApi *dsoundApi = &dsoundState->api;
20644 if (!fpl__LoadDirectSoundApi(dsoundApi)) {
20652 fplAssert(
sizeof(GUID) ==
sizeof(targetDevice->
id.dshow));
20653 deviceId = (
const GUID *)&targetDevice->
id.dshow;
20655 if (!SUCCEEDED(dsoundApi->DirectSoundCreate(deviceId, &dsoundState->directSound,
fpl_null))) {
20657 fpl__Win32FormatGuidString(idString,
fplArrayCount(idString), deviceId);
20663 waveFormat.Format.cbSize =
sizeof(waveFormat);
20664 waveFormat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
20665 waveFormat.Format.nChannels = (WORD)targetFormat->
channels;
20666 waveFormat.Format.nSamplesPerSec = (DWORD)targetFormat->
sampleRate;
20668 waveFormat.Format.nBlockAlign = (waveFormat.Format.nChannels * waveFormat.Format.wBitsPerSample) / 8;
20669 waveFormat.Format.nAvgBytesPerSec = waveFormat.Format.nBlockAlign * waveFormat.Format.nSamplesPerSec;
20670 waveFormat.Samples.wValidBitsPerSample = waveFormat.Format.wBitsPerSample;
20672 waveFormat.SubFormat = FPL__GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
20674 waveFormat.SubFormat = FPL__GUID_KSDATAFORMAT_SUBTYPE_PCM;
20679# if defined(FPL__ENABLE_WINDOW)
20681 windowHandle = appState->window.win32.windowHandle;
20685 windowHandle = apiFuncs->user.GetDesktopWindow();
20689 if (FAILED(IDirectSound_SetCooperativeLevel(dsoundState->directSound, windowHandle, (targetFormat->
preferExclusiveMode) ? DSSCL_EXCLUSIVE : DSSCL_PRIORITY))) {
20695 descDSPrimary.dwSize =
sizeof(DSBUFFERDESC);
20696 descDSPrimary.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
20697 if (FAILED(IDirectSound_CreateSoundBuffer(dsoundState->directSound, &descDSPrimary, &dsoundState->primaryBuffer,
fpl_null))) {
20702 if (FAILED(IDirectSoundBuffer_SetFormat(dsoundState->primaryBuffer, (WAVEFORMATEX *)&waveFormat))) {
20703 char subformatString[64];
20704 fpl__Win32FormatGuidString(subformatString,
fplArrayCount(subformatString), &waveFormat.SubFormat);
20705 FPL__DSOUND_INIT_ERROR(
fplAudioResultType_Failed,
"Failed setting audio format for primary sound buffer to (nChannels: %d, nSamplesPerSec: %u, wBitsPerSample: %d, subformat: '%s')!", waveFormat.Format.nChannels, waveFormat.Format.nSamplesPerSec, waveFormat.Format.wBitsPerSample, subformatString);
20709 DWORD requiredSize;
20710 if (FAILED(IDirectSoundBuffer_GetFormat(dsoundState->primaryBuffer,
fpl_null, 0, &requiredSize))) {
20715 char actualFormatData[1024];
20716 WAVEFORMATEXTENSIBLE *actualFormat = (WAVEFORMATEXTENSIBLE *)actualFormatData;
20717 if (FAILED(IDirectSoundBuffer_GetFormat(dsoundState->primaryBuffer, (WAVEFORMATEX *)actualFormat, requiredSize,
fpl_null))) {
20718 FPL__DSOUND_INIT_ERROR(
fplAudioResultType_Failed,
"Failed getting actual wave format from size '{%u}' for primary sound buffer!", requiredSize);
20724 if (fpl__Win32IsEqualGuid(actualFormat->SubFormat, FPL__GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
20725 if (actualFormat->Format.wBitsPerSample == 64) {
20731 switch (actualFormat->Format.wBitsPerSample) {
20749 internalFormat.
channels = actualFormat->Format.nChannels;
20750 internalFormat.
sampleRate = actualFormat->Format.nSamplesPerSec;
20757 commonAudio->internalFormat = internalFormat;
20761 "Using internal format (Channels: %u, Samplerate: %u, Type: %s, Periods: %u, Buffer size frames/bytes: %u/%u)",
20764 internalFormatTypeName,
20767 bufferSizeInBytes);
20771 descDS.dwSize =
sizeof(DSBUFFERDESC);
20772 descDS.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
20773 descDS.dwBufferBytes = (DWORD)bufferSizeInBytes;
20774 descDS.lpwfxFormat = (WAVEFORMATEX *)&waveFormat;
20775 if (FAILED(IDirectSound_CreateSoundBuffer(dsoundState->directSound, &descDS, &dsoundState->secondaryBuffer,
fpl_null))) {
20776 FPL__DSOUND_INIT_ERROR(
fplAudioResultType_Failed,
"Failed creating secondary sound buffer with buffer size of '%u' bytes", bufferSizeInBytes);
20780 if (FAILED(IDirectSoundBuffer_QueryInterface(dsoundState->secondaryBuffer, guid_IID_IDirectSoundNotify, (
void **)&dsoundState->notify))) {
20785 DWORD periodSizeInBytes = bufferSizeInBytes / internalFormat.
periods;
20786 DSBPOSITIONNOTIFY notifyPoints[FPL__DIRECTSOUND_MAX_PERIODS];
20787 for (uint32_t i = 0; i < internalFormat.
periods; ++i) {
20788 dsoundState->notifyEvents[i] = CreateEventA(
fpl_null,
false,
false,
fpl_null);
20789 if (dsoundState->notifyEvents[i] ==
fpl_null) {
20790 fpl__AudioReleaseDirectSound(commonAudio, dsoundState);
20795 notifyPoints[i].dwOffset = i * periodSizeInBytes;
20796 notifyPoints[i].hEventNotify = dsoundState->notifyEvents[i];
20798 if (FAILED(IDirectSoundNotify_SetNotificationPositions(dsoundState->notify, internalFormat.
periods, notifyPoints))) {
20804 if (dsoundState->stopEvent ==
fpl_null) {
20811fpl_internal void fpl__AudioStopMainLoopDirectSound(fpl__DirectSoundAudioState *dsoundState) {
20812 dsoundState->breakMainLoop =
true;
20813 SetEvent(dsoundState->stopEvent);
20816fpl_internal bool fpl__GetCurrentFrameDirectSound(
const fpl__CommonAudioState *commonAudio, fpl__DirectSoundAudioState *dsoundState, uint32_t *pCurrentPos) {
20821 DWORD dwCurrentPosition;
20822 if (FAILED(IDirectSoundBuffer_GetCurrentPosition(dsoundState->secondaryBuffer,
fpl_null, &dwCurrentPosition))) {
20826 fplAssert(commonAudio->internalFormat.channels > 0);
20827 *pCurrentPos = (uint32_t)dwCurrentPosition /
fplGetAudioSampleSizeInBytes(commonAudio->internalFormat.type) / commonAudio->internalFormat.channels;
20831fpl_internal uint32_t fpl__GetAvailableFramesDirectSound(
const fpl__CommonAudioState *commonAudio, fpl__DirectSoundAudioState *dsoundState) {
20833 uint32_t currentFrame;
20834 if (!fpl__GetCurrentFrameDirectSound(commonAudio, dsoundState, ¤tFrame)) {
20841 uint32_t totalFrameCount = commonAudio->internalFormat.bufferSizeInFrames;
20842 uint32_t committedBeg = currentFrame;
20843 uint32_t committedEnd;
20844 committedEnd = dsoundState->lastProcessedFrame;
20845 if (committedEnd <= committedBeg) {
20846 committedEnd += totalFrameCount;
20849 uint32_t committedSize = (committedEnd - committedBeg);
20850 fplAssert(committedSize <= totalFrameCount);
20852 return totalFrameCount - committedSize;
20855fpl_internal uint32_t fpl__WaitForFramesDirectSound(
const fpl__CommonAudioState *commonAudio, fpl__DirectSoundAudioState *dsoundState) {
20856 fplAssert(commonAudio->internalFormat.sampleRate > 0);
20857 fplAssert(commonAudio->internalFormat.periods > 0);
20860 DWORD timeoutInMilliseconds = (commonAudio->internalFormat.bufferSizeInFrames / (commonAudio->internalFormat.sampleRate / 1000)) / commonAudio->internalFormat.periods;
20861 if (timeoutInMilliseconds < 1) {
20862 timeoutInMilliseconds = 1;
20866 unsigned int eventCount = commonAudio->internalFormat.periods + 1;
20867 HANDLE pEvents[FPL__DIRECTSOUND_MAX_PERIODS + 1];
20868 fplMemoryCopy(dsoundState->notifyEvents,
sizeof(HANDLE) * commonAudio->internalFormat.periods, pEvents);
20869 pEvents[eventCount - 1] = dsoundState->stopEvent;
20871 while (!dsoundState->breakMainLoop) {
20873 uint32_t framesAvailable = fpl__GetAvailableFramesDirectSound(commonAudio, dsoundState);
20874 if (framesAvailable > 0) {
20875 return framesAvailable;
20879 WaitForMultipleObjects(eventCount, pEvents, FALSE, timeoutInMilliseconds);
20883 return fpl__GetAvailableFramesDirectSound(commonAudio, dsoundState);
20886fpl_internal bool fpl__AudioStopDirectSound(fpl__DirectSoundAudioState *dsoundState) {
20888 if (FAILED(IDirectSoundBuffer_Stop(dsoundState->secondaryBuffer))) {
20891 IDirectSoundBuffer_SetCurrentPosition(dsoundState->secondaryBuffer, 0);
20896 fplAssert(commonAudio->internalFormat.channels > 0);
20897 fplAssert(commonAudio->internalFormat.periods > 0);
20902 uint32_t framesToRead = commonAudio->internalFormat.bufferSizeInFrames / commonAudio->internalFormat.periods;
20903 uint32_t desiredLockSize = framesToRead * commonAudio->internalFormat.channels * audioSampleSizeBytes;
20906 DWORD actualLockSize;
20908 DWORD actualLockSize2;
20910 if (SUCCEEDED(IDirectSoundBuffer_Lock(dsoundState->secondaryBuffer, 0, desiredLockSize, &pLockPtr, &actualLockSize, &pLockPtr2, &actualLockSize2, 0))) {
20911 framesToRead = actualLockSize / audioSampleSizeBytes / commonAudio->internalFormat.channels;
20912 fpl__ReadAudioFramesFromClient(commonAudio, framesToRead, pLockPtr);
20913 IDirectSoundBuffer_Unlock(dsoundState->secondaryBuffer, pLockPtr, actualLockSize, pLockPtr2, actualLockSize2);
20914 dsoundState->lastProcessedFrame = framesToRead;
20915 if (FAILED(IDirectSoundBuffer_Play(dsoundState->secondaryBuffer, 0, 0, DSBPLAY_LOOPING))) {
20924fpl_internal void fpl__AudioRunMainLoopDirectSound(
const fpl__CommonAudioState *commonAudio, fpl__DirectSoundAudioState *dsoundState) {
20925 fplAssert(commonAudio->internalFormat.channels > 0);
20930 ResetEvent(dsoundState->stopEvent);
20933 dsoundState->breakMainLoop =
false;
20934 while (!dsoundState->breakMainLoop) {
20936 uint32_t framesAvailable = fpl__WaitForFramesDirectSound(commonAudio, dsoundState);
20937 if (framesAvailable == 0) {
20942 if (dsoundState->breakMainLoop) {
20947 DWORD lockOffset = dsoundState->lastProcessedFrame * commonAudio->internalFormat.channels * audioSampleSizeBytes;
20948 DWORD lockSize = framesAvailable * commonAudio->internalFormat.channels * audioSampleSizeBytes;
20951 DWORD actualLockSize;
20953 DWORD actualLockSize2;
20954 if (FAILED(IDirectSoundBuffer_Lock(dsoundState->secondaryBuffer, lockOffset, lockSize, &pLockPtr, &actualLockSize, &pLockPtr2, &actualLockSize2, 0))) {
20955 FPL__ERROR(FPL__MODULE_AUDIO_DIRECTSOUND,
"Failed to lock directsound secondary buffer '%p' for offset/size (%lu / %lu)", dsoundState->secondaryBuffer, lockOffset, lockSize);
20960 uint32_t frameCount = actualLockSize / audioSampleSizeBytes / commonAudio->internalFormat.channels;
20961 fpl__ReadAudioFramesFromClient(commonAudio, frameCount, pLockPtr);
20962 dsoundState->lastProcessedFrame = (dsoundState->lastProcessedFrame + frameCount) % commonAudio->internalFormat.bufferSizeInFrames;
20965 IDirectSoundBuffer_Unlock(dsoundState->secondaryBuffer, pLockPtr, actualLockSize, pLockPtr2, actualLockSize2);
20976#if defined(FPL__ENABLE_AUDIO_ALSA)
20979typedef struct fpl__AlsaBufferScale {
20980 const char *deviceName;
20982} fpl__AlsaBufferScale;
20984fpl_globalvar fpl__AlsaBufferScale fpl__globalAlsaBufferScales[] = {
20988fpl_internal float fpl__AlsaGetBufferScale(
const char *deviceName) {
20990 for (
int i = 0; i <
fplArrayCount(fpl__globalAlsaBufferScales); ++i) {
20991 const char *testDeviceName = fpl__globalAlsaBufferScales[i].deviceName;
20993 float scale = fpl__globalAlsaBufferScales[i].scale;
21001fpl_internal uint32_t fpl__AlsaScaleBufferSize(
const uint32_t bufferSize,
const float scale) {
21002 uint32_t result =
fplMax(1, (uint32_t)(bufferSize * scale));
21006#if defined(FPL__ANONYMOUS_ALSA_HEADERS)
21007typedef void snd_pcm_t;
21008typedef void snd_pcm_format_mask_t;
21009typedef void snd_pcm_hw_params_t;
21010typedef void snd_pcm_sw_params_t;
21012typedef uint64_t snd_pcm_uframes_t;
21013typedef int64_t snd_pcm_sframes_t;
21015typedef struct snd_pcm_chmap_t {
21016 unsigned int channels;
21017 unsigned int pos[0];
21020typedef enum snd_pcm_stream_t {
21021 SND_PCM_STREAM_PLAYBACK = 0,
21022 SND_PCM_STREAM_CAPTURE,
21025typedef struct snd_pcm_channel_area_t {
21027 unsigned int first;
21029} snd_pcm_channel_area_t;
21031typedef enum snd_pcm_format_t {
21032 SND_PCM_FORMAT_UNKNOWN = -1,
21033 SND_PCM_FORMAT_S8 = 0,
21035 SND_PCM_FORMAT_S16_LE,
21036 SND_PCM_FORMAT_S16_BE,
21037 SND_PCM_FORMAT_U16_LE,
21038 SND_PCM_FORMAT_U16_BE,
21039 SND_PCM_FORMAT_S24_LE,
21040 SND_PCM_FORMAT_S24_BE,
21041 SND_PCM_FORMAT_U24_LE,
21042 SND_PCM_FORMAT_U24_BE,
21043 SND_PCM_FORMAT_S32_LE,
21044 SND_PCM_FORMAT_S32_BE,
21045 SND_PCM_FORMAT_U32_LE,
21046 SND_PCM_FORMAT_U32_BE,
21047 SND_PCM_FORMAT_FLOAT_LE,
21048 SND_PCM_FORMAT_FLOAT_BE,
21049 SND_PCM_FORMAT_FLOAT64_LE,
21050 SND_PCM_FORMAT_FLOAT64_BE,
21051 SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
21052 SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
21053 SND_PCM_FORMAT_MU_LAW,
21054 SND_PCM_FORMAT_A_LAW,
21055 SND_PCM_FORMAT_IMA_ADPCM,
21056 SND_PCM_FORMAT_MPEG,
21057 SND_PCM_FORMAT_GSM,
21058 SND_PCM_FORMAT_S20_LE,
21059 SND_PCM_FORMAT_S20_BE,
21060 SND_PCM_FORMAT_U20_LE,
21061 SND_PCM_FORMAT_U20_BE,
21062 SND_PCM_FORMAT_SPECIAL,
21063 SND_PCM_FORMAT_S24_3LE,
21064 SND_PCM_FORMAT_S24_3BE,
21065 SND_PCM_FORMAT_U24_3LE,
21066 SND_PCM_FORMAT_U24_3BE,
21067 SND_PCM_FORMAT_S20_3LE,
21068 SND_PCM_FORMAT_S20_3BE,
21069 SND_PCM_FORMAT_U20_3LE,
21070 SND_PCM_FORMAT_U20_3BE,
21071 SND_PCM_FORMAT_S18_3LE,
21072 SND_PCM_FORMAT_S18_3BE,
21073 SND_PCM_FORMAT_U18_3LE,
21074 SND_PCM_FORMAT_U18_3BE,
21075 SND_PCM_FORMAT_S16,
21076 SND_PCM_FORMAT_U16,
21077 SND_PCM_FORMAT_S24,
21078 SND_PCM_FORMAT_U24,
21079 SND_PCM_FORMAT_S32,
21080 SND_PCM_FORMAT_U32,
21081 SND_PCM_FORMAT_FLOAT,
21082 SND_PCM_FORMAT_FLOAT64,
21083 SND_PCM_FORMAT_IEC958_SUBFRAME,
21084 SND_PCM_FORMAT_S20,
21088typedef enum snd_pcm_access_t {
21089 SND_PCM_ACCESS_MMAP_INTERLEAVED = 0,
21090 SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
21091 SND_PCM_ACCESS_MMAP_COMPLEX,
21092 SND_PCM_ACCESS_RW_INTERLEAVED,
21093 SND_PCM_ACCESS_RW_NONINTERLEAVED
21096#define SND_PCM_NO_AUTO_RESAMPLE 0x00010000
21097#define SND_PCM_NO_AUTO_CHANNELS 0x00020000
21098#define SND_PCM_NO_AUTO_FORMAT 0x00040000
21101# include <alsa/asoundlib.h>
21104#define FPL__ALSA_FUNC_snd_pcm_open(name) int name(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
21105typedef FPL__ALSA_FUNC_snd_pcm_open(fpl__alsa_func_snd_pcm_open);
21106#define FPL__ALSA_FUNC_snd_pcm_close(name) int name(snd_pcm_t *pcm)
21107typedef FPL__ALSA_FUNC_snd_pcm_close(fpl__alsa_func_snd_pcm_close);
21108#define FPL__ALSA_FUNC_snd_pcm_hw_params_sizeof(name) size_t name(void)
21109typedef FPL__ALSA_FUNC_snd_pcm_hw_params_sizeof(fpl__alsa_func_snd_pcm_hw_params_sizeof);
21110#define FPL__ALSA_FUNC_snd_pcm_hw_params(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
21111typedef FPL__ALSA_FUNC_snd_pcm_hw_params(fpl__alsa_func_snd_pcm_hw_params);
21112#define FPL__ALSA_FUNC_snd_pcm_hw_params_any(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
21113typedef FPL__ALSA_FUNC_snd_pcm_hw_params_any(fpl__alsa_func_snd_pcm_hw_params_any);
21114#define FPL__ALSA_FUNC_snd_pcm_hw_params_set_format(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val)
21115typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_format(fpl__alsa_func_snd_pcm_hw_params_set_format);
21116#define FPL__ALSA_FUNC_snd_pcm_hw_params_set_format_first(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t *format)
21117typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_format_first(fpl__alsa_func_snd_pcm_hw_params_set_format_first);
21118#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_format_mask(name) void name(snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask)
21119typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_format_mask(fpl__alsa_func_snd_pcm_hw_params_get_format_mask);
21120#define FPL__ALSA_FUNC_snd_pcm_hw_params_set_channels_near(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
21121typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_channels_near(fpl__alsa_func_snd_pcm_hw_params_set_channels_near);
21122#define FPL__ALSA_FUNC_snd_pcm_hw_params_set_rate_resample(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
21123typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_rate_resample(fpl__alsa_func_snd_pcm_hw_params_set_rate_resample);
21124#define FPL__ALSA_FUNC_snd_pcm_hw_params_set_rate_near(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
21125typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_rate_near(fpl__alsa_func_snd_pcm_hw_params_set_rate_near);
21126#define FPL__ALSA_FUNC_snd_pcm_hw_params_set_buffer_size_near(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
21127typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_buffer_size_near(fpl__alsa_func_snd_pcm_hw_params_set_buffer_size_near);
21128#define FPL__ALSA_FUNC_snd_pcm_hw_params_set_periods_near(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
21129typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_periods_near(fpl__alsa_func_snd_pcm_hw_params_set_periods_near);
21130#define FPL__ALSA_FUNC_snd_pcm_hw_params_set_access(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access)
21131typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_access(fpl__alsa_func_snd_pcm_hw_params_set_access);
21132#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_format(name) int name(const snd_pcm_hw_params_t *params, snd_pcm_format_t *val)
21133typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_format(fpl__alsa_func_snd_pcm_hw_params_get_format);
21134#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_channels(name) int name(const snd_pcm_hw_params_t *params, unsigned int *val)
21135typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_channels(fpl__alsa_func_snd_pcm_hw_params_get_channels);
21136#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_rate(name) int name(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
21137typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_rate(fpl__alsa_func_snd_pcm_hw_params_get_rate);
21138#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_buffer_size(name) int name(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
21139typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_buffer_size(fpl__alsa_func_snd_pcm_hw_params_get_buffer_size);
21140#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_periods(name) int name(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
21141typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_periods(fpl__alsa_func_snd_pcm_hw_params_get_periods);
21142#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_access(name) int name(const snd_pcm_hw_params_t *params, snd_pcm_access_t *_access)
21143typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_access(fpl__alsa_func_snd_pcm_hw_params_get_access);
21144#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_sbits(name) int name(const snd_pcm_hw_params_t *params)
21145typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_sbits(fpl__alsa_func_snd_pcm_hw_params_get_sbits);
21146#define FPL__ALSA_FUNC_snd_pcm_sw_params_sizeof(name) size_t name(void)
21147typedef FPL__ALSA_FUNC_snd_pcm_sw_params_sizeof(fpl__alsa_func_snd_pcm_sw_params_sizeof);
21148#define FPL__ALSA_FUNC_snd_pcm_sw_params_current(name) int name(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
21149typedef FPL__ALSA_FUNC_snd_pcm_sw_params_current(fpl__alsa_func_snd_pcm_sw_params_current);
21150#define FPL__ALSA_FUNC_snd_pcm_sw_params_set_avail_min(name) int name(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
21151typedef FPL__ALSA_FUNC_snd_pcm_sw_params_set_avail_min(fpl__alsa_func_snd_pcm_sw_params_set_avail_min);
21152#define FPL__ALSA_FUNC_snd_pcm_sw_params_set_start_threshold(name) int name(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
21153typedef FPL__ALSA_FUNC_snd_pcm_sw_params_set_start_threshold(fpl__alsa_func_snd_pcm_sw_params_set_start_threshold);
21154#define FPL__ALSA_FUNC_snd_pcm_sw_params(name) int name(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
21155typedef FPL__ALSA_FUNC_snd_pcm_sw_params(fpl__alsa_func_snd_pcm_sw_params);
21156#define FPL__ALSA_FUNC_snd_pcm_format_mask_sizeof(name) size_t name(void)
21157typedef FPL__ALSA_FUNC_snd_pcm_format_mask_sizeof(fpl__alsa_func_snd_pcm_format_mask_sizeof);
21158#define FPL__ALSA_FUNC_snd_pcm_format_mask_test(name) int name(const snd_pcm_format_mask_t *mask, snd_pcm_format_t val)
21159typedef FPL__ALSA_FUNC_snd_pcm_format_mask_test(fpl__alsa_func_snd_pcm_format_mask_test);
21160#define FPL__ALSA_FUNC_snd_pcm_get_chmap(name) snd_pcm_chmap_t *name(snd_pcm_t *pcm)
21161typedef FPL__ALSA_FUNC_snd_pcm_get_chmap(fpl__alsa_func_snd_pcm_get_chmap);
21162#define FPL__ALSA_FUNC_snd_pcm_prepare(name) int name(snd_pcm_t *pcm)
21163typedef FPL__ALSA_FUNC_snd_pcm_prepare(fpl__alsa_func_snd_pcm_prepare);
21164#define FPL__ALSA_FUNC_snd_pcm_start(name) int name(snd_pcm_t *pcm)
21165typedef FPL__ALSA_FUNC_snd_pcm_start(fpl__alsa_func_snd_pcm_start);
21166#define FPL__ALSA_FUNC_snd_pcm_drop(name) int name(snd_pcm_t *pcm)
21167typedef FPL__ALSA_FUNC_snd_pcm_drop(fpl__alsa_func_snd_pcm_drop);
21168#define FPL__ALSA_FUNC_snd_device_name_hint(name) int name(int card, const char *iface, void ***hints)
21169typedef FPL__ALSA_FUNC_snd_device_name_hint(fpl__alsa_func_snd_device_name_hint);
21170#define FPL__ALSA_FUNC_snd_device_name_get_hint(name) char *name(const void *hint, const char *id)
21171typedef FPL__ALSA_FUNC_snd_device_name_get_hint(fpl__alsa_func_snd_device_name_get_hint);
21172#define FPL__ALSA_FUNC_snd_device_name_free_hint(name) int name(void **hints)
21173typedef FPL__ALSA_FUNC_snd_device_name_free_hint(fpl__alsa_func_snd_device_name_free_hint);
21174#define FPL__ALSA_FUNC_snd_card_get_index(name) int name(const char *name)
21175typedef FPL__ALSA_FUNC_snd_card_get_index(fpl__alsa_func_snd_card_get_index);
21176#define FPL__ALSA_FUNC_snd_pcm_mmap_begin(name) int name(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
21177typedef FPL__ALSA_FUNC_snd_pcm_mmap_begin(fpl__alsa_func_snd_pcm_mmap_begin);
21178#define FPL__ALSA_FUNC_snd_pcm_mmap_commit(name) snd_pcm_sframes_t name(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t frames)
21179typedef FPL__ALSA_FUNC_snd_pcm_mmap_commit(fpl__alsa_func_snd_pcm_mmap_commit);
21180#define FPL__ALSA_FUNC_snd_pcm_recover(name) int name(snd_pcm_t *pcm, int err, int silent)
21181typedef FPL__ALSA_FUNC_snd_pcm_recover(fpl__alsa_func_snd_pcm_recover);
21182#define FPL__ALSA_FUNC_snd_pcm_writei(name) snd_pcm_sframes_t name(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
21183typedef FPL__ALSA_FUNC_snd_pcm_writei(fpl__alsa_func_snd_pcm_writei);
21184#define FPL__ALSA_FUNC_snd_pcm_avail(name) snd_pcm_sframes_t name(snd_pcm_t *pcm)
21185typedef FPL__ALSA_FUNC_snd_pcm_avail(fpl__alsa_func_snd_pcm_avail);
21186#define FPL__ALSA_FUNC_snd_pcm_avail_update(name) snd_pcm_sframes_t name(snd_pcm_t *pcm)
21187typedef FPL__ALSA_FUNC_snd_pcm_avail_update(fpl__alsa_func_snd_pcm_avail_update);
21188#define FPL__ALSA_FUNC_snd_pcm_wait(name) int name(snd_pcm_t *pcm, int timeout)
21189typedef FPL__ALSA_FUNC_snd_pcm_wait(fpl__alsa_func_snd_pcm_wait);
21190#define FPL__ALSA_FUNC_snd_pcm_info_sizeof(name) size_t name(void)
21191typedef FPL__ALSA_FUNC_snd_pcm_info_sizeof(fpl__alsa_func_snd_pcm_info_sizeof);
21192#define FPL__ALSA_FUNC_snd_pcm_info(name) int name(snd_pcm_t *handle, snd_pcm_info_t *info)
21193typedef FPL__ALSA_FUNC_snd_pcm_info(fpl__alsa_func_snd_pcm_info);
21194#define FPL__ALSA_FUNC_snd_pcm_info_get_name(name) const char* name(const snd_pcm_info_t *obj)
21195typedef FPL__ALSA_FUNC_snd_pcm_info_get_name(fpl__alsa_func_snd_pcm_info_get_name);
21197typedef struct fpl__AlsaAudioApi {
21199 fpl__alsa_func_snd_pcm_open *snd_pcm_open;
21200 fpl__alsa_func_snd_pcm_close *snd_pcm_close;
21201 fpl__alsa_func_snd_pcm_hw_params_sizeof *snd_pcm_hw_params_sizeof;
21202 fpl__alsa_func_snd_pcm_hw_params *snd_pcm_hw_params;
21203 fpl__alsa_func_snd_pcm_hw_params_any *snd_pcm_hw_params_any;
21204 fpl__alsa_func_snd_pcm_hw_params_set_format *snd_pcm_hw_params_set_format;
21205 fpl__alsa_func_snd_pcm_hw_params_set_format_first *snd_pcm_hw_params_set_format_first;
21206 fpl__alsa_func_snd_pcm_hw_params_get_format_mask *snd_pcm_hw_params_get_format_mask;
21207 fpl__alsa_func_snd_pcm_hw_params_set_channels_near *snd_pcm_hw_params_set_channels_near;
21208 fpl__alsa_func_snd_pcm_hw_params_set_rate_resample *snd_pcm_hw_params_set_rate_resample;
21209 fpl__alsa_func_snd_pcm_hw_params_set_rate_near *snd_pcm_hw_params_set_rate_near;
21210 fpl__alsa_func_snd_pcm_hw_params_set_buffer_size_near *snd_pcm_hw_params_set_buffer_size_near;
21211 fpl__alsa_func_snd_pcm_hw_params_set_periods_near *snd_pcm_hw_params_set_periods_near;
21212 fpl__alsa_func_snd_pcm_hw_params_set_access *snd_pcm_hw_params_set_access;
21213 fpl__alsa_func_snd_pcm_hw_params_get_format *snd_pcm_hw_params_get_format;
21214 fpl__alsa_func_snd_pcm_hw_params_get_channels *snd_pcm_hw_params_get_channels;
21215 fpl__alsa_func_snd_pcm_hw_params_get_rate *snd_pcm_hw_params_get_rate;
21216 fpl__alsa_func_snd_pcm_hw_params_get_buffer_size *snd_pcm_hw_params_get_buffer_size;
21217 fpl__alsa_func_snd_pcm_hw_params_get_periods *snd_pcm_hw_params_get_periods;
21218 fpl__alsa_func_snd_pcm_hw_params_get_access *snd_pcm_hw_params_get_access;
21219 fpl__alsa_func_snd_pcm_hw_params_get_sbits *snd_pcm_hw_params_get_sbits;
21220 fpl__alsa_func_snd_pcm_sw_params_sizeof *snd_pcm_sw_params_sizeof;
21221 fpl__alsa_func_snd_pcm_sw_params_current *snd_pcm_sw_params_current;
21222 fpl__alsa_func_snd_pcm_sw_params_set_avail_min *snd_pcm_sw_params_set_avail_min;
21223 fpl__alsa_func_snd_pcm_sw_params_set_start_threshold *snd_pcm_sw_params_set_start_threshold;
21224 fpl__alsa_func_snd_pcm_sw_params *snd_pcm_sw_params;
21225 fpl__alsa_func_snd_pcm_format_mask_sizeof *snd_pcm_format_mask_sizeof;
21226 fpl__alsa_func_snd_pcm_format_mask_test *snd_pcm_format_mask_test;
21227 fpl__alsa_func_snd_pcm_get_chmap *snd_pcm_get_chmap;
21228 fpl__alsa_func_snd_pcm_prepare *snd_pcm_prepare;
21229 fpl__alsa_func_snd_pcm_start *snd_pcm_start;
21230 fpl__alsa_func_snd_pcm_drop *snd_pcm_drop;
21231 fpl__alsa_func_snd_device_name_hint *snd_device_name_hint;
21232 fpl__alsa_func_snd_device_name_get_hint *snd_device_name_get_hint;
21233 fpl__alsa_func_snd_device_name_free_hint *snd_device_name_free_hint;
21234 fpl__alsa_func_snd_card_get_index *snd_card_get_index;
21235 fpl__alsa_func_snd_pcm_mmap_begin *snd_pcm_mmap_begin;
21236 fpl__alsa_func_snd_pcm_mmap_commit *snd_pcm_mmap_commit;
21237 fpl__alsa_func_snd_pcm_recover *snd_pcm_recover;
21238 fpl__alsa_func_snd_pcm_writei *snd_pcm_writei;
21239 fpl__alsa_func_snd_pcm_avail *snd_pcm_avail;
21240 fpl__alsa_func_snd_pcm_avail_update *snd_pcm_avail_update;
21241 fpl__alsa_func_snd_pcm_wait *snd_pcm_wait;
21242 fpl__alsa_func_snd_pcm_info_sizeof *snd_pcm_info_sizeof;
21243 fpl__alsa_func_snd_pcm_info *snd_pcm_info;
21244 fpl__alsa_func_snd_pcm_info_get_name *snd_pcm_info_get_name;
21245} fpl__AlsaAudioApi;
21247typedef struct fpl__AlsaAudioState {
21248 fpl__AlsaAudioApi api;
21249 snd_pcm_t *pcmDevice;
21250 void *intermediaryBuffer;
21252 bool breakMainLoop;
21253} fpl__AlsaAudioState;
21255fpl_internal void fpl__UnloadAlsaApi(fpl__AlsaAudioApi *alsaApi) {
21257 if (alsaApi->libHandle !=
fpl_null) {
21258 dlclose(alsaApi->libHandle);
21263fpl_internal bool fpl__LoadAlsaApi(fpl__AlsaAudioApi *alsaApi) {
21265 const char *libraryNames[] = {
21268 bool result =
false;
21269 for (uint32_t index = 0; index <
fplArrayCount(libraryNames); ++index) {
21270 const char *libName = libraryNames[index];
21274 FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_AUDIO_ALSA, libHandle, libName);
21275 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_open, snd_pcm_open);
21276 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_close, snd_pcm_close);
21277 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_sizeof, snd_pcm_hw_params_sizeof);
21278 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params, snd_pcm_hw_params);
21279 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_any, snd_pcm_hw_params_any);
21280 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_set_format, snd_pcm_hw_params_set_format);
21281 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_set_format_first, snd_pcm_hw_params_set_format_first);
21282 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_get_format_mask, snd_pcm_hw_params_get_format_mask);
21283 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_set_channels_near, snd_pcm_hw_params_set_channels_near);
21284 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_set_rate_resample, snd_pcm_hw_params_set_rate_resample);
21285 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_set_rate_near, snd_pcm_hw_params_set_rate_near);
21286 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_set_buffer_size_near, snd_pcm_hw_params_set_buffer_size_near);
21287 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_set_periods_near, snd_pcm_hw_params_set_periods_near);
21288 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_set_access, snd_pcm_hw_params_set_access);
21289 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_get_format, snd_pcm_hw_params_get_format);
21290 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_get_channels, snd_pcm_hw_params_get_channels);
21291 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_get_rate, snd_pcm_hw_params_get_rate);
21292 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_get_buffer_size, snd_pcm_hw_params_get_buffer_size);
21293 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_get_periods, snd_pcm_hw_params_get_periods);
21294 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_get_access, snd_pcm_hw_params_get_access);
21295 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params_get_sbits, snd_pcm_hw_params_get_sbits);
21296 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_sw_params_sizeof, snd_pcm_sw_params_sizeof);
21297 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_sw_params_current, snd_pcm_sw_params_current);
21298 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_sw_params_set_avail_min, snd_pcm_sw_params_set_avail_min);
21299 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_sw_params_set_start_threshold, snd_pcm_sw_params_set_start_threshold);
21300 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_sw_params, snd_pcm_sw_params);
21301 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_format_mask_sizeof, snd_pcm_format_mask_sizeof);
21302 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_format_mask_test, snd_pcm_format_mask_test);
21303 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_get_chmap, snd_pcm_get_chmap);
21304 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_prepare, snd_pcm_prepare);
21305 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_start, snd_pcm_start);
21306 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_drop, snd_pcm_drop);
21307 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_device_name_hint, snd_device_name_hint);
21308 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_device_name_get_hint, snd_device_name_get_hint);
21309 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_device_name_free_hint, snd_device_name_free_hint);
21310 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_card_get_index, snd_card_get_index);
21311 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_mmap_begin, snd_pcm_mmap_begin);
21312 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_mmap_commit, snd_pcm_mmap_commit);
21313 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_recover, snd_pcm_recover);
21314 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_writei, snd_pcm_writei);
21315 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_avail, snd_pcm_avail);
21316 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_avail_update, snd_pcm_avail_update);
21317 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_wait, snd_pcm_wait);
21318 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_info_sizeof, snd_pcm_info_sizeof);
21319 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_info, snd_pcm_info);
21320 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_info_get_name, snd_pcm_info_get_name);
21321 alsaApi->libHandle = libHandle;
21327 fpl__UnloadAlsaApi(alsaApi);
21334 if (requiresRestart !=
fpl_null) {
21335 *requiresRestart =
false;
21337 const fpl__AlsaAudioApi *alsaApi = &alsaState->api;
21339 while (!alsaState->breakMainLoop) {
21340 snd_pcm_sframes_t framesAvailable = alsaApi->snd_pcm_avail_update(alsaState->pcmDevice);
21341 if (framesAvailable < 0) {
21342 if (framesAvailable == -EPIPE) {
21343 if (alsaApi->snd_pcm_recover(alsaState->pcmDevice, framesAvailable, 1) < 0) {
21346 if (requiresRestart !=
fpl_null) {
21347 *requiresRestart =
true;
21349 framesAvailable = alsaApi->snd_pcm_avail_update(alsaState->pcmDevice);
21350 if (framesAvailable < 0) {
21357 if (framesAvailable >= periodSizeInFrames) {
21358 return periodSizeInFrames;
21361 if (framesAvailable < periodSizeInFrames) {
21363 int waitResult = alsaApi->snd_pcm_wait(alsaState->pcmDevice, -1);
21364 if (waitResult < 0) {
21365 if (waitResult == -EPIPE) {
21366 if (alsaApi->snd_pcm_recover(alsaState->pcmDevice, waitResult, 1) < 0) {
21369 if (requiresRestart !=
fpl_null) {
21370 *requiresRestart =
true;
21378 snd_pcm_sframes_t framesAvailable = alsaApi->snd_pcm_avail_update(alsaState->pcmDevice);
21379 if (framesAvailable < 0) {
21382 return framesAvailable;
21385fpl_internal bool fpl__GetAudioFramesFromClientAlsa(fpl__CommonAudioState *commonAudio, fpl__AlsaAudioState *alsaState) {
21387 const fpl__AlsaAudioApi *alsaApi = &alsaState->api;
21389 if (!fpl__IsAudioDeviceStarted(commonAudio) && fpl__AudioGetDeviceState(commonAudio) != fpl__AudioDeviceState_Starting) {
21392 if (alsaState->breakMainLoop) {
21396 if (alsaState->isUsingMMap) {
21398 bool requiresRestart;
21399 uint32_t framesAvailable = fpl__AudioWaitForFramesAlsa(&commonAudio->internalFormat, alsaState, &requiresRestart);
21400 if (framesAvailable == 0) {
21403 if (alsaState->breakMainLoop) {
21407 const snd_pcm_channel_area_t *channelAreas;
21408 snd_pcm_uframes_t mappedOffset;
21409 snd_pcm_uframes_t mappedFrames = framesAvailable;
21410 while (framesAvailable > 0) {
21411 int result = alsaApi->snd_pcm_mmap_begin(alsaState->pcmDevice, &channelAreas, &mappedOffset, &mappedFrames);
21415 if (mappedFrames > 0) {
21416 void *bufferPtr = (uint8_t *)channelAreas[0].addr + ((channelAreas[0].first + (mappedOffset * channelAreas[0].step)) / 8);
21417 fpl__ReadAudioFramesFromClient(commonAudio, mappedFrames, bufferPtr);
21419 result = alsaApi->snd_pcm_mmap_commit(alsaState->pcmDevice, mappedOffset, mappedFrames);
21420 if (result < 0 || (snd_pcm_uframes_t)result != mappedFrames) {
21421 alsaApi->snd_pcm_recover(alsaState->pcmDevice, result, 1);
21424 if (requiresRestart) {
21425 if (alsaApi->snd_pcm_start(alsaState->pcmDevice) < 0) {
21429 if (framesAvailable >= mappedFrames) {
21430 framesAvailable -= mappedFrames;
21432 framesAvailable = 0;
21438 while (!alsaState->breakMainLoop) {
21439 uint32_t framesAvailable = fpl__AudioWaitForFramesAlsa(&commonAudio->internalFormat, alsaState,
fpl_null);
21440 if (framesAvailable == 0) {
21443 if (alsaState->breakMainLoop) {
21446 fpl__ReadAudioFramesFromClient(commonAudio, framesAvailable, alsaState->intermediaryBuffer);
21447 snd_pcm_sframes_t framesWritten = alsaApi->snd_pcm_writei(alsaState->pcmDevice, alsaState->intermediaryBuffer, framesAvailable);
21448 if (framesWritten < 0) {
21449 if (framesWritten == -EAGAIN) {
21452 }
else if (framesWritten == -EPIPE) {
21454 if (alsaApi->snd_pcm_recover(alsaState->pcmDevice, framesWritten, 1) < 0) {
21455 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to recover device after underrun!");
21458 framesWritten = alsaApi->snd_pcm_writei(alsaState->pcmDevice, alsaState->intermediaryBuffer, framesAvailable);
21459 if (framesWritten < 0) {
21460 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to write data to the PCM device!");
21466 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to write audio frames from client, error code: %d!", framesWritten);
21478fpl_internal void fpl__AudioStopMainLoopAlsa(fpl__AlsaAudioState *alsaState) {
21480 alsaState->breakMainLoop =
true;
21483fpl_internal bool fpl__AudioReleaseAlsa(
const fpl__CommonAudioState *commonAudio, fpl__AlsaAudioState *alsaState) {
21485 fpl__AlsaAudioApi *alsaApi = &alsaState->api;
21486 if (alsaState->pcmDevice !=
fpl_null) {
21487 alsaApi->snd_pcm_close(alsaState->pcmDevice);
21489 if (alsaState->intermediaryBuffer !=
fpl_null) {
21490 fpl__ReleaseDynamicMemory(alsaState->intermediaryBuffer);
21491 alsaState->intermediaryBuffer =
fpl_null;
21494 fpl__UnloadAlsaApi(alsaApi);
21501 const fpl__AlsaAudioApi *alsaApi = &alsaState->api;
21504 if (alsaApi->snd_pcm_prepare(alsaState->pcmDevice) < 0) {
21505 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to prepare PCM device '%p'!", alsaState->pcmDevice);
21510 if (!fpl__GetAudioFramesFromClientAlsa(commonAudio, alsaState)) {
21511 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to get initial audio frames from client!");
21515 if (alsaState->isUsingMMap) {
21516 if (alsaApi->snd_pcm_start(alsaState->pcmDevice) < 0) {
21517 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to start PCM device '%p'!", alsaState->pcmDevice);
21525fpl_internal bool fpl__AudioStopAlsa(fpl__AlsaAudioState *alsaState) {
21527 const fpl__AlsaAudioApi *alsaApi = &alsaState->api;
21528 if (alsaApi->snd_pcm_drop(alsaState->pcmDevice)) {
21529 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to drop the PCM device '%p'!", alsaState->pcmDevice);
21541 return SND_PCM_FORMAT_U8;
21543 return SND_PCM_FORMAT_S16_BE;
21545 return SND_PCM_FORMAT_S24_3BE;
21547 return SND_PCM_FORMAT_S32_BE;
21549 return SND_PCM_FORMAT_FLOAT_BE;
21551 return SND_PCM_FORMAT_UNKNOWN;
21556 return SND_PCM_FORMAT_U8;
21558 return SND_PCM_FORMAT_S16_LE;
21560 return SND_PCM_FORMAT_S24_3LE;
21562 return SND_PCM_FORMAT_S32_LE;
21564 return SND_PCM_FORMAT_FLOAT_LE;
21566 return SND_PCM_FORMAT_UNKNOWN;
21571fpl_internal void fpl__AudioRunMainLoopAlsa(fpl__CommonAudioState *commonAudio, fpl__AlsaAudioState *alsaState) {
21573 alsaState->breakMainLoop =
false;
21574 while (!alsaState->breakMainLoop && fpl__GetAudioFramesFromClientAlsa(commonAudio, alsaState)) {
21581 case SND_PCM_FORMAT_U8:
21583 case SND_PCM_FORMAT_S16_BE:
21584 case SND_PCM_FORMAT_S16_LE:
21586 case SND_PCM_FORMAT_S24_3BE:
21587 case SND_PCM_FORMAT_S24_3LE:
21589 case SND_PCM_FORMAT_S32_BE:
21590 case SND_PCM_FORMAT_S32_LE:
21592 case SND_PCM_FORMAT_FLOAT_BE:
21593 case SND_PCM_FORMAT_FLOAT_LE:
21601 snd_pcm_hw_params_t *hardwareParams =
fpl_null;
21602 snd_pcm_sw_params_t *softwareParams =
fpl_null;
21604# define FPL__ALSA_INIT_ERROR(ret, format, ...) do { \
21605 if (softwareParams != fpl_null) fpl__ReleaseTemporaryMemory(softwareParams); \
21606 if (hardwareParams != fpl_null) fpl__ReleaseTemporaryMemory(hardwareParams); \
21607 FPL__ERROR(FPL__MODULE_AUDIO_ALSA, format, ## __VA_ARGS__); \
21608 fpl__AudioReleaseAlsa(commonAudio, alsaState); \
21609 return fplAudioResultType_Failed; \
21613 fpl__AlsaAudioApi *alsaApi = &alsaState->api;
21614 if (!fpl__LoadAlsaApi(alsaApi)) {
21623 snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
21624 int openMode = SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT;
21626 const char *defaultDeviceNames[16] =
fplZeroInit;
21627 int defaultDeviceCount = 0;
21628 defaultDeviceNames[defaultDeviceCount++] =
"default";
21630 defaultDeviceNames[defaultDeviceCount++] =
"dmix";
21631 defaultDeviceNames[defaultDeviceCount++] =
"dmix:0";
21632 defaultDeviceNames[defaultDeviceCount++] =
"dmix:0,0";
21634 defaultDeviceNames[defaultDeviceCount++] =
"hw";
21635 defaultDeviceNames[defaultDeviceCount++] =
"hw:0";
21636 defaultDeviceNames[defaultDeviceCount++] =
"hw:0,0";
21638 bool isDeviceOpen =
false;
21639 for (
size_t defaultDeviceIndex = 0; defaultDeviceIndex < defaultDeviceCount; ++defaultDeviceIndex) {
21640 const char *defaultDeviceName = defaultDeviceNames[defaultDeviceIndex];
21641 FPL_LOG_DEBUG(
"ALSA",
"Opening PCM audio device '%s'", defaultDeviceName);
21642 if (alsaApi->snd_pcm_open(&alsaState->pcmDevice, defaultDeviceName, stream, openMode) == 0) {
21643 FPL_LOG_DEBUG(
"ALSA",
"Successfully opened PCM audio device '%s'", defaultDeviceName);
21644 isDeviceOpen =
true;
21648 FPL_LOG_ERROR(
"ALSA",
"Failed opening PCM audio device '%s'!", defaultDeviceName);
21651 if (!isDeviceOpen) {
21655 const char *forcedDeviceId = audioSettings->
targetDevice.
id.alsa;
21657 if (alsaApi->snd_pcm_open(&alsaState->pcmDevice, forcedDeviceId, stream, openMode) < 0) {
21671 float bufferSizeScaleFactor = 1.0f;
21673 size_t pcmInfoSize = alsaApi->snd_pcm_info_sizeof();
21674 snd_pcm_info_t *pcmInfo = (snd_pcm_info_t *)fpl__AllocateTemporaryMemory(pcmInfoSize, 8);
21676 FPL__ALSA_INIT_ERROR(fplAudioResultType_OutOfMemory,
"Out of stack memory for snd_pcm_info_t!");
21680 if (alsaApi->snd_pcm_info(alsaState->pcmDevice, pcmInfo) == 0) {
21681 const char *deviceName = alsaApi->snd_pcm_info_get_name(pcmInfo);
21685 char **ppDeviceHints;
21686 if (alsaApi->snd_device_name_hint(-1,
"pcm", (
void ***)&ppDeviceHints) == 0) {
21687 char **ppNextDeviceHint = ppDeviceHints;
21689 while (*ppNextDeviceHint !=
fpl_null) {
21690 char *hintName = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"NAME");
21691 char *hintDesc = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"DESC");
21692 char *hintIOID = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"IOID");
21694 bool foundDevice =
false;
21698 bufferSizeScaleFactor = fpl__AlsaGetBufferScale(hintDesc);
21699 foundDevice =
true;
21708 ++ppNextDeviceHint;
21715 alsaApi->snd_device_name_free_hint((
void **)ppDeviceHints);
21718 bufferSizeScaleFactor = fpl__AlsaGetBufferScale(deviceName);
21722 fpl__ReleaseTemporaryMemory(pcmInfo);
21731 FPL_LOG_DEBUG(
"ALSA",
"Get hardware parameters from device '%s'", deviceName);
21732 size_t hardwareParamsSize = alsaApi->snd_pcm_hw_params_sizeof();
21733 hardwareParams = (snd_pcm_hw_params_t *)fpl__AllocateTemporaryMemory(hardwareParamsSize, 8);
21735 if (alsaApi->snd_pcm_hw_params_any(alsaState->pcmDevice, hardwareParams) < 0) {
21738 FPL_LOG_DEBUG(
"ALSA",
"Successfullyy got hardware parameters from device '%s'", deviceName);
21743 alsaState->isUsingMMap =
false;
21744 if (!audioSettings->
specific.alsa.noMMap) {
21745 if (alsaApi->snd_pcm_hw_params_set_access(alsaState->pcmDevice, hardwareParams, SND_PCM_ACCESS_MMAP_INTERLEAVED) == 0) {
21746 alsaState->isUsingMMap =
true;
21748 FPL_LOG_ERROR(
"ALSA",
"Failed setting MMap access mode for device '%s', trying fallback to standard mode!", deviceName);
21751 if (!alsaState->isUsingMMap) {
21752 if (alsaApi->snd_pcm_hw_params_set_access(alsaState->pcmDevice, hardwareParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
21765 size_t formatMaskSize = alsaApi->snd_pcm_format_mask_sizeof();
21766 snd_pcm_format_mask_t *formatMask = (snd_pcm_format_mask_t *)fpl__AllocateTemporaryMemory(formatMaskSize, 8);
21768 alsaApi->snd_pcm_hw_params_get_format_mask(hardwareParams, formatMask);
21770 snd_pcm_format_t foundFormat;
21771 snd_pcm_format_t preferredFormat = fpl__MapAudioFormatToAlsaFormat(targetFormat->
type);
21772 if (!alsaApi->snd_pcm_format_mask_test(formatMask, preferredFormat)) {
21775 snd_pcm_format_t defaultFormats[] = {
21776 isBigEndian ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE,
21777 isBigEndian ? SND_PCM_FORMAT_FLOAT_BE : SND_PCM_FORMAT_FLOAT_LE,
21778 isBigEndian ? SND_PCM_FORMAT_S32_BE : SND_PCM_FORMAT_S32_LE,
21779 isBigEndian ? SND_PCM_FORMAT_S24_3BE : SND_PCM_FORMAT_S24_3LE,
21782 foundFormat = SND_PCM_FORMAT_UNKNOWN;
21783 for (
size_t defaultFormatIndex = 0; defaultFormatIndex <
fplArrayCount(defaultFormats); ++defaultFormatIndex) {
21784 snd_pcm_format_t defaultFormat = defaultFormats[defaultFormatIndex];
21785 if (alsaApi->snd_pcm_format_mask_test(formatMask, defaultFormat)) {
21786 foundFormat = defaultFormat;
21791 foundFormat = preferredFormat;
21794 fpl__ReleaseTemporaryMemory(formatMask);
21796 if (foundFormat == SND_PCM_FORMAT_UNKNOWN) {
21800 if (alsaApi->snd_pcm_hw_params_set_format(alsaState->pcmDevice, hardwareParams, foundFormat) < 0) {
21803 internalFormat.
type = fpl__MapAlsaFormatToAudioFormat(foundFormat);
21808 unsigned int internalChannels = targetFormat->
channels;
21809 if (alsaApi->snd_pcm_hw_params_set_channels_near(alsaState->pcmDevice, hardwareParams, &internalChannels) < 0) {
21810 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed setting PCM channels '%lu' for device '%s'!", internalChannels, deviceName);
21812 internalFormat.
channels = internalChannels;
21819 alsaApi->snd_pcm_hw_params_set_rate_resample(alsaState->pcmDevice, hardwareParams, 0);
21820 unsigned int actualSampleRate = targetFormat->
sampleRate;
21822 if (alsaApi->snd_pcm_hw_params_set_rate_near(alsaState->pcmDevice, hardwareParams, &actualSampleRate, 0) < 0) {
21823 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed setting PCM sample rate '%lu' for device '%s'!", actualSampleRate, deviceName);
21825 internalFormat.
sampleRate = actualSampleRate;
21830 snd_pcm_uframes_t actualBufferSize;
21832 actualBufferSize = fpl__AlsaScaleBufferSize(targetFormat->
bufferSizeInFrames, bufferSizeScaleFactor);
21837 if (alsaApi->snd_pcm_hw_params_set_buffer_size_near(alsaState->pcmDevice, hardwareParams, &actualBufferSize) < 0) {
21838 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed setting PCM buffer size '%lu' for device '%s'!", actualBufferSize, deviceName);
21847 uint32_t internalPeriods = targetFormat->
periods;
21848 int periodsDir = 0;
21849 if (alsaApi->snd_pcm_hw_params_set_periods_near(alsaState->pcmDevice, hardwareParams, &internalPeriods, &periodsDir) < 0) {
21850 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed setting PCM periods '%lu' for device '%s'!", internalPeriods, deviceName);
21852 internalFormat.
periods = internalPeriods;
21857 if (alsaApi->snd_pcm_hw_params(alsaState->pcmDevice, hardwareParams) < 0) {
21858 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed to install PCM hardware parameters for device '%s'!", deviceName);
21862 commonAudio->internalFormat = internalFormat;
21867 size_t softwareParamsSize = alsaApi->snd_pcm_sw_params_sizeof();
21868 softwareParams = (snd_pcm_sw_params_t *)fpl__AllocateTemporaryMemory(softwareParamsSize, 8);
21870 if (alsaApi->snd_pcm_sw_params_current(alsaState->pcmDevice, softwareParams) < 0) {
21873 snd_pcm_uframes_t minAvailableFrames = fpl__PrevPowerOfTwo(internalFormat.
bufferSizeInFrames / internalFormat.
periods);
21874 if (alsaApi->snd_pcm_sw_params_set_avail_min(alsaState->pcmDevice, softwareParams, minAvailableFrames) < 0) {
21875 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed to set software available min frames of '%lu' for device '%s'!", minAvailableFrames, deviceName);
21877 if (!alsaState->isUsingMMap) {
21879 if (alsaApi->snd_pcm_sw_params_set_start_threshold(alsaState->pcmDevice, softwareParams, threshold) < 0) {
21880 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed to set start threshold of '%lu' for device '%s'!", threshold, deviceName);
21883 if (alsaApi->snd_pcm_sw_params(alsaState->pcmDevice, softwareParams) < 0) {
21884 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed to install PCM software parameters for device '%s'!", deviceName);
21887 if (!alsaState->isUsingMMap) {
21889 alsaState->intermediaryBuffer = fpl__AllocateDynamicMemory(bufferSizeInBytes, 16);
21890 if (alsaState->intermediaryBuffer ==
fpl_null) {
21891 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed allocating intermediary buffer of size '%lu' for device '%s'!", bufferSizeInBytes, deviceName);
21898#undef FPL__ALSA_INIT_ERROR
21900 fpl__ReleaseTemporaryMemory(softwareParams);
21901 fpl__ReleaseTemporaryMemory(hardwareParams);
21908 const fpl__AlsaAudioApi *alsaApi = &alsaState->api;
21909 char **ppDeviceHints;
21910 if (alsaApi->snd_device_name_hint(-1,
"pcm", (
void ***)&ppDeviceHints) < 0) {
21913 uint32_t capacityOverflow = 0;
21914 uint32_t result = 0;
21915 char **ppNextDeviceHint = ppDeviceHints;
21916 while (*ppNextDeviceHint !=
fpl_null) {
21917 char *name = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"NAME");
21918 char *ioid = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"IOID");
21923 if (result >= maxDeviceCount) {
21924 ++capacityOverflow;
21929 char *desc = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"DESC");
21948 ++ppNextDeviceHint;
21950 alsaApi->snd_device_name_free_hint((
void **)ppDeviceHints);
21951 if (capacityOverflow > 0) {
21952 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Capacity of '%lu' for audio device infos has been reached. '%lu' audio devices are not included in the result", maxDeviceCount, capacityOverflow);
21969#if defined(FPL__ENABLE_AUDIO)
21971#define FPL__AUDIO_RESULT_TYPE_COUNT FPL__ENUM_COUNT(fplAudioResultType_First, fplAudioResultType_Last)
21972fpl_globalvar const char *fpl__global_audioResultTypeNameTable[] = {
21975 "Audio-Device not initialized",
21976 "Audio-Device already stopped",
21977 "Audio-Device already started",
21978 "Audio-Device is busy",
21979 "No Audio-Device found",
21981 "Platform not initialized",
21982 "Backend already initialized",
21983 "Audio format was not set",
21984 "Number of audio channels was not set",
21985 "Audio sample rate was not set",
21986 "Audio buffer sizes was not set",
21987 "Unknown audio failure",
21993 const char *result = fpl__global_audioResultTypeNameTable[index];
21997typedef struct fpl__AudioEvent {
22000 volatile int32_t signaled;
22003fpl_internal bool fpl__InitAudioEvent(fpl__AudioEvent *ev) {
22015fpl_internal void fpl__ReleaseAudioEvent(fpl__AudioEvent *ev) {
22020fpl_internal void fpl__WaitForAudioEvent(fpl__AudioEvent *ev) {
22022 while (!ev->signaled) {
22029fpl_internal void fpl__SetAudioEvent(fpl__AudioEvent *ev) {
22036typedef struct fpl__AudioState {
22037 fpl__CommonAudioState common;
22041 fpl__AudioEvent startEvent;
22042 fpl__AudioEvent stopEvent;
22043 fpl__AudioEvent wakeupEvent;
22047 bool isAsyncBackend;
22050# if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
22051 fpl__DirectSoundAudioState dsound;
22053# if defined(FPL__ENABLE_AUDIO_ALSA)
22054 fpl__AlsaAudioState alsa;
22059fpl_internal fpl__AudioState *fpl__GetAudioState(fpl__PlatformAppState *appState) {
22061 fpl__AudioState *result =
fpl_null;
22062 if (appState->audio.mem !=
fpl_null) {
22063 result = (fpl__AudioState *)appState->audio.mem;
22068fpl_internal void fpl__StopAudioDeviceMainLoop(fpl__AudioState *audioState) {
22070 switch (audioState->backendType) {
22072# if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
22075 fpl__AudioStopMainLoopDirectSound(&audioState->dsound);
22079# if defined(FPL__ENABLE_AUDIO_ALSA)
22082 fpl__AudioStopMainLoopAlsa(&audioState->alsa);
22091fpl_internal bool fpl__ReleaseAudioDevice(fpl__AudioState *audioState) {
22093 bool result =
false;
22094 switch (audioState->backendType) {
22096# if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
22099 result = fpl__AudioReleaseDirectSound(&audioState->common, &audioState->dsound);
22103# if defined(FPL__ENABLE_AUDIO_ALSA)
22106 result = fpl__AudioReleaseAlsa(&audioState->common, &audioState->alsa);
22116fpl_internal bool fpl__StopAudioDevice(fpl__AudioState *audioState) {
22118 bool result =
false;
22119 switch (audioState->backendType) {
22121# if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
22124 result = fpl__AudioStopDirectSound(&audioState->dsound);
22128# if defined(FPL__ENABLE_AUDIO_ALSA)
22131 result = fpl__AudioStopAlsa(&audioState->alsa);
22144 switch (audioState->backendType) {
22146# if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
22149 result = fpl__AudioStartDirectSound(&audioState->common, &audioState->dsound);
22153# if defined(FPL__ENABLE_AUDIO_ALSA)
22156 result = fpl__AudioStartAlsa(&audioState->common, &audioState->alsa);
22166fpl_internal void fpl__RunAudioDeviceMainLoop(fpl__AudioState *audioState) {
22168 switch (audioState->backendType) {
22170# if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
22173 fpl__AudioRunMainLoopDirectSound(&audioState->common, &audioState->dsound);
22177# if defined(FPL__ENABLE_AUDIO_ALSA)
22180 fpl__AudioRunMainLoopAlsa(&audioState->common, &audioState->alsa);
22190 switch (backendType) {
22199fpl_internal void fpl__AudioSetDeviceState(fpl__CommonAudioState *audioState, fpl__AudioDeviceState newState) {
22200 fplAtomicStoreU32((
volatile uint32_t *)&audioState->state, (uint32_t)newState);
22203fpl_internal fpl__AudioDeviceState fpl__AudioGetDeviceState(fpl__CommonAudioState *audioState) {
22204 fpl__AudioDeviceState result = (fpl__AudioDeviceState)
fplAtomicLoadU32((
volatile uint32_t *)&audioState->state);
22208fpl_internal bool fpl__IsAudioDeviceInitialized(fpl__CommonAudioState *audioState) {
22212 fpl__AudioDeviceState state = fpl__AudioGetDeviceState(audioState);
22213 return(state != fpl__AudioDeviceState_Uninitialized);
22216fpl_internal bool fpl__IsAudioDeviceStarted(fpl__CommonAudioState *audioState) {
22220 fpl__AudioDeviceState state = fpl__AudioGetDeviceState(audioState);
22221 return(state == fpl__AudioDeviceState_Started);
22225#if defined(FPL_PLATFORM_WINDOWS)
22227 const fpl__Win32Api *wapi = &fpl__global__AppState->win32.winApi;
22230 fpl__AudioState *audioState = (fpl__AudioState *)data;
22231 fpl__CommonAudioState *commonAudioState = &audioState->common;
22235#if defined(FPL_PLATFORM_WINDOWS)
22236 wapi->ole.CoInitializeEx(
fpl_null, 0);
22241 fpl__StopAudioDevice(audioState);
22244 fpl__AudioSetDeviceState(commonAudioState, fpl__AudioDeviceState_Stopped);
22245 fpl__SetAudioEvent(&audioState->stopEvent);
22248 fpl__WaitForAudioEvent(&audioState->wakeupEvent);
22254 if (fpl__AudioGetDeviceState(commonAudioState) == fpl__AudioDeviceState_Uninitialized) {
22259 fplAssert(fpl__AudioGetDeviceState(commonAudioState) == fpl__AudioDeviceState_Starting);
22262 audioState->workResult = fpl__StartAudioDevice(audioState);
22264 fpl__SetAudioEvent(&audioState->startEvent);
22269 fpl__AudioSetDeviceState(commonAudioState, fpl__AudioDeviceState_Started);
22270 fpl__SetAudioEvent(&audioState->startEvent);
22273 fpl__RunAudioDeviceMainLoop(audioState);
22277 fpl__SetAudioEvent(&audioState->stopEvent);
22279#if defined(FPL_PLATFORM_WINDOWS)
22280 wapi->ole.CoUninitialize();
22284fpl_internal void fpl__ReleaseAudio(fpl__AudioState *audioState) {
22287#if defined(FPL_PLATFORM_WINDOWS)
22289 const fpl__Win32Api *wapi = &fpl__global__AppState->win32.winApi;
22292 fpl__CommonAudioState *commonAudioState = &audioState->common;
22294 if (fpl__IsAudioDeviceInitialized(commonAudioState)) {
22297 if (fpl__IsAudioDeviceStarted(commonAudioState)) {
22304 fpl__AudioSetDeviceState(commonAudioState, fpl__AudioDeviceState_Uninitialized);
22307 fpl__SetAudioEvent(&audioState->wakeupEvent);
22313 fpl__ReleaseAudioEvent(&audioState->stopEvent);
22314 fpl__ReleaseAudioEvent(&audioState->startEvent);
22315 fpl__ReleaseAudioEvent(&audioState->wakeupEvent);
22319 fpl__ReleaseAudioDevice(audioState);
22325#if defined(FPL_PLATFORM_WINDOWS)
22326 wapi->ole.CoUninitialize();
22333#if defined(FPL_PLATFORM_WINDOWS)
22335 const fpl__Win32Api *wapi = &fpl__global__AppState->win32.winApi;
22339 fpl__ReleaseAudio(audioState);
22347 audioState->common.clientUserData = audioSettings->
userData;
22349#if defined(FPL_PLATFORM_WINDOWS)
22350 wapi->ole.CoInitializeEx(
fpl_null, 0);
22355 fpl__ReleaseAudio(audioState);
22358 if (!fpl__InitAudioEvent(&audioState->wakeupEvent)) {
22359 fpl__ReleaseAudio(audioState);
22362 if (!fpl__InitAudioEvent(&audioState->startEvent)) {
22363 fpl__ReleaseAudio(audioState);
22366 if (!fpl__InitAudioEvent(&audioState->stopEvent)) {
22367 fpl__ReleaseAudio(audioState);
22373 uint32_t backendCount = 0;
22380 propeBackendTypes[backendCount++] = audioSettings->
backend;
22383 for (uint32_t backendIndex = 0; backendIndex < backendCount; ++backendIndex) {
22387 switch (propeBackendType) {
22388# if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
22391 initResult = fpl__AudioInitDirectSound(audioSettings, &actualTargetFormat, &audioState->common, &audioState->dsound);
22393 fpl__AudioReleaseDirectSound(&audioState->common, &audioState->dsound);
22398# if defined(FPL__ENABLE_AUDIO_ALSA)
22401 initResult = fpl__AudioInitAlsa(audioSettings, &actualTargetFormat, &audioState->common, &audioState->alsa);
22403 fpl__AudioReleaseAlsa(&audioState->common, &audioState->alsa);
22412 audioState->backendType = propeBackendType;
22413 audioState->isAsyncBackend = fpl__IsAudioBackendAsync(propeBackendType);
22419 fpl__ReleaseAudio(audioState);
22423 if (!audioState->isAsyncBackend) {
22427 audioThreadParams.
runFunc = fpl__AudioWorkerThread;
22428 audioThreadParams.
userData = audioState;
22430 if (audioState->workerThread ==
fpl_null) {
22431 fpl__ReleaseAudio(audioState);
22437 fpl__WaitForAudioEvent(&audioState->stopEvent);
22439 fpl__AudioSetDeviceState(&audioState->common, fpl__AudioDeviceState_Stopped);
22442 fplAssert(fpl__AudioGetDeviceState(&audioState->common) == fpl__AudioDeviceState_Stopped);
22456#if defined(FPL__ENABLE_VIDEO)
22458typedef union fpl__ActiveVideoBackend {
22459 fpl__VideoBackend base;
22461#if defined(FPL_PLATFORM_WINDOWS)
22462# if defined(FPL__ENABLE_VIDEO_OPENGL)
22463 fpl__VideoBackendWin32OpenGL win32_opengl;
22465# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
22466 fpl__VideoBackendWin32Software win32_software;
22470#if defined(FPL_SUBPLATFORM_X11)
22471# if defined(FPL__ENABLE_VIDEO_OPENGL)
22472 fpl__VideoBackendX11OpenGL x11_opengl;
22474# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
22475 fpl__VideoBackendX11Software x11_software;
22479#if defined(FPL__ENABLE_VIDEO_VULKAN)
22480 fpl__VideoBackendVulkan vulkan;
22483} fpl__ActiveVideoBackend;
22485typedef struct fpl__VideoState {
22486 fpl__VideoContext context;
22487 fpl__VideoData data;
22489 fpl__ActiveVideoBackend activeBackend;
22492fpl_internal fpl__VideoState *fpl__GetVideoState(fpl__PlatformAppState *appState) {
22494 fpl__VideoState *result =
fpl_null;
22495 if (appState->video.mem !=
fpl_null) {
22496 result = (fpl__VideoState *)appState->video.mem;
22501fpl_internal void fpl__DestroySurfaceBackend(fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
22502 const fpl__VideoContext *ctx = &videoState->context;
22504 ctx->destroyedWindowFunc(appState, &videoState->activeBackend.base);
22507fpl_internal void fpl__UnloadVideoBackend(fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
22508 const fpl__VideoContext *ctx = &videoState->context;
22510 ctx->unloadFunc(appState, &videoState->activeBackend.base);
22514fpl_internal bool fpl__LoadVideoBackend(fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
22515 const fpl__VideoContext *ctx = &videoState->context;
22517 bool result = ctx->loadFunc(appState, &videoState->activeBackend.base);
22521fpl_internal void fpl__ShutdownVideoBackend(fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
22524 const fpl__VideoContext *ctx = &videoState->context;
22526 ctx->shutdownFunc(appState, &appState->window, &videoState->activeBackend.base);
22528# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
22531 fpl__ReleaseDynamicMemory(backbuffer->
pixels);
22538fpl_internal bool fpl__InitializeVideoBackend(
const fplVideoBackendType backendType,
const fplVideoSettings *videoSettings,
const uint32_t windowWidth,
const uint32_t windowHeight, fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
22543 const fpl__VideoContext *ctx = &videoState->context;
22546# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
22549 backbuffer->
width = windowWidth;
22550 backbuffer->
height = windowHeight;
22554 backbuffer->
pixels = (uint32_t *)fpl__AllocateDynamicMemory(size, 4);
22556 FPL__ERROR(FPL__MODULE_VIDEO_SOFTWARE,
"Failed allocating video software backbuffer of size %xu bytes", size);
22557 fpl__ShutdownVideoBackend(appState, videoState);
22563 uint32_t *p = backbuffer->
pixels;
22564 uint32_t color = appState->initSettings.window.background.value == 0 ? 0xFF000000 : appState->initSettings.window.background.value;
22565 for (uint32_t y = 0; y < backbuffer->
height; ++y) {
22566 for (uint32_t x = 0; x < backbuffer->
width; ++x) {
22574 bool videoInitResult = ctx->initializeFunc(appState, &appState->window, videoSettings, &videoState->data, &videoState->activeBackend.base);
22575 if (!videoInitResult) {
22577 fpl__ShutdownVideoBackend(appState, videoState);
22585 switch (backendType) {
22586#if defined(FPL__ENABLE_VIDEO_OPENGL)
22589# if defined(FPL_PLATFORM_WINDOWS)
22590 return fpl__VideoBackend_Win32OpenGL_Construct();
22591# elif defined(FPL_SUBPLATFORM_X11)
22592 return fpl__VideoBackend_X11OpenGL_Construct();
22597#if defined(FPL__ENABLE_VIDEO_VULKAN)
22600 return fpl__VideoBackend_Vulkan_Construct();
22604#if defined(FPL__ENABLE_VIDEO_SOFTWARE)
22607# if defined(FPL_PLATFORM_WINDOWS)
22608 return fpl__VideoBackend_Win32Software_Construct();
22609# elif defined(FPL_SUBPLATFORM_X11)
22610 return fpl__VideoBackend_X11Software_Construct();
22618 FPL__ERROR(FPL__MODULE_VIDEO,
"The video backend '%s' is not supported for this platform",
fplGetVideoBackendName(backendType));
22619 return(fpl__StubVideoContext());
22633#if defined(FPL__ENABLE_WINDOW)
22634fpl_internal FPL__FUNC_PREPARE_VIDEO_WINDOW(fpl__PrepareVideoWindowDefault) {
22637# if defined(FPL__ENABLE_VIDEO)
22639 fpl__VideoState *videoState = fpl__GetVideoState(appState);
22640 if (videoState->context.prepareWindowFunc !=
fpl_null) {
22641 bool result = videoState->context.prepareWindowFunc(appState, &initSettings->
video, &appState->window, &videoState->activeBackend.base);
22650fpl_internal FPL__FUNC_FINALIZE_VIDEO_WINDOW(fpl__FinalizeVideoWindowDefault) {
22653#if defined(FPL__ENABLE_VIDEO)
22655 fpl__VideoState *videoState = fpl__GetVideoState(appState);
22656 if (videoState->context.finalizeWindowFunc !=
fpl_null) {
22657 bool result = videoState->context.finalizeWindowFunc(appState, &initSettings->
video, &appState->window, &videoState->activeBackend.base);
22666fpl_internal void fpl__ReleaseWindow(
const fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
22668# if defined(FPL_PLATFORM_WINDOWS)
22669 fpl__Win32ReleaseWindow(&initState->win32, &appState->win32, &appState->window.win32);
22670# elif defined(FPL_SUBPLATFORM_X11)
22671 fpl__X11ReleaseWindow(&appState->x11, &appState->window.x11);
22677 bool result =
false;
22679# if defined(FPL_PLATFORM_WINDOWS)
22680 result = fpl__Win32InitWindow(initSettings, currentWindowSettings, appState, &appState->win32, &appState->window.win32, setupCallbacks);
22681# elif defined(FPL_SUBPLATFORM_X11)
22682 result = fpl__X11InitWindow(initSettings, currentWindowSettings, appState, &appState->x11, &appState->window.x11, setupCallbacks);
22697#if defined(FPL__ENABLE_AUDIO)
22699#define FPL__AUDIOFORMATTYPE_COUNT FPL__ENUM_COUNT(fplAudioFormatType_First, fplAudioFormatType_Last)
22701fpl_globalvar uint32_t fpl__globalAudioFormatSampleSizeTable[] = {
22713fpl_globalvar const char *fpl__globalAudioFormatNameTable[] = {
22727 uint32_t result = fpl__globalAudioFormatSampleSizeTable[index];
22733 const char *result = fpl__globalAudioFormatNameTable[index];
22737#define FPL__AUDIOBACKENDTYPE_COUNT FPL__ENUM_COUNT(fplAudioBackendType_First, fplAudioBackendType_Last)
22738fpl_globalvar const char *fpl__globalAudioBackendNameTable[] = {
22748 const fpl__PlatformAppState *appState = fpl__global__AppState;
22755 const char *result = fpl__globalAudioBackendNameTable[index];
22760 if (sampleRate == 0 || bufferSizeInMilliSeconds == 0)
return(0);
22761 uint32_t result = bufferSizeInMilliSeconds * sampleRate / 1000UL;
22766 if (sampleRate == 0 || frameCount == 0)
return(0);
22767 uint32_t result = frameCount * 1000UL / sampleRate;
22772 if (channelCount == 0)
return(0);
22778 if (channelCount == 0 || frameCount == 0)
return(0);
22780 uint32_t result = frameSize * frameCount;
22785 FPL__CheckArgumentNullNoRet(inFormat);
22786 FPL__CheckArgumentNullNoRet(outFormat);
22794 outFormat->
channels = FPL__DEFAULT_AUDIO_CHANNELS;
22802 outFormat->
sampleRate = FPL__DEFAULT_AUDIO_SAMPLERATE;
22810 outFormat->
type = FPL__DEFAULT_AUDIO_FORMAT;
22815 if (outFormat->
periods > 0) {
22818 outFormat->
periods = FPL__DEFAULT_AUDIO_PERIODS;
22839 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
22844 fpl__CommonAudioState *commonAudioState = &audioState->common;
22846 if (!fpl__IsAudioDeviceInitialized(commonAudioState)) {
22850 fpl__AudioDeviceState firstDeviceState = fpl__AudioGetDeviceState(commonAudioState);
22851 if (firstDeviceState == fpl__AudioDeviceState_Stopped) {
22859 if (fpl__AudioGetDeviceState(commonAudioState) == fpl__AudioDeviceState_Stopping) {
22863 if (fpl__AudioGetDeviceState(commonAudioState) == fpl__AudioDeviceState_Stopped) {
22869 if (fpl__AudioGetDeviceState(commonAudioState) != fpl__AudioDeviceState_Started) {
22874 fpl__AudioSetDeviceState(commonAudioState, fpl__AudioDeviceState_Stopping);
22876 if (audioState->isAsyncBackend) {
22878 fpl__StopAudioDevice(audioState);
22883 fpl__StopAudioDeviceMainLoop(audioState);
22887 fpl__WaitForAudioEvent(&audioState->stopEvent);
22898 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
22903 fpl__CommonAudioState *commonAudioState = &audioState->common;
22905 if (!fpl__IsAudioDeviceInitialized(commonAudioState)) {
22909 if (fpl__AudioGetDeviceState(commonAudioState) == fpl__AudioDeviceState_Started) {
22917 if (fpl__AudioGetDeviceState(commonAudioState) == fpl__AudioDeviceState_Starting) {
22921 if (fpl__AudioGetDeviceState(commonAudioState) == fpl__AudioDeviceState_Started) {
22927 if (fpl__AudioGetDeviceState(commonAudioState) != fpl__AudioDeviceState_Stopped) {
22932 fpl__AudioSetDeviceState(commonAudioState, fpl__AudioDeviceState_Starting);
22934 if (audioState->isAsyncBackend) {
22936 fpl__StartAudioDevice(audioState);
22937 fpl__AudioSetDeviceState(commonAudioState, fpl__AudioDeviceState_Started);
22940 fpl__SetAudioEvent(&audioState->wakeupEvent);
22944 fpl__WaitForAudioEvent(&audioState->startEvent);
22945 result = audioState->workResult;
22954 FPL__CheckArgumentNull(outFormat,
false);
22955 FPL__CheckPlatform(
false);
22956 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
22959 *outFormat = audioState->common.internalFormat;
22966 FPL__CheckPlatform(
false);
22967 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
22969 if (fpl__AudioGetDeviceState(&audioState->common) == fpl__AudioDeviceState_Stopped) {
22970 audioState->common.clientReadCallback = newCallback;
22971 audioState->common.clientUserData = userData;
22980 FPL__CheckArgumentZero(maxDeviceCount, 0);
22982 FPL__CheckPlatform(0);
22983 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
22987 uint32_t result = 0;
22989 switch (audioState->backendType) {
22990# if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
22993 result = fpl__GetAudioDevicesDirectSound(&audioState->dsound, devices, maxDeviceCount);
22997# if defined(FPL__ENABLE_AUDIO_ALSA)
23000 result = fpl__GetAudioDevicesAlsa(&audioState->alsa, devices, maxDeviceCount);
23021#if defined(FPL__ENABLE_VIDEO)
23022#define FPL__VIDEOBACKENDTYPE_COUNT FPL__ENUM_COUNT(fplVideoBackendType_First, fplVideoBackendType_Last)
23023fpl_globalvar const char *fpl__globalVideoBackendNameTable[FPL__VIDEOBACKENDTYPE_COUNT] = {
23032 const char *result = fpl__globalVideoBackendNameTable[index];
23038 fpl__PlatformAppState *appState = fpl__global__AppState;
23039 fpl__VideoState *videoState = fpl__GetVideoState(appState);
23041 return(videoState->backendType);
23048 fpl__PlatformAppState *appState = fpl__global__AppState;
23049 fpl__VideoState *videoState = fpl__GetVideoState(appState);
23052#if defined(FPL__ENABLE_VIDEO_SOFTWARE)
23054 result = &videoState->data.backbuffer;
23062 FPL__CheckPlatform(
false);
23063 fpl__PlatformAppState *appState = fpl__global__AppState;
23064 fpl__VideoState *videoState = fpl__GetVideoState(appState);
23065 bool result =
false;
23069 fpl__ShutdownVideoBackend(appState, videoState);
23070 result = fpl__InitializeVideoBackend(videoState->backendType, &appState->currentSettings.video, width, height, appState, videoState);
23077 FPL__CheckPlatformNoRet();
23078 fpl__PlatformAppState *appState = fpl__global__AppState;
23079 const fpl__VideoState *videoState = fpl__GetVideoState(appState);
23082 videoState->context.presentFunc(appState, &appState->window, &videoState->data, &videoState->activeBackend.base);
23088 fpl__PlatformAppState *appState = fpl__global__AppState;
23089 const fpl__VideoState *videoState = fpl__GetVideoState(appState);
23093 result = videoState->context.getProcedureFunc(&videoState->activeBackend.base, procName);
23100 fpl__PlatformAppState *appState = fpl__global__AppState;
23101 const fpl__VideoState *videoState = fpl__GetVideoState(appState);
23104 result = &videoState->activeBackend.base.surface;
23110 fpl__VideoContext context = fpl__ConstructVideoContext(backendType);
23111 bool result =
false;
23112 if (context.getRequirementsFunc !=
fpl_null) {
23113 result = context.getRequirementsFunc(requirements);
23124#if !defined(FPL__SYSTEM_INIT_DEFINED)
23125#define FPL__SYSTEM_INIT_DEFINED
23127fpl_internal void fpl__ReleasePlatformStates(fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
23131# if defined(FPL__ENABLE_AUDIO)
23134 if (appState->currentSettings.audio.stopAuto) {
23135 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
23137 fpl__CommonAudioState *commonAudioState = &audioState->common;
23138 fpl__AudioDeviceState deviceState = fpl__AudioGetDeviceState(commonAudioState);
23139 if (deviceState != fpl__AudioDeviceState_Stopped) {
23140 FPL_LOG_DEBUG(
"Core",
"Stop Audio (Auto)");
23146 FPL_LOG_DEBUG(
"Core",
"Release Audio");
23147 fpl__AudioState *audioState = fpl__GetAudioState(appState);
23149 fpl__ReleaseAudio(audioState);
23155# if defined(FPL__ENABLE_VIDEO)
23157 fpl__VideoState *videoState = fpl__GetVideoState(appState);
23159 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Shutdown Video Backend '%s'",
fplGetVideoBackendName(videoState->backendType));
23160 fpl__ShutdownVideoBackend(appState, videoState);
23166# if defined(FPL__ENABLE_WINDOW)
23168 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Window");
23169 fpl__ReleaseWindow(initState, appState);
23170 fpl__ClearInternalEvents();
23175# if defined(FPL__ENABLE_VIDEO)
23177 fpl__VideoState *videoState = fpl__GetVideoState(appState);
23179 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Destroy surface for Video Backend '%s'",
fplGetVideoBackendName(videoState->backendType));
23180 fpl__DestroySurfaceBackend(appState, videoState);
23182 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Video Backend '%s'",
fplGetVideoBackendName(videoState->backendType));
23183 fpl__UnloadVideoBackend(appState, videoState);
23191# if defined(FPL_PLATFORM_WINDOWS)
23192 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Win32 Platform");
23193 fpl__Win32ReleasePlatform(initState, appState);
23194# elif defined(FPL_PLATFORM_LINUX)
23195 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Linux Platform");
23196 fpl__LinuxReleasePlatform(initState, appState);
23197# elif defined(FPL_PLATFORM_UNIX)
23198 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Unix Platform");
23199 fpl__UnixReleasePlatform(initState, appState);
23205# if defined(FPL_SUBPLATFORM_X11)
23206 FPL_LOG_DEBUG(
"Core",
"Release X11 Subplatform");
23207 fpl__X11ReleaseSubplatform(&appState->x11);
23209# if defined(FPL_SUBPLATFORM_POSIX)
23210 FPL_LOG_DEBUG(
"Core",
"Release POSIX Subplatform");
23211 fpl__PosixReleaseSubplatform(&appState->posix);
23216 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release allocated Platform App State Memory");
23224#define FPL__PLATFORMTYPE_COUNT FPL__ENUM_COUNT(fplPlatformType_First, fplPlatformType_Last)
23225fpl_globalvar const char *fpl__globalPlatformTypeNameTable[] = {
23234 fpl__PlatformInitState *initState = &fpl__global__InitState;
23235 bool result = initState->isInitialized;
23241 const char *result = fpl__globalPlatformTypeNameTable[index];
23246 fpl__PlatformInitState *initState = &fpl__global__InitState;
23247 return(initState->initResult);
23251 fpl__PlatformInitState *initState = &fpl__global__InitState;
23252 initState->initResult = resultType;
23258 fpl__PlatformInitState *initState = &fpl__global__InitState;
23259 if (!initState->isInitialized) {
23260 FPL__CRITICAL(FPL__MODULE_CORE,
"Platform is not initialized");
23263 fpl__PlatformAppState *appState = fpl__global__AppState;
23264 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Platform");
23265 fpl__ReleasePlatformStates(initState, appState);
23266 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Platform released");
23271 if (fpl__global__InitState.isInitialized) {
23272 FPL__CRITICAL(FPL__MODULE_CORE,
"Platform is already initialized");
23276 fpl__PlatformInitState *initState = &fpl__global__InitState;
23285 size_t platformAppStateSize =
fplGetAlignedSize(
sizeof(fpl__PlatformAppState), 16);
23288#if defined(FPL__ENABLE_VIDEO)
23289 size_t videoMemoryOffset = 0;
23291 platformAppStateSize += FPL__ARBITARY_PADDING;
23292 videoMemoryOffset = platformAppStateSize;
23293 platformAppStateSize +=
sizeof(fpl__VideoState);
23297#if defined(FPL__ENABLE_AUDIO)
23298 size_t audioMemoryOffset = 0;
23300 platformAppStateSize += FPL__ARBITARY_PADDING;
23301 audioMemoryOffset = platformAppStateSize;
23302 platformAppStateSize +=
sizeof(fpl__AudioState);
23306 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Allocate Platform App State Memory of size '%zu':", platformAppStateSize);
23309 if (platformAppStateMemory ==
fpl_null) {
23310 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed Allocating Platform App State Memory of size '%zu'", platformAppStateSize);
23314 fpl__PlatformAppState *appState = fpl__global__AppState = (fpl__PlatformAppState *)platformAppStateMemory;
23315 appState->initFlags = initFlags;
23317 appState->initSettings = *initSettings;
23321 appState->currentSettings = appState->initSettings;
23323 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully allocated Platform App State Memory of size '%zu'", platformAppStateSize);
23326# if defined(FPL_APPTYPE_WINDOW)
23328# elif defined(FPL_APPTYPE_CONSOLE)
23333# if defined(FPL__ENABLE_VIDEO)
23342# if !defined(FPL__ENABLE_WINDOW)
23347# if defined(FPL_SUBPLATFORM_POSIX)
23349 FPL_LOG_DEBUG(
"Core",
"Initialize POSIX Subplatform:");
23350 if (!fpl__PosixInitSubplatform(initFlags, initSettings, &initState->posix, &appState->posix)) {
23351 FPL__CRITICAL(
"Core",
"Failed initializing POSIX Subplatform!");
23352 fpl__ReleasePlatformStates(initState, appState);
23355 FPL_LOG_DEBUG(
"Core",
"Successfully initialized POSIX Subplatform");
23359# if defined(FPL_SUBPLATFORM_X11)
23361 FPL_LOG_DEBUG(
"Core",
"Initialize X11 Subplatform:");
23362 if (!fpl__X11InitSubplatform(&appState->x11)) {
23363 FPL__CRITICAL(
"Core",
"Failed initializing X11 Subplatform!");
23364 fpl__ReleasePlatformStates(initState, appState);
23367 FPL_LOG_DEBUG(
"Core",
"Successfully initialized X11 Subplatform");
23372 bool isInitialized =
false;
23373 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Initialize %s Platform:", FPL_PLATFORM_NAME);
23374# if defined(FPL_PLATFORM_WINDOWS)
23375 isInitialized = fpl__Win32InitPlatform(appState->initFlags, &appState->initSettings, initState, appState);
23376# elif defined(FPL_PLATFORM_LINUX)
23377 isInitialized = fpl__LinuxInitPlatform(appState->initFlags, &appState->initSettings, initState, appState);
23378# elif defined(FPL_PLATFORM_UNIX)
23379 isInitialized = fpl__UnixInitPlatform(appState->initFlags, &appState->initSettings, initState, appState);
23382 if (!isInitialized) {
23383 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed initializing %s Platform!", FPL_PLATFORM_NAME);
23384 fpl__ReleasePlatformStates(initState, appState);
23387 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully initialized %s Platform", FPL_PLATFORM_NAME);
23390# if defined(FPL__ENABLE_VIDEO)
23392 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Init Video State");
23393 appState->video.mem = (uint8_t *)platformAppStateMemory + videoMemoryOffset;
23394 appState->video.memSize =
sizeof(fpl__VideoState);
23395 fpl__VideoState *videoState = fpl__GetVideoState(appState);
23401 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Construct Video Context:");
23402 videoState->context = fpl__ConstructVideoContext(videoBackendType);
23403 videoState->backendType = videoBackendType;
23407 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Load Video API for Backend '%s':", videoBackendName);
23409 if (!fpl__LoadVideoBackend(appState, videoState)) {
23410 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed loading Video API for Backend '%s'!", videoBackendName);
23411 fpl__ReleasePlatformStates(initState, appState);
23415 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully loaded Video API for Backend '%s'", videoBackendName);
23420# if defined(FPL__ENABLE_WINDOW)
23422 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Init Window:");
23423 fpl__SetupWindowCallbacks winCallbacks =
fplZeroInit;
23424 winCallbacks.preSetup = fpl__PrepareVideoWindowDefault;
23425 winCallbacks.postSetup = fpl__FinalizeVideoWindowDefault;
23426 if (!fpl__InitWindow(&appState->initSettings, &appState->currentSettings.window, appState, &winCallbacks)) {
23427 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed initializing Window!");
23428 fpl__ReleasePlatformStates(initState, appState);
23431 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully initialized Window");
23436# if defined(FPL__ENABLE_VIDEO)
23438 fpl__VideoState *videoState = fpl__GetVideoState(appState);
23443 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Init Video with Backend '%s':", videoBackendName);
23444 if (!fpl__InitializeVideoBackend(appState->initSettings.video.backend, &appState->initSettings.video, windowSize.
width, windowSize.
height, appState, videoState)) {
23445 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed initialization Video with Backend '%s' with settings (Width=%d, Height=%d)", videoBackendName, windowSize.
width, windowSize.
height);
23446 fpl__ReleasePlatformStates(initState, appState);
23449 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully initialized Video with Backend '%s'", videoBackendName);
23454# if defined(FPL__ENABLE_AUDIO)
23456 appState->audio.mem = (uint8_t *)platformAppStateMemory + audioMemoryOffset;
23457 appState->audio.memSize =
sizeof(fpl__AudioState);
23459 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Init Audio with Backend '%s':", audioBackendName);
23460 fpl__AudioState *audioState = fpl__GetAudioState(appState);
23462 fplAudioResultType initAudioResult = fpl__InitAudio(&appState->initSettings.audio, audioState);
23464 const char *initAudioResultName = fplGetAudioResultName(initAudioResult);
23466 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed initialization audio with Backend '%s' settings (Format=%s, SampleRate=%d, Channels=%d) -> %s",
23471 initAudioResultName);
23472 fpl__ReleasePlatformStates(initState, appState);
23475 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully initialized Audio with Backend '%s'", audioBackendName);
23478 if (appState->initSettings.audio.startAuto && (appState->initSettings.audio.clientReadCallback !=
fpl_null)) {
23479 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Play Audio (Auto)");
23482 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed auto-play of audio, code: %d!", playResult);
23483 fpl__ReleasePlatformStates(initState, appState);
23490 initState->isInitialized =
true;
23496#if defined(FPL_PLATFORM_WINDOWS)
23498#elif defined(FPL_PLATFORM_LINUX)
23500#elif defined(FPL_PLATFORM_UNIX)
23510#if defined(FPL_COMPILER_MSVC)
23512# pragma warning( pop )
23513#elif defined(FPL_COMPILER_GCC)
23515# pragma GCC diagnostic pop
23516#elif defined(FPL_COMPILER_CLANG)
23518# pragma clang diagnostic pop
23528#if defined(FPL_ENTRYPOINT) && !defined(FPL__ENTRYPOINT_IMPLEMENTED)
23529# define FPL__ENTRYPOINT_IMPLEMENTED
23536#if !defined(FPL__HAS_PLATFORM_INCLUDES)
23537# define FPL__HAS_PLATFORM_INCLUDES
23539# if defined(FPL_PLATFORM_WINDOWS)
23541# if !defined(NOMINMAX)
23545# if !defined(WIN32_LEAN_AND_MEAN)
23546# define WIN32_LEAN_AND_MEAN 1
23550# include <windows.h>
23551# if _WIN32_WINNT < 0x0600
23552# error "Windows Vista or higher required!"
23563# if defined(FPL_PLATFORM_WINDOWS)
23565#define FPL__FUNC_WIN32_CommandLineToArgvW(name) LPWSTR* WINAPI name(LPCWSTR lpCmdLine, int *pNumArgs)
23566typedef FPL__FUNC_WIN32_CommandLineToArgvW(fpl__win32_func_CommandLineToArgvW);
23568typedef struct fpl__Win32CommandLineUTF8Arguments {
23572} fpl__Win32CommandLineUTF8Arguments;
23574fpl_internal fpl__Win32CommandLineUTF8Arguments fpl__Win32ParseWideArguments(LPWSTR cmdLine,
const bool appendExecutable) {
23575 fpl__Win32CommandLineUTF8Arguments args =
fplZeroInit;
23578 HMODULE shellapiLibrary = LoadLibraryA(
"shell32.dll");
23579 if (shellapiLibrary !=
fpl_null) {
23580 fpl__win32_func_CommandLineToArgvW *commandLineToArgvW = (fpl__win32_func_CommandLineToArgvW *)GetProcAddress(shellapiLibrary,
"CommandLineToArgvW");
23581 if (commandLineToArgvW !=
fpl_null) {
23583 int cmdLineLen = lstrlenW(cmdLine);
23584 int executableFilePathArgumentCount = 0;
23585 wchar_t **executableFilePathArgs = NULL;
23586 size_t executableFilePathLen = 0;
23587 if (appendExecutable || (cmdLineLen == 0)) {
23588 executableFilePathArgumentCount = 0;
23589 executableFilePathArgs = commandLineToArgvW(L
"", &executableFilePathArgumentCount);
23590 executableFilePathLen = 0;
23591 for (
int i = 0; i < executableFilePathArgumentCount; ++i) {
23594 executableFilePathLen++;
23596 size_t sourceLen = lstrlenW(executableFilePathArgs[i]);
23597 int destLen = WideCharToMultiByte(CP_UTF8, 0, executableFilePathArgs[i], (
int)sourceLen,
fpl_null, 0,
fpl_null,
fpl_null);
23598 executableFilePathLen += destLen;
23603 int actualArgumentCount = 0;
23605 size_t actualArgumentsLen = 0;
23606 if (cmdLine !=
fpl_null && cmdLineLen > 0) {
23607 actualArgs = commandLineToArgvW(cmdLine, &actualArgumentCount);
23608 for (
int i = 0; i < actualArgumentCount; ++i) {
23609 size_t sourceLen = lstrlenW(actualArgs[i]);
23611 actualArgumentsLen += destLen;
23616 uint32_t totalArgumentCount = 0;
23617 if (executableFilePathArgumentCount > 0) {
23618 totalArgumentCount++;
23620 totalArgumentCount += actualArgumentCount;
23626 size_t totalStringLen = executableFilePathLen + actualArgumentsLen + totalArgumentCount;
23627 size_t singleArgStringSize =
sizeof(char) * (totalStringLen);
23628 size_t arbitaryPadding = 64;
23629 size_t argArraySize =
sizeof(
char **) * totalArgumentCount;
23630 size_t totalArgSize = singleArgStringSize + arbitaryPadding + argArraySize;
23633 args.count = totalArgumentCount;
23635 args.args = (
char **)((uint8_t *)args.mem + singleArgStringSize + arbitaryPadding);
23638 char *destArg = (
char *)args.mem;
23639 int startArgIndex = 0;
23640 if (executableFilePathArgumentCount > 0)
23642 args.args[startArgIndex++] = destArg;
23643 for (
int i = 0; i < executableFilePathArgumentCount; ++i) {
23647 wchar_t *sourceArg = executableFilePathArgs[i];
23648 size_t sourceArgLen = lstrlenW(sourceArg);
23650 WideCharToMultiByte(CP_UTF8, 0, sourceArg, (
int)sourceArgLen, destArg, destArgLen,
fpl_null,
fpl_null);
23651 destArg += destArgLen;
23654 LocalFree(executableFilePathArgs);
23658 if (actualArgumentCount > 0) {
23660 for (
int i = 0; i < actualArgumentCount; ++i) {
23661 args.args[startArgIndex++] = destArg;
23662 wchar_t *sourceArg = actualArgs[i];
23663 size_t sourceArgLen = lstrlenW(sourceArg);
23665 WideCharToMultiByte(CP_UTF8, 0, sourceArg, (
int)sourceArgLen, destArg, destArgLen,
fpl_null,
fpl_null);
23666 destArg += destArgLen;
23669 LocalFree(actualArgs);
23672 FreeLibrary(shellapiLibrary);
23678fpl_internal fpl__Win32CommandLineUTF8Arguments fpl__Win32ParseAnsiArguments(LPSTR cmdLine,
const bool appendExecutable) {
23679 fpl__Win32CommandLineUTF8Arguments result;
23682 int wideDestLen = MultiByteToWideChar(CP_ACP, 0, cmdLine, (
int)ansiSourceLen,
fpl_null, 0);
23684 wchar_t *wideCmdLine = (
wchar_t *)
fplMemoryAllocate(
sizeof(
wchar_t) * (wideDestLen + 1));
23685 MultiByteToWideChar(CP_ACP, 0, cmdLine, (
int)ansiSourceLen, wideCmdLine, wideDestLen);
23686 wideCmdLine[wideDestLen] = 0;
23687 result = fpl__Win32ParseWideArguments(wideCmdLine, appendExecutable);
23690 wchar_t tmp[1] = { 0 };
23691 result = fpl__Win32ParseWideArguments(tmp, appendExecutable);
23696#if !defined(FPL_NO_CRT)
23701 HWND consoleHandle = GetConsoleWindow();
23708 HWND consoleHandle = GetConsoleWindow();
23712 AttachConsole(GetCurrentProcessId());
23715 HANDLE hConOut = CreateFileW(L
"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
23716 HANDLE hConIn = CreateFileW(L
"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
23717 SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
23718 SetStdHandle(STD_ERROR_HANDLE, hConOut);
23719 SetStdHandle(STD_INPUT_HANDLE, hConIn);
23721#if !defined(FPL_NO_CRT)
23723 freopen_s(&dummy,
"CONIN$",
"r", stdin);
23724 freopen_s(&dummy,
"CONOUT$",
"w", stderr);
23725 freopen_s(&dummy,
"CONOUT$",
"w", stdout);
23730# if defined(FPL_NO_CRT)
23734# if defined(FPL_APPTYPE_WINDOW)
23735# if defined(UNICODE)
23736void __stdcall wWinMainCRTStartup(
void) {
23737 fpl__Win32InitConsole();
23738 LPWSTR argsW = GetCommandLineW();
23739 int result = wWinMain(GetModuleHandleW(
fpl_null),
fpl_null, argsW, SW_SHOW);
23740 fpl__Win32FreeConsole();
23741 ExitProcess(result);
23744void __stdcall WinMainCRTStartup(
void) {
23745 fpl__Win32InitConsole();
23746 LPSTR argsA = GetCommandLineA();
23747 int result = WinMain(GetModuleHandleA(
fpl_null),
fpl_null, argsA, SW_SHOW);
23748 fpl__Win32FreeConsole();
23749 ExitProcess(result);
23752# elif defined(FPL_APPTYPE_CONSOLE)
23753void __stdcall mainCRTStartup(
void) {
23754 fpl__Win32InitConsole();
23755 fpl__Win32CommandLineUTF8Arguments args;
23756# if defined(UNICODE)
23757 LPWSTR argsW = GetCommandLineW();
23758 args = fpl__Win32ParseWideArguments(argsW,
false);
23760 LPSTR argsA = GetCommandLineA();
23761 args = fpl__Win32ParseAnsiArguments(argsA,
false);
23763 int result = main(args.count, args.args);
23765 fpl__Win32FreeConsole();
23766 ExitProcess(result);
23769# error "Application type not set!"
23776# if defined(UNICODE)
23777int WINAPI wWinMain(HINSTANCE appInstance, HINSTANCE prevInstance, LPWSTR cmdLine,
int cmdShow) {
23778 fpl__Win32InitConsole();
23779 fpl__Win32CommandLineUTF8Arguments args = fpl__Win32ParseWideArguments(cmdLine,
true);
23780 int result = main(args.count, args.args);
23782 fpl__Win32FreeConsole();
23786int WINAPI WinMain(HINSTANCE appInstance, HINSTANCE prevInstance, LPSTR cmdLine,
int cmdShow) {
23787 fpl__Win32InitConsole();
23788 fpl__Win32CommandLineUTF8Arguments args = fpl__Win32ParseAnsiArguments(cmdLine,
true);
23789 int result = main(args.count, args.args);
23791 fpl__Win32FreeConsole();
23803#if !defined(FPL_NO_UNDEF)
23805# if defined(FPL_SUBPLATFORM_X11)
23819# if defined(FPL_PLATFORM_WINDOWS)
fpl_platform_api int64_t fplAtomicExchangeS64(volatile int64_t *target, const int64_t value)
Replaces a 64-bit signed integer with the given value atomically.
fpl_common_api void * fplAtomicLoadPtr(volatile void **source)
Loads the pointer value atomically and returns the value.
fpl_platform_api uint32_t fplAtomicExchangeU32(volatile uint32_t *target, const uint32_t value)
Replaces a 32-bit unsigned integer with the given value atomically.
fpl_platform_api uint32_t fplAtomicIncrementU32(volatile uint32_t *dest)
Increments the given 32-bit unsigned integer by one atomically.
fpl_platform_api uint64_t fplAtomicExchangeU64(volatile uint64_t *target, const uint64_t value)
Replaces a 64-bit unsigned integer with the given value atomically.
fpl_platform_api bool fplAtomicIsCompareAndSwapU32(volatile uint32_t *dest, const uint32_t comparand, const uint32_t exchange)
Compares a 32-bit unsigned integer with a comparand and swaps it when comparand matches the destinati...
fpl_platform_api uint64_t fplAtomicFetchAndAddU64(volatile uint64_t *value, const uint64_t addend)
Adds a 64-bit unsigned integer to the value by the given addend atomically.
fpl_platform_api uint64_t fplAtomicIncrementU64(volatile uint64_t *dest)
Increments the given 64-bit unsigned integer by one atomically.
fpl_platform_api int64_t fplAtomicIncrementS64(volatile int64_t *dest)
Increments the given 64-bit signed integer by one atomically.
fpl_platform_api void fplAtomicStoreS32(volatile int32_t *dest, const int32_t value)
Overwrites the 32-bit signed value atomically.
fpl_common_api size_t fplAtomicAddAndFetchSize(volatile size_t *dest, const size_t addend)
Adds the addend to destination size atomically and returns the result after the addition.
fpl_platform_api int32_t fplAtomicLoadS32(volatile int32_t *source)
Loads the 32-bit signed value atomically and returns the value.
fpl_common_api void * fplAtomicExchangePtr(volatile void **target, const void *value)
Replaces a pointer with the given value atomically.
fpl_platform_api uint64_t fplAtomicAddAndFetchU64(volatile uint64_t *dest, const uint64_t addend)
Adds the addend to destination 64-bit unsigned integer atomically and returns the result after the ad...
fpl_platform_api uint64_t fplAtomicLoadU64(volatile uint64_t *source)
Loads the 64-bit unsigned value atomically and returns the value.
fpl_common_api void * fplAtomicCompareAndSwapPtr(volatile void **dest, const void *comparand, const void *exchange)
Compares a pointer with a comparand and swaps it when comparand matches the destination.
fpl_common_api size_t fplAtomicIncrementSize(volatile size_t *dest)
Increments the given size by one atomically.
fpl_platform_api bool fplAtomicIsCompareAndSwapS32(volatile int32_t *dest, const int32_t comparand, const int32_t exchange)
Compares a 32-bit signed integer with a comparand and swaps it when comparand matches the destination...
fpl_common_api void * fplAtomicAddAndFetchPtr(volatile void **dest, const intptr_t addend)
Adds the addend to destination pointer atomically and returns the result after the addition.
fpl_common_api size_t fplAtomicExchangeSize(volatile size_t *target, const size_t value)
Replaces a size with the given value atomically.
fpl_common_api void fplAtomicStorePtr(volatile void **dest, const void *value)
Overwrites the pointer value atomically.
fpl_platform_api uint32_t fplAtomicAddAndFetchU32(volatile uint32_t *dest, const uint32_t addend)
Adds the addend to destination 32-bit unsigned integer atomically and returns the result after the ad...
fpl_platform_api bool fplAtomicIsCompareAndSwapU64(volatile uint64_t *dest, const uint64_t comparand, const uint64_t exchange)
Compares a 64-bit unsigned integer with a comparand and swaps it when comparand matches the destinati...
fpl_common_api void fplAtomicStoreSize(volatile size_t *dest, const size_t value)
Overwrites the size value atomically.
fpl_platform_api void fplAtomicReadWriteFence()
Inserts a memory read and write fence/barrier.
fpl_platform_api int32_t fplAtomicAddAndFetchS32(volatile int32_t *dest, const int32_t addend)
Adds the addend to destination 32-bit signed integer atomically and returns the result after the addi...
fpl_platform_api uint32_t fplAtomicCompareAndSwapU32(volatile uint32_t *dest, const uint32_t comparand, const uint32_t exchange)
Compares a 32-bit unsigned integer with a comparand and swaps it when comparand matches the destinati...
fpl_platform_api int64_t fplAtomicCompareAndSwapS64(volatile int64_t *dest, const int64_t comparand, const int64_t exchange)
Compares a 64-bit signed integer with a comparand and swaps it when comparand matches the destination...
fpl_platform_api int32_t fplAtomicCompareAndSwapS32(volatile int32_t *dest, const int32_t comparand, const int32_t exchange)
Compares a 32-bit signed integer with a comparand and swaps it when comparand matches the destination...
fpl_platform_api uint32_t fplAtomicFetchAndAddU32(volatile uint32_t *value, const uint32_t addend)
Adds a 32-bit unsigned integer to the value by the given addend atomically.
fpl_platform_api void fplAtomicStoreU64(volatile uint64_t *dest, const uint64_t value)
Overwrites the 64-bit unsigned value atomically.
fpl_common_api size_t fplAtomicCompareAndSwapSize(volatile size_t *dest, const size_t comparand, const size_t exchange)
Compares a size with a comparand and swaps it when comparand matches the destination.
fpl_platform_api void fplAtomicReadFence()
Inserts a memory read fence/barrier.
fpl_common_api bool fplAtomicIsCompareAndSwapPtr(volatile void **dest, const void *comparand, const void *exchange)
Compares a pointer with a comparand and swaps it when comparand matches the destination and returns a...
fpl_platform_api uint32_t fplAtomicLoadU32(volatile uint32_t *source)
Loads the 32-bit unsigned value atomically and returns the value.
fpl_platform_api int32_t fplAtomicFetchAndAddS32(volatile int32_t *value, const int32_t addend)
Adds a 32-bit signed integer to the value by the given addend atomically.
fpl_platform_api int64_t fplAtomicLoadS64(volatile int64_t *source)
Loads the 64-bit signed value atomically and returns the value.
fpl_platform_api int64_t fplAtomicAddAndFetchS64(volatile int64_t *dest, const int64_t addend)
Adds the addend to destination 64-bit signed integer atomically and returns the result after the addi...
fpl_common_api size_t fplAtomicFetchAndAddSize(volatile size_t *dest, const size_t addend)
Adds a size to the value by the given addend atomically.
fpl_platform_api int32_t fplAtomicIncrementS32(volatile int32_t *dest)
Increments the given 32-bit signed integer by one atomically.
fpl_platform_api void fplAtomicWriteFence()
Inserts a memory write fence/barrier.
fpl_platform_api bool fplAtomicIsCompareAndSwapS64(volatile int64_t *dest, const int64_t comparand, const int64_t exchange)
Compares a 64-bit signed integer with a comparand and swaps it when comparand matches the destination...
fpl_common_api void * fplAtomicFetchAndAddPtr(volatile void **dest, const intptr_t addend)
Adds a addend to the pointer atomically and returns the initial value before the add.
fpl_platform_api int64_t fplAtomicFetchAndAddS64(volatile int64_t *value, const int64_t addend)
Adds a 64-bit signed integer to the value by the given addend atomically.
fpl_common_api size_t fplAtomicLoadSize(volatile size_t *source)
Loads the size value atomically and returns the value.
fpl_common_api bool fplAtomicIsCompareAndSwapSize(volatile size_t *dest, const size_t comparand, const size_t exchange)
Compares a size with a comparand and swaps it when comparand matches the destination and returns a bo...
fpl_platform_api uint64_t fplAtomicCompareAndSwapU64(volatile uint64_t *dest, const uint64_t comparand, const uint64_t exchange)
Compares a 64-bit unsigned integer with a comparand and swaps it when comparand matches the destinati...
fpl_common_api void * fplAtomicIncrementPtr(volatile void **dest)
Increments/Advances the given pointer by one atomically.
fpl_platform_api void fplAtomicStoreU32(volatile uint32_t *dest, const uint32_t value)
Overwrites the 32-bit unsigned value atomically.
fpl_platform_api void fplAtomicStoreS64(volatile int64_t *dest, const int64_t value)
Overwrites the 64-bit signed value atomically.
fpl_platform_api int32_t fplAtomicExchangeS32(volatile int32_t *target, const int32_t value)
Replaces a 32-bit signed integer with the given value atomically.
fpl_common_api uint32_t fplGetAudioBufferSizeInMilliseconds(uint32_t sampleRate, uint32_t frameCount)
Computes the duration in milliseconds for the given sample rate and frame count.
fpl_common_api bool fplGetAudioHardwareFormat(fplAudioDeviceFormat *outFormat)
Retrieves the native format for the current audio device.
fpl_common_api fplAudioResultType fplPlayAudio()
Start playing asynchronous audio.
fpl_common_api uint32_t fplGetAudioDevices(fplAudioDeviceInfo *devices, uint32_t maxDeviceCount)
Retrieves all playback audio devices.
fpl_common_api const char * fplGetAudioFormatName(const fplAudioFormatType format)
Gets the string that represents the given audio format type.
fpl_common_api void fplConvertAudioTargetFormatToDeviceFormat(const fplAudioTargetFormat *inFormat, fplAudioDeviceFormat *outFormat)
Converts a fplAudioTargetFormat into a fplAudioDeviceFormat structure.
fpl_common_api uint32_t fplGetAudioSampleSizeInBytes(const fplAudioFormatType format)
Computes the number of bytes required to write one sample with one channel.
fpl_common_api fplAudioResultType fplStopAudio()
Stop playing asynchronous audio.
fpl_common_api uint32_t fplGetAudioBufferSizeInFrames(uint32_t sampleRate, uint32_t bufferSizeInMilliSeconds)
Computes the total number of frames for given sample rate and buffer size.
fpl_common_api fplAudioBackendType fplGetAudioBackendType()
Gets the current audio backend type.
fpl_common_api uint32_t fplGetAudioBufferSizeInBytes(const fplAudioFormatType format, const uint32_t channelCount, const uint32_t frameCount)
Computes the total number of bytes for the buffer and the given parameters.
fpl_common_api const char * fplGetAudioBackendName(fplAudioBackendType backendType)
Gets the string that represents the given audio backend type.
fplAudioResultType
An enumeration of audio results.
fpl_common_api uint32_t fplGetAudioFrameSizeInBytes(const fplAudioFormatType format, const uint32_t channelCount)
Computes the number of bytes required for one interleaved audio frame - containing all the channels.
fpl_common_api bool fplSetAudioClientReadCallback(fpl_audio_client_read_callback *newCallback, void *userData)
Overwrites the audio client read callback.
@ fplAudioResultType_DeviceBusy
The audio device is busy/waiting.
@ fplAudioResultType_PlatformNotInitialized
The platform is not initialized.
@ fplAudioResultType_Failed
Unknown error.
@ fplAudioResultType_NoDeviceFound
No audio device is found.
@ fplAudioResultType_BackendAlreadyInitialized
The audio backend is already initialized.
@ fplAudioResultType_DeviceNotInitialized
The audio device is not initialized.
@ fplAudioResultType_DeviceAlreadyStopped
The audio device is already stopped.
@ fplAudioResultType_Last
Last fplAudioResultType.
@ fplAudioResultType_First
First fplAudioResultType.
@ fplAudioResultType_UnsetAudioChannels
The number of audio channels is not set.
@ fplAudioResultType_None
No result.
@ fplAudioResultType_Success
Success.
@ fplAudioResultType_UnsetAudioSampleRate
The sample rate is not set.
@ fplAudioResultType_UnsetAudioBufferSize
The audio buffer size is not set.
@ fplAudioResultType_UnsetAudioFormat
The fplAudioFormatType is not set.
@ fplAudioResultType_ApiFailed
Failed to load the audio api.
@ fplAudioResultType_DeviceAlreadyStarted
The audio device is already started.
fpl_platform_api void fplConsoleOut(const char *text)
Writes the given text to the standard output console buffer.
fpl_common_api void fplConsoleFormatOut(const char *format,...)
Writes the given formatted text to the standard output console buffer.
fpl_platform_api char fplConsoleWaitForCharInput()
Wait for a character to be typed in the console input and return it.
fpl_platform_api void fplConsoleError(const char *text)
Writes the given text to the standard error console buffer.
fpl_common_api void fplConsoleFormatError(const char *format,...)
Writes the given formatted text to the standard error console buffer.
#define FPL_MAX_PATH_LENGTH
Maximum length of a path.
#define FPL_MAX_FILENAME_LENGTH
Maximum length of a filename.
#define FPL_PATH_SEPARATOR
Path separator character.
#define FPL_MAX_NAME_LENGTH
Maximum length of a name (in characters)
#define FPL_MAX_BUFFER_LENGTH
Maximum length of an internal buffer (in bytes)
#define FPL_FILE_EXT_SEPARATOR
File extension character.
fpl_platform_api void fplDebugOut(const char *text)
Writes the given text into the debugger output stream.
#define fplStaticAssert(exp)
Breaks the compilation, when the specified expression evaluates to false.
#define fplAssert(exp)
Breaks with an runtime assertion, when the specified expression evaluates to false.
fpl_common_api void fplDebugFormatOut(const char *format,...)
Writes the given formatted text into the debugger output stream.
fpl_platform_api bool fplDynamicLibraryLoad(const char *libraryFilePath, fplDynamicLibraryHandle *outHandle)
Loads a dynamic library and returns if the load was successful or not.
fpl_platform_api void * fplGetDynamicLibraryProc(const fplDynamicLibraryHandle *handle, const char *name)
Returns the dynamic library procedure address for the given procedure name.
fpl_platform_api void fplDynamicLibraryUnload(fplDynamicLibraryHandle *handle)
Unloads the loaded library and resets the handle to zero.
fpl_common_api const char * fplGetLastError()
Gets the last internal error string.
fpl_common_api const char * fplGetErrorByIndex(const size_t index)
Gets the last error string from the given index.
fpl_common_api void fplClearErrors()
Clears all the current errors in the platform.
fpl_common_api size_t fplGetErrorCount()
Gets the count of total last errors.
fpl_platform_api uint64_t fplFileWriteBlock64(const fplFileHandle *fileHandle, void *sourceBuffer, const uint64_t sourceSize)
Writes a block to the given file and returns the number of written bytes.
fpl_platform_api bool fplDirectoryRemove(const char *path)
Deletes the given empty directory without confirmation and returns true when the deletion was success...
fpl_platform_api bool fplFileFlush(fplFileHandle *fileHandle)
Flushes the buffers of the given file and causes all buffered data to be written to a file.
fpl_platform_api uint64_t fplFileGetSizeFromPath64(const char *filePath)
Gets the file size in bytes for the given file.
fpl_platform_api bool fplDirectoryExists(const char *path)
Checks if the given directory exists and returns a boolean indicating its existence.
fpl_platform_api bool fplFileMove(const char *sourceFilePath, const char *targetFilePath)
Movies the given source file to the target file and returns true when the move was successful.
fpl_platform_api bool fplDirectoryListNext(fplFileEntry *entry)
Gets the next file entry from iterating through files/directories.
fpl_platform_api uint32_t fplFileGetSizeFromHandle32(const fplFileHandle *fileHandle)
Gets the file size in bytes for an opened file.
uint64_t fplFileTimeStamp
The elapsed seconds since the UNIX epoch (1970-01-01 00:00:00)
fpl_platform_api bool fplFileCreateBinary(const char *filePath, fplFileHandle *outHandle)
Create a binary file for writing to the given string path and returns the handle of it.
fpl_platform_api bool fplDirectoryListBegin(const char *path, const char *filter, fplFileEntry *entry)
Iterates through files/directories in the given directory.
fpl_platform_api uint32_t fplFileGetSizeFromPath32(const char *filePath)
Gets the file size in bytes for the given file.
fplFilePermissionMasks
An enumeration of file permission types.
fpl_platform_api bool fplFileExists(const char *filePath)
Checks if the file exists and returns a boolean indicating the existence.
fpl_platform_api void fplDirectoryListEnd(fplFileEntry *entry)
Releases opened resources from iterating through files/directories.
fpl_platform_api uint64_t fplFileGetPosition64(const fplFileHandle *fileHandle)
Gets the current file position in bytes.
fpl_platform_api uint32_t fplFileGetPosition32(const fplFileHandle *fileHandle)
Gets the current file position in bytes.
fpl_platform_api size_t fplFileGetSizeFromPath(const char *filePath)
Gets the file size in bytes for the given file.
fpl_common_api size_t fplFileGetSizeFromHandle(const fplFileHandle *fileHandle)
Gets the file size in bytes for an opened file.
fpl_platform_api bool fplFileGetTimestampsFromPath(const char *filePath, fplFileTimeStamps *outStamps)
Gets the timestamps for the given file.
fpl_platform_api size_t fplFileReadBlock(const fplFileHandle *fileHandle, const size_t sizeToRead, void *targetBuffer, const size_t maxTargetBufferSize)
Reads a block from the given file and returns the number of bytes read.
fpl_platform_api bool fplFileSetTimestamps(const char *filePath, const fplFileTimeStamps *timeStamps)
Sets the timestamps for the given file.
fplFileAttributeFlags
An enumeratation of file attribute flags (Normal, Readonly, Hidden, etc.)
fpl_platform_api uint64_t fplFileGetSizeFromHandle64(const fplFileHandle *fileHandle)
Gets the file size in bytes for an opened file.
fplFilePermissionFlags
An enumeration of file permission flags.
fpl_platform_api bool fplFileGetTimestampsFromHandle(const fplFileHandle *fileHandle, fplFileTimeStamps *outStamps)
Gets the timestamps for an opened file.
fpl_platform_api bool fplDirectoriesCreate(const char *path)
Creates all the directories in the given path.
fpl_platform_api uint32_t fplFileWriteBlock32(const fplFileHandle *fileHandle, void *sourceBuffer, const uint32_t sourceSize)
Writes a block to the given file and returns the number of written bytes.
fpl_platform_api uint64_t fplFileSetPosition64(const fplFileHandle *fileHandle, const int64_t position, const fplFilePositionMode mode)
Sets the current file position by the given position, depending on the mode it's absolute or relative...
fpl_platform_api bool fplFileDelete(const char *filePath)
Deletes the given file without confirmation and returns true when the deletion was successful.
fplFileEntryType
An enumeration of file entry types (File, Directory, etc.)
fpl_common_api size_t fplFileSetPosition(const fplFileHandle *fileHandle, const intptr_t position, const fplFilePositionMode mode)
Sets the current file position by the given position, depending on the mode it's absolute or relative...
fpl_common_api size_t fplFileWriteBlock(const fplFileHandle *fileHandle, void *sourceBuffer, const size_t sourceSize)
Writes a block to the given file and returns the number of written bytes.
fpl_platform_api uint32_t fplFileReadBlock32(const fplFileHandle *fileHandle, const uint32_t sizeToRead, void *targetBuffer, const uint32_t maxTargetBufferSize)
Reads a block from the given file and returns the number of bytes read.
fpl_platform_api void fplFileClose(fplFileHandle *fileHandle)
Closes the given file and releases the underlying resources and clears the handle to zero.
fpl_platform_api bool fplFileCopy(const char *sourceFilePath, const char *targetFilePath, const bool overwrite)
Copies the given source file to the target path and returns true when the copy was successful.
fpl_common_api size_t fplFileGetPosition(const fplFileHandle *fileHandle)
Gets the current file position in bytes.
fpl_platform_api uint32_t fplFileSetPosition32(const fplFileHandle *fileHandle, const int32_t position, const fplFilePositionMode mode)
Sets the current file position by the given position, depending on the mode it's absolute or relative...
fpl_platform_api bool fplFileOpenBinary(const char *filePath, fplFileHandle *outHandle)
Opens a binary file for reading from a string path and returns the handle of it.
fpl_platform_api uint64_t fplFileReadBlock64(const fplFileHandle *fileHandle, const uint64_t sizeToRead, void *targetBuffer, const uint64_t maxTargetBufferSize)
Reads a block from the given file and returns the number of bytes read.
fplFilePositionMode
An enumeration of file position modes (Beginning, Current, End)
@ fplFilePermissionMasks_Group
Group.
@ fplFilePermissionMasks_User
User.
@ fplFilePermissionMasks_Owner
Owner.
@ fplFilePermissionMasks_None
No mask.
@ fplFileAttributeFlags_Archive
Archive.
@ fplFileAttributeFlags_None
No attributes.
@ fplFileAttributeFlags_Normal
Normal.
@ fplFileAttributeFlags_System
System.
@ fplFileAttributeFlags_Hidden
Hidden.
@ fplFilePermissionFlags_CanExecuteSearch
CanExecute.
@ fplFilePermissionFlags_CanRead
CanRead.
@ fplFilePermissionFlags_CanWrite
CanWrite.
@ fplFilePermissionFlags_All
All (Read, Write, Execute, Search)
@ fplFileEntryType_Unknown
Unknown entry type.
@ fplFileEntryType_Directory
Entry is a directory.
@ fplFileEntryType_File
Entry is a file.
@ fplFilePositionMode_Beginning
Starts from the beginning.
@ fplFilePositionMode_Current
Starts from the current position.
@ fplFilePositionMode_End
Starts from the end.
fpl_common_api uint64_t fplCPUXCR0()
Gets the x86 extended control register for index zero.
fpl_common_api void fplCPUID(fplCPUIDLeaf *outLeaf, const uint32_t functionId)
Queries the x86 CPUID leaf register (EAX, EBX, ECX, EDX) for the given function id.
fpl_common_api const char * fplCPUGetArchName(const fplCPUArchType type)
Gets the string representation of the given architecture type.
fpl_common_api size_t fplCPUGetName(char *destBuffer, const size_t maxDestBufferLen)
Retrieves the name of the processor.
fpl_platform_api size_t fplCPUGetCoreCount()
Retrieves the total number of processor cores.
fplCPUArchType
An enumeration of architecture types.
fpl_common_api uint64_t fplCPURDTSC()
Reads the current time stamp counter (RDTSC)
fpl_common_api bool fplCPUGetCapabilities(fplCPUCapabilities *outCaps)
Gets the capabilities of the processor.
fpl_platform_api fplCPUArchType fplCPUGetArchitecture()
Gets the processor architecture type.
@ fplCPUArchType_x64
X64 only architecture.
@ fplCPUArchType_Arm32
ARM32 architecture.
@ fplCPUArchType_First
First fplCPUArchType.
@ fplCPUArchType_x86_64
X86 with 64-bit architecture.
@ fplCPUArchType_Unknown
Unknown architecture.
@ fplCPUArchType_Arm64
ARM64 architecture.
@ fplCPUArchType_Last
Last fplCPUArchType.
@ fplCPUArchType_x86
X86 architecture.
fplLocaleFormat
A enumeration of locale formats.
fpl_platform_api size_t fplGetInputLocale(const fplLocaleFormat targetFormat, char *buffer, const size_t maxBufferLen)
Gets the input locale in the given target format.
fpl_platform_api size_t fplGetUserLocale(const fplLocaleFormat targetFormat, char *buffer, const size_t maxBufferLen)
Gets the user locale in the given target format.
fpl_platform_api size_t fplGetSystemLocale(const fplLocaleFormat targetFormat, char *buffer, const size_t maxBufferLen)
Gets the system locale in the given target format.
@ fplLocaleFormat_ISO639
ISO-639 format (de-DE, en-US, etc.)
@ fplLocaleFormat_None
No locale format.
fplLogLevel
An enumeration of log levels.
fpl_common_api void fplSetMaxLogLevel(const fplLogLevel maxLevel)
Changes the current maximum log level to the given value.
fpl_common_api const fplLogSettings * fplGetLogSettings()
Gets the current log settings.
fpl_common_api void fplSetLogSettings(const fplLogSettings *params)
Overwrites the current log settings.
fpl_common_api fplLogLevel fplGetMaxLogLevel()
Gets the current maximum allowed log level.
void() fpl_log_func_callback(const char *funcName, const int lineNumber, const fplLogLevel level, const char *message)
A callback for printing a log message.
fplLogWriterFlags
An enumeration of log writer flags.
@ fplLogLevel_Warning
Warning.
@ fplLogLevel_Last
Last fplLogLevel.
@ fplLogLevel_Trace
Trace.
@ fplLogLevel_Verbose
Verbose.
@ fplLogLevel_Debug
Debug.
@ fplLogLevel_Critical
Critical.
@ fplLogLevel_Error
Error.
@ fplLogLevel_First
First fplLogLevel.
@ fplLogWriterFlags_ErrorConsole
Error-Console output.
@ fplLogWriterFlags_DebugOut
Debug output.
@ fplLogWriterFlags_Custom
Custom output.
@ fplLogWriterFlags_None
No appender flags.
@ fplLogWriterFlags_StandardConsole
Standard-Console output.
#define fplMin(a, b)
Returns the smallest value of A and B.
#define fplIsBitSet(value, bit)
Returns true when the given value has the given bit set.
#define fplMax(a, b)
Returns the biggest value of A and B.
#define fplIsBigEndian()
Returns true when the given platform is big-endian.
#define fplIsAligned(ptr, alignment)
Returns true when the given pointer address is aligned to the given alignment.
#define fplGetAlignedSize(size, alignment)
Returns the given size, extended to satisfy the given alignment boundary.
#define fplZeroInit
Initializes a struct to zero.
#define fplCopyStruct(src, dst)
Copies the given source struct into the destination struct.
#define fplArrayCount(arr)
Returns the element count from a static array. This should ideally produce a compile error when passi...
#define fplStructInit
Initializes a struct by the given type.
#define fplClearStruct(ptr)
Clears the given struct pointer to zero.
fpl_platform_api bool fplMemoryGetInfos(fplMemoryInfos *outInfos)
Retrieves the current system memory usage.
fpl_common_api void fplMemoryCopy(const void *sourceMem, const size_t sourceSize, void *targetMem)
Copies the given source memory with its length to the target memory.
fpl_platform_api void * fplMemoryAllocate(const size_t size)
Allocates memory from the operating system by the given size.
fpl_common_api void fplMemorySet(void *mem, const uint8_t value, const size_t size)
Sets the given memory by the given size to the given value.
fpl_platform_api void fplMemoryFree(void *ptr)
Releases the memory allocated from the operating system.
fpl_common_api void fplMemoryClear(void *mem, const size_t size)
Clears the given memory by the given size to zero.
fpl_common_api void * fplMemoryAlignedAllocate(const size_t size, const size_t alignment)
Allocates aligned memory from the operating system by the given alignment.
fpl_common_api void fplMemoryAlignedFree(void *ptr)
Releases the aligned memory allocated from the operating system.
fpl_platform_api size_t fplSessionGetUsername(char *nameBuffer, const size_t maxNameBufferLen)
Gets the username of the current logged-in user from the session.
fpl_platform_api size_t fplGetExecutableFilePath(char *destPath, const size_t maxDestLen)
Gets the full path to this executable, including the executable file name.
fpl_common_api size_t fplChangeFileExtension(const char *filePath, const char *newFileExtension, char *destPath, const size_t maxDestLen)
Changes the file extension on the given source path and writes the result into a destination buffer.
fpl_common_api size_t fplPathCombine(char *destPath, const size_t maxDestPathLen, const size_t pathCount,...)
Combines all given paths by the platforms path separator for a fixed number of arguments.
fpl_common_api const char * fplExtractFileExtension(const char *sourcePath)
Extracts the file extension from the given source path.
fpl_platform_api size_t fplGetHomePath(char *destPath, const size_t maxDestLen)
Gets the full path to your home directory.
fpl_common_api size_t fplExtractFilePath(const char *sourcePath, char *destPath, const size_t maxDestLen)
Extracts the directory path from the given file path.
fpl_common_api const char * fplExtractFileName(const char *sourcePath)
Extracts the file name including the file extension from the given source path.
fpl_common_api void fplSetDefaultAudioSettings(fplAudioSettings *audio)
Resets the given audio settings to default settings (S16 PCM, 48 kHz, 2 Channels)
fpl_common_api void fplSetDefaultInputSettings(fplInputSettings *input)
Resets the given input settings container to default values.
fplImageType
An enumeration of image types.
void() fpl_memory_release_callback(void *userData, void *ptr)
Custom memory release callback.
fplInitFlags
An enumeration of initialization flags.
fplPlatformResultType
An enumeration of platform result types.
fplVulkanValidationLayerMode
The validation layer modes for Vulkan.
fplAudioFormatType
An enumeration of audio format types.
fpl_common_api const fplSettings * fplGetCurrentSettings()
Gets the current settings.
fplAudioLatencyMode
An enumeration of audio latency modes.
fplMemoryAllocationMode
A enumeration of dynamic memory allocation modes.
fplOpenGLCompabilityFlags
An enumeration of OpenGL compability flags.
fpl_window_event_callback fpl_window_exposed_callback
A callback executed when the window needs to be exposed/repainted.
uint32_t() fpl_audio_client_read_callback(const fplAudioDeviceFormat *deviceFormat, const uint32_t frameCount, void *outputSamples, void *userData)
A callback for reading audio samples from the client.
fpl_inline fplColor32 fplCreateColorRGBA(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a)
Creates a fplColor32 from the specified r, g, b, a components.
fpl_common_api fplSettings fplMakeDefaultSettings()
Creates a full settings structure containing default values.
fpl_common_api void fplSetDefaultConsoleSettings(fplConsoleSettings *console)
Resets the given console settings container to default settings.
fplAudioDefaultFields
An enumeration of audio default fields.
void() fplVulkanValidationLayerCallback(void *userData, const char *message, const uint32_t messageSeverity, const uint32_t messageType, const void *debugUtilsMessengerCallbackData)
The debug callback called when the validation layer writes something.
fplAudioBackendType
An enumeration of audio backend types.
fpl_common_api void fplSetDefaultSettings(fplSettings *settings)
Resets the given settings container to default values for window, video, audio, etc.
fplVideoBackendType
An enumeration of video backend types.
fplPlatformType
An enumeration of platform types.
fpl_common_api const char * fplPlatformGetResultName(const fplPlatformResultType type)
Gets the string representation of a platform result type.
void *() fpl_memory_allocate_callback(void *userData, const size_t size, const size_t alignment)
Custom memory allocation callback.
bool() fpl_window_event_callback(const fplPlatformType platformType, void *windowState, void *rawEventData, void *userData)
A callback executed for each raw window event.
fpl_common_api void fplSetDefaultWindowSettings(fplWindowSettings *window)
Resets the given window settings container to default settings.
fpl_common_api void fplSetDefaultVideoSettings(fplVideoSettings *video)
Resets the given video settings to default values.
fplVulkanValidationSeverity
The validation layer logging severity for Vulkan.
@ fplImageType_None
No image type.
@ fplImageType_RGBA
RGBA image type.
@ fplInitFlags_None
No init flags.
@ fplInitFlags_Audio
Use asynchronous audio playback.
@ fplInitFlags_All
All init flags.
@ fplInitFlags_Window
Create a single window.
@ fplInitFlags_Video
Use a video backbuffer (This flag ensures that fplInitFlags_Window is included always)
@ fplInitFlags_GameController
Support for game controllers.
@ fplInitFlags_Console
Create a console window.
@ fplPlatformResultType_FailedPlatform
Platform initialization failed.
@ fplPlatformResultType_Last
Last fplPlatformResultType.
@ fplPlatformResultType_FailedWindow
Window creation failed.
@ fplPlatformResultType_Success
Everything is fine.
@ fplPlatformResultType_FailedAudio
Audio initialization failed.
@ fplPlatformResultType_First
First fplPlatformResultType.
@ fplPlatformResultType_AlreadyInitialized
Platform is already initialized.
@ fplPlatformResultType_FailedVideo
Video initialization failed.
@ fplPlatformResultType_NotInitialized
Platform is not initialized.
@ fplPlatformResultType_FailedAllocatingMemory
Failed allocating required memory.
@ fplVulkanValidationLayerMode_Required
Enable validations and stop when its not supported.
@ fplVulkanValidationLayerMode_Disabled
Do not use the validation.
@ fplVulkanValidationLayerMode_Optional
Enable validations when its possible.
@ fplAudioFormatType_U8
Unsigned 8-bit integer PCM.
@ fplAudioFormatType_F64
64-bit IEEE_FLOAT
@ fplAudioFormatType_S24
Signed 24-bit integer PCM.
@ fplAudioFormatType_Last
Last fplAudioFormatType.
@ fplAudioFormatType_S16
Signed 16-bit integer PCM.
@ fplAudioFormatType_None
No audio format.
@ fplAudioFormatType_S32
Signed 32-bit integer PCM.
@ fplAudioFormatType_F32
32-bit IEEE_FLOAT
@ fplAudioFormatType_S64
Signed 64-bit integer PCM.
@ fplAudioFormatType_First
First fplAudioFormatType.
@ fplAudioLatencyMode_Conservative
Conservative latency.
@ fplAudioLatencyMode_Low
Low latency.
@ fplMemoryAllocationMode_Custom
Use custom memory allocation.
@ fplMemoryAllocationMode_Automatic
Use OS memory allocation.
@ fplOpenGLCompabilityFlags_Legacy
Use legacy context.
@ fplOpenGLCompabilityFlags_Compability
Use compability profile.
@ fplOpenGLCompabilityFlags_Core
Use core profile.
@ fplOpenGLCompabilityFlags_Forward
Remove features marked as deprecated.
@ fplAudioDefaultFields_Channels
Number of channels is default.
@ fplAudioDefaultFields_Periods
Number of periods is default.
@ fplAudioDefaultFields_SampleRate
Samples per seconds is default.
@ fplAudioDefaultFields_Type
Audio format is default.
@ fplAudioDefaultFields_None
No default fields.
@ fplAudioDefaultFields_BufferSize
Buffer size is default.
@ fplAudioBackendType_First
First fplAudioBackendType.
@ fplAudioBackendType_Last
Last fplAudioBackendType.
@ fplAudioBackendType_Alsa
ALSA.
@ fplAudioBackendType_None
No audio backend.
@ fplAudioBackendType_Auto
Auto detect.
@ fplAudioBackendType_DirectSound
DirectSound.
@ fplVideoBackendType_Vulkan
Vulkan.
@ fplVideoBackendType_None
No video backend.
@ fplVideoBackendType_Software
Software.
@ fplVideoBackendType_First
First fplVideoBackendType.
@ fplVideoBackendType_OpenGL
OpenGL.
@ fplVideoBackendType_Last
Last fplVideoBackendType.
@ fplPlatformType_Linux
Linux platform.
@ fplPlatformType_Unknown
Unknown platform.
@ fplPlatformType_Last
Last fplPlatformType.
@ fplPlatformType_Windows
Windows platform.
@ fplPlatformType_First
First fplPlatformType.
@ fplPlatformType_Unix
Unix platform.
@ fplVulkanValidationSeverity_Verbose
Log warning, error, info, verbose.
@ fplVulkanValidationSeverity_Off
Log nothing.
@ fplVulkanValidationSeverity_All
Log out everything.
@ fplVulkanValidationSeverity_Info
Log warning, error, infos.
@ fplVulkanValidationSeverity_Error
Log error only.
@ fplVulkanValidationSeverity_Warning
Log warning and error.
#define fpl_globalvar
Global persistent variable.
#define fpl_force_inline
Always inlines this function.
#define fpl_internal
Private/Internal function.
#define fpl_platform_api
Platform api.
#define fpl_main
Main entry point api definition.
#define fpl_inline
Inline function.
#define fpl_common_api
Common api.
fpl_common_api size_t fplStringFormatArgs(char *destBuffer, const size_t maxDestBufferLen, const char *format, va_list argList)
Fills out the given destination string buffer with a formatted string, using the format specifier and...
fpl_common_api char * fplCopyStringLen(const char *source, const size_t sourceLen, char *dest, const size_t maxDestLen)
Copies the given source string with a constrained length into a destination string.
fpl_common_api bool fplIsStringEqualLen(const char *a, const size_t aLen, const char *b, const size_t bLen)
Compares two strings with constrained lengths and returns a boolean indicating the equality.
fpl_common_api char * fplStringAppend(const char *appended, char *buffer, size_t maxBufferLen)
Appends the source string to the given buffer.
fpl_common_api int32_t fplStringToS32Len(const char *str, const size_t len)
Converts the given string into a 32-bit integer constrained by string length.
fpl_common_api size_t fplS32ToString(const int32_t value, char *buffer, const size_t maxBufferLen)
Converts the given 32-bit integer value into a string.
fpl_common_api char * fplCopyString(const char *source, char *dest, const size_t maxDestLen)
Copies the given source string into a destination string.
fpl_common_api char * fplEnforcePathSeparatorLen(char *path, size_t maxPathLen)
Ensures that the given string always ends with a path separator with length constrained.
fpl_common_api bool fplIsStringEqual(const char *a, const char *b)
Compares two strings and returns a boolean indicating the equality.
fpl_common_api char * fplStringAppendLen(const char *appended, const size_t appendedLen, char *buffer, size_t maxBufferLen)
Appends the source string to the given buffer constrained by length.
fpl_common_api size_t fplStringFormat(char *destBuffer, const size_t maxDestBufferLen, const char *format,...)
Fills out the given destination string buffer with a formatted string, using the format specifier and...
fpl_platform_api size_t fplWideStringToUTF8String(const wchar_t *wideSource, const size_t wideSourceLen, char *utf8Dest, const size_t maxUtf8DestLen)
Converts the given 16-bit source wide string with length in an 8-bit UTF-8 ANSI string.
fpl_platform_api size_t fplUTF8StringToWideString(const char *utf8Source, const size_t utf8SourceLen, wchar_t *wideDest, const size_t maxWideDestLen)
Converts the given 8-bit UTF-8 source ANSI string with length in a 16-bit wide string.
fpl_common_api bool fplIsStringMatchWildcard(const char *source, const char *wildcard)
Matches the given string by the given wildcard and returns a boolean indicating the match.
fpl_common_api size_t fplGetStringLength(const char *str)
Counts the number of characters without including the zero terminator.
fpl_common_api int32_t fplStringToS32(const char *str)
Converts the given string into a 32-bit integer.
fpl_common_api char * fplEnforcePathSeparator(char *path)
Ensures that the given string always ends with a path separator.
fpl_platform_api bool fplConditionBroadcast(fplConditionVariable *condition)
Wakes up all threads that wait on the given condition.
fpl_platform_api fplThreadHandle * fplThreadCreateWithParameters(fplThreadParameters *parameters)
Creates and starts a thread from the specified fplThreadParameters and returns the handle to it.
uint32_t fplThreadState
A type definition for mapping fplThreadState into a 32-bit integer.
fpl_platform_api void fplSemaphoreDestroy(fplSemaphoreHandle *semaphore)
Releases the internal semaphore resources.
fpl_platform_api bool fplMutexInit(fplMutexHandle *mutex)
Initializes the given mutex.
fpl_platform_api bool fplSignalWaitForAny(fplSignalHandle **signals, const size_t count, const size_t stride, const fplTimeoutValue timeout)
Waits until any of the given signals wakes up or the timeout has been reached.
fplSignalValue
An enumeration of signal values.
fpl_platform_api void fplThreadSleep(const uint32_t milliseconds)
Let the current thread sleep for the given amount of milliseconds.
fpl_platform_api bool fplSignalInit(fplSignalHandle *signal, const fplSignalValue initialValue)
Initializes the given signal.
fpl_platform_api bool fplConditionWait(fplConditionVariable *condition, fplMutexHandle *mutex, const fplTimeoutValue timeout)
Sleeps on the given condition and releases the mutex when done.
fpl_platform_api bool fplMutexUnlock(fplMutexHandle *mutex)
Unlocks the given mutex.
fpl_platform_api bool fplThreadYield()
Let the current thread yield execution to another thread that is ready to run on this core.
fpl_platform_api bool fplSignalSet(fplSignalHandle *signal)
Sets the signal and wakes up the given signal.
fpl_platform_api bool fplSemaphoreRelease(fplSemaphoreHandle *semaphore)
Increments the semaphore value by one.
fpl_platform_api fplThreadPriority fplGetThreadPriority(fplThreadHandle *thread)
Retrieves the current thread priority from the OS from the given fplThreadHandle .
fpl_platform_api bool fplSetThreadPriority(fplThreadHandle *thread, const fplThreadPriority newPriority)
Changes the thread priority to the given one, for the given fplThreadHandle .
fpl_common_api fplThreadState fplGetThreadState(fplThreadHandle *thread)
Gets the current thread state for the given thread.
fpl_common_api size_t GetUsedThreadCount()
Gets the number of used/active threads.
fpl_common_api const fplThreadHandle * fplGetMainThread()
Gets the thread handle for the main thread.
fplThreadStates
An enumeration of thread states.
fplThreadPriority
Defines all possible thread priorities.
void() fpl_run_thread_callback(const fplThreadHandle *thread, void *data)
A callback to execute user code inside another thread.
fpl_platform_api bool fplSemaphoreWait(fplSemaphoreHandle *semaphore, const fplTimeoutValue timeout)
Waits for the semaphore until it gets signaled or the timeout has been reached.
fpl_platform_api bool fplSignalWaitForAll(fplSignalHandle **signals, const size_t count, const size_t stride, const fplTimeoutValue timeout)
Waits until all the given signals are waked up.
fpl_platform_api bool fplConditionSignal(fplConditionVariable *condition)
Wakes up one thread that waits on the given condition.
fpl_platform_api fplThreadHandle * fplThreadCreate(fpl_run_thread_callback *runFunc, void *data)
Creates and starts a thread and returns the handle to it.
fpl_platform_api bool fplThreadWaitForAll(fplThreadHandle **threads, const size_t count, const size_t stride, const fplTimeoutValue timeout)
Wait until all given threads are done running or the given timeout has been reached.
fpl_platform_api void fplConditionDestroy(fplConditionVariable *condition)
Releases the given condition and clears the structure to zero.
fpl_platform_api void fplMutexDestroy(fplMutexHandle *mutex)
Releases the given mutex and clears the structure to zero.
fpl_common_api size_t GetAvailableThreadCount()
Gets the number of available threads.
fpl_platform_api int32_t fplSemaphoreValue(fplSemaphoreHandle *semaphore)
Gets the current semaphore value.
fpl_platform_api bool fplSemaphoreInit(fplSemaphoreHandle *semaphore, const uint32_t initialValue)
Initializes the semaphore with the given initial value.
fpl_platform_api bool fplThreadWaitForOne(fplThreadHandle *thread, const fplTimeoutValue timeout)
Wait until the given thread is done running or the given timeout has been reached.
fpl_platform_api bool fplSemaphoreTryWait(fplSemaphoreHandle *semaphore)
Tries to wait for the semaphore until it gets signaled or return immediately.
fpl_platform_api bool fplSignalWaitForOne(fplSignalHandle *signal, const fplTimeoutValue timeout)
Waits until the given signal is waked up.
fpl_platform_api bool fplMutexLock(fplMutexHandle *mutex)
Locks the given mutex and blocks any other threads.
fpl_platform_api bool fplThreadWaitForAny(fplThreadHandle **threads, const size_t count, const size_t stride, const fplTimeoutValue timeout)
Wait until one of the given threads is done running or the given timeout has been reached.
fpl_platform_api void fplSignalDestroy(fplSignalHandle *signal)
Releases the given signal and clears the structure to zero.
fpl_platform_api bool fplSignalReset(fplSignalHandle *signal)
Resets the signal.
fpl_platform_api bool fplThreadTerminate(fplThreadHandle *thread)
Forces the given thread to stop and release all underlying resources.
fpl_platform_api uint32_t fplGetCurrentThreadId()
Gets the thread id for the current thread.
fpl_platform_api bool fplMutexTryLock(fplMutexHandle *mutex)
Tries to lock the given mutex without blocking other threads.
fpl_platform_api bool fplConditionInit(fplConditionVariable *condition)
Initialize s the given condition.
@ fplSignalValue_Unset
Value is unset.
@ fplSignalValue_Set
Value is set.
@ fplThreadState_Starting
Thread is being started.
@ fplThreadState_Stopping
Thread is being stopped.
@ fplThreadState_Stopped
Thread is stopped.
@ fplThreadState_Running
Thread is still running.
@ fplThreadPriority_Low
Low priority.
@ fplThreadPriority_First
First fplThreadPriority.
@ fplThreadPriority_Idle
Idle priority (Only when nothing is going on)
@ fplThreadPriority_Lowest
Lowest fplThreadPriority.
@ fplThreadPriority_High
High priority.
@ fplThreadPriority_Normal
Normal priority.
@ fplThreadPriority_RealTime
Realtime priority (Time critical)
@ fplThreadPriority_Highest
Highest fplThreadPriority.
@ fplThreadPriority_Unknown
Unknown priority.
@ fplThreadPriority_Last
Last fplThreadPriority.
uint64_t fplMilliseconds
A type definition for milliseconds / 64-bit.
fpl_platform_api fplMilliseconds fplMillisecondsQuery()
Gets the current system clock in milliseconds, since some fixed starting point (OS start,...
double fplSeconds
A type definition for seconds / 64-bit.
fpl_platform_api fplSeconds fplTimestampElapsed(const fplTimestamp start, const fplTimestamp finish)
Gets the delta value from two fplTimestamp values in seconds.
fpl_platform_api fplTimestamp fplTimestampQuery()
Gets the current fplTimestamp with most precision, used for time delta measurements only.
uint32_t fplTimeoutValue
A type definition for a timeout value in milliseconds.
#define FPL_TIMEOUT_INFINITE
Infinite timeout constant.
fpl_common_api fplVideoBackendType fplGetVideoBackendType()
Gets the current video backend.
fpl_common_api const fplVideoSurface * fplGetVideoSurface()
Gets the current fplVideoSurface that stores all handles used for the active video backend.
fpl_common_api const void * fplGetVideoProcedure(const char *procName)
Gets the procedure by the specified name from the active video backend.
fpl_inline fplVideoRect fplCreateVideoRectFromLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom)
Makes a video rectangle from a LTRB rectangle.
fpl_common_api bool fplResizeVideoBackBuffer(const uint32_t width, const uint32_t height)
Resizes the current video backbuffer.
fpl_common_api bool fplGetVideoRequirements(const fplVideoBackendType backendType, fplVideoRequirements *requirements)
Gets the video requirements for the specified video backend.
fpl_common_api fplVideoBackBuffer * fplGetVideoBackBuffer()
Retrieves the pointer to the current video backbuffer.
fpl_common_api const char * fplGetVideoBackendName(fplVideoBackendType backendType)
Gets a string that represents the given video backend.
fpl_common_api void fplVideoFlip()
Forces the window to be redrawn or to swap the back/front buffer.
fpl_platform_api bool fplWindowUpdate()
Clears the internal event queue and updates input devices if needed.
fpl_platform_api bool fplSetWindowState(const fplWindowState newState)
Changes the current window state.
fpl_platform_api bool fplGetWindowPosition(fplWindowPosition *outPos)
Retrieves the absolute window position.
fpl_platform_api void fplSetWindowFloating(const bool value)
Enables or disables the window floating (Top-most)
fpl_platform_api bool fplSetWindowFullscreenRect(const bool value, const int32_t x, const int32_t y, const int32_t width, const int32_t height)
Enables or disables fullscreen mode based on the given rectangle.
fpl_platform_api bool fplDisableWindowFullscreen()
Switches the window back to window mode.
fpl_platform_api bool fplIsWindowFloating()
Gets the window floating state as boolean.
fpl_platform_api void fplSetWindowDecorated(const bool value)
Enables or disables the window decoration (Titlebar, Border, etc.).
fpl_platform_api void fplSetWindowResizeable(const bool value)
Enables or disables the ability to resize the window.
fpl_platform_api bool fplEnableWindowFullscreen()
Enables fullscreen mode on the nearest display.
fplWindowState
An enumeration containg the states of a window.
fpl_platform_api fplWindowState fplGetWindowState()
Gets the current window state.
fpl_platform_api void fplSetWindowPosition(const int32_t left, const int32_t top)
Changes the window absolute position to the given coordinates.
fpl_platform_api void fplSetWindowTitle(const char *title)
Changes the window title to the given string.
fpl_platform_api bool fplGetWindowSize(fplWindowSize *outSize)
Retrieves the inner window size.
fpl_platform_api bool fplIsWindowResizable()
Gets the window resizable state as boolean.
fpl_platform_api bool fplSetWindowFullscreenSize(const bool value, const uint32_t fullscreenWidth, const uint32_t fullscreenHeight, const uint32_t refreshRate)
Enables or disables fullscreen mode based on the given size and the current display.
fpl_common_api char * fplGetWindowTitle(char *outTitle, const size_t maxOutTitleLength)
Retrieves the window title and writes it into the output string.
fpl_platform_api void fplWindowShutdown()
Closes the window and stops the event loop.
fpl_platform_api void fplSetWindowSize(const uint32_t width, const uint32_t height)
Resizes the window to fit the inner size based on the given size.
fpl_platform_api void fplSetWindowCursorEnabled(const bool value)
Enables or disables the window cursor.
fpl_platform_api bool fplIsWindowRunning()
Gets the window running state as a boolean.
fpl_platform_api bool fplIsWindowDecorated()
Gets the window decorated state as boolean.
fpl_common_api void fplSetWindowInputEvents(const bool enabled)
Enables or Disables the input events for the window entirely.
fpl_platform_api bool fplIsWindowFullscreen()
Gets the window fullscreen state as boolean.
fplWindowVisibilityState
An enumeration containing the visibility state of a window.
@ fplWindowState_Unknown
Unknown state.
@ fplWindowState_Fullscreen
Fullscreen state.
@ fplWindowState_Normal
Normal window state.
@ fplWindowState_Maximize
Maximize window state.
@ fplWindowState_Iconify
Iconify/Minimize window state.
@ fplWindowVisibilityState_Unknown
Unknown state.
@ fplWindowVisibilityState_Show
Window is visible.
@ fplWindowVisibilityState_Hide
Window is hidden.
fpl_platform_api bool fplSetClipboardText(const char *text)
Overwrites the current clipboard text with the given one.
fpl_platform_api bool fplGetClipboardText(char *dest, const uint32_t maxDestLen)
Retrieves the current clipboard text.
fpl_platform_api bool fplGetDisplayFromPosition(const int32_t x, const int32_t y, fplDisplayInfo *outInfo)
Finds the display from a cursor position and retrieves the information for it.
fpl_platform_api size_t fplGetDisplays(fplDisplayInfo *outDisplays, const size_t maxDisplayCount)
Gets informations about all active displays.
fpl_platform_api size_t fplGetDisplayModes(const char *id, fplDisplayMode *outModes, const size_t maxDisplayModeCount)
Gets the information about the available display modes for the given display id.
fpl_platform_api size_t fplGetDisplayCount()
Gets the number of active displays.
fpl_platform_api bool fplGetWindowDisplay(fplDisplayInfo *outInfo)
Gets information about the display for the FPL window.
fpl_platform_api bool fplGetPrimaryDisplay(fplDisplayInfo *outInfo)
Gets information about the primary display.
fplWindowEventType
An enumeration of window event types (Resized, PositionChanged, etc.)
fpl_platform_api bool fplPollEvent(fplEvent *ev)
Polls the next event from the internal event queue or from the OS, handles them, and removes it from ...
fpl_platform_api void fplPollEvents()
Polls all the events from the OS and clears the internal event queue.
fplButtonState
An enumeration of button states.
fplMouseEventType
An enumeration of mouse event types (Move, ButtonDown, ...)
fplKey
An enumeration of mapped keys (Based on MS Virtual-Key-Codes, mostly directly mapped from ASCII)
fplGamepadButtonType
An enumeration of gamepad buttons.
fplMouseButtonType
An enumeration of mouse button types (Left, Right, ...)
fplGamepadEventType
An enumeration of gamepad event types (Connected, Disconnected, StateChanged, etc....
fplKeyboardEventType
An enumeration of keyboard event types.
fplEventType
An enumeration of event types (Window, Keyboard, Mouse, ...)
fplKeyboardModifierFlags
An enumeration of keyboard modifier flags.
@ fplWindowEventType_PositionChanged
Window was moved.
@ fplWindowEventType_Minimized
Window has been minimized.
@ fplWindowEventType_LostFocus
Window lost focus.
@ fplWindowEventType_Shown
Window was shown.
@ fplWindowEventType_None
None window event type.
@ fplWindowEventType_Exposed
Window was exposed.
@ fplWindowEventType_Restored
Window has been restored.
@ fplWindowEventType_Hidden
Window was hidden.
@ fplWindowEventType_Resized
Window has been resized.
@ fplWindowEventType_Closed
Window was closed.
@ fplWindowEventType_DroppedFiles
Dropped one or more files into the window.
@ fplWindowEventType_Maximized
Window has been maximized.
@ fplWindowEventType_GotFocus
Window got focus.
@ fplButtonState_Press
Key pressed.
@ fplButtonState_Release
Key released.
@ fplButtonState_Repeat
Key is hold down.
@ fplMouseEventType_Move
Mouse position has been changed.
@ fplMouseEventType_Button
Mouse button event.
@ fplMouseEventType_Wheel
Mouse wheel event.
@ fplMouseEventType_None
No mouse event type.
@ fplKey_Oem3
'‘~’ for US
@ fplKey_OemPlus
'+' for any country
@ fplKey_OemMinus
'-' for any country
@ fplKey_OemPeriod
'.' for any country
@ fplKey_OemComma
',' for any country
@ fplGamepadButtonType_LeftShoulder
Left-Shoulder.
@ fplGamepadButtonType_LeftThumb
Left-Thumb.
@ fplGamepadButtonType_ActionY
Action-Y.
@ fplGamepadButtonType_DPadRight
DPad right.
@ fplGamepadButtonType_Start
Start.
@ fplGamepadButtonType_RightShoulder
Right-Shoulder.
@ fplGamepadButtonType_DPadDown
DPad down.
@ fplGamepadButtonType_ActionA
Action-A.
@ fplGamepadButtonType_ActionX
Action-X.
@ fplGamepadButtonType_RightThumb
Right-Thumb.
@ fplGamepadButtonType_Back
Back.
@ fplGamepadButtonType_DPadLeft
DPad left.
@ fplGamepadButtonType_ActionB
Action-B.
@ fplGamepadButtonType_DPadUp
DPad up.
@ fplMouseButtonType_Middle
Middle mouse button.
@ fplMouseButtonType_MaxCount
Max mouse button count.
@ fplMouseButtonType_Right
Right mouse button.
@ fplMouseButtonType_Left
Left mouse button.
@ fplMouseButtonType_None
No mouse button.
@ fplGamepadEventType_StateChanged
Gamepad state updated.
@ fplGamepadEventType_Disconnected
Gamepad disconnected.
@ fplGamepadEventType_Connected
Gamepad connected.
@ fplGamepadEventType_None
No gamepad event.
@ fplKeyboardEventType_None
None key event type.
@ fplKeyboardEventType_Input
Character was entered.
@ fplKeyboardEventType_Button
Key button event.
@ fplEventType_None
None event type.
@ fplEventType_Keyboard
Keyboard event.
@ fplEventType_Window
Window event.
@ fplEventType_Mouse
Mouse event.
@ fplEventType_Gamepad
Gamepad event.
@ fplKeyboardModifierFlags_RAlt
Right alt key is down.
@ fplKeyboardModifierFlags_LAlt
Left alt key is down.
@ fplKeyboardModifierFlags_None
No modifiers.
@ fplKeyboardModifierFlags_NumLock
Numlock state is active.
@ fplKeyboardModifierFlags_RCtrl
Right ctrl key is down.
@ fplKeyboardModifierFlags_LShift
Left shift key is down.
@ fplKeyboardModifierFlags_ScrollLock
Scrolllock state is active.
@ fplKeyboardModifierFlags_RShift
Right shift key is down.
@ fplKeyboardModifierFlags_LSuper
Left super key is down.
@ fplKeyboardModifierFlags_RSuper
Right super key is down.
@ fplKeyboardModifierFlags_CapsLock
Capslock state is active.
@ fplKeyboardModifierFlags_LCtrl
Left ctrl key is down.
A structure containing the name and the id of the audio device.
char name[FPL_MAX_NAME_LENGTH]
Device name.
fplAudioDeviceID id
Device id.
A structure containing audio settings, such as format, device info, callbacks, backend,...
fplAudioDeviceInfo targetDevice
The target device.
fpl_b32 startAuto
Start playing of audio samples after platform initialization automatically.
void * userData
User data pointer for client read callback.
fpl_audio_client_read_callback * clientReadCallback
The callback for retrieving audio data from the client.
fpl_b32 stopAuto
Stop playing of audio samples before platform release automatically.
fplAudioBackendType backend
The targeted backend.
fplAudioTargetFormat targetFormat
The target format.
fplSpecificAudioSettings specific
Specific settings.
A structure that containing the processor capabilities, like MMX,SSE,AVX etc.
fpl_b32 hasAVX
Is AVX supported.
fpl_b32 hasMMX
Is MMX supported.
fpl_b32 hasSSE2
Is SSE-2 supported.
fpl_b32 hasSSE3
Is SSE-3 supported.
fpl_b32 hasAVX512
Is AVX-512 supported.
fpl_b32 hasSSE
Is SSE supported.
fpl_b32 hasSSE4_1
Is SSE-4.1 supported.
fpl_b32 hasSSE4_2
Is SSE-4.2 supported.
fpl_b32 hasFMA3
Is FMA-3 supported.
fpl_b32 hasSSSE3
Is SSSE-3 supported.
fpl_b32 hasAVX2
Is AVX-2 supported.
The condition variable structure.
fpl_b32 isValid
Is it valid.
fplInternalConditionVariable internalHandle
The internal condition handle.
A structure containing the title and options for the console.
char title[FPL_MAX_NAME_LENGTH]
Console title.
A struct containing informations about a display.
char id[FPL_MAX_NAME_LENGTH]
ID of the display.
fplWindowSize virtualSize
Virtual size in screen coordinates.
fpl_b32 isPrimary
Is primary display.
fplWindowPosition virtualPosition
Virtual position in screen coordinates.
fplWindowSize physicalSize
Actual absolute size in screen coordinates.
A structure containing one set of display mode settings, such as size, refresh rate,...
uint32_t colorBits
Color depth in bits per pixel.
uint32_t height
The height in screen coordinates.
uint32_t width
The width in screen coordinates.
uint32_t refreshRate
The refresh rate in Hz.
A structure containing the internal handle to a dynamic library.
fpl_b32 isValid
Library opened successfully.
fplInternalDynamicLibraryHandle internalHandle
Internal library handle.
A structure containing event data for all event types (Window, Keyboard, Mouse, etc....
fplMouseEvent mouse
Mouse event data.
fplKeyboardEvent keyboard
Keyboard event data.
fplWindowEvent window
Window event data.
fplGamepadEvent gamepad
Gamepad event data.
fplEventType type
Event type.
A structure containing the informations for a file or directory (name, type, attributes,...
fplInternalFileRootInfo internalRoot
Internal root info.
fplFileEntryType type
Entry type.
fplFilePermissions permissions
Permissions.
size_t size
Size (Zero when not a file)
fplInternalFileEntryHandle internalHandle
Internal filehandle.
char name[FPL_MAX_FILENAME_LENGTH]
Name.
fplFileTimeStamps timeStamps
Time stamps.
fplFileAttributeFlags attributes
Attributes.
The filehandle structure.
fplInternalFileHandle internalHandle
Internal filehandle.
fpl_b32 isValid
File opened successfully.
A structure containing filestamps for creation/access/modify date.
fplFileTimeStamp creationTime
Creation timestamp.
fplFileTimeStamp lastAccessTime
Last access timestamp.
fplFileTimeStamp lastModifyTime
Last modify timestamp.
A structure containing gamepad event data (Type, Device, State, etc.)
const char * deviceName
Device name of the controller.
uint32_t deviceIndex
Gamepad device index.
fplGamepadEventType type
Gamepad event type.
fplGamepadState state
Full gamepad state.
A structure containing the entire gamepad state.
fplGamepadButton rightThumb
Analog right thumb button.
fplGamepadButton leftShoulder
Left shoulder button.
float leftTrigger
Analog left trigger in range (0.0 to 1.0f)
fplGamepadButton buttons[14]
All gamepad buttons.
fpl_b32 isActive
Is this device active, which means are any buttons pressed or positions stick changed.
fpl_b32 isConnected
Is device physical connected.
float leftStickX
Analog left thumb X in range (-1.0 to 1.0f)
fplGamepadButton back
Back button.
float rightStickY
Analog right thumb Y in range (-1.0 to 1.0f)
float leftStickY
Analog left thumb Y in range (-1.0 to 1.0f)
float rightTrigger
Analog right trigger in range (0.0 to 1.0f)
fplGamepadButton dpadUp
Digital button up.
fplGamepadButton dpadRight
Digital button right.
float rightStickX
Analog right thumb X in range (-1.0 to 1.0f)
fplGamepadButton start
Start button.
fplGamepadButton actionX
Action button X.
fplGamepadButton actionA
Action button A.
const char * deviceName
Device name.
fplGamepadButton dpadDown
Digital button down.
fplGamepadButton rightShoulder
Right shoulder button.
fplGamepadButton dpadLeft
Digital button left.
fplGamepadButton actionB
Action button B.
fplGamepadButton actionY
Action button Y.
fplGamepadButton leftThumb
Analog left thumb button.
A struct containing the full state for all gamepad devices.
fplGamepadState deviceStates[FPL_MAX_GAMEPAD_STATE_COUNT]
Device states.
A union that contains graphics api settings.
fplOpenGLSettings opengl
OpenGL settings.
fplVulkanSettings vulkan
Vulkan settings.
int dummy
Field for preventing union to be empty.
A structure containing data for working with a image source.
uint32_t width
Width in pixels.
fplImageType type
Image type.
const uint8_t * data
Pointer to the source data.
uint32_t height
Height in pixels.
A structure containing the internal root file informations.
const char * rootPath
Saved root path.
const char * filter
Saved filter wildcard.
A structure containing keyboard event data (Type, Keycode, Mapped key, etc.)
uint64_t keyCode
Raw ascii key code or 32-bit unicode for text input.
fplKeyboardEventType type
Keyboard event type.
fplKey mappedKey
Mapped key.
fplButtonState buttonState
Button state.
fplKeyboardModifierFlags modifiers
Keyboard modifiers.
A struct containing the full keyboard state.
fplButtonState buttonStatesMapped[FPL_MAX_KEYBOARD_STATE_COUNT]
Mapped button states.
fplKeyboardModifierFlags modifiers
Modifier flags.
fpl_b32 keyStatesRaw[FPL_MAX_KEYBOARD_STATE_COUNT]
Key states.
A structure containing log settings.
fplLogWriter writers[1]
Single writer.
fplLogLevel maxLevel
Maximum log level.
fpl_b32 isInitialized
Is initialized (When set to false all values will be set to default values)
A structure containing console logging properties.
int dummy
Field for preventing struct to be empty.
A structure containing properties custom logging properties.
fpl_log_func_callback * callback
User callback.
A structure containing log writer settings.
fplLogWriterFlags flags
Flags.
fplLogWriterConsole console
Console.
fplLogWriterCustom custom
Custom.
A structure for setting up memory allocation usage.
fpl_memory_release_callback * releaseCallback
Callback for releasing memory.
void * userData
User data passed through callbacks.
fpl_memory_allocate_callback * allocateCallback
Callback for allocating memory.
fplMemoryAllocationMode mode
Memory allocation mode.
size_t size
The size of the allocated memory.
void * base
The base pointer.
A structure that contains informations about current memory usage.
uint64_t installedPhysicalSize
Size of physical installed memory in bytes.
uint64_t freePageCount
Number of available memory pages.
uint64_t totalCacheSize
Total size of memory cache in bytes.
uint64_t totalPhysicalSize
Total size of physical memory in bytes (May be less than size of installed physical memory,...
uint64_t totalPageCount
Total number of memory pages.
uint64_t freePhysicalSize
Available physical memory in bytes.
uint64_t pageSize
Page size in bytes.
uint64_t freeCacheSize
Available size of the memory cache in bytes.
A structure for setting up memory settings for dynamic and temporary allocations.
fplMemoryAllocationSettings dynamic
Dynamic memory allocation settings.
fplMemoryAllocationSettings temporary
Temporary memory allocation settings.
A structure containing mouse event data (Type, Button, Position, etc.)
fplMouseButtonType mouseButton
Mouse button.
int32_t mouseX
Mouse X-Position.
fplMouseEventType type
Mouse event type.
fplButtonState buttonState
Button state.
int32_t mouseY
Mouse Y-Position.
float wheelDelta
Mouse wheel delta.
A struct containing the full mouse state.
int32_t y
Y-Position in pixels.
fplButtonState buttonStates[fplMouseButtonType_MaxCount]
Mouse button states mapped to fplMouseButtonType.
int32_t x
X-Position in pixels.
The mutex handle structure.
fplInternalMutexHandle internalHandle
The internal mutex handle.
fpl_b32 isValid
Is it valid.
A structure that contains the version information for the operating system.
char osName[FPL_MAX_NAME_LENGTH]
Name of the operating system.
char distributionName[FPL_MAX_NAME_LENGTH]
Name of the distribution (May be empty)
fplVersionInfo osVersion
Version of the operating system.
fplVersionInfo distributionVersion
Version of the distribution (May be empty)
A structure that contains OpenGL video settings.
uint32_t minorVersion
Desired minor version.
const char * libraryFile
Custom OpenGL driver library file name/path (null = Default OpenGL library)
fplOpenGLCompabilityFlags compabilityFlags
Compability flags.
uint8_t multiSamplingCount
Multisampling count.
uint32_t majorVersion
Desired major version.
The semaphore handle structure.
fplInternalSemaphoreHandle internalHandle
The internal semaphore handle.
fpl_b32 isValid
Is it valid.
A structure containing settings, such as window, video, etc.
fplWindowSettings window
Window settings.
fplAudioSettings audio
Audio settings.
fplMemorySettings memory
Memory settings.
fplConsoleSettings console
Console settings.
fplInputSettings input
Input settings.
fplVideoSettings video
Video settings.
The signal handle structure.
fplInternalSignalHandle internalHandle
The internal signal handle.
fpl_b32 isValid
Is it valid.
The thread handle structure.
fplInternalThreadHandle internalHandle
The internal thread handle.
fplThreadParameters parameters
The initial fplThreadParameters.
volatile fpl_b32 isValid
Is this thread valid.
uint32_t id
The identifier of the thread.
volatile fplThreadState currentState
Thread state.
volatile fpl_b32 isStopping
Is this thread stopping.
Contains creation parameters for fplThreadCreateWithParameters()
size_t stackSize
The stack size in bytes or zero for using the default size.
fplThreadPriority priority
The fplThreadPriority.
fpl_run_thread_callback * runFunc
The fpl_run_thread_callback.
void * userData
The user data passed to the run callback.
A structure that contains version informations.
fplVersionNumberPart fix
Fix version.
fplVersionNumberPart build
Build version.
fplVersionNumberPart values[4]
Version number parts.
fplVersionNumberPart major
Major version.
fplVersionNumberPart minor
Minor version.
char fullName[FPL_MAX_NAME_LENGTH]
Full name.
A structure containing video backbuffer properties.
uint32_t * pixels
The 32-bit pixel top-down array, format: 0xAABBGGRR. Do not modify before WindowUpdate.
fplVideoRect outputRect
The output rectangle for displaying the backbuffer (Size may not match backbuffer size!...
size_t pixelStride
The size of one entire pixel with all 4 components in bytes. Do not modify, it will be set automatica...
uint32_t height
The height of the backbuffer in pixels. Do not modify, it will be set automatically.
size_t lineWidth
The width of one line in bytes. Do not modify, it will be set automatically.
uint32_t width
The width of the backbuffer in pixels. Do not modify, it will be set automatically.
fpl_b32 useOutputRect
Set this to true to actually use the output rectangle.
A structure defining a video rectangles position and size.
int32_t x
Left position in pixels.
int32_t height
Height in pixels.
int32_t y
Top position in pixels.
int32_t width
Width in pixels.
Stores the requirements for the Vulkan video backend.
const char * instanceExtensions[2]
The required instance extensions.
uint32_t instanceExtensionCount
The number of required instance extensions.
A structure that contains video settings such as backend, v-sync, API-settings, etc.
fplVideoBackendType backend
video backend type
fpl_b32 isAutoSize
Is backbuffer automatically resized. Usable only for software rendering!
fpl_b32 isVSync
Is vertical synchronization enabled. Usable only for hardware rendering!
fplGraphicsApiSettings graphics
Graphics API settings.
Stores the surface properties for the active video backend.
int dummy
Field for preventing union to be empty.
fplVideoWindow window
The video window.
fplVideoSurfaceVulkan vulkan
The Vulkan surface properties.
fplVideoSurfaceOpenGL opengl
The OpenGL surface properties.
Stores the surface properties for the OpenGL video backend.
void * renderingContext
The OpenGL rendering context (HGLRC or XRC)
Stores the surface properties for the Vulkan video backend.
void * surfaceKHR
The Vulkan Surface KHR (VkSurfaceKHR)
void * instance
The Vulkan Instance (VkInstance)
A structure that contains Vulkan video settings.
fplVersionInfo engineVersion
The engine version (Only required if fplVulkanSettings::instanceHandle is fpl_null)
fplVersionInfo apiVersion
The preferred Vulkan api version (Only required if fplVulkanSettings::instanceHandle is fpl_null)
fplVulkanValidationLayerMode validationLayerMode
The fplVulkanValidationLayerMode.
const char * appName
The application name (Only required if fplVulkanSettings::instanceHandle is fpl_null)
void * userData
User data passed to any callbacks.
void * instanceHandle
The vulkan instance (VkInstance), when null it will be automatically created.
fplVersionInfo appVersion
The application version (Only required if fplVulkanSettings::instanceHandle is fpl_null)
const char * engineName
The engine name (Only required if fplVulkanSettings::instanceHandle is fpl_null)
const char * libraryFile
Custom Vulkan driver library file name/path (null = Default Vulkan library)
fplVulkanValidationSeverity validationSeverity
The fplVulkanValidationSeverity.
const void * allocator
The vulkan allocator (VkAllocationCallbacks)
fplVulkanValidationLayerCallback * validationLayerCallback
The validation layer callback fplVulkanValidationLayerCallback.
A structure containing the window callbacks.
void * eventUserData
User data pointer for the event callback.
fpl_window_event_callback * eventCallback
Expose callback.
void * exposedUserData
User data pointer for the expose callback.
fpl_window_exposed_callback * exposedCallback
Expose callback.
A structure containing number and dropped files informations.
fplMemoryBlock internalMemory
The internal memory block.
size_t fileCount
Number of dropped in files.
const char ** files
File paths (Do not release this memory, its automatically released after the event is processed)
A structure containing window event data (Size, Position, etc.)
fplWindowSize size
Window size.
fplWindowDropFiles dropFiles
Drop files.
fplWindowEventType type
Window event type.
fplWindowPosition position
Window position.
A structure containing the position of a window.
int32_t left
Left position in screen coordinates.
int32_t top
Top position in screen coordinates.
A structure containing window settings, such as size, title etc.
fpl_b32 isFloating
Is floating.
fplWindowSize windowSize
Window size in screen coordinates.
fplWindowSize fullscreenSize
Fullscreen size in screen coordinates.
fpl_b32 isResizable
Is window resizable.
fpl_b32 isScreenSaverPrevented
Is screen saver prevented (true: prevents the screensaver to kick-in, false: system behavior)
fpl_b32 isMonitorPowerPrevented
Is monitor power change prevented (true: prevents the monitor for powering off automatically,...
fplColor32 background
The background fplColor32 for the window when using fplVideoBackendType_Software or fplVideoBackendTy...
fplWindowCallbacks callbacks
Window callbacks.
fpl_b32 isFullscreen
Is window in fullscreen mode.
fplImageSource icons[2]
Window icons (0 = Small, 1 = Large)
uint32_t fullscreenRefreshRate
Fullscreen refresh rate in Hz.
char title[FPL_MAX_NAME_LENGTH]
Window title.
fpl_b32 isDecorated
Is window decorated.
A structure containing the size of a window.
uint32_t width
Width in screen coordinates.
uint32_t height
Height in screen coordinates.
A union containing a id of the underlying backend.
int dummy
Field for preventing union to be empty.
A structure containing the 4-registers (EAX, EBX, ECX, EDX) for a CPU-Leaf.
uint32_t edx
The 32-bit EDX Register.
uint32_t ecx
The 32-bit ECX Register.
uint32_t eax
The 32-bit EAX Register.
uint32_t raw[4]
The raw 32-bit register array.
uint32_t ebx
The 32-bit EBX Register.
Defines a 32-bit color in format BGRA.
uint8_t a
The 8-bit alpha component.
uint32_t value
The 32-bit color value in format 0xBBGGRRAA.
uint8_t g
The 8-bit green component.
uint8_t r
The 8-bit red component.
uint8_t m[4]
The color components array, stored as B, G, R, A.
uint8_t b
The 8-bit blue component.
A union containing the file permissions (UMask)
uint8_t owner
Owner flags.
uint8_t group
Group flags.
A union containing the internal condition variable for any platform.
int dummy
Field for preventing union to be empty.
A union containing the library handle for any platform.
A union containing the internal filehandle for any platform.
A union containing the internal filehandle for any platform.
A union containing the internal mutex handle for any platform.
A union containing the internal semaphore handle for any platform.
A union containing the internal signal handle for any platform.
A union containing the thread handle for any platform.
A union containing backend specific audio settings.
int dummy
Field for preventing union to be empty.
A structure storing a timestamp, used for delta measurements only.
uint64_t unused
Field for preventing union to be empty.
Stores the video requirements for the desired video backend.
fplVideoRequirementsVulkan vulkan
The requirements for Vulkan backend.
Stores the video window handles.
int dummy
Field for preventing union to be empty.