1660#if defined(__cplusplus)
1667# if (__cplusplus >= 201103L)
1672# define FPL_IS_CPP11
1675# if (__cplusplus >= 201402L)
1680# define FPL_IS_CPP14
1683# if (__cplusplus >= 201703L)
1688# define FPL_IS_CPP17
1691# if (__cplusplus >= 202004L)
1696# define FPL_IS_CPP20
1698#elif defined(_MSC_VER)
1699# if (_MSC_VER >= 1900)
1706# if (_MSC_VER >= 1920)
1715 #error "This MSVC compiler does not support C99 or higher!"
1717#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
1724# if __STDC_VERSION__ >= 201112L
1732 #error "This C compiler is not supported!"
1740#if defined(__x86_64__) || defined(_M_X64) || defined(__amd64__)
1745# define FPL_ARCH_X64
1746#elif defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_)
1751# define FPL_ARCH_X86
1752#elif defined(__aarch64__) || defined(_M_ARM64)
1753# if defined(__APPLE__)
1758# define FPL_ARCH_APPLE_ARM64
1764# define FPL_ARCH_ARM64
1766#elif defined(__arm__) || defined(_M_ARM) || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7__) || defined(__armv7__)
1771# define FPL_ARCH_ARM32
1772#elif defined(__riscv) || defined(__riscv_xlen)
1777# define FPL_ARCH_RISCV
1778#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || defined(_ARCH_PPC64)
1783# define FPL_ARCH_POWERPC64
1784#elif defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
1789# define FPL_ARCH_POWERPC32
1790#elif defined(__mips__) || defined(__mips64) || defined(_MIPS_ARCH)
1795# define FPL_ARCH_MIPS
1796#elif defined(__sparc__) || defined(__sparcv9)
1801# define FPL_ARCH_SPARC
1803# error "This architecture is not supported!"
1811# define FPL__M_CPU_64BIT
1813# define FPL__M_CPU_32BIT
1815#elif defined(__GNUC__) || defined(__clang__)
1816# if defined(__LP64__) || defined(_LP64)
1817# define FPL__M_CPU_64BIT
1819# define FPL__M_CPU_32BIT
1821#elif defined(_MSC_VER)
1822# if defined(_WIN64) || defined(_M_X64) || defined(__x86_64__)
1823# define FPL__M_CPU_64BIT
1825# define FPL__M_CPU_32BIT
1827#elif defined(__APPLE__) || defined(__linux__) || defined(__unix__)
1828# if defined(__x86_64__) || defined(__aarch64__) || defined(__ppc64__)
1829# define FPL__M_CPU_64BIT
1831# define FPL__M_CPU_32BIT
1834# if (defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8) || (sizeof(void *) == 8)
1835# define FPL__M_CPU_64BIT
1837# define FPL__M_CPU_32BIT
1841#if defined(FPL__M_CPU_64BIT)
1846# define FPL_CPU_64BIT
1847#elif defined(FPL__M_CPU_32BIT)
1852# define FPL_CPU_32BIT
1861#if defined(__clang__)
1866# define FPL_COMPILER_CLANG
1867#elif defined(__INTEL_COMPILER)
1872# define FPL_COMPILER_INTEL
1873#elif defined(__MINGW32__) || defined(__MINGW64__)
1878# define FPL_COMPILER_MINGW
1879#elif defined(__CC_ARM)
1884# define FPL_COMPILER_ARM
1885#elif defined(__GNUC__)
1890# define FPL_COMPILER_GCC
1891#elif defined(_MSC_VER)
1896# define FPL_COMPILER_MSVC
1897#elif defined(__APPLE__)
1902# define FPL_COMPILER_APPLE_CLANG
1903#elif defined(__BORLANDC__)
1908# define FPL_COMPILER_BORLAND
1909#elif defined(__TCC__)
1914# define FPL_COMPILER_TCC
1915#elif defined(__DMC__)
1920# define FPL_COMPILER_DMC
1921#elif defined(__CSMC__)
1926# define FPL_COMPILER_CSMC
1927#elif defined(__LINARO__)
1932# define FPL_COMPILER_LINARO
1934 #error "This compiler is not supported!"
1944#if defined(_WIN32) || defined(_WIN64)
1945# define FPL_PLATFORM_WINDOWS
1946# define FPL_PLATFORM_NAME "Windows"
1947#elif defined(__ANDROID__)
1948# define FPL_PLATFORM_ANDROID
1949# define FPL_PLATFORM_NAME "Android"
1950# define FPL_SUBPLATFORM_POSIX
1951# define FPL_SUBPLATFORM_STD_STRINGS
1952# define FPL_SUBPLATFORM_STD_CONSOLE
1953#elif defined(__linux__) || defined(__gnu_linux__)
1954# define FPL_PLATFORM_LINUX
1955# define FPL_PLATFORM_NAME "Linux"
1956# define FPL_SUBPLATFORM_POSIX
1957# define FPL_SUBPLATFORM_X11
1958# define FPL_SUBPLATFORM_STD_STRINGS
1959# define FPL_SUBPLATFORM_STD_CONSOLE
1960#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__bsdi__)
1962# define FPL_PLATFORM_UNIX
1963# define FPL_PLATFORM_NAME "BSD"
1964# define FPL_SUBPLATFORM_BSD
1965# define FPL_SUBPLATFORM_POSIX
1966# define FPL_SUBPLATFORM_X11
1967# define FPL_SUBPLATFORM_STD_STRINGS
1968# define FPL_SUBPLATFORM_STD_CONSOLE
1969#elif defined(unix) || defined(__unix) || defined(__unix__)
1970# define FPL_PLATFORM_UNIX
1971# define FPL_PLATFORM_NAME "Unix"
1972# define FPL_SUBPLATFORM_POSIX
1973# define FPL_SUBPLATFORM_X11
1974# define FPL_SUBPLATFORM_STD_STRINGS
1975# define FPL_SUBPLATFORM_STD_CONSOLE
1977# error "This platform is not supported!"
1983#if defined(FPL_COMPILER_CLANG) || defined(FPL_COMPILER_GCC)
1984# define fpl__m_Asm __asm__
1985#elif defined(FPL_COMPILER_MSVC)
1986# define fpl__m_Asm __asm
1988# define fpl__m_Asm asm
1995#define fplAsm fpl__m_Asm
2000#if defined(FPL_COMPILER_MSVC)
2001# define fpl__MinAlignment 8
2002#elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
2003# if defined(FPL_CPU_64BIT)
2004# define fpl__MinAlignment 8
2006# define fpl__MinAlignment 4
2009# define fpl__MinAlignment 8
2017#define fplMinAlignment fpl__MinAlignment
2022#if defined(FPL_IS_CPP11)
2023# define fpl__m_AlignAs(N) alignas(N)
2024#elif defined(FPL_COMPILER_MSVC)
2025# define fpl__m_AlignAs(N) __declspec(align(N))
2026#elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
2027# define fpl__m_AlignAs(N) __attribute__((aligned(N)))
2029# define fpl__m_AlignAs(N)
2038#define fplAlignAs(N) fpl__m_AlignAs(((N) < fplMinAlignment ? fplMinAlignment : (N)))
2042#if defined(FPL_SUBPLATFORM_POSIX)
2043# if !defined(_XOPEN_SOURCE)
2044# define _XOPEN_SOURCE 600
2046# if !defined(_DEFAULT_SOURCE)
2047# define _DEFAULT_SOURCE 1
2049# if !defined(__STDC_FORMAT_MACROS)
2050# define __STDC_FORMAT_MACROS
2052# if !defined(__STDC_LIMIT_MACROS)
2053# define __STDC_LIMIT_MACROS
2055# if !defined(_LARGEFILE_SOURCE)
2056# define _LARGEFILE_SOURCE
2058# if !defined(_LARGEFILE64_SOURCE)
2059# define _LARGEFILE64_SOURCE
2061# if !defined(_FILE_OFFSET_BITS)
2062# define _FILE_OFFSET_BITS 64
2066#if defined(FPL_PLATFORM_LINUX)
2067# define FPL__INCLUDE_ALLOCA
2069# define FPL__INCLUDE_MALLOC
2073#if defined(FPL_PLATFORM_WINDOWS) && defined(FPL_COMPILER_MINGW)
2074# if !defined(_WIN32_WINNT)
2075# define _WIN32_WINNT 0x0600
2090#define fpl_globalvar static
2092#define fpl_localvar static
2094#define fpl_internal static
2096#define fpl_inline inline
2098#define fpl_internal_inline inline
2100#if defined(FPL_IS_CPP)
2103# define fpl_extern extern
2109#if defined(_WIN32) || defined(__CYGWIN__)
2111# define fpl__m_dllexport __attribute__ ((dllexport))
2112# define fpl__m_dllimport __attribute__ ((dllimport))
2114# define fpl__m_dllexport __declspec(dllexport)
2115# define fpl__m_dllimport __declspec(dllimport)
2117# define fpl__m_dlllocal
2120# define fpl__m_dllimport __attribute__((visibility("default")))
2121# define fpl__m_dllexport __attribute__((visibility("default")))
2122# define fpl__m_dlllocal __attribute__((visibility("hidden")))
2124# define fpl__m_dllimport
2125# define fpl__m_dllexport
2126# define fpl__m_dlllocal
2134#define fpl_dllimport fpl__m_dllimport
2139#define fpl_dllexport fpl__m_dllexport
2144#define fpl_dlllocal fpl__m_dlllocal
2149#if defined(FPL_API_AS_PRIVATE)
2150# define fpl__m_api static
2151#elif defined(FPL_DLLEXPORT)
2152# define fpl__m_api fpl_dllexport
2153#elif defined(FPL_DLLIMPORT)
2154# define fpl__m_api fpl_dllimport
2156# define fpl__m_api fpl_extern
2163#define fpl_api fpl__m_api
2171#if defined(FPL_IS_CPP)
2172# define fpl__m_platform_api extern "C" fpl_api
2173# define fpl__m_common_api extern "C" fpl_api
2175# define fpl__m_platform_api fpl_api
2176# define fpl__m_common_api fpl_api
2183#define fpl_platform_api fpl__m_platform_api
2188#define fpl_common_api fpl__m_common_api
2193#if defined(FPL_COMPILER_MSVC)
2194# define fpl__m_force_inline __forceinline
2195# define fpl__m_no_inline __declspec(noinline)
2196#elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
2197# define fpl__m_force_inline __attribute__((__always_inline__)) inline
2198# define fpl__m_no_inline __attribute__((noinline))
2200# define fpl__m_force_inline inline
2201# define fpl__m_no_inline
2208#define fpl_force_inline fpl__m_force_inline
2213#define fpl_no_inline fpl__m_no_inline
2220#if defined(FPL_NO_CRT)
2221# if defined(FPL_SUBPLATFORM_STD_CONSOLE)
2222# undef FPL_SUBPLATFORM_STD_CONSOLE
2224# if defined(FPL_SUBPLATFORM_STD_STRINGS)
2225# undef FPL_SUBPLATFORM_STD_STRINGS
2227# if !defined(FPL_USERFUNC_vsnprintf)
2228# error "You need to provide a replacement for vsnprintf() by defining FPL_USERFUNC_vsnprintf!"
2237#if defined(FPL_APPTYPE_CONSOLE) && defined(FPL_APPTYPE_WINDOW)
2238# error "Its now allowed to define both FPL_APPTYPE_CONSOLE and FPL_APPTYPE_WINDOW!"
2240#if defined(FPL_NO_CRT)
2241# if !defined(FPL_APPTYPE_CONSOLE) && !defined(FPL_APPTYPE_WINDOW)
2242# error "In 'No-CRT' mode you need to define either FPL_APPTYPE_CONSOLE or FPL_APPTYPE_WINDOW manually!"
2244#elif !defined(FPL_NO_APPTYPE) && !(defined(FPL_APPTYPE_CONSOLE) || defined(FPL_APPTYPE_WINDOW))
2245# if !defined(FPL_NO_WINDOW)
2247# define FPL_APPTYPE_WINDOW
2250# define FPL_APPTYPE_CONSOLE
2257#if defined(FPL_IMPLEMENTATION) && !defined(FPL_NO_ENTRYPOINT)
2258# define FPL_ENTRYPOINT
2264#if defined(FPL_DEBUG)
2265# define FPL__ENABLE_DEBUG
2266#elif defined(FPL_RELEASE)
2267# define FPL__ENABLE_RELEASE
2273#if defined(FPL_COMPILER_MSVC)
2275# if !defined(FPL__ENABLE_DEBUG) && !defined(FPL__ENABLE_RELEASE)
2276# if defined(_DEBUG) || (!defined(NDEBUG))
2277# define FPL__ENABLE_DEBUG
2279# define FPL__ENABLE_RELEASE
2284# define FPL__M_FUNCTION_NAME __FUNCTION__
2287# if defined(FPL_APPTYPE_WINDOW)
2288# pragma comment(linker, "/SUBSYSTEM:WINDOWS")
2289# elif defined(FPL_APPTYPE_CONSOLE)
2290# pragma comment(linker, "/SUBSYSTEM:CONSOLE")
2294# pragma comment(lib, "kernel32.lib")
2297# define FPL__M_FUNCTION_NAME __FUNCTION__
2301#if !defined(FPL__ENABLE_DEBUG) && !defined(FPL__ENABLE_RELEASE)
2302# define FPL__ENABLE_DEBUG
2306#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
2307# define FPL__M_IS_IDE 1
2309# define FPL__M_IS_IDE 0
2317#define FPL_IS_IDE FPL__M_IS_IDE
2323#define FPL_FUNCTION_NAME FPL__M_FUNCTION_NAME
2362#if defined(__AVX512F__)
2363# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_AVX512
2364#elif defined(__AVX2__)
2365# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_AVX2
2366#elif defined(__AVX__)
2367# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_AVX
2368#elif defined(__SSE4_2__)
2369# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_SSE4_2
2370#elif defined(__SSE4_1__)
2371# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_SSE4_1
2372#elif defined(__SSSE3__)
2373# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_SSE3
2374#elif defined(__SSE3__)
2375# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_SSSE3
2376#elif defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) || defined(FPL_ARCH_X64)
2377# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_SSE2
2378#elif defined(__SSE__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)
2379# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_SSE
2380#elif defined(FPL_ARCH_X86)
2381# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_IA32
2383# define FPL__M_X86_CPU_INSTR_SET_LEVEL fplX86InstructionSetLevel_None
2390#define FPL_X86_CPU_INSTR_SET_LEVEL FPL__M_X86_CPU_INSTR_SET_LEVEL
2395#if !defined(FPL_NO_ASSERTIONS)
2396# if !defined(FPL_FORCE_ASSERTIONS)
2397# if defined(FPL__ENABLE_DEBUG)
2398# define FPL__ENABLE_ASSERTIONS
2401# define FPL__ENABLE_ASSERTIONS
2404#if defined(FPL__ENABLE_ASSERTIONS)
2405# if !defined(FPL_NO_C_ASSERT) && !defined(FPL_NO_CRT)
2406# define FPL__ENABLE_C_ASSERT
2413#if defined(__has_include)
2414# define fpl__m_HasInclude(inc) __has_include(inc)
2416# define fpl__m_HasInclude(inc) (1)
2425#define fplHasInclude(inc) fpl__m_HasInclude(inc)
2430#if !defined(FPL_NO_WINDOW) && !defined(FPL_APPTYPE_CONSOLE)
2431# define FPL__SUPPORT_WINDOW
2437#if !defined(FPL_NO_VIDEO)
2438# define FPL__SUPPORT_VIDEO
2440#if defined(FPL__SUPPORT_VIDEO)
2441# if !defined(FPL_NO_VIDEO_OPENGL)
2442# define FPL__SUPPORT_VIDEO_OPENGL
2444# if !defined(FPL_NO_VIDEO_VULKAN)
2445# define FPL__SUPPORT_VIDEO_VULKAN
2447# if !defined(FPL_NO_VIDEO_SOFTWARE)
2448# define FPL__SUPPORT_VIDEO_SOFTWARE
2455#if !defined(FPL_NO_AUDIO)
2457# define FPL__SUPPORT_AUDIO
2459#if defined(FPL__SUPPORT_AUDIO)
2460# if !defined(FPL_NO_AUDIO_DIRECTSOUND) && defined(FPL_PLATFORM_WINDOWS)
2461# define FPL__SUPPORT_AUDIO_DIRECTSOUND
2463# if !defined(FPL_NO_AUDIO_ALSA) && defined(FPL_PLATFORM_LINUX)
2464# if fplHasInclude(<alsa/asoundlib.h>)
2465# define FPL__SUPPORT_AUDIO_ALSA
2467# warning "FPL-Warning: ALSA audio development library is missing. Please install 'libasound2-dev' and try again!"
2475#if !defined(FPL__SUPPORT_WINDOW)
2476# if defined(FPL_SUBPLATFORM_X11)
2477# undef FPL_SUBPLATFORM_X11
2480# if defined(FPL__SUPPORT_VIDEO)
2481# undef FPL__SUPPORT_VIDEO
2483# if defined(FPL__SUPPORT_VIDEO_OPENGL)
2484# undef FPL__SUPPORT_VIDEO_OPENGL
2486# if defined(FPL__SUPPORT_VIDEO_VULKAN)
2487# undef FPL__SUPPORT_VIDEO_VULKAN
2489# if defined(FPL__SUPPORT_VIDEO_SOFTWARE)
2490# undef FPL__SUPPORT_VIDEO_SOFTWARE
2497#if defined(FPL__SUPPORT_WINDOW)
2498# define FPL__ENABLE_WINDOW
2501#if defined(FPL__SUPPORT_VIDEO)
2502# define FPL__ENABLE_VIDEO
2503# if defined(FPL__SUPPORT_VIDEO_OPENGL)
2504# define FPL__ENABLE_VIDEO_OPENGL
2506# if defined(FPL__SUPPORT_VIDEO_VULKAN)
2507# define FPL__ENABLE_VIDEO_VULKAN
2509# if defined(FPL__SUPPORT_VIDEO_SOFTWARE)
2510# define FPL__ENABLE_VIDEO_SOFTWARE
2514#if defined(FPL__SUPPORT_AUDIO)
2515# define FPL__ENABLE_AUDIO
2516# if defined(FPL__SUPPORT_AUDIO_DIRECTSOUND)
2517# define FPL__ENABLE_AUDIO_DIRECTSOUND
2519# if defined(FPL__SUPPORT_AUDIO_ALSA)
2520# define FPL__ENABLE_AUDIO_ALSA
2524#if defined(FPL_LOGGING)
2525# define FPL__ENABLE_LOGGING
2526# if defined(FPL_LOG_MULTIPLE_WRITERS)
2527# define FPL__ENABLE_LOG_MULTIPLE_WRITERS
2541#if defined(FPL__ENABLE_ASSERTIONS)
2542# if defined(FPL__ENABLE_C_ASSERT) && !defined(FPL_FORCE_ASSERTIONS)
2543# define FPL__INCLUDE_ASSERT
2544# define fpl__m_Assert(exp) assert(exp)
2545# if defined(__cplusplus)
2546# define fpl__m_StaticAssert(exp) static_assert(exp, "fpl_static_assert")
2549# define fpl__m_Assert(exp) if(!(exp)) {*(int *)0 = 0;}
2551# if !defined(fpl__m_StaticAssert)
2552# define FPL__M_STATICASSERT_0(exp, line, counter) \
2553 int fpl__ct_assert_##line_##counter(int ct_assert_failed[(exp)?1:-1])
2554# define fpl__m_StaticAssert(exp) \
2555 FPL__M_STATICASSERT_0(exp, __LINE__, __COUNTER__)
2558# define fpl__m_Assert(exp)
2559# define fpl__m_StaticAssert(exp)
2567#define fplAssert(exp) fpl__m_Assert(exp)
2574#define fplStaticAssert(exp) fpl__m_StaticAssert(exp)
2581#define fplAlwaysAssert(exp) if(!(exp)) {*(int *)0 = 0;}
2588#define fplAssertPtr(ptr) fpl__m_Assert((ptr) != fpl_null)
2594#if defined(__has_builtin)
2595# if __has_builtin(__builtin_debugtrap)
2596# define fpl__m_DebugBreak() __builtin_debugtrap()
2597# elif __has_builtin(__debugbreak)
2598# define fpl__m_DebugBreak() __debugbreak()
2601#if !defined(fpl__m_DebugBreak)
2602# if defined(FPL_COMPILER_MSVC) || defined(FPL_COMPILER_INTEL)
2603# define fpl__m_DebugBreak() __debugbreak()
2604# elif defined(FPL_COMPILER_ARM)
2605# define fpl__m_DebugBreak() __breakpoint(42)
2606# elif defined(FPL_ARCH_X86) || defined(FPL_ARCH_X64)
2608# elif defined(__thumb__)
2610# elif defined(FPL_ARCH_ARM64)
2612# elif defined(FPL_ARCH_ARM32)
2614# elif defined(FPL_COMPILER_GCC)
2615# define fpl__m_DebugBreak() __builtin_trap()
2617# define FPL__INCLUDE_SIGNAL
2618# if defined(SIGTRAP)
2619# define fpl__m_DebugBreak() raise(SIGTRAP)
2621# define fpl__m_DebugBreak() raise(SIGABRT)
2630#define fplDebugBreak() fpl__m_DebugBreak()
2644#if !defined(FPL_NO_MEMORY_MACROS) || defined(FPL_FORCE_MEMORY_MACROS)
2645# define FPL__ENABLE_MEMORY_MACROS
2658#if defined(FPL__INCLUDE_ASSERT)
2661#if defined(FPL__INCLUDE_SIGNAL)
2664#if defined(FPL__INCLUDE_MALLOC)
2667#if defined(FPL__INCLUDE_ALLOCA)
2670#if !defined(FPL_NO_CRT)
2675#if !defined(UINT32_MAX)
2677# define UINT32_MAX (0xFFFFFFFFU)
2681#if defined(FPL_IS_CPP11)
2682# define fpl__m_null nullptr
2684# define fpl__m_null NULL
2686# define fpl__m_null 0
2693#define fpl_null fpl__m_null
2707#if defined(FPL_CPU_64BIT)
2710#elif defined(FPL_CPU_32BIT)
2716#error "Unsupported Char Size, expect 8 bits"
2732#define FPL_NOT_IMPLEMENTED {*(int *)0 = 0xBAD;}
2734#if defined(FPL_IS_C99)
2735# define fpl__m_ZeroInit {0}
2736# define fpl__m_StructSet(ptr, type, value) *(ptr) = (type)value
2737# define fpl__m_StructInit(type, ...) (type){__VA_ARGS__}
2738# define fpl__m_StructField(type, name, ...) .name = __VA_ARGS__
2740# define fpl__m_ZeroInit {}
2741# define fpl__m_StructSet(ptr, type, value) *(ptr) = value
2742# define fpl__m_StructInit(type, ...) {__VA_ARGS__}
2743# define fpl__m_StructField(type, name, ...) __VA_ARGS__
2751#define fplZeroInit fpl__m_ZeroInit
2760#define fplStructSet fpl__m_StructSet
2769#define fplStructInit fpl__m_StructInit
2779#define fplStructField fpl__m_StructField
2788#define fplGetAlignmentOffset(value, alignment) ( (((alignment) > 1) && (((value) & ((alignment) - 1)) != 0)) ? ((alignment) - ((value) & (alignment - 1))) : 0)
2797#define fplGetAlignedSize(size, alignment) (((size) > 0 && (alignment) > 0) ? ((size) + fplGetAlignmentOffset(size, alignment)) : (size))
2806#define fplIsAligned(ptr, alignment) (((uintptr_t)(const void *)(ptr)) % (alignment) == 0)
2814#define fplIsPowerOfTwo(value) (((value) != 0) && (((value) & (~(value) + 1)) == (value)))
2823#define fplIsBitSet(value, bit) (((value) >> (bit)) & 0x1)
2831#define fplKiloBytes(value) (((value) * 1024ull))
2839#define fplMegaBytes(value) ((fplKiloBytes(value) * 1024ull))
2847#define fplGigaBytes(value) ((fplMegaBytes(value) * 1024ull))
2855#define fplTeraBytes(value) ((fplGigaBytes(value) * 1024ull))
2863typedef enum fplEndianessType {
2865 fplEndianessType_Little = 0x04030201,
2867 fplEndianessType_Big = 0x01020304,
2872 unsigned char bytes[4];
2878fpl_globalvar const fplEndianess fpl__global_endianessOrder = { 1, 2, 3, 4 };
2887#define fplIsBigEndian() (fpl__global_endianessOrder.value == fplEndianessType_Big)
2894#define fplIsLittleEndian() (fpl__global_endianessOrder.value == fplEndianessType_Little)
2901#define fplGetEndianess32() (fpl__global_endianessOrder.value)
2908#define fplClearStruct(ptr) fplMemoryClear((void *)(ptr), sizeof(*(ptr)))
2916#define fplCopyStruct(src, dst) fplMemoryCopy(src, sizeof(*(src)), dst)
2921#if defined(_countof)
2922# define fpl__m_ArrayCount(arr) _countof(arr)
2923#elif defined(ARRAY_SIZE)
2924# define fpl__m_ArrayCount(arr) ARRAY_SIZE(arr)
2926# define fpl__m_ArrayCount(arr) (sizeof(arr) / sizeof((arr)[0]))
2935#define fplArrayCount(arr) fpl__m_ArrayCount(arr)
2944#define fplOffsetOf(type, field) ((size_t)(&(((type*)(0))->field)))
2953#define fplMin(a, b) ((a) < (b) ? (a) : (b))
2962#define fplMax(a, b) ((a) > (b) ? (a) : (b))
2964#if defined(FPL_PLATFORM_WINDOWS)
2965# define fpl__m_StackAllocate(size) _alloca(size)
2967# define fpl__m_StackAllocate(size) alloca(size)
2977#define fplStackAllocate(size) fpl__m_StackAllocate(size)
2981#if defined(FPL_IS_CPP)
2982# define FPL__M_ENUM_AS_FLAGS_OPERATORS(etype) \
2983 inline etype operator | (etype a, etype b) { \
2984 return static_cast<etype>(static_cast<int>(a) | static_cast<int>(b)); \
2986 inline etype& operator |= (etype &a, etype b) { \
2989 inline etype operator & (etype a, etype b) { \
2990 return static_cast<etype>(static_cast<int>(a) & static_cast<int>(b)); \
2992 inline etype& operator &= (etype &a, etype b) { \
2995 inline etype operator ~ (etype a) { \
2996 return static_cast<etype>(~static_cast<int>(a)); \
2998 inline etype operator ^ (etype a, etype b) { \
2999 return static_cast<etype>(static_cast<int>(a) ^ static_cast<int>(b)); \
3001 inline etype& operator ^= (etype &a, etype b) { \
3005# define FPL__M_ENUM_AS_FLAGS_OPERATORS(etype)
3013#define FPL_ENUM_AS_FLAGS_OPERATORS(type) FPL__M_ENUM_AS_FLAGS_OPERATORS(type)
3020#if !defined(FPL_NO_PLATFORM_INCLUDES) && !defined(FPL__HAS_PLATFORM_INCLUDES)
3021# define FPL__HAS_PLATFORM_INCLUDES
3023# if defined(FPL_PLATFORM_WINDOWS)
3025# if !defined(NOMINMAX)
3029# if !defined(WIN32_LEAN_AND_MEAN)
3030# define WIN32_LEAN_AND_MEAN 1
3034# include <windows.h>
3035# if _WIN32_WINNT < 0x0600
3036# error "Windows Vista or higher required!"
3040# if defined(FPL_SUBPLATFORM_POSIX)
3041# include <pthread.h>
3043# include <semaphore.h>
3047# if defined(FPL_SUBPLATFORM_X11)
3049# include <X11/Xlib.h>
3050# include <X11/Xutil.h>
3051# include <X11/Xatom.h>
3059#if !defined(FPL__HAS_PLATFORM_INCLUDES) || defined(FPL_OPAQUE_HANDLES)
3061# if defined(FPL_PLATFORM_WINDOWS)
3064typedef struct fpl__Win32Guid {
3071typedef void *fpl__Win32Handle;
3073typedef fpl__Win32Handle fpl__Win32InstanceHandle;
3075typedef fpl__Win32Handle fpl__Win32LibraryHandle;
3077typedef fpl__Win32Handle fpl__Win32FileHandle;
3079typedef fpl__Win32Handle fpl__Win32ThreadHandle;
3081typedef uint64_t fpl__Win32MutexHandle[16];
3083typedef fpl__Win32Handle fpl__Win32SignalHandle;
3085typedef void *fpl__Win32ConditionVariable;
3087typedef fpl__Win32Handle fpl__Win32SemaphoreHandle;
3089typedef fpl__Win32Handle fpl__Win32WindowHandle;
3091typedef fpl__Win32Handle fpl__Win32DeviceContext;
3093typedef fpl__Win32Handle fpl__Win32RenderingContext;
3095typedef union fpl__Win32LargeInteger {
3104} fpl__Win32LargeInteger;
3108# if defined(FPL_SUBPLATFORM_POSIX)
3111typedef void *fpl__POSIXLibraryHandle;
3113typedef int fpl__POSIXFileHandle;
3115typedef void *fpl__POSIXDirHandle;
3117typedef uint64_t fpl__POSIXThreadHandle;
3119typedef uint64_t fpl__POSIXMutexHandle[16];
3121typedef uint64_t fpl__POSIXSemaphoreHandle[8];
3123typedef uint64_t fpl__POSIXConditionVariable[16];
3127# if defined(FPL_SUBPLATFORM_X11)
3132typedef void *fpl__X11Display;
3135typedef int fpl__X11Window;
3137typedef void *fpl__X11Visual;
3139typedef void *fpl__X11GC;
3141typedef void *fpl__X11Image;
3143typedef void *fpl__GLXContext;
3147# if defined(FPL_PLATFORM_LINUX)
3150typedef int fpl__LinuxSignalHandle;
3156# if defined(FPL_PLATFORM_WINDOWS)
3159typedef GUID fpl__Win32Guid;
3161typedef HANDLE fpl__Win32Handle;
3163typedef HINSTANCE fpl__Win32InstanceHandle;
3165typedef HMODULE fpl__Win32LibraryHandle;
3167typedef HANDLE fpl__Win32ThreadHandle;
3169typedef HANDLE fpl__Win32FileHandle;
3171typedef CRITICAL_SECTION fpl__Win32MutexHandle;
3173typedef HANDLE fpl__Win32SignalHandle;
3175typedef CONDITION_VARIABLE fpl__Win32ConditionVariable;
3177typedef HANDLE fpl__Win32SemaphoreHandle;
3179typedef HWND fpl__Win32WindowHandle;
3181typedef HDC fpl__Win32DeviceContext;
3183typedef HGLRC fpl__Win32RenderingContext;
3185typedef LARGE_INTEGER fpl__Win32LargeInteger;
3189# if defined(FPL_SUBPLATFORM_POSIX)
3192typedef void *fpl__POSIXLibraryHandle;
3194typedef int fpl__POSIXFileHandle;
3196typedef DIR *fpl__POSIXDirHandle;
3198typedef pthread_t fpl__POSIXThreadHandle;
3200typedef pthread_mutex_t fpl__POSIXMutexHandle;
3202typedef sem_t fpl__POSIXSemaphoreHandle;
3204typedef pthread_cond_t fpl__POSIXConditionVariable;
3208# if defined(FPL_SUBPLATFORM_X11)
3211typedef Display *fpl__X11Display;
3213typedef Window fpl__X11Window;
3215typedef Visual *fpl__X11Visual;
3217typedef GC fpl__X11GC;
3219typedef XImage *fpl__X11Image;
3221typedef void *fpl__GLXContext;
3226# if defined(FPL_PLATFORM_LINUX)
3229typedef int fpl__LinuxSignalHandle;
3245#if defined(FPL_PLATFORM_WINDOWS)
3246# if defined(MAX_PATH)
3247# define FPL__M_MAX_FILENAME_LENGTH (MAX_PATH)
3248# define FPL__M_MAX_PATH_LENGTH (MAX_PATH * 2)
3250# define FPL__M_MAX_FILENAME_LENGTH (260)
3251# define FPL__M_MAX_PATH_LENGTH (260 * 2)
3253# define FPL__M_PATH_SEPARATOR '\\'
3254# define FPL__M_FILE_EXT_SEPARATOR '.'
3256# define FPL__M_MAX_FILENAME_LENGTH (512)
3257# define FPL__M_MAX_PATH_LENGTH (2048)
3258# define FPL__M_PATH_SEPARATOR '/'
3259# define FPL__M_FILE_EXT_SEPARATOR '.'
3266#define FPL_MAX_FILENAME_LENGTH FPL__M_MAX_FILENAME_LENGTH
3272#define FPL_MAX_PATH_LENGTH FPL__M_MAX_PATH_LENGTH
3278#define FPL_PATH_SEPARATOR FPL__M_PATH_SEPARATOR
3284#define FPL_FILE_EXT_SEPARATOR FPL__M_FILE_EXT_SEPARATOR
3290#define FPL_MAX_NAME_LENGTH (256)
3296#define FPL_MAX_BUFFER_LENGTH (2048)
4347#if defined(FPL__ENABLE_VIDEO_OPENGL)
4381#if defined(FPL__ENABLE_VIDEO_VULKAN)
4391typedef void (
fplVulkanValidationLayerCallback)(
void *userData,
const char *message,
const uint32_t messageSeverity,
const uint32_t messageType,
const void *debugUtilsMessengerCallbackData);
4462#if defined(FPL__ENABLE_VIDEO_OPENGL)
4466#if defined(FPL__ENABLE_VIDEO_VULKAN)
4739#define FPL_MAX_AUDIO_CHANNEL_COUNT 32
4780#if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
4782 fpl__Win32Guid dshow;
4784#if defined(FPL__ENABLE_AUDIO_ALSA)
4824#if defined(FPL__ENABLE_AUDIO_ALSA)
4829typedef struct fplAlsaAudioSettings {
4832} fplAlsaAudioSettings;
4840#if defined(FPL__ENABLE_AUDIO_ALSA)
4842 fplAlsaAudioSettings alsa;
5270#if defined(FPL__ENABLE_LOGGING)
5337#if defined(FPL__ENABLE_LOG_MULTIPLE_WRITERS)
5361 fplLogLevel maxLevel;
5457#if defined(FPL_PLATFORM_WINDOWS)
5459 fpl__Win32LibraryHandle win32LibraryHandle;
5460#elif defined(FPL_SUBPLATFORM_POSIX)
5462 fpl__POSIXLibraryHandle posixLibraryHandle;
5590#if defined(FPL_PLATFORM_WINDOWS)
5594 fpl__Win32LargeInteger qpc;
5598#elif defined(FPL_SUBPLATFORM_POSIX)
5604 int64_t nanoSeconds;
5621#define FPL_TIMEOUT_INFINITE UINT32_MAX
5735#if defined(FPL_PLATFORM_WINDOWS)
5737 fpl__Win32ThreadHandle win32ThreadHandle;
5738#elif defined(FPL_SUBPLATFORM_POSIX)
5740 fpl__POSIXThreadHandle posixThread;
5778#if defined(FPL_PLATFORM_WINDOWS)
5783typedef struct fpl__Win32InternalSemaphore {
5785 fpl__Win32SemaphoreHandle handle;
5787 volatile int32_t value;
5788} fpl__Win32InternalSemaphore;
5796#if defined(FPL_PLATFORM_WINDOWS)
5798 fpl__Win32InternalSemaphore win32;
5799#elif defined(FPL_SUBPLATFORM_POSIX)
5801 fpl__POSIXSemaphoreHandle posixHandle;
5821#if defined(FPL_PLATFORM_WINDOWS)
5823 fpl__Win32MutexHandle win32CriticalSection;
5824#elif defined(FPL_SUBPLATFORM_POSIX)
5826 fpl__POSIXMutexHandle posixMutex;
5846#if defined(FPL_PLATFORM_WINDOWS)
5848 fpl__Win32SignalHandle win32EventHandle;
5849#elif defined(FPL_PLATFORM_LINUX)
5851 fpl__LinuxSignalHandle linuxEventHandle;
5882#if defined(FPL_PLATFORM_WINDOWS)
5884 fpl__Win32ConditionVariable win32Condition;
5885#elif defined(FPL_SUBPLATFORM_POSIX)
5887 fpl__POSIXConditionVariable posixCondition;
6405#if defined(FPL_PLATFORM_WINDOWS)
6407 fpl__Win32FileHandle win32FileHandle;
6408#elif defined(FPL_SUBPLATFORM_POSIX)
6410 fpl__POSIXFileHandle posixFileHandle;
6528#if defined(FPL_PLATFORM_WINDOWS)
6530 fpl__Win32FileHandle win32FileHandle;
6531#elif defined(FPL_SUBPLATFORM_POSIX)
6533 fpl__POSIXDirHandle posixDirHandle;
6969#if defined(FPL__ENABLE_WINDOW)
7697#define FPL_MAX_KEYBOARD_STATE_COUNT 256
7716#define FPL_MAX_GAMEPAD_STATE_COUNT 4
8088#if defined(FPL__ENABLE_VIDEO)
8143#if defined(FPL__ENABLE_VIDEO_VULKAN)
8156#if defined(FPL__ENABLE_VIDEO_OPENGL)
8167#if defined(FPL_PLATFORM_WINDOWS)
8172typedef struct fplVideoWindowWin32 {
8174 fpl__Win32WindowHandle windowHandle;
8176 fpl__Win32DeviceContext deviceContext;
8177} fplVideoWindowWin32;
8180#if defined(FPL_SUBPLATFORM_X11)
8185typedef struct fplVideoWindowX11 {
8187 fpl__X11Window window;
8189 fpl__X11Display display;
8191 fpl__X11Visual visual;
8202#if defined(FPL_PLATFORM_WINDOWS)
8203 fplVideoWindowWin32 win32;
8204#elif defined(FPL_SUBPLATFORM_X11)
8205 fplVideoWindowX11 x11;
8219#if defined(FPL__ENABLE_VIDEO_VULKAN)
8224#if defined(FPL__ENABLE_VIDEO_OPENGL)
8233#if defined(FPL__ENABLE_VIDEO_VULKAN)
8251#if defined(FPL__ENABLE_VIDEO_VULKAN)
8316#if defined(FPL__ENABLE_AUDIO)
8647#if defined(FPL_PLATFORM_WINDOWS)
8648# if defined(FPL_ENTRYPOINT)
8650fpl_main int main(
int argc,
char **args);
8721#if (defined(FPL_IMPLEMENTATION) || FPL_IS_IDE) && !defined(FPL__IMPLEMENTED)
8722#define FPL__IMPLEMENTED
8729#if !defined(FPL__COMPILER_CONFIG_DEFINED)
8730#define FPL__COMPILER_CONFIG_DEFINED
8735#if defined(FPL_COMPILER_MSVC)
8738# pragma warning( push )
8741# pragma warning( disable : 4577 )
8743# pragma warning( disable : 4065 )
8745# pragma warning( disable : 4127 )
8747# pragma warning( disable : 4100 )
8749# pragma warning( disable : 4201 )
8751# pragma warning( disable : 4189 )
8753# pragma warning( disable : 4204 )
8755#elif defined(FPL_COMPILER_GCC)
8758# pragma GCC diagnostic push
8760# pragma GCC diagnostic ignored "-Wunused-variable"
8762# pragma GCC diagnostic ignored "-Wunused-function"
8764#elif defined(FPL_COMPILER_CLANG)
8767# pragma clang diagnostic push
8770# pragma clang diagnostic ignored "-Wunused-variable"
8772# pragma clang diagnostic ignored "-Wunused-function"
8783#if !defined(FPL__PLATFORM_INCLUDES_DEFINED)
8784#define FPL__PLATFORM_INCLUDES_DEFINED
8786#if !defined(FPL__HAS_PLATFORM_INCLUDES)
8787# define FPL__HAS_PLATFORM_INCLUDES
8789# if defined(FPL_PLATFORM_WINDOWS)
8791# if !defined(NOMINMAX)
8795# if !defined(WIN32_LEAN_AND_MEAN)
8796# define WIN32_LEAN_AND_MEAN 1
8800# include <windows.h>
8801# if _WIN32_WINNT < 0x0600
8802# error "Windows Vista or higher required!"
8806# if defined(FPL_SUBPLATFORM_POSIX)
8807# include <pthread.h>
8809# include <semaphore.h>
8813# if defined(FPL_SUBPLATFORM_X11)
8815# include <X11/Xlib.h>
8816# include <X11/Xutil.h>
8817# include <X11/Xatom.h>
8825#if defined(FPL_PLATFORM_WINDOWS)
8830fplStaticAssert(
sizeof(fpl__Win32MutexHandle) >=
sizeof(CRITICAL_SECTION));
8832fplStaticAssert(
sizeof(fpl__Win32ConditionVariable) >=
sizeof(CONDITION_VARIABLE));
8833#elif defined(FPL_SUBPLATFORM_POSIX)
8838fplStaticAssert(
sizeof(fpl__POSIXMutexHandle) >=
sizeof(pthread_mutex_t));
8840fplStaticAssert(
sizeof(fpl__POSIXConditionVariable) >=
sizeof(pthread_cond_t));
8842#if defined(FPL_PLATFORM_LINUX)
8849#if defined(FPL_COMPILER_MSVC)
8851#elif defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG)
8852# if defined(FPL_ARCH_X86) || defined(FPL_ARCH_X64)
8858#if !defined(FPL_NO_CRT)
8871#if !defined(FPL__INTERNAL_TOP_DEFINED)
8872#define FPL__INTERNAL_TOP_DEFINED
8875#define FPL__MODULE_CORE "Core"
8876#define FPL__MODULE_FILES "Files"
8877#define FPL__MODULE_THREADING "Threading"
8878#define FPL__MODULE_MEMORY "Memory"
8879#define FPL__MODULE_WINDOW "Window"
8880#define FPL__MODULE_LIBRARIES "Libraries"
8881#define FPL__MODULE_OS "OS"
8882#define FPL__MODULE_HARDWARE "Hardware"
8883#define FPL__MODULE_STRINGS "Strings"
8884#define FPL__MODULE_PATHS "Paths"
8885#define FPL__MODULE_ARGS "Arguments"
8887#define FPL__MODULE_AUDIO "Audio"
8888#define FPL__MODULE_AUDIO_DIRECTSOUND "DirectSound"
8889#define FPL__MODULE_AUDIO_ALSA "ALSA"
8891#define FPL__MODULE_VIDEO "Video"
8892#define FPL__MODULE_VIDEO_OPENGL "OpenGL"
8893#define FPL__MODULE_VIDEO_VULKAN "Vulkan"
8894#define FPL__MODULE_VIDEO_SOFTWARE "Software"
8896#define FPL__MODULE_WIN32 "Win32"
8897#define FPL__MODULE_XINPUT "XInput"
8899#define FPL__MODULE_LINUX "Linux"
8900#define FPL__MODULE_UNIX "Unix"
8901#define FPL__MODULE_POSIX "POSIX"
8902#define FPL__MODULE_PTHREAD "pthread"
8903#define FPL__MODULE_X11 "X11"
8904#define FPL__MODULE_GLX "GLX"
8911#define FPL__ENUM_COUNT(first, last) ((last) - (first) + 1)
8914#define FPL__ENUM_VALUE_TO_ARRAY_INDEX(value, first, last) (((value) >= (first) && (value) <= (last)) ? ((value) - (first)) : 0)
8917#define FPL__ENUM_NAME(str, enumValue) str
8932#if !defined(FPL__INTERNAL_LOGGING_DEFINED)
8933#define FPL__INTERNAL_LOGGING_DEFINED
8935#define FPL__MODULE_CONCAT(mod, format) "[" mod "] " format
8937#if defined(FPL__ENABLE_LOGGING)
8940#define FPL__LOGLEVEL_COUNT FPL__ENUM_COUNT(fplLogLevel_First, fplLogLevel_Last)
8957 const char *result = fpl__LogLevelNameTable[index];
8961fpl_internal void fpl__LogWrite(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *message) {
8964#if defined(FPL_LOG_MULTIPLE_WRITERS)
8965 settings->criticalWriter.console.logToError =
true;
8967 settings->errorWriter = settings->criticalWriter;
8968 settings->warningWriter = settings->criticalWriter;
8970 settings->verboseWriter = settings->infoWriter;
8979 if ((settings->
maxLevel == -1) || (level <= settings->maxLevel)) {
8980#if defined(FPL_LOG_MULTIPLE_WRITERS)
8986 const char *levelStr = fpl__LogLevelToString(level);
9002fpl_internal void fpl__LogWriteArgs(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, va_list argList) {
9004 va_copy(listCopy, argList);
9007 if (formattedLen > 0) {
9008 fpl__LogWrite(funcName, lineNumber, level, buffer);
9013fpl_internal void fpl__LogWriteVarArgs(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, ...) {
9015 va_start(argList, format);
9016 fpl__LogWriteArgs(funcName, lineNumber, level, format, argList);
9020# define FPL_LOG(lvl, mod, format, ...) fpl__LogWriteVarArgs(FPL_FUNCTION_NAME, __LINE__, lvl, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
9021# define FPL_LOG_CRITICAL(mod, format, ...) FPL_LOG(fplLogLevel_Critical, mod, format, ## __VA_ARGS__)
9022# define FPL_LOG_ERROR(mod, format, ...) FPL_LOG(fplLogLevel_Error, mod, format, ## __VA_ARGS__)
9023# define FPL_LOG_WARN(mod, format, ...) FPL_LOG(fplLogLevel_Warning, mod, format, ## __VA_ARGS__)
9024# define FPL_LOG_INFO(mod, format, ...) FPL_LOG(fplLogLevel_Info, mod, format, ## __VA_ARGS__)
9025# define FPL_LOG_VERBOSE(mod, format, ...) FPL_LOG(fplLogLevel_Verbose, mod, format, ## __VA_ARGS__)
9026# define FPL_LOG_DEBUG(mod, format, ...) FPL_LOG(fplLogLevel_Debug, mod, format, ## __VA_ARGS__)
9027# define FPL_LOG_TRACE(mod, format, ...) FPL_LOG(fplLogLevel_Trace, mod, format, ## __VA_ARGS__)
9029# define FPL__LOG_FUNCTION_N(mod, name) FPL_LOG(fplLogLevel_Debug, mod, "-> %s()", name)
9030# define FPL_LOG_FUNCTION(mod) FPL__LOG_FUNCTION_N(mod, FPL_FUNCTION_NAME)
9034# define FPL_LOG(lvl, mod, format, ...)
9035# define FPL_LOG_CRITICAL(mod, format, ...)
9036# define FPL_LOG_ERROR(mod, format, ...)
9037# define FPL_LOG_WARN(mod, format, ...)
9038# define FPL_LOG_INFO(mod, format, ...)
9039# define FPL_LOG_VERBOSE(mod, format, ...)
9040# define FPL_LOG_DEBUG(mod, format, ...)
9041# define FPL_LOG_FUNCTION(mod)
9049#define FPL__M_CRITICAL(funcName, line, mod, format, ...) fpl__HandleError(funcName, line, fplLogLevel_Critical, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
9050#define FPL__M_ERROR(funcName, line, mod, format, ...) fpl__HandleError(funcName, line, fplLogLevel_Error, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
9051#define FPL__M_WARNING(funcName, line, mod, format, ...) fpl__HandleError(funcName, line, fplLogLevel_Warning, FPL__MODULE_CONCAT(mod, format), ## __VA_ARGS__)
9053#define FPL__CRITICAL(mod, format, ...) FPL__M_CRITICAL(FPL_FUNCTION_NAME, __LINE__, mod, format, ## __VA_ARGS__)
9054#define FPL__ERROR(mod, format, ...) FPL__M_ERROR(FPL_FUNCTION_NAME, __LINE__, mod, format, ## __VA_ARGS__)
9055#define FPL__WARNING(mod, format, ...) FPL__M_WARNING(FPL_FUNCTION_NAME, __LINE__, mod, format, ## __VA_ARGS__)
9064#if !defined(FPL__PLATFORM_CONSTANTS_DEFINED)
9065#define FPL__PLATFORM_CONSTANTS_DEFINED
9068#define FPL__ARBITARY_PADDING 64
9070#define FPL__MEMORY_PADDING sizeof(uintptr_t)
9074fpl_internal void fpl__HandleError(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, ...);
9102fpl_internal void *fpl__AllocateDynamicMemory(
const size_t size,
const size_t alignment);
9104fpl_internal void *fpl__AllocateTemporaryMemory(
const size_t size,
const size_t alignment);
9105fpl_internal void fpl__ReleaseTemporaryMemory(
void *ptr);
9107fpl_internal uint32_t fpl__NextPowerOfTwo(
const uint32_t input) {
9118fpl_internal uint32_t fpl__PrevPowerOfTwo(
const uint32_t input) {
9119 uint32_t result = fpl__NextPowerOfTwo(input) >> 1;
9123fpl_internal uint32_t fpl__RoundToPowerOfTwo(
const uint32_t input) {
9124 uint32_t prev = fpl__PrevPowerOfTwo(input);
9125 uint32_t next = fpl__NextPowerOfTwo(input);
9126 if ((next - input) < (input - prev)) {
9133fpl_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) {
9134 for (
size_t i = 0; i < maxWildcardCount; ++i) {
9135 const char *wildcard = wildcards[i];
9137 size_t index = *outCount;
9138 char *target = outLines[index];
9140 *outCount = index + 1;
9144 bool result = *outCount < maxLineCount;
9148fpl_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) {
9149 if (filePath ==
fpl_null || wildcards ==
fpl_null || maxWildcardCount == 0 || maxLineSize == 0 || maxLineCount == 0 || outLines ==
fpl_null) {
9158 char *line = (
char *)fpl__AllocateTemporaryMemory(maxLineSize, 8);
9161 size_t bytesRead = 0;
9162 size_t posLineBytes = 0;
9164 while (!done && ((bytesRead =
fplFileReadBlock(&fileHandle, maxBufferSize, &buffer[0], maxBufferSize)) > 0)) {
9165 buffer[bytesRead] = 0;
9166 char *start = &buffer[0];
9169 size_t lineSizeToRead = 0;
9170 while (readPos < bytesRead) {
9172 size_t remainingLineBytes = maxLineSize - posLineBytes;
9173 char *lineTargetP = line + posLineBytes;
9174 if (lineSizeToRead < remainingLineBytes) {
9177 fplCopyStringLen(start, remainingLineBytes - 1, lineTargetP, remainingLineBytes);
9179 if (!fpl__AddLineWhenAnyMatches(line, wildcards, maxWildcardCount, maxLineSize, maxLineCount, outLines, &result)) {
9196 if (lineSizeToRead > 0) {
9197 size_t remainingLineBytes = maxLineSize - posLineBytes;
9198 char *lineTargetP = line + posLineBytes;
9199 if (lineSizeToRead < remainingLineBytes) {
9201 posLineBytes += lineSizeToRead;
9202 if (bytesRead <= maxBufferSize) {
9203 if (!fpl__AddLineWhenAnyMatches(line, wildcards, maxWildcardCount, maxLineSize, maxLineCount, outLines, &result)) {
9208 fplCopyStringLen(start, remainingLineBytes - 1, lineTargetP, remainingLineBytes);
9212 if (!fpl__AddLineWhenAnyMatches(line, wildcards, maxWildcardCount, maxLineSize, maxLineCount, outLines, &result)) {
9218 fpl__ReleaseTemporaryMemory(line);
9227 const char *p = versionStr;
9228 for (
int i = 0; i < 4; ++i) {
9229 const char *digitStart = p;
9230 while (*p >=
'0' && *p <=
'9') {
9233 size_t len = p - digitStart;
9239 if (*p !=
'.' && *p !=
'-')
break;
9259#if defined(FPL_PLATFORM_WINDOWS)
9260# include <windowsx.h>
9263# include <shellapi.h>
9265# if defined(FPL_IS_CPP)
9266# define fpl__Win32IsEqualGuid(a, b) InlineIsEqualGUID(a, b)
9267# define fpl__Win32CopyGuid(src, dst) fplMemoryCopy(src, sizeof(*(src)), dst)
9269# define fpl__Win32IsEqualGuid(a, b) InlineIsEqualGUID(&a, &b)
9270# define fpl__Win32CopyGuid(src, dst) fplMemoryCopy(src, sizeof(*(src)), dst)
9273fpl_globalvar const fpl__Win32Guid FPL__WIN32_GUID_ZERO = { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
9275fpl_internal const char *fpl__Win32FormatGuidString(
char *buffer,
const size_t maxBufferLen,
const fpl__Win32Guid *guid) {
9276 fplStringFormat(buffer, maxBufferLen,
"{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
9277 guid->Data1, guid->Data2, guid->Data3,
9278 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
9279 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
9284#define FPL__WIN32_LOAD_LIBRARY_BREAK(mod, target, libName) \
9285 (target) = LoadLibraryA(libName); \
9286 if((target) == fpl_null) { \
9287 FPL__WARNING(mod, "Failed loading library '%s'", (libName)); \
9290#define FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK(mod, libHandle, libName, target, type, name) \
9291 (target)->name = (type *)(void *)GetProcAddress(libHandle, #name); \
9292 if ((target)->name == fpl_null) { \
9293 FPL__WARNING(mod, "Failed getting procedure address '%s' from library '%s'", #name, libName); \
9296#if !defined(FPL_NO_RUNTIME_LINKING)
9297# define FPL__WIN32_LOAD_LIBRARY FPL__WIN32_LOAD_LIBRARY_BREAK
9298# define FPL__WIN32_GET_FUNCTION_ADDRESS FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK
9300# define FPL__WIN32_LOAD_LIBRARY(mod, target, libName)
9301# define FPL__WIN32_GET_FUNCTION_ADDRESS(mod, libHandle, libName, target, type, name) \
9302 (target)->name = name
9308#define FPL__FUNC_XINPUT_XInputGetState(name) DWORD WINAPI name(DWORD dwUserIndex, XINPUT_STATE *pState)
9309typedef FPL__FUNC_XINPUT_XInputGetState(fpl__win32_func_XInputGetState);
9310FPL__FUNC_XINPUT_XInputGetState(fpl__Win32XInputGetStateStub) {
9311 return(ERROR_DEVICE_NOT_CONNECTED);
9313#define FPL__FUNC_XINPUT_XInputGetCapabilities(name) DWORD WINAPI name(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
9314typedef FPL__FUNC_XINPUT_XInputGetCapabilities(fpl__win32_func_XInputGetCapabilities);
9315FPL__FUNC_XINPUT_XInputGetCapabilities(fpl__Win32XInputGetCapabilitiesStub) {
9316 return(ERROR_DEVICE_NOT_CONNECTED);
9318typedef struct fpl__Win32XInputApi {
9319 HMODULE xinputLibrary;
9320 fpl__win32_func_XInputGetState *XInputGetState;
9321 fpl__win32_func_XInputGetCapabilities *XInputGetCapabilities;
9322} fpl__Win32XInputApi;
9324fpl_internal void fpl__Win32UnloadXInputApi(fpl__Win32XInputApi *xinputApi) {
9326 if (xinputApi->xinputLibrary) {
9327 FPL_LOG_DEBUG(
"XInput",
"Unload XInput Library");
9328 FreeLibrary(xinputApi->xinputLibrary);
9329 xinputApi->xinputLibrary =
fpl_null;
9330 xinputApi->XInputGetState = fpl__Win32XInputGetStateStub;
9331 xinputApi->XInputGetCapabilities = fpl__Win32XInputGetCapabilitiesStub;
9335fpl_internal void fpl__Win32LoadXInputApi(fpl__Win32XInputApi *xinputApi) {
9337 const char *xinputFileNames[] = {
9342 bool result =
false;
9343 for (uint32_t index = 0; index <
fplArrayCount(xinputFileNames); ++index) {
9344 const char *libName = xinputFileNames[index];
9348 FPL__WIN32_LOAD_LIBRARY_BREAK(FPL__MODULE_XINPUT, libHandle, libName);
9349 xinputApi->xinputLibrary = libHandle;
9350 FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK(FPL__MODULE_XINPUT, libHandle, libName, xinputApi, fpl__win32_func_XInputGetState, XInputGetState);
9351 FPL__WIN32_GET_FUNCTION_ADDRESS_BREAK(FPL__MODULE_XINPUT, libHandle, libName, xinputApi, fpl__win32_func_XInputGetCapabilities, XInputGetCapabilities);
9357 fpl__Win32UnloadXInputApi(xinputApi);
9361 xinputApi->XInputGetState = fpl__Win32XInputGetStateStub;
9362 xinputApi->XInputGetCapabilities = fpl__Win32XInputGetCapabilitiesStub;
9371#define FPL__FUNC_WIN32_ChoosePixelFormat(name) int WINAPI name(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd)
9372typedef FPL__FUNC_WIN32_ChoosePixelFormat(fpl__win32_func_ChoosePixelFormat);
9373#define FPL__FUNC_WIN32_SetPixelFormat(name) BOOL WINAPI name(HDC hdc, int format, CONST PIXELFORMATDESCRIPTOR *ppfd)
9374typedef FPL__FUNC_WIN32_SetPixelFormat(fpl__win32_func_SetPixelFormat);
9375#define FPL__FUNC_WIN32_DescribePixelFormat(name) int WINAPI name(HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd)
9376typedef FPL__FUNC_WIN32_DescribePixelFormat(fpl__win32_func_DescribePixelFormat);
9377#define FPL__FUNC_WIN32_GetDeviceCaps(name) int WINAPI name(HDC hdc, int index)
9378typedef FPL__FUNC_WIN32_GetDeviceCaps(fpl__win32_func_GetDeviceCaps);
9379#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)
9380typedef FPL__FUNC_WIN32_StretchDIBits(fpl__win32_func_StretchDIBits);
9381#define FPL__FUNC_WIN32_DeleteObject(name) BOOL WINAPI name( _In_ HGDIOBJ ho)
9382typedef FPL__FUNC_WIN32_DeleteObject(fpl__win32_func_DeleteObject);
9383#define FPL__FUNC_WIN32_SwapBuffers(name) BOOL WINAPI name(HDC)
9384typedef FPL__FUNC_WIN32_SwapBuffers(fpl__win32_func_SwapBuffers);
9385#define FPL__FUNC_WIN32_CreateDIBSection(name) HBITMAP WINAPI name(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset)
9386typedef FPL__FUNC_WIN32_CreateDIBSection(fpl__win32_func_CreateDIBSection);
9387#define FPL__FUNC_WIN32_CreateBitmap(name) HBITMAP WINAPI name(int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID *lpBits)
9388typedef FPL__FUNC_WIN32_CreateBitmap(fpl__win32_func_CreateBitmap);
9389#define FPL__FUNC_WIN32_CreateSolidBrush(name) HBRUSH WINAPI name(COLORREF color)
9390typedef FPL__FUNC_WIN32_CreateSolidBrush(fpl__win32_func_CreateSolidBrush);
9393#define FPL__FUNC_WIN32_SHGetFolderPathW(name) HRESULT WINAPI name(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath)
9394typedef FPL__FUNC_WIN32_SHGetFolderPathW(fpl__win32_func_SHGetFolderPathW);
9395#define FPL__FUNC_WIN32_DragQueryFileW(name) UINT WINAPI name(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch)
9396typedef FPL__FUNC_WIN32_DragQueryFileW(fpl__win32_func_DragQueryFileW);
9397#define FPL__FUNC_WIN32_DragAcceptFiles(name) void WINAPI name(HWND hWnd, BOOL fAccept)
9398typedef FPL__FUNC_WIN32_DragAcceptFiles(fpl__win32_func_DragAcceptFiles);
9401#define FPL__FUNC_WIN32_RegisterClassExW(name) ATOM WINAPI name(CONST WNDCLASSEXW *)
9402typedef FPL__FUNC_WIN32_RegisterClassExW(fpl__win32_func_RegisterClassExW);
9403#define FPL__FUNC_WIN32_UnregisterClassW(name) BOOL WINAPI name(LPCWSTR lpClassName, HINSTANCE hInstance)
9404typedef FPL__FUNC_WIN32_UnregisterClassW(fpl__win32_func_UnregisterClassW);
9405#define FPL__FUNC_WIN32_ShowWindow(name) BOOL WINAPI name(HWND hWnd, int nCmdShow)
9406typedef FPL__FUNC_WIN32_ShowWindow(fpl__win32_func_ShowWindow);
9407#define FPL__FUNC_WIN32_DestroyWindow(name) BOOL WINAPI name(HWND hWnd)
9408typedef FPL__FUNC_WIN32_DestroyWindow(fpl__win32_func_DestroyWindow);
9409#define FPL__FUNC_WIN32_UpdateWindow(name) BOOL WINAPI name(HWND hWnd)
9410typedef FPL__FUNC_WIN32_UpdateWindow(fpl__win32_func_UpdateWindow);
9411#define FPL__FUNC_WIN32_TranslateMessage(name) BOOL WINAPI name(CONST MSG *lpMsg)
9412typedef FPL__FUNC_WIN32_TranslateMessage(fpl__win32_func_TranslateMessage);
9413#define FPL__FUNC_WIN32_DispatchMessageW(name) LRESULT WINAPI name(CONST MSG *lpMsg)
9414typedef FPL__FUNC_WIN32_DispatchMessageW(fpl__win32_func_DispatchMessageW);
9415#define FPL__FUNC_WIN32_PeekMessageW(name) BOOL WINAPI name(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg)
9416typedef FPL__FUNC_WIN32_PeekMessageW(fpl__win32_func_PeekMessageW);
9417#define FPL__FUNC_WIN32_DefWindowProcW(name) LRESULT WINAPI name(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
9418typedef FPL__FUNC_WIN32_DefWindowProcW(fpl__win32_func_DefWindowProcW);
9419#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)
9420typedef FPL__FUNC_WIN32_CreateWindowExW(fpl__win32_func_CreateWindowExW);
9421#define FPL__FUNC_WIN32_SetWindowPos(name) BOOL WINAPI name(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
9422typedef FPL__FUNC_WIN32_SetWindowPos(fpl__win32_func_SetWindowPos);
9423#define FPL__FUNC_WIN32_GetWindowPlacement(name) BOOL WINAPI name(HWND hWnd, WINDOWPLACEMENT *lpwndpl)
9424typedef FPL__FUNC_WIN32_GetWindowPlacement(fpl__win32_func_GetWindowPlacement);
9425#define FPL__FUNC_WIN32_SetWindowPlacement(name) BOOL WINAPI name(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl)
9426typedef FPL__FUNC_WIN32_SetWindowPlacement(fpl__win32_func_SetWindowPlacement);
9427#define FPL__FUNC_WIN32_GetClientRect(name) BOOL WINAPI name(HWND hWnd, LPRECT lpRect)
9428typedef FPL__FUNC_WIN32_GetClientRect(fpl__win32_func_GetClientRect);
9429#define FPL__FUNC_WIN32_GetWindowRect(name) BOOL WINAPI name(HWND hWnd, LPRECT lpRect)
9430typedef FPL__FUNC_WIN32_GetWindowRect(fpl__win32_func_GetWindowRect);
9431#define FPL__FUNC_WIN32_AdjustWindowRect(name) BOOL WINAPI name(LPRECT lpRect, DWORD dwStyle, BOOL bMenu)
9432typedef FPL__FUNC_WIN32_AdjustWindowRect(fpl__win32_func_AdjustWindowRect);
9433#define FPL__FUNC_WIN32_ClientToScreen(name) BOOL WINAPI name(HWND hWnd, LPPOINT lpPoint)
9434typedef FPL__FUNC_WIN32_ClientToScreen(fpl__win32_func_ClientToScreen);
9435#define FPL__FUNC_WIN32_GetAsyncKeyState(name) SHORT WINAPI name(int vKey)
9436typedef FPL__FUNC_WIN32_GetAsyncKeyState(fpl__win32_func_GetAsyncKeyState);
9437#define FPL__FUNC_WIN32_GetKeyState(name) SHORT WINAPI name(int vKey)
9438typedef FPL__FUNC_WIN32_GetKeyState(fpl__win32_func_GetKeyState);
9439#define FPL__FUNC_WIN32_MapVirtualKeyW(name) UINT WINAPI name(UINT uCode, UINT uMapType)
9440typedef FPL__FUNC_WIN32_MapVirtualKeyW(fpl__win32_func_MapVirtualKeyW);
9441#define FPL__FUNC_WIN32_SetCursor(name) HCURSOR WINAPI name(HCURSOR hCursor)
9442typedef FPL__FUNC_WIN32_SetCursor(fpl__win32_func_SetCursor);
9443#define FPL__FUNC_WIN32_GetCursor(name) HCURSOR WINAPI name(VOID)
9444typedef FPL__FUNC_WIN32_GetCursor(fpl__win32_func_GetCursor);
9445#define FPL__FUNC_WIN32_GetCursorPos(name) BOOL WINAPI name(LPPOINT lpPoint)
9446typedef FPL__FUNC_WIN32_GetCursorPos(fpl__win32_func_GetCursorPos);
9447#define FPL__FUNC_WIN32_WindowFromPoint(name) HWND WINAPI name(POINT Point)
9448typedef FPL__FUNC_WIN32_WindowFromPoint(fpl__win32_func_WindowFromPoint);
9449#define FPL__FUNC_WIN32_PtInRect(name) BOOL WINAPI name(CONST RECT *lprc, POINT pt)
9450typedef FPL__FUNC_WIN32_PtInRect(fpl__win32_func_PtInRect);
9451#define FPL__FUNC_WIN32_LoadCursorA(name) HCURSOR WINAPI name(HINSTANCE hInstance, LPCSTR lpCursorName)
9452typedef FPL__FUNC_WIN32_LoadCursorA(fpl__win32_func_LoadCursorA);
9453#define FPL__FUNC_WIN32_LoadCursorW(name) HCURSOR WINAPI name(HINSTANCE hInstance, LPCWSTR lpCursorName)
9454typedef FPL__FUNC_WIN32_LoadCursorW(fpl__win32_func_LoadCursorW);
9455#define FPL__FUNC_WIN32_LoadIconA(name) HICON WINAPI name(HINSTANCE hInstance, LPCSTR lpIconName)
9456typedef FPL__FUNC_WIN32_LoadIconA(fpl__win32_func_LoadIconA);
9457#define FPL__FUNC_WIN32_LoadIconW(name) HICON WINAPI name(HINSTANCE hInstance, LPCWSTR lpIconName)
9458typedef FPL__FUNC_WIN32_LoadIconW(fpl__win32_func_LoadIconW);
9459#define FPL__FUNC_WIN32_SetWindowTextW(name) BOOL WINAPI name(HWND hWnd, LPCWSTR lpString)
9460typedef FPL__FUNC_WIN32_SetWindowTextW(fpl__win32_func_SetWindowTextW);
9461#define FPL__FUNC_WIN32_GetWindowTextW(name) int WINAPI name(HWND hWnd, LPWSTR lpString, int nMaxCount)
9462typedef FPL__FUNC_WIN32_GetWindowTextW(fpl__win32_func_GetWindowTextW);
9463#define FPL__FUNC_WIN32_SetWindowLongW(name) LONG WINAPI name(HWND hWnd, int nIndex, LONG dwNewLong)
9464typedef FPL__FUNC_WIN32_SetWindowLongW(fpl__win32_func_SetWindowLongW);
9465#define FPL__FUNC_WIN32_GetWindowLongW(name) LONG WINAPI name(HWND hWnd, int nIndex)
9466typedef FPL__FUNC_WIN32_GetWindowLongW(fpl__win32_func_GetWindowLongW);
9468#if defined(FPL_ARCH_X64)
9469#define FPL__FUNC_WIN32_SetWindowLongPtrW(name) LONG_PTR WINAPI name(HWND hWnd, int nIndex, LONG_PTR dwNewLong)
9470typedef FPL__FUNC_WIN32_SetWindowLongPtrW(fpl__win32_func_SetWindowLongPtrW);
9471#define FPL__FUNC_WIN32_GetWindowLongPtrW(name) LONG_PTR WINAPI name(HWND hWnd, int nIndex)
9472typedef FPL__FUNC_WIN32_GetWindowLongPtrW(fpl__win32_func_GetWindowLongPtrW);
9475#define FPL__FUNC_WIN32_ReleaseDC(name) int WINAPI name(HWND hWnd, HDC hDC)
9476typedef FPL__FUNC_WIN32_ReleaseDC(fpl__win32_func_ReleaseDC);
9477#define FPL__FUNC_WIN32_GetDC(name) HDC WINAPI name(HWND hWnd)
9478typedef FPL__FUNC_WIN32_GetDC(fpl__win32_func_GetDC);
9479#define FPL__FUNC_WIN32_ChangeDisplaySettingsW(name) LONG WINAPI name(DEVMODEW* lpDevMode, DWORD dwFlags)
9480typedef FPL__FUNC_WIN32_ChangeDisplaySettingsW(fpl__win32_func_ChangeDisplaySettingsW);
9481#define FPL__FUNC_WIN32_EnumDisplaySettingsW(name) BOOL WINAPI name(LPCWSTR lpszDeviceName, DWORD iModeNum, DEVMODEW* lpDevMode)
9482typedef FPL__FUNC_WIN32_EnumDisplaySettingsW(fpl__win32_func_EnumDisplaySettingsW);
9483#define FPL__FUNC_WIN32_OpenClipboard(name) BOOL WINAPI name(HWND hWndNewOwner)
9484typedef FPL__FUNC_WIN32_OpenClipboard(fpl__win32_func_OpenClipboard);
9485#define FPL__FUNC_WIN32_CloseClipboard(name) BOOL WINAPI name(VOID)
9486typedef FPL__FUNC_WIN32_CloseClipboard(fpl__win32_func_CloseClipboard);
9487#define FPL__FUNC_WIN32_EmptyClipboard(name) BOOL WINAPI name(VOID)
9488typedef FPL__FUNC_WIN32_EmptyClipboard(fpl__win32_func_EmptyClipboard);
9489#define FPL__FUNC_WIN32_IsClipboardFormatAvailable(name) BOOL WINAPI name(UINT format)
9490typedef FPL__FUNC_WIN32_IsClipboardFormatAvailable(fpl__win32_func_IsClipboardFormatAvailable);
9491#define FPL__FUNC_WIN32_SetClipboardData(name) HANDLE WINAPI name(UINT uFormat, HANDLE hMem)
9492typedef FPL__FUNC_WIN32_SetClipboardData(fpl__win32_func_SetClipboardData);
9493#define FPL__FUNC_WIN32_GetClipboardData(name) HANDLE WINAPI name(UINT uFormat)
9494typedef FPL__FUNC_WIN32_GetClipboardData(fpl__win32_func_GetClipboardData);
9495#define FPL__FUNC_WIN32_GetDesktopWindow(name) HWND WINAPI name(VOID)
9496typedef FPL__FUNC_WIN32_GetDesktopWindow(fpl__win32_func_GetDesktopWindow);
9497#define FPL__FUNC_WIN32_GetForegroundWindow(name) HWND WINAPI name(VOID)
9498typedef FPL__FUNC_WIN32_GetForegroundWindow(fpl__win32_func_GetForegroundWindow);
9499#define FPL__FUNC_WIN32_IsZoomed(name) BOOL WINAPI name(HWND hWnd)
9500typedef FPL__FUNC_WIN32_IsZoomed(fpl__win32_func_IsZoomed);
9501#define FPL__FUNC_WIN32_IsIconic(name) BOOL WINAPI name(HWND hWnd)
9502typedef FPL__FUNC_WIN32_IsIconic(fpl__win32_func_IsIconic);
9503#define FPL__FUNC_WIN32_SendMessageW(name) LRESULT WINAPI name(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
9504typedef FPL__FUNC_WIN32_SendMessageW(fpl__win32_func_SendMessageW);
9505#define FPL__FUNC_WIN32_GetMonitorInfoW(name) BOOL WINAPI name(HMONITOR hMonitor, LPMONITORINFO lpmi)
9506typedef FPL__FUNC_WIN32_GetMonitorInfoW(fpl__win32_func_GetMonitorInfoW);
9507#define FPL__FUNC_WIN32_EnumDisplayMonitors(name) BOOL WINAPI name(HDC hdc, LPCRECT lprcClip, MONITORENUMPROC lpfnEnum,LPARAM dwData)
9508typedef FPL__FUNC_WIN32_EnumDisplayMonitors(fpl__win32_func_EnumDisplayMonitors);
9509#define FPL__FUNC_WIN32_MonitorFromRect(name) HMONITOR WINAPI name(LPCRECT lprc, DWORD dwFlags)
9510typedef FPL__FUNC_WIN32_MonitorFromRect(fpl__win32_func_MonitorFromRect);
9511#define FPL__FUNC_WIN32_MonitorFromPoint(name) HMONITOR WINAPI name(POINT pt, DWORD dwFlags)
9512typedef FPL__FUNC_WIN32_MonitorFromPoint(fpl__win32_func_MonitorFromPoint);
9513#define FPL__FUNC_WIN32_MonitorFromWindow(name) HMONITOR WINAPI name(HWND hwnd, DWORD dwFlags)
9514typedef FPL__FUNC_WIN32_MonitorFromWindow(fpl__win32_func_MonitorFromWindow);
9515#define FPL__FUNC_WIN32_RegisterRawInputDevices(name) BOOL WINAPI name(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize)
9516typedef FPL__FUNC_WIN32_RegisterRawInputDevices(fpl__win32_func_RegisterRawInputDevices);
9517#define FPL__FUNC_WIN32_ClipCursor(name) BOOL WINAPI name(CONST RECT *lpRect)
9518typedef FPL__FUNC_WIN32_ClipCursor(fpl__win32_func_ClipCursor);
9519#define FPL__FUNC_WIN32_PostQuitMessage(name) VOID WINAPI name(int nExitCode)
9520typedef FPL__FUNC_WIN32_PostQuitMessage(fpl__win32_func_PostQuitMessage);
9521#define FPL__FUNC_WIN32_CreateIconIndirect(name) HICON WINAPI name(PICONINFO piconinfo)
9522typedef FPL__FUNC_WIN32_CreateIconIndirect(fpl__win32_func_CreateIconIndirect);
9523#define FPL__FUNC_WIN32_GetKeyboardLayout(name) HKL WINAPI name(DWORD idThread)
9524typedef FPL__FUNC_WIN32_GetKeyboardLayout(fpl__win32_func_GetKeyboardLayout);
9525#define FPL__FUNC_WIN32_SetCapture(name) HWND WINAPI name(HWND hWnd)
9526typedef FPL__FUNC_WIN32_SetCapture(fpl__win32_func_SetCapture);
9527#define FPL__FUNC_WIN32_ReleaseCapture(name) BOOL WINAPI name(VOID)
9528typedef FPL__FUNC_WIN32_ReleaseCapture(fpl__win32_func_ReleaseCapture);
9529#define FPL__FUNC_WIN32_ScreenToClient(name) BOOL WINAPI name(HWND hWnd, LPPOINT lpPoint)
9530typedef FPL__FUNC_WIN32_ScreenToClient(fpl__win32_func_ScreenToClient);
9531#define FPL__FUNC_WIN32_BeginPaint(name) HDC WINAPI name(_In_ HWND hWnd, _Out_ LPPAINTSTRUCT lpPaint)
9532typedef FPL__FUNC_WIN32_BeginPaint(fpl__win32_func_BeginPaint);
9533#define FPL__FUNC_WIN32_EndPaint(name) BOOL WINAPI name(_In_ HWND hWnd, _In_ CONST PAINTSTRUCT *lpPaint)
9534typedef FPL__FUNC_WIN32_EndPaint(fpl__win32_func_EndPaint);
9535#define FPL__FUNC_WIN32_SetForegroundWindow(name) BOOL WINAPI name(_In_ HWND hWnd)
9536typedef FPL__FUNC_WIN32_SetForegroundWindow(fpl__win32_func_SetForegroundWindow);
9537#define FPL__FUNC_WIN32_SetFocus(name) HWND WINAPI name(_In_opt_ HWND hWnd)
9538typedef FPL__FUNC_WIN32_SetFocus(fpl__win32_func_SetFocus);
9539#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)
9540typedef FPL__FUNC_WIN32_SetTimer(fpl__win32_func_SetTimer);
9541#define FPL__FUNC_WIN32_GetSysColorBrush(name) HBRUSH WINAPI name(_In_ int nIndex)
9542typedef FPL__FUNC_WIN32_GetSysColorBrush(fpl__win32_func_GetSysColorBrush);
9543#define FPL__FUNC_WIN32_GetSysColorBrush(name) HBRUSH WINAPI name(_In_ int nIndex)
9544typedef FPL__FUNC_WIN32_GetSysColorBrush(fpl__win32_func_GetSysColorBrush);
9547#define FPL__FUNC_WIN32_CoInitializeEx(name) HRESULT WINAPI name(LPVOID pvReserved, DWORD dwCoInit)
9548typedef FPL__FUNC_WIN32_CoInitializeEx(fpl__win32_func_CoInitializeEx);
9549#define FPL__FUNC_WIN32_CoUninitialize(name) void WINAPI name(void)
9550typedef FPL__FUNC_WIN32_CoUninitialize(fpl__win32_func_CoUninitialize);
9551#define FPL__FUNC_WIN32_CoCreateInstance(name) HRESULT WINAPI name(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv)
9552typedef FPL__FUNC_WIN32_CoCreateInstance(fpl__win32_func_CoCreateInstance);
9553#define FPL__FUNC_WIN32_CoTaskMemFree(name) void WINAPI name(LPVOID pv)
9554typedef FPL__FUNC_WIN32_CoTaskMemFree(fpl__win32_func_CoTaskMemFree);
9555#define FPL__FUNC_WIN32_PropVariantClear(name) HRESULT WINAPI name(PROPVARIANT *pvar)
9556typedef FPL__FUNC_WIN32_PropVariantClear(fpl__win32_func_PropVariantClear);
9558typedef struct fpl__Win32GdiApi {
9560 fpl__win32_func_ChoosePixelFormat *ChoosePixelFormat;
9561 fpl__win32_func_SetPixelFormat *SetPixelFormat;
9562 fpl__win32_func_DescribePixelFormat *DescribePixelFormat;
9563 fpl__win32_func_GetDeviceCaps *GetDeviceCaps;
9564 fpl__win32_func_StretchDIBits *StretchDIBits;
9565 fpl__win32_func_DeleteObject *DeleteObject;
9566 fpl__win32_func_SwapBuffers *SwapBuffers;
9567 fpl__win32_func_CreateDIBSection *CreateDIBSection;
9568 fpl__win32_func_CreateBitmap *CreateBitmap;
9569 fpl__win32_func_CreateSolidBrush *CreateSolidBrush;
9572typedef struct fpl__Win32ShellApi {
9573 HMODULE shellLibrary;
9574 fpl__win32_func_SHGetFolderPathW *SHGetFolderPathW;
9575 fpl__win32_func_DragQueryFileW *DragQueryFileW;
9576 fpl__win32_func_DragAcceptFiles *DragAcceptFiles;
9577} fpl__Win32ShellApi;
9579typedef struct fpl__Win32UserApi {
9580 HMODULE userLibrary;
9581 fpl__win32_func_RegisterClassExW *RegisterClassExW;
9582 fpl__win32_func_UnregisterClassW *UnregisterClassW;
9583 fpl__win32_func_ShowWindow *ShowWindow;
9584 fpl__win32_func_DestroyWindow *DestroyWindow;
9585 fpl__win32_func_UpdateWindow *UpdateWindow;
9586 fpl__win32_func_TranslateMessage *TranslateMessage;
9587 fpl__win32_func_DispatchMessageW *DispatchMessageW;
9588 fpl__win32_func_PeekMessageW *PeekMessageW;
9589 fpl__win32_func_DefWindowProcW *DefWindowProcW;
9590 fpl__win32_func_CreateWindowExW *CreateWindowExW;
9591 fpl__win32_func_SetWindowPos *SetWindowPos;
9592 fpl__win32_func_GetWindowPlacement *GetWindowPlacement;
9593 fpl__win32_func_SetWindowPlacement *SetWindowPlacement;
9594 fpl__win32_func_GetClientRect *GetClientRect;
9595 fpl__win32_func_GetWindowRect *GetWindowRect;
9596 fpl__win32_func_AdjustWindowRect *AdjustWindowRect;
9597 fpl__win32_func_GetAsyncKeyState *GetAsyncKeyState;
9598 fpl__win32_func_MapVirtualKeyW *MapVirtualKeyW;
9599 fpl__win32_func_SetCursor *SetCursor;
9600 fpl__win32_func_GetCursor *GetCursor;
9601 fpl__win32_func_LoadCursorA *LoadCursorA;
9602 fpl__win32_func_LoadCursorW *LoadCursorW;
9603 fpl__win32_func_LoadIconA *LoadIconA;
9604 fpl__win32_func_LoadIconW *LoadIconW;
9605 fpl__win32_func_SetWindowTextW *SetWindowTextW;
9606 fpl__win32_func_GetWindowTextW *GetWindowTextW;
9607 fpl__win32_func_SetWindowLongW *SetWindowLongW;
9608 fpl__win32_func_GetWindowLongW *GetWindowLongW;
9609#if defined(FPL_ARCH_X64)
9610 fpl__win32_func_SetWindowLongPtrW *SetWindowLongPtrW;
9611 fpl__win32_func_GetWindowLongPtrW *GetWindowLongPtrW;
9613 fpl__win32_func_ReleaseDC *ReleaseDC;
9614 fpl__win32_func_GetDC *GetDC;
9615 fpl__win32_func_ChangeDisplaySettingsW *ChangeDisplaySettingsW;
9616 fpl__win32_func_EnumDisplaySettingsW *EnumDisplaySettingsW;
9617 fpl__win32_func_OpenClipboard *OpenClipboard;
9618 fpl__win32_func_CloseClipboard *CloseClipboard;
9619 fpl__win32_func_EmptyClipboard *EmptyClipboard;
9620 fpl__win32_func_IsClipboardFormatAvailable *IsClipboardFormatAvailable;
9621 fpl__win32_func_SetClipboardData *SetClipboardData;
9622 fpl__win32_func_GetClipboardData *GetClipboardData;
9623 fpl__win32_func_GetDesktopWindow *GetDesktopWindow;
9624 fpl__win32_func_GetForegroundWindow *GetForegroundWindow;
9625 fpl__win32_func_IsZoomed *IsZoomed;
9626 fpl__win32_func_IsIconic *IsIconic;
9627 fpl__win32_func_SendMessageW *SendMessageW;
9628 fpl__win32_func_GetMonitorInfoW *GetMonitorInfoW;
9629 fpl__win32_func_EnumDisplayMonitors *EnumDisplayMonitors;
9630 fpl__win32_func_MonitorFromRect *MonitorFromRect;
9631 fpl__win32_func_MonitorFromPoint *MonitorFromPoint;
9632 fpl__win32_func_MonitorFromWindow *MonitorFromWindow;
9633 fpl__win32_func_GetCursorPos *GetCursorPos;
9634 fpl__win32_func_WindowFromPoint *WindowFromPoint;
9635 fpl__win32_func_ClientToScreen *ClientToScreen;
9636 fpl__win32_func_PtInRect *PtInRect;
9637 fpl__win32_func_RegisterRawInputDevices *RegisterRawInputDevices;
9638 fpl__win32_func_ClipCursor *ClipCursor;
9639 fpl__win32_func_PostQuitMessage *PostQuitMessage;
9640 fpl__win32_func_CreateIconIndirect *CreateIconIndirect;
9641 fpl__win32_func_GetKeyboardLayout *GetKeyboardLayout;
9642 fpl__win32_func_GetKeyState *GetKeyState;
9643 fpl__win32_func_SetCapture *SetCapture;
9644 fpl__win32_func_ReleaseCapture *ReleaseCapture;
9645 fpl__win32_func_ScreenToClient *ScreenToClient;
9646 fpl__win32_func_BeginPaint *BeginPaint;
9647 fpl__win32_func_EndPaint *EndPaint;
9648 fpl__win32_func_SetForegroundWindow *SetForegroundWindow;
9649 fpl__win32_func_SetFocus *SetFocus;
9650 fpl__win32_func_SetTimer *SetTimer;
9651 fpl__win32_func_GetSysColorBrush *GetSysColorBrush;
9654typedef struct fpl__Win32OleApi {
9656 fpl__win32_func_CoInitializeEx *CoInitializeEx;
9657 fpl__win32_func_CoUninitialize *CoUninitialize;
9658 fpl__win32_func_CoCreateInstance *CoCreateInstance;
9659 fpl__win32_func_CoTaskMemFree *CoTaskMemFree;
9660 fpl__win32_func_PropVariantClear *PropVariantClear;
9663typedef struct fpl__Win32Api {
9664 fpl__Win32GdiApi gdi;
9665 fpl__Win32ShellApi shell;
9666 fpl__Win32UserApi user;
9667 fpl__Win32OleApi ole;
9671fpl_internal void fpl__Win32UnloadApi(fpl__Win32Api *wapi) {
9673 if (wapi->ole.oleLibrary !=
fpl_null) {
9674 FreeLibrary(wapi->ole.oleLibrary);
9677 if (wapi->gdi.gdiLibrary !=
fpl_null) {
9678 FreeLibrary(wapi->gdi.gdiLibrary);
9681 if (wapi->user.userLibrary !=
fpl_null) {
9682 FreeLibrary(wapi->user.userLibrary);
9685 if (wapi->shell.shellLibrary !=
fpl_null) {
9686 FreeLibrary(wapi->shell.shellLibrary);
9689 wapi->isValid =
false;
9692fpl_internal bool fpl__Win32LoadApi(fpl__Win32Api *wapi) {
9694 bool result =
false;
9698 const char *shellLibraryName =
"shell32.dll";
9700 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, shellLibrary, shellLibraryName);
9701 wapi->shell.shellLibrary = shellLibrary;
9702 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, shellLibrary, shellLibraryName, &wapi->shell, fpl__win32_func_SHGetFolderPathW, SHGetFolderPathW);
9703 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, shellLibrary, shellLibraryName, &wapi->shell, fpl__win32_func_DragQueryFileW, DragQueryFileW);
9704 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, shellLibrary, shellLibraryName, &wapi->shell, fpl__win32_func_DragAcceptFiles, DragAcceptFiles);
9707 const char *userLibraryName =
"user32.dll";
9709 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, userLibrary, userLibraryName);
9710 wapi->user.userLibrary = userLibrary;
9711 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_RegisterClassExW, RegisterClassExW);
9712 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_UnregisterClassW, UnregisterClassW);
9713 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ShowWindow, ShowWindow);
9714 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_DestroyWindow, DestroyWindow);
9715 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_UpdateWindow, UpdateWindow);
9716 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_TranslateMessage, TranslateMessage);
9717 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_DispatchMessageW, DispatchMessageW);
9718 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_PeekMessageW, PeekMessageW);
9719 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_DefWindowProcW, DefWindowProcW);
9720 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_CreateWindowExW, CreateWindowExW);
9721 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowPos, SetWindowPos);
9722 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowPlacement, GetWindowPlacement);
9723 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowPlacement, SetWindowPlacement);
9724 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetClientRect, GetClientRect);
9725 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowRect, GetWindowRect);
9726 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_AdjustWindowRect, AdjustWindowRect);
9727 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetAsyncKeyState, GetAsyncKeyState);
9728 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MapVirtualKeyW, MapVirtualKeyW);
9729 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetCursor, SetCursor);
9730 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetCursor, GetCursor);
9731 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadCursorA, LoadCursorA);
9732 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadCursorW, LoadCursorW);
9733 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetCursorPos, GetCursorPos);
9734 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_WindowFromPoint, WindowFromPoint);
9735 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadIconA, LoadIconA);
9736 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_LoadIconW, LoadIconW);
9737 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowTextW, SetWindowTextW);
9738 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowLongW, SetWindowLongW);
9739 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowLongW, GetWindowLongW);
9741# if defined(FPL_ARCH_X64)
9742 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetWindowLongPtrW, SetWindowLongPtrW);
9743 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetWindowLongPtrW, GetWindowLongPtrW);
9746 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ReleaseDC, ReleaseDC);
9747 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetDC, GetDC);
9748 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ChangeDisplaySettingsW, ChangeDisplaySettingsW);
9749 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EnumDisplaySettingsW, EnumDisplaySettingsW);
9750 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_IsClipboardFormatAvailable, IsClipboardFormatAvailable);
9751 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_OpenClipboard, OpenClipboard);
9752 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_CloseClipboard, CloseClipboard);
9753 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EmptyClipboard, EmptyClipboard);
9754 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetClipboardData, SetClipboardData);
9755 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetClipboardData, GetClipboardData);
9756 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetDesktopWindow, GetDesktopWindow);
9757 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetForegroundWindow, GetForegroundWindow);
9758 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_IsZoomed, IsZoomed);
9759 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_IsIconic, IsIconic);
9760 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SendMessageW, SendMessageW);
9761 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetMonitorInfoW, GetMonitorInfoW);
9762 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EnumDisplayMonitors, EnumDisplayMonitors);
9763 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MonitorFromRect, MonitorFromRect);
9764 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MonitorFromPoint, MonitorFromPoint);
9765 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_MonitorFromWindow, MonitorFromWindow);
9766 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ClientToScreen, ClientToScreen);
9767 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_PtInRect, PtInRect);
9768 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_RegisterRawInputDevices, RegisterRawInputDevices);
9769 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ClipCursor, ClipCursor);
9770 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_PostQuitMessage, PostQuitMessage);
9771 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_CreateIconIndirect, CreateIconIndirect);
9772 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetKeyboardLayout, GetKeyboardLayout);
9773 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetKeyState, GetKeyState);
9774 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetCapture, SetCapture);
9775 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ReleaseCapture, ReleaseCapture);
9776 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_ScreenToClient, ScreenToClient);
9777 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_BeginPaint, BeginPaint);
9778 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_EndPaint, EndPaint);
9779 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetForegroundWindow, SetForegroundWindow);
9780 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetFocus, SetFocus);
9781 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_SetTimer, SetTimer);
9782 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, userLibrary, userLibraryName, &wapi->user, fpl__win32_func_GetSysColorBrush, GetSysColorBrush);
9785 const char *gdiLibraryName =
"gdi32.dll";
9787 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName);
9788 wapi->gdi.gdiLibrary = gdiLibrary;
9789 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_ChoosePixelFormat, ChoosePixelFormat);
9790 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_SetPixelFormat, SetPixelFormat);
9791 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_DescribePixelFormat, DescribePixelFormat);
9792 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_StretchDIBits, StretchDIBits);
9793 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_DeleteObject, DeleteObject);
9794 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_SwapBuffers, SwapBuffers);
9795 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_GetDeviceCaps, GetDeviceCaps);
9796 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_CreateDIBSection, CreateDIBSection);
9797 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_CreateBitmap, CreateBitmap);
9798 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, gdiLibrary, gdiLibraryName, &wapi->gdi, fpl__win32_func_CreateSolidBrush, CreateSolidBrush);
9801 const char *oleLibraryName =
"ole32.dll";
9803 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_WIN32, oleLibrary, oleLibraryName);
9804 wapi->ole.oleLibrary = oleLibrary;
9805 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoInitializeEx, CoInitializeEx);
9806 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoUninitialize, CoUninitialize);
9807 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoCreateInstance, CoCreateInstance);
9808 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_CoTaskMemFree, CoTaskMemFree);
9809 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_WIN32, oleLibrary, oleLibraryName, &wapi->ole, fpl__win32_func_PropVariantClear, PropVariantClear);
9814 fpl__Win32UnloadApi(wapi);
9816 wapi->isValid = result;
9821#define FPL__WIN32_CLASSNAME L"FPLWindowClassW"
9822#define FPL__WIN32_UNNAMED_WINDOW L"Unnamed FPL Unicode Window"
9823#define FPL__WIN32_UNNAMED_CONSOLE L"Unnamed FPL Unicode Console"
9824#if defined(FPL_ARCH_X64)
9825# define fpl__win32_SetWindowLongPtr fpl__global__AppState->win32.winApi.user.SetWindowLongPtrW
9827# define fpl__win32_SetWindowLongPtr fpl__global__AppState->win32.winApi.user.SetWindowLongW
9829#define fpl__win32_SetWindowLong fpl__global__AppState->win32.winApi.user.SetWindowLongW
9830#define fpl__win32_GetWindowLong fpl__global__AppState->win32.winApi.user.GetWindowLongW
9832# define fpl__win32_LoadIcon fpl__global__AppState->win32.winApi.user.LoadIconW
9833# define fpl__win32_LoadCursor fpl__global__AppState->win32.winApi.user.LoadCursorW
9835# define fpl__win32_LoadIcon fpl__global__AppState->win32.winApi.user.LoadIconA
9836# define fpl__win32_LoadCursor fpl__global__AppState->win32.winApi.user.LoadCursorA
9841typedef struct fpl__Win32XInputState {
9842 fpl__GameControllerName deviceNames[XUSER_MAX_COUNT];
9843 fpl_b32 isConnected[XUSER_MAX_COUNT];
9844 fpl__Win32XInputApi xinputApi;
9845 LARGE_INTEGER lastDeviceSearchTime;
9846} fpl__Win32XInputState;
9848typedef struct fpl__Win32InitState {
9849 HINSTANCE appInstance;
9851} fpl__Win32InitState;
9853typedef struct fpl__Win32AppState {
9854 fpl__Win32XInputState xinput;
9855 fpl__Win32Api winApi;
9856} fpl__Win32AppState;
9858#if defined(FPL__ENABLE_WINDOW)
9859typedef struct fpl__Win32LastWindowInfo {
9860 WINDOWPLACEMENT placement;
9866} fpl__Win32LastWindowInfo;
9868typedef struct fpl__Win32WindowState {
9869 wchar_t windowClass[256];
9870 fpl__Win32LastWindowInfo lastFullscreenInfo;
9875 HBRUSH backgroundBrush;
9876 HCURSOR defaultCursor;
9880} fpl__Win32WindowState;
9890#if defined(FPL_SUBPLATFORM_POSIX)
9891# include <sys/types.h>
9892# include <sys/mman.h>
9893# include <sys/stat.h>
9894# include <sys/errno.h>
9895# include <sys/time.h>
9896# include <sys/utsname.h>
9906#if !defined(FPL_PLATFORM_ANDROID)
9907# define st_atime st_atim.tv_sec
9908# define st_mtime st_mtim.tv_sec
9909# define st_ctime st_ctim.tv_sec
9912#if defined(FPL_PLATFORM_LINUX)
9913# define fpl__lseek64 lseek64
9914# define fpl__off64_t off64_t
9916# define fpl__lseek64 lseek
9917# define fpl__off64_t off_t
9921#define FPL__POSIX_LOAD_LIBRARY_BREAK(mod, target, libName) \
9922 (target) = dlopen(libName, FPL__POSIX_DL_LOADTYPE); \
9923 if((target) == fpl_null) { \
9924 FPL__WARNING(mod, "Failed loading library '%s'", (libName)); \
9928#define FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(mod, libHandle, libName, target, type, name) \
9929 (target)->name = (type *)dlsym(libHandle, #name)
9931#define FPL__POSIX_GET_FUNCTION_ADDRESS_BREAK(mod, libHandle, libName, target, type, name) \
9932 (target)->name = (type *)dlsym(libHandle, #name); \
9933 if ((target)->name == fpl_null) { \
9934 FPL__WARNING(mod, "Failed getting procedure address '%s' from library '%s'", #name, libName); \
9937#if !defined(FPL_NO_RUNTIME_LINKING)
9938# define FPL__POSIX_LOAD_LIBRARY FPL__POSIX_LOAD_LIBRARY_BREAK
9939# define FPL__POSIX_GET_FUNCTION_ADDRESS FPL__POSIX_GET_FUNCTION_ADDRESS_BREAK
9941# define FPL__POSIX_LOAD_LIBRARY(mod, target, libName)
9942# define FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(mod, libHandle, libName, target, type, name) \
9943 (target)->name = name
9944# define FPL__POSIX_GET_FUNCTION_ADDRESS(mod, libHandle, libName, target, type, name) \
9945 (target)->name = name
9948#define FPL__FUNC_PTHREAD_pthread_self(name) pthread_t name(void)
9949typedef FPL__FUNC_PTHREAD_pthread_self(fpl__pthread_func_pthread_self);
9950#define FPL__FUNC_PTHREAD_pthread_setschedparam(name) int name(pthread_t thread, int policy, const struct sched_param *param)
9951typedef FPL__FUNC_PTHREAD_pthread_setschedparam(fpl__pthread_func_pthread_setschedparam);
9952#define FPL__FUNC_PTHREAD_pthread_getschedparam(name) int name(pthread_t thread, int *policy, struct sched_param *param)
9953typedef FPL__FUNC_PTHREAD_pthread_getschedparam(fpl__pthread_func_pthread_getschedparam);
9954#define FPL__FUNC_PTHREAD_pthread_setschedprio(name) int name(pthread_t thread, int prio)
9955typedef FPL__FUNC_PTHREAD_pthread_setschedprio(fpl__pthread_func_pthread_setschedprio);
9957#define FPL__FUNC_PTHREAD_pthread_attr_init(name) int name(pthread_attr_t *attr)
9958typedef FPL__FUNC_PTHREAD_pthread_attr_init(fpl__pthread_func_pthread_attr_init);
9959#define FPL__FUNC_PTHREAD_pthread_attr_getschedparam(name) int name(const pthread_attr_t *__restrict__ attr, struct sched_param *__restrict__ param)
9960typedef FPL__FUNC_PTHREAD_pthread_attr_getschedparam(fpl__pthread_func_pthread_attr_getschedparam);
9961#define FPL__FUNC_PTHREAD_pthread_attr_setschedparam(name) int name(pthread_attr_t *__restrict__ attr, const struct sched_param *__restrict__ param)
9962typedef FPL__FUNC_PTHREAD_pthread_attr_setschedparam(fpl__pthread_func_pthread_attr_setschedparam);
9963#define FPL__FUNC_PTHREAD_pthread_attr_setstacksize(name) int name(pthread_attr_t *attr, size_t stacksize)
9964typedef FPL__FUNC_PTHREAD_pthread_attr_setstacksize(fpl__pthread_func_pthread_attr_setstacksize);
9965#define FPL__FUNC_PTHREAD_pthread_attr_setdetachstate(name) int name(pthread_attr_t *attr, int detachstate);
9966typedef FPL__FUNC_PTHREAD_pthread_attr_setdetachstate(fpl__pthread_func_pthread_attr_setdetachstate);
9967#define FPL__FUNC_PTHREAD_pthread_attr_setschedpolicy(name) int name(pthread_attr_t *__attr, int __policy)
9968typedef FPL__FUNC_PTHREAD_pthread_attr_setschedpolicy(fpl__pthread_func_pthread_attr_setschedpolicy);
9970#define FPL__FUNC_PTHREAD_pthread_create(name) int name(pthread_t *, const pthread_attr_t *, void *(*__start_routine) (void *), void *)
9971typedef FPL__FUNC_PTHREAD_pthread_create(fpl__pthread_func_pthread_create);
9972#define FPL__FUNC_PTHREAD_pthread_kill(name) int name(pthread_t thread, int sig)
9973typedef FPL__FUNC_PTHREAD_pthread_kill(fpl__pthread_func_pthread_kill);
9974#define FPL__FUNC_PTHREAD_pthread_join(name) int name(pthread_t __th, void **retval)
9975typedef FPL__FUNC_PTHREAD_pthread_join(fpl__pthread_func_pthread_join);
9976#define FPL__FUNC_PTHREAD_pthread_exit(name) void name(void *__retval)
9977typedef FPL__FUNC_PTHREAD_pthread_exit(fpl__pthread_func_pthread_exit);
9978#define FPL__FUNC_PTHREAD_pthread_yield(name) int name(void)
9979typedef FPL__FUNC_PTHREAD_pthread_yield(fpl__pthread_func_pthread_yield);
9980#define FPL__FUNC_PTHREAD_pthread_timedjoin_np(name) int name(pthread_t thread, void **retval, const struct timespec *abstime)
9981typedef FPL__FUNC_PTHREAD_pthread_timedjoin_np(fpl__pthread_func_pthread_timedjoin_np);
9983#define FPL__FUNC_PTHREAD_pthread_mutex_init(name) int name(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
9984typedef FPL__FUNC_PTHREAD_pthread_mutex_init(fpl__pthread_func_pthread_mutex_init);
9985#define FPL__FUNC_PTHREAD_pthread_mutex_destroy(name) int name(pthread_mutex_t *mutex)
9986typedef FPL__FUNC_PTHREAD_pthread_mutex_destroy(fpl__pthread_func_pthread_mutex_destroy);
9987#define FPL__FUNC_PTHREAD_pthread_mutex_lock(name) int name(pthread_mutex_t *mutex)
9988typedef FPL__FUNC_PTHREAD_pthread_mutex_lock(fpl__pthread_func_pthread_mutex_lock);
9989#define FPL__FUNC_PTHREAD_pthread_mutex_trylock(name) int name(pthread_mutex_t *mutex)
9990typedef FPL__FUNC_PTHREAD_pthread_mutex_trylock(fpl__pthread_func_pthread_mutex_trylock);
9991#define FPL__FUNC_PTHREAD_pthread_mutex_unlock(name) int name(pthread_mutex_t *mutex)
9992typedef FPL__FUNC_PTHREAD_pthread_mutex_unlock(fpl__pthread_func_pthread_mutex_unlock);
9994#define FPL__FUNC_PTHREAD_pthread_cond_init(name) int name(pthread_cond_t *cond, const pthread_condattr_t *attr)
9995typedef FPL__FUNC_PTHREAD_pthread_cond_init(fpl__pthread_func_pthread_cond_init);
9996#define FPL__FUNC_PTHREAD_pthread_cond_destroy(name) int name(pthread_cond_t *cond)
9997typedef FPL__FUNC_PTHREAD_pthread_cond_destroy(fpl__pthread_func_pthread_cond_destroy);
9998#define FPL__FUNC_PTHREAD_pthread_cond_timedwait(name) int name(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
9999typedef FPL__FUNC_PTHREAD_pthread_cond_timedwait(fpl__pthread_func_pthread_cond_timedwait);
10000#define FPL__FUNC_PTHREAD_pthread_cond_wait(name) int name(pthread_cond_t *cond, pthread_mutex_t *mutex)
10001typedef FPL__FUNC_PTHREAD_pthread_cond_wait(fpl__pthread_func_pthread_cond_wait);
10002#define FPL__FUNC_PTHREAD_pthread_cond_broadcast(name) int name(pthread_cond_t *cond)
10003typedef FPL__FUNC_PTHREAD_pthread_cond_broadcast(fpl__pthread_func_pthread_cond_broadcast);
10004#define FPL__FUNC_PTHREAD_pthread_cond_signal(name) int name(pthread_cond_t *cond)
10005typedef FPL__FUNC_PTHREAD_pthread_cond_signal(fpl__pthread_func_pthread_cond_signal);
10007#define FPL__FUNC_PTHREAD_sem_init(name) int name(sem_t *__sem, int __pshared, unsigned int __value)
10008typedef FPL__FUNC_PTHREAD_sem_init(fpl__pthread_func_sem_init);
10009#define FPL__FUNC_PTHREAD_sem_destroy(name) int name(sem_t *__sem)
10010typedef FPL__FUNC_PTHREAD_sem_destroy(fpl__pthread_func_sem_destroy);
10011#define FPL__FUNC_PTHREAD_sem_wait(name) int name(sem_t *__sem)
10012typedef FPL__FUNC_PTHREAD_sem_wait(fpl__pthread_func_sem_wait);
10013#define FPL__FUNC_PTHREAD_sem_timedwait(name) int name(sem_t *__restrict __sem, const struct timespec *__restrict __abstime)
10014typedef FPL__FUNC_PTHREAD_sem_timedwait(fpl__pthread_func_sem_timedwait);
10015#define FPL__FUNC_PTHREAD_sem_trywait(name) int name(sem_t *__sem)
10016typedef FPL__FUNC_PTHREAD_sem_trywait(fpl__pthread_func_sem_trywait);
10017#define FPL__FUNC_PTHREAD_sem_post(name) int name(sem_t *__sem)
10018typedef FPL__FUNC_PTHREAD_sem_post(fpl__pthread_func_sem_post);
10019#define FPL__FUNC_PTHREAD_sem_getvalue(name) int name(sem_t *__restrict __sem, int *__restrict __sval)
10020typedef FPL__FUNC_PTHREAD_sem_getvalue(fpl__pthread_func_sem_getvalue);
10022typedef struct fpl__PThreadApi {
10026 fpl__pthread_func_pthread_self *pthread_self;
10027 fpl__pthread_func_pthread_setschedparam *pthread_setschedparam;
10028 fpl__pthread_func_pthread_getschedparam *pthread_getschedparam;
10029 fpl__pthread_func_pthread_setschedprio *pthread_setschedprio;
10031 fpl__pthread_func_pthread_create *pthread_create;
10032 fpl__pthread_func_pthread_kill *pthread_kill;
10033 fpl__pthread_func_pthread_join *pthread_join;
10034 fpl__pthread_func_pthread_exit *pthread_exit;
10035 fpl__pthread_func_pthread_yield *pthread_yield;
10036 fpl__pthread_func_pthread_timedjoin_np *pthread_timedjoin_np;
10039 fpl__pthread_func_pthread_attr_init *pthread_attr_init;
10040 fpl__pthread_func_pthread_attr_getschedparam *pthread_attr_getschedparam;
10041 fpl__pthread_func_pthread_attr_setschedparam *pthread_attr_setschedparam;
10042 fpl__pthread_func_pthread_attr_setstacksize *pthread_attr_setstacksize;
10043 fpl__pthread_func_pthread_attr_setdetachstate *pthread_attr_setdetachstate;
10044 fpl__pthread_func_pthread_attr_setschedpolicy *pthread_attr_setschedpolicy;
10047 fpl__pthread_func_pthread_mutex_init *pthread_mutex_init;
10048 fpl__pthread_func_pthread_mutex_destroy *pthread_mutex_destroy;
10049 fpl__pthread_func_pthread_mutex_lock *pthread_mutex_lock;
10050 fpl__pthread_func_pthread_mutex_trylock *pthread_mutex_trylock;
10051 fpl__pthread_func_pthread_mutex_unlock *pthread_mutex_unlock;
10054 fpl__pthread_func_pthread_cond_init *pthread_cond_init;
10055 fpl__pthread_func_pthread_cond_destroy *pthread_cond_destroy;
10056 fpl__pthread_func_pthread_cond_timedwait *pthread_cond_timedwait;
10057 fpl__pthread_func_pthread_cond_wait *pthread_cond_wait;
10058 fpl__pthread_func_pthread_cond_broadcast *pthread_cond_broadcast;
10059 fpl__pthread_func_pthread_cond_signal *pthread_cond_signal;
10062 fpl__pthread_func_sem_init *sem_init;
10063 fpl__pthread_func_sem_destroy *sem_destroy;
10064 fpl__pthread_func_sem_wait *sem_wait;
10065 fpl__pthread_func_sem_timedwait *sem_timedwait;
10066 fpl__pthread_func_sem_trywait *sem_trywait;
10067 fpl__pthread_func_sem_post *sem_post;
10068 fpl__pthread_func_sem_getvalue *sem_getvalue;
10071#define FPL__POSIX_DL_LOADTYPE RTLD_NOW
10073fpl_internal void fpl__PThreadUnloadApi(fpl__PThreadApi *pthreadApi) {
10075 if (pthreadApi->libHandle !=
fpl_null) {
10076 dlclose(pthreadApi->libHandle);
10081fpl_internal bool fpl__PThreadLoadApi(fpl__PThreadApi *pthreadApi) {
10082 const char *libpthreadFileNames[] = {
10086 bool result =
false;
10087 for (uint32_t index = 0; index <
fplArrayCount(libpthreadFileNames); ++index) {
10088 const char *libName = libpthreadFileNames[index];
10092 FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_PTHREAD, libHandle, libName);
10095 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_self, pthread_self);
10096 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_setschedparam, pthread_setschedparam);
10097 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_getschedparam, pthread_getschedparam);
10098 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_setschedprio, pthread_setschedprio);
10100 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_create, pthread_create);
10101 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_kill, pthread_kill);
10102 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_join, pthread_join);
10103 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_exit, pthread_exit);
10104 FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_yield, pthread_yield);
10105 FPL__POSIX_GET_FUNCTION_ADDRESS_OPTIONAL(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_timedjoin_np, pthread_timedjoin_np);
10108 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_init, pthread_attr_init);
10109 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_getschedparam, pthread_attr_getschedparam);
10110 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setschedparam, pthread_attr_setschedparam);
10111 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setstacksize, pthread_attr_setstacksize);
10112 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setdetachstate, pthread_attr_setdetachstate);
10113 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
10116 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_init, pthread_mutex_init);
10117 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_destroy, pthread_mutex_destroy);
10118 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_lock, pthread_mutex_lock);
10119 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_trylock, pthread_mutex_trylock);
10120 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_mutex_unlock, pthread_mutex_unlock);
10123 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_init, pthread_cond_init);
10124 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_destroy, pthread_cond_destroy);
10125 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_timedwait, pthread_cond_timedwait);
10126 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_wait, pthread_cond_wait);
10127 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_broadcast, pthread_cond_broadcast);
10128 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_pthread_cond_signal, pthread_cond_signal);
10131 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_init, sem_init);
10132 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_destroy, sem_destroy);
10133 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_wait, sem_wait);
10134 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_timedwait, sem_timedwait);
10135 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_trywait, sem_trywait);
10136 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_post, sem_post);
10137 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_PTHREAD, libHandle, libName, pthreadApi, fpl__pthread_func_sem_getvalue, sem_getvalue);
10139 pthreadApi->libHandle = libHandle;
10145 fpl__PThreadUnloadApi(pthreadApi);
10150typedef struct fpl__PosixInitState {
10152} fpl__PosixInitState;
10154typedef struct fpl__PosixAppState {
10155 fpl__PThreadApi pthreadApi;
10156} fpl__PosixAppState;
10164#if defined(FPL_PLATFORM_LINUX)
10165typedef struct fpl__LinuxInitState {
10167} fpl__LinuxInitState;
10169#if defined(FPL__ENABLE_WINDOW)
10170#define FPL__LINUX_MAX_GAME_CONTROLLER_COUNT 4
10171typedef struct fpl__LinuxGameController {
10172 char deviceName[512 + 1];
10176 uint8_t buttonCount;
10177 fplGamepadState state;
10178} fpl__LinuxGameController;
10180typedef struct fpl__LinuxGameControllersState {
10181 fpl__LinuxGameController controllers[FPL__LINUX_MAX_GAME_CONTROLLER_COUNT];
10182 uint64_t lastCheckTime;
10183} fpl__LinuxGameControllersState;
10186typedef struct fpl__LinuxAppState {
10187#if defined(FPL__ENABLE_WINDOW)
10188 fpl__LinuxGameControllersState controllersState;
10191} fpl__LinuxAppState;
10194#if defined(FPL__ENABLE_WINDOW)
10195fpl_internal void fpl__LinuxFreeGameControllers(fpl__LinuxGameControllersState *controllersState);
10196fpl_internal void fpl__LinuxPollGameControllers(
const fplSettings *settings, fpl__LinuxGameControllersState *controllersState,
const bool useEvents);
10206#if defined(FPL_PLATFORM_UNIX)
10207typedef struct fpl__UnixInitState {
10209} fpl__UnixInitState;
10211typedef struct fpl__UnixAppState {
10213} fpl__UnixAppState;
10221#if defined(FPL_SUBPLATFORM_X11)
10223#include <X11/keysym.h>
10228#define FPL__FUNC_X11_XFree(name) int name(void *data)
10229typedef FPL__FUNC_X11_XFree(fpl__func_x11_XFree);
10230#define FPL__FUNC_X11_XFlush(name) int name(Display *display)
10231typedef FPL__FUNC_X11_XFlush(fpl__func_x11_XFlush);
10232#define FPL__FUNC_X11_XOpenDisplay(name) Display *name(char *display_name)
10233typedef FPL__FUNC_X11_XOpenDisplay(fpl__func_x11_XOpenDisplay);
10234#define FPL__FUNC_X11_XCloseDisplay(name) int name(Display *display)
10235typedef FPL__FUNC_X11_XCloseDisplay(fpl__func_x11_XCloseDisplay);
10236#define FPL__FUNC_X11_XDefaultScreen(name) int name(Display *display)
10237typedef FPL__FUNC_X11_XDefaultScreen(fpl__func_x11_XDefaultScreen);
10238#define FPL__FUNC_X11_XRootWindow(name) Window name(Display *display, int screen_number)
10239typedef FPL__FUNC_X11_XRootWindow(fpl__func_x11_XRootWindow);
10240#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)
10241typedef FPL__FUNC_X11_XCreateWindow(fpl__func_x11_XCreateWindow);
10242#define FPL__FUNC_X11_XDestroyWindow(name) int name(Display *display, Window w)
10243typedef FPL__FUNC_X11_XDestroyWindow(fpl__func_x11_XDestroyWindow);
10244#define FPL__FUNC_X11_XCreateColormap(name) Colormap name(Display *display, Window w, Visual *visual, int alloc)
10245typedef FPL__FUNC_X11_XCreateColormap(fpl__func_x11_XCreateColormap);
10246#define FPL__FUNC_X11_XDefaultColormap(name) Colormap name(Display *display, int screen_number)
10247typedef FPL__FUNC_X11_XDefaultColormap(fpl__func_x11_XDefaultColormap);
10248#define FPL__FUNC_X11_XFreeColormap(name) int name(Display *display, Colormap colormap)
10249typedef FPL__FUNC_X11_XFreeColormap(fpl__func_x11_XFreeColormap);
10250#define FPL__FUNC_X11_XMapWindow(name) int name(Display *display, Window w)
10251typedef FPL__FUNC_X11_XMapWindow(fpl__func_x11_XMapWindow);
10252#define FPL__FUNC_X11_XUnmapWindow(name) int name(Display *display, Window w)
10253typedef FPL__FUNC_X11_XUnmapWindow(fpl__func_x11_XUnmapWindow);
10254#define FPL__FUNC_X11_XStoreName(name) int name(Display *display, Window w, _Xconst char *window_name)
10255typedef FPL__FUNC_X11_XStoreName(fpl__func_x11_XStoreName);
10256#define FPL__FUNC_X11_XDefaultVisual(name) Visual *name(Display *display, int screen_number)
10257typedef FPL__FUNC_X11_XDefaultVisual(fpl__func_x11_XDefaultVisual);
10258#define FPL__FUNC_X11_XDefaultDepth(name) int name(Display *display, int screen_number)
10259typedef FPL__FUNC_X11_XDefaultDepth(fpl__func_x11_XDefaultDepth);
10260#define FPL__FUNC_X11_XInternAtom(name) Atom name(Display *display, const char *atom_name, Bool only_if_exists)
10261typedef FPL__FUNC_X11_XInternAtom(fpl__func_x11_XInternAtom);
10262#define FPL__FUNC_X11_XSetWMProtocols(name) Status name(Display *display, Window w, Atom *protocols, int count)
10263typedef FPL__FUNC_X11_XSetWMProtocols(fpl__func_x11_XSetWMProtocols);
10264#define FPL__FUNC_X11_XPending(name) int name(Display *display)
10265typedef FPL__FUNC_X11_XPending(fpl__func_x11_XPending);
10266#define FPL__FUNC_X11_XSync(name) int name(Display *display, Bool discard)
10267typedef FPL__FUNC_X11_XSync(fpl__func_x11_XSync);
10268#define FPL__FUNC_X11_XNextEvent(name) int name(Display *display, XEvent *event_return)
10269typedef FPL__FUNC_X11_XNextEvent(fpl__func_x11_XNextEvent);
10270#define FPL__FUNC_X11_XPeekEvent(name) int name(Display *display, XEvent *event_return)
10271typedef FPL__FUNC_X11_XPeekEvent(fpl__func_x11_XPeekEvent);
10272#define FPL__FUNC_X11_XEventsQueued(name) int name(Display *display, int mode)
10273typedef FPL__FUNC_X11_XEventsQueued(fpl__func_x11_XEventsQueued);
10274#define FPL__FUNC_X11_XGetWindowAttributes(name) Status name(Display *display, Window w, XWindowAttributes *window_attributes_return)
10275typedef FPL__FUNC_X11_XGetWindowAttributes(fpl__func_x11_XGetWindowAttributes);
10276#define FPL__FUNC_X11_XResizeWindow(name) int name(Display *display, Window w, unsigned int width, unsigned int height)
10277typedef FPL__FUNC_X11_XResizeWindow(fpl__func_x11_XResizeWindow);
10278#define FPL__FUNC_X11_XMoveWindow(name) int name(Display *display, Window w, int x, int y)
10279typedef FPL__FUNC_X11_XMoveWindow(fpl__func_x11_XMoveWindow);
10280#define FPL__FUNC_X11_XGetKeyboardMapping(name) KeySym *name(Display *display, KeyCode first_keycode, int keycode_count, int *keysyms_per_keycode_return)
10281typedef FPL__FUNC_X11_XGetKeyboardMapping(fpl__func_x11_XGetKeyboardMapping);
10282#define FPL__FUNC_X11_XLookupString(name) int name(XKeyEvent* event_struct, char* buffer_return, int bytes_buffer, KeySym* keysym_return, XComposeStatus* status_in_out)
10283typedef FPL__FUNC_X11_XLookupString(fpl__func_x11_XLookupString);
10284#define FPL__FUNC_X11_XSendEvent(name) Status name(Display *display, Window w, Bool propagate, long event_mask, XEvent *event_send)
10285typedef FPL__FUNC_X11_XSendEvent(fpl__func_x11_XSendEvent);
10286#define FPL__FUNC_X11_XMatchVisualInfo(name) Status name(Display* display, int screen, int depth, int clazz, XVisualInfo* vinfo_return)
10287typedef FPL__FUNC_X11_XMatchVisualInfo(fpl__func_x11_XMatchVisualInfo);
10288#define FPL__FUNC_X11_XCreateGC(name) GC name(Display* display, Drawable d, unsigned long valuemask, XGCValues* values)
10289typedef FPL__FUNC_X11_XCreateGC(fpl__func_x11_XCreateGC);
10290#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)
10291typedef FPL__FUNC_X11_XGetImage(fpl__func_x11_XGetImage);
10292#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)
10293typedef FPL__FUNC_X11_XCreateImage(fpl__func_x11_XCreateImage);
10294#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)
10295typedef FPL__FUNC_X11_XPutImage(fpl__func_x11_XPutImage);
10296#define FPL__FUNC_X11_XMapRaised(name) int name(Display *display, Window w)
10297typedef FPL__FUNC_X11_XMapRaised(fpl__func_x11_XMapRaised);
10298#define FPL__FUNC_X11_XCreatePixmap(name) Pixmap name(Display * display, Drawable d, unsigned int width, unsigned int height, unsigned int depth)
10299typedef FPL__FUNC_X11_XCreatePixmap(fpl__func_x11_XCreatePixmap);
10300#define FPL__FUNC_X11_XSelectInput(name) int name(Display * display, Window w, long eventMask)
10301typedef FPL__FUNC_X11_XSelectInput(fpl__func_x11_XSelectInput);
10302#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)
10303typedef FPL__FUNC_X11_XGetWindowProperty(fpl__func_x11_XGetWindowProperty);
10304#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)
10305typedef FPL__FUNC_X11_XChangeProperty(fpl__func_x11_XChangeProperty);
10306#define FPL__FUNC_X11_XDeleteProperty(name) int name(Display* display, Window w,Atom prop)
10307typedef FPL__FUNC_X11_XDeleteProperty(fpl__func_x11_XDeleteProperty);
10308#define FPL__FUNC_X11_XStringListToTextProperty(name) Status name(char** list, int count, XTextProperty* text_prop_return)
10309typedef FPL__FUNC_X11_XStringListToTextProperty(fpl__func_x11_XStringListToTextProperty);
10310#define FPL__FUNC_X11_XSetWMIconName(name) void name(Display* display, Window w, XTextProperty *text_prop)
10311typedef FPL__FUNC_X11_XSetWMIconName(fpl__func_x11_XSetWMIconName);
10312#define FPL__FUNC_X11_XSetWMName(name) void name(Display* display, Window w, XTextProperty *text_prop)
10313typedef FPL__FUNC_X11_XSetWMName(fpl__func_x11_XSetWMName);
10314#define FPL__FUNC_X11_XQueryKeymap(name) int name(Display* display, char [32])
10315typedef FPL__FUNC_X11_XQueryKeymap(fpl__func_x11_XQueryKeymap);
10316#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)
10317typedef FPL__FUNC_X11_XQueryPointer(fpl__func_x11_XQueryPointer);
10318#define FPL__FUNC_X11_XConvertSelection(name) int name(Display *display, Atom selection, Atom target, Atom property, Window requestor, Time time)
10319typedef FPL__FUNC_X11_XConvertSelection(fpl__func_x11_XConvertSelection);
10320#define FPL__FUNC_X11_XInitThreads(name) Status name(void)
10321typedef FPL__FUNC_X11_XInitThreads(fpl__func_x11_XInitThreads);
10322#define FPL__FUNC_X11_XSetErrorHandler(name) XErrorHandler name(XErrorHandler *handler)
10323typedef FPL__FUNC_X11_XSetErrorHandler(fpl__func_x11_XSetErrorHandler);
10325typedef struct fpl__X11Api {
10327 fpl__func_x11_XFlush *XFlush;
10328 fpl__func_x11_XFree *XFree;
10329 fpl__func_x11_XOpenDisplay *XOpenDisplay;
10330 fpl__func_x11_XCloseDisplay *XCloseDisplay;
10331 fpl__func_x11_XDefaultScreen *XDefaultScreen;
10332 fpl__func_x11_XRootWindow *XRootWindow;
10333 fpl__func_x11_XCreateWindow *XCreateWindow;
10334 fpl__func_x11_XDestroyWindow *XDestroyWindow;
10335 fpl__func_x11_XCreateColormap *XCreateColormap;
10336 fpl__func_x11_XFreeColormap *XFreeColormap;
10337 fpl__func_x11_XDefaultColormap *XDefaultColormap;
10338 fpl__func_x11_XMapWindow *XMapWindow;
10339 fpl__func_x11_XUnmapWindow *XUnmapWindow;
10340 fpl__func_x11_XStoreName *XStoreName;
10341 fpl__func_x11_XDefaultVisual *XDefaultVisual;
10342 fpl__func_x11_XDefaultDepth *XDefaultDepth;
10343 fpl__func_x11_XInternAtom *XInternAtom;
10344 fpl__func_x11_XSetWMProtocols *XSetWMProtocols;
10345 fpl__func_x11_XPending *XPending;
10346 fpl__func_x11_XSync *XSync;
10347 fpl__func_x11_XNextEvent *XNextEvent;
10348 fpl__func_x11_XPeekEvent *XPeekEvent;
10349 fpl__func_x11_XEventsQueued *XEventsQueued;
10350 fpl__func_x11_XGetWindowAttributes *XGetWindowAttributes;
10351 fpl__func_x11_XResizeWindow *XResizeWindow;
10352 fpl__func_x11_XMoveWindow *XMoveWindow;
10353 fpl__func_x11_XGetKeyboardMapping *XGetKeyboardMapping;
10354 fpl__func_x11_XLookupString *XLookupString;
10355 fpl__func_x11_XSendEvent *XSendEvent;
10356 fpl__func_x11_XMatchVisualInfo *XMatchVisualInfo;
10357 fpl__func_x11_XCreateGC *XCreateGC;
10358 fpl__func_x11_XGetImage *XGetImage;
10359 fpl__func_x11_XPutImage *XPutImage;
10360 fpl__func_x11_XMapRaised *XMapRaised;
10361 fpl__func_x11_XCreateImage *XCreateImage;
10362 fpl__func_x11_XCreatePixmap *XCreatePixmap;
10363 fpl__func_x11_XSelectInput *XSelectInput;
10364 fpl__func_x11_XGetWindowProperty *XGetWindowProperty;
10365 fpl__func_x11_XChangeProperty *XChangeProperty;
10366 fpl__func_x11_XDeleteProperty *XDeleteProperty;
10367 fpl__func_x11_XStringListToTextProperty *XStringListToTextProperty;
10368 fpl__func_x11_XSetWMIconName *XSetWMIconName;
10369 fpl__func_x11_XSetWMName *XSetWMName;
10370 fpl__func_x11_XQueryKeymap *XQueryKeymap;
10371 fpl__func_x11_XQueryPointer *XQueryPointer;
10372 fpl__func_x11_XConvertSelection *XConvertSelection;
10373 fpl__func_x11_XInitThreads *XInitThreads;
10374 fpl__func_x11_XSetErrorHandler *XSetErrorHandler;
10377fpl_internal void fpl__UnloadX11Api(fpl__X11Api *x11Api) {
10379 if (x11Api->libHandle !=
fpl_null) {
10380 dlclose(x11Api->libHandle);
10385fpl_internal bool fpl__LoadX11Api(fpl__X11Api *x11Api) {
10387 const char *libFileNames[] = {
10393 bool result =
false;
10394 for (uint32_t index = 0; index <
fplArrayCount(libFileNames); ++index) {
10395 const char *libName = libFileNames[index];
10399 FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_X11, libHandle, libName);
10400 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XFlush, XFlush);
10401 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XFree, XFree);
10402 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XOpenDisplay, XOpenDisplay);
10403 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCloseDisplay, XCloseDisplay);
10404 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultScreen, XDefaultScreen);
10405 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XRootWindow, XRootWindow);
10406 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateWindow, XCreateWindow);
10407 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDestroyWindow, XDestroyWindow);
10408 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateColormap, XCreateColormap);
10409 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XFreeColormap, XFreeColormap);
10410 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultColormap, XDefaultColormap);
10411 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMapWindow, XMapWindow);
10412 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XUnmapWindow, XUnmapWindow);
10413 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XStoreName, XStoreName);
10414 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultVisual, XDefaultVisual);
10415 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDefaultDepth, XDefaultDepth);
10416 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XInternAtom, XInternAtom);
10417 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetWMProtocols, XSetWMProtocols);
10418 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XPending, XPending);
10419 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSync, XSync);
10420 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XNextEvent, XNextEvent);
10421 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XPeekEvent, XPeekEvent);
10422 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XEventsQueued, XEventsQueued);
10423 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetWindowAttributes, XGetWindowAttributes);
10424 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XResizeWindow, XResizeWindow);
10425 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMoveWindow, XMoveWindow);
10426 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetKeyboardMapping, XGetKeyboardMapping);
10427 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XLookupString, XLookupString);
10428 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSendEvent, XSendEvent);
10429 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMatchVisualInfo, XMatchVisualInfo);
10430 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateGC, XCreateGC);
10431 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetImage, XGetImage);
10432 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XPutImage, XPutImage);
10433 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XMapRaised, XMapRaised);
10434 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreateImage, XCreateImage);
10435 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XCreatePixmap, XCreatePixmap);
10436 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSelectInput, XSelectInput);
10437 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XGetWindowProperty, XGetWindowProperty);
10438 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XChangeProperty, XChangeProperty);
10439 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XDeleteProperty, XDeleteProperty);
10440 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XStringListToTextProperty, XStringListToTextProperty);
10441 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetWMIconName, XSetWMIconName);
10442 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetWMName, XSetWMName);
10443 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XQueryKeymap, XQueryKeymap);
10444 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XQueryPointer, XQueryPointer);
10445 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XConvertSelection, XConvertSelection);
10446 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XInitThreads, XInitThreads);
10447 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_X11, libHandle, libName, x11Api, fpl__func_x11_XSetErrorHandler, XSetErrorHandler);
10448 x11Api->libHandle = libHandle;
10454 fpl__UnloadX11Api(x11Api);
10459typedef struct fpl__X11SubplatformState {
10461} fpl__X11SubplatformState;
10463typedef struct fpl__X11WindowStateInfo {
10466 fplWindowPosition position;
10467 fplWindowSize size;
10468} fpl__X11WindowStateInfo;
10470typedef struct fpl__X11Xdnd {
10476#define FPL__FUNC_X11_ErrorHandlerCallback(name) int name(Display *display, XErrorEvent *ev)
10477typedef FPL__FUNC_X11_ErrorHandlerCallback(fpl__func_X11ErrorHandlerCallback);
10479typedef struct fpl__X11WindowState {
10480 fpl__X11WindowStateInfo lastWindowStateInfo;
10483 fpl__func_X11ErrorHandlerCallback *lastErrorHandler;
10489 Atom wmDeleteWindow;
10493 Atom netWMStateFocused;
10494 Atom netWMStateFullscreen;
10495 Atom netWMStateHidden;
10496 Atom netWMStateMaximizedVert;
10497 Atom netWMStateMaximizedHorz;
10501 Atom netWMIconName;
10509 Atom xdndActionCopy;
10512 Atom xdndSelection;
10517} fpl__X11WindowState;
10519#define FPL__XDND_VERSION 5
10531#if !defined(FPL__PLATFORM_STATES_DEFINED)
10532#define FPL__PLATFORM_STATES_DEFINED
10536typedef struct fpl__PlatformInitSettings {
10537 fplMemorySettings memorySettings;
10538} fpl__PlatformInitSettings;
10540typedef struct fpl__PlatformInitState {
10541#if defined(FPL_SUBPLATFORM_POSIX)
10542 fpl__PosixInitState posix;
10545 fpl__PlatformInitSettings initSettings;
10550# if defined(FPL_PLATFORM_WINDOWS)
10551 fpl__Win32InitState win32;
10552# elif defined(FPL_PLATFORM_LINUX)
10553 fpl__LinuxInitState plinux;
10554# elif defined(FPL_PLATFORM_UNIX)
10555 fpl__UnixInitState punix;
10558} fpl__PlatformInitState;
10561#if defined(FPL__ENABLE_WINDOW)
10562#define FPL__MAX_EVENT_COUNT 32768
10563typedef struct fpl__EventQueue {
10565 fplEvent events[FPL__MAX_EVENT_COUNT];
10566 uint32_t pollIndex;
10567 uint32_t pushCount;
10570typedef struct fpl__PlatformWindowState {
10571 fpl__EventQueue eventQueue;
10574 uint64_t keyPressTimes[256];
10578#if defined(FPL_PLATFORM_WINDOWS)
10579 fpl__Win32WindowState win32;
10581#if defined(FPL_SUBPLATFORM_X11)
10582 fpl__X11WindowState x11;
10584} fpl__PlatformWindowState;
10587#if defined(FPL__ENABLE_VIDEO)
10588typedef struct fpl__PlatformVideoState {
10591} fpl__PlatformVideoState;
10594#if defined(FPL__ENABLE_AUDIO)
10595typedef struct fpl__PlatformAudioState {
10598 size_t maxBackendSize;
10599 uintptr_t offsetToBackend;
10600} fpl__PlatformAudioState;
10606typedef struct fpl__PlatformAppState fpl__PlatformAppState;
10607struct fpl__PlatformAppState {
10609#if defined(FPL_SUBPLATFORM_POSIX)
10610 fpl__PosixAppState posix;
10612#if defined(FPL_SUBPLATFORM_X11)
10613 fpl__X11SubplatformState x11;
10617#if defined(FPL__ENABLE_WINDOW)
10618 fpl__PlatformWindowState window;
10620#if defined(FPL__ENABLE_VIDEO)
10621 fpl__PlatformVideoState video;
10623#if defined(FPL__ENABLE_AUDIO)
10624 fpl__PlatformAudioState audio;
10628 fplSettings initSettings;
10629 fplSettings currentSettings;
10634# if defined(FPL_PLATFORM_WINDOWS)
10635 fpl__Win32AppState win32;
10636# elif defined(FPL_PLATFORM_LINUX)
10637 fpl__LinuxAppState plinux;
10638# elif defined(FPL_PLATFORM_UNIX)
10639 fpl__UnixAppState plinux;
10647#if defined(FPL__ENABLE_WINDOW)
10648fpl_internal fplKey fpl__GetMappedKey(
const fpl__PlatformWindowState *windowState,
const uint64_t keyCode) {
10651 result = windowState->keyMap[keyCode];
10653 result = fplKey_None;
10658 fpl__PlatformAppState *appState = fpl__global__AppState;
10660 fpl__EventQueue *eventQueue = &appState->window.eventQueue;
10662 uint32_t eventCount = eventQueue->pollIndex;
10663 eventQueue->pollIndex = 0;
10664 for (
size_t eventIndex = 0; eventIndex < eventCount; ++eventIndex) {
10665 fplEvent *ev = &eventQueue->events[eventIndex];
10671 eventQueue->pushCount = 0;
10675 fpl__PlatformAppState *appState = fpl__global__AppState;
10676 bool result =
false;
10678 fpl__EventQueue *eventQueue = &appState->window.eventQueue;
10680 if (eventQueue->pollIndex < eventQueue->pushCount) {
10681 uint32_t eventIndex = eventQueue->pollIndex++;
10682 *ev = eventQueue->events[eventIndex];
10684 }
else if (eventQueue->pushCount > 0) {
10685 eventQueue->pollIndex = 0;
10686 eventQueue->pushCount = 0;
10693 fpl__PlatformAppState *appState = fpl__global__AppState;
10695 fpl__EventQueue *eventQueue = &appState->window.eventQueue;
10697 if (eventQueue->pushCount < FPL__MAX_EVENT_COUNT) {
10698 uint32_t eventIndex = eventQueue->pushCount++;
10699 eventQueue->events[eventIndex] = *event;
10707 fpl__PushInternalEvent(&newEvent);
10716 fpl__PushInternalEvent(&newEvent);
10725 fpl__PushInternalEvent(&newEvent);
10728fpl_internal void fpl__PushWindowDropFilesEvent(
const char *filePath,
const size_t fileCount,
const char **files,
const fplMemoryBlock *memory) {
10735 fpl__PushInternalEvent(&newEvent);
10746 fpl__PushInternalEvent(&newEvent);
10749fpl_internal void fpl__PushKeyboardInputEvent(
const uint32_t textCode,
const fplKey mappedKey) {
10755 fpl__PushInternalEvent(&newEvent);
10766 fpl__PushInternalEvent(&newEvent);
10769fpl_internal void fpl__PushMouseWheelEvent(
const int32_t x,
const int32_t y,
const float wheelDelta) {
10777 fpl__PushInternalEvent(&newEvent);
10780fpl_internal void fpl__PushMouseMoveEvent(
const int32_t x,
const int32_t y) {
10787 fpl__PushInternalEvent(&newEvent);
10791#if defined(FPL_LOG_KEY_EVENTS)
10792 const char *buttonStateName =
"";
10794 buttonStateName =
"Press";
10796 buttonStateName =
"Repeat";
10798 buttonStateName =
"Released";
10799 FPL_LOG_INFO(FPL__MODULE_OS,
"[%llu] Keyboard button event with keycode: '%llu', state: '%s'", time, keyCode, buttonStateName);
10802 fplKey mappedKey = fpl__GetMappedKey(windowState, keyCode);
10803 bool repeat =
false;
10806 windowState->keyStates[keyCode] = buttonState;
10815 windowState->keyStates[keyCode] = buttonState;
10818 fpl__PushKeyboardButtonEvent(keyCode, mappedKey, modifiers, repeat ?
fplButtonState_Repeat : buttonState);
10821fpl_internal void fpl__HandleKeyboardInputEvent(fpl__PlatformWindowState *windowState,
const uint64_t keyCode,
const uint32_t textCode) {
10822 fplKey mappedKey = fpl__GetMappedKey(windowState, keyCode);
10823 fpl__PushKeyboardInputEvent(textCode, mappedKey);
10827 if (mouseButton <
fplArrayCount(windowState->mouseStates)) {
10828 windowState->mouseStates[(int)mouseButton] = buttonState;
10830 fpl__PushMouseButtonEvent(x, y, mouseButton, buttonState);
10833fpl_internal void fpl__HandleMouseMoveEvent(fpl__PlatformWindowState *windowState,
const int32_t x,
const int32_t y) {
10834 fpl__PushMouseMoveEvent(x, y);
10837fpl_internal void fpl__HandleMouseWheelEvent(fpl__PlatformWindowState *windowState,
const int32_t x,
const int32_t y,
const float wheelDelta) {
10838 fpl__PushMouseWheelEvent(x, y, wheelDelta);
10842#define FPL__FUNC_PREPARE_VIDEO_WINDOW(name) bool name(fpl__PlatformAppState *appState, const fplInitFlags initFlags, const fplSettings *initSettings)
10843typedef FPL__FUNC_PREPARE_VIDEO_WINDOW(callback_PreSetupWindow);
10846#define FPL__FUNC_FINALIZE_VIDEO_WINDOW(name) bool name(fpl__PlatformAppState *appState, const fplInitFlags initFlags, const fplSettings *initSettings)
10847typedef FPL__FUNC_FINALIZE_VIDEO_WINDOW(callback_PostSetupWindow);
10849typedef struct fpl__SetupWindowCallbacks {
10850 callback_PreSetupWindow *preSetup;
10851 callback_PostSetupWindow *postSetup;
10852} fpl__SetupWindowCallbacks;
10869#if !defined(FPL__COMMON_DEFINED)
10870#define FPL__COMMON_DEFINED
10875fpl_internal void *fpl__AllocateDynamicMemory(
const size_t size,
const size_t alignment) {
10876 void *result = fpl__AllocateMemory(&fpl__global__InitState.initSettings.memorySettings.dynamic, size, alignment);
10880fpl_internal void fpl__ReleaseDynamicMemory(
void *ptr) {
10881 fpl__ReleaseMemory(&fpl__global__InitState.initSettings.memorySettings.dynamic, ptr);
10884fpl_internal void *fpl__AllocateTemporaryMemory(
const size_t size,
const size_t alignment) {
10885 void *result = fpl__AllocateMemory(&fpl__global__InitState.initSettings.memorySettings.temporary, size, alignment);
10889fpl_internal void fpl__ReleaseTemporaryMemory(
void *ptr) {
10890 fpl__ReleaseMemory(&fpl__global__InitState.initSettings.memorySettings.temporary, ptr);
10896static const uint32_t FPL__DEFAULT_AUDIO_SAMPLERATE = 44100;
10898static const uint16_t FPL__DEFAULT_AUDIO_CHANNELS = 2;
10899static const uint16_t FPL__DEFAULT_AUDIO_PERIODS = 3;
10900static const uint32_t FPL__DEFAULT_AUDIO_BUFFERSIZE_LOWLATENCY_IN_MSECS = 10;
10901static const uint32_t FPL__DEFAULT_AUDIO_BUFFERSIZE_CONSERVATIVE_IN_MSECS = 25;
10906#define FPL__MAX_LAST_ERROR_STRING_LENGTH 256
10907#define FPL__MAX_ERRORSTATE_COUNT 256
10909typedef struct fpl__ErrorState {
10910 char errors[FPL__MAX_ERRORSTATE_COUNT][FPL__MAX_LAST_ERROR_STRING_LENGTH];
10916fpl_internal void fpl__PushError_Formatted(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, va_list argList) {
10920 fpl__ErrorState *state = &fpl__global__LastErrorState;
10921 char buffer[FPL__MAX_LAST_ERROR_STRING_LENGTH] =
fplZeroInit;
10923 if (formattedLen > 0) {
10924 fplAssert(state->count < FPL__MAX_ERRORSTATE_COUNT);
10925 size_t errorIndex = state->count;
10926 state->count = (state->count + 1) % FPL__MAX_ERRORSTATE_COUNT;
10927 fplCopyStringLen(buffer, formattedLen, state->errors[errorIndex], FPL__MAX_LAST_ERROR_STRING_LENGTH);
10931#if defined(FPL__ENABLE_LOGGING)
10933 va_copy(listCopy, argList);
10934 fpl__LogWriteArgs(funcName, lineNumber, level, format, listCopy);
10939fpl_internal void fpl__HandleError(
const char *funcName,
const int lineNumber,
const fplLogLevel level,
const char *format, ...) {
10941 va_start(valist, format);
10942 fpl__PushError_Formatted(funcName, lineNumber, level, format, valist);
10945#if defined(FPL_CRASH_ON_ERROR) || defined(FPL_CRASH_ON_WARNING)
10947# if defined(FPL_CRASH_ON_WARNING)
10950 if (level >= minErrorLevel) {
10964fpl_internal void fpl__ArgumentInvalidError(
const char *funcName,
const int line,
const char *paramName) {
10965 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter are not valid", paramName);
10967fpl_internal void fpl__ArgumentNullError(
const char *funcName,
const int line,
const char *paramName) {
10968 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter are not allowed to be null", paramName);
10970fpl_internal void fpl__ArgumentZeroError(
const char *funcName,
const int line,
const char *paramName) {
10971 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter must be greater than zero", paramName);
10973fpl_internal void fpl__ArgumentMinError(
const char *funcName,
const int line,
const char *paramName,
const size_t value,
const size_t minValue) {
10974 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter '%zu' must be greater or equal than '%zu'", paramName, value, minValue);
10976fpl_internal void fpl__ArgumentMaxError(
const char *funcName,
const int line,
const char *paramName,
const size_t value,
const size_t maxValue) {
10977 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter '%zu' must be less or equal than '%zu'", paramName, value, maxValue);
10979fpl_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) {
10980 FPL__M_ERROR(funcName, line, FPL__MODULE_ARGS,
"%s parameter '%zu' must be in range of '%zu' to '%zu'", paramName, value, minValue, maxValue);
10983#define FPL__CheckArgumentInvalid(arg, cond, ret) \
10985 fpl__ArgumentInvalidError(FPL_FUNCTION_NAME, __LINE__, #arg); \
10989#define FPL__CheckArgumentInvalidNoRet(arg, cond) \
10991 fpl__ArgumentInvalidError(FPL_FUNCTION_NAME, __LINE__, #arg); \
10994#define FPL__CheckArgumentNull(arg, ret) \
10995 if((arg) == fpl_null) { \
10996 fpl__ArgumentNullError(FPL_FUNCTION_NAME, __LINE__, #arg); \
10999#define FPL__CheckArgumentNullNoRet(arg) \
11000 if((arg) == fpl_null) { \
11001 fpl__ArgumentNullError(FPL_FUNCTION_NAME, __LINE__, #arg); \
11004#define FPL__CheckArgumentZero(arg, ret) \
11006 fpl__ArgumentZeroError(FPL_FUNCTION_NAME, __LINE__, #arg); \
11009#define FPL__CheckArgumentZeroNoRet(arg) \
11011 fpl__ArgumentZeroError(FPL_FUNCTION_NAME, __LINE__, #arg); \
11014#define FPL__CheckArgumentMin(arg, minValue, ret) \
11015 if((arg) < (minValue)) { \
11016 fpl__ArgumentMinError(FPL_FUNCTION_NAME, __LINE__, #arg, arg, minValue); \
11019#define FPL__CheckArgumentMax(arg, maxValue, ret) \
11020 if((arg) > (maxValue)) { \
11021 fpl__ArgumentMaxError(FPL_FUNCTION_NAME, __LINE__, #arg, arg, maxValue); \
11024#define FPL__CheckPlatform(ret) \
11025 if(fpl__global__AppState == fpl_null) { \
11026 FPL__ERROR(FPL__MODULE_CORE, "[%s] Platform is not initialized", FPL_FUNCTION_NAME); \
11029#define FPL__CheckPlatformNoRet() \
11030 if(fpl__global__AppState == fpl_null) { \
11031 FPL__ERROR(FPL__MODULE_CORE, "[%s] Platform is not initialized", FPL_FUNCTION_NAME); \
11035#define FPL__CheckApi(cond, name, ret) \
11037 FPL__ERROR(FPL__MODULE_API, "The API '%s' is not loaded", (name)); \
11040#define FPL__CheckApiNoRet(cond, name) \
11042 FPL__ERROR(FPL__MODULE_API, "The API '%s' is not loaded", (name)); \
11046#if !defined(FPL_MAX_THREAD_COUNT)
11048# define FPL_MAX_THREAD_COUNT 256
11051#if !defined(FPL_MAX_SIGNAL_COUNT)
11053# define FPL_MAX_SIGNAL_COUNT 256
11056typedef struct fpl__ThreadState {
11065 for (uint32_t index = 0; index < FPL_MAX_THREAD_COUNT; ++index) {
11076fpl_internal bool fpl__IsEqualsMemory(
const void *a,
const void *b,
const size_t size) {
11077 const uint8_t *ptrA = (
const uint8_t *)a;
11078 const uint8_t *ptrB = (
const uint8_t *)b;
11081 bool result =
true;
11084 if (*ptrA != *ptrB) {
11092 result = memcmp(a, b, size) == 0;
11097fpl_internal bool fpl__IsZeroMemory(
const void *memory,
const size_t size) {
11098 const uint8_t *ptr = (
const uint8_t *)memory;
11100 bool result =
true;
11111 result = memcmp(a, b, size) == 0;
11119#if !defined(FPL__COMMON_STRINGS_DEFINED)
11120#define FPL__COMMON_STRINGS_DEFINED
11129 const char *s = source;
11130 const char *w = wildcard;
11137 }
else if (*w ==
'*') {
11141 if ((*s == nw) || (nw ==
'?') || (nw ==
'*')) {
11162 if (aLen != bLen) {
11165 bool result =
true;
11166 for (
size_t index = 0; index < aLen; ++index) {
11167 char aChar = a[index];
11168 char bChar = b[index];
11169 if (aChar != bChar) {
11181 bool result =
true;
11183 const char aChar = *(a++);
11184 const char bChar = *(b++);
11185 if (aChar == 0 || bChar == 0) {
11186 result = (aChar == bChar);
11189 if (aChar != bChar) {
11198 FPL__CheckArgumentNull(path,
fpl_null);
11199 FPL__CheckArgumentZero(maxPathLen,
fpl_null);
11204 size_t len = end - path;
11208 if (len + 1 <= maxPathLen) {
11211 result = &path[len + 1];
11213 FPL__ERROR(FPL__MODULE_PATHS,
"Cannot append path separator: Max length '%zu' of path '%s' is exceeded", maxPathLen, path);
11216 result = &path[len];
11223 FPL__CheckArgumentNull(path,
fpl_null);
11228 size_t len = end - path;
11234 result = &path[len + 1];
11236 result = &path[len];
11243 FPL__CheckArgumentNull(appended,
fpl_null);
11244 FPL__CheckArgumentZero(maxBufferLen,
fpl_null);
11245 if (appendedLen == 0) {
11249 size_t requiredSize = curBufferLen + appendedLen + 1;
11250 FPL__CheckArgumentMin(maxBufferLen, requiredSize,
fpl_null);
11251 char *start = buffer + curBufferLen;
11252 size_t remainingBufferSize = maxBufferLen - (curBufferLen > 0 ? curBufferLen + 1 : 0);
11253 char *result =
fplCopyStringLen(appended, appendedLen, start, remainingBufferSize);
11264 uint32_t result = 0;
11275 size_t requiredLen = sourceLen + 1;
11276 FPL__CheckArgumentMin(maxDestLen, requiredLen,
fpl_null);
11278 char *result = dest + sourceLen;
11296 FPL__CheckArgumentNull(format, 0);
11299 va_copy(listCopy, argList);
11303 FPL__CheckArgumentMin(maxDestBufferLen, 1, 0);
11308# if defined(FPL_NO_CRT)
11309# if defined(FPL_USERFUNC_vsnprintf)
11310 charCount = FPL_USERFUNC_vsnprintf(destBuffer, maxDestBufferLen, format, listCopy);
11315 charCount = vsnprintf(destBuffer, maxDestBufferLen, format, listCopy);
11317 if (charCount < 0) {
11318 FPL__ERROR(FPL__MODULE_STRINGS,
"Format parameter are '%s' are invalid", format);
11321 size_t result = charCount;
11323 size_t requiredMaxDestBufferLen = charCount + 1;
11324 FPL__CheckArgumentMin(maxDestBufferLen, requiredMaxDestBufferLen, 0);
11325 destBuffer[charCount] = 0;
11332 FPL__CheckArgumentNull(format, 0);
11334 va_start(argList, format);
11343 bool isNegative =
false;
11350 size_t digitCount = 0;
11354 }
while (tmp != 0);
11356 size_t result = digitCount + (isNegative ? 1 : 0);
11359 size_t requiredLen = result + 1;
11360 FPL__CheckArgumentMin(maxBufferLen, requiredLen, 0);
11369 const char *digits =
"0123456789";
11372 *--p = digits[tmp % 10];
11374 }
while (tmp != 0);
11383 FPL__CheckArgumentNull(str, 0);
11384 FPL__CheckArgumentZero(len, 0);
11385 const char *p = str;
11386 bool isNegative =
false;
11394 uint32_t value = 0;
11395 while (*p && ((
size_t)(p - str) < len)) {
11397 if (c <
'0' || c >
'9') {
11400 int v = (int)(*p -
'0');
11402 value += (uint32_t)v;
11405 int32_t result = isNegative ? -(int32_t)value : (int32_t)value;
11419#if !defined(FPL__COMMON_CONSOLE_DEFINED)
11420#define FPL__COMMON_CONSOLE_DEFINED
11423 FPL__CheckArgumentNullNoRet(format);
11426 va_start(argList, format);
11435 FPL__CheckArgumentNullNoRet(format);
11438 va_start(argList, format);
11450#if !defined(FPL__COMMON_MEMORY_DEFINED)
11451#define FPL__COMMON_MEMORY_DEFINED
11454 FPL__CheckArgumentZero(size,
fpl_null);
11455 FPL__CheckArgumentZero(alignment,
fpl_null);
11456 if (alignment & (alignment - 1)) {
11457 FPL__ERROR(FPL__MODULE_MEMORY,
"Alignment parameter '%zu' must be a power of two", alignment);
11461 size_t newSize =
sizeof(
void *) + (alignment << 1) + size;
11464 void *alignedPtr = (
void *)((uint8_t *)basePtr +
sizeof(
void *));
11466 uintptr_t mask = alignment - 1;
11467 if ((alignment > 1) && (((uintptr_t)alignedPtr & mask) != 0)) {
11468 uintptr_t offset = ((uintptr_t)alignment - ((uintptr_t)alignedPtr & mask));
11469 alignedPtr = (uint8_t *)alignedPtr + offset;
11472 *(
void **)((
void *)((uint8_t *)alignedPtr -
sizeof(
void *))) = basePtr;
11475 return(alignedPtr);
11479 FPL__CheckArgumentNullNoRet(ptr);
11481 void *basePtr = *(
void **)((
void *)((uint8_t *)ptr -
sizeof(
void *)));
11486#define FPL__MEM_SHIFT_64 3
11487#define FPL__MEM_MASK_64 0x00000007
11488#define FPL__MEM_SHIFT_32 2
11489#define FPL__MEM_MASK_32 0x00000003
11490#define FPL__MEM_SHIFT_16 1
11491#define FPL__MEM_MASK_16 0x0000000
11494#define FPL__MEMORY_SET(T, memory, size, shift, mask, value) \
11496 size_t setBytes = 0; \
11497 if (sizeof(T) > sizeof(uint8_t)) { \
11499 for (uint32_t bytesIncrement = 0; bytesIncrement < sizeof(T); ++bytesIncrement) { \
11500 uint32_t bitShift = bytesIncrement * 8; \
11501 setValue |= ((T)value << bitShift); \
11503 T *dataBlock = (T *)(memory); \
11504 T *dataBlockEnd = (T *)(memory) + (size >> shift); \
11505 while (dataBlock < dataBlockEnd) { \
11506 *dataBlock++ = setValue; \
11507 setBytes += sizeof(T); \
11510 uint8_t *data8 = (uint8_t *)memory + setBytes; \
11511 uint8_t *data8End = (uint8_t *)memory + size; \
11512 while (data8 < data8End) { \
11513 *data8++ = value; \
11517#define FPL__MEMORY_CLEAR(T, memory, size, shift, mask) \
11519 size_t clearBytes = 0; \
11520 if (sizeof(T) > sizeof(uint8_t)) { \
11521 T *dataBlock = (T *)(memory); \
11522 T *dataBlockEnd = (T *)(memory) + (size >> shift); \
11523 while (dataBlock < dataBlockEnd) { \
11524 *dataBlock++ = 0; \
11525 clearBytes += sizeof(T); \
11528 uint8_t *data8 = (uint8_t *)memory + clearBytes; \
11529 uint8_t *data8End = (uint8_t *)memory + size; \
11530 while (data8 < data8End) { \
11535#define FPL__MEMORY_COPY(T, source, sourceSize, dest, shift, mask) \
11537 size_t copiedBytes = 0; \
11538 if (sizeof(T) > sizeof(uint8_t)) { \
11539 const T *sourceDataBlock = (const T *)(source); \
11540 const T *sourceDataBlockEnd = (const T *)(source) + (sourceSize >> shift); \
11541 T *destDataBlock = (T *)(dest); \
11542 while (sourceDataBlock < sourceDataBlockEnd) { \
11543 *destDataBlock++ = *sourceDataBlock++; \
11544 copiedBytes += sizeof(T); \
11547 const uint8_t *sourceData8 = (const uint8_t *)source + copiedBytes; \
11548 const uint8_t *sourceData8End = (const uint8_t *)source + sourceSize; \
11549 uint8_t *destData8 = (uint8_t *)dest + copiedBytes; \
11550 while (sourceData8 < sourceData8End) { \
11551 *destData8++ = *sourceData8++; \
11556 FPL__CheckArgumentNullNoRet(mem);
11557 FPL__CheckArgumentZeroNoRet(size);
11558#if defined(FPL__ENABLE_MEMORY_MACROS)
11559 if (size % 8 == 0) {
11560 FPL__MEMORY_SET(uint64_t, mem, size, FPL__MEM_SHIFT_64, FPL__MEM_MASK_64, value);
11561 }
else if (size % 4 == 0) {
11562 FPL__MEMORY_SET(uint32_t, mem, size, FPL__MEM_SHIFT_32, FPL__MEM_MASK_32, value);
11563 }
else if (size % 2 == 0) {
11564 FPL__MEMORY_SET(uint16_t, mem, size, FPL__MEM_SHIFT_16, FPL__MEM_MASK_16, value);
11566 FPL__MEMORY_SET(uint8_t, mem, size, 0, 0, value);
11568#elif defined(FPL_PLATFORM_WINDOWS)
11569 FillMemory(mem, size, value);
11571 memset(mem, value, size);
11576 FPL__CheckArgumentNullNoRet(mem);
11577 FPL__CheckArgumentZeroNoRet(size);
11578#if defined(FPL__ENABLE_MEMORY_MACROS)
11579 if (size % 8 == 0) {
11580 FPL__MEMORY_CLEAR(uint64_t, mem, size, FPL__MEM_SHIFT_64, FPL__MEM_MASK_64);
11581 }
else if (size % 4 == 0) {
11582 FPL__MEMORY_CLEAR(uint32_t, mem, size, FPL__MEM_SHIFT_32, FPL__MEM_MASK_32);
11583 }
else if (size % 2 == 0) {
11584 FPL__MEMORY_CLEAR(uint16_t, mem, size, FPL__MEM_SHIFT_16, FPL__MEM_MASK_16);
11586 FPL__MEMORY_CLEAR(uint8_t, mem, size, 0, 0);
11588#elif defined(FPL_PLATFORM_WINDOWS)
11589 ZeroMemory(mem, size);
11591 memset(mem, 0, size);
11596 FPL__CheckArgumentNullNoRet(sourceMem);
11597 FPL__CheckArgumentZeroNoRet(sourceSize);
11598 FPL__CheckArgumentNullNoRet(targetMem);
11599#if defined(FPL__ENABLE_MEMORY_MACROS)
11600 if (sourceSize % 8 == 0) {
11601 FPL__MEMORY_COPY(uint64_t, sourceMem, sourceSize, targetMem, FPL__MEM_SHIFT_64, FPL__MEM_MASK_64);
11602 }
else if (sourceSize % 4 == 0) {
11603 FPL__MEMORY_COPY(uint32_t, sourceMem, sourceSize, targetMem, FPL__MEM_SHIFT_32, FPL__MEM_MASK_32);
11604 }
else if (sourceSize % 2 == 0) {
11605 FPL__MEMORY_COPY(uint16_t, sourceMem, sourceSize, targetMem, FPL__MEM_SHIFT_16, FPL__MEM_MASK_16);
11607 FPL__MEMORY_COPY(uint8_t, sourceMem, sourceSize, targetMem, 0, 0);
11609#elif defined(FPL_PLATFORM_WINDOWS)
11610 CopyMemory(targetMem, sourceMem, sourceSize);
11612 memcpy(targetMem, sourceMem, sourceSize);
11626#if defined(FPL_ARCH_X64) || defined(FPL_ARCH_X86)
11628# define FPL__CPU_BRAND_BUFFER_SIZE 0x40
11630# if defined(FPL_COMPILER_MSVC)
11633# if _MSC_VER >= 1400
11634# define fpl__m_CPUID(outLeaf, functionId) __cpuid((int *)(outLeaf)->raw, (int)(functionId))
11636# if _MSC_VER >= 1600
11637# define fpl__m_GetXCR0() ((uint64_t)_xgetbv(0))
11641# define fpl__m_RDTSC() ((uint64_t)__rdtsc())
11643# elif defined(FPL_COMPILER_GCC) ||defined(FPL_COMPILER_CLANG)
11647 int eax = 0, ebx = 0, ecx = 0, edx = 0;
11648 __cpuid_count(functionId, 0, eax, ebx, ecx, edx);
11649 outLeaf->
eax = eax;
11650 outLeaf->
ebx = ebx;
11651 outLeaf->
ecx = ecx;
11652 outLeaf->
edx = edx;
11658 __asm(
".byte 0x0F, 0x01, 0xd0" :
"=a"(eax),
"=d"(edx) :
"c"(0));
11663# if defined(FPL_ARCH_X86)
11665 unsigned long long int result;
11666 __asm__
volatile (
".byte 0x0f, 0x31" :
"=A" (result));
11667 return((uint64_t)result);
11669# elif defined(FPL_ARCH_X64)
11672 __asm__ __volatile__(
"rdtsc" :
"=a"(lo),
"=d"(hi));
11673 uint64_t result = (uint64_t)(((
unsigned long long)lo) | (((
unsigned long long)hi) << 32));
11680#if defined(fpl__m_CPUID)
11681 fpl__m_CPUID(outLeaf, functionId);
11688#if defined(fpl__m_GetXCR0)
11689 uint64_t result = fpl__m_GetXCR0();
11697#if defined(fpl__m_RDTSC)
11698 uint64_t result = fpl__m_RDTSC();
11717 uint32_t maxFunctionId = info0.
eax;
11719 if (1 <= maxFunctionId) {
11724 if (7 <= maxFunctionId) {
11730 uint64_t xcr0 = hasXSave ?
fplCPUXCR0() : 0;
11732 const uint32_t MASK_XMM = 0x2;
11733 const uint32_t MASK_YMM = 0x4;
11734 const uint32_t MASK_MASKREG = 0x20;
11735 const uint32_t MASK_ZMM0_15 = 0x40;
11736 const uint32_t MASK_ZMM16_31 = 0x80;
11738 const uint32_t MASK_SSE = MASK_XMM;
11739 const uint32_t MASK_AVX = MASK_XMM | MASK_YMM;
11740 const uint32_t MASK_AVX_512 = MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 | MASK_ZMM16_31;
11742 bool hasSSESupport = (xcr0 & MASK_SSE) == MASK_SSE;
11743 bool hasAVXSupport = (xcr0 & MASK_AVX) == MASK_AVX;
11744 bool hasAVX512Support = (xcr0 & MASK_AVX_512) == MASK_AVX_512;
11748 if (hasSSESupport) {
11757 if (hasAVXSupport) {
11762 if (hasAVX512Support) {
11775 if (
fplCPUID(0x80000001, &tempLeaf)) {
11785 uint32_t extendedIds = cpuInfo.
eax;
11788 char cpuBrandBuffer[FPL__CPU_BRAND_BUFFER_SIZE] =
fplZeroInit;
11789 uint32_t max =
fplMin(extendedIds, 0x80000004);
11790 for (uint32_t i = 0x80000002; i <= max; ++i) {
11792 uint32_t offset = (i - 0x80000002) << 4;
11799 size_t requiredDestBufferLen = result + 1;
11800 FPL__CheckArgumentMin(maxDestBufferLen, requiredDestBufferLen, 0);
11809#if defined(FPL_ARCH_ARM64)
11810 int64_t virtual_timer_value;
11811 fplAsm volatile(
"mrs %0, cntvct_el0" :
"=r"(virtual_timer_value));
11812 return (uint64_t)virtual_timer_value;
11813#elif defined(FPL_ARCH_ARM32) && (__ARM_ARCH >= 6)
11816 uint32_t pmcntenset;
11818 fplAsm volatile(
"mrc p15, 0, %0, c9, c14, 0" :
"=r"(pmuseren));
11819 if (pmuseren & 1) {
11821 fplAsm volatile(
"mrc p15, 0, %0, c9, c12, 1" :
"=r"(pmcntenset));
11822 if (pmcntenset & 0x80000000ul) {
11824 fplAsm volatile(
"mrc p15, 0, %0, c9, c13, 0" :
"=r"(pmccntr));
11826 return (uint64_t)pmccntr * 64ULL;
11832 return (uint64_t)tv.tv_sec * 1000000ULL + (uint64_t)tv.tv_usec;
11859#if !defined(FPL__COMMON_ATOMICS_DEFINED)
11860#define FPL__COMMON_ATOMICS_DEFINED
11864#if defined(FPL_CPU_64BIT)
11866#elif defined(FPL_CPU_32BIT)
11869# error "Unsupported architecture/platform!"
11876#if defined(FPL_CPU_64BIT)
11878#elif defined(FPL_CPU_32BIT)
11881# error "Unsupported architecture/platform!"
11888#if defined(FPL_CPU_64BIT)
11890#elif defined(FPL_CPU_32BIT)
11893# error "Unsupported architecture/platform!"
11900#if defined(FPL_CPU_64BIT)
11902#elif defined(FPL_CPU_32BIT)
11905# error "Unsupported architecture/platform!"
11912#if defined(FPL_CPU_64BIT)
11914#elif defined(FPL_CPU_32BIT)
11917# error "Unsupported architecture/platform!"
11924#if defined(FPL_CPU_64BIT)
11926#elif defined(FPL_CPU_32BIT)
11929# error "Unsupported architecture/platform!"
11936#if defined(FPL_CPU_64BIT)
11938#elif defined(FPL_CPU_32BIT)
11941# error "Unsupported architecture/platform!"
11947#if defined(FPL_CPU_64BIT)
11949#elif defined(FPL_CPU_32BIT)
11952# error "Unsupported architecture/platform!"
11959#if defined(FPL_CPU_64BIT)
11961#elif defined(FPL_CPU_32BIT)
11964# error "Unsupported architecture/platform!"
11970#if defined(FPL_CPU_64BIT)
11972#elif defined(FPL_CPU_32BIT)
11975# error "Unsupported architecture/platform!"
11982#if defined(FPL_CPU_64BIT)
11984#elif defined(FPL_CPU_32BIT)
11987# error "Unsupported architecture/platform!"
11993#if defined(FPL_CPU_64BIT)
11995#elif defined(FPL_CPU_32BIT)
11998# error "Unsupported architecture/platform!"
12004#if defined(FPL_CPU_64BIT)
12006#elif defined(FPL_CPU_32BIT)
12009# error "Unsupported architecture/platform!"
12014#if defined(FPL_CPU_64BIT)
12016#elif defined(FPL_CPU_32BIT)
12019# error "Unsupported architecture/platform!"
12024#if defined(FPL_CPU_64BIT)
12026#elif defined(FPL_CPU_32BIT)
12029# error "Unsupported architecture/platform!"
12034#if defined(FPL_CPU_64BIT)
12036#elif defined(FPL_CPU_32BIT)
12039# error "Unsupported architecture/platform!"
12057 const fplThreadHandle *result = &fpl__global__ThreadState.mainThread;
12063 for (
size_t threadIndex = 0; threadIndex < FPL_MAX_THREAD_COUNT; ++threadIndex) {
12074 for (
size_t threadIndex = 0; threadIndex < FPL_MAX_THREAD_COUNT; ++threadIndex) {
12086#if !defined(FPL__COMMON_FILES_DEFINED)
12087#define FPL__COMMON_FILES_DEFINED
12090#if defined(FPL_CPU_64BIT)
12091 return fplFileReadBlock64(fileHandle, sizeToRead, targetBuffer, maxTargetBufferSize);
12093 return fplFileReadBlock32(fileHandle, (uint32_t)sizeToRead, targetBuffer, (uint32_t)maxTargetBufferSize);
12098#if defined(FPL_CPU_64BIT)
12106#if defined(FPL_CPU_64BIT)
12114#if defined(FPL_CPU_64BIT)
12122#if defined(FPL_CPU_64BIT)
12130#if defined(FPL_CPU_64BIT)
12142#if !defined(FPL__COMMON_PATHS_DEFINED)
12143#define FPL__COMMON_PATHS_DEFINED
12146 FPL__CheckArgumentNull(sourcePath, 0);
12149 if (sourceLen > 0) {
12151 const char *chPtr = (
const char *)sourcePath;
12154 pathLen = (int)(chPtr - sourcePath);
12160 size_t requiredDestLen = pathLen + 1;
12161 FPL__CheckArgumentMin(maxDestLen, requiredDestLen, 0);
12171 const char *chPtr = sourcePath;
12173 const char *lastPathSep =
fpl_null;
12176 lastPathSep = chPtr;
12182 chPtr = lastPathSep;
12184 chPtr = sourcePath;
12203 result = sourcePath;
12204 const char *chPtr = sourcePath;
12207 result = chPtr + 1;
12216 FPL__CheckArgumentNull(filePath, 0);
12217 FPL__CheckArgumentNull(newFileExtension, 0);
12220 FPL__CheckArgumentZero(filePathLen, 0);
12227 const char *chPtr = (
const char *)filePath;
12228 const char *lastPathSeparatorPtr =
fpl_null;
12231 lastPathSeparatorPtr = chPtr;
12236 if (lastPathSeparatorPtr !=
fpl_null) {
12237 chPtr = lastPathSeparatorPtr + 1;
12239 chPtr = (
const char *)filePath;
12241 const char *lastExtSeparatorPtr =
fpl_null;
12244 lastExtSeparatorPtr = chPtr;
12249 size_t filenameLen;
12250 if (lastExtSeparatorPtr !=
fpl_null) {
12251 filenameLen = (size_t)((uintptr_t)lastExtSeparatorPtr - (uintptr_t)filePath);
12253 filenameLen = filePathLen;
12256 result = filenameLen + extLen;
12260 size_t requiredDestLen = result + 1;
12261 FPL__CheckArgumentMin(maxDestLen, requiredDestLen, 0);
12264 char *destExtPtr = destPath + filenameLen;
12265 fplCopyStringLen(newFileExtension, extLen, destExtPtr, maxDestLen - filenameLen);
12272 FPL__CheckArgumentZero(pathCount, 0);
12276 size_t curDestPosition = 0;
12277 char *currentDestPtr = destPath;
12280 va_start(vargs, pathCount);
12281 for (
size_t pathIndex = 0; pathIndex < pathCount; ++pathIndex) {
12282 const char *path = va_arg(vargs,
const char *);
12285 bool requireSeparator = pathIndex < (pathCount - 1);
12286 size_t requiredPathLen = requireSeparator ? pathLen + 1 : pathLen;
12288 result += requiredPathLen;
12291 size_t requiredDestLen = result + 1;
12292 FPL__CheckArgumentMin(maxDestPathLen, requiredDestLen, 0);
12294 fplCopyStringLen(path, pathLen, currentDestPtr, maxDestPathLen - curDestPosition);
12295 currentDestPtr += pathLen;
12296 if (requireSeparator) {
12299 curDestPosition += requiredPathLen;
12303 *currentDestPtr = 0;
12313#if !defined(FPL__COMMON_WINDOW_DEFINED)
12314#define FPL__COMMON_WINDOW_DEFINED
12317 fpl__PlatformAppState *appState = fpl__global__AppState;
12318 char *result =
fplCopyString(appState->currentSettings.window.title, outTitle, maxOutTitleLength);
12323 FPL__CheckPlatformNoRet();
12324 fpl__PlatformAppState *appState = fpl__global__AppState;
12325 appState->currentSettings.input.disabledEvents = !enabled;
12332#if defined(FPL__ENABLE_LOGGING)
12334 FPL__CheckArgumentNullNoRet(params);
12335 fpl__global__LogSettings = *params;
12339 return &fpl__global__LogSettings;
12342 fpl__global__LogSettings.maxLevel = maxLevel;
12345 return fpl__global__LogSettings.maxLevel;
12350 const char *result =
"";
12351 const fpl__ErrorState *errorState = &fpl__global__LastErrorState;
12352 if (errorState->count > 0) {
12353 size_t index = errorState->count - 1;
12360 const char *result =
"";
12361 const fpl__ErrorState *errorState = &fpl__global__LastErrorState;
12362 if (index < errorState->count) {
12363 result = errorState->errors[index];
12365 result = errorState->errors[errorState->count - 1];
12372 const fpl__ErrorState *errorState = &fpl__global__LastErrorState;
12373 result = errorState->count;
12378 fpl__ErrorState *errorState = &fpl__global__LastErrorState;
12384 const fpl__PlatformAppState *appState = fpl__global__AppState;
12385 return &appState->currentSettings;
12389 FPL__CheckArgumentNullNoRet(video);
12394#if defined(FPL__ENABLE_VIDEO_OPENGL)
12399#if defined(FPL__ENABLE_VIDEO_VULKAN)
12408#if defined(FPL__ENABLE_VIDEO_OPENGL)
12410#elif defined(FPL__ENABLE_VIDEO_SOFTWARE)
12412#elif defined(FPL__ENABLE_VIDEO_VULKAN)
12420#define FPL__AUDIO_CHANNEL_TYPE_COUNT FPL__ENUM_COUNT(fplAudioChannelType_First, fplAudioChannelType_Last)
12423fpl_globalvar const char *fpl__global_audioChannelTypeNameTable[] = {
12464 const char *result = fpl__global_audioChannelTypeNameTable[index];
12469 FPL__CheckArgumentNullNoRet(audio);
12477 FPL__CheckArgumentNullNoRet(window);
12479 window->
title[0] = 0;
12493 FPL__CheckArgumentNullNoRet(console);
12495 console->
title[0] = 0;
12499 FPL__CheckArgumentNullNoRet(input);
12505 FPL__CheckArgumentNullNoRet(settings);
12519#define FPL__PLATFORMRESULTTYPE_COUNT FPL__ENUM_COUNT(fplPlatformResultType_First, fplPlatformResultType_Last)
12522fpl_globalvar const char *fpl__global_platformResultTypeNameTable[] = {
12536 const char *result = fpl__global_platformResultTypeNameTable[index];
12540#define FPL__ARCHTYPE_COUNT FPL__ENUM_COUNT(fplCPUArchType_First, fplCPUArchType_Last)
12543fpl_globalvar const char *fpl__global_ArchTypeNameTable[] = {
12555 const char *result = fpl__global_ArchTypeNameTable[index];
12559#define FPL__CPU_CAPABILITIESTYPE_COUNT FPL__ENUM_COUNT(fplCPUCapabilitiesType_First, fplCPUCapabilitiesType_Last)
12562fpl_globalvar const char *fpl__global_CPUCapabilitesTypeNameTable[] = {
12571 const char *result = fpl__global_CPUCapabilitesTypeNameTable[index];
12578#if defined(FPL_PLATFORM_WINDOWS)
12582 OutputDebugStringW(buffer);
12594 va_start(argList, format);
12616#if defined(FPL_PLATFORM_WINDOWS)
12618# if defined(FPL_ARCH_X86)
12619# define FPL_MEMORY_BARRIER() \
12621 _InterlockedOr(&barrier, 0);
12622# elif defined(FPL_ARCH_X64)
12624# define FPL_MEMORY_BARRIER()
12627#if defined(FPL__ENABLE_WINDOW)
12630 DWORD result = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
12632 result |= WS_POPUP;
12634 result |= WS_OVERLAPPEDWINDOW;
12636 result &= ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
12643 DWORD result = WS_EX_APPWINDOW;
12645 result |= WS_EX_TOPMOST;
12650fpl_internal void fpl__Win32SaveWindowState(
const fpl__Win32Api *wapi, fpl__Win32LastWindowInfo *target, HWND windowHandle) {
12651 target->isMaximized = !!wapi->user.IsZoomed(windowHandle);
12652 target->isMinimized = !!wapi->user.IsIconic(windowHandle);
12653 target->style = fpl__win32_GetWindowLong(windowHandle, GWL_STYLE);
12654 target->exStyle = fpl__win32_GetWindowLong(windowHandle, GWL_EXSTYLE);
12655 wapi->user.GetWindowPlacement(windowHandle, &target->placement);
12658fpl_internal void fpl__Win32RestoreWindowState(
const fpl__Win32Api *wapi,
const fpl__Win32LastWindowInfo *target, HWND windowHandle) {
12659 fplAssert(target->style > 0 && target->exStyle > 0);
12660 fpl__win32_SetWindowLong(windowHandle, GWL_STYLE, target->style);
12661 fpl__win32_SetWindowLong(windowHandle, GWL_EXSTYLE, target->exStyle);
12662 wapi->user.SetWindowPlacement(windowHandle, &target->placement);
12663 wapi->user.SetWindowPos(windowHandle,
fpl_null, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
12664 if (target->isMaximized) {
12665 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
12666 }
else if (target->isMinimized) {
12667 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
12672 const fpl__PlatformAppState *platState = fpl__global__AppState;
12674 const fpl__Win32AppState *win32State = &platState->win32;
12675 const fpl__Win32Api *wapi = &win32State->winApi;
12677 const fpl__Win32WindowState *win32Window = &platState->window.win32;
12678 const fpl__Win32LastWindowInfo *fullscreenInfo = &win32Window->lastFullscreenInfo;
12679 HWND windowHandle = win32Window->windowHandle;
12680 fpl__Win32RestoreWindowState(wapi, fullscreenInfo, windowHandle);
12682 if (fullscreenInfo->wasResolutionChanged) {
12683 result = (wapi->user.ChangeDisplaySettingsW(
fpl_null, CDS_RESET) == DISP_CHANGE_SUCCESSFUL);
12690fpl_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) {
12691 fpl__PlatformAppState *platState = fpl__global__AppState;
12693 fpl__Win32AppState *win32State = &platState->win32;
12694 const fpl__Win32Api *wapi = &win32State->winApi;
12696 fpl__Win32WindowState *win32Window = &platState->window.win32;
12697 fpl__Win32LastWindowInfo *fullscreenInfo = &win32Window->lastFullscreenInfo;
12699 HWND windowHandle = win32Window->windowHandle;
12700 HDC deviceContext = win32Window->deviceContext;
12702 fplAssert(fullscreenInfo->style > 0 && fullscreenInfo->exStyle > 0);
12703 fpl__win32_SetWindowLong(windowHandle, GWL_STYLE, fullscreenInfo->style & ~(WS_CAPTION | WS_THICKFRAME));
12704 fpl__win32_SetWindowLong(windowHandle, GWL_EXSTYLE, fullscreenInfo->exStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
12707 monitor.cbSize =
sizeof(monitor);
12708 wapi->user.GetMonitorInfoW(wapi->user.MonitorFromWindow(windowHandle, MONITOR_DEFAULTTONEAREST), &monitor);
12711 if (allowResolutionChange && (fullscreenWidth > 0) && (fullscreenHeight > 0)) {
12712 int32_t useFullscreenWidth = fullscreenWidth;
12713 int32_t useFullscreenHeight = fullscreenHeight;
12715 DWORD useRefreshRate = refreshRate;
12716 if (!useRefreshRate) {
12717 useRefreshRate = wapi->gdi.GetDeviceCaps(deviceContext, VREFRESH);
12720 DWORD useColourBits = colorBits;
12721 if (!useColourBits) {
12722 useColourBits = wapi->gdi.GetDeviceCaps(deviceContext, BITSPIXEL);
12727 windowRect.left = 0;
12728 windowRect.top = 0;
12729 windowRect.right = windowRect.left + useFullscreenWidth;
12730 windowRect.bottom = windowRect.top + useFullscreenHeight;
12733 placement.length =
sizeof(placement);
12734 placement.rcNormalPosition = windowRect;
12735 placement.showCmd = SW_SHOW;
12736 wapi->user.SetWindowPlacement(windowHandle, &placement);
12737 wapi->user.SetWindowPos(windowHandle,
fpl_null, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
12740 wapi->user.EnumDisplaySettingsW(
fpl_null, 0, &fullscreenSettings);
12741 fullscreenSettings.dmPelsWidth = useFullscreenWidth;
12742 fullscreenSettings.dmPelsHeight = useFullscreenHeight;
12743 fullscreenSettings.dmBitsPerPel = useColourBits;
12744 fullscreenSettings.dmDisplayFrequency = useRefreshRate;
12745 fullscreenSettings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
12746 result = (wapi->user.ChangeDisplaySettingsW(&fullscreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
12747 fullscreenInfo->wasResolutionChanged =
true;
12750 if ((xpos != INT32_MAX) && (ypos != INT32_MAX) && (fullscreenWidth != 0) && (fullscreenHeight != 0)) {
12751 windowRect.left = xpos;
12752 windowRect.top = ypos;
12753 windowRect.right = xpos + fullscreenWidth;
12754 windowRect.top = ypos + fullscreenHeight;
12756 windowRect = monitor.rcMonitor;
12759 placement.length =
sizeof(placement);
12760 placement.rcNormalPosition = windowRect;
12761 placement.showCmd = SW_SHOWNORMAL;
12762 wapi->user.SetWindowPlacement(windowHandle, &placement);
12763 wapi->user.SetWindowPos(windowHandle,
fpl_null, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
12765 fullscreenInfo->wasResolutionChanged =
false;
12771fpl_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) {
12772 FPL__CheckPlatform(
false);
12773 fpl__PlatformAppState *appState = fpl__global__AppState;
12774 fpl__Win32AppState *win32AppState = &appState->win32;
12775 fpl__Win32WindowState *windowState = &appState->window.win32;
12777 fpl__Win32LastWindowInfo *fullscreenState = &windowState->lastFullscreenInfo;
12778 const fpl__Win32Api *wapi = &win32AppState->winApi;
12780 HWND windowHandle = windowState->windowHandle;
12784 fpl__Win32SaveWindowState(wapi, fullscreenState, windowHandle);
12785 if (fullscreenState->isMaximized || fullscreenState->isMinimized) {
12786 wapi->user.ShowWindow(windowHandle, SW_RESTORE);
12792 windowSettings->
isFullscreen = fpl__Win32EnterFullscreen(x, y, w, h, refreshRate, 0, allowResolutionChange);
12794 fpl__Win32LeaveFullscreen();
12797 fpl__Win32LeaveFullscreen();
12804fpl_internal float fpl__Win32XInputProcessStickValue(
const SHORT value,
const SHORT deadZoneThreshold) {
12806 if (value < -deadZoneThreshold) {
12807 result = (float)((value + deadZoneThreshold) / (32768.0f - deadZoneThreshold));
12808 }
else if (value > deadZoneThreshold) {
12809 result = (float)((value - deadZoneThreshold) / (32767.0f - deadZoneThreshold));
12819 outState->
leftStickX = fpl__Win32XInputProcessStickValue(newState->sThumbLX, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
12820 outState->
leftStickY = fpl__Win32XInputProcessStickValue(newState->sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
12821 outState->
rightStickX = fpl__Win32XInputProcessStickValue(newState->sThumbRX, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
12822 outState->
rightStickY = fpl__Win32XInputProcessStickValue(newState->sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
12825 outState->
leftTrigger = (float)newState->bLeftTrigger / 255.0f;
12826 outState->rightTrigger = (float)newState->bRightTrigger / 255.0f;
12829 if (newState->wButtons & XINPUT_GAMEPAD_DPAD_UP)
12830 outState->dpadUp.isDown =
true;
12831 if (newState->wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
12832 outState->dpadDown.isDown =
true;
12833 if (newState->wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
12834 outState->dpadLeft.isDown =
true;
12835 if (newState->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
12836 outState->dpadRight.isDown =
true;
12839 if (newState->wButtons & XINPUT_GAMEPAD_A)
12840 outState->actionA.isDown =
true;
12841 if (newState->wButtons & XINPUT_GAMEPAD_B)
12842 outState->actionB.isDown =
true;
12843 if (newState->wButtons & XINPUT_GAMEPAD_X)
12844 outState->actionX.isDown =
true;
12845 if (newState->wButtons & XINPUT_GAMEPAD_Y)
12846 outState->actionY.isDown =
true;
12849 if (newState->wButtons & XINPUT_GAMEPAD_START)
12850 outState->start.isDown =
true;
12851 if (newState->wButtons & XINPUT_GAMEPAD_BACK)
12852 outState->back.isDown =
true;
12855 if (newState->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)
12856 outState->leftShoulder.isDown =
true;
12857 if (newState->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
12858 outState->rightShoulder.isDown =
true;
12861 if (newState->wButtons & XINPUT_GAMEPAD_LEFT_THUMB)
12862 outState->leftThumb.isDown =
true;
12863 if (newState->wButtons & XINPUT_GAMEPAD_RIGHT_THUMB)
12864 outState->rightThumb.isDown =
true;
12867 outState->isActive = !fpl__IsZeroMemory(newState,
sizeof(*newState));
12870fpl_internal void fpl__Win32UpdateGameControllers(
const fplSettings *settings,
const fpl__Win32InitState *initState, fpl__Win32XInputState *xinputState) {
12873 if (xinputState->xinputApi.XInputGetState !=
fpl_null) {
12877 if (xinputState->lastDeviceSearchTime.QuadPart == 0) {
12878 QueryPerformanceCounter(&xinputState->lastDeviceSearchTime);
12880 LARGE_INTEGER currentDeviceSearchTime, currentDeviceSearchFreq;
12881 QueryPerformanceCounter(¤tDeviceSearchTime);
12882 QueryPerformanceFrequency(¤tDeviceSearchFreq);
12883 uint64_t deviceSearchDifferenceTimeInMs = ((currentDeviceSearchTime.QuadPart - xinputState->lastDeviceSearchTime.QuadPart) / (currentDeviceSearchFreq.QuadPart / 1000));
12885 xinputState->lastDeviceSearchTime = currentDeviceSearchTime;
12886 for (DWORD controllerIndex = 0; controllerIndex < XUSER_MAX_COUNT; ++controllerIndex) {
12888 if (xinputState->xinputApi.XInputGetState(controllerIndex, &controllerState) == ERROR_SUCCESS) {
12889 if (!xinputState->isConnected[controllerIndex]) {
12891 xinputState->isConnected[controllerIndex] =
true;
12892 fplStringFormat(xinputState->deviceNames[controllerIndex],
fplArrayCount(xinputState->deviceNames[controllerIndex]),
"XInput-Device [%d]", controllerIndex);
12899 fpl__PushInternalEvent(&ev);
12902 if (xinputState->isConnected[controllerIndex]) {
12904 xinputState->isConnected[controllerIndex] =
false;
12911 fpl__PushInternalEvent(&ev);
12920 for (DWORD controllerIndex = 0; controllerIndex < XUSER_MAX_COUNT; ++controllerIndex) {
12921 if (xinputState->isConnected[controllerIndex]) {
12923 if (xinputState->xinputApi.XInputGetState(controllerIndex, &controllerState) == ERROR_SUCCESS) {
12930 const XINPUT_GAMEPAD *newPadState = &controllerState.Gamepad;
12931 fpl__Win32XInputGamepadToGamepadState(newPadState, &ev.
gamepad.
state);
12933 fpl__PushInternalEvent(&ev);
12940fpl_internal bool fpl__Win32IsKeyDown(
const fpl__Win32Api *wapi,
const int virtualKey) {
12941 bool result = (wapi->user.GetAsyncKeyState(virtualKey) & 0x8000) != 0;
12945fpl_internal bool fpl__Win32IsKeyActive(
const fpl__Win32Api *wapi,
const int virtualKey) {
12946 bool result = (wapi->user.GetKeyState(virtualKey) & 0x0001) != 0;
12950fpl_internal bool fpl__Win32IsCursorInWindow(
const fpl__Win32Api *wapi,
const fpl__Win32WindowState *win32Window) {
12952 if (!wapi->user.GetCursorPos(&pos)) {
12956 if (wapi->user.WindowFromPoint(pos) != win32Window->windowHandle) {
12961 wapi->user.GetClientRect(win32Window->windowHandle, &area);
12963 wapi->user.ClientToScreen(win32Window->windowHandle, (LPPOINT)&area.left);
12964 wapi->user.ClientToScreen(win32Window->windowHandle, (LPPOINT)&area.right);
12965 bool result = wapi->user.PtInRect(&area, pos) == TRUE;
12970fpl_internal void fpl__Win32LoadCursor(
const fpl__Win32Api *wapi,
const fpl__Win32WindowState *window) {
12971 if (window->isCursorActive) {
12972 wapi->user.SetCursor(fpl__win32_LoadCursor(
fpl_null, IDC_ARROW));
12978fpl_internal void fpl__Win32UpdateClipRect(
const fpl__Win32Api *wapi,
const fpl__Win32WindowState *window) {
12981 wapi->user.GetClientRect(window->windowHandle, &clipRect);
12982 wapi->user.ClientToScreen(window->windowHandle, (POINT *)&clipRect.left);
12983 wapi->user.ClientToScreen(window->windowHandle, (POINT *)&clipRect.right);
12984 wapi->user.ClipCursor(&clipRect);
12990fpl_internal void fpl__Win32SetCursorState(
const fpl__Win32Api *wapi, fpl__Win32WindowState *window,
const bool state) {
12993 const RAWINPUTDEVICE rid =
fplStructInit(RAWINPUTDEVICE, 0x01, 0x02, 0, window->windowHandle);
12994 if (!wapi->user.RegisterRawInputDevices(&rid, 1,
sizeof(rid))) {
12995 FPL__ERROR(FPL__MODULE_WINDOW,
"Failed register raw input mouse device for window handle '%p'", window->windowHandle);
12999 if (!wapi->user.RegisterRawInputDevices(&rid, 1,
sizeof(rid))) {
13000 FPL__ERROR(FPL__MODULE_WINDOW,
"Failed to unregister raw input mouse device");
13003 if (fpl__Win32IsCursorInWindow(wapi, window)) {
13004 fpl__Win32LoadCursor(wapi, window);
13008fpl_internal void fpl__Win32ShowCursor(
const fpl__Win32Api *wapi, fpl__Win32WindowState *window) {
13009 fpl__Win32SetCursorState(wapi, window,
false);
13011fpl_internal void fpl__Win32HideCursor(
const fpl__Win32Api *wapi, fpl__Win32WindowState *window) {
13012 fpl__Win32SetCursorState(wapi, window,
true);
13017 bool lAltKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_LMENU);
13018 bool rAltKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_RMENU);
13019 bool lShiftKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_LSHIFT);
13020 bool rShiftKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_RSHIFT);
13021 bool lCtrlKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_LCONTROL);
13022 bool rCtrlKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_RCONTROL);
13023 bool lSuperKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_LWIN);
13024 bool rSuperKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_RWIN);
13025 bool capsLockActive = fpl__Win32IsKeyActive(wapi, VK_CAPITAL);
13026 bool numLockActive = fpl__Win32IsKeyActive(wapi, VK_NUMLOCK);
13027 bool scrollLockActive = fpl__Win32IsKeyActive(wapi, VK_SCROLL);
13028 if (lAltKeyIsDown) {
13031 if (rAltKeyIsDown) {
13034 if (lShiftKeyIsDown) {
13037 if (rShiftKeyIsDown) {
13040 if (lCtrlKeyIsDown) {
13043 if (rCtrlKeyIsDown) {
13046 if (lSuperKeyIsDown) {
13049 if (rSuperKeyIsDown) {
13052 if (capsLockActive) {
13055 if (numLockActive) {
13058 if (scrollLockActive) {
13064fpl_internal void fpl__Win32HandleMessage(
const fpl__Win32Api *wapi, fpl__PlatformAppState *appState, fpl__Win32WindowState *windowState, MSG *msg) {
13065 if (appState->currentSettings.window.callbacks.eventCallback !=
fpl_null) {
13066 appState->currentSettings.window.callbacks.eventCallback(
fplGetPlatformType(), windowState, &msg, appState->currentSettings.window.callbacks.eventUserData);
13068 wapi->user.TranslateMessage(msg);
13069 wapi->user.DispatchMessageW(msg);
13072fpl_internal void CALLBACK fpl__Win32MessageFiberProc(
struct fpl__PlatformAppState *appState) {
13073 fpl__Win32AppState *win32State = &appState->win32;
13074 fpl__Win32WindowState *windowState = &appState->window.win32;
13075 const fpl__Win32Api *wapi = &win32State->winApi;
13076 wapi->user.SetTimer(appState->window.win32.windowHandle, 1, 1, 0);
13079 while (wapi->user.PeekMessageW(&message, 0, 0, 0, PM_REMOVE)) {
13080 fpl__Win32HandleMessage(wapi, appState, windowState, &message);
13082 SwitchToFiber(appState->window.win32.mainFiber);
13086LRESULT CALLBACK fpl__Win32MessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
13087 fpl__PlatformAppState *appState = fpl__global__AppState;
13090 fpl__Win32AppState *win32State = &appState->win32;
13091 fpl__Win32WindowState *win32Window = &appState->window.win32;
13092 const fpl__Win32Api *wapi = &win32State->winApi;
13094 if (!win32Window->windowHandle) {
13095 return wapi->user.DefWindowProcW(hwnd, msg, wParam, lParam);
13098 LRESULT result = 0;
13102 if (win32Window->mainFiber !=
fpl_null) {
13103 SwitchToFiber(win32Window->mainFiber);
13110 appState->window.isRunning =
false;
13115 DWORD newWidth = LOWORD(lParam);
13116 DWORD newHeight = HIWORD(lParam);
13117 if (wParam == SIZE_MAXIMIZED) {
13119 }
else if (wParam == SIZE_MINIMIZED) {
13121 }
else if (wParam == SIZE_RESTORED) {
13125# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
13127 if (appState->initSettings.video.isAutoSize) {
13140 HDROP dropHandle = (HDROP)wParam;
13144 fileCount = wapi->shell.DragQueryFileW(dropHandle, 0xFFFFFFFF, fileBufferW, 0);
13145 if (fileCount > 0) {
13146 size_t filesTableSize = fileCount *
sizeof(
char **);
13148 size_t filesMemorySize = filesTableSize + FPL__ARBITARY_PADDING + maxFileStride * fileCount;
13149 void *filesTableMemory = fpl__AllocateDynamicMemory(filesMemorySize, 16);
13150 char **filesTable = (
char **)filesTableMemory;
13151 for (UINT fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
13152 filesTable[fileIndex] = (
char *)((uint8_t *)filesTableMemory + filesTableSize + FPL__ARBITARY_PADDING + fileIndex * maxFileStride);
13154 for (UINT fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
13155 char *file = filesTable[fileIndex];
13156 fileBufferW[0] = 0;
13157 UINT dragResult = wapi->shell.DragQueryFileW(dropHandle, 0, fileBufferW,
fplArrayCount(fileBufferW));
13158 size_t sourceLen = lstrlenW(fileBufferW);
13162 memory.
size = filesMemorySize;
13163 memory.
base = filesTableMemory;
13164 fpl__PushWindowDropFilesEvent(fileBufferA, fileCount, (
const char **)filesTable, &memory);
13168 case WM_SYSKEYDOWN:
13173 if (!appState->currentSettings.input.disabledEvents) {
13174 uint64_t keyCode = wParam;
13175 bool isDown = (lParam & (1 << 31)) == 0;
13176 bool wasDown = (lParam & (1 << 30)) != 0;
13177 bool altKeyIsDown = fpl__Win32IsKeyDown(wapi, VK_MENU);
13180 fpl__HandleKeyboardButtonEvent(&appState->window, GetTickCount(), keyCode, modifiers, keyState,
false);
13188 if ((msg == WM_UNICHAR) && (wParam == UNICODE_NOCHAR)) {
13192 fpl__HandleKeyboardInputEvent(&appState->window, (uint64_t)wParam, (uint32_t)wParam);
13200 case WM_MOUSEACTIVATE:
13202 if (HIWORD(lParam) == WM_LBUTTONDOWN) {
13203 if (LOWORD(lParam) == HTCLOSE || LOWORD(lParam) == HTMINBUTTON || LOWORD(lParam) == HTMAXBUTTON) {
13204 win32Window->isFrameInteraction =
true;
13209 case WM_CAPTURECHANGED:
13211 if (lParam == 0 && win32Window->isFrameInteraction) {
13212 if (!win32Window->isCursorActive) {
13213 fpl__Win32HideCursor(wapi, win32Window);
13215 win32Window->isFrameInteraction =
false;
13224 fpl__PushInternalEvent(&newEvent);
13225 if (win32Window->isFrameInteraction) {
13228 if (!win32Window->isCursorActive) {
13229 fpl__Win32HideCursor(wapi, win32Window);
13236 if (!win32Window->isCursorActive) {
13237 fpl__Win32ShowCursor(wapi, win32Window);
13242 fpl__PushInternalEvent(&newEvent);
13246 case WM_ENTERSIZEMOVE:
13247 case WM_ENTERMENULOOP:
13250 if (!win32Window->isCursorActive) {
13251 fpl__Win32ShowCursor(wapi, win32Window);
13255 case WM_EXITSIZEMOVE:
13256 case WM_EXITMENULOOP:
13258 if (!win32Window->isCursorActive) {
13259 fpl__Win32HideCursor(wapi, win32Window);
13263 case WM_LBUTTONDOWN:
13265 case WM_RBUTTONDOWN:
13267 case WM_MBUTTONDOWN:
13270 if (!appState->currentSettings.input.disabledEvents) {
13272 if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) {
13278 wapi->user.SetCapture(hwnd);
13280 wapi->user.ReleaseCapture();
13283 if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) {
13285 }
else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONUP) {
13287 }
else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONUP) {
13293 int32_t mouseX = GET_X_LPARAM(lParam);
13294 int32_t mouseY = GET_Y_LPARAM(lParam);
13295 fpl__HandleMouseButtonEvent(&appState->window, mouseX, mouseY, mouseButton, buttonState);
13301 if (!appState->currentSettings.input.disabledEvents) {
13302 int32_t mouseX = GET_X_LPARAM(lParam);
13303 int32_t mouseY = GET_Y_LPARAM(lParam);
13304 fpl__HandleMouseMoveEvent(&appState->window, mouseX, mouseY);
13307 case WM_MOUSEWHEEL:
13309 int32_t mouseX = GET_X_LPARAM(lParam);
13310 int32_t mouseY = GET_Y_LPARAM(lParam);
13311 short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
13312 float wheelDelta = zDelta / (float)WHEEL_DELTA;
13313 fpl__HandleMouseWheelEvent(&appState->window, mouseX, mouseY, wheelDelta);
13318 if (LOWORD(lParam) == HTCLIENT) {
13319 fpl__Win32LoadCursor(wapi, win32Window);
13326 if (appState->currentSettings.window.callbacks.exposedCallback !=
fpl_null) {
13328 msgData.message = msg;
13329 msgData.hwnd = hwnd;
13330 msgData.wParam = wParam;
13331 msgData.lParam = lParam;
13332 appState->currentSettings.window.callbacks.exposedCallback(
fplGetPlatformType(), win32Window, &msgData, appState->currentSettings.window.callbacks.exposedUserData);
13336 HDC hdc = wapi->user.BeginPaint(hwnd, &ps);
13337 wapi->user.EndPaint(hwnd, &ps);
13343 case WM_ERASEBKGND:
13352 case WM_SYSCOMMAND:
13354 WPARAM masked = wParam & 0xFFF0;
13356 case SC_SCREENSAVE:
13357 case SC_MONITORPOWER: {
13358 if (appState->currentSettings.window.isScreenSaverPrevented || appState->currentSettings.window.isMonitorPowerPrevented) {
13368 result = wapi->user.DefWindowProcW(hwnd, msg, wParam, lParam);
13372fpl_internal HICON fpl__Win32LoadIconFromImageSource(
const fpl__Win32Api *wapi,
const HINSTANCE appInstance,
const fplImageSource *imageSource) {
13377 bi.bV5Size =
sizeof(bi);
13378 bi.bV5Width = (LONG)imageSource->
width;
13379 bi.bV5Height = -(LONG)imageSource->
height;
13381 bi.bV5BitCount = 32;
13382 bi.bV5Compression = BI_BITFIELDS;
13383 bi.bV5RedMask = 0x00ff0000;
13384 bi.bV5GreenMask = 0x0000ff00;
13385 bi.bV5BlueMask = 0x000000ff;
13386 bi.bV5AlphaMask = 0xff000000;
13389 HDC dc = wapi->user.GetDC(
fpl_null);
13390 HBITMAP colorBitmap = wapi->gdi.CreateDIBSection(dc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (
void **)&targetData,
fpl_null, (DWORD)0);
13392 FPL__ERROR(FPL__MODULE_WIN32,
"Failed to create DIBSection from image with size %lu x %lu", imageSource->
width, imageSource->
height);
13394 wapi->user.ReleaseDC(
fpl_null, dc);
13396 HBITMAP maskBitmap = wapi->gdi.CreateBitmap(imageSource->
width, imageSource->
height, 1, 1,
fpl_null);
13398 FPL__ERROR(FPL__MODULE_WIN32,
"Failed to create Bitmap Mask from image with size %lu x %lu", imageSource->
width, imageSource->
height);
13402 uint8_t *dst = targetData;
13403 const uint8_t *src = imageSource->
data;
13405 for (uint32_t i = 0; i < imageSource->
width * imageSource->
height; ++i) {
13417 ii.hbmMask = maskBitmap;
13418 ii.hbmColor = colorBitmap;
13419 result = wapi->user.CreateIconIndirect(&ii);
13421 FPL__ERROR(FPL__MODULE_WIN32,
"Image source type '%d' for icon is not supported", imageSource->
type);
13425 wapi->gdi.DeleteObject(colorBitmap);
13428 wapi->gdi.DeleteObject(maskBitmap);
13432 result = fpl__win32_LoadIcon(appInstance, IDI_APPLICATION);
13437fpl_internal fplKey fpl__Win32TranslateVirtualKey(
const fpl__Win32Api *wapi,
const uint64_t virtualKey) {
13438 switch (virtualKey) {
13672 case VK_VOLUME_MUTE:
13674 case VK_VOLUME_DOWN:
13678 case VK_MEDIA_NEXT_TRACK:
13680 case VK_MEDIA_PREV_TRACK:
13682 case VK_MEDIA_STOP:
13684 case VK_MEDIA_PLAY_PAUSE:
13693 case VK_OEM_PERIOD:
13714 return fplKey_None;
13718fpl_internal bool fpl__Win32InitWindow(
const fplSettings *initSettings,
fplWindowSettings *currentWindowSettings, fpl__PlatformAppState *platAppState, fpl__Win32AppState *appState, fpl__Win32WindowState *windowState,
const fpl__SetupWindowCallbacks *setupCallbacks) {
13720 const fpl__Win32Api *wapi = &appState->winApi;
13725 for (
int i = 0; i < 256; ++i) {
13726 int vk = wapi->user.MapVirtualKeyW(MAPVK_VSC_TO_VK, i);
13730 platAppState->window.keyMap[i] = fpl__Win32TranslateVirtualKey(wapi, vk);
13735 SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
13737 SetThreadExecutionState(ES_CONTINUOUS);
13741 if (setupCallbacks->preSetup !=
fpl_null) {
13742 setupCallbacks->preSetup(platAppState, platAppState->initFlags, &platAppState->initSettings);
13747 windowClass.cbSize =
sizeof(windowClass);
13748 windowClass.hInstance = GetModuleHandleA(
fpl_null);
13752 windowState->backgroundBrush =
fpl_null;
13753 windowClass.hbrBackground = wapi->user.GetSysColorBrush(COLOR_BACKGROUND);
13756 windowState->backgroundBrush = wapi->gdi.CreateSolidBrush(brushColor);
13757 windowClass.hbrBackground = windowState->backgroundBrush;
13760 windowClass.cbSize =
sizeof(windowClass);
13761 windowClass.style = CS_HREDRAW | CS_VREDRAW;
13762 windowClass.hCursor = fpl__win32_LoadCursor(windowClass.hInstance, IDC_ARROW);
13763 windowClass.hIconSm = fpl__Win32LoadIconFromImageSource(wapi, windowClass.hInstance, &initWindowSettings->
icons[0]);
13764 windowClass.hIcon = fpl__Win32LoadIconFromImageSource(wapi, windowClass.hInstance, &initWindowSettings->
icons[1]);
13765 windowClass.lpszClassName = FPL__WIN32_CLASSNAME;
13766 windowClass.lpfnWndProc = fpl__Win32MessageProc;
13767 windowClass.style |= CS_OWNDC;
13768 lstrcpynW(windowState->windowClass, windowClass.lpszClassName,
fplArrayCount(windowState->windowClass));
13769 if (wapi->user.RegisterClassExW(&windowClass) == 0) {
13770 FPL__ERROR(FPL__MODULE_WINDOW,
"Failed registering window class '%s'", windowState->windowClass);
13779 const wchar_t *defaultTitle = FPL__WIN32_UNNAMED_WINDOW;
13780 lstrcpynW(windowTitleBuffer, defaultTitle,
fplArrayCount(windowTitleBuffer));
13782 wchar_t *windowTitle = windowTitleBuffer;
13786 windowState->mainFiber = ConvertThreadToFiber(0);
13787 windowState->messageFiber = CreateFiber(0, (PFIBER_START_ROUTINE)fpl__Win32MessageFiberProc, platAppState);
13790 DWORD style = fpl__Win32MakeWindowStyle(&initSettings->
window);
13791 DWORD exStyle = fpl__Win32MakeWindowExStyle(&initSettings->
window);
13797 int windowX = CW_USEDEFAULT;
13798 int windowY = CW_USEDEFAULT;
13804 windowRect.left = 0;
13805 windowRect.top = 0;
13808 wapi->user.AdjustWindowRect(&windowRect, style,
false);
13809 windowWidth = windowRect.right - windowRect.left;
13810 windowHeight = windowRect.bottom - windowRect.top;
13813 windowWidth = CW_USEDEFAULT;
13814 windowHeight = CW_USEDEFAULT;
13818 windowState->windowHandle = wapi->user.CreateWindowExW(exStyle, windowClass.lpszClassName, windowTitle, style, windowX, windowY, windowWidth, windowHeight,
fpl_null,
fpl_null, windowClass.hInstance,
fpl_null);
13819 if (windowState->windowHandle ==
fpl_null) {
13820 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);
13825 wapi->shell.DragAcceptFiles(windowState->windowHandle, TRUE);
13831 if (wapi->user.GetClientRect(windowState->windowHandle, &clientRect)) {
13832 currentWindowSettings->
windowSize.
width = clientRect.right - clientRect.left;
13833 currentWindowSettings->
windowSize.
height = clientRect.bottom - clientRect.top;
13837 windowState->deviceContext = wapi->user.GetDC(windowState->windowHandle);
13838 if (windowState->deviceContext ==
fpl_null) {
13839 FPL__ERROR(FPL__MODULE_WINDOW,
"Failed aquiring device context from window '%d'", windowState->windowHandle);
13844 if (setupCallbacks->postSetup !=
fpl_null) {
13845 setupCallbacks->postSetup(platAppState, platAppState->initFlags, initSettings);
13854 wapi->user.ShowWindow(windowState->windowHandle, SW_SHOW);
13855 wapi->user.SetForegroundWindow(windowState->windowHandle);
13856 wapi->user.SetFocus(windowState->windowHandle);
13859 windowState->defaultCursor = windowClass.hCursor;
13860 windowState->isCursorActive =
true;
13861 platAppState->window.isRunning =
true;
13866fpl_internal void fpl__Win32ReleaseWindow(
const fpl__Win32InitState *initState,
const fpl__Win32AppState *appState, fpl__Win32WindowState *windowState) {
13867 const fpl__Win32Api *wapi = &appState->winApi;
13868 if (windowState->deviceContext !=
fpl_null) {
13869 wapi->user.ReleaseDC(windowState->windowHandle, windowState->deviceContext);
13870 windowState->deviceContext =
fpl_null;
13872 if (windowState->windowHandle !=
fpl_null) {
13873 wapi->user.DestroyWindow(windowState->windowHandle);
13874 windowState->windowHandle =
fpl_null;
13875 wapi->user.UnregisterClassW(windowState->windowClass, initState->appInstance);
13877 if (windowState->backgroundBrush !=
fpl_null) {
13878 wapi->gdi.DeleteObject(windowState->backgroundBrush);
13879 windowState->backgroundBrush =
fpl_null;
13881 if (windowState->messageFiber !=
fpl_null) {
13882 DeleteFiber(windowState->messageFiber);
13883 windowState->messageFiber =
fpl_null;
13885 if (windowState->mainFiber !=
fpl_null) {
13886 ConvertFiberToThread();
13887 windowState->mainFiber =
fpl_null;
13894 FPL__CheckArgumentNull(threads,
false);
13895 FPL__CheckArgumentMax(count, FPL_MAX_THREAD_COUNT,
false);
13897 const size_t actualStride = stride > 0 ? stride :
sizeof(
fplThreadHandle *);
13898 for (
size_t index = 0; index < count; ++index) {
13901 FPL__ERROR(FPL__MODULE_THREADING,
"Thread for index '%d' are not allowed to be null", index);
13906 FPL__ERROR(FPL__MODULE_THREADING,
"Thread handle for index '%d' are not allowed to be null", index);
13915 size_t minThreads = waitForAll ? count : 1;
13916 size_t stoppedThreads = 0;
13917 while (stoppedThreads < minThreads) {
13918 stoppedThreads = 0;
13919 for (
size_t index = 0; index < count; ++index) {
13925 if (stoppedThreads >= minThreads) {
13935 bool result = stoppedThreads >= minThreads;
13940 FPL__CheckArgumentNull(signals,
false);
13941 FPL__CheckArgumentMax(count, FPL_MAX_SIGNAL_COUNT,
false);
13943 HANDLE signalHandles[FPL_MAX_SIGNAL_COUNT];
13944 const size_t actualStride = stride > 0 ? stride :
sizeof(
fplSignalHandle *);
13945 for (uint32_t index = 0; index < count; ++index) {
13947 if (availableSignal ==
fpl_null) {
13948 FPL__ERROR(FPL__MODULE_THREADING,
"Signal for index '%d' are not allowed to be null", index);
13952 FPL__ERROR(FPL__MODULE_THREADING,
"Signal handle for index '%d' are not allowed to be null", index);
13955 HANDLE handle = availableSignal->
internalHandle.win32EventHandle;
13956 signalHandles[index] = handle;
13959 DWORD code = WaitForMultipleObjects((DWORD)count, signalHandles, waitForAll ? TRUE : FALSE, t);
13960 bool result = (code >= WAIT_OBJECT_0);
13964fpl_internal void fpl__Win32ReleasePlatform(fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
13966 fpl__Win32AppState *win32AppState = &appState->win32;
13967 fpl__Win32InitState *win32InitState = &initState->win32;
13969 fpl__Win32UnloadXInputApi(&win32AppState->xinput.xinputApi);
13971 fpl__Win32UnloadApi(&win32AppState->winApi);
13974fpl_internal bool fpl__Win32InitPlatform(
const fplInitFlags initFlags,
const fplSettings *initSettings, fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
13978 fpl__Win32InitState *win32InitState = &initState->win32;
13979 fpl__Win32AppState *win32AppState = &appState->win32;
13984 win32InitState->appInstance = GetModuleHandleA(
fpl_null);
13987 QueryPerformanceFrequency(&win32InitState->qpf);
13990 HANDLE mainThreadHandle = GetCurrentThread();
13991 DWORD mainThreadHandleId = GetCurrentThreadId();
13994 mainThread->
id = mainThreadHandleId;
13995 mainThread->
internalHandle.win32ThreadHandle = mainThreadHandle;
13999 if (!fpl__Win32LoadApi(&win32AppState->winApi)) {
14001 fpl__Win32ReleasePlatform(initState, appState);
14007 fpl__Win32LoadXInputApi(&win32AppState->xinput.xinputApi);
14012 HWND consoleWindow = GetConsoleWindow();
14013 if (!showConsole) {
14015 win32AppState->winApi.user.ShowWindow(consoleWindow, SW_HIDE);
14019 }
else if (consoleWindow !=
fpl_null) {
14028 const wchar_t *defaultTitle = FPL__WIN32_UNNAMED_CONSOLE;
14029 lstrcpynW(consoleTitleBuffer, defaultTitle,
fplArrayCount(consoleTitleBuffer));
14031 wchar_t *windowTitle = consoleTitleBuffer;
14033 SetConsoleTitleW(windowTitle);
14035 win32AppState->winApi.user.ShowWindow(consoleWindow, SW_SHOW);
14045 FPL_MEMORY_BARRIER();
14049 FPL_MEMORY_BARRIER();
14053 FPL_MEMORY_BARRIER();
14054 _ReadWriteBarrier();
14059 uint32_t result = InterlockedExchange((
volatile LONG *)target, value);
14064 int32_t result = InterlockedExchange((
volatile LONG *)target, value);
14069 uint64_t result = InterlockedExchange64((
volatile LONG64 *)target, value);
14074 int64_t result = InterlockedExchange64((
volatile LONG64 *)target, value);
14080 uint32_t result = InterlockedExchangeAdd((
volatile LONG *)value, addend);
14085 int32_t result = InterlockedExchangeAdd((
volatile LONG *)value, addend);
14090 uint64_t result = InterlockedExchangeAdd64((
volatile LONG64 *)value, addend);
14095 int64_t result = InterlockedExchangeAdd64((
volatile LONG64 *)value, addend);
14101 uint32_t result = InterlockedAdd((
volatile LONG *)value, addend);
14106 int32_t result = InterlockedAdd((
volatile LONG *)value, addend);
14111 uint64_t result = InterlockedAdd64((
volatile LONG64 *)value, addend);
14116 int64_t result = InterlockedAdd64((
volatile LONG64 *)value, addend);
14122 uint32_t result = InterlockedIncrement((
volatile LONG *)value);
14127 int32_t result = InterlockedIncrement((
volatile LONG *)value);
14132 uint64_t result = InterlockedIncrement64((
volatile LONG64 *)value);
14137 int64_t result = InterlockedIncrement64((
volatile LONG64 *)value);
14143 uint32_t result = InterlockedCompareExchange((
volatile LONG *)dest, exchange, comparand);
14148 int32_t result = InterlockedCompareExchange((
volatile LONG *)dest, exchange, comparand);
14153 uint64_t result = InterlockedCompareExchange64((
volatile LONG64 *)dest, exchange, comparand);
14158 int64_t result = InterlockedCompareExchange64((
volatile LONG64 *)dest, exchange, comparand);
14164 uint32_t value = InterlockedCompareExchange((
volatile LONG *)dest, exchange, comparand);
14165 bool result = (value == comparand);
14170 int32_t value = InterlockedCompareExchange((
volatile LONG *)dest, exchange, comparand);
14171 bool result = (value == comparand);
14176 uint64_t value = InterlockedCompareExchange64((
volatile LONG64 *)dest, exchange, comparand);
14177 bool result = (value == comparand);
14182 int64_t value = InterlockedCompareExchange64((
volatile LONG64 *)dest, exchange, comparand);
14183 bool result = (value == comparand);
14188 uint32_t result = InterlockedCompareExchange((
volatile LONG *)source, 0, 0);
14192 uint64_t result = InterlockedCompareExchange64((
volatile LONG64 *)source, 0, 0);
14196 int32_t result = InterlockedCompareExchange((
volatile LONG *)source, 0, 0);
14200 int64_t result = InterlockedCompareExchange64((
volatile LONG64 *)source, 0, 0);
14205 InterlockedExchange((
volatile LONG *)dest, value);
14208 InterlockedExchange64((
volatile LONG64 *)dest, value);
14211 InterlockedExchange((
volatile LONG *)dest, value);
14214 InterlockedExchange64((
volatile LONG64 *)dest, value);
14220fpl_internal const char *fpl__Win32GetVersionName(DWORD major, DWORD minor) {
14221 const char *result;
14222 if (major == 5 && minor == 0) {
14223 result =
"Windows 2000";
14224 }
else if (major == 5 && minor == 1) {
14225 result =
"Windows XP";
14226 }
else if (major == 5 && minor == 2) {
14227 result =
"Windows XP";
14228 }
else if (major == 6 && minor == 0) {
14229 result =
"Windows Vista";
14230 }
else if (major == 6 && minor == 1) {
14231 result =
"Windows 7";
14232 }
else if (major == 6 && minor == 2) {
14233 result =
"Windows 8";
14234 }
else if (major == 6 && minor == 3) {
14235 result =
"Windows 8.1";
14236 }
else if (major == 10) {
14237 result =
"Windows 10";
14239 result =
"Windows";
14244#define FPL__FUNC_NTDLL_RtlGetVersion(name) DWORD WINAPI name(PRTL_OSVERSIONINFOW lpVersionInformation)
14245typedef FPL__FUNC_NTDLL_RtlGetVersion(fpl__func_ntdll_RtlGetVersionProc);
14246#define FPL__FUNC_KERNEL32_GetVersion(name) DWORD WINAPI name(void)
14247typedef FPL__FUNC_KERNEL32_GetVersion(fpl__func_kernel32_GetVersion);
14248#define FPL__FUNC_KERNEL32_GetVersionExW(name) BOOL WINAPI name(LPOSVERSIONINFOEXW lpVersionInfo)
14249typedef FPL__FUNC_KERNEL32_GetVersionExW(fpl__func_kernel32_GetVersionExW);
14251 FPL__CheckArgumentNull(outInfos,
false);
14256 HMODULE ntdllModule = GetModuleHandleA(
"ntdll");
14257 fpl__func_ntdll_RtlGetVersionProc *rtlGetVersionProc = (fpl__func_ntdll_RtlGetVersionProc *)(
void *)GetProcAddress(ntdllModule,
"RtlGetVersion");
14258 if (rtlGetVersionProc !=
fpl_null) {
14260 info.dwOSVersionInfoSize =
sizeof(info);
14261 if (rtlGetVersionProc(&info) == 0) {
14267 const char *versionName = fpl__Win32GetVersionName(info.dwMajorVersion, info.dwMinorVersion);
14274 HMODULE kernelLib = LoadLibraryA(
"kernel32.dll");
14276 FPL__ERROR(FPL__MODULE_WIN32,
"Kernel32 library could not be loaded");
14279 fpl__func_kernel32_GetVersion *getVersionProc = (fpl__func_kernel32_GetVersion *)(
void *)GetProcAddress(kernelLib,
"GetVersion");
14280 fpl__func_kernel32_GetVersionExW *getVersionExProc = (fpl__func_kernel32_GetVersionExW *)(
void *)GetProcAddress(kernelLib,
"GetVersionExW");
14281 FreeLibrary(kernelLib);
14283 if (getVersionExProc !=
fpl_null) {
14285 infoEx.dwOSVersionInfoSize =
sizeof(infoEx);
14286 if (getVersionExProc(&infoEx) == TRUE) {
14292 const char *versionName = fpl__Win32GetVersionName(infoEx.dwMajorVersion, infoEx.dwMinorVersion);
14299 DWORD dwVersion = getVersionProc();
14300 if (dwVersion > 0) {
14301 DWORD major = (DWORD)(LOBYTE(LOWORD(dwVersion)));
14302 DWORD minor = (DWORD)(HIBYTE(LOWORD(dwVersion)));
14304 if (dwVersion < 0x80000000) {
14305 build = (DWORD)((DWORD)(HIWORD(dwVersion)));
14312 const char *versionName = fpl__Win32GetVersionName(major, minor);
14321#define FPL__FUNC_ADV32_GetUserNameW(name) BOOL WINAPI name(LPWSTR lpBuffer, LPDWORD pcbBuffer)
14322typedef FPL__FUNC_ADV32_GetUserNameW(fpl__func_adv32_GetUserNameW);
14324 const char *libName =
"advapi32.dll";
14325 HMODULE adv32Lib = LoadLibraryA(libName);
14327 FPL__ERROR(FPL__MODULE_WIN32,
"Failed loading library '%s'", libName);
14330 fpl__func_adv32_GetUserNameW *getUserNameProc = (fpl__func_adv32_GetUserNameW *)(
void *)GetProcAddress(adv32Lib,
"GetUserNameW");
14332 if (getUserNameProc !=
fpl_null) {
14335 if (getUserNameProc(wideBuffer, &size) == TRUE) {
14339 FreeLibrary(adv32Lib);
14348 GetSystemInfo(&sysInfo);
14350 size_t result = sysInfo.dwNumberOfProcessors;
14354#define FPL__WIN32_PROCESSOR_ARCHITECTURE_ARM64 12
14359 if (IsWow64Process(GetCurrentProcess(), &isWow64)) {
14361 GetNativeSystemInfo(&sysInfo);
14363 GetSystemInfo(&sysInfo);
14365 GetSystemInfo(&sysInfo);
14367 switch (sysInfo.wProcessorArchitecture) {
14368 case PROCESSOR_ARCHITECTURE_AMD64:
14371 case PROCESSOR_ARCHITECTURE_IA64:
14374 case PROCESSOR_ARCHITECTURE_ARM:
14377 case FPL__WIN32_PROCESSOR_ARCHITECTURE_ARM64:
14380 case PROCESSOR_ARCHITECTURE_UNKNOWN:
14383 case PROCESSOR_ARCHITECTURE_INTEL:
14391#define FPL__FUNC_WIN32_KERNEL32_GetPhysicallyInstalledSystemMemory(name) BOOL WINAPI name(PULONGLONG TotalMemoryInKilobytes)
14392typedef FPL__FUNC_WIN32_KERNEL32_GetPhysicallyInstalledSystemMemory(fpl__win32_kernel_func_GetPhysicallyInstalledSystemMemory);
14394 FPL__CheckArgumentNull(outInfos,
false);
14395 bool result =
false;
14397 HMODULE kernel32lib = LoadLibraryA(
"kernel32.dll");
14401 fpl__win32_kernel_func_GetPhysicallyInstalledSystemMemory *getPhysicallyInstalledSystemMemory = (fpl__win32_kernel_func_GetPhysicallyInstalledSystemMemory *)(
void *)GetProcAddress(kernel32lib,
"GetPhysicallyInstalledSystemMemory");
14402 FreeLibrary(kernel32lib);
14404 ULONGLONG installedMemorySize = 0;
14405 if (getPhysicallyInstalledSystemMemory !=
fpl_null) {
14406 getPhysicallyInstalledSystemMemory(&installedMemorySize);
14410 GetSystemInfo(&systemInfo);
14413 statex.dwLength =
sizeof(statex);
14415 if (GlobalMemoryStatusEx(&statex)) {
14422 outInfos->
pageSize = systemInfo.dwPageSize;
14435fpl_internal DWORD WINAPI fpl__Win32ThreadProc(
void *data) {
14451 CloseHandle(handle);
14459 DWORD threadId = GetCurrentThreadId();
14460 uint32_t result = (uint32_t)threadId;
14465 int win32Priority = 0;
14466 switch (newPriority) {
14468 win32Priority = THREAD_PRIORITY_IDLE;
14471 win32Priority = THREAD_PRIORITY_LOWEST;
14474 win32Priority = THREAD_PRIORITY_NORMAL;
14477 win32Priority = THREAD_PRIORITY_HIGHEST;
14480 win32Priority = THREAD_PRIORITY_TIME_CRITICAL;
14483 FPL__ERROR(
"Threading",
"The thread priority %d is not supported", newPriority);
14486 bool result = SetThreadPriority(threadHandle, win32Priority) == TRUE;
14491 FPL__CheckArgumentNull(parameters,
fpl_null);
14496 DWORD creationFlags = 0;
14497 DWORD threadId = 0;
14498 SIZE_T stackSize = parameters->
stackSize;
14501 HANDLE handle = CreateThread(
fpl_null, stackSize, fpl__Win32ThreadProc, thread, creationFlags, &threadId);
14505 thread->
id = threadId;
14509 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating thread, error code: %d", GetLastError());
14512 FPL__ERROR(FPL__MODULE_THREADING,
"All %d threads are in use, you cannot create until you free one", FPL_MAX_THREAD_COUNT);
14518 FPL__CheckArgumentNull(runFunc,
fpl_null);
14521 parameters.
runFunc = runFunc;
14528 switch (win32ThreadPriority) {
14529 case THREAD_PRIORITY_IDLE:
14531 case THREAD_PRIORITY_LOWEST:
14532 case THREAD_PRIORITY_BELOW_NORMAL:
14534 case THREAD_PRIORITY_NORMAL:
14536 case THREAD_PRIORITY_ABOVE_NORMAL:
14537 case THREAD_PRIORITY_HIGHEST:
14539 case THREAD_PRIORITY_TIME_CRITICAL:
14551 int win32ThreadPriority = GetThreadPriority(threadHandle);
14552 result = fpl__Win32MapNativeThreadPriority(win32ThreadPriority);
14558 FPL__CheckArgumentNull(thread,
false);
14559 bool result =
false;
14562 result = fpl__Win32SetThreadPriority(threadHandle, newPriority);
14568 Sleep((DWORD)milliseconds);
14577 FPL__CheckArgumentNull(thread,
false);
14583 TerminateThread(handle, 0);
14584 CloseHandle(handle);
14595 FPL__CheckArgumentNull(thread,
false);
14599 FPL__ERROR(FPL__MODULE_THREADING,
"Win32 thread handle are not allowed to be null");
14604 result = (WaitForSingleObject(handle, t) == WAIT_OBJECT_0);
14612 bool result = fpl__Win32ThreadWaitForMultiple(threads, count, stride, timeout,
true);
14617 bool result = fpl__Win32ThreadWaitForMultiple(threads, count, stride, timeout,
false);
14622 FPL__CheckArgumentNull(mutex,
false);
14624 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex '%p' is already initialized", mutex);
14630 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
14631 InitializeCriticalSection(critSection);
14636 FPL__CheckArgumentNullNoRet(mutex);
14639 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
14640 DeleteCriticalSection(critSection);
14646 FPL__CheckArgumentNull(mutex,
false);
14648 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex parameter must be valid");
14652 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
14653 EnterCriticalSection(critSection);
14658 FPL__CheckArgumentNull(mutex,
false);
14660 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex parameter must be valid");
14664 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
14665 bool result = TryEnterCriticalSection(critSection) == TRUE;
14670 FPL__CheckArgumentNull(mutex,
false);
14672 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex parameter must be valid");
14676 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
14677 LeaveCriticalSection(critSection);
14682 FPL__CheckArgumentNull(signal,
false);
14684 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' is already initialized", signal);
14689 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating signal (Win32 event): %d", GetLastError());
14699 FPL__CheckArgumentNullNoRet(signal);
14702 CloseHandle(handle);
14708 FPL__CheckArgumentNull(signal,
false);
14710 FPL__ERROR(FPL__MODULE_THREADING,
"Signal handle are not allowed to be null");
14715 bool result = (WaitForSingleObject(handle, t) == WAIT_OBJECT_0);
14720 bool result = fpl__Win32SignalWaitForMultiple(signals, count, stride, timeout,
true);
14725 bool result = fpl__Win32SignalWaitForMultiple(signals, count, stride, timeout,
false);
14730 FPL__CheckArgumentNull(signal,
false);
14732 FPL__ERROR(FPL__MODULE_THREADING,
"Signal handle are not allowed to be null");
14736 bool result = SetEvent(handle) == TRUE;
14741 FPL__CheckArgumentNull(signal,
false);
14743 FPL__ERROR(FPL__MODULE_THREADING,
"Signal handle are not allowed to be null");
14747 bool result = ResetEvent(handle) == TRUE;
14752 FPL__CheckArgumentNull(condition,
false);
14755 CONDITION_VARIABLE *condVar = (CONDITION_VARIABLE *)&condition->
internalHandle.win32Condition;
14756 InitializeConditionVariable(condVar);
14762 FPL__CheckArgumentNullNoRet(condition);
14769 FPL__CheckArgumentNull(condition,
false);
14770 FPL__CheckArgumentNull(mutex,
false);
14772 FPL__ERROR(FPL__MODULE_THREADING,
"Condition '%p' is not valid", condition);
14776 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex '%p' is not valid", mutex);
14780 CRITICAL_SECTION *critSection = (CRITICAL_SECTION *)&mutex->
internalHandle.win32CriticalSection;
14781 CONDITION_VARIABLE *condVar = (CONDITION_VARIABLE *)&condition->
internalHandle.win32Condition;
14782 bool result = SleepConditionVariableCS(condVar, critSection, t) != 0;
14787 FPL__CheckArgumentNull(condition,
false);
14789 FPL__ERROR(FPL__MODULE_THREADING,
"Condition '%p' is not valid", condition);
14792 CONDITION_VARIABLE *critSection = (CONDITION_VARIABLE *)&condition->
internalHandle.win32Condition;
14793 WakeConditionVariable(critSection);
14798 FPL__CheckArgumentNull(condition,
false);
14800 FPL__ERROR(FPL__MODULE_THREADING,
"Condition '%p' is not valid", condition);
14803 CONDITION_VARIABLE *critSection = (CONDITION_VARIABLE *)&condition->
internalHandle.win32Condition;
14804 WakeAllConditionVariable(critSection);
14809 FPL__CheckArgumentNull(semaphore,
false);
14810 FPL__CheckArgumentMax(initialValue, INT32_MAX,
false);
14812 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is already initialized", semaphore);
14815 HANDLE handle = CreateSemaphoreA(
fpl_null, (LONG)initialValue, INT32_MAX,
fpl_null);
14817 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating semaphore");
14828 FPL__CheckArgumentNullNoRet(semaphore);
14836 FPL__CheckArgumentNull(semaphore,
false);
14838 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
14842 bool result =
false;
14843 if (WaitForSingleObject(semaphore->
internalHandle.win32.handle, timeout) == WAIT_OBJECT_0) {
14851 FPL__CheckArgumentNull(semaphore,
false);
14853 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
14856 bool result =
false;
14857 if (WaitForSingleObject(semaphore->
internalHandle.win32.handle, 0) == WAIT_OBJECT_0) {
14865 FPL__CheckArgumentNull(semaphore,
false);
14867 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
14875 FPL__CheckArgumentNull(semaphore,
false);
14877 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
14880 bool result =
true;
14884 FPL__ERROR(FPL__MODULE_THREADING,
"Failed releasing the semaphore '%p'", semaphore);
14896 DWORD writtenChars = 0;
14897 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
14900 WriteConsoleW(handle, wideBuffer, charsToWrite, &writtenChars,
fpl_null);
14905 DWORD writtenChars = 0;
14906 HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
14909 WriteConsoleW(handle, wideBuffer, charsToWrite, &writtenChars,
fpl_null);
14913 HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
14915 GetConsoleMode(handle, &savedMode);
14916 SetConsoleMode(handle, ENABLE_PROCESSED_INPUT);
14918 if (WaitForSingleObject(handle, INFINITE) == WAIT_OBJECT_0) {
14919 DWORD charsRead = 0;
14921 if (ReadFile(handle, inputBuffer, 1, &charsRead,
fpl_null) != 0) {
14922 result = inputBuffer[0];
14925 SetConsoleMode(handle, savedMode);
14933 FPL__CheckArgumentZero(size,
fpl_null);
14934 void *result = VirtualAlloc(
fpl_null, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
14936 FPL__ERROR(FPL__MODULE_MEMORY,
"Failed allocating memory of %xu bytes", size);
14942 FPL__CheckArgumentNullNoRet(ptr);
14943 VirtualFree(ptr, 0, MEM_RELEASE);
14949fpl_internal const uint64_t FPL__WIN32_TICKS_PER_SEC = 10000000ULL;
14950fpl_internal const uint64_t FPL__WIN32_UNIX_EPOCH_DIFFERENCE = 11644473600ULL;
14957 if (fileTime !=
fpl_null && (fileTime->dwLowDateTime > 0 || fileTime->dwHighDateTime > 0)) {
14959 SYSTEMTIME sysTime;
14960 FileTimeToSystemTime(fileTime, &sysTime);
14961 sysTime.wMilliseconds = 0;
14964 FILETIME withoutMSecs;
14965 SystemTimeToFileTime(&sysTime, &withoutMSecs);
14968 ULARGE_INTEGER ticks;
14969 ticks.LowPart = withoutMSecs.dwLowDateTime;
14970 ticks.HighPart = withoutMSecs.dwHighDateTime;
14973 result = (ticks.QuadPart / FPL__WIN32_TICKS_PER_SEC) - FPL__WIN32_UNIX_EPOCH_DIFFERENCE;
14983 if (unixTimeStamp > 0) {
14984 uint64_t ticks = (unixTimeStamp + FPL__WIN32_UNIX_EPOCH_DIFFERENCE) * FPL__WIN32_TICKS_PER_SEC;
14986 result.dwLowDateTime = (DWORD)ticks;
14987 result.dwHighDateTime = ticks >> 32;
14995 FPL__CheckArgumentNull(outHandle,
false);
14999 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_READ, FILE_SHARE_READ,
fpl_null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
fpl_null);
15000 if (win32FileHandle != INVALID_HANDLE_VALUE) {
15003 outHandle->
internalHandle.win32FileHandle = (
void *)win32FileHandle;
15011 FPL__CheckArgumentNull(outHandle,
false);
15015 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_WRITE, FILE_SHARE_WRITE,
fpl_null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
fpl_null);
15016 if (win32FileHandle != INVALID_HANDLE_VALUE) {
15019 outHandle->
internalHandle.win32FileHandle = (
void *)win32FileHandle;
15027 FPL__CheckArgumentNull(fileHandle, 0);
15028 FPL__CheckArgumentZero(sizeToRead, 0);
15029 FPL__CheckArgumentNull(targetBuffer, 0);
15031 FPL__ERROR(FPL__MODULE_FILES,
"Filehandle is not opened for reading");
15034 uint32_t result = 0;
15035 HANDLE win32FileHandle = (HANDLE)fileHandle->
internalHandle.win32FileHandle;
15036 DWORD bytesRead = 0;
15037 if (ReadFile(win32FileHandle, targetBuffer, (DWORD)sizeToRead, &bytesRead,
fpl_null) == TRUE) {
15038 result = bytesRead;
15044 FPL__CheckArgumentNull(fileHandle, 0);
15045 FPL__CheckArgumentZero(sizeToRead, 0);
15046 FPL__CheckArgumentNull(targetBuffer, 0);
15048 FPL__ERROR(FPL__MODULE_FILES,
"Filehandle is not opened for reading");
15052 uint64_t result = 0;
15053 HANDLE win32FileHandle = (HANDLE)fileHandle->
internalHandle.win32FileHandle;
15054 uint64_t remainingSize = sizeToRead;
15055 uint64_t bufferPos = 0;
15056 const uint64_t MaxDWORD = (uint64_t)(DWORD)-1;
15057 while (remainingSize > 0) {
15058 DWORD bytesRead = 0;
15059 uint8_t *target = (uint8_t *)targetBuffer + bufferPos;
15060 uint64_t size =
fplMin(remainingSize, MaxDWORD);
15062 if (ReadFile(win32FileHandle, target, (DWORD)size, &bytesRead,
fpl_null) == TRUE) {
15063 result = bytesRead;
15067 remainingSize -= bytesRead;
15068 bufferPos += bytesRead;
15074 FPL__CheckArgumentNull(fileHandle, 0);
15075 FPL__CheckArgumentZero(sourceSize, 0);
15076 FPL__CheckArgumentNull(sourceBuffer, 0);
15078 FPL__ERROR(FPL__MODULE_FILES,
"Filehandle is not opened for writing");
15081 HANDLE win32FileHandle = (HANDLE)fileHandle->
internalHandle.win32FileHandle;
15082 uint32_t result = 0;
15083 DWORD bytesWritten = 0;
15084 if (WriteFile(win32FileHandle, sourceBuffer, (DWORD)sourceSize, &bytesWritten,
fpl_null) == TRUE) {
15085 result = bytesWritten;
15091 FPL__CheckArgumentNull(fileHandle, 0);
15092 FPL__CheckArgumentZero(sourceSize, 0);
15093 FPL__CheckArgumentNull(sourceBuffer, 0);
15095 FPL__ERROR(FPL__MODULE_FILES,
"Filehandle is not opened for writing");
15098 HANDLE win32FileHandle = (HANDLE)fileHandle->
internalHandle.win32FileHandle;
15099 uint64_t result = 0;
15100 uint64_t bufferPos = 0;
15101 uint64_t remainingSize = sourceSize;
15102 const uint64_t MaxDWORD = (uint64_t)(DWORD)-1;
15103 while (remainingSize > 0) {
15104 uint8_t *source = (uint8_t *)sourceBuffer + bufferPos;
15105 uint64_t size =
fplMin(remainingSize, MaxDWORD);
15107 DWORD bytesWritten = 0;
15108 if (WriteFile(win32FileHandle, source, (DWORD)size, &bytesWritten,
fpl_null) == TRUE) {
15109 result = bytesWritten;
15113 remainingSize -= bytesWritten;
15114 bufferPos += bytesWritten;
15120 FPL__CheckArgumentNull(fileHandle, 0);
15121 uint32_t result = 0;
15122 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15123 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
15124 DWORD moveMethod = FILE_BEGIN;
15126 moveMethod = FILE_CURRENT;
15128 moveMethod = FILE_END;
15131 r = SetFilePointer(win32FileHandle, (LONG)position,
fpl_null, moveMethod);
15132 result = (uint32_t)r;
15138 FPL__CheckArgumentNull(fileHandle, 0);
15139 uint64_t result = 0;
15140 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15141 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
15142 DWORD moveMethod = FILE_BEGIN;
15144 moveMethod = FILE_CURRENT;
15146 moveMethod = FILE_END;
15150 li.QuadPart = position;
15151 if (SetFilePointerEx(win32FileHandle, li, &r, moveMethod) == TRUE) {
15152 result = (uint64_t)r.QuadPart;
15159 FPL__CheckArgumentNull(fileHandle, 0);
15160 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15161 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
15162 DWORD filePosition = SetFilePointer(win32FileHandle, 0L,
fpl_null, FILE_CURRENT);
15163 if (filePosition != INVALID_SET_FILE_POINTER) {
15164 return filePosition;
15171 FPL__CheckArgumentNull(fileHandle, 0);
15172 uint64_t result = 0;
15173 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15174 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
15178 if (SetFilePointerEx(win32FileHandle, li, &r, FILE_CURRENT) == TRUE) {
15179 result = (uint64_t)r.QuadPart;
15186 FPL__CheckArgumentNull(fileHandle,
false);
15187 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15188 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
15189 bool result = FlushFileBuffers(win32FileHandle) == TRUE;
15197 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
15198 CloseHandle(win32FileHandle);
15204 uint32_t result = 0;
15208 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_READ, FILE_SHARE_READ,
fpl_null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
fpl_null);
15209 if (win32FileHandle != INVALID_HANDLE_VALUE) {
15210 DWORD fileSize = GetFileSize(win32FileHandle,
fpl_null);
15211 result = (uint32_t)fileSize;
15212 CloseHandle(win32FileHandle);
15219 uint64_t result = 0;
15223 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_READ, FILE_SHARE_READ,
fpl_null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
fpl_null);
15224 if (win32FileHandle != INVALID_HANDLE_VALUE) {
15226 if (GetFileSizeEx(win32FileHandle, &li) == TRUE) {
15227 result = (uint64_t)li.QuadPart;
15229 CloseHandle(win32FileHandle);
15236 FPL__CheckArgumentNull(fileHandle, 0);
15237 uint32_t result = 0;
15238 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15239 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
15240 DWORD fileSize = GetFileSize(win32FileHandle,
fpl_null);
15241 result = (uint32_t)fileSize;
15247 FPL__CheckArgumentNull(fileHandle, 0);
15248 uint64_t result = 0;
15249 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15250 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
15252 if (GetFileSizeEx(win32FileHandle, &li) == TRUE) {
15253 result = (uint64_t)li.QuadPart;
15260 FPL__CheckArgumentNull(outStamps,
false);
15264 HANDLE win32FileHandle = CreateFileW(filePathWide, GENERIC_READ, FILE_SHARE_READ,
fpl_null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
fpl_null);
15265 bool result =
false;
15266 if (win32FileHandle != INVALID_HANDLE_VALUE) {
15268 if (GetFileTime(win32FileHandle, ×[0], ×[1], ×[2]) == TRUE) {
15270 outStamps->
creationTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[0]);
15271 outStamps->
lastAccessTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[1]);
15272 outStamps->
lastModifyTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[2]);
15275 CloseHandle(win32FileHandle);
15283 FPL__CheckArgumentNull(fileHandle, 0);
15284 FPL__CheckArgumentNull(outStamps, 0);
15285 if (fileHandle->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15286 HANDLE win32FileHandle = (
void *)fileHandle->
internalHandle.win32FileHandle;
15288 if (GetFileTime(win32FileHandle, ×[0], ×[1], ×[2]) == TRUE) {
15290 outStamps->
creationTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[0]);
15291 outStamps->
lastAccessTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[1]);
15292 outStamps->
lastModifyTime = fpl__Win32ConvertFileTimeToUnixTimestamp(×[2]);
15300 bool result =
false;
15304 WIN32_FIND_DATAW findData;
15305 HANDLE searchHandle = FindFirstFileW(filePathWide, &findData);
15306 if (searchHandle != INVALID_HANDLE_VALUE) {
15307 result = !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
15308 FindClose(searchHandle);
15315 FPL__CheckArgumentNull(sourceFilePath,
false);
15316 FPL__CheckArgumentNull(targetFilePath,
false);
15321 bool result = (CopyFileW(sourceFilePathWide, targetFilePathWide, !overwrite) == TRUE);
15326 FPL__CheckArgumentNull(sourceFilePath,
false);
15327 FPL__CheckArgumentNull(targetFilePath,
false);
15332 bool result = (MoveFileW(sourceFilePathWide, targetFilePathWide) == TRUE);
15337 FPL__CheckArgumentNull(filePath,
false);
15340 bool result = (DeleteFileW(filePathWide) == TRUE);
15345 bool result =
false;
15349 WIN32_FIND_DATAW findData;
15350 HANDLE searchHandle = FindFirstFileW(pathWide, &findData);
15351 if (searchHandle != INVALID_HANDLE_VALUE) {
15352 result = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0;
15353 FindClose(searchHandle);
15360 FPL__CheckArgumentNull(path,
false);
15363 bool result = CreateDirectoryW(pathWide,
fpl_null) > 0;
15367 FPL__CheckArgumentNull(path,
false);
15370 bool result = RemoveDirectoryW(pathWide) > 0;
15373fpl_internal void fpl__Win32FillFileEntry(
const char *rootPath,
const WIN32_FIND_DATAW *findData,
fplFileEntry *entry) {
15378 if (findData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
15381 (findData->dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
15382 (findData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
15383 (findData->dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
15384 (findData->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ||
15385 (findData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
15392 if (findData->dwFileAttributes & FILE_ATTRIBUTE_NORMAL) {
15395 if (findData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
15398 if (findData->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
15401 if (findData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
15407 if ((findData->dwFileAttributes & FILE_ATTRIBUTE_READONLY) || (findData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
15413 ul.LowPart = findData->nFileSizeLow;
15414 ul.HighPart = findData->nFileSizeHigh;
15415 entry->
size = (size_t)ul.QuadPart;
15424 FPL__CheckArgumentNull(path,
false);
15425 FPL__CheckArgumentNull(entry,
false);
15433 wchar_t pathAndFilterWide[MAX_PATH + 1];
15435 WIN32_FIND_DATAW findData;
15436 HANDLE searchHandle = FindFirstFileW(pathAndFilterWide, &findData);
15437 bool result =
false;
15438 if (searchHandle != INVALID_HANDLE_VALUE) {
15443 bool foundFirst =
true;
15444 while (foundFirst) {
15445 if (lstrcmpW(findData.cFileName, L
".") == 0 || lstrcmpW(findData.cFileName, L
"..") == 0) {
15446 foundFirst = FindNextFileW(searchHandle, &findData) == TRUE;
15449 fpl__Win32FillFileEntry(path, &findData, entry);
15457 FPL__CheckArgumentNull(entry,
false);
15458 bool result =
false;
15459 if (entry->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15461 WIN32_FIND_DATAW findData;
15464 foundNext = FindNextFileW(searchHandle, &findData) == TRUE;
15466 if (lstrcmpW(findData.cFileName, L
".") == 0 || lstrcmpW(findData.cFileName, L
"..") == 0) {
15473 }
while (foundNext);
15478 FPL__CheckArgumentNullNoRet(entry);
15479 if (entry->
internalHandle.win32FileHandle != INVALID_HANDLE_VALUE) {
15481 FindClose(searchHandle);
15490 wchar_t modulePath[MAX_PATH];
15491 GetModuleFileNameW(
fpl_null, modulePath, MAX_PATH);
15492 size_t modulePathLen = lstrlenW(modulePath);
15498 FPL__CheckPlatform(0);
15499 const fpl__Win32Api *wapi = &fpl__global__AppState->win32.winApi;
15500 wchar_t homePath[MAX_PATH];
15501 wapi->shell.SHGetFolderPathW(
fpl_null, CSIDL_PROFILE,
fpl_null, 0, homePath);
15502 size_t homePathLen = lstrlenW(homePath);
15511 const fpl__Win32InitState *initState = &fpl__global__InitState.win32;
15513 if (initState->qpf.QuadPart > 0) {
15514 LARGE_INTEGER time;
15515 QueryPerformanceCounter(&time);
15516 result.win32.qpc.QuadPart = time.QuadPart;
15518 result.win32.ticks = GetTickCount64();
15524 const fpl__Win32InitState *initState = &fpl__global__InitState.win32;
15526 LARGE_INTEGER freq = initState->qpf;
15527 if (freq.QuadPart > 0) {
15528 uint64_t delta = finish.win32.qpc.QuadPart - start.win32.qpc.QuadPart;
15529 result = (
fplSeconds)(delta / (
double)freq.QuadPart);
15531 uint64_t delta = finish.win32.ticks - start.win32.ticks;
15546 FPL__CheckArgumentNull(wideSource, 0);
15547 FPL__CheckArgumentZero(wideSourceLen, 0);
15550 size_t minRequiredLen = result + 1;
15551 FPL__CheckArgumentMin(maxUtf8DestLen, minRequiredLen, 0);
15552 WideCharToMultiByte(CP_UTF8, 0, wideSource, (
int)wideSourceLen, utf8Dest, (
int)maxUtf8DestLen,
fpl_null,
fpl_null);
15553 utf8Dest[result] = 0;
15558 FPL__CheckArgumentNull(utf8Source, 0);
15559 FPL__CheckArgumentZero(utf8SourceLen, 0);
15560 size_t result = MultiByteToWideChar(CP_UTF8, 0, utf8Source, (
int)utf8SourceLen,
fpl_null, 0);
15562 size_t minRequiredLen = result + 1;
15563 FPL__CheckArgumentMin(maxWideDestLen, minRequiredLen, 0);
15564 MultiByteToWideChar(CP_UTF8, 0, utf8Source, (
int)utf8SourceLen, wideDest, (
int)maxWideDestLen);
15565 wideDest[result] = 0;
15574 bool result =
false;
15578 HMODULE libModule = LoadLibraryW(libraryFilePathWide);
15590 HMODULE libModule = (HMODULE)handle->
internalHandle.win32LibraryHandle;
15591 return (
void *)GetProcAddress(libModule, name);
15597 HMODULE libModule = (HMODULE)handle->
internalHandle.win32LibraryHandle;
15598 FreeLibrary(libModule);
15603#if defined(FPL__ENABLE_WINDOW)
15608 FPL__CheckArgumentNull(outSize,
false);
15609 FPL__CheckPlatform(
false);
15610 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
15611 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15612 const fpl__Win32Api *wapi = &appState->winApi;
15613 bool result =
false;
15615 if (wapi->user.GetClientRect(windowState->windowHandle, &windowRect)) {
15616 outSize->
width = windowRect.right - windowRect.left;
15617 outSize->
height = windowRect.bottom - windowRect.top;
15624 FPL__CheckPlatformNoRet();
15625 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
15626 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15627 const fpl__Win32Api *wapi = &appState->winApi;
15628 RECT clientRect, windowRect;
15629 if (wapi->user.GetClientRect(windowState->windowHandle, &clientRect) &&
15630 wapi->user.GetWindowRect(windowState->windowHandle, &windowRect)) {
15631 int borderWidth = (windowRect.right - windowRect.left) - (clientRect.right - clientRect.left);
15632 int borderHeight = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
15633 int newWidth = width + borderWidth;
15634 int newHeight = height + borderHeight;
15635 wapi->user.SetWindowPos(windowState->windowHandle,
fpl_null, 0, 0, newWidth, newHeight, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
15640 FPL__CheckPlatform(
false);
15641 const fpl__PlatformAppState *appState = fpl__global__AppState;
15642 bool result = appState->currentSettings.window.isResizable != 0;
15647 FPL__CheckPlatformNoRet();
15648 fpl__PlatformAppState *appState = fpl__global__AppState;
15649 const fpl__Win32WindowState *windowState = &appState->window.win32;
15650 if (!appState->currentSettings.window.isFullscreen && appState->currentSettings.window.isDecorated) {
15651 DWORD style = fpl__win32_GetWindowLong(windowState->windowHandle, GWL_STYLE);
15652 DWORD exStyle = fpl__win32_GetWindowLong(windowState->windowHandle, GWL_EXSTYLE);
15654 style |= (WS_MAXIMIZEBOX | WS_THICKFRAME);
15656 style &= ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
15658 fpl__win32_SetWindowLong(windowState->windowHandle, GWL_STYLE, style);
15659 appState->currentSettings.window.isResizable = value;
15664 FPL__CheckPlatform(
false);
15665 const fpl__PlatformAppState *appState = fpl__global__AppState;
15666 bool result = appState->currentSettings.window.isDecorated != 0;
15671 FPL__CheckPlatformNoRet();
15672 fpl__PlatformAppState *appState = fpl__global__AppState;
15673 const fpl__Win32WindowState *windowState = &appState->window.win32;
15674 const fpl__Win32Api *wapi = &appState->win32.winApi;
15675 if (!appState->currentSettings.window.isFullscreen) {
15676 HWND windowHandle = windowState->windowHandle;
15677 DWORD style = fpl__win32_GetWindowLong(windowHandle, GWL_STYLE);
15678 DWORD exStyle = fpl__win32_GetWindowLong(windowHandle, GWL_EXSTYLE);
15680 style &= ~WS_POPUP;
15681 style |= WS_OVERLAPPEDWINDOW;
15682 if (!appState->currentSettings.window.isResizable) {
15683 style &= ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
15686 style &= ~WS_OVERLAPPEDWINDOW;
15689 fpl__win32_SetWindowLong(windowHandle, GWL_STYLE, style);
15690 wapi->user.SetWindowPos(windowHandle,
fpl_null, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
15691 appState->currentSettings.window.isDecorated = value;
15696 FPL__CheckPlatform(
false);
15697 const fpl__PlatformAppState *appState = fpl__global__AppState;
15698 bool result = appState->currentSettings.window.isFloating != 0;
15703 FPL__CheckPlatformNoRet();
15704 fpl__PlatformAppState *appState = fpl__global__AppState;
15705 const fpl__Win32WindowState *windowState = &appState->window.win32;
15706 const fpl__Win32Api *wapi = &appState->win32.winApi;
15707 if (!appState->currentSettings.window.isFullscreen) {
15709 wapi->user.SetWindowPos(windowState->windowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
15711 wapi->user.SetWindowPos(windowState->windowHandle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
15713 appState->currentSettings.window.isFloating = value;
15718 FPL__CheckPlatform(
false);
15719 fpl__PlatformAppState *appState = fpl__global__AppState;
15720 bool result = appState->currentSettings.window.isFullscreen != 0;
15726 bool result = fpl__Win32SetWindowFullscreen(value, INT32_MAX, INT32_MAX, fullscreenWidth, fullscreenHeight, refreshRate,
true);
15731 bool result = fpl__Win32SetWindowFullscreen(value, x, y, width, height, 0,
false);
15736 bool result = fpl__Win32SetWindowFullscreen(
true, INT32_MAX, INT32_MAX, 0, 0, 0,
false);
15741 bool result = fpl__Win32SetWindowFullscreen(
false, 0, 0, 0, 0, 0,
false);
15746 FPL__CheckArgumentNull(outPos,
false);
15747 FPL__CheckPlatform(
false);
15748 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
15749 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15750 const fpl__Win32Api *wapi = &appState->winApi;
15751 bool result =
false;
15753 placement.length =
sizeof(WINDOWPLACEMENT);
15754 if (wapi->user.GetWindowPlacement(windowState->windowHandle, &placement) == TRUE) {
15755 switch (placement.showCmd) {
15758 outPos->
left = placement.ptMaxPosition.x;
15759 outPos->
top = placement.ptMaxPosition.y;
15763 outPos->
left = placement.ptMinPosition.x;
15764 outPos->
top = placement.ptMinPosition.y;
15768 outPos->
left = placement.rcNormalPosition.left;
15769 outPos->
top = placement.rcNormalPosition.top;
15778 FPL__CheckPlatformNoRet();
15779 fpl__PlatformAppState *appState = fpl__global__AppState;
15780 const fpl__Win32AppState *win32AppState = &fpl__global__AppState->win32;
15781 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15782 const fpl__Win32Api *wapi = &win32AppState->winApi;
15783 HWND handle = windowState->windowHandle;
15787 wapi->user.SetWindowTextW(handle, titleWide);
15791 FPL__CheckPlatformNoRet();
15792 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
15793 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15794 const fpl__Win32Api *wapi = &appState->winApi;
15796 placement.length =
sizeof(WINDOWPLACEMENT);
15798 if (wapi->user.GetWindowPlacement(windowState->windowHandle, &placement) &&
15799 wapi->user.GetWindowRect(windowState->windowHandle, &windowRect)) {
15800 switch (placement.showCmd) {
15804 placement.rcNormalPosition.left = left;
15805 placement.rcNormalPosition.top = top;
15806 placement.rcNormalPosition.right = placement.rcNormalPosition.left + (windowRect.right - windowRect.left);
15807 placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + (windowRect.bottom - windowRect.top);
15808 wapi->user.SetWindowPlacement(windowState->windowHandle, &placement);
15816 const fpl__PlatformAppState *appState = fpl__global__AppState;
15817 const fpl__Win32AppState *win32AppState = &appState->win32;
15818 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15819 const fpl__Win32Api *wapi = &win32AppState->winApi;
15820 HWND windowHandle = windowState->windowHandle;
15822 if (appState->currentSettings.window.isFullscreen) {
15825 bool isMaximized = !!wapi->user.IsZoomed(windowHandle);
15826 bool isMinimized = !!wapi->user.IsIconic(windowHandle);
15829 }
else if (isMaximized) {
15839 FPL__CheckPlatform(
false);
15840 const fpl__PlatformAppState *appState = fpl__global__AppState;
15841 const fpl__Win32AppState *win32AppState = &appState->win32;
15842 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15843 const fpl__Win32Api *wapi = &win32AppState->winApi;
15844 HWND windowHandle = windowState->windowHandle;
15845 bool result =
false;
15846 switch (newState) {
15849 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
15855 if (!appState->currentSettings.window.isFullscreen && appState->currentSettings.window.isResizable) {
15856 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
15863 wapi->user.SendMessageW(windowHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
15869 if (!appState->currentSettings.window.isFullscreen)
15870 result = fpl__Win32SetWindowFullscreen(
true, INT32_MAX, INT32_MAX, 0, 0, 0,
false);
15883 FPL__CheckPlatformNoRet();
15884 fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15885 windowState->isCursorActive = value;
15888fpl_internal bool fpl__Win32ProcessNextEvent(
const fpl__Win32Api *wapi, fpl__PlatformAppState *appState, fpl__Win32WindowState *windowState) {
15889 bool result =
false;
15890 if (windowState->windowHandle != 0) {
15892 if (wapi->user.PeekMessageW(&msg, windowState->windowHandle, 0, 0, PM_REMOVE) == TRUE) {
15893 fpl__Win32HandleMessage(wapi, appState, windowState, &msg);
15901 FPL__CheckPlatform(
false);
15902 fpl__PlatformAppState *appState = fpl__global__AppState;
15903 fpl__Win32AppState *win32AppState = &appState->win32;
15904 fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15905 const fpl__Win32InitState *win32InitState = &fpl__global__InitState.win32;
15906 const fpl__Win32Api *wapi = &win32AppState->winApi;
15909 if (fpl__PollInternalEvent(ev)) {
15914 if (!fpl__Win32ProcessNextEvent(wapi, appState, windowState)) {
15919 if (fpl__PollInternalEvent(ev)) {
15928 FPL__CheckPlatformNoRet();
15929 fpl__PlatformAppState *appState = fpl__global__AppState;
15930 fpl__Win32AppState *win32AppState = &appState->win32;
15931 fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15932 const fpl__Win32InitState *win32InitState = &fpl__global__InitState.win32;
15933 const fpl__Win32Api *wapi = &win32AppState->winApi;
15934 if (windowState->windowHandle != 0) {
15935 if (windowState->mainFiber !=
fpl_null && windowState->messageFiber !=
fpl_null) {
15936 SwitchToFiber(windowState->messageFiber);
15939 while (wapi->user.PeekMessageW(&msg, windowState->windowHandle, 0, 0, PM_REMOVE)) {
15940 fpl__Win32HandleMessage(wapi, appState, windowState, &msg);
15944 fpl__ClearInternalEvents();
15948 FPL__CheckPlatform(
false);
15949 fpl__PlatformAppState *appState = fpl__global__AppState;
15950 fpl__Win32AppState *win32AppState = &appState->win32;
15951 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15952 const fpl__Win32InitState *win32InitState = &fpl__global__InitState.win32;
15953 const fpl__Win32Api *wapi = &win32AppState->winApi;
15954 fpl__ClearInternalEvents();
15956 fpl__Win32UpdateGameControllers(&appState->currentSettings, win32InitState, &win32AppState->xinput);
15958 bool result = appState->window.isRunning != 0;
15963 FPL__CheckPlatform(
false);
15964 bool result = fpl__global__AppState->window.isRunning != 0;
15969 FPL__CheckPlatformNoRet();
15970 fpl__PlatformAppState *appState = fpl__global__AppState;
15971 const fpl__Win32AppState *win32AppState = &appState->win32;
15972 if (appState->window.isRunning) {
15973 appState->window.isRunning =
false;
15974 const fpl__Win32Api *wapi = &win32AppState->winApi;
15975 wapi->user.PostQuitMessage(0);
15980 FPL__CheckPlatform(
false);
15981 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
15982 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
15983 const fpl__Win32Api *wapi = &appState->winApi;
15984 bool result =
false;
15985 if (wapi->user.OpenClipboard(windowState->windowHandle)) {
15986 if (wapi->user.IsClipboardFormatAvailable(CF_UNICODETEXT)) {
15987 HGLOBAL dataHandle = wapi->user.GetClipboardData(CF_UNICODETEXT);
15989 const wchar_t *stringValue = (
const wchar_t *)GlobalLock(dataHandle);
15991 GlobalUnlock(dataHandle);
15995 wapi->user.CloseClipboard();
16001 FPL__CheckPlatform(
false);
16002 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16003 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16004 const fpl__Win32Api *wapi = &appState->winApi;
16005 bool result =
false;
16006 if (wapi->user.OpenClipboard(windowState->windowHandle)) {
16008 const size_t bufferLen = textLen + 1;
16009 HGLOBAL handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)bufferLen *
sizeof(
wchar_t));
16011 wchar_t *target = (
wchar_t *)GlobalLock(handle);
16013 GlobalUnlock(handle);
16014 wapi->user.EmptyClipboard();
16015 wapi->user.SetClipboardData(CF_UNICODETEXT, handle);
16018 wapi->user.CloseClipboard();
16024 FPL__CheckArgumentNull(outState,
false);
16025 FPL__CheckPlatform(
false);
16026 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16027 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16028 const fpl__Win32Api *wapi = &appState->winApi;
16030 outState->
modifiers = fpl__Win32GetKeyboardModifiers(wapi);
16031 for (uint32_t keyCode = 0; keyCode < 256; ++keyCode) {
16032 int k = wapi->user.MapVirtualKeyW(MAPVK_VSC_TO_VK, keyCode);
16036 bool down = fpl__Win32IsKeyDown(wapi, k);
16037 fplKey key = fpl__GetMappedKey(&fpl__global__AppState->window, keyCode);
16045 FPL__CheckArgumentNull(outStates,
false);
16046 FPL__CheckPlatform(
false);
16047 fpl__PlatformAppState *platformAppState = fpl__global__AppState;
16049 fpl__Win32AppState *appState = &platformAppState->win32;
16050 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16051 const fpl__Win32Api *wapi = &appState->winApi;
16052 fpl__Win32XInputState *xinputState = &appState->xinput;
16054 if (xinputState->xinputApi.XInputGetState !=
fpl_null) {
16056 QueryPerformanceCounter(&xinputState->lastDeviceSearchTime);
16059 for (DWORD controllerIndex = 0; controllerIndex < XUSER_MAX_COUNT; ++controllerIndex) {
16061 if (xinputState->xinputApi.XInputGetState(controllerIndex, &controllerState) == ERROR_SUCCESS) {
16062 if (!xinputState->isConnected[controllerIndex]) {
16063 xinputState->isConnected[controllerIndex] =
true;
16064 fplStringFormat(xinputState->deviceNames[controllerIndex],
fplArrayCount(xinputState->deviceNames[controllerIndex]),
"XInput-Device [%d]", controllerIndex);
16066 const XINPUT_GAMEPAD *newPadState = &controllerState.Gamepad;
16068 fpl__Win32XInputGamepadToGamepadState(newPadState, targetPadState);
16069 targetPadState->
deviceName = xinputState->deviceNames[controllerIndex];
16071 if (xinputState->isConnected[controllerIndex]) {
16072 xinputState->isConnected[controllerIndex] =
false;
16083 FPL__CheckArgumentNull(outX,
false);
16084 FPL__CheckArgumentNull(outY,
false);
16085 FPL__CheckPlatform(
false);
16086 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16087 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16088 const fpl__Win32Api *wapi = &appState->winApi;
16090 if (wapi->user.GetCursorPos(&p) == TRUE) {
16092 HMONITOR monitor = wapi->user.MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST);
16095 info.cbSize =
sizeof(info);
16096 if (wapi->user.GetMonitorInfoW(monitor, (LPMONITORINFO)&info) != 0) {
16097 *outX = p.x - info.rcMonitor.left;
16098 *outY = p.y - info.rcMonitor.top;
16112 FPL__CheckArgumentNull(outState,
false);
16113 FPL__CheckPlatform(
false);
16114 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16115 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16116 const fpl__Win32Api *wapi = &appState->winApi;
16118 if ((wapi->user.GetCursorPos(&p) == TRUE) && (wapi->user.ScreenToClient(windowState->windowHandle, &p))) {
16123 bool leftDown = fpl__Win32IsKeyDown(wapi, VK_LBUTTON);
16124 bool rightDown = fpl__Win32IsKeyDown(wapi, VK_RBUTTON);
16125 bool middleDown = fpl__Win32IsKeyDown(wapi, VK_MBUTTON);
16135fpl_internal BOOL WINAPI fpl__Win32MonitorCountEnumProc(HMONITOR monitorHandle, HDC hdc, LPRECT rect, LPARAM userData) {
16136 size_t *count = (
size_t *)(uintptr_t)userData;
16137 *count = *count + 1;
16142 FPL__CheckPlatform(0);
16143 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16144 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16145 const fpl__Win32Api *wapi = &appState->winApi;
16147 LPARAM param = (LPARAM)&result;
16148 wapi->user.EnumDisplayMonitors(
fpl_null,
fpl_null, fpl__Win32MonitorCountEnumProc, param);
16154 size_t idLen = lstrlenW(info->szDevice);
16158 outInfo->
virtualSize.
width = info->rcMonitor.right - info->rcMonitor.left;
16160 outInfo->
physicalSize.
width = (info->rcMonitor.right > info->rcMonitor.left) ? (info->rcMonitor.right - info->rcMonitor.left) : (info->rcMonitor.left - info->rcMonitor.right);
16161 outInfo->
physicalSize.
height = (info->rcMonitor.bottom > info->rcMonitor.top) ? (info->rcMonitor.bottom - info->rcMonitor.top) : (info->rcMonitor.top - info->rcMonitor.bottom);
16162 outInfo->
isPrimary = (info->dwFlags & MONITORINFOF_PRIMARY) ? 1 : 0;
16165typedef struct fpl__Win32DisplayEnumState {
16166 fplDisplayInfo *baseInfo;
16167 const fpl__Win32Api *wapi;
16170} fpl__Win32DisplayEnumState;
16172fpl_internal BOOL WINAPI fpl__Win32MonitorInfoEnumProc(HMONITOR monitorHandle, HDC hdc, LPRECT rect, LPARAM userData) {
16173 fpl__Win32DisplayEnumState *enumState = (fpl__Win32DisplayEnumState *)(uintptr_t)userData;
16174 const fpl__Win32Api *wapi = enumState->wapi;
16175 if (enumState->count < enumState->maxCount) {
16176 fplDisplayInfo *targetInfo = enumState->baseInfo + enumState->count;
16179 info.cbSize =
sizeof(info);
16180 if (wapi->user.GetMonitorInfoW(monitorHandle, (LPMONITORINFO)&info) != 0) {
16181 fpl__Win32FillDisplayInfo(&info, targetInfo);
16183 ++enumState->count;
16184 BOOL result = enumState->count < enumState->maxCount;
16192 FPL__CheckArgumentNull(displays, 0);
16193 FPL__CheckArgumentZero(maxDisplayCount, 0);
16194 FPL__CheckPlatform(0);
16195 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16196 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16197 const fpl__Win32Api *wapi = &appState->winApi;
16198 fpl__Win32DisplayEnumState enumState =
fplZeroInit;
16199 enumState.baseInfo = displays;
16200 enumState.maxCount = maxDisplayCount;
16201 enumState.wapi = wapi;
16202 LPARAM param = (LPARAM)&enumState;
16203 wapi->user.EnumDisplayMonitors(
fpl_null,
fpl_null, fpl__Win32MonitorInfoEnumProc, param);
16204 return(enumState.count);
16207fpl_internal BOOL WINAPI fpl__Win32PrimaryMonitorEnumProc(HMONITOR monitorHandle, HDC hdc, LPRECT rect, LPARAM userData) {
16208 fpl__Win32DisplayEnumState *enumState = (fpl__Win32DisplayEnumState *)(uintptr_t)userData;
16209 const fpl__Win32Api *wapi = enumState->wapi;
16211 info.cbSize =
sizeof(info);
16212 if (wapi->user.GetMonitorInfoW(monitorHandle, (LPMONITORINFO)&info) != 0) {
16213 if (info.dwFlags & MONITORINFOF_PRIMARY) {
16215 fpl__Win32FillDisplayInfo(&info, enumState->baseInfo);
16216 enumState->count = 1;
16224 FPL__CheckArgumentNull(display,
false);
16225 FPL__CheckPlatform(
false);
16226 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16227 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16228 const fpl__Win32Api *wapi = &appState->winApi;
16229 fpl__Win32DisplayEnumState enumState =
fplZeroInit;
16230 enumState.baseInfo = display;
16231 enumState.maxCount = 1;
16232 enumState.wapi = wapi;
16233 LPARAM param = (LPARAM)&enumState;
16234 wapi->user.EnumDisplayMonitors(
fpl_null,
fpl_null, fpl__Win32PrimaryMonitorEnumProc, param);
16235 bool result = (enumState.count == 1);
16240 FPL__CheckArgumentNull(outDisplay,
false);
16241 FPL__CheckPlatform(
false);
16242 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16243 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16244 const fpl__Win32Api *wapi = &appState->winApi;
16245 HMONITOR foundMonitor = wapi->user.MonitorFromWindow(windowState->windowHandle, MONITOR_DEFAULTTONULL);
16246 bool result =
false;
16249 info.cbSize =
sizeof(info);
16250 if (wapi->user.GetMonitorInfoW(foundMonitor, (LPMONITORINFO)&info) != 0) {
16252 fpl__Win32FillDisplayInfo(&info, outDisplay);
16260 FPL__CheckArgumentNull(outDisplay,
false);
16261 FPL__CheckPlatform(
false);
16262 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16263 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16264 const fpl__Win32Api *wapi = &appState->winApi;
16268 bool result =
false;
16269 HMONITOR foundMonitor = wapi->user.MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
16272 info.cbSize =
sizeof(info);
16273 if (wapi->user.GetMonitorInfoW(foundMonitor, (LPMONITORINFO)&info) != 0) {
16275 fpl__Win32FillDisplayInfo(&info, outDisplay);
16283 FPL__CheckArgumentNull(
id, 0);
16284 FPL__CheckPlatform(0);
16285 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16286 const fpl__Win32WindowState *windowState = &fpl__global__AppState->window.win32;
16287 const fpl__Win32Api *wapi = &appState->winApi;
16288 wchar_t deviceName[CCHDEVICENAME + 1];
16292 while (wapi->user.EnumDisplaySettingsW(deviceName, (DWORD)result, &devMode)) {
16294 if (result == maxDisplayModeCount) {
16299 outMode->
width = devMode.dmPelsWidth;
16300 outMode->
height = devMode.dmPelsHeight;
16301 outMode->
colorBits = devMode.dmBitsPerPel;
16302 outMode->
refreshRate = devMode.dmDisplayFrequency;
16314 return LOCALE_SNAME;
16316 return LOCALE_SABBREVLANGNAME;
16322 LCTYPE lcType = fpl__Win32GetLocaleLCIDFromFormat(targetFormat);
16324 int r = GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, lcType, bufferWide,
fplArrayCount(bufferWide));
16331 LCTYPE lcType = fpl__Win32GetLocaleLCIDFromFormat(targetFormat);
16333 int r = GetLocaleInfoW(LOCALE_USER_DEFAULT, lcType, bufferWide,
fplArrayCount(bufferWide));
16340 FPL__CheckPlatform(
false);
16341 const fpl__Win32AppState *appState = &fpl__global__AppState->win32;
16342 const fpl__Win32Api *wapi = &appState->winApi;
16343 HKL kbLayout = wapi->user.GetKeyboardLayout(GetCurrentThreadId());
16344 LCID langId = (DWORD)(intptr_t)kbLayout & 0xFFFF;
16345 LCTYPE lcType = fpl__Win32GetLocaleLCIDFromFormat(targetFormat);
16347 int r = GetLocaleInfoW(langId, lcType, bufferWide,
fplArrayCount(bufferWide));
16358#if defined(FPL_SUBPLATFORM_POSIX)
16359fpl_internal void fpl__PosixReleaseSubplatform(fpl__PosixAppState *appState) {
16360 fpl__PThreadUnloadApi(&appState->pthreadApi);
16363fpl_internal bool fpl__PosixInitSubplatform(
const fplInitFlags initFlags,
const fplSettings *initSettings, fpl__PosixInitState *initState, fpl__PosixAppState *appState) {
16364 fpl__PThreadApi *pthreadApi = &appState->pthreadApi;
16366 if (!fpl__PThreadLoadApi(pthreadApi)) {
16367 FPL__ERROR(FPL__MODULE_POSIX,
"Failed initializing PThread API");
16371 pthread_t currentThreadHandle = pthreadApi->pthread_self();
16372 uint32_t mainThreadId = (uint32_t)currentThreadHandle;
16375 mainThread->
id = mainThreadId;
16382fpl_internal void fpl__InitWaitTimeSpec(
const uint32_t milliseconds,
struct timespec *outSpec) {
16383 time_t secs = milliseconds / 1000;
16384 uint64_t nanoSecs = (milliseconds - (secs * 1000)) * 1000000;
16385 if (nanoSecs >= 1000000000) {
16386 time_t addonSecs = (time_t)(nanoSecs / 1000000000);
16387 nanoSecs -= (addonSecs * 1000000000);
16390 clock_gettime(CLOCK_REALTIME, outSpec);
16391 outSpec->tv_sec += secs;
16392 outSpec->tv_nsec += nanoSecs;
16395void *fpl__PosixThreadProc(
void *data) {
16397 const fpl__PThreadApi *pthreadApi = &fpl__global__AppState->posix.pthreadApi;
16411 pthreadApi->pthread_exit(data);
16415fpl_internal bool fpl__PosixMutexLock(
const fpl__PThreadApi *pthreadApi, pthread_mutex_t *handle) {
16418 lockRes = pthreadApi->pthread_mutex_lock(handle);
16419 }
while (lockRes == EAGAIN);
16420 bool result = (lockRes == 0);
16424fpl_internal bool fpl__PosixMutexTryLock(
const fpl__PThreadApi *pthreadApi, pthread_mutex_t *handle) {
16427 lockRes = pthreadApi->pthread_mutex_trylock(handle);
16428 }
while (lockRes == EAGAIN);
16429 bool result = (lockRes == 0);
16433fpl_internal bool fpl__PosixMutexUnlock(
const fpl__PThreadApi *pthreadApi, pthread_mutex_t *handle) {
16436 unlockRes = pthreadApi->pthread_mutex_unlock(handle);
16437 }
while (unlockRes == EAGAIN);
16438 bool result = (unlockRes == 0);
16442fpl_internal int fpl__PosixMutexCreate(
const fpl__PThreadApi *pthreadApi, pthread_mutex_t *handle) {
16445 mutexRes = pthreadApi->pthread_mutex_init(handle,
fpl_null);
16446 }
while (mutexRes == EAGAIN);
16451 FPL__CheckArgumentNull(threads,
false);
16452 FPL__CheckArgumentMax(maxCount, FPL_MAX_THREAD_COUNT,
false);
16453 const size_t actualStride = stride > 0 ? stride :
sizeof(
fplThreadHandle *);
16454 for (uint32_t index = 0; index < maxCount; ++index) {
16457 FPL__ERROR(FPL__MODULE_THREADING,
"Thread for index '%d' are not allowed to be null", index);
16462 uint32_t completeCount = 0;
16463 bool isRunning[FPL_MAX_THREAD_COUNT];
16464 for (uint32_t index = 0; index < maxCount; ++index) {
16467 if (!isRunning[index]) {
16473 bool result =
false;
16474 while (completeCount < minCount) {
16475 for (uint32_t index = 0; index < maxCount; ++index) {
16477 if (isRunning[index]) {
16480 isRunning[index] =
false;
16482 if (completeCount >= minCount) {
16501#if defined(FPL_COMPILER_GCC) || defined(FPL_COMPILER_CLANG) || defined(__GNUC__)
16505 __sync_synchronize();
16508 __sync_synchronize();
16511 __sync_synchronize();
16515 __sync_synchronize();
16516 uint32_t result = __sync_lock_test_and_set(target, value);
16520 __sync_synchronize();
16521 uint64_t result = __sync_lock_test_and_set(target, value);
16525 __sync_synchronize();
16526 int32_t result = __sync_lock_test_and_set(target, value);
16530 __sync_synchronize();
16531 int64_t result = __sync_lock_test_and_set(target, value);
16537 uint32_t result = __sync_fetch_and_add(value, addend);
16542 uint64_t result = __sync_fetch_and_add(value, addend);
16547 int32_t result = __sync_fetch_and_add(value, addend);
16552 int64_t result = __sync_fetch_and_add(value, addend);
16558 uint32_t result = __sync_add_and_fetch(value, addend);
16563 int32_t result = __sync_add_and_fetch(value, addend);
16568 uint64_t result = __sync_add_and_fetch(value, addend);
16573 int64_t result = __sync_add_and_fetch(value, addend);
16579 uint32_t result = __sync_add_and_fetch(value, 1);
16584 uint64_t result = __sync_add_and_fetch(value, 1);
16589 int32_t result = __sync_add_and_fetch(value, 1);
16594 int64_t result = __sync_add_and_fetch(value, 1);
16600 uint32_t result = __sync_val_compare_and_swap(dest, comparand, exchange);
16605 uint64_t result = __sync_val_compare_and_swap(dest, comparand, exchange);
16610 int32_t result = __sync_val_compare_and_swap(dest, comparand, exchange);
16615 int64_t result = __sync_val_compare_and_swap(dest, comparand, exchange);
16621 bool result = __sync_bool_compare_and_swap(dest, comparand, exchange);
16626 bool result = __sync_bool_compare_and_swap(dest, comparand, exchange);
16631 bool result = __sync_bool_compare_and_swap(dest, comparand, exchange);
16636 bool result = __sync_bool_compare_and_swap(dest, comparand, exchange);
16641 uint32_t result = __sync_add_and_fetch(source, 0);
16645 uint64_t result = __sync_add_and_fetch(source, 0);
16649 int32_t result = __sync_add_and_fetch(source, 0);
16653 int64_t result = __sync_add_and_fetch(source, 0);
16658 __sync_synchronize();
16659 __sync_lock_test_and_set(dest, value);
16662 __sync_synchronize();
16663 __sync_lock_test_and_set(dest, value);
16666 __sync_synchronize();
16667 __sync_lock_test_and_set(dest, value);
16670 __sync_synchronize();
16671 __sync_lock_test_and_set(dest, value);
16674# error "This POSIX compiler/platform is not supported!"
16683 clock_gettime(CLOCK_MONOTONIC, &t);
16684 result.posix.seconds = (uint64_t)t.tv_sec;
16685 result.posix.nanoSeconds = (int64_t)t.tv_nsec;
16690 uint64_t deltaSeconds = finish.posix.seconds - start.posix.seconds;
16691 int64_t deltaNanos = finish.posix.nanoSeconds - start.posix.nanoSeconds;
16692 if (deltaNanos < 0) {
16694 deltaNanos += 1000000000L;
16711 FPL__CheckArgumentNull(thread,
false);
16712 FPL__CheckPlatform(
false);
16713 const fpl__PlatformAppState *appState = fpl__global__AppState;
16714 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
16717 if (pthreadApi->pthread_kill(threadHandle, 0) == 0) {
16718 pthreadApi->pthread_join(threadHandle,
fpl_null);
16729 FPL__CheckPlatform(0);
16730 const fpl__PlatformAppState *appState = fpl__global__AppState;
16731 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
16732 pthread_t currentThread = pthreadApi->pthread_self();
16733 uint32_t result = (uint32_t)currentThread;
16738 FPL__CheckArgumentNull(parameters,
fpl_null);
16740 const fpl__PlatformAppState *appState = fpl__global__AppState;
16741 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
16753 pthread_attr_t *attrPtr =
fpl_null;
16754 pthread_attr_t attr;
16755 if (pthreadApi->pthread_attr_init(&attr) == 0) {
16757 int scheduler = -1;
16759#if defined(SCHED_IDLE)
16760 if (pthreadApi->pthread_attr_setschedpolicy(&attr, SCHED_IDLE) == 0) {
16761 scheduler = SCHED_IDLE;
16765#if defined(SCHED_FIFO)
16766 if ((scheduler == -1) && (pthreadApi->pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0)) {
16767 scheduler = SCHED_FIFO;
16770#if defined(SCHED_RR)
16771 if ((scheduler == -1) && (pthreadApi->pthread_attr_setschedpolicy(&attr, SCHED_RR) == 0)) {
16772 scheduler = SCHED_RR;
16777 scheduler = sched_getscheduler(0);
16782 pthreadApi->pthread_attr_setstacksize(&attr, parameters->
stackSize);
16786 if (scheduler != -1) {
16787 struct sched_param sched;
16788 if (pthreadApi->pthread_attr_getschedparam(&attr, &sched) == 0) {
16792 int minPrio = sched_get_priority_min(scheduler);
16793 int maxPrio = sched_get_priority_max(scheduler);
16794 int range = maxPrio - minPrio;
16795 int step = range / maxThreadPrioCount;
16799 priority = minPrio;
16801 priority = maxPrio;
16804 priority = minPrio + threadPrioNumber * step;
16805 if (priority < minPrio) {
16806 priority = minPrio;
16807 }
else if (priority > maxPrio) {
16808 priority = maxPrio;
16812 sched.sched_priority = priority;
16813 pthreadApi->pthread_attr_setschedparam(&attr, &sched);
16824 threadRes = pthreadApi->pthread_create(&thread->
internalHandle.posixThread, attrPtr, fpl__PosixThreadProc, (
void *)thread);
16825 }
while (threadRes == EAGAIN);
16826 if (threadRes != 0) {
16827 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating thread, error code: %d", threadRes);
16829 if (threadRes == 0) {
16837 FPL__ERROR(FPL__MODULE_THREADING,
"All %d threads are in use, you cannot create until you free one", FPL_MAX_THREAD_COUNT);
16843 FPL__CheckArgumentNull(runFunc,
fpl_null);
16845 parameters.
runFunc = runFunc;
16853 const fpl__PlatformAppState *appState = fpl__global__AppState;
16854 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
16856 pthread_t curThread = pthreadApi->pthread_self();
16858 int currentSchedulerPolicy;
16859 struct sched_param params;
16860 if (pthreadApi->pthread_getschedparam(curThread, ¤tSchedulerPolicy, ¶ms) != 0) {
16861 FPL__ERROR(FPL__MODULE_THREADING,
"Failed getting scheduler parameters for pthread '%d'", curThread);
16868 int minPrio = sched_get_priority_min(currentSchedulerPolicy);
16869 int maxPrio = sched_get_priority_max(currentSchedulerPolicy);
16870 int range = maxPrio - minPrio;
16871 int step = range / maxThreadPrioCount;
16873 int currentPrio = params.sched_priority;
16876 if (minPrio == maxPrio || currentPrio == minPrio) {
16878 }
else if (currentPrio == maxPrio) {
16881 int index = (currentPrio - minPrio) / step;
16882 fplAssert(index >= 0 && index < maxThreadPrioCount);
16891 FPL__CheckPlatform(
false);
16892 const fpl__PlatformAppState *appState = fpl__global__AppState;
16893 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
16895 pthread_t curThread = pthreadApi->pthread_self();
16897 int currentSchedulerPolicy;
16898 struct sched_param params;
16899 if (pthreadApi->pthread_getschedparam(curThread, ¤tSchedulerPolicy, ¶ms) != 0) {
16900 FPL__ERROR(FPL__MODULE_THREADING,
"Failed getting scheduler parameters for pthread '%d'", curThread);
16905 int newSchedulerPolicies[3];
16906 int schedulerPolicyCount = 0;
16907 switch (newPriority) {
16911 newSchedulerPolicies[schedulerPolicyCount++] = currentSchedulerPolicy;
16914#if defined(SCHED_RR)
16915 newSchedulerPolicies[schedulerPolicyCount++] = SCHED_RR;
16917 newSchedulerPolicies[schedulerPolicyCount++] = currentSchedulerPolicy;
16920#if defined(SCHED_FIFO)
16921 newSchedulerPolicies[schedulerPolicyCount++] = SCHED_FIFO;
16923#if defined(SCHED_RR)
16924 newSchedulerPolicies[schedulerPolicyCount++] = SCHED_RR;
16926 newSchedulerPolicies[schedulerPolicyCount++] = currentSchedulerPolicy;
16938 for (
int i = 0; i < schedulerPolicyCount; ++i) {
16939 int policy = newSchedulerPolicies[i];
16940 int minPrio = sched_get_priority_min(policy);
16941 int maxPrio = sched_get_priority_max(policy);
16942 int range = maxPrio - minPrio;
16943 int step = range / maxThreadPrioCount;
16947 priority = minPrio;
16949 priority = maxPrio;
16951 priority = minPrio + threadPrioNumber * step;
16952 if (priority < minPrio) {
16953 priority = minPrio;
16954 }
else if (priority > maxPrio) {
16955 priority = maxPrio;
16958 params.sched_priority = priority;
16959 if (pthreadApi->pthread_setschedparam(curThread, policy, ¶ms) == 0) {
16962 FPL__WARNING(FPL__MODULE_THREADING,
"Failed to set thread priority '%d' with policy '%d'", priority, policy);
16970 FPL__CheckPlatform(
false);
16971 const fpl__PlatformAppState *appState = fpl__global__AppState;
16972 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
16973 bool result =
false;
16981 fpl__InitWaitTimeSpec(timeout, &t);
16982 joinRes = pthreadApi->pthread_timedjoin_np(threadHandle,
fpl_null, &t);
16984 joinRes = pthreadApi->pthread_join(threadHandle,
fpl_null);
16987 result = (joinRes == 0);
16993 bool result = fpl__PosixThreadWaitForMultiple(threads, count, count, stride, timeout);
16998 bool result = fpl__PosixThreadWaitForMultiple(threads, 1, count, stride, timeout);
17003 FPL__CheckPlatform(
false);
17004 const fpl__PlatformAppState *appState = fpl__global__AppState;
17005 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17007 if (pthreadApi->pthread_yield !=
fpl_null) {
17008 result = (pthreadApi->pthread_yield() == 0);
17010 result = (sched_yield() == 0);
17018 if (milliseconds > 1000) {
17019 s = milliseconds / 1000;
17020 ms = milliseconds % 1000;
17025 struct timespec input, output;
17027 input.tv_nsec = ms * 1000000;
17028 nanosleep(&input, &output);
17032 FPL__CheckArgumentNull(mutex,
false);
17034 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex '%p' is already initialized", mutex);
17037 FPL__CheckPlatform(
false);
17038 const fpl__PlatformAppState *appState = fpl__global__AppState;
17039 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17040 fplAssert(
sizeof(fpl__POSIXMutexHandle) >=
sizeof(pthread_mutex_t));
17041 pthread_mutex_t mutexHandle;
17042 int mutexRes = fpl__PosixMutexCreate(pthreadApi, &mutexHandle);
17043 if (mutexRes != 0) {
17044 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating POSIX condition");
17054 FPL__CheckPlatformNoRet();
17055 const fpl__PlatformAppState *appState = fpl__global__AppState;
17056 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17058 pthread_mutex_t *handle = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
17059 pthreadApi->pthread_mutex_destroy(handle);
17065 FPL__CheckArgumentNull(mutex,
false);
17066 FPL__CheckPlatform(
false);
17067 const fpl__PlatformAppState *appState = fpl__global__AppState;
17068 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17069 bool result =
false;
17071 pthread_mutex_t *handle = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
17072 result = fpl__PosixMutexLock(pthreadApi, handle);
17078 FPL__CheckArgumentNull(mutex,
false);
17079 FPL__CheckPlatform(
false);
17080 const fpl__PlatformAppState *appState = fpl__global__AppState;
17081 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17082 bool result =
false;
17084 pthread_mutex_t *handle = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
17085 result = fpl__PosixMutexTryLock(pthreadApi, handle);
17091 FPL__CheckArgumentNull(mutex,
false);
17092 FPL__CheckPlatform(
false);
17093 const fpl__PlatformAppState *appState = fpl__global__AppState;
17094 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17095 bool result =
false;
17097 pthread_mutex_t *handle = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
17098 result = fpl__PosixMutexUnlock(pthreadApi, handle);
17104 FPL__CheckArgumentNull(condition,
false);
17105 FPL__CheckPlatform(
false);
17106 const fpl__PlatformAppState *appState = fpl__global__AppState;
17107 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17108 fplAssert(
sizeof(fpl__POSIXConditionVariable) >=
sizeof(pthread_cond_t));
17109 pthread_cond_t handle = PTHREAD_COND_INITIALIZER;
17112 condRes = pthreadApi->pthread_cond_init(&handle,
fpl_null);
17113 }
while (condRes == EAGAIN);
17114 if (condRes == 0) {
17123 FPL__CheckPlatformNoRet();
17124 const fpl__PlatformAppState *appState = fpl__global__AppState;
17125 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17127 pthread_cond_t *handle = (pthread_cond_t *)&condition->
internalHandle.posixCondition;
17128 pthreadApi->pthread_cond_destroy(handle);
17134 FPL__CheckArgumentNull(condition,
false);
17135 FPL__CheckArgumentNull(mutex,
false);
17137 FPL__ERROR(FPL__MODULE_THREADING,
"Condition is not valid");
17141 FPL__ERROR(FPL__MODULE_THREADING,
"Mutex is not valid");
17144 FPL__CheckPlatform(
false);
17145 const fpl__PlatformAppState *appState = fpl__global__AppState;
17146 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17147 pthread_cond_t *cond = (pthread_cond_t *)&condition->
internalHandle.posixCondition;
17148 pthread_mutex_t *mut = (pthread_mutex_t *)&mutex->
internalHandle.posixMutex;
17151 result = pthreadApi->pthread_cond_wait(cond, mut) == 0;
17154 fpl__InitWaitTimeSpec(timeout, &t);
17155 result = pthreadApi->pthread_cond_timedwait(cond, mut, &t) == 0;
17161 FPL__CheckArgumentNull(condition,
false);
17163 FPL__ERROR(FPL__MODULE_THREADING,
"Condition is not valid");
17166 FPL__CheckPlatform(
false);
17167 const fpl__PlatformAppState *appState = fpl__global__AppState;
17168 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17169 pthread_cond_t *handle = (pthread_cond_t *)&condition->
internalHandle.posixCondition;
17170 bool result = pthreadApi->pthread_cond_signal(handle) == 0;
17175 FPL__CheckArgumentNull(condition,
false);
17177 FPL__ERROR(FPL__MODULE_THREADING,
"Condition is not valid");
17180 FPL__CheckPlatform(
false);
17181 const fpl__PlatformAppState *appState = fpl__global__AppState;
17182 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17183 pthread_cond_t *handle = (pthread_cond_t *)&condition->
internalHandle.posixCondition;
17184 bool result = pthreadApi->pthread_cond_broadcast(handle) == 0;
17189 FPL__CheckArgumentNull(semaphore,
false);
17190 FPL__CheckArgumentMax(initialValue, UINT32_MAX,
false);
17192 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is already initialized", semaphore);
17195 FPL__CheckPlatform(
false);
17197 const fpl__PlatformAppState *appState = fpl__global__AppState;
17198 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17200 int res = pthreadApi->sem_init(&handle, 0, (
int)initialValue);
17202 FPL__ERROR(FPL__MODULE_THREADING,
"Failed creating semaphore");
17212 FPL__CheckPlatformNoRet();
17213 const fpl__PlatformAppState *appState = fpl__global__AppState;
17214 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17217 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
17218 pthreadApi->sem_destroy(handle);
17225 FPL__CheckArgumentNull(semaphore,
false);
17227 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
17230 FPL__CheckPlatform(
false);
17231 const fpl__PlatformAppState *appState = fpl__global__AppState;
17232 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17233 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
17236 res = pthreadApi->sem_wait(handle);
17239 fpl__InitWaitTimeSpec(timeout, &t);
17240 res = pthreadApi->sem_timedwait(handle, &t);
17242 bool result = res == 0;
17247 FPL__CheckArgumentNull(semaphore,
false);
17249 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
17252 FPL__CheckPlatform(
false);
17253 const fpl__PlatformAppState *appState = fpl__global__AppState;
17254 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17255 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
17256 int res = pthreadApi->sem_trywait(handle);
17257 bool result = (res == 0);
17262 FPL__CheckArgumentNull(semaphore,
false);
17264 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
17267 FPL__CheckPlatform(0);
17268 const fpl__PlatformAppState *appState = fpl__global__AppState;
17269 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17270 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
17272 int res = pthreadApi->sem_getvalue(handle, &value);
17276 return((int32_t)value);
17280 FPL__CheckArgumentNull(semaphore,
false);
17282 FPL__ERROR(FPL__MODULE_THREADING,
"Semaphore '%p' is not valid", semaphore);
17285 FPL__CheckPlatform(0);
17286 const fpl__PlatformAppState *appState = fpl__global__AppState;
17287 const fpl__PThreadApi *pthreadApi = &appState->posix.pthreadApi;
17288 sem_t *handle = (sem_t *)&semaphore->
internalHandle.posixHandle;
17289 int res = pthreadApi->sem_post(handle);
17290 bool result = (res == 0);
17298 bool result =
false;
17300 void *p = dlopen(libraryFilePath, FPL__POSIX_DL_LOADTYPE);
17315 result = dlsym(p, name);
17332 FPL__CheckArgumentZero(size,
fpl_null);
17335 size_t newSize =
sizeof(size_t) + FPL__MEMORY_PADDING + size;
17336 void *basePtr = mmap(
fpl_null, newSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
17338 *(
size_t *)basePtr = newSize;
17340 void *result = (uint8_t *)basePtr +
sizeof(
size_t) + FPL__MEMORY_PADDING;
17345 FPL__CheckArgumentNullNoRet(ptr);
17347 void *basePtr = (
void *)((uint8_t *)ptr - (FPL__MEMORY_PADDING +
sizeof(
size_t)));
17348 size_t storedSize = *(
size_t *)basePtr;
17349 munmap(basePtr, storedSize);
17356 FPL__CheckArgumentNull(outHandle,
false);
17358 int posixFileHandle;
17360 posixFileHandle = open(filePath, O_RDONLY);
17361 }
while (posixFileHandle == -1 && errno == EINTR);
17362 if (posixFileHandle != -1) {
17373 FPL__CheckArgumentNull(outHandle,
false);
17375 int posixFileHandle;
17377 posixFileHandle = open(filePath, O_WRONLY | O_CREAT | O_TRUNC, 0666);
17378 }
while (posixFileHandle == -1 && errno == EINTR);
17379 if (posixFileHandle != -1) {
17389 FPL__CheckArgumentNull(fileHandle, 0);
17390 FPL__CheckArgumentZero(sourceSize, 0);
17391 FPL__CheckArgumentNull(sourceBuffer, 0);
17393 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for writing");
17396 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17399 res = write(posixFileHandle, sourceBuffer, sourceSize);
17400 }
while (res == -1 && errno == EINTR);
17403 result = (size_t)res;
17409 FPL__CheckArgumentNull(fileHandle, 0);
17410 FPL__CheckArgumentZero(sizeToRead, 0);
17411 FPL__CheckArgumentNull(targetBuffer, 0);
17413 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for reading");
17416 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17419 res = read(posixFileHandle, targetBuffer, sizeToRead);
17420 }
while (res == -1 && errno == EINTR);
17421 uint32_t result = 0;
17423 result = (uint32_t)res;
17429 FPL__CheckArgumentNull(fileHandle, 0);
17430 FPL__CheckArgumentZero(sizeToRead, 0);
17431 FPL__CheckArgumentNull(targetBuffer, 0);
17433 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for reading");
17436 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17437 uint64_t result = 0;
17438 uint64_t remainingSize = sizeToRead;
17439 uint64_t bufferPos = 0;
17440 const uint64_t MaxValue = (uint64_t)(
size_t)-1;
17441 while (remainingSize > 0) {
17442 uint8_t *target = (uint8_t *)targetBuffer + bufferPos;
17443 size_t size =
fplMin(remainingSize, MaxValue);
17446 res = read(posixFileHandle, target, size);
17447 }
while (res == -1 && errno == EINTR);
17453 remainingSize -= res;
17460 FPL__CheckArgumentNull(fileHandle, 0);
17461 FPL__CheckArgumentZero(sourceSize, 0);
17462 FPL__CheckArgumentNull(sourceBuffer, 0);
17464 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for writing");
17467 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17470 res = write(posixFileHandle, sourceBuffer, sourceSize);
17471 }
while (res == -1 && errno == EINTR);
17472 uint32_t result = 0;
17474 result = (uint32_t)res;
17480 FPL__CheckArgumentNull(fileHandle, 0);
17481 FPL__CheckArgumentZero(sourceSize, 0);
17482 FPL__CheckArgumentNull(sourceBuffer, 0);
17484 FPL__ERROR(FPL__MODULE_FILES,
"File handle is not opened for writing");
17487 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17488 uint64_t result = 0;
17489 uint64_t remainingSize = sourceSize;
17490 uint64_t bufferPos = 0;
17491 const uint64_t MaxValue = (uint64_t)(
size_t)-1;
17492 while (remainingSize > 0) {
17493 uint8_t *source = (uint8_t *)sourceBuffer + bufferPos;
17494 size_t size =
fplMin(remainingSize, MaxValue);
17497 res = write(posixFileHandle, source, size);
17498 }
while (res == -1 && errno == EINTR);
17502 remainingSize -= res;
17509 FPL__CheckArgumentNull(fileHandle, 0);
17510 uint32_t result = 0;
17512 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17513 int whence = SEEK_SET;
17519 off_t r = lseek(posixFileHandle, position, whence);
17520 result = (uint32_t)r;
17526 FPL__CheckArgumentNull(fileHandle, 0);
17527 uint64_t result = 0;
17529 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17530 int whence = SEEK_SET;
17536 fpl__off64_t r = fpl__lseek64(posixFileHandle, position, whence);
17537 result = (uint64_t)r;
17543 FPL__CheckArgumentNull(fileHandle, 0);
17544 uint32_t result = 0;
17546 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17547 off_t res = lseek(posixFileHandle, 0, SEEK_CUR);
17549 result = (uint32_t)res;
17556 FPL__CheckArgumentNull(fileHandle, 0);
17557 uint64_t result = 0;
17559 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17560 fpl__off64_t r = fpl__lseek64(posixFileHandle, 0, SEEK_CUR);
17562 result = (uint64_t)r;
17569 FPL__CheckArgumentNull(fileHandle,
false);
17570 bool result =
false;
17572 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17573 result = fsync(posixFileHandle) == 0;
17580 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17581 close(posixFileHandle);
17587 uint32_t result = 0;
17589 int posixFileHandle;
17591 posixFileHandle = open(filePath, O_RDONLY);
17592 }
while (posixFileHandle == -1 && errno == EINTR);
17593 if (posixFileHandle != -1) {
17594 off_t res = lseek(posixFileHandle, 0, SEEK_END);
17596 result = (uint32_t)res;
17598 close(posixFileHandle);
17605 uint64_t result = 0;
17607 int posixFileHandle;
17609 posixFileHandle = open(filePath, O_RDONLY);
17610 }
while (posixFileHandle == -1 && errno == EINTR);
17611 if (posixFileHandle != -1) {
17612 fpl__off64_t r = fpl__lseek64(posixFileHandle, 0, SEEK_END);
17614 result = (uint64_t)r;
17616 close(posixFileHandle);
17623 uint32_t result = 0;
17625 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17626 off_t curPos = lseek(posixFileHandle, 0, SEEK_CUR);
17627 if (curPos != -1) {
17628 result = (uint32_t)lseek(posixFileHandle, 0, SEEK_END);
17629 lseek(posixFileHandle, curPos, SEEK_SET);
17636 uint64_t result = 0;
17638 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17639 fpl__off64_t curPos = fpl__lseek64(posixFileHandle, 0, SEEK_CUR);
17640 if (curPos != -1) {
17641 result = (uint64_t)fpl__lseek64(posixFileHandle, 0, SEEK_END);
17642 fpl__lseek64(posixFileHandle, curPos, SEEK_SET);
17648fpl_internal uint64_t fpl__PosixConvertTimeToUnixTimeStamp(
const time_t secs) {
17649 uint64_t result = (uint64_t)secs;
17654 FPL__CheckArgumentNull(outStamps,
false);
17655 bool result =
false;
17657 struct stat statBuf;
17658 if (stat(filePath, &statBuf) != -1) {
17659 outStamps->
creationTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_ctime);
17660 outStamps->
lastAccessTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_atime);
17661 outStamps->
lastModifyTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_mtime);
17669 FPL__CheckArgumentNull(fileHandle,
false);
17670 FPL__CheckArgumentNull(outStamps,
false);
17671 bool result =
false;
17673 int posixFileHandle = fileHandle->
internalHandle.posixFileHandle;
17674 struct stat statBuf;
17675 if (fstat(posixFileHandle, &statBuf) != -1) {
17676 outStamps->
creationTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_ctime);
17677 outStamps->
lastAccessTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_atime);
17678 outStamps->
lastModifyTime = fpl__PosixConvertTimeToUnixTimeStamp(statBuf.st_mtime);
17686 bool result =
false;
17688 result = access(filePath, F_OK) != -1;
17694 FPL__CheckArgumentNull(sourceFilePath,
false);
17695 FPL__CheckArgumentNull(targetFilePath,
false);
17696 if (access(sourceFilePath, F_OK) == -1) {
17697 FPL__ERROR(FPL__MODULE_FILES,
"Source file '%s' does not exits", sourceFilePath);
17700 if (!overwrite && access(sourceFilePath, F_OK) != -1) {
17701 FPL__ERROR(FPL__MODULE_FILES,
"Target file '%s' already exits", targetFilePath);
17704 int inputFileHandle;
17706 inputFileHandle = open(sourceFilePath, O_RDONLY);
17707 }
while (inputFileHandle == -1 && errno == EINTR);
17708 if (inputFileHandle == -1) {
17709 FPL__ERROR(FPL__MODULE_FILES,
"Failed open source file '%s', error code: %d", sourceFilePath, inputFileHandle);
17712 int outputFileHandle;
17714 outputFileHandle = open(targetFilePath, O_WRONLY | O_CREAT | O_TRUNC, 0666);
17715 }
while (outputFileHandle == -1 && errno == EINTR);
17716 if (outputFileHandle == -1) {
17717 close(inputFileHandle);
17718 FPL__ERROR(FPL__MODULE_FILES,
"Failed creating target file '%s', error code: %d", targetFilePath, inputFileHandle);
17721 uint8_t buffer[1024 * 10];
17725 readbytes = read(inputFileHandle, buffer,
fplArrayCount(buffer));
17726 }
while (readbytes == -1 && errno == EINTR);
17727 if (readbytes > 0) {
17728 ssize_t writtenBytes;
17730 writtenBytes = write(outputFileHandle, buffer, readbytes);
17731 }
while (writtenBytes == -1 && errno == EINTR);
17732 if (writtenBytes <= 0) {
17739 close(outputFileHandle);
17740 close(inputFileHandle);
17745 FPL__CheckArgumentNull(sourceFilePath,
false);
17746 FPL__CheckArgumentNull(targetFilePath,
false);
17747 bool result = rename(sourceFilePath, targetFilePath) == 0;
17752 FPL__CheckArgumentNull(filePath,
false);
17753 bool result = unlink(filePath) == 0;
17758 bool result =
false;
17761 result = (stat(path, &sb) == 0) && S_ISDIR(sb.st_mode);
17767 FPL__CheckArgumentNull(path,
false);
17768 bool result = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) == 0;
17772 FPL__CheckArgumentNull(path,
false);
17773 bool result = rmdir(path) == 0;
17789 if (stat(fullPath, &sb) == 0) {
17790 if (S_ISDIR(sb.st_mode)) {
17792 }
else if (S_ISREG(sb.st_mode)) {
17795 entry->
size = (size_t)sb.st_size;
17796 if (dp->d_name[0] ==
'.') {
17800 if (sb.st_mode & S_IRUSR) {
17803 if (sb.st_mode & S_IWUSR) {
17806 if (sb.st_mode & S_IXUSR) {
17809 if (sb.st_mode & S_IRGRP) {
17812 if (sb.st_mode & S_IWGRP) {
17815 if (sb.st_mode & S_IXGRP) {
17818 if (sb.st_mode & S_IROTH) {
17821 if (sb.st_mode & S_IWOTH) {
17824 if (sb.st_mode & S_IXOTH) {
17831 FPL__CheckArgumentNull(path,
false);
17832 FPL__CheckArgumentNull(entry,
false);
17833 DIR *dir = opendir(path);
17849 FPL__CheckArgumentNull(entry,
false);
17850 bool result =
false;
17853 struct dirent *dp = readdir(dirHandle);
17862 dp = readdir(dirHandle);
17865 closedir(dirHandle);
17868 fpl__PosixFillFileEntry(dp, entry);
17876 FPL__CheckArgumentNullNoRet(entry);
17879 closedir(dirHandle);
17888 uid_t uid = geteuid();
17889 struct passwd *pw = getpwuid(uid);
17892 if (nameLen > 0 && nameBuffer !=
fpl_null) {
17893 size_t requiredLen = nameLen + 1;
17894 FPL__CheckArgumentMin(maxNameBufferLen, requiredLen, 0);
17903 size_t result = sysconf(_SC_NPROCESSORS_ONLN);
17908 const char *procNames[] = {
17910 "/proc/curproc/exe",
17911 "/proc/curproc/file",
17916 const char *procName = procNames[i];
17920 char *lastP = buf + (len - 1);
17924 len = (lastP - buf) + 1;
17931 size_t requiredLen = len + 1;
17932 FPL__CheckArgumentMin(maxDestLen, requiredLen, 0);
17943 const char *homeDir = getenv(
"HOME");
17945 int userId = getuid();
17946 struct passwd *userPwd = getpwuid(userId);
17947 homeDir = userPwd->pw_dir;
17951 size_t requiredLen = result + 1;
17952 FPL__CheckArgumentMin(maxDestLen, requiredLen, 0);
17961 struct utsname nameInfos;
17962 if (uname(&nameInfos) == 0) {
17963 const char *machineName = nameInfos.machine;
17972 const char *m = machineName + 4;
17974 while (*p >=
'0' && *p <=
'9') {
17979 if (version == 6) {
17981 }
else if (version >= 7) {
17991 bool result =
false;
17992 struct utsname nameInfos;
17993 if (uname(&nameInfos) == 0) {
17994 const char *kernelName = nameInfos.sysname;
17995 const char *kernelVersion = nameInfos.release;
17996 const char *systemName = nameInfos.version;
17999 fpl__ParseVersionString(kernelVersion, &outInfos->
osVersion);
18017#if defined(FPL_SUBPLATFORM_STD_STRINGS)
18021 FPL__CheckArgumentNull(wideSource, 0);
18022 FPL__CheckArgumentZero(wideSourceLen, 0);
18023 size_t result = wcstombs(
fpl_null, wideSource, wideSourceLen);
18025 size_t requiredLen = result + 1;
18026 FPL__CheckArgumentMin(maxUtf8DestLen, requiredLen, 0);
18027 wcstombs(utf8Dest, wideSource, wideSourceLen);
18028 utf8Dest[result] = 0;
18034 FPL__CheckArgumentNull(utf8Source, 0);
18035 FPL__CheckArgumentZero(utf8SourceLen, 0);
18036 size_t result = mbstowcs(
fpl_null, utf8Source, utf8SourceLen);
18038 size_t requiredLen = result + 1;
18039 FPL__CheckArgumentMin(maxWideDestLen, requiredLen, 0);
18040 mbstowcs(wideDest, utf8Source, utf8SourceLen);
18041 wideDest[result] = 0;
18054#if defined(FPL_SUBPLATFORM_STD_CONSOLE)
18058 fprintf(stdout,
"%s", text);
18063 fprintf(stderr,
"%s", text);
18068 const char result = (c >= 0 && c < 256) ? (
char)c : 0;
18078#if defined(FPL_SUBPLATFORM_X11)
18080#define FPL__X11_DEFAULT_WINDOW_WIDTH 400
18081#define FPL__X11_DEFAULT_WINDOW_HEIGHT 400
18083fpl_internal void fpl__X11ReleaseSubplatform(fpl__X11SubplatformState *subplatform) {
18085 fpl__UnloadX11Api(&subplatform->api);
18088fpl_internal bool fpl__X11InitSubplatform(fpl__X11SubplatformState *subplatform) {
18090 if (!fpl__LoadX11Api(&subplatform->api)) {
18091 FPL__ERROR(FPL__MODULE_X11,
"Failed loading x11 api");
18097fpl_internal void fpl__X11ReleaseWindow(
const fpl__X11SubplatformState *subplatform, fpl__X11WindowState *windowState) {
18099 const fpl__X11Api *x11Api = &subplatform->api;
18100 if (windowState->window) {
18101 FPL_LOG_DEBUG(
"X11",
"Hide window '%d' from display '%p'", (
int)windowState->window, windowState->display);
18102 x11Api->XUnmapWindow(windowState->display, windowState->window);
18103 FPL_LOG_DEBUG(
"X11",
"Destroy window '%d' on display '%p'", (
int)windowState->window, windowState->display);
18104 x11Api->XDestroyWindow(windowState->display, windowState->window);
18105 x11Api->XFlush(windowState->display);
18106 windowState->window = 0;
18108 if (windowState->colorMap) {
18109 FPL_LOG_DEBUG(
"X11",
"Release color map '%d' from display '%p'", (
int)windowState->colorMap, windowState->display);
18110 x11Api->XFreeColormap(windowState->display, windowState->colorMap);
18111 windowState->colorMap = 0;
18113 if (windowState->display) {
18114 FPL_LOG_DEBUG(
"X11",
"Close display '%p'", windowState->display);
18115 x11Api->XCloseDisplay(windowState->display);
18119 FPL_LOG_DEBUG(
"X11",
"Restore previous error handler '%p'", windowState->lastErrorHandler);
18120 x11Api->XSetErrorHandler(windowState->lastErrorHandler);
18268 case XK_KP_Multiply:
18272 case XK_KP_Subtract:
18338 case XK_Mode_switch:
18339 case XK_ISO_Level3_Shift:
18356 return fplKey_None;
18363 int iconSourceCount = 0;
18367 iconSources[iconSourceCount++] = windowSettings->
icons[0];
18370 iconSources[iconSourceCount++] = windowSettings->
icons[1];
18373 if (iconSourceCount > 0) {
18374 int targetSize = 0;
18375 for (
int i = 0; i < iconSourceCount; ++i) {
18376 targetSize += 2 + iconSources[i].
width * iconSources[i].
height;
18379 long *data = (
long *)fpl__AllocateTemporaryMemory(
sizeof(
long) * targetSize, 16);
18380 long *target = data;
18382 for (
int i = 0; i < iconSourceCount; ++i) {
18385 *target++ = (int32_t)iconSource->
width;
18386 *target++ = (int32_t)iconSource->height;
18387 const uint32_t *source = (
const uint32_t *)iconSource->data;
18388 for (
int j = 0; j < iconSource->width * iconSource->height; ++j) {
18389 *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);
18393 x11Api->XChangeProperty(x11WinState->display, x11WinState->window, x11WinState->netWMIcon, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *)data, targetSize);
18395 fpl__ReleaseTemporaryMemory(data);
18397 x11Api->XDeleteProperty(x11WinState->display, x11WinState->window, x11WinState->netWMIcon);
18400 x11Api->XFlush(x11WinState->display);
18404fpl_internal int fpl__X11ErrorHandler(Display *display, XErrorEvent *ev) {
18405 FPL__CheckPlatform(0);
18406 fpl__PlatformAppState *appState = fpl__global__AppState;
18407 const fpl__X11SubplatformState *subplatform = &appState->x11;
18408 const fpl__X11Api *x11Api = &subplatform->api;
18409 const fpl__X11WindowState *windowState = &appState->window.x11;
18411 if (windowState->lastErrorHandler !=
fpl_null) {
18412 return windowState->lastErrorHandler(display, ev);
18419fpl_internal bool fpl__X11InitWindow(
const fplSettings *initSettings,
fplWindowSettings *currentWindowSettings, fpl__PlatformAppState *appState, fpl__X11SubplatformState *subplatform, fpl__X11WindowState *windowState,
const fpl__SetupWindowCallbacks *setupCallbacks) {
18421 const fpl__X11Api *x11Api = &subplatform->api;
18423 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Set init threads");
18424 x11Api->XInitThreads();
18427 FPL_LOG_DEBUG(
"X11",
"Enable error handler");
18428 windowState->lastErrorHandler = x11Api->XSetErrorHandler(fpl__X11ErrorHandler);
18433 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Open default Display");
18434 windowState->display = x11Api->XOpenDisplay(
fpl_null);
18435 if (windowState->display ==
fpl_null) {
18436 FPL__ERROR(FPL__MODULE_X11,
"Failed opening default Display!");
18439 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Successfully opened default Display: %p", windowState->display);
18441 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Get default screen from display '%p'", windowState->display);
18442 windowState->screen = x11Api->XDefaultScreen(windowState->display);
18443 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Got default screen from display '%p': %d", windowState->display, windowState->screen);
18445 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Get root window from display '%p' and screen '%d'", windowState->display, windowState->screen);
18446 windowState->root = x11Api->XRootWindow(windowState->display, windowState->screen);
18447 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Got root window from display '%p' and screen '%d': %d", windowState->display, windowState->screen, (
int)windowState->root);
18449 bool usePreSetupWindow =
false;
18450 if (setupCallbacks->preSetup !=
fpl_null) {
18451 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Call Pre-Setup for Window");
18452 setupCallbacks->preSetup(appState, appState->initFlags, initSettings);
18455 Visual *visual = windowState->visual;
18456 int colorDepth = windowState->colorDepth;
18458 if (visual !=
fpl_null && colorDepth > 0) {
18459 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Got visual '%p' and color depth '%d' from pre-setup", visual, colorDepth);
18460 windowState->colorMap = colormap = x11Api->XCreateColormap(windowState->display, windowState->root, visual, AllocNone);
18462 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Using default visual, color depth, colormap");
18463 windowState->visual = visual = x11Api->XDefaultVisual(windowState->display, windowState->screen);
18464 windowState->colorDepth = colorDepth = x11Api->XDefaultDepth(windowState->display, windowState->screen);
18465 windowState->colorMap = colormap = x11Api->XDefaultColormap(windowState->display, windowState->screen);
18468 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Using visual: %p", visual);
18469 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Using color depth: %d", colorDepth);
18470 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Using color map: %d", (
int)colormap);
18472 int flags = CWColormap | CWBorderPixel | CWEventMask | CWBitGravity | CWWinGravity;
18475 unsigned long backgroundPixel;
18477 backgroundPixel = 0;
18479 flags |= CWBackPixel;
18484 swa.colormap = colormap;
18486 StructureNotifyMask |
18487 ExposureMask | FocusChangeMask | VisibilityChangeMask |
18488 EnterWindowMask | LeaveWindowMask | PropertyChangeMask |
18489 KeyPressMask | KeyReleaseMask |
18490 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask;
18491 swa.background_pixel = backgroundPixel;
18492 swa.border_pixel = 0;
18493 swa.bit_gravity = NorthWestGravity;
18494 swa.win_gravity = NorthWestGravity;
18505 windowWidth = FPL__X11_DEFAULT_WINDOW_WIDTH;
18506 windowHeight = FPL__X11_DEFAULT_WINDOW_HEIGHT;
18514 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);
18515 windowState->window = x11Api->XCreateWindow(windowState->display,
18527 if (!windowState->window) {
18528 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);
18529 fpl__X11ReleaseWindow(subplatform, windowState);
18532 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);
18535 windowState->utf8String = x11Api->XInternAtom(windowState->display,
"UTF8_STRING", False);
18538 windowState->wmDeleteWindow = x11Api->XInternAtom(windowState->display,
"WM_DELETE_WINDOW", False);
18539 windowState->wmProtocols = x11Api->XInternAtom(windowState->display,
"WM_PROTOCOLS", False);
18540 windowState->wmState = x11Api->XInternAtom(windowState->display,
"WM_STATE", False);
18541 windowState->netWMPing = x11Api->XInternAtom(windowState->display,
"_NET_WM_PING", False);
18542 windowState->netWMState = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE", False);
18543 windowState->netWMStateFocused = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_FOCUSED", False);
18544 windowState->netWMStateFullscreen = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_FULLSCREEN", False);
18545 windowState->netWMStateHidden = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_HIDDEN", False);
18546 windowState->netWMStateMaximizedVert = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_MAXIMIZED_VERT", False);
18547 windowState->netWMStateMaximizedHorz = x11Api->XInternAtom(windowState->display,
"_NET_WM_STATE_MAXIMIZED_HORZ", False);
18548 windowState->netWMPid = x11Api->XInternAtom(windowState->display,
"_NET_WM_PID", False);
18549 windowState->netWMIcon = x11Api->XInternAtom(windowState->display,
"_NET_WM_ICON", False);
18550 windowState->netWMName = x11Api->XInternAtom(windowState->display,
"_NET_WM_NAME", False);
18551 windowState->netWMIconName = x11Api->XInternAtom(windowState->display,
"_NET_WM_ICON_NAME", False);
18552 windowState->motifWMHints = x11Api->XInternAtom(windowState->display,
"_MOTIF_WM_HINTS", False);
18554 windowState->xdndAware = x11Api->XInternAtom(windowState->display,
"XdndAware", False);
18555 windowState->xdndEnter = x11Api->XInternAtom(windowState->display,
"XdndEnter", False);
18556 windowState->xdndPosition = x11Api->XInternAtom(windowState->display,
"XdndPosition", False);
18557 windowState->xdndStatus = x11Api->XInternAtom(windowState->display,
"XdndStatus", False);
18558 windowState->xdndActionCopy = x11Api->XInternAtom(windowState->display,
"XdndActionCopy", False);
18559 windowState->xdndDrop = x11Api->XInternAtom(windowState->display,
"XdndDrop", False);
18560 windowState->xdndFinished = x11Api->XInternAtom(windowState->display,
"XdndFinished", False);
18561 windowState->xdndSelection = x11Api->XInternAtom(windowState->display,
"XdndSelection", False);
18562 windowState->xdndTypeList = x11Api->XInternAtom(windowState->display,
"XdndTypeList", False);
18563 windowState->textUriList = x11Api->XInternAtom(windowState->display,
"text/uri-list", False);
18567 Atom protocols[] = {
18568 windowState->wmDeleteWindow,
18569 windowState->netWMPing
18571 x11Api->XSetWMProtocols(windowState->display, windowState->window, protocols,
fplArrayCount(protocols));
18576 const long pid = getpid();
18577 x11Api->XChangeProperty(windowState->display, windowState->window, windowState->netWMPid, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *)&pid, 1);
18586 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Show window '%d' on display '%p' with title '%s'", (
int)windowState->window, windowState->display, nameBuffer);
18587 fpl__X11LoadWindowIcon(x11Api, windowState, currentWindowSettings);
18589 x11Api->XMapWindow(windowState->display, windowState->window);
18590 x11Api->XFlush(windowState->display);
18595 FPL_LOG_DEBUG(FPL__MODULE_X11,
"Build X11 Keymap");
18597 for (
int keyCode = 8; keyCode <= 255; ++keyCode) {
18599 KeySym *keySyms = x11Api->XGetKeyboardMapping(windowState->display, keyCode, 1, &dummy);
18600 KeySym keySym = keySyms[0];
18601 fplKey mappedKey = fpl__X11TranslateKeySymbol(keySym);
18602 appState->window.keyMap[keyCode] = mappedKey;
18603 x11Api->XFree(keySyms);
18612 const Atom version = FPL__XDND_VERSION;
18613 x11Api->XChangeProperty(windowState->display, windowState->window, windowState->xdndAware, XA_ATOM, 32, PropModeReplace, (
unsigned char *)&version, 1);
18616 appState->window.isRunning =
true;
18623 if (state & ShiftMask) {
18627 if (state & ControlMask) {
18631 if (state & Mod1Mask) {
18635 if (state & Mod4Mask) {
18642fpl_internal unsigned long fpl__X11GetWindowProperty(
const fpl__X11Api *x11Api, Display *display, Window window, Atom prop, Atom type,
unsigned char **value) {
18645 unsigned long itemCount, bytesAfter;
18646 x11Api->XGetWindowProperty(display, window, prop, 0, LONG_MAX, False, type, &actualType, &actualFormat, &itemCount, &bytesAfter, value);
18650fpl_internal const int fpl__X11GetWMState(
const fpl__X11Api *x11Api, fpl__X11WindowState *windowState) {
18651 struct {
int state; Window icon; } *value = NULL;
18652 unsigned long numItems = fpl__X11GetWindowProperty(x11Api, windowState->display, windowState->window, windowState->wmState, windowState->wmState, (
unsigned char **)&value);
18653 int state = WithdrawnState;
18655 state = value->state;
18656 x11Api->XFree(value);
18661#define fpl__X11NetWMStateHiddenFlag (1 << 0)
18662#define fpl__X11NetWMStateMaximizedFlag (1 << 1)
18663#define fpl__X11NetWMStateFullscreenFlag (1 << 2)
18665fpl_internal unsigned int fpl__X11GetNetWMState(
const fpl__X11Api *x11Api, fpl__X11WindowState *windowState) {
18666 Atom *atoms = NULL;
18667 unsigned long numItems = fpl__X11GetWindowProperty(x11Api, windowState->display, windowState->window, windowState->netWMState, XA_ATOM, (
unsigned char **)&atoms);
18668 unsigned int flags = 0;
18670 int i, maximized = 0;
18671 for (i = 0; i < numItems; ++i) {
18672 if (atoms[i] == windowState->netWMStateHidden) {
18673 flags |= fpl__X11NetWMStateHiddenFlag;
18674 }
else if (atoms[i] == windowState->netWMStateMaximizedVert) {
18676 }
else if (atoms[i] == windowState->netWMStateMaximizedHorz) {
18678 }
else if (atoms[i] == windowState->netWMStateFullscreen) {
18679 flags |= fpl__X11NetWMStateFullscreenFlag;
18682 if (maximized == 3) {
18683 flags |= fpl__X11NetWMStateMaximizedFlag;
18687 XWindowAttributes attr;
18689 x11Api->XGetWindowAttributes(windowState->display, windowState->window, &attr);
18690 if (attr.map_state == IsUnmapped) {
18691 flags |= fpl__X11NetWMStateHiddenFlag;
18694 x11Api->XFree(atoms);
18699fpl_internal fpl__X11WindowStateInfo fpl__X11GetWindowStateInfo(
const fpl__X11Api *x11Api, fpl__X11WindowState *windowState) {
18701 const int state = fpl__X11GetWMState(x11Api, windowState);
18702 unsigned int flags = fpl__X11GetNetWMState(x11Api, windowState);
18703 if (state == NormalState) {
18705 }
else if (state == IconicState) {
18710 if (flags & fpl__X11NetWMStateHiddenFlag) {
18713 if (flags & fpl__X11NetWMStateFullscreenFlag) {
18715 }
else if (state != IconicState && flags & fpl__X11NetWMStateMaximizedFlag) {
18721fpl_internal fpl__X11WindowStateInfo fpl__X11ReconcilWindowStateInfo(fpl__X11WindowStateInfo *last, fpl__X11WindowStateInfo *next) {
18723 if (last->state != next->state) {
18724 change.state = next->state;
18726 if (last->visibility != next->visibility) {
18727 change.visibility = next->visibility;
18732fpl_internal void *fpl__X11ParseUriPaths(
const char *text,
size_t *size,
int *count,
int textLength) {
18733 const char *textCursor = text;
18734 const char *textEnd = text + textLength;
18737 while (*textCursor !=
'\0' || textCursor != textEnd) {
18738 if (*textCursor ==
'\r' && *(textCursor + 1) ==
'\n')
18743 size_t filesTableSize = fileCount *
sizeof(
char **);
18745 size_t filesMemorySize = filesTableSize + FPL__ARBITARY_PADDING + maxFileStride * fileCount;
18746 void *filesTableMemory = fpl__AllocateDynamicMemory(filesMemorySize, 8);
18747 char **filesTable = (
char **)filesTableMemory;
18748 for (
int fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
18749 filesTable[fileIndex] = (
char *)((uint8_t *)filesTableMemory + filesTableSize + FPL__ARBITARY_PADDING + fileIndex * maxFileStride);
18751 for (
int fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
18752 char *file = filesTable[fileIndex];
18753 const char *line = textCursor;
18755 while (*textCursor !=
'\r' && (*textCursor !=
'\0' || textCursor != textEnd)) {
18765 *size = filesMemorySize;
18766 *count = fileCount;
18767 return filesTableMemory;
18770fpl_internal void fpl__X11HandleTextInputEvent(
const fpl__X11Api *x11Api, fpl__PlatformWindowState *winState,
const uint64_t keyCode, XEvent *ev) {
18773 if (x11Api->XLookupString(&ev->xkey, buf, 32, &keysym, NULL) != NoSymbol) {
18776 uint32_t textCode = (uint32_t)wideBuffer[0];
18777 if (textCode > 0) {
18778 fpl__HandleKeyboardInputEvent(winState, keyCode, textCode);
18783fpl_internal void fpl__X11HandleEvent(
const fpl__X11SubplatformState *subplatform, fpl__PlatformAppState *appState, XEvent *ev) {
18785 fpl__PlatformWindowState *winState = &appState->window;
18786 fpl__X11WindowState *x11WinState = &winState->x11;
18787 fpl__X11WindowStateInfo *lastX11WinInfo = &x11WinState->lastWindowStateInfo;
18788 const fpl__X11Api *x11Api = &appState->x11.api;
18790 if (appState->currentSettings.window.callbacks.eventCallback !=
fpl_null) {
18791 appState->currentSettings.window.callbacks.eventCallback(
fplGetPlatformType(), x11WinState, ev, appState->currentSettings.window.callbacks.eventUserData);
18794 switch (ev->type) {
18795 case ConfigureNotify:
18797# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
18799 if (appState->initSettings.video.isAutoSize) {
18800 uint32_t w = (uint32_t)ev->xconfigure.width;
18801 uint32_t h = (uint32_t)ev->xconfigure.height;
18807 if (ev->xconfigure.width != lastX11WinInfo->size.width || ev->xconfigure.height != lastX11WinInfo->size.height) {
18809 lastX11WinInfo->size.width = (int32_t)ev->xconfigure.width;
18810 lastX11WinInfo->size.height = (int32_t)ev->xconfigure.height;
18814 if (ev->xconfigure.x != lastX11WinInfo->position.left || ev->xconfigure.y != lastX11WinInfo->position.top) {
18816 lastX11WinInfo->position.left = (int32_t)ev->xconfigure.x;
18817 lastX11WinInfo->position.top = (int32_t)ev->xconfigure.y;
18821 case ClientMessage:
18823 if (ev->xclient.message_type == x11WinState->wmProtocols) {
18824 const Atom protocol = (Atom)ev->xclient.data.l[0];
18825 if (protocol != None) {
18826 if (protocol == x11WinState->wmDeleteWindow) {
18828 winState->isRunning =
false;
18830 }
else if (protocol == x11WinState->netWMPing) {
18832 XEvent reply = *ev;
18833 reply.xclient.window = x11WinState->root;
18834 x11Api->XSendEvent(x11WinState->display, x11WinState->root, False, SubstructureNotifyMask | SubstructureRedirectMask, &reply);
18837 }
else if (ev->xclient.message_type == x11WinState->xdndEnter) {
18839 unsigned long i, count;
18840 Atom *formats = NULL;
18841 bool list = ev->xclient.data.l[1] & 1;
18842 x11WinState->xdnd.source = ev->xclient.data.l[0];
18843 x11WinState->xdnd.version = ev->xclient.data.l[1] >> 24;
18844 x11WinState->xdnd.format = None;
18845 if (x11WinState->xdnd.version > FPL__XDND_VERSION) {
18849 count = fpl__X11GetWindowProperty(x11Api, x11WinState->display, x11WinState->xdnd.source, x11WinState->xdndTypeList, XA_ATOM, (
unsigned char **)&formats);
18852 formats = (Atom *)ev->xclient.data.l + 2;
18854 for (i = 0; i < count; ++i) {
18855 if (formats[i] == x11WinState->textUriList) {
18856 x11WinState->xdnd.format = x11WinState->textUriList;
18860 if (list && formats) {
18861 x11Api->XFree(formats);
18863 }
else if (ev->xclient.message_type == x11WinState->xdndDrop) {
18865 Time time = CurrentTime;
18866 if (x11WinState->xdnd.version > FPL__XDND_VERSION) {
18869 if (x11WinState->xdnd.format) {
18870 if (x11WinState->xdnd.version >= 1) {
18871 time = ev->xclient.data.l[2];
18874 x11Api->XConvertSelection(x11WinState->display, x11WinState->xdndSelection, x11WinState->xdnd.format, x11WinState->xdndSelection, x11WinState->window, time);
18875 }
else if (x11WinState->xdnd.version >= 2) {
18879 reply.type = ClientMessage;
18880 reply.xclient.window = x11WinState->xdnd.source;
18881 reply.xclient.message_type = x11WinState->xdndFinished;
18882 reply.xclient.format = 32;
18883 reply.xclient.data.l[0] = x11WinState->window;
18884 reply.xclient.data.l[1] = 0;
18885 reply.xclient.data.l[2] = None;
18887 x11Api->XSendEvent(x11WinState->display, x11WinState->xdnd.source, False, NoEventMask, &reply);
18888 x11Api->XFlush(x11WinState->display);
18890 }
else if (ev->xclient.message_type == x11WinState->xdndPosition) {
18894 const int xabs = (ev->xclient.data.l[2] >> 16) & 0xffff;
18895 const int yabs = (ev->xclient.data.l[2]) & 0xffff;
18896 if (x11WinState->xdnd.version > FPL__XDND_VERSION) {
18902 reply.type = ClientMessage;
18903 reply.xclient.window = x11WinState->xdnd.source;
18904 reply.xclient.message_type = x11WinState->xdndStatus;
18905 reply.xclient.format = 32;
18906 reply.xclient.data.l[0] = x11WinState->window;
18907 reply.xclient.data.l[2] = 0;
18908 reply.xclient.data.l[3] = 0;
18910 if (x11WinState->xdnd.format) {
18912 reply.xclient.data.l[1] = 1;
18913 if (x11WinState->xdnd.version >= 2)
18914 reply.xclient.data.l[4] = x11WinState->xdndActionCopy;
18916 x11Api->XSendEvent(x11WinState->display, x11WinState->xdnd.source, False, NoEventMask, &reply);
18917 x11Api->XFlush(x11WinState->display);
18921 case SelectionNotify:
18923 if (ev->xselection.property == x11WinState->xdndSelection) {
18926 const unsigned long result = fpl__X11GetWindowProperty(x11Api, x11WinState->display, ev->xselection.requestor, ev->xselection.property, ev->xselection.target, (
unsigned char **)&data);
18928 size_t filesTableSize;
18930 void *filesTable = fpl__X11ParseUriPaths(data, &filesTableSize, &fileCount, result);
18932 memory.
size = filesTableSize;
18933 memory.
base = filesTable;
18934 fpl__PushWindowDropFilesEvent(NULL, fileCount, (
const char **)filesTable, &memory);
18937 x11Api->XFree(data);
18939 if (x11WinState->xdnd.version >= 2) {
18943 reply.type = ClientMessage;
18944 reply.xclient.window = x11WinState->xdnd.source;
18945 reply.xclient.message_type = x11WinState->xdndFinished;
18946 reply.xclient.format = 32;
18947 reply.xclient.data.l[0] = x11WinState->window;
18948 reply.xclient.data.l[1] = result;
18949 reply.xclient.data.l[2] = x11WinState->xdndActionCopy;
18951 x11Api->XSendEvent(x11WinState->display, x11WinState->xdnd.source, False, NoEventMask, &reply);
18952 x11Api->XFlush(x11WinState->display);
18960 if (!appState->currentSettings.input.disabledEvents) {
18961 int keyState = ev->xkey.state;
18962 uint64_t keyCode = (uint64_t)ev->xkey.keycode;
18963 Time keyTime = ev->xkey.time;
18964 Time lastPressTime = winState->keyPressTimes[keyCode];
18965 Time diffTime = keyTime - lastPressTime;
18966 FPL_LOG_INFO(
"X11",
"Diff for key '%llu', time: %lu, diff: %lu, last: %lu", keyCode, keyTime, diffTime, lastPressTime);
18967 if (diffTime == keyTime || (diffTime > 0 && diffTime < (1 << 31))) {
18969 fpl__HandleKeyboardButtonEvent(winState, (uint64_t)keyTime, keyCode, fpl__X11TranslateModifierFlags(keyState),
fplButtonState_Press,
false);
18970 fpl__X11HandleTextInputEvent(x11Api, winState, keyCode, ev);
18972 winState->keyPressTimes[keyCode] = keyTime;
18980 if (!appState->currentSettings.input.disabledEvents) {
18981 bool isRepeat =
false;
18982 if (x11Api->XEventsQueued(x11WinState->display, QueuedAfterReading)) {
18984 x11Api->XPeekEvent(x11WinState->display, &nextEvent);
18985 if ((nextEvent.type == KeyPress) && (nextEvent.xkey.time == ev->xkey.time) && (nextEvent.xkey.keycode == ev->xkey.keycode)) {
18987 x11Api->XNextEvent(x11WinState->display, ev);
18992 int keyState = ev->xkey.state;
18993 uint64_t keyCode = (uint64_t)ev->xkey.keycode;
18996 fpl__X11HandleTextInputEvent(x11Api, winState, keyCode, ev);
18997 fpl__HandleKeyboardButtonEvent(winState, (uint64_t)ev->xkey.time, (uint64_t)keyCode, fpl__X11TranslateModifierFlags(keyState),
fplButtonState_Repeat,
false);
18999 fpl__HandleKeyboardButtonEvent(winState, (uint64_t)ev->xkey.time, (uint64_t)keyCode, fpl__X11TranslateModifierFlags(keyState),
fplButtonState_Release,
true);
19006 int x = ev->xbutton.x;
19007 int y = ev->xbutton.y;
19009 if (!appState->currentSettings.input.disabledEvents) {
19011 if (ev->xbutton.button == Button1) {
19013 }
else if (ev->xbutton.button == Button2) {
19015 }
else if (ev->xbutton.button == Button3) {
19021 if (ev->xbutton.button == Button4) {
19022 fpl__HandleMouseWheelEvent(winState, x, y, 1.0f);
19023 }
else if (ev->xbutton.button == Button5) {
19024 fpl__HandleMouseWheelEvent(winState, x, y, -1.0f);
19028 case ButtonRelease:
19031 if (!appState->currentSettings.input.disabledEvents) {
19032 int x = ev->xbutton.x;
19033 int y = ev->xbutton.y;
19034 if (ev->xbutton.button == Button1) {
19036 }
else if (ev->xbutton.button == Button2) {
19038 }
else if (ev->xbutton.button == Button3) {
19047 if (!appState->currentSettings.input.disabledEvents) {
19048 fpl__HandleMouseMoveEvent(winState, ev->xmotion.x, ev->xmotion.y);
19055 if (appState->currentSettings.window.callbacks.exposedCallback !=
fpl_null) {
19056 appState->currentSettings.window.callbacks.exposedCallback(
fplGetPlatformType(), x11WinState, ev, appState->currentSettings.window.callbacks.exposedUserData);
19064 if (ev->xfocus.mode == NotifyGrab || ev->xfocus.mode == NotifyUngrab) {
19074 if (ev->xfocus.mode == NotifyGrab || ev->xfocus.mode == NotifyUngrab) {
19080 case PropertyNotify:
19082 if (ev->xproperty.atom == x11WinState->netWMState || ev->xproperty.atom == x11WinState->wmState) {
19083 fpl__X11WindowStateInfo nextWindowStateInfo = fpl__X11GetWindowStateInfo(x11Api, x11WinState);
19084 fpl__X11WindowStateInfo changedWindowStateInfo = fpl__X11ReconcilWindowStateInfo(&x11WinState->lastWindowStateInfo, &nextWindowStateInfo);
19085 switch (changedWindowStateInfo.visibility) {
19095 switch (changedWindowStateInfo.state) {
19108 x11WinState->lastWindowStateInfo.state = nextWindowStateInfo.state;
19109 x11WinState->lastWindowStateInfo.visibility = nextWindowStateInfo.visibility;
19119 FPL__CheckPlatform(
false);
19120 bool result = fpl__global__AppState->window.isRunning;
19125 FPL__CheckPlatformNoRet();
19126 fpl__PlatformAppState *appState = fpl__global__AppState;
19127 if (appState->window.isRunning) {
19128 appState->window.isRunning =
false;
19129 const fpl__X11SubplatformState *subplatform = &appState->x11;
19130 const fpl__X11Api *x11Api = &subplatform->api;
19131 const fpl__X11WindowState *windowState = &appState->window.x11;
19133 ev.type = ClientMessage;
19134 ev.xclient.window = windowState->window;
19135 ev.xclient.message_type = windowState->wmProtocols;
19136 ev.xclient.format = 32;
19137 ev.xclient.data.l[0] = windowState->wmDeleteWindow;
19138 ev.xclient.data.l[1] = 0;
19139 x11Api->XSendEvent(windowState->display, windowState->root, False, SubstructureRedirectMask | SubstructureNotifyMask, &ev);
19143fpl_internal bool fpl__X11ProcessNextEvent(
const fpl__X11SubplatformState *subplatform, fpl__PlatformAppState *appState) {
19144 bool result =
false;
19145 const fpl__X11Api *x11Api = &subplatform->api;
19146 fpl__X11WindowState *windowState = &appState->window.x11;
19147 if (x11Api->XPending(windowState->display)) {
19149 x11Api->XNextEvent(windowState->display, &ev);
19150 fpl__X11HandleEvent(subplatform, appState, &ev);
19157 FPL__CheckPlatform(
false);
19158 fpl__PlatformAppState *appState = fpl__global__AppState;
19159 const fpl__X11SubplatformState *subplatform = &appState->x11;
19160 const fpl__X11Api *x11Api = &subplatform->api;
19161 const fpl__X11WindowState *windowState = &appState->window.x11;
19164 if (fpl__PollInternalEvent(ev)) {
19169 if (!fpl__X11ProcessNextEvent(subplatform, appState)) {
19174 if (fpl__PollInternalEvent(ev)) {
19183 FPL__CheckPlatformNoRet();
19184 fpl__PlatformAppState *appState = fpl__global__AppState;
19185 const fpl__X11SubplatformState *subplatform = &appState->x11;
19186 const fpl__X11Api *x11Api = &subplatform->api;
19187 const fpl__X11WindowState *windowState = &appState->window.x11;
19188 while (x11Api->XPending(windowState->display)) {
19190 x11Api->XNextEvent(windowState->display, &ev);
19191 fpl__X11HandleEvent(subplatform, appState, &ev);
19193 fpl__ClearInternalEvents();
19197 FPL__CheckPlatform(
false);
19198 fpl__PlatformAppState *appState = fpl__global__AppState;
19199 const fpl__X11SubplatformState *subplatform = &appState->x11;
19200 const fpl__X11Api *x11Api = &subplatform->api;
19201 const fpl__X11WindowState *windowState = &appState->window.x11;
19203 fpl__ClearInternalEvents();
19206#if defined(FPL_PLATFORM_LINUX)
19208 fpl__LinuxAppState *linuxAppState = &appState->plinux;
19209 fpl__LinuxPollGameControllers(&appState->currentSettings, &linuxAppState->controllersState,
true);
19213 bool result = appState->window.isRunning;
19222 FPL__CheckArgumentNull(outSize,
false);
19223 FPL__CheckPlatform(
false);
19224 fpl__PlatformAppState *appState = fpl__global__AppState;
19225 const fpl__X11SubplatformState *subplatform = &appState->x11;
19226 const fpl__X11Api *x11Api = &subplatform->api;
19227 const fpl__X11WindowState *windowState = &appState->window.x11;
19228 XWindowAttributes attribs;
19229 x11Api->XGetWindowAttributes(windowState->display, windowState->window, &attribs);
19230 outSize->
width = attribs.width;
19231 outSize->
height = attribs.height;
19236 fpl__PlatformAppState *appState = fpl__global__AppState;
19237 FPL__CheckPlatformNoRet();
19238 const fpl__X11SubplatformState *subplatform = &appState->x11;
19239 const fpl__X11Api *x11Api = &subplatform->api;
19240 const fpl__X11WindowState *windowState = &appState->window.x11;
19241 x11Api->XResizeWindow(windowState->display, windowState->window, width, height);
19242 x11Api->XFlush(windowState->display);
19255 FPL__CheckPlatform(
false);
19256 fpl__PlatformAppState *appState = fpl__global__AppState;
19257 bool result = appState->currentSettings.window.isDecorated;
19261#define FPL__MWM_HINTS_DECORATIONS (1L << 1)
19262#define FPL__MWM_HINTS_FUNCTIONS (1L << 0)
19263#define FPL__MWM_FUNC_ALL (1L<<0)
19264#define FPL__PROPERTY_MOTIF_WM_HINTS_ELEMENT_COUNT 5
19267 unsigned long flags;
19268 unsigned long functions;
19269 unsigned long decorations;
19271 unsigned long status;
19272} fpl__MotifWMHints;
19275 FPL__CheckPlatformNoRet();
19276 fpl__PlatformAppState *appState = fpl__global__AppState;
19277 const fpl__X11SubplatformState *subplatform = &appState->x11;
19278 const fpl__X11Api *x11Api = &subplatform->api;
19279 const fpl__X11WindowState *windowState = &appState->window.x11;
19282 hints.flags = FPL__MWM_HINTS_DECORATIONS | FPL__MWM_HINTS_FUNCTIONS;
19283 hints.decorations = value ? 1 : 0;
19284 hints.functions = value ? FPL__MWM_FUNC_ALL : 0;
19286 x11Api->XChangeProperty(windowState->display, windowState->window,
19287 windowState->motifWMHints,
19288 windowState->motifWMHints, 32,
19290 (
unsigned char *)&hints,
19291 FPL__PROPERTY_MOTIF_WM_HINTS_ELEMENT_COUNT);
19293 appState->currentSettings.window.isDecorated = value;
19346 FPL__CheckPlatform(
false);
19347 fpl__PlatformAppState *appState = fpl__global__AppState;
19348 const fpl__X11SubplatformState *subplatform = &appState->x11;
19349 const fpl__X11Api *x11Api = &subplatform->api;
19350 const fpl__X11WindowState *windowState = &appState->window.x11;
19354 xev.type = ClientMessage;
19355 xev.xclient.window = windowState->window;
19356 xev.xclient.message_type = windowState->netWMState;
19357 xev.xclient.format = 32;
19358 xev.xclient.data.l[0] = value ? 1 : 0;
19359 xev.xclient.data.l[1] = windowState->netWMStateFullscreen;
19360 xev.xclient.data.l[3] = 1l;
19364 bool result = x11Api->XSendEvent(windowState->display, windowState->root, 0, SubstructureRedirectMask | SubstructureNotifyMask, &xev) != 0;
19366 appState->currentSettings.window.isFullscreen = value;
19387 FPL__CheckPlatform(
false);
19388 fpl__PlatformAppState *appState = fpl__global__AppState;
19389 bool result = appState->currentSettings.window.isFullscreen;
19394 FPL__CheckArgumentNull(outPos,
false);
19395 FPL__CheckPlatform(
false);
19396 fpl__PlatformAppState *appState = fpl__global__AppState;
19397 const fpl__X11SubplatformState *subplatform = &appState->x11;
19398 const fpl__X11Api *x11Api = &subplatform->api;
19399 const fpl__X11WindowState *windowState = &appState->window.x11;
19400 XWindowAttributes attribs;
19401 x11Api->XGetWindowAttributes(windowState->display, windowState->window, &attribs);
19402 outPos->
left = attribs.x;
19403 outPos->
top = attribs.y;
19408 FPL__CheckPlatformNoRet();
19409 fpl__PlatformAppState *appState = fpl__global__AppState;
19410 const fpl__X11SubplatformState *subplatform = &appState->x11;
19411 const fpl__X11Api *x11Api = &subplatform->api;
19412 const fpl__X11WindowState *windowState = &appState->window.x11;
19413 x11Api->XMoveWindow(windowState->display, windowState->window, left, top);
19419 FPL__CheckArgumentNullNoRet(title);
19420 FPL__CheckPlatformNoRet();
19421 fpl__PlatformAppState *appState = fpl__global__AppState;
19422 const fpl__X11SubplatformState *subplatform = &appState->x11;
19423 const fpl__X11Api *x11Api = &subplatform->api;
19424 const fpl__X11WindowState *windowState = &appState->window.x11;
19428 x11Api->XChangeProperty(windowState->display, windowState->window,
19429 windowState->netWMName, windowState->utf8String, 8,
19433 x11Api->XChangeProperty(windowState->display, windowState->window,
19434 windowState->netWMIconName, windowState->utf8String, 8,
19438 x11Api->XFlush(windowState->display);
19452 FPL__CheckPlatform(
false);
19453 FPL__CheckArgumentNull(outState,
false);
19454 fpl__PlatformAppState *appState = fpl__global__AppState;
19455 const fpl__X11SubplatformState *subplatform = &appState->x11;
19456 const fpl__X11Api *x11Api = &subplatform->api;
19457 const fpl__X11WindowState *windowState = &appState->window.x11;
19458 bool result =
false;
19460 if (x11Api->XQueryKeymap(windowState->display, keysReturn)) {
19462 for (uint64_t keyCode = 0; keyCode < 256; ++keyCode) {
19463 bool isDown = (keysReturn[keyCode / 8] & (1 << (keyCode % 8))) != 0;
19465 fplKey mappedKey = fpl__GetMappedKey(&appState->window, keyCode);
19503 FPL__CheckPlatform(
false);
19504 FPL__CheckArgumentNull(outState,
false);
19505 fpl__PlatformAppState *appState = fpl__global__AppState;
19506 const fpl__X11SubplatformState *subplatform = &appState->x11;
19507 const fpl__X11Api *x11Api = &subplatform->api;
19508 const fpl__X11WindowState *windowState = &appState->window.x11;
19509 bool result =
false;
19510 Window root, child;
19511 int rootx, rooty, winx, winy;
19513 if (x11Api->XQueryPointer(windowState->display, windowState->window, &root, &child, &rootx, &rooty, &winx, &winy, &mask)) {
19514 outState->
x = winx;
19515 outState->
y = winy;
19535#if defined(FPL_PLATFORM_LINUX)
19536# include <locale.h>
19537# include <sys/eventfd.h>
19538# include <sys/epoll.h>
19539# include <sys/select.h>
19540# include <linux/joystick.h>
19542fpl_internal void fpl__LinuxReleasePlatform(fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
19543#if defined(FPL__ENABLE_WINDOW)
19545 fpl__LinuxFreeGameControllers(&appState->plinux.controllersState);
19550fpl_internal bool fpl__LinuxInitPlatform(
const fplInitFlags initFlags,
const fplSettings *initSettings, fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
19551 setlocale(LC_ALL,
"");
19563#if defined(FPL__ENABLE_WINDOW)
19564fpl_internal void fpl__LinuxFreeGameControllers(fpl__LinuxGameControllersState *controllersState) {
19565 for (
int controllerIndex = 0; controllerIndex <
fplArrayCount(controllersState->controllers); ++controllerIndex) {
19566 fpl__LinuxGameController *controller = controllersState->controllers + controllerIndex;
19567 if (controller->fd > 0) {
19568 close(controller->fd);
19569 controller->fd = 0;
19574fpl_internal float fpl__LinuxJoystickProcessStickValue(
const int16_t value,
const int16_t deadZoneThreshold) {
19576 if (value < -deadZoneThreshold) {
19577 result = (float)((value + deadZoneThreshold) / (32768.0f - deadZoneThreshold));
19578 }
else if (value > deadZoneThreshold) {
19579 result = (float)((value - deadZoneThreshold) / (32767.0f - deadZoneThreshold));
19584fpl_internal void fpl__LinuxPushGameControllerStateUpdateEvent(
const struct js_event *event, fpl__LinuxGameController *controller) {
19589 buttonMappingTable[0] = &padState->
actionA;
19590 buttonMappingTable[1] = &padState->
actionB;
19591 buttonMappingTable[2] = &padState->
actionX;
19592 buttonMappingTable[3] = &padState->
actionY;
19595 buttonMappingTable[6] = &padState->
back;
19596 buttonMappingTable[7] = &padState->
start;
19598 buttonMappingTable[9] = &padState->
leftThumb;
19599 buttonMappingTable[10] = &padState->
rightThumb;
19601 const int16_t deadZoneThresholdLeftStick = 5000;
19602 const int16_t deadZoneThresholdRightStick = 5000;
19604 switch (event->type & ~JS_EVENT_INIT) {
19605 case JS_EVENT_AXIS:
19607 switch (event->number) {
19611 padState->
leftStickX = fpl__LinuxJoystickProcessStickValue(event->value, deadZoneThresholdLeftStick);
19615 padState->
leftStickY = fpl__LinuxJoystickProcessStickValue(-event->value, deadZoneThresholdLeftStick);
19621 padState->
rightStickX = fpl__LinuxJoystickProcessStickValue(event->value, deadZoneThresholdRightStick);
19625 padState->
rightStickY = fpl__LinuxJoystickProcessStickValue(-event->value, deadZoneThresholdRightStick);
19631 padState->
leftTrigger = (float)((event->value + 32768) >> 8) / 255.0f;
19635 padState->
rightTrigger = (float)((event->value + 32768) >> 8) / 255.0f;
19641 if (event->value == -32767) {
19644 }
else if (event->value == 32767) {
19656 if (event->value == -32767) {
19659 }
else if (event->value == 32767) {
19673 case JS_EVENT_BUTTON:
19675 if ((event->number >= 0) && (event->number <
fplArrayCount(buttonMappingTable))) {
19678 mappedButton->
isDown =
event->value != 0;
19688fpl_internal void fpl__LinuxPollGameControllers(
const fplSettings *settings, fpl__LinuxGameControllersState *controllersState,
const bool useEvents) {
19700 const char *deviceNames[] = {
19703 for (
int deviceNameIndex = 0; deviceNameIndex <
fplArrayCount(deviceNames); ++deviceNameIndex) {
19704 const char *deviceName = deviceNames[deviceNameIndex];
19705 bool alreadyFound =
false;
19706 int freeIndex = -1;
19707 for (uint32_t controllerIndex = 0; controllerIndex <
fplArrayCount(controllersState->controllers); ++controllerIndex) {
19708 fpl__LinuxGameController *controller = controllersState->controllers + controllerIndex;
19709 if ((controller->fd > 0) &&
fplIsStringEqual(deviceName, controller->deviceName)) {
19710 alreadyFound =
true;
19713 if (controller->fd == 0) {
19714 if (freeIndex == -1) {
19715 freeIndex = controllerIndex;
19719 if (!alreadyFound && freeIndex >= 0) {
19720 int fd = open(deviceName, O_RDONLY);
19722 FPL_LOG_ERROR(FPL__MODULE_LINUX,
"Failed opening joystick device '%s'", deviceName);
19725 uint8_t numAxis = 0;
19726 uint8_t numButtons = 0;
19727 ioctl(fd, JSIOCGAXES, &numAxis);
19728 ioctl(fd, JSIOCGBUTTONS, &numButtons);
19729 if (numAxis == 0 || numButtons == 0) {
19730 FPL_LOG_ERROR(FPL__MODULE_LINUX,
"Joystick device '%s' does not have enough buttons/axis to map to a XInput controller!", deviceName);
19736 struct js_event msg;
19737 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))) {
19743 fpl__LinuxGameController *controller = controllersState->controllers + freeIndex;
19745 controller->fd = fd;
19746 controller->axisCount = numAxis;
19747 controller->buttonCount = numButtons;
19749 ioctl(fd, JSIOCGNAME(
fplArrayCount(controller->displayName)), controller->displayName);
19750 fcntl(fd, F_SETFL, O_NONBLOCK);
19759 fpl__PushInternalEvent(&ev);
19766 for (uint32_t controllerIndex = 0; controllerIndex <
fplArrayCount(controllersState->controllers); ++controllerIndex) {
19767 fpl__LinuxGameController *controller = controllersState->controllers + controllerIndex;
19768 if (controller->fd > 0) {
19770 struct js_event event;
19771 bool wasDisconnected =
false;
19774 if (read(controller->fd, &event,
sizeof(event)) < 0) {
19775 if (errno == ENODEV) {
19776 close(controller->fd);
19777 controller->fd = 0;
19779 wasDisconnected =
true;
19787 fpl__PushInternalEvent(&ev);
19792 fpl__LinuxPushGameControllerStateUpdateEvent(&event, controller);
19795 controller->state.isActive = !fpl__IsZeroMemory(&controller->state,
sizeof(
fplGamepadState));
19796 controller->state.isConnected = !wasDisconnected;
19797 controller->state.deviceName = controller->deviceName;
19799 if (controller->fd > 0) {
19808 fpl__PushInternalEvent(&ev);
19816 FPL__CheckPlatform(
false);
19817 FPL__CheckArgumentNull(outStates,
false);
19818 fpl__PlatformAppState *appState = fpl__global__AppState;
19820#if defined(FPL_PLATFORM_LINUX)
19821 fpl__LinuxGameControllersState *controllersState = &appState->plinux.controllersState;
19822 fpl__LinuxPollGameControllers(&appState->currentSettings, controllersState,
false);
19825 for (
int i = 0; i <
fplArrayCount(controllersState->controllers); ++i) {
19826 outStates->
deviceStates[i] = controllersState->controllers[i].state;
19840 FPL__CheckArgumentNull(signal,
false);
19842 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' is already valid", signal);
19845 int linuxEventHandle = eventfd((initialValue ==
fplSignalValue_Set) ? 1 : 0, EFD_CLOEXEC);
19846 if (linuxEventHandle == -1) {
19847 FPL__ERROR(FPL__MODULE_THREADING,
"Failed initializing signal '%p'", signal);
19864 FPL__CheckArgumentNull(signal,
false);
19866 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' is not valid", signal);
19872 read(ev, &value,
sizeof(value));
19878 struct timeval t = { 0, timeout * 1000 };
19879 int selectResult = select(1, &f, NULL, NULL, &t);
19880 if (selectResult == 0) {
19883 }
else if (selectResult == -1) {
19893 FPL__CheckArgumentNull(signals,
false);
19894 FPL__CheckArgumentMax(maxCount, FPL_MAX_SIGNAL_COUNT,
false);
19895 const size_t actualStride = stride > 0 ? stride :
sizeof(
fplSignalHandle *);
19896 for (uint32_t index = 0; index < maxCount; ++index) {
19899 FPL__ERROR(FPL__MODULE_THREADING,
"Signal for index '%d' are not allowed to be null", index);
19903 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' for index '%d' is not valid", signal, index);
19908 int e = epoll_create(maxCount);
19914 struct epoll_event events[FPL_MAX_SIGNAL_COUNT];
19915 for (
int index = 0; index < maxCount; index++) {
19916 events[index].events = EPOLLIN;
19917 events[index].data.u32 = index;
19919 int x = epoll_ctl(e, EPOLL_CTL_ADD, signal->
internalHandle.linuxEventHandle, events + index);
19925 int eventsResult = -1;
19926 int waiting = minCount;
19927 struct epoll_event revent[FPL_MAX_SIGNAL_COUNT];
19928 while (waiting > 0) {
19929 int ret = epoll_wait(e, revent, waiting, t);
19931 if (minCount == maxCount) {
19936 for (
int eventIndex = 0; eventIndex < ret; eventIndex++) {
19937 uint32_t signalIndex = revent[eventIndex].data.u32;
19939 epoll_ctl(e, EPOLL_CTL_DEL, signal->
internalHandle.linuxEventHandle, NULL);
19941 eventsResult = revent[0].data.u32;
19945 bool result = (waiting == 0);
19950 bool result = fpl__LinuxSignalWaitForMultiple(signals, count, count, stride, timeout);
19955 bool result = fpl__LinuxSignalWaitForMultiple(signals, 1, count, stride, timeout);
19960 FPL__CheckArgumentNull(signal,
false);
19962 FPL__ERROR(FPL__MODULE_THREADING,
"Signal '%p' is not valid", signal);
19965 uint64_t value = 1;
19966 int writtenBytes = write(signal->
internalHandle.linuxEventHandle, &value,
sizeof(value));
19967 bool result = writtenBytes ==
sizeof(value);
19975 FPL__CheckArgumentNull(outInfos,
false);
19976 bool result =
false;
19986fpl_internal size_t fpl__LinuxLocaleToISO639(
const char *source,
char *target,
const size_t maxTargetLen) {
19994 }
else if (*p ==
'.') {
20009 char *locale = setlocale(LC_CTYPE, NULL);
20010 size_t result = fpl__LinuxLocaleToISO639(locale, buffer, maxBufferLen);
20016 char *locale = setlocale(LC_ALL, NULL);
20017 size_t result = fpl__LinuxLocaleToISO639(locale, buffer, maxBufferLen);
20023 char *locale = setlocale(LC_ALL, NULL);
20024 size_t result = fpl__LinuxLocaleToISO639(locale, buffer, maxBufferLen);
20035#if defined(FPL_PLATFORM_UNIX)
20036fpl_internal void fpl__UnixReleasePlatform(fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
20039fpl_internal bool fpl__UnixInitPlatform(
const fplInitFlags initFlags,
const fplSettings *initSettings, fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
20075#if !defined(FPL__VIDEO_BACKENDS_IMPLEMENTED) && defined(FPL__ENABLE_VIDEO)
20076# define FPL__VIDEO_BACKENDS_IMPLEMENTED
20083typedef struct fpl__VideoData {
20084#if defined(FPL__ENABLE_VIDEO_SOFTWARE)
20085 fplVideoBackBuffer backbuffer;
20090struct fpl__VideoBackend;
20092#define FPL__FUNC_VIDEO_BACKEND_LOAD(name) bool name(const fpl__PlatformAppState *appState, struct fpl__VideoBackend *backend)
20093typedef FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__func_VideoBackendLoad);
20095#define FPL__FUNC_VIDEO_BACKEND_UNLOAD(name) void name(const fpl__PlatformAppState *appState, struct fpl__VideoBackend *backend)
20096typedef FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__func_VideoBackendUnload);
20098#define FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(name) bool name(const fpl__PlatformAppState *appState, const fplVideoSettings *videoSettings, fpl__PlatformWindowState *windowState, struct fpl__VideoBackend *backend)
20099typedef FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__func_VideoBackendPrepareWindow);
20101#define FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(name) bool name(const fpl__PlatformAppState *appState, const fplVideoSettings *videoSettings, fpl__PlatformWindowState *windowState, struct fpl__VideoBackend *backend)
20102typedef FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(fpl__func_VideoBackendFinalizeWindow);
20104#define FPL__FUNC_VIDEO_BACKEND_DESTROYEDWINDOW(name) void name(const fpl__PlatformAppState *appState, struct fpl__VideoBackend *backend)
20105typedef FPL__FUNC_VIDEO_BACKEND_DESTROYEDWINDOW(fpl__func_VideoBackendDestroyedWindow);
20107#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)
20108typedef FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__func_VideoBackendInitialize);
20110#define FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(name) void name(const fpl__PlatformAppState *appState, const fpl__PlatformWindowState *windowState, struct fpl__VideoBackend *backend)
20111typedef FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__func_VideoBackendShutdown);
20113#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)
20114typedef FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__func_VideoBackendPresent);
20116#define FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(name) const void *name(const struct fpl__VideoBackend *backend, const char *procName)
20117typedef FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__func_VideoBackendGetProcedure);
20119#define FPL__FUNC_VIDEO_BACKEND_GETREQUIREMENTS(name) bool name(fplVideoRequirements *requirements)
20120typedef FPL__FUNC_VIDEO_BACKEND_GETREQUIREMENTS(fpl__func_VideoBackendGetRequirements);
20122typedef struct fpl__VideoContext {
20123 fpl__func_VideoBackendLoad *loadFunc;
20124 fpl__func_VideoBackendUnload *unloadFunc;
20125 fpl__func_VideoBackendInitialize *initializeFunc;
20126 fpl__func_VideoBackendShutdown *shutdownFunc;
20127 fpl__func_VideoBackendPrepareWindow *prepareWindowFunc;
20128 fpl__func_VideoBackendFinalizeWindow *finalizeWindowFunc;
20129 fpl__func_VideoBackendDestroyedWindow *destroyedWindowFunc;
20130 fpl__func_VideoBackendPresent *presentFunc;
20131 fpl__func_VideoBackendGetProcedure *getProcedureFunc;
20132 fpl__func_VideoBackendGetRequirements *getRequirementsFunc;
20134} fpl__VideoContext;
20137fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_Load_Stub) {
return(
true); }
20138fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_Unload_Stub) {}
20139fpl_internal FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__VideoBackend_PrepareWindow_Stub) {
return(
true); }
20140fpl_internal FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(fpl__VideoBackend_FinalizeWindow_Stub) {
return(
true); }
20141fpl_internal FPL__FUNC_VIDEO_BACKEND_DESTROYEDWINDOW(fpl__VideoBackend_DestroyedWindow_Stub) {}
20142fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_Initialize_Stub) {
return(
false); }
20143fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_Shutdown_Stub) {}
20144fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_Present_Stub) {}
20145fpl_internal FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__VideoBackend_GetProcedure_Stub) {
return(
fpl_null); }
20146fpl_internal FPL__FUNC_VIDEO_BACKEND_GETREQUIREMENTS(fpl__VideoBackend_GetRequirements_Stub) {
return(
false); }
20148fpl_internal fpl__VideoContext fpl__StubVideoContext(
void) {
20150 result.loadFunc = fpl__VideoBackend_Load_Stub;
20151 result.unloadFunc = fpl__VideoBackend_Unload_Stub;
20152 result.prepareWindowFunc = fpl__VideoBackend_PrepareWindow_Stub;
20153 result.finalizeWindowFunc = fpl__VideoBackend_FinalizeWindow_Stub;
20154 result.destroyedWindowFunc = fpl__VideoBackend_DestroyedWindow_Stub;
20155 result.initializeFunc = fpl__VideoBackend_Initialize_Stub;
20156 result.shutdownFunc = fpl__VideoBackend_Shutdown_Stub;
20157 result.presentFunc = fpl__VideoBackend_Present_Stub;
20158 result.getProcedureFunc = fpl__VideoBackend_GetProcedure_Stub;
20159 result.getRequirementsFunc = fpl__VideoBackend_GetRequirements_Stub;
20164#define FPL__VIDEOBACKEND_MAGIC (uint64_t)0x564944454f535953
20166typedef struct fpl__VideoBackend {
20168 fplVideoSurface surface;
20169} fpl__VideoBackend;
20176#if defined(FPL__ENABLE_VIDEO_OPENGL) && defined(FPL_PLATFORM_WINDOWS)
20178#define FPL__GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
20179#define FPL__GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
20180#define FPL__GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
20181#define FPL__GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008
20182#define FPL__GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
20183#define FPL__GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
20185#define FPL__WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
20186#define FPL__WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
20187#define FPL__WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
20188#define FPL__WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
20189#define FPL__WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
20190#define FPL__WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
20191#define FPL__WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
20192#define FPL__WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
20193#define FPL__WGL_CONTEXT_FLAGS_ARB 0x2094
20194#define FPL__WGL_DRAW_TO_WINDOW_ARB 0x2001
20195#define FPL__WGL_ACCELERATION_ARB 0x2003
20196#define FPL__WGL_SWAP_METHOD_ARB 0x2007
20197#define FPL__WGL_SUPPORT_OPENGL_ARB 0x2010
20198#define FPL__WGL_DOUBLE_BUFFER_ARB 0x2011
20199#define FPL__WGL_PIXEL_TYPE_ARB 0x2013
20200#define FPL__WGL_COLOR_BITS_ARB 0x2014
20201#define FPL__WGL_ALPHA_BITS_ARB 0x201B
20202#define FPL__WGL_DEPTH_BITS_ARB 0x2022
20203#define FPL__WGL_STENCIL_BITS_ARB 0x2023
20204#define FPL__WGL_FULL_ACCELERATION_ARB 0x2027
20205#define FPL__WGL_SWAP_EXCHANGE_ARB 0x2028
20206#define FPL__WGL_TYPE_RGBA_ARB 0x202B
20207#define FPL__WGL_SAMPLE_BUFFERS_ARB 0x2041
20208#define FPL__WGL_SAMPLES_ARB 0x2042
20210#define FPL__FUNC_WGL_wglMakeCurrent(name) BOOL WINAPI name(HDC deviceContext, HGLRC renderingContext)
20211typedef FPL__FUNC_WGL_wglMakeCurrent(fpl__win32_func_wglMakeCurrent);
20212#define FPL__FUNC_WGL_wglGetProcAddress(name) PROC WINAPI name(LPCSTR procedure)
20213typedef FPL__FUNC_WGL_wglGetProcAddress(fpl__win32_func_wglGetProcAddress);
20214#define FPL__FUNC_WGL_wglDeleteContext(name) BOOL WINAPI name(HGLRC renderingContext)
20215typedef FPL__FUNC_WGL_wglDeleteContext(fpl__win32_func_wglDeleteContext);
20216#define FPL__FUNC_WGL_wglCreateContext(name) HGLRC WINAPI name(HDC deviceContext)
20217typedef FPL__FUNC_WGL_wglCreateContext(fpl__win32_func_wglCreateContext);
20219#define FPL__FUNC_WGL_wglChoosePixelFormatARB(name) BOOL WINAPI name(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats)
20220typedef FPL__FUNC_WGL_wglChoosePixelFormatARB(fpl__win32_func_wglChoosePixelFormatARB);
20221#define FPL__FUNC_WGL_wglCreateContextAttribsARB(name) HGLRC WINAPI name(HDC hDC, HGLRC hShareContext, const int *attribList)
20222typedef FPL__FUNC_WGL_wglCreateContextAttribsARB(fpl__win32_func_wglCreateContextAttribsARB);
20223#define FPL__FUNC_WGL_wglSwapIntervalEXT(name) BOOL WINAPI name(int interval)
20224typedef FPL__FUNC_WGL_wglSwapIntervalEXT(fpl__win32_func_wglSwapIntervalEXT);
20226typedef struct fpl__Win32OpenGLApi {
20227 HMODULE openglLibrary;
20228 fpl__win32_func_wglMakeCurrent *wglMakeCurrent;
20229 fpl__win32_func_wglGetProcAddress *wglGetProcAddress;
20230 fpl__win32_func_wglDeleteContext *wglDeleteContext;
20231 fpl__win32_func_wglCreateContext *wglCreateContext;
20232 fpl__win32_func_wglChoosePixelFormatARB *wglChoosePixelFormatARB;
20233 fpl__win32_func_wglCreateContextAttribsARB *wglCreateContextAttribsARB;
20234 fpl__win32_func_wglSwapIntervalEXT *wglSwapIntervalEXT;
20235} fpl__Win32OpenGLApi;
20237fpl_internal void fpl__UnloadWin32OpenGLApi(fpl__Win32OpenGLApi *api) {
20238 if (api->openglLibrary !=
fpl_null) {
20239 FreeLibrary(api->openglLibrary);
20244fpl_internal bool fpl__LoadWin32OpenGLApi(fpl__Win32OpenGLApi *api,
const char *libraryName) {
20246 libraryName =
"opengl32.dll";
20248 bool result =
false;
20252 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName);
20253 api->openglLibrary = openglLibrary;
20254 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName, api, fpl__win32_func_wglGetProcAddress, wglGetProcAddress);
20255 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName, api, fpl__win32_func_wglCreateContext, wglCreateContext);
20256 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName, api, fpl__win32_func_wglDeleteContext, wglDeleteContext);
20257 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_VIDEO_OPENGL, openglLibrary, libraryName, api, fpl__win32_func_wglMakeCurrent, wglMakeCurrent);
20261 fpl__UnloadWin32OpenGLApi(api);
20266typedef struct fpl__VideoBackendWin32OpenGL {
20267 fpl__VideoBackend base;
20268 fpl__Win32OpenGLApi api;
20269 HGLRC renderingContext;
20270} fpl__VideoBackendWin32OpenGL;
20272fpl_internal FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__VideoBackend_Win32OpenGL_GetProcedure) {
20273 const fpl__VideoBackendWin32OpenGL *nativeBackend = (
const fpl__VideoBackendWin32OpenGL *)backend;
20274 void *result = (
void *)GetProcAddress(nativeBackend->api.openglLibrary, procName);
20278fpl_internal LRESULT CALLBACK fpl__Win32OpenGLTemporaryWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
20279 fpl__Win32AppState *appState = &fpl__global__AppState->win32;
20280 const fpl__Win32Api *wapi = &appState->winApi;
20283 wapi->user.PostQuitMessage(0);
20286 return wapi->user.DefWindowProcW(hWnd, message, wParam, lParam);
20291fpl_internal FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__VideoBackend_Win32OpenGL_PrepareWindow) {
20292 const fpl__Win32AppState *nativeAppState = &appState->win32;
20293 const fpl__Win32Api *wapi = &nativeAppState->winApi;
20294 fpl__Win32WindowState *nativeWindowState = &windowState->win32;
20296 nativeWindowState->pixelFormat = 0;
20299 fpl__Win32OpenGLApi glApi;
20300 if (fpl__LoadWin32OpenGLApi(&glApi, videoSettings->graphics.opengl.libraryFile)) {
20303 windowClass.cbSize =
sizeof(windowClass);
20304 windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
20305 windowClass.lpfnWndProc = fpl__Win32OpenGLTemporaryWindowProc;
20306 windowClass.hInstance = GetModuleHandleW(
fpl_null);
20307 windowClass.hCursor = fpl__win32_LoadCursor(
fpl_null, IDC_ARROW);
20308 windowClass.lpszClassName = L
"FPL_Temp_GL_Window";
20309 if (wapi->user.RegisterClassExW(&windowClass)) {
20311 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);
20312 if (tempWindowHandle !=
fpl_null) {
20314 HDC tempDC = wapi->user.GetDC(tempWindowHandle);
20318 fakePFD.nSize =
sizeof(fakePFD);
20319 fakePFD.nVersion = 1;
20320 fakePFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
20321 fakePFD.iPixelType = PFD_TYPE_RGBA;
20322 fakePFD.cColorBits = 32;
20323 fakePFD.cAlphaBits = 8;
20324 fakePFD.cDepthBits = 24;
20325 int fakePFDID = wapi->gdi.ChoosePixelFormat(tempDC, &fakePFD);
20326 if (fakePFDID != 0) {
20327 if (wapi->gdi.SetPixelFormat(tempDC, fakePFDID, &fakePFD)) {
20329 HGLRC tempCtx = glApi.wglCreateContext(tempDC);
20331 if (glApi.wglMakeCurrent(tempDC, tempCtx)) {
20332 glApi.wglChoosePixelFormatARB = (fpl__win32_func_wglChoosePixelFormatARB *)(
void *)glApi.wglGetProcAddress(
"wglChoosePixelFormatARB");
20333 if (glApi.wglChoosePixelFormatARB !=
fpl_null) {
20334 int multisampleCount = (int)videoSettings->graphics.opengl.multiSamplingCount;
20335 const int pixelAttribs[] = {
20336 FPL__WGL_DRAW_TO_WINDOW_ARB, 1,
20337 FPL__WGL_SUPPORT_OPENGL_ARB, 1,
20338 FPL__WGL_DOUBLE_BUFFER_ARB, 1,
20339 FPL__WGL_PIXEL_TYPE_ARB, FPL__WGL_TYPE_RGBA_ARB,
20340 FPL__WGL_ACCELERATION_ARB, FPL__WGL_FULL_ACCELERATION_ARB,
20341 FPL__WGL_COLOR_BITS_ARB, 32,
20342 FPL__WGL_ALPHA_BITS_ARB, 8,
20343 FPL__WGL_DEPTH_BITS_ARB, 24,
20344 FPL__WGL_STENCIL_BITS_ARB, 8,
20345 FPL__WGL_SAMPLE_BUFFERS_ARB, (multisampleCount > 0) ? 1 : 0,
20346 FPL__WGL_SAMPLES_ARB, multisampleCount,
20351 if (glApi.wglChoosePixelFormatARB(tempDC, pixelAttribs, NULL, 1, &pixelFormat, &numFormats)) {
20352 nativeWindowState->pixelFormat = pixelFormat;
20357 glApi.wglDeleteContext(tempCtx);
20361 wapi->user.ReleaseDC(tempWindowHandle, tempDC);
20363 wapi->user.DestroyWindow(tempWindowHandle);
20366 fpl__UnloadWin32OpenGLApi(&glApi);
20372fpl_internal FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(fpl__VideoBackend_Win32OpenGL_FinalizeWindow) {
20373 const fpl__Win32AppState *nativeAppState = &appState->win32;
20374 const fpl__Win32Api *wapi = &nativeAppState->winApi;
20375 fpl__Win32WindowState *nativeWindowState = &windowState->win32;
20380 HDC deviceContext = nativeWindowState->deviceContext;
20381 HWND handle = nativeWindowState->windowHandle;
20385 bool pixelFormatSet =
false;
20386 if (nativeWindowState->pixelFormat != 0) {
20387 wapi->gdi.DescribePixelFormat(deviceContext, nativeWindowState->pixelFormat,
sizeof(pfd), &pfd);
20388 pixelFormatSet = wapi->gdi.SetPixelFormat(deviceContext, nativeWindowState->pixelFormat, &pfd) == TRUE;
20389 if (!pixelFormatSet) {
20390 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Failed setting Pixelformat '%d' from pre setup", nativeWindowState->pixelFormat);
20393 if (!pixelFormatSet) {
20395 pfd.nSize =
sizeof(pfd);
20397 pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
20398 pfd.iPixelType = PFD_TYPE_RGBA;
20399 pfd.cColorBits = 32;
20400 pfd.cDepthBits = 24;
20401 pfd.cAlphaBits = 8;
20402 pfd.cStencilBits = 8;
20403 pfd.iLayerType = PFD_MAIN_PLANE;
20404 int pixelFormat = wapi->gdi.ChoosePixelFormat(deviceContext, &pfd);
20405 if (!pixelFormat) {
20406 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);
20409 wapi->gdi.DescribePixelFormat(deviceContext, pixelFormat,
sizeof(pfd), &pfd);
20410 if (!wapi->gdi.SetPixelFormat(deviceContext, pixelFormat, &pfd)) {
20411 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);
20418fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_Win32OpenGL_Shutdown) {
20419 const fpl__Win32AppState *nativeAppState = &appState->win32;
20421 fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
20422 const fpl__Win32OpenGLApi *glapi = &nativeBackend->api;
20424 if (nativeBackend->renderingContext) {
20426 glapi->wglDeleteContext(nativeBackend->renderingContext);
20427 nativeBackend->renderingContext =
fpl_null;
20431fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_Win32OpenGL_Initialize) {
20432 const fpl__Win32AppState *nativeAppState = &appState->win32;
20433 const fpl__Win32WindowState *nativeWindowState = &windowState->win32;
20434 const fpl__Win32Api *wapi = &nativeAppState->winApi;
20436 fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
20438 fpl__Win32OpenGLApi *glapi = &nativeBackend->api;
20443 HDC deviceContext = nativeWindowState->deviceContext;
20444 HGLRC legacyRenderingContext = glapi->wglCreateContext(deviceContext);
20445 if (!legacyRenderingContext) {
20446 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Failed creating Legacy OpenGL Rendering Context for DC '%x')", deviceContext);
20449 if (!glapi->wglMakeCurrent(deviceContext, legacyRenderingContext)) {
20450 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"Failed activating Legacy OpenGL Rendering Context for DC '%x' and RC '%x')", deviceContext, legacyRenderingContext);
20451 glapi->wglDeleteContext(legacyRenderingContext);
20456 glapi->wglSwapIntervalEXT = (fpl__win32_func_wglSwapIntervalEXT *)(
void *)glapi->wglGetProcAddress(
"wglSwapIntervalEXT");
20457 glapi->wglChoosePixelFormatARB = (fpl__win32_func_wglChoosePixelFormatARB *)(
void *)glapi->wglGetProcAddress(
"wglChoosePixelFormatARB");
20458 glapi->wglCreateContextAttribsARB = (fpl__win32_func_wglCreateContextAttribsARB *)(
void *)glapi->wglGetProcAddress(
"wglCreateContextAttribsARB");
20463 HGLRC activeRenderingContext;
20466 if (!(videoSettings->graphics.opengl.majorVersion >= 3 && videoSettings->graphics.opengl.minorVersion >= 0)) {
20467 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"You have not specified the 'majorVersion' and 'minorVersion' in the VideoSettings");
20470 if (glapi->wglChoosePixelFormatARB ==
fpl_null) {
20471 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"wglChoosePixelFormatARB is not available, modern OpenGL is not available for your video card");
20474 if (glapi->wglCreateContextAttribsARB ==
fpl_null) {
20475 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"wglCreateContextAttribsARB is not available, modern OpenGL is not available for your video card");
20482 profile = FPL__WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
20484 profile = FPL__WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
20486 FPL__ERROR(FPL__MODULE_VIDEO_OPENGL,
"No opengl compability profile selected, please specific Core fplOpenGLCompabilityFlags_Core or fplOpenGLCompabilityFlags_Compability");
20490 flags = FPL__WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
20493 int contextAttribIndex = 0;
20495 contextAttribList[contextAttribIndex++] = FPL__WGL_CONTEXT_MAJOR_VERSION_ARB;
20496 contextAttribList[contextAttribIndex++] = (int)videoSettings->graphics.opengl.majorVersion;
20497 contextAttribList[contextAttribIndex++] = FPL__WGL_CONTEXT_MINOR_VERSION_ARB;
20498 contextAttribList[contextAttribIndex++] = (int)videoSettings->graphics.opengl.minorVersion;
20499 contextAttribList[contextAttribIndex++] = FPL__WGL_CONTEXT_PROFILE_MASK_ARB;
20500 contextAttribList[contextAttribIndex++] = profile;
20502 contextAttribList[contextAttribIndex++] = FPL__WGL_CONTEXT_FLAGS_ARB;
20503 contextAttribList[contextAttribIndex++] = flags;
20507 HGLRC modernRenderingContext = glapi->wglCreateContextAttribsARB(deviceContext, 0, contextAttribList);
20508 if (modernRenderingContext) {
20509 if (!glapi->wglMakeCurrent(deviceContext, modernRenderingContext)) {
20510 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);
20512 glapi->wglDeleteContext(modernRenderingContext);
20513 modernRenderingContext =
fpl_null;
20516 glapi->wglMakeCurrent(deviceContext, legacyRenderingContext);
20517 activeRenderingContext = legacyRenderingContext;
20520 glapi->wglDeleteContext(legacyRenderingContext);
20521 legacyRenderingContext =
fpl_null;
20522 activeRenderingContext = modernRenderingContext;
20525 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);
20528 glapi->wglMakeCurrent(deviceContext, legacyRenderingContext);
20529 activeRenderingContext = legacyRenderingContext;
20533 glapi->wglMakeCurrent(deviceContext, legacyRenderingContext);
20534 activeRenderingContext = legacyRenderingContext;
20538 nativeBackend->renderingContext = activeRenderingContext;
20541 if (glapi->wglSwapIntervalEXT !=
fpl_null) {
20542 int swapInterval = videoSettings->isVSync ? 1 : 0;
20543 glapi->wglSwapIntervalEXT(swapInterval);
20546 backend->surface.window.win32.deviceContext = deviceContext;
20547 backend->surface.window.win32.windowHandle = nativeWindowState->windowHandle;
20548 backend->surface.opengl.renderingContext = (
void *)activeRenderingContext;
20553fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_Win32OpenGL_Unload) {
20554 fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
20555 fpl__UnloadWin32OpenGLApi(&nativeBackend->api);
20559fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_Win32OpenGL_Load) {
20560 fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
20563 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
20570fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_Win32OpenGL_Present) {
20571 const fpl__Win32AppState *win32AppState = &appState->win32;
20572 const fpl__Win32WindowState *win32WindowState = &appState->window.win32;
20573 const fpl__Win32Api *wapi = &win32AppState->winApi;
20574 const fpl__VideoBackendWin32OpenGL *nativeBackend = (fpl__VideoBackendWin32OpenGL *)backend;
20575 wapi->gdi.SwapBuffers(win32WindowState->deviceContext);
20578fpl_internal fpl__VideoContext fpl__VideoBackend_Win32OpenGL_Construct(
void) {
20579 fpl__VideoContext result = fpl__StubVideoContext();
20580 result.loadFunc = fpl__VideoBackend_Win32OpenGL_Load;
20581 result.unloadFunc = fpl__VideoBackend_Win32OpenGL_Unload;
20582 result.getProcedureFunc = fpl__VideoBackend_Win32OpenGL_GetProcedure;
20583 result.initializeFunc = fpl__VideoBackend_Win32OpenGL_Initialize;
20584 result.shutdownFunc = fpl__VideoBackend_Win32OpenGL_Shutdown;
20585 result.prepareWindowFunc = fpl__VideoBackend_Win32OpenGL_PrepareWindow;
20586 result.finalizeWindowFunc = fpl__VideoBackend_Win32OpenGL_FinalizeWindow;
20587 result.presentFunc = fpl__VideoBackend_Win32OpenGL_Present;
20597#if defined(FPL__ENABLE_VIDEO_OPENGL) && defined(FPL_SUBPLATFORM_X11)
20599typedef uint8_t GLubyte;
20602typedef XID GLXDrawable;
20603typedef XID GLXWindow;
20604typedef void GLXContext_Void;
20605typedef GLXContext_Void *GLXContext;
20606typedef void GLXFBConfig_Void;
20607typedef GLXFBConfig_Void *GLXFBConfig;
20610#define GLX_DOUBLEBUFFER 5
20611#define GLX_RED_SIZE 8
20612#define GLX_GREEN_SIZE 9
20613#define GLX_BLUE_SIZE 10
20614#define GLX_ALPHA_SIZE 11
20615#define GLX_DEPTH_SIZE 12
20616#define GLX_STENCIL_SIZE 13
20617#define GLX_SAMPLE_BUFFERS 0x186a0
20618#define GLX_SAMPLES 0x186a1
20620#define GLX_X_VISUAL_TYPE 0x22
20621#define GLX_TRUE_COLOR 0x8002
20622#define GLX_RGBA_TYPE 0x8014
20625#define FPL__FUNC_GLX_glXQueryVersion(name) Bool name(Display *dpy, int *major, int *minor)
20626typedef FPL__FUNC_GLX_glXQueryVersion(fpl__func_glx_glXQueryVersion);
20627#define FPL__FUNC_GLX_glXChooseVisual(name) XVisualInfo* name(Display *dpy, int screen, int *attribList)
20628typedef FPL__FUNC_GLX_glXChooseVisual(fpl__func_glx_glXChooseVisual);
20629#define FPL__FUNC_GLX_glXCreateContext(name) GLXContext name(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct)
20630typedef FPL__FUNC_GLX_glXCreateContext(fpl__func_glx_glXCreateContext);
20631#define FPL__FUNC_GLX_glXCreateNewContext(name) GLXContext name(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct)
20632typedef FPL__FUNC_GLX_glXCreateNewContext(fpl__func_glx_glXCreateNewContext);
20633#define FPL__FUNC_GLX_glXDestroyContext(name) void name(Display *dpy, GLXContext ctx)
20634typedef FPL__FUNC_GLX_glXDestroyContext(fpl__func_glx_glXDestroyContext);
20635#define FPL__FUNC_GLX_glXMakeCurrent(name) Bool name(Display *dpy, GLXDrawable drawable, GLXContext ctx)
20636typedef FPL__FUNC_GLX_glXMakeCurrent(fpl__func_glx_glXMakeCurrent);
20637#define FPL__FUNC_GLX_glXSwapBuffers(name) void name(Display *dpy, GLXDrawable drawable)
20638typedef FPL__FUNC_GLX_glXSwapBuffers(fpl__func_glx_glXSwapBuffers);
20639#define FPL__FUNC_GLX_glXGetProcAddress(name) void *name(const GLubyte *procName)
20640typedef FPL__FUNC_GLX_glXGetProcAddress(fpl__func_glx_glXGetProcAddress);
20641#define FPL__FUNC_GLX_glXChooseFBConfig(name) GLXFBConfig *name(Display *dpy, int screen, const int *attrib_list, int *nelements)
20642typedef FPL__FUNC_GLX_glXChooseFBConfig(fpl__func_glx_glXChooseFBConfig);
20643#define FPL__FUNC_GLX_glXGetFBConfigs(name) GLXFBConfig *name(Display *dpy, int screen, int *nelements)
20644typedef FPL__FUNC_GLX_glXGetFBConfigs(fpl__func_glx_glXGetFBConfigs);
20645#define FPL__FUNC_GLX_glXGetVisualFromFBConfig(name) XVisualInfo *name(Display *dpy, GLXFBConfig config)
20646typedef FPL__FUNC_GLX_glXGetVisualFromFBConfig(fpl__func_glx_glXGetVisualFromFBConfig);
20647#define FPL__FUNC_GLX_glXGetFBConfigAttrib(name) int name(Display *dpy, GLXFBConfig config, int attribute, int *value)
20648typedef FPL__FUNC_GLX_glXGetFBConfigAttrib(fpl__func_glx_glXGetFBConfigAttrib);
20649#define FPL__FUNC_GLX_glXCreateWindow(name) GLXWindow name(Display *dpy, GLXFBConfig config, Window win, const int *attrib_list)
20650typedef FPL__FUNC_GLX_glXCreateWindow(fpl__func_glx_glXCreateWindow);
20651#define FPL__FUNC_GLX_glXQueryExtension(name) Bool name(Display *dpy, int *errorBase, int *eventBase)
20652typedef FPL__FUNC_GLX_glXQueryExtension(fpl__func_glx_glXQueryExtension);
20653#define FPL__FUNC_GLX_glXQueryExtensionsString(name) const char *name(Display *dpy, int screen)
20654typedef FPL__FUNC_GLX_glXQueryExtensionsString(fpl__func_glx_glXQueryExtensionsString);
20657#define FPL__FUNC_GLX_glXCreateContextAttribsARB(name) GLXContext name(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list)
20658typedef FPL__FUNC_GLX_glXCreateContextAttribsARB(fpl__func_glx_glXCreateContextAttribsARB);
20660#define FPL__GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
20661#define FPL__GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
20662#define FPL__GLX_CONTEXT_FLAGS_ARB 0x2094
20663#define FPL__GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
20665#define FPL__GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
20666#define FPL__GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
20667#define FPL__GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
20668#define FPL__GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
20670typedef struct fpl__X11VideoOpenGLApi {
20672 fpl__func_glx_glXQueryVersion *glXQueryVersion;
20673 fpl__func_glx_glXChooseVisual *glXChooseVisual;
20674 fpl__func_glx_glXCreateContext *glXCreateContext;
20675 fpl__func_glx_glXDestroyContext *glXDestroyContext;
20676 fpl__func_glx_glXCreateNewContext *glXCreateNewContext;
20677 fpl__func_glx_glXMakeCurrent *glXMakeCurrent;
20678 fpl__func_glx_glXSwapBuffers *glXSwapBuffers;
20679 fpl__func_glx_glXGetProcAddress *glXGetProcAddress;
20680 fpl__func_glx_glXChooseFBConfig *glXChooseFBConfig;
20681 fpl__func_glx_glXGetFBConfigs *glXGetFBConfigs;
20682 fpl__func_glx_glXGetVisualFromFBConfig *glXGetVisualFromFBConfig;
20683 fpl__func_glx_glXGetFBConfigAttrib *glXGetFBConfigAttrib;
20684 fpl__func_glx_glXCreateWindow *glXCreateWindow;
20685 fpl__func_glx_glXQueryExtension *glXQueryExtension;
20686 fpl__func_glx_glXQueryExtensionsString *glXQueryExtensionsString;
20687 fpl__func_glx_glXCreateContextAttribsARB *glXCreateContextAttribsARB;
20688} fpl__X11VideoOpenGLApi;
20690fpl_internal void fpl__UnloadX11OpenGLApi(fpl__X11VideoOpenGLApi *api) {
20692 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Unload Api (Library '%p')", api->libHandle);
20693 dlclose(api->libHandle);
20698fpl_internal bool fpl__LoadX11OpenGLApi(fpl__X11VideoOpenGLApi *api,
const char *libraryName) {
20699 uint32_t libFileCount = 0;
20701 const char *libFileNames[4];
20703 libFileNames[libFileCount++] = libraryName;
20705 libFileNames[libFileCount++] =
"libGL.so.1";
20706 libFileNames[libFileCount++] =
"libGL.so";
20709 bool result =
false;
20710 for (uint32_t index = 0; index < libFileCount; ++index) {
20711 const char *libName = libFileNames[index];
20712 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Load GLX Api from Library: %s", libName);
20715 FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_GLX, libHandle, libName);
20716 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXQueryVersion, glXQueryVersion);
20717 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXChooseVisual, glXChooseVisual);
20718 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXCreateContext, glXCreateContext);
20719 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXDestroyContext, glXDestroyContext);
20720 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXCreateNewContext, glXCreateNewContext);
20721 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXMakeCurrent, glXMakeCurrent);
20722 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXSwapBuffers, glXSwapBuffers);
20723 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXGetProcAddress, glXGetProcAddress);
20724 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXChooseFBConfig, glXChooseFBConfig);
20725 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXGetFBConfigs, glXGetFBConfigs);
20726 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXGetVisualFromFBConfig, glXGetVisualFromFBConfig);
20727 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXGetFBConfigAttrib, glXGetFBConfigAttrib);
20728 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXCreateWindow, glXCreateWindow);
20729 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXQueryExtension, glXQueryExtension);
20730 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_GLX, libHandle, libName, api, fpl__func_glx_glXQueryExtensionsString, glXQueryExtensionsString);
20731 api->libHandle = libHandle;
20735 FPL_LOG_DEBUG(FPL__MODULE_GLX, ,
"Successfully loaded GLX Api from Library '%s'", libName);
20738 fpl__UnloadX11OpenGLApi(api);
20743typedef struct fpl__VideoBackendX11OpenGL {
20744 fpl__VideoBackend base;
20745 fpl__X11VideoOpenGLApi api;
20746 GLXFBConfig fbConfig;
20747 XVisualInfo *visualInfo;
20748 GLXContext context;
20749 bool isActiveContext;
20750} fpl__VideoBackendX11OpenGL;
20752fpl_internal FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__VideoBackend_X11OpenGL_GetProcedure) {
20753 const fpl__VideoBackendX11OpenGL *nativeBackend = (
const fpl__VideoBackendX11OpenGL *)backend;
20754 void *result = dlsym(nativeBackend->api.libHandle, procName);
20758fpl_internal FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__VideoBackend_X11OpenGL_PrepareWindow) {
20759 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
20760 const fpl__X11Api *x11Api = &nativeAppState->api;
20762 fpl__X11WindowState *nativeWindowState = &windowState->x11;
20763 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
20764 fpl__X11VideoOpenGLApi *glApi = &nativeBackend->api;
20766 Display *display = nativeWindowState->display;
20767 Window window = nativeWindowState->window;
20768 int screen = nativeWindowState->screen;
20770 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Query GLX version for display '%p'", display);
20771 int major = 0, minor = 0;
20772 if (!glApi->glXQueryVersion(display, &major, &minor)) {
20773 FPL_LOG_ERROR(FPL__MODULE_GLX,
"Failed querying GLX version for display '%p'", display);
20776 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully queried GLX version for display '%p': %d.%d", display, major, minor);
20780 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Query OpenGL extension on display '%p'", display);
20782 FPL__ERROR(FPL__MODULE_GLX,
"OpenGL GLX Extension is not supported by the active display '%p'", display);
20786 const char *extensionString = glApi->glXQueryExtensionsString(display, screen);
20787 if (extensionString !=
fpl_null) {
20788 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"OpenGL GLX extensions: %s", extensionString);
20791 bool isModern = major > 1 || (major == 1 && minor >= 3);
20796 attr[attrIndex++] = GLX_X_VISUAL_TYPE;
20797 attr[attrIndex++] = GLX_TRUE_COLOR;
20800 attr[attrIndex++] = GLX_RGBA;
20801 attr[attrIndex++] = True;
20804 attr[attrIndex++] = GLX_DOUBLEBUFFER;
20805 attr[attrIndex++] = True;
20807 attr[attrIndex++] = GLX_RED_SIZE;
20808 attr[attrIndex++] = 8;
20810 attr[attrIndex++] = GLX_GREEN_SIZE;
20811 attr[attrIndex++] = 8;
20813 attr[attrIndex++] = GLX_BLUE_SIZE;
20814 attr[attrIndex++] = 8;
20816 attr[attrIndex++] = GLX_ALPHA_SIZE;
20817 attr[attrIndex++] = 8;
20819 attr[attrIndex++] = GLX_DEPTH_SIZE;
20820 attr[attrIndex++] = 24;
20822 attr[attrIndex++] = GLX_STENCIL_SIZE;
20823 attr[attrIndex++] = 8;
20826 attr[attrIndex++] = GLX_SAMPLE_BUFFERS;
20827 attr[attrIndex++] = 1;
20829 attr[attrIndex++] = GLX_SAMPLES;
20833 attr[attrIndex] = 0;
20837 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Get framebuffer configuration from display '%p' and screen '%d'", display, screen);
20838 int configCount = 0;
20839 GLXFBConfig *configs = glApi->glXChooseFBConfig(display, screen, attr, &configCount);
20840 if (configs ==
fpl_null || !configCount) {
20841 FPL__ERROR(FPL__MODULE_GLX,
"No framebuffer configuration from display '%p' and screen '%d' found!", display, screen);
20842 nativeBackend->fbConfig =
fpl_null;
20845 nativeBackend->fbConfig = configs[0];
20846 nativeBackend->visualInfo =
fpl_null;
20847 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully got framebuffer configuration from display '%p' and screen '%d': %p", display, screen, nativeBackend->fbConfig);
20849 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Release %d framebuffer configurations", configCount);
20850 x11Api->XFree(configs);
20853 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Choose visual from display '%p' and screen '%d'", display, screen);
20854 XVisualInfo *visualInfo = glApi->glXChooseVisual(display, screen, attr);
20856 FPL__ERROR(FPL__MODULE_GLX,
"No visual info for display '%p' and screen '%d' found!", display, screen);
20859 nativeBackend->visualInfo = visualInfo;
20860 nativeBackend->fbConfig =
fpl_null;
20861 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully got visual info from display '%p' and screen '%d': %p", display, screen, nativeBackend->visualInfo);
20864 if (nativeBackend->fbConfig !=
fpl_null) {
20865 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Get visual info from display '%p' and frame buffer config '%p'", display, nativeBackend->fbConfig);
20866 XVisualInfo *visualInfo = glApi->glXGetVisualFromFBConfig(display, nativeBackend->fbConfig);
20868 FPL__ERROR(FPL__MODULE_GLX,
"Failed getting visual info from display '%p' and frame buffer config '%p'", display, nativeBackend->fbConfig);
20871 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully got visual info from display '%p' and frame buffer config '%p': %p", display, nativeBackend->fbConfig, visualInfo);
20873 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using visual: %p", visualInfo->visual);
20874 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using color depth: %d", visualInfo->depth);
20876 nativeWindowState->visual = visualInfo->visual;
20877 nativeWindowState->colorDepth = visualInfo->depth;
20879 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Release visual info '%p'", visualInfo);
20880 x11Api->XFree(visualInfo);
20881 }
else if (nativeBackend->visualInfo !=
fpl_null) {
20882 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using existing visual info: %p", nativeBackend->visualInfo);
20883 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using visual: %p", nativeBackend->visualInfo->visual);
20884 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Using color depth: %d", nativeBackend->visualInfo->depth);
20885 nativeWindowState->visual = nativeBackend->visualInfo->visual;
20886 nativeWindowState->colorDepth = nativeBackend->visualInfo->depth;
20888 FPL__ERROR(FPL__MODULE_GLX,
"No visual info or frame buffer config defined!");
20895fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_X11OpenGL_Shutdown) {
20896 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
20897 const fpl__X11Api *x11Api = &nativeAppState->api;
20898 const fpl__X11WindowState *nativeWindowState = &windowState->x11;
20900 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
20901 fpl__X11VideoOpenGLApi *glApi = &nativeBackend->api;
20903 if (nativeBackend->isActiveContext) {
20904 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Deactivate GLX rendering context for display '%p'", nativeWindowState->display);
20905 glApi->glXMakeCurrent(nativeWindowState->display, 0,
fpl_null);
20906 nativeBackend->isActiveContext =
false;
20909 if (nativeBackend->context !=
fpl_null) {
20910 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Destroy GLX rendering context '%p' for display '%p'", nativeBackend->context, nativeWindowState->display);
20911 glApi->glXDestroyContext(nativeWindowState->display, nativeBackend->context);
20912 nativeBackend->context =
fpl_null;
20915 if (nativeBackend->visualInfo !=
fpl_null) {
20916 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Destroy visual info '%p' (Fallback)", nativeBackend->visualInfo);
20917 x11Api->XFree(nativeBackend->visualInfo);
20918 nativeBackend->visualInfo =
fpl_null;
20922fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_X11OpenGL_Initialize) {
20923 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
20924 const fpl__X11Api *x11Api = &nativeAppState->api;
20925 const fpl__X11WindowState *nativeWindowState = &windowState->x11;
20927 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
20928 fpl__X11VideoOpenGLApi *glApi = &nativeBackend->api;
20930 Display *display = nativeWindowState->display;
20931 Window window = nativeWindowState->window;
20936 GLXContext legacyRenderingContext;
20937 if (nativeBackend->fbConfig !=
fpl_null) {
20938 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Create GLX legacy rendering context on display '%p' and frame buffer config '%p'", display, nativeBackend->fbConfig);
20939 legacyRenderingContext = glApi->glXCreateNewContext(display, nativeBackend->fbConfig, GLX_RGBA_TYPE,
fpl_null, 1);
20940 if (!legacyRenderingContext) {
20941 FPL__ERROR(FPL__MODULE_GLX,
"Failed creating GLX legacy rendering context on display '%p' and frame buffer config '%p'", display, nativeBackend->fbConfig);
20942 goto failed_x11_glx;
20944 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);
20945 }
else if (nativeBackend->visualInfo !=
fpl_null) {
20946 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Create GLX legacy rendering context on display '%p' and visual info '%p'", display, nativeBackend->visualInfo);
20947 legacyRenderingContext = glApi->glXCreateContext(display, nativeBackend->visualInfo,
fpl_null, 1);
20948 if (!legacyRenderingContext) {
20949 FPL__ERROR(FPL__MODULE_GLX,
"Failed creating GLX legacy rendering context on display '%p' and visual info '%p'", display, nativeBackend->visualInfo);
20950 goto failed_x11_glx;
20953 FPL__ERROR(FPL__MODULE_GLX,
"No visual info or frame buffer config defined!");
20954 goto failed_x11_glx;
20960 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Activate GLX legacy rendering context '%p' on display '%p' and window '%d'", legacyRenderingContext, display, (
int)window);
20961 if (!glApi->glXMakeCurrent(display, window, legacyRenderingContext)) {
20962 FPL__ERROR(FPL__MODULE_GLX,
"Failed activating GLX legacy rendering context '%p' on display '%p' and window '%d'", legacyRenderingContext, display, (
int)window);
20963 goto failed_x11_glx;
20965 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Successfully activated GLX legacy rendering context '%p' on display '%p' and window '%d'", legacyRenderingContext, display, (
int)window);
20971 glApi->glXCreateContextAttribsARB = (fpl__func_glx_glXCreateContextAttribsARB *)glApi->glXGetProcAddress((
const GLubyte *)
"glXCreateContextAttribsARB");
20974 glApi->glXMakeCurrent(display, 0,
fpl_null);
20976 GLXContext activeRenderingContext;
20981 FPL__ERROR(FPL__MODULE_GLX,
"You have not specified the 'majorVersion' and 'minorVersion' in the VideoSettings");
20982 goto failed_x11_glx;
20985 if (glApi->glXCreateContextAttribsARB ==
fpl_null) {
20986 FPL__ERROR(FPL__MODULE_GLX,
"glXCreateContextAttribsARB is not available, modern OpenGL is not available for your video card");
20987 goto failed_x11_glx;
20993 profile = FPL__GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
20995 profile = FPL__GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
20997 FPL__ERROR(FPL__MODULE_GLX,
"No opengl compability profile selected, please specific Core OpenGLCompabilityFlags_Core or OpenGLCompabilityFlags_Compability");
20998 goto failed_x11_glx;
21001 flags = FPL__GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
21004 int contextAttribIndex = 0;
21006 contextAttribList[contextAttribIndex++] = FPL__GLX_CONTEXT_MAJOR_VERSION_ARB;
21008 contextAttribList[contextAttribIndex++] = FPL__GLX_CONTEXT_MINOR_VERSION_ARB;
21010 contextAttribList[contextAttribIndex++] = FPL__GLX_CONTEXT_PROFILE_MASK_ARB;
21011 contextAttribList[contextAttribIndex++] = profile;
21013 contextAttribList[contextAttribIndex++] = FPL__GLX_CONTEXT_FLAGS_ARB;
21014 contextAttribList[contextAttribIndex++] = flags;
21016 contextAttribList[contextAttribIndex] = 0;
21018 GLXContext modernRenderingContext = glApi->glXCreateContextAttribsARB(display, nativeBackend->fbConfig,
fpl_null, True, contextAttribList);
21019 if (!modernRenderingContext) {
21023 glApi->glXMakeCurrent(display, window, legacyRenderingContext);
21024 activeRenderingContext = legacyRenderingContext;
21026 if (!glApi->glXMakeCurrent(display, window, modernRenderingContext)) {
21030 glApi->glXDestroyContext(display, modernRenderingContext);
21033 glApi->glXMakeCurrent(display, window, legacyRenderingContext);
21034 activeRenderingContext = legacyRenderingContext;
21037 glApi->glXDestroyContext(display, legacyRenderingContext);
21038 legacyRenderingContext =
fpl_null;
21039 activeRenderingContext = modernRenderingContext;
21044 glApi->glXMakeCurrent(display, window, legacyRenderingContext);
21045 activeRenderingContext = legacyRenderingContext;
21051 nativeBackend->context = activeRenderingContext;
21052 nativeBackend->isActiveContext =
true;
21054 backend->surface.window.x11.display = display;
21055 backend->surface.window.x11.window = window;
21056 backend->surface.window.x11.visual = nativeWindowState->visual;
21057 backend->surface.window.x11.screen = nativeWindowState->screen;
21058 backend->surface.opengl.renderingContext = (
void *)activeRenderingContext;
21068 if (nativeBackend->visualInfo !=
fpl_null) {
21070 FPL_LOG_DEBUG(FPL__MODULE_GLX,
"Destroy visual info '%p'", nativeBackend->visualInfo);
21071 x11Api->XFree(nativeBackend->visualInfo);
21072 nativeBackend->visualInfo =
fpl_null;
21076 if (legacyRenderingContext) {
21077 glApi->glXDestroyContext(display, legacyRenderingContext);
21079 fpl__VideoBackend_X11OpenGL_Shutdown(appState, windowState, backend);
21085fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_X11OpenGL_Unload) {
21086 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
21087 fpl__UnloadX11OpenGLApi(&nativeBackend->api);
21091fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_X11OpenGL_Load) {
21092 fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
21095 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
21102fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_X11OpenGL_Present) {
21103 const fpl__VideoBackendX11OpenGL *nativeBackend = (fpl__VideoBackendX11OpenGL *)backend;
21104 const fpl__X11WindowState *x11WinState = &appState->window.x11;
21105 const fpl__X11VideoOpenGLApi *glApi = &nativeBackend->api;
21106 glApi->glXSwapBuffers(x11WinState->display, x11WinState->window);
21109fpl_internal fpl__VideoContext fpl__VideoBackend_X11OpenGL_Construct(
void) {
21110 fpl__VideoContext result = fpl__StubVideoContext();
21111 result.loadFunc = fpl__VideoBackend_X11OpenGL_Load;
21112 result.unloadFunc = fpl__VideoBackend_X11OpenGL_Unload;
21113 result.getProcedureFunc = fpl__VideoBackend_X11OpenGL_GetProcedure;
21114 result.initializeFunc = fpl__VideoBackend_X11OpenGL_Initialize;
21115 result.shutdownFunc = fpl__VideoBackend_X11OpenGL_Shutdown;
21116 result.prepareWindowFunc = fpl__VideoBackend_X11OpenGL_PrepareWindow;
21117 result.presentFunc = fpl__VideoBackend_X11OpenGL_Present;
21127#if defined(FPL__ENABLE_VIDEO_SOFTWARE) && defined(FPL_SUBPLATFORM_X11)
21128typedef struct fpl__VideoBackendX11Software {
21129 fpl__VideoBackend base;
21130 GC graphicsContext;
21132} fpl__VideoBackendX11Software;
21134fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_X11Software_Shutdown) {
21135 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
21136 const fpl__X11Api *x11Api = &nativeAppState->api;
21137 const fpl__X11WindowState *nativeWindowState = &windowState->x11;
21139 fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
21141 if (nativeBackend->buffer !=
fpl_null) {
21146 if (nativeBackend->graphicsContext !=
fpl_null) {
21147 nativeBackend->graphicsContext =
fpl_null;
21151fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_X11Software_Initialize) {
21152 const fpl__X11SubplatformState *nativeAppState = &appState->x11;
21153 const fpl__X11Api *x11Api = &nativeAppState->api;
21154 const fpl__X11WindowState *nativeWindowState = &windowState->x11;
21156 fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
21161 nativeBackend->graphicsContext = x11Api->XCreateGC(nativeWindowState->display, nativeWindowState->window, 0, 0);
21162 if (nativeBackend->graphicsContext ==
fpl_null) {
21166 nativeBackend->buffer = x11Api->XCreateImage(nativeWindowState->display, nativeWindowState->visual, 24, ZPixmap, 0, (
char *)backbuffer->
pixels, backbuffer->
width, backbuffer->
height, 32, (
int)backbuffer->
lineWidth);
21167 if (nativeBackend->buffer ==
fpl_null) {
21168 fpl__VideoBackend_X11Software_Shutdown(appState, windowState, backend);
21173 x11Api->XPutImage(nativeWindowState->display, nativeWindowState->window, nativeBackend->graphicsContext, nativeBackend->buffer, 0, 0, 0, 0, backbuffer->
width, backbuffer->
height);
21174 x11Api->XSync(nativeWindowState->display, False);
21176 backend->surface.window.x11.display = nativeWindowState->display;
21177 backend->surface.window.x11.window = nativeWindowState->window;
21178 backend->surface.window.x11.visual = nativeWindowState->visual;
21179 backend->surface.window.x11.screen = nativeWindowState->screen;
21184fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_X11Software_Load) {
21185 fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
21187 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
21191fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_X11Software_Unload) {
21192 fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
21196fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_X11Software_Present) {
21197 const fpl__VideoBackendX11Software *nativeBackend = (fpl__VideoBackendX11Software *)backend;
21198 const fpl__X11WindowState *x11WinState = &appState->window.x11;
21199 const fpl__X11Api *x11Api = &appState->x11.api;
21201 x11Api->XPutImage(x11WinState->display, x11WinState->window, nativeBackend->graphicsContext, nativeBackend->buffer, 0, 0, 0, 0, backbuffer->
width, backbuffer->
height);
21202 x11Api->XSync(x11WinState->display, False);
21205fpl_internal fpl__VideoContext fpl__VideoBackend_X11Software_Construct(
void) {
21206 fpl__VideoContext result = fpl__StubVideoContext();
21207 result.loadFunc = fpl__VideoBackend_X11Software_Load;
21208 result.unloadFunc = fpl__VideoBackend_X11Software_Unload;
21209 result.initializeFunc = fpl__VideoBackend_X11Software_Initialize;
21210 result.shutdownFunc = fpl__VideoBackend_X11Software_Shutdown;
21211 result.presentFunc = fpl__VideoBackend_X11Software_Present;
21212 result.recreateOnResize =
true;
21222#if defined(FPL__ENABLE_VIDEO_SOFTWARE) && defined(FPL_PLATFORM_WINDOWS)
21223typedef struct fpl__VideoBackendWin32Software {
21224 fpl__VideoBackend base;
21225 BITMAPINFO bitmapInfo;
21226} fpl__VideoBackendWin32Software;
21228fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_Win32Software_Shutdown) {
21229 fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
21230 BITMAPINFO *bitmapInfo = &nativeBackend->bitmapInfo;
21234fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_Win32Software_Initialize) {
21235 fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
21237 BITMAPINFO *bitmapInfo = &nativeBackend->bitmapInfo;
21239 bitmapInfo->bmiHeader.biSize =
sizeof(BITMAPINFOHEADER);
21240 bitmapInfo->bmiHeader.biWidth = (LONG)backbuffer->
width;
21242 bitmapInfo->bmiHeader.biHeight = -(LONG)backbuffer->
height;
21243 bitmapInfo->bmiHeader.biBitCount = 32;
21244 bitmapInfo->bmiHeader.biCompression = BI_RGB;
21245 bitmapInfo->bmiHeader.biPlanes = 1;
21246 bitmapInfo->bmiHeader.biSizeImage = (DWORD)(backbuffer->
height * backbuffer->
lineWidth);
21250fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_Win32Software_Unload) {
21251 fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
21255fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_Win32Software_Load) {
21256 fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
21258 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
21262fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_Win32Software_Present) {
21263 const fpl__Win32AppState *win32AppState = &appState->win32;
21264 const fpl__Win32WindowState *win32WindowState = &appState->window.win32;
21265 const fpl__Win32Api *wapi = &win32AppState->winApi;
21266 const fpl__VideoBackendWin32Software *nativeBackend = (fpl__VideoBackendWin32Software *)backend;
21270 int32_t targetX = 0;
21271 int32_t targetY = 0;
21272 int32_t targetWidth = area.
width;
21273 int32_t targetHeight = area.
height;
21274 int32_t sourceWidth = backbuffer->
width;
21275 int32_t sourceHeight = backbuffer->
height;
21281 wapi->gdi.StretchDIBits(win32WindowState->deviceContext, 0, 0, area.
width, area.
height, 0, 0, 0, 0,
fpl_null,
fpl_null, DIB_RGB_COLORS, BLACKNESS);
21283 wapi->gdi.StretchDIBits(win32WindowState->deviceContext, targetX, targetY, targetWidth, targetHeight, 0, 0, sourceWidth, sourceHeight, backbuffer->
pixels, &nativeBackend->bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
21287fpl_internal fpl__VideoContext fpl__VideoBackend_Win32Software_Construct(
void) {
21288 fpl__VideoContext result = fpl__StubVideoContext();
21289 result.loadFunc = fpl__VideoBackend_Win32Software_Load;
21290 result.unloadFunc = fpl__VideoBackend_Win32Software_Unload;
21291 result.initializeFunc = fpl__VideoBackend_Win32Software_Initialize;
21292 result.shutdownFunc = fpl__VideoBackend_Win32Software_Shutdown;
21293 result.presentFunc = fpl__VideoBackend_Win32Software_Present;
21294 result.recreateOnResize =
true;
21304#if defined(FPL__ENABLE_VIDEO_VULKAN)
21306#if !fplHasInclude(<vulkan/vulkan.h>) || defined(FPL_NO_PLATFORM_INCLUDES)
21308#if defined(FPL_PLATFORM_WINDOWS)
21309# define fpl__VKAPI_CALL __stdcall
21310# define fpl__VKAPI_PTR fpl__VKAPI_CALL
21311# define fpl__VKAPI_ATTR
21313# define fpl__VKAPI_CALL
21314# define fpl__VKAPI_PTR fpl__VKAPI_CALL
21315# define fpl__VKAPI_ATTR
21318#define FPL__VK_NULL_HANDLE fpl_null
21320#define FPL__VK_MAX_EXTENSION_NAME_SIZE 256
21321#define FPL__VK_MAX_DESCRIPTION_SIZE 256
21323#define FPL__VK_MAKE_VERSION(major, minor, patch) \
21324 ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))
21326typedef enum fpl__VkResult {
21327 FPL__VK_ERROR_OUT_OF_HOST_MEMORY = -1,
21328 FPL__VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
21329 FPL__VK_ERROR_INITIALIZATION_FAILED = -3,
21330 FPL__VK_ERROR_DEVICE_LOST = -4,
21331 FPL__VK_ERROR_MEMORY_MAP_FAILED = -5,
21332 FPL__VK_ERROR_LAYER_NOT_PRESENT = -6,
21333 FPL__VK_ERROR_EXTENSION_NOT_PRESENT = -7,
21334 FPL__VK_ERROR_FEATURE_NOT_PRESENT = -8,
21335 FPL__VK_ERROR_INCOMPATIBLE_DRIVER = -9,
21336 FPL__VK_ERROR_TOO_MANY_OBJECTS = -10,
21337 FPL__VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
21338 FPL__VK_ERROR_FRAGMENTED_POOL = -12,
21339 FPL__VK_ERROR_UNKNOWN = -13,
21341 FPL__VK_SUCCESS = 0,
21343 FPL__VK_NOT_READY = 1,
21344 FPL__VK_TIMEOUT = 2,
21345 FPL__VK_EVENT_SET = 3,
21346 FPL__VK_EVENT_RESET = 4,
21347 FPL__VK_INCOMPLETE = 5,
21349 FPL__VK_RESULT_MAX_ENUM = 0x7FFFFFFF
21352typedef uint32_t fpl__VkFlags;
21353typedef uint32_t fpl__VkBool32;
21355typedef void fpl__VkAllocationCallbacks;
21357typedef void *fpl__VkInstance;
21358typedef void *fpl__VkSurfaceKHR;
21359typedef void *fpl__VkPhysicalDevice;
21361typedef enum fpl__VkStructureType {
21362 FPL__VK_STRUCTURE_TYPE_APPLICATION_INFO = 0,
21363 FPL__VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1,
21364 FPL__VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
21365 FPL__VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
21366 FPL__VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT = 1000128002,
21367 FPL__VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004,
21368 FPL__VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
21369} fpl__VkStructureType;
21371typedef struct fpl__VkApplicationInfo {
21372 fpl__VkStructureType sType;
21374 const char *pApplicationName;
21375 uint32_t applicationVersion;
21376 const char *pEngineName;
21377 uint32_t engineVersion;
21378 uint32_t apiVersion;
21379} fpl__VkApplicationInfo;
21381typedef fpl__VkFlags fpl__VkInstanceCreateFlags;
21383typedef struct fpl__VkInstanceCreateInfo {
21384 fpl__VkStructureType sType;
21386 fpl__VkInstanceCreateFlags flags;
21387 const fpl__VkApplicationInfo *pApplicationInfo;
21388 uint32_t enabledLayerCount;
21389 const char *
const *ppEnabledLayerNames;
21390 uint32_t enabledExtensionCount;
21391 const char *
const *ppEnabledExtensionNames;
21392} fpl__VkInstanceCreateInfo;
21394typedef struct fpl__VkExtensionProperties {
21395 char extensionName[FPL__VK_MAX_EXTENSION_NAME_SIZE];
21396 uint32_t specVersion;
21397} fpl__VkExtensionProperties;
21399typedef struct fpl__VkLayerProperties {
21400 char layerName[FPL__VK_MAX_EXTENSION_NAME_SIZE];
21401 uint32_t specVersion;
21402 uint32_t implementationVersion;
21403 char description[FPL__VK_MAX_DESCRIPTION_SIZE];
21404} fpl__VkLayerProperties;
21407typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkCreateInstance)(
const fpl__VkInstanceCreateInfo *pCreateInfo,
const fpl__VkAllocationCallbacks *pAllocator, fpl__VkInstance *pInstance);
21408typedef void (fpl__VKAPI_PTR *fpl__func_vkDestroyInstance)(fpl__VkInstance instance,
const fpl__VkAllocationCallbacks *pAllocator);
21409typedef void *(fpl__VKAPI_PTR *fpl__func_vkGetInstanceProcAddr)(fpl__VkInstance instance,
const char *pName);
21410typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkEnumerateInstanceExtensionProperties)(
const char *pLayerName, uint32_t *pPropertyCount, fpl__VkExtensionProperties *pProperties);
21411typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkEnumerateInstanceLayerProperties)(uint32_t *pPropertyCount, fpl__VkLayerProperties *pProperties);
21414typedef void (fpl__VKAPI_PTR *fpl__func_vkDestroySurfaceKHR)(fpl__VkInstance instance, fpl__VkSurfaceKHR surface,
const fpl__VkAllocationCallbacks *pAllocator);
21416#if defined(FPL_PLATFORM_WINDOWS)
21418typedef fpl__VkFlags fpl__VkWin32SurfaceCreateFlagsKHR;
21419typedef struct fpl__VkWin32SurfaceCreateInfoKHR {
21420 fpl__VkStructureType sType;
21422 fpl__VkWin32SurfaceCreateFlagsKHR flags;
21423 fpl__Win32InstanceHandle hinstance;
21424 fpl__Win32WindowHandle hwnd;
21425} fpl__VkWin32SurfaceCreateInfoKHR;
21427typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkCreateWin32SurfaceKHR)(fpl__VkInstance instance,
const fpl__VkWin32SurfaceCreateInfoKHR *pCreateInfo,
const fpl__VkAllocationCallbacks *pAllocator, fpl__VkSurfaceKHR *pSurface);
21428typedef fpl__VkBool32(fpl__VKAPI_PTR *fpl__func_vkGetPhysicalDeviceWin32PresentationSupportKHR)(fpl__VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
21430#elif defined(FPL_SUBPLATFORM_X11)
21432typedef fpl__VkFlags fpl__VkXlibSurfaceCreateFlagsKHR;
21433typedef struct fpl__VkXlibSurfaceCreateInfoKHR {
21434 fpl__VkStructureType sType;
21436 fpl__VkXlibSurfaceCreateFlagsKHR flags;
21437 fpl__X11Display *dpy;
21438 fpl__X11Window window;
21439} fpl__VkXlibSurfaceCreateInfoKHR;
21441typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkCreateXlibSurfaceKHR)(fpl__VkInstance instance,
const fpl__VkXlibSurfaceCreateInfoKHR *pCreateInfo,
const fpl__VkAllocationCallbacks *pAllocator, fpl__VkSurfaceKHR *pSurface);
21442typedef fpl__VkBool32(fpl__VKAPI_PTR *fpl__func_vkGetPhysicalDeviceXlibPresentationSupportKHR)(fpl__VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
21446typedef void *fpl__VkDebugUtilsMessengerEXT;
21448typedef enum fpl__VkDebugUtilsMessageSeverityFlagBitsEXT {
21449 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001,
21450 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010,
21451 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100,
21452 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000,
21453 FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
21454} fpl__VkDebugUtilsMessageSeverityFlagBitsEXT;
21455typedef fpl__VkFlags fpl__VkDebugUtilsMessageSeverityFlagsEXT;
21457typedef enum fpl__VkDebugUtilsMessageTypeFlagBitsEXT {
21458 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001,
21459 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002,
21460 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004,
21461 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
21462} fpl__VkDebugUtilsMessageTypeFlagBitsEXT;
21463typedef fpl__VkFlags fpl__VkDebugUtilsMessageTypeFlagsEXT;
21465typedef struct fpl__VkDebugUtilsLabelEXT {
21466 fpl__VkStructureType sType;
21468 const char *pLabelName;
21470} fpl__VkDebugUtilsLabelEXT;
21472typedef void fpl__VkDebugUtilsObjectNameInfoEXT;
21473typedef fpl__VkFlags fpl__VkDebugUtilsMessengerCallbackDataFlagsEXT;
21474typedef struct fpl__VkDebugUtilsMessengerCallbackDataEXT {
21475 fpl__VkStructureType sType;
21477 fpl__VkDebugUtilsMessengerCallbackDataFlagsEXT flags;
21478 const char *pMessageIdName;
21479 int32_t messageIdNumber;
21480 const char *pMessage;
21481 uint32_t queueLabelCount;
21482 const fpl__VkDebugUtilsLabelEXT *pQueueLabels;
21483 uint32_t cmdBufLabelCount;
21484 const fpl__VkDebugUtilsLabelEXT *pCmdBufLabels;
21485 uint32_t objectCount;
21486 const fpl__VkDebugUtilsObjectNameInfoEXT *pObjects;
21487} fpl__VkDebugUtilsMessengerCallbackDataEXT;
21489typedef fpl__VkFlags fpl__VkDebugUtilsMessengerCreateFlagsEXT;
21491typedef fpl__VkBool32(fpl__VKAPI_PTR *fpl__func_vkDebugUtilsMessengerCallbackEXT) (
21492 fpl__VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
21493 fpl__VkDebugUtilsMessageTypeFlagsEXT messageTypes,
21494 const fpl__VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
21497typedef struct fpl__VkDebugUtilsMessengerCreateInfoEXT {
21498 fpl__VkStructureType sType;
21500 fpl__VkDebugUtilsMessengerCreateFlagsEXT flags;
21501 fpl__VkDebugUtilsMessageSeverityFlagsEXT messageSeverity;
21502 fpl__VkDebugUtilsMessageTypeFlagsEXT messageType;
21503 fpl__func_vkDebugUtilsMessengerCallbackEXT pfnUserCallback;
21505} fpl__VkDebugUtilsMessengerCreateInfoEXT;
21507typedef fpl__VkResult(fpl__VKAPI_PTR *fpl__func_vkCreateDebugUtilsMessengerEXT)(fpl__VkInstance instance,
const fpl__VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
const fpl__VkAllocationCallbacks *pAllocator, fpl__VkDebugUtilsMessengerEXT *pMessenger);
21508typedef void (fpl__VKAPI_PTR *fpl__func_vkDestroyDebugUtilsMessengerEXT)(fpl__VkInstance instance, fpl__VkDebugUtilsMessengerEXT messenger,
const fpl__VkAllocationCallbacks *pAllocator);
21512# if defined(FPL_PLATFORM_WINDOWS)
21513# define VK_USE_PLATFORM_WIN32_KHR
21514# elif defined(FPL_SUBPLATFORM_X11)
21515# define VK_USE_PLATFORM_XLIB_KHR
21518# if !defined(FPL_NO_RUNTIME_LINKING)
21519# define VK_NO_PROTOTYPES
21521# include <vulkan/vulkan.h>
21523# define fpl__VKAPI_CALL VKAPI_CALL
21524# define fpl__VKAPI_PTR VKAPI_PTR
21525# define fpl__VKAPI_ATTR VKAPI_ATTR
21527# define FPL__VK_STRUCTURE_TYPE_APPLICATION_INFO VK_STRUCTURE_TYPE_APPLICATION_INFO
21528# define FPL__VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
21529# define FPL__VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR
21530# define FPL__VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR
21531# define FPL__VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
21533typedef enum fpl__VkResult {
21534 FPL__VK_ERROR_OUT_OF_HOST_MEMORY = VK_ERROR_OUT_OF_HOST_MEMORY,
21535 FPL__VK_ERROR_OUT_OF_DEVICE_MEMORY = VK_ERROR_OUT_OF_DEVICE_MEMORY,
21536 FPL__VK_ERROR_INITIALIZATION_FAILED = VK_ERROR_INITIALIZATION_FAILED,
21537 FPL__VK_ERROR_DEVICE_LOST = VK_ERROR_DEVICE_LOST,
21538 FPL__VK_ERROR_MEMORY_MAP_FAILED = VK_ERROR_MEMORY_MAP_FAILED,
21539 FPL__VK_ERROR_LAYER_NOT_PRESENT = VK_ERROR_LAYER_NOT_PRESENT,
21540 FPL__VK_ERROR_EXTENSION_NOT_PRESENT = VK_ERROR_EXTENSION_NOT_PRESENT,
21541 FPL__VK_ERROR_FEATURE_NOT_PRESENT = VK_ERROR_FEATURE_NOT_PRESENT,
21542 FPL__VK_ERROR_INCOMPATIBLE_DRIVER = VK_ERROR_INCOMPATIBLE_DRIVER,
21543 FPL__VK_ERROR_TOO_MANY_OBJECTS = VK_ERROR_TOO_MANY_OBJECTS,
21544 FPL__VK_ERROR_FORMAT_NOT_SUPPORTED = VK_ERROR_FORMAT_NOT_SUPPORTED,
21545 FPL__VK_ERROR_FRAGMENTED_POOL = VK_ERROR_FRAGMENTED_POOL,
21546 FPL__VK_ERROR_UNKNOWN = VK_ERROR_UNKNOWN,
21548 FPL__VK_SUCCESS = VK_SUCCESS,
21550 FPL__VK_NOT_READY = VK_NOT_READY,
21551 FPL__VK_TIMEOUT = VK_TIMEOUT,
21552 FPL__VK_EVENT_SET = VK_EVENT_SET,
21553 FPL__VK_EVENT_RESET = VK_EVENT_RESET,
21554 FPL__VK_INCOMPLETE = VK_INCOMPLETE,
21556 FPL__VK_RESULT_MAX_ENUM = VK_RESULT_MAX_ENUM
21559# define FPL__VK_NULL_HANDLE VK_NULL_HANDLE
21561# define FPL__VK_MAKE_VERSION(major, minor, patch) VK_MAKE_VERSION(major, minor, patch)
21563typedef VkFlags fpl__VkFlags;
21564typedef VkBool32 fpl__VkBool32;
21566typedef VkAllocationCallbacks fpl__VkAllocationCallbacks;
21568typedef VkInstance fpl__VkInstance;
21569typedef VkSurfaceKHR fpl__VkSurfaceKHR;
21570typedef VkPhysicalDevice fpl__VkPhysicalDevice;
21572typedef VkApplicationInfo fpl__VkApplicationInfo;
21573typedef VkInstanceCreateInfo fpl__VkInstanceCreateInfo;
21575typedef VkExtensionProperties fpl__VkExtensionProperties;
21576typedef VkLayerProperties fpl__VkLayerProperties;
21579typedef PFN_vkCreateInstance fpl__func_vkCreateInstance;
21580typedef PFN_vkDestroyInstance fpl__func_vkDestroyInstance;
21581typedef PFN_vkGetInstanceProcAddr fpl__func_vkGetInstanceProcAddr;
21582typedef PFN_vkEnumerateInstanceExtensionProperties fpl__func_vkEnumerateInstanceExtensionProperties;
21583typedef PFN_vkEnumerateInstanceLayerProperties fpl__func_vkEnumerateInstanceLayerProperties;
21586typedef PFN_vkDestroySurfaceKHR fpl__func_vkDestroySurfaceKHR;
21587#if defined(FPL_PLATFORM_WINDOWS)
21588typedef VkWin32SurfaceCreateInfoKHR fpl__VkWin32SurfaceCreateInfoKHR;
21589typedef PFN_vkCreateWin32SurfaceKHR fpl__func_vkCreateWin32SurfaceKHR;
21590typedef PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR fpl__func_vkGetPhysicalDeviceWin32PresentationSupportKHR;
21591#elif defined(FPL_SUBPLATFORM_X11)
21592typedef VkXlibSurfaceCreateInfoKHR fpl__VkXlibSurfaceCreateInfoKHR;
21593typedef PFN_vkCreateXlibSurfaceKHR fpl__func_vkCreateXlibSurfaceKHR;
21594typedef PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR fpl__func_vkGetPhysicalDeviceXlibPresentationSupportKHR;
21597typedef VkDebugUtilsMessageSeverityFlagBitsEXT fpl__VkDebugUtilsMessageSeverityFlagBitsEXT;
21598typedef VkDebugUtilsMessageSeverityFlagsEXT fpl__VkDebugUtilsMessageSeverityFlagsEXT;
21599# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
21600# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
21601# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
21602# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
21603# define FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT
21604typedef VkDebugUtilsMessageTypeFlagBitsEXT fpl__VkDebugUtilsMessageTypeFlagBitsEXT;
21605typedef VkDebugUtilsMessageTypeFlagsEXT fpl__VkDebugUtilsMessageTypeFlagsEXT;
21606# define FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
21607# define FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
21608# define FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
21609# define FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT
21610typedef VkDebugUtilsMessengerCallbackDataEXT fpl__VkDebugUtilsMessengerCallbackDataEXT;
21611typedef VkDebugUtilsMessengerEXT fpl__VkDebugUtilsMessengerEXT;
21612typedef PFN_vkDebugUtilsMessengerCallbackEXT fpl__func_vkDebugUtilsMessengerCallbackEXT;
21613typedef VkDebugUtilsMessengerCreateInfoEXT fpl__VkDebugUtilsMessengerCreateInfoEXT;
21615typedef PFN_vkCreateDebugUtilsMessengerEXT fpl__func_vkCreateDebugUtilsMessengerEXT;
21616typedef PFN_vkDestroyDebugUtilsMessengerEXT fpl__func_vkDestroyDebugUtilsMessengerEXT;
21620typedef struct fpl__VulkanApi {
21621 fplDynamicLibraryHandle libraryHandle;
21622 fpl__func_vkCreateInstance vkCreateInstance;
21623 fpl__func_vkDestroyInstance vkDestroyInstance;
21624 fpl__func_vkGetInstanceProcAddr vkGetInstanceProcAddr;
21625 fpl__func_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
21626 fpl__func_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties;
21629fpl_internal void fpl__UnloadVulkanApi(fpl__VulkanApi *api) {
21630 if (api->libraryHandle.isValid) {
21636fpl_internal bool fpl__LoadVulkanApi(fpl__VulkanApi *api,
const char *libraryName) {
21640#if defined(FPL_NO_RUNTIME_LINKING)
21641 api->vkCreateInstance = vkCreateInstance;
21642 api->vkDestroyInstance = vkDestroyInstance;
21643 api->vkGetInstanceProcAddr = vkGetInstanceProcAddr;
21644 api->vkEnumerateInstanceExtensionProperties = vkEnumerateInstanceExtensionProperties;
21645 api->vkEnumerateInstanceLayerProperties = vkEnumerateInstanceLayerProperties;
21649 uint32_t libraryCount = 0;
21651 const char *libraryNames[4];
21653 libraryNames[libraryCount++] = libraryName;
21656#if defined(FPL_PLATFORM_WINDOWS)
21657 libraryNames[libraryCount++] =
"vulkan-1.dll";
21658#elif defined(FPL_SUBPLATFORM_POSIX)
21659 libraryNames[libraryCount++] =
"libvulkan.so";
21660 libraryNames[libraryCount++] =
"libvulkan.so.1";
21662 FPL__WARNING(FPL__MODULE_VIDEO_VULKAN,
"Unsupported Platform!");
21667#define FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libName, target, type, name) \
21668 (target)->name = (type)fplGetDynamicLibraryProc(&libHandle, #name); \
21669 if ((target)->name == fpl_null) { \
21670 FPL__WARNING(FPL__MODULE_VIDEO_VULKAN, "Failed getting procedure address '%s' from library '%s'", #name, libName); \
21674 bool result =
false;
21675 for (uint32_t i = 0; i < libraryCount; ++i) {
21676 const char *libraryName = libraryNames[i];
21678 if (api->libraryHandle.isValid) {
21687 api->libraryHandle = libHandle;
21689 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkCreateInstance, vkCreateInstance);
21690 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkDestroyInstance, vkDestroyInstance);
21691 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkGetInstanceProcAddr, vkGetInstanceProcAddr);
21692 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkEnumerateInstanceExtensionProperties, vkEnumerateInstanceExtensionProperties);
21693 FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE(libHandle, libraryName, api, fpl__func_vkEnumerateInstanceLayerProperties, vkEnumerateInstanceLayerProperties);
21700 fpl__UnloadVulkanApi(api);
21703#undef FPL__VULKAN_GET_FUNCTION_ADDRESS_CONTINUE
21708typedef struct fpl__VulkanDebugMessengerUserData {
21712} fpl__VulkanDebugMessengerUserData;
21714typedef struct fpl__VideoBackendVulkan {
21715 fpl__VideoBackend base;
21716 fpl__VulkanApi api;
21717 fpl__VkInstance instanceHandle;
21718 fpl__VkSurfaceKHR surfaceHandle;
21719 fpl__VkDebugUtilsMessengerEXT debugMessenger;
21720 fpl__VulkanDebugMessengerUserData debugMessengerUserData;
21721 const fpl__VkAllocationCallbacks *allocator;
21722 fpl_b32 isInstanceUserDefined;
21723} fpl__VideoBackendVulkan;
21725fpl_internal const char *fpl__GetVulkanResultString(
const fpl__VkResult result) {
21727 case FPL__VK_ERROR_OUT_OF_HOST_MEMORY:
21728 return "Out of Host-Memory";
21729 case FPL__VK_ERROR_OUT_OF_DEVICE_MEMORY:
21730 return "Out of Device-Memory";
21731 case FPL__VK_ERROR_INITIALIZATION_FAILED:
21732 return "Initialization failed";
21733 case FPL__VK_ERROR_DEVICE_LOST:
21734 return "Device lost";
21735 case FPL__VK_ERROR_MEMORY_MAP_FAILED:
21736 return "Memory map failed";
21737 case FPL__VK_ERROR_LAYER_NOT_PRESENT:
21738 return "Layer not present";
21739 case FPL__VK_ERROR_EXTENSION_NOT_PRESENT:
21740 return "Extension not present";
21741 case FPL__VK_ERROR_FEATURE_NOT_PRESENT:
21742 return "Feature not present";
21743 case FPL__VK_ERROR_INCOMPATIBLE_DRIVER:
21744 return "Incompatible driver";
21745 case FPL__VK_ERROR_TOO_MANY_OBJECTS:
21746 return "Too many objects";
21747 case FPL__VK_ERROR_FORMAT_NOT_SUPPORTED:
21748 return "Format not supported";
21749 case FPL__VK_ERROR_FRAGMENTED_POOL:
21750 return "Fragmented pool";
21751 case FPL__VK_SUCCESS:
21753 case FPL__VK_NOT_READY:
21754 return "Not-Ready";
21755 case FPL__VK_TIMEOUT:
21757 case FPL__VK_EVENT_SET:
21758 return "Event-Set";
21759 case FPL__VK_EVENT_RESET:
21760 return "Event-Reset";
21761 case FPL__VK_INCOMPLETE:
21762 return "Incomplete";
21768fpl_internal FPL__FUNC_VIDEO_BACKEND_GETPROCEDURE(fpl__VideoBackend_Vulkan_GetProcedure) {
21769 const fpl__VideoBackendVulkan *nativeBackend = (
const fpl__VideoBackendVulkan *)backend;
21770 const fpl__VulkanApi *api = &nativeBackend->api;
21771 if (api->libraryHandle.isValid) {
21777fpl_internal FPL__FUNC_VIDEO_BACKEND_GETREQUIREMENTS(fpl__VideoBackend_Vulkan_GetRequirements) {
21778 FPL__CheckArgumentNull(requirements,
false);
21781 fplAssert(requirements->vulkan.instanceExtensionCount <
fplArrayCount(requirements->vulkan.instanceExtensions));
21782 requirements->vulkan.instanceExtensions[requirements->vulkan.instanceExtensionCount++] =
"VK_KHR_surface";
21783#if defined(FPL_PLATFORM_WINDOWS)
21784 fplAssert(requirements->vulkan.instanceExtensionCount <
fplArrayCount(requirements->vulkan.instanceExtensions));
21785 requirements->vulkan.instanceExtensions[requirements->vulkan.instanceExtensionCount++] =
"VK_KHR_win32_surface";
21786#elif defined(FPL_SUBPLATFORM_X11)
21787 fplAssert(requirements->vulkan.instanceExtensionCount <
fplArrayCount(requirements->vulkan.instanceExtensions));
21788 requirements->vulkan.instanceExtensions[requirements->vulkan.instanceExtensionCount++] =
"VK_KHR_xlib_surface";
21799 uint32_t result = FPL__VK_MAKE_VERSION(major, minor, patch);
21803fpl_internal const char *fpl__GetVulkanMessageSeverityName(
const fpl__VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity) {
21804 switch (messageSeverity) {
21805 case FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
return "ERROR";
21806 case FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
return "WARNING";
21807 case FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
return "INFO";
21808 case FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
return "VERBOSE";
21809 default:
return "Unknown";
21813fpl_internal fpl__VKAPI_ATTR fpl__VkBool32 fpl__VKAPI_CALL fpl__VulkanDebugCallback(fpl__VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, fpl__VkDebugUtilsMessageTypeFlagsEXT messageType,
const fpl__VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
void *pUserData) {
21814 fpl__VulkanDebugMessengerUserData *data = (fpl__VulkanDebugMessengerUserData *)pUserData;
21815 const char *message = pCallbackData->pMessage;
21816 if (data->userCallback !=
fpl_null) {
21817 data->userCallback(data->userData, message, messageSeverity, messageType, pCallbackData);
21819 if (messageSeverity == FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
21820 FPL_LOG_ERROR(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
21821 else if (messageSeverity == FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
21822 FPL_LOG_WARN(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
21823 else if (messageSeverity == FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
21824 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
21825 else if (messageSeverity == FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
21826 FPL_LOG_DEBUG(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
21828 FPL_LOG_DEBUG(FPL__MODULE_VIDEO_VULKAN,
"Validation: %s", message);
21834fpl_internal void fpl__VulkanDestroyDebugMessenger(fpl__VideoBackendVulkan *nativeBackend) {
21835 if (nativeBackend->debugMessenger !=
fpl_null) {
21836 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Destroy Vulkan Debug Messenger '%p'", nativeBackend->debugMessenger);
21837 const fpl__VulkanApi *api = &nativeBackend->api;
21838 fpl__func_vkDestroyDebugUtilsMessengerEXT destroyFunc = (fpl__func_vkDestroyDebugUtilsMessengerEXT)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkDestroyDebugUtilsMessengerEXT");
21840 destroyFunc(nativeBackend->instanceHandle, nativeBackend->debugMessenger, nativeBackend->allocator);
21841 nativeBackend->debugMessenger =
fpl_null;
21847 fpl__VkDebugUtilsMessageSeverityFlagsEXT severities = 0;
21850 severities = FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
21853 severities = FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | FPL__VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
21856 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;
21860 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;
21867 fpl__VulkanDebugMessengerUserData *userData = &nativeBackend->debugMessengerUserData;
21869 userData->userData = settings->
userData;
21873 fpl__VkDebugUtilsMessageTypeFlagsEXT messageTypes =
21874 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
21875 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
21876 FPL__VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
21878 fpl__VkDebugUtilsMessengerCreateInfoEXT createInfo =
fplZeroInit;
21879 createInfo.sType = FPL__VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
21880 createInfo.messageSeverity = severities;
21881 createInfo.messageType = messageTypes;
21882 createInfo.pfnUserCallback = fpl__VulkanDebugCallback;
21883 createInfo.pUserData = userData;
21885 const fpl__VulkanApi *api = &nativeBackend->api;
21887 fpl__func_vkCreateDebugUtilsMessengerEXT createFunc = (fpl__func_vkCreateDebugUtilsMessengerEXT)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkCreateDebugUtilsMessengerEXT");
21889 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Vulkan instance proc 'vkCreateDebugUtilsMessengerEXT' not found! Maybe the instance extension 'VK_EXT_debug_utils' was not set?");
21893 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Create Vulkan Debug Messenger for Instance '%p' with severity flags of '%lu'", nativeBackend->instanceHandle, severities);
21894 fpl__VkResult creationResult = (fpl__VkResult)createFunc(nativeBackend->instanceHandle, &createInfo, nativeBackend->allocator, &nativeBackend->debugMessenger);
21895 if (creationResult != FPL__VK_SUCCESS) {
21896 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);
21903fpl_internal FPL__FUNC_VIDEO_BACKEND_PREPAREWINDOW(fpl__VideoBackend_Vulkan_PrepareWindow) {
21904 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
21907 const fpl__VulkanApi *api = &nativeBackend->api;
21909 nativeBackend->allocator =
fpl_null;
21910 nativeBackend->instanceHandle =
fpl_null;
21911 nativeBackend->isInstanceUserDefined =
false;
21915 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Failed getting required instance extensions for creating an Vulkan instance!");
21924 bool supportsDebugUtils =
false;
21926 fpl__VkExtensionProperties *supportedInstanceExtensions =
fpl_null;
21927 uint32_t supportedInstanceExtensionCount = 0;
21928 api->vkEnumerateInstanceExtensionProperties(
fpl_null, &supportedInstanceExtensionCount,
fpl_null);
21929 if (supportedInstanceExtensionCount > 0) {
21930 supportedInstanceExtensions = (fpl__VkExtensionProperties *)fpl__AllocateTemporaryMemory(
sizeof(fpl__VkExtensionProperties) * supportedInstanceExtensionCount, 16);
21931 api->vkEnumerateInstanceExtensionProperties(
fpl_null, &supportedInstanceExtensionCount, supportedInstanceExtensions);
21932 for (uint32_t i = 0; i < supportedInstanceExtensionCount; ++i) {
21933 if (
fplIsStringEqual(supportedInstanceExtensions[i].extensionName,
"VK_EXT_debug_utils")) {
21934 supportsDebugUtils =
true;
21937 fpl__ReleaseTemporaryMemory(supportedInstanceExtensions);
21938 supportedInstanceExtensions =
fpl_null;
21941 bool supportsValidationLayer =
false;
21943 fpl__VkLayerProperties *supportedLayers =
fpl_null;
21944 uint32_t supportedLayerCount = 0;
21945 api->vkEnumerateInstanceLayerProperties(&supportedLayerCount,
fpl_null);
21946 if (supportedLayerCount > 0) {
21947 supportedLayers = (fpl__VkLayerProperties *)fpl__AllocateTemporaryMemory(
sizeof(fpl__VkLayerProperties) * supportedLayerCount, 16);
21948 api->vkEnumerateInstanceLayerProperties(&supportedLayerCount, supportedLayers);
21949 for (uint32_t i = 0; i < supportedLayerCount; ++i) {
21950 if (
fplIsStringEqual(supportedLayers[i].layerName,
"VK_LAYER_KHRONOS_validation")) {
21951 supportsValidationLayer =
true;
21954 fpl__ReleaseTemporaryMemory(supportedLayers);
21958 const char *enabledValidationLayers[4] =
fplZeroInit;
21959 const char *enabledInstanceExtensions[8] =
fplZeroInit;
21960 uint32_t enabledValidationLayerCount = 0;
21961 uint32_t enabledInstanceExtensionCount = 0;
21964 if (!supportsDebugUtils) {
21965 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"VK_EXT_debug_utils instance extension is not supported!");
21968 if (!supportsValidationLayer) {
21969 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"VK_LAYER_KHRONOS_validation instance layer is not supported!");
21973 if (supportsDebugUtils && supportsValidationLayer) {
21974 enabledValidationLayers[enabledValidationLayerCount++] =
"VK_LAYER_KHRONOS_validation";
21975 enabledInstanceExtensions[enabledInstanceExtensionCount++] =
"VK_EXT_debug_utils";
21983 fpl__VkApplicationInfo applicationInfo =
fplZeroInit;
21984 applicationInfo.sType = FPL__VK_STRUCTURE_TYPE_APPLICATION_INFO;
21991 fpl__VkInstanceCreateInfo instanceCreateInfo =
fplZeroInit;
21992 instanceCreateInfo.sType = FPL__VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
21993 instanceCreateInfo.pApplicationInfo = &applicationInfo;
21994 instanceCreateInfo.enabledExtensionCount = enabledInstanceExtensionCount;
21995 instanceCreateInfo.ppEnabledExtensionNames = enabledInstanceExtensions;
21996 instanceCreateInfo.enabledLayerCount = enabledValidationLayerCount;
21997 instanceCreateInfo.ppEnabledLayerNames = enabledValidationLayers;
21999 const fpl__VkAllocationCallbacks *allocator = (
const fpl__VkAllocationCallbacks *)videoSettings->
graphics.
vulkan.
allocator;
22001 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Create Vulkan Instance with %lu extensions and %lu layers", instanceCreateInfo.enabledExtensionCount, instanceCreateInfo.enabledLayerCount);
22002 fpl__VkInstance instance =
fpl_null;
22003 fpl__VkResult creationResult = (fpl__VkResult)api->vkCreateInstance(&instanceCreateInfo, allocator, &instance);
22004 if (creationResult != FPL__VK_SUCCESS) {
22005 const char *creationError = fpl__GetVulkanResultString(creationResult);
22006 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);
22010 nativeBackend->allocator = allocator;
22011 nativeBackend->instanceHandle = instance;
22012 nativeBackend->isInstanceUserDefined =
false;
22016 if (!fpl__VulkanCreateDebugMessenger(&videoSettings->
graphics.
vulkan, nativeBackend)) {
22018 FPL__WARNING(FPL__MODULE_VIDEO_VULKAN,
"The debug messenger could not be created, no validation message are printed");
22020 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"The debug messenger could not be created, stop vulkan initialization!");
22031 nativeBackend->isInstanceUserDefined =
true;
22036fpl_internal FPL__FUNC_VIDEO_BACKEND_FINALIZEWINDOW(fpl__VideoBackend_Vulkan_FinalizeWindow) {
22040fpl_internal FPL__FUNC_VIDEO_BACKEND_SHUTDOWN(fpl__VideoBackend_Vulkan_Shutdown) {
22041 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
22043 const fpl__VulkanApi *api = &nativeBackend->api;
22045 if (nativeBackend->surfaceHandle != FPL__VK_NULL_HANDLE) {
22046 fpl__func_vkDestroySurfaceKHR destroyProc = (fpl__func_vkDestroySurfaceKHR)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkDestroySurfaceKHR");
22049 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Destroy Vulkan Surface '%p'", nativeBackend->surfaceHandle);
22050 destroyProc(nativeBackend->instanceHandle, nativeBackend->surfaceHandle, nativeBackend->allocator);
22052 nativeBackend->surfaceHandle = FPL__VK_NULL_HANDLE;
22056fpl_internal FPL__FUNC_VIDEO_BACKEND_INITIALIZE(fpl__VideoBackend_Vulkan_Initialize) {
22057 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
22059 const fpl__VulkanApi *api = &nativeBackend->api;
22061 if (nativeBackend->instanceHandle == FPL__VK_NULL_HANDLE) {
22062 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Cannot create a Vulkan surface without a Vulkan instance!");
22066 fpl__VkSurfaceKHR surfaceHandle = FPL__VK_NULL_HANDLE;
22068#if defined(FPL_PLATFORM_WINDOWS)
22069 FPL_LOG_DEBUG(FPL__MODULE_VIDEO_VULKAN,
"Query Vulkan Instance Proc 'vkCreateWin32SurfaceKHR' for instance '%p'", nativeBackend->instanceHandle);
22070 fpl__func_vkCreateWin32SurfaceKHR createProc = (fpl__func_vkCreateWin32SurfaceKHR)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkCreateWin32SurfaceKHR");
22072 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Vulkan instance proc 'vkCreateWin32SurfaceKHR' not found! Maybe the instance extension 'VK_KHR_win32_surface' was not set?");
22076 fpl__VkWin32SurfaceCreateInfoKHR creationInfo =
fplZeroInit;
22077 creationInfo.sType = FPL__VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
22078 creationInfo.hinstance = fpl__global__InitState.win32.appInstance;
22079 creationInfo.hwnd = windowState->win32.windowHandle;
22081 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);
22082 fpl__VkResult creationResult = (fpl__VkResult)createProc(nativeBackend->instanceHandle, &creationInfo, nativeBackend->allocator, &surfaceHandle);
22083 if (creationResult != FPL__VK_SUCCESS) {
22084 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Failed creating vulkan surface KHR for Win32 -> (VkResult: %d)!", creationResult);
22087#elif defined(FPL_SUBPLATFORM_X11)
22088 FPL_LOG_DEBUG(FPL__MODULE_VIDEO_VULKAN,
"Query Vulkan Instance Proc 'vkCreateXlibSurfaceKHR' for instance '%p'", nativeBackend->instanceHandle);
22089 fpl__func_vkCreateXlibSurfaceKHR createProc = (fpl__func_vkCreateXlibSurfaceKHR)api->vkGetInstanceProcAddr(nativeBackend->instanceHandle,
"vkCreateXlibSurfaceKHR");
22091 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Vulkan instance proc 'vkCreateXlibSurfaceKHR' not found! Maybe the instance extension 'VK_KHR_xlib_surface' was not set?");
22095 fpl__VkXlibSurfaceCreateInfoKHR creationInfo =
fplZeroInit;
22096 creationInfo.sType = FPL__VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
22097 creationInfo.dpy = (fpl__X11Display *)windowState->x11.display;
22098 creationInfo.window = windowState->x11.window;
22100 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);
22101 fpl__VkResult creationResult = createProc(nativeBackend->instanceHandle, &creationInfo, nativeBackend->allocator, &surfaceHandle);
22102 if (creationResult != FPL__VK_SUCCESS) {
22103 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Failed creating vulkan surface KHR for X11 -> (VkResult: %d)!", creationResult);
22107 FPL__ERROR(FPL__MODULE_VIDEO_VULKAN,
"Unsupported Platform!");
22111 fplAssert(surfaceHandle != FPL__VK_NULL_HANDLE);
22112 nativeBackend->surfaceHandle = surfaceHandle;
22114 backend->surface.vulkan.instance = nativeBackend->instanceHandle;
22115 backend->surface.vulkan.surfaceKHR = (
void *)nativeBackend->surfaceHandle;
22117#if defined(FPL_PLATFORM_WINDOWS)
22118 backend->surface.window.win32.windowHandle = windowState->win32.windowHandle;
22119 backend->surface.window.win32.deviceContext = windowState->win32.deviceContext;
22120#elif defined(FPL_SUBPLATFORM_X11)
22121 backend->surface.window.x11.display = windowState->x11.display;
22122 backend->surface.window.x11.window = windowState->x11.window;
22123 backend->surface.window.x11.screen = windowState->x11.screen;
22124 backend->surface.window.x11.visual = windowState->x11.visual;
22130fpl_internal FPL__FUNC_VIDEO_BACKEND_DESTROYEDWINDOW(fpl__VideoBackend_Vulkan_DestroyedWindow) {
22131 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
22134 if (!nativeBackend->isInstanceUserDefined && nativeBackend->instanceHandle !=
fpl_null && nativeBackend->debugMessenger !=
fpl_null) {
22135 fpl__VulkanDestroyDebugMessenger(nativeBackend);
22139 const fpl__VulkanApi *api = &nativeBackend->api;
22140 if (!nativeBackend->isInstanceUserDefined && nativeBackend->instanceHandle !=
fpl_null) {
22141 FPL_LOG_INFO(FPL__MODULE_VIDEO_VULKAN,
"Destroy Vulkan Instance '%p'", nativeBackend->instanceHandle);
22142 api->vkDestroyInstance(nativeBackend->instanceHandle, nativeBackend->allocator);
22143 nativeBackend->instanceHandle =
fpl_null;
22147fpl_internal FPL__FUNC_VIDEO_BACKEND_UNLOAD(fpl__VideoBackend_Vulkan_Unload) {
22148 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
22151 fpl__UnloadVulkanApi(&nativeBackend->api);
22157fpl_internal FPL__FUNC_VIDEO_BACKEND_LOAD(fpl__VideoBackend_Vulkan_Load) {
22158 fpl__VideoBackendVulkan *nativeBackend = (fpl__VideoBackendVulkan *)backend;
22163 nativeBackend->base.magic = FPL__VIDEOBACKEND_MAGIC;
22173fpl_internal FPL__FUNC_VIDEO_BACKEND_PRESENT(fpl__VideoBackend_Vulkan_Present) {
22174 const fpl__VideoBackendVulkan *nativeBackend = (
const fpl__VideoBackendVulkan *)backend;
22177fpl_internal fpl__VideoContext fpl__VideoBackend_Vulkan_Construct(
void) {
22178 fpl__VideoContext result = fpl__StubVideoContext();
22179 result.loadFunc = fpl__VideoBackend_Vulkan_Load;
22180 result.unloadFunc = fpl__VideoBackend_Vulkan_Unload;
22181 result.getProcedureFunc = fpl__VideoBackend_Vulkan_GetProcedure;
22182 result.initializeFunc = fpl__VideoBackend_Vulkan_Initialize;
22183 result.shutdownFunc = fpl__VideoBackend_Vulkan_Shutdown;
22184 result.prepareWindowFunc = fpl__VideoBackend_Vulkan_PrepareWindow;
22185 result.finalizeWindowFunc = fpl__VideoBackend_Vulkan_FinalizeWindow;
22186 result.destroyedWindowFunc = fpl__VideoBackend_Vulkan_DestroyedWindow;
22187 result.presentFunc = fpl__VideoBackend_Vulkan_Present;
22188 result.getRequirementsFunc = fpl__VideoBackend_Vulkan_GetRequirements;
22202#if !defined(FPL__AUDIO_BACKEND_API_IMPLEMENTED) && defined(FPL__ENABLE_AUDIO)
22203# define FPL__AUDIO_BACKEND_API_IMPLEMENTED
22205struct fplAudioContext;
22207struct fplAudioBackend;
22209#define FPL_AUDIO_BACKEND_INITIALIZE_FUNC(name) fplAudioResultType name(struct fplAudioContext *context, struct fplAudioBackend *backend)
22216typedef FPL_AUDIO_BACKEND_INITIALIZE_FUNC(fpl_audio_backend_initialize_func);
22218#define FPL_AUDIO_BACKEND_GET_AUDIO_DEVICES_FUNC(name) uint32_t name(struct fplAudioContext *context, struct fplAudioBackend *backend, const uint32_t maxDeviceCount, const uint32_t deviceInfoSize, fplAudioDeviceInfo *deviceInfos)
22219typedef FPL_AUDIO_BACKEND_GET_AUDIO_DEVICES_FUNC(fpl_audio_backend_get_audio_devices_func);
22221#define FPL_AUDIO_BACKEND_GET_AUDIO_DEVICE_INFO_FUNC(name) fplAudioResultType name(struct fplAudioContext *context, struct fplAudioBackend *backend, const fplAudioDeviceID *targetDevice, fplAudioDeviceInfoExtended *outDeviceInfo)
22222typedef FPL_AUDIO_BACKEND_GET_AUDIO_DEVICE_INFO_FUNC(fpl_audio_backend_get_audio_device_info_func);
22224#define FPL_AUDIO_BACKEND_RELEASE_FUNC(name) bool name(struct fplAudioContext *context, struct fplAudioBackend *backend)
22231typedef FPL_AUDIO_BACKEND_RELEASE_FUNC(fpl_audio_backend_release_func);
22244#define FPL_AUDIO_BACKEND_INITIALIZE_DEVICE_FUNC(name) fplAudioResultType name(struct fplAudioContext *context, struct fplAudioBackend *backend, const fplSpecificAudioSettings *audioSettings, const fplAudioFormat *targetFormat, const fplAudioDeviceInfo *targetDevice, fplAudioFormat *outputFormat, fplAudioDeviceInfo *outputDevice, fplAudioChannelMap *outputChannelMap)
22245typedef FPL_AUDIO_BACKEND_INITIALIZE_DEVICE_FUNC(fpl_audio_backend_initialize_device_func);
22247#define FPL_AUDIO_BACKEND_RELEASE_DEVICE_FUNC(name) bool name(struct fplAudioContext *context, struct fplAudioBackend *backend)
22254typedef FPL_AUDIO_BACKEND_RELEASE_DEVICE_FUNC(fpl_audio_backend_release_device_func);
22256#define FPL_AUDIO_BACKEND_START_DEVICE_FUNC(name) fplAudioResultType name(struct fplAudioContext *context, struct fplAudioBackend *backend)
22257typedef FPL_AUDIO_BACKEND_START_DEVICE_FUNC(fpl_audio_backend_start_device_func);
22259#define FPL_AUDIO_BACKEND_STOP_DEVICE_FUNC(name) bool name(struct fplAudioContext *context, struct fplAudioBackend *backend)
22260typedef FPL_AUDIO_BACKEND_STOP_DEVICE_FUNC(fpl_audio_backend_stop_device_func);
22262#define FPL_AUDIO_BACKEND_MAIN_LOOP_FUNC(name) void name(struct fplAudioContext *context, struct fplAudioBackend *backend)
22263typedef FPL_AUDIO_BACKEND_MAIN_LOOP_FUNC(fpl_audio_backend_main_loop_func);
22265#define FPL_AUDIO_BACKEND_STOP_MAIN_LOOP_FUNC(name) void name(struct fplAudioContext *context, struct fplAudioBackend *backend)
22266typedef FPL_AUDIO_BACKEND_STOP_MAIN_LOOP_FUNC(fpl_audio_backend_stop_main_loop_func);
22269typedef struct fplAudioBackendFunctionTable {
22270 fpl_audio_backend_initialize_func *initialize;
22271 fpl_audio_backend_release_func *release;
22272 fpl_audio_backend_get_audio_devices_func *getAudioDevices;
22273 fpl_audio_backend_get_audio_device_info_func *getAudioDeviceInfo;
22274 fpl_audio_backend_initialize_device_func *initializeDevice;
22275 fpl_audio_backend_release_device_func *releaseDevice;
22276 fpl_audio_backend_start_device_func *startDevice;
22277 fpl_audio_backend_stop_device_func *stopDevice;
22278 fpl_audio_backend_main_loop_func *mainLoop;
22279 fpl_audio_backend_stop_main_loop_func *stopMainLoop;
22281} fplAudioBackendFunctionTable;
22284typedef struct fplAudioBackendID {
22289} fplAudioBackendID;
22292typedef struct fplAudioBackendDescriptorIDName {
22294 fplAudioBackendID id;
22297} fplAudioBackendDescriptorIDName;
22299typedef struct fplAudioBackendDescriptorHeader {
22301 fplAudioBackendDescriptorIDName idName;
22305 uint32_t backendSize;
22310} fplAudioBackendDescriptorHeader;
22313typedef struct fplAudioBackendDescriptor {
22315 fplAudioBackendDescriptorHeader header;
22317 fplAudioBackendFunctionTable table;
22318} fplAudioBackendDescriptor;
22320typedef struct fplAudioBackend {
22322 fplAudioDeviceInfo internalDevice;
22324 fplAudioFormat internalFormat;
22326 fplAudioFormat desiredFormat;
22330 void *clientUserData;
22334#define FPL_AUDIO_BACKEND_DATA_PADDING 16
22337#define FPL_AUDIO_BACKEND_DATA_OFFSET (sizeof(fplAudioBackend) + FPL_AUDIO_BACKEND_DATA_PADDING)
22340#define FPL_GET_AUDIO_BACKEND_IMPL(backend, type) (type *)(((uint8_t *)(backend) + FPL_AUDIO_BACKEND_DATA_OFFSET))
22349#if !defined(FPL__AUDIO_BACKENDS_IMPLEMENTED) && defined(FPL__ENABLE_AUDIO)
22350# define FPL__AUDIO_BACKENDS_IMPLEMENTED
22352typedef enum fpl__AudioDeviceState {
22354 fpl__AudioDeviceState_Uninitialized = 0,
22356 fpl__AudioDeviceState_Stopped,
22358 fpl__AudioDeviceState_Started,
22360 fpl__AudioDeviceState_Starting,
22362 fpl__AudioDeviceState_Stopping,
22363} fpl__AudioDeviceState;
22365typedef struct fplAudioContext {
22367 volatile fpl__AudioDeviceState state;
22370typedef struct fpl__CommonAudioState {
22372 fplAudioBackendFunctionTable funcTable;
22374 fplAudioChannelMap channelsMapping;
22376 fplAudioBackend *backend;
22378 fplAudioContext context;
22379} fpl__CommonAudioState;
22381fpl_internal uint32_t fpl__ReadAudioFramesFromClient(
const fplAudioBackend *backend, uint32_t frameCount,
void *pSamples) {
22382 uint32_t framesRead = 0;
22383 if (backend->clientReadCallback !=
fpl_null) {
22384 framesRead = backend->clientReadCallback(&backend->internalFormat, frameCount, pSamples, backend->clientUserData);
22386 uint32_t channels = backend->internalFormat.channels;
22387 uint32_t samplesRead = framesRead * channels;
22389 uint32_t consumedBytes = samplesRead * sampleSize;
22390 uint32_t remainingBytes = ((frameCount * channels) - samplesRead) * sampleSize;
22391 if (remainingBytes > 0) {
22392 fplMemoryClear((uint8_t *)pSamples + consumedBytes, remainingBytes);
22394 return(samplesRead);
22398#if defined(FPL_PLATFORM_WINDOWS)
22399fpl_globalvar const fpl__Win32Guid FPL__GUID_KSDATAFORMAT_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
22400fpl_globalvar const fpl__Win32Guid FPL__GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
22415 }
else if (channels == 3) {
22425 }
else if (channels == 4) {
22437 }
else if (channels == 5) {
22451 }
else if (channels == 6) {
22458 }
else if (channels == 7) {
22481fpl_internal fpl__AudioDeviceState fpl__AudioGetDeviceState(fplAudioContext *context);
22482fpl_internal bool fpl__IsAudioDeviceInitialized(fplAudioContext *context);
22483fpl_internal bool fpl__IsAudioDeviceStarted(fplAudioContext *context);
22490#if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
22492# include <mmsystem.h>
22493# include <dsound.h>
22495#define FPL__FUNC_DSOUND_DirectSoundCreate(name) HRESULT WINAPI name(const GUID* pcGuidDevice, LPDIRECTSOUND *ppDS8, LPUNKNOWN pUnkOuter)
22496typedef FPL__FUNC_DSOUND_DirectSoundCreate(func_DirectSoundCreate);
22497#define FPL__FUNC_DSOUND_DirectSoundEnumerateW(name) HRESULT WINAPI name(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext)
22498typedef FPL__FUNC_DSOUND_DirectSoundEnumerateW(func_DirectSoundEnumerateW);
22500#define FPL__DIRECTSOUND_MAX_PERIODS 4
22502static GUID FPL__IID_IDirectSoundNotify = { 0xb0210783, 0x89cd, 0x11d0, {0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16} };
22504 GUID FPL__IID_IDirectSoundNotify_Guid = FPL__IID_IDirectSoundNotify;
22506 GUID *FPL__IID_IDirectSoundNotify_Guid = &FPL__IID_IDirectSoundNotify;
22509fpl_globalvar const DWORD FPL__DirectSound_ChannelMask_Mono = SPEAKER_FRONT_CENTER;
22510fpl_globalvar const DWORD FPL__DirectSound_ChannelMask_Stereo = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
22513 HMODULE dsoundLibrary;
22514 func_DirectSoundCreate *DirectSoundCreate;
22515 func_DirectSoundEnumerateW *DirectSoundEnumerateW;
22516} fpl__DirectSoundApi;
22518fpl_internal void fpl__UnloadDirectSoundApi(fpl__DirectSoundApi *dsoundApi) {
22520 if (dsoundApi->dsoundLibrary !=
fpl_null) {
22521 FreeLibrary(dsoundApi->dsoundLibrary);
22526fpl_internal bool fpl__LoadDirectSoundApi(fpl__DirectSoundApi *dsoundApi) {
22528 bool result =
false;
22529 const char *dsoundLibraryName =
"dsound.dll";
22533 FPL__WIN32_LOAD_LIBRARY(FPL__MODULE_AUDIO_DIRECTSOUND, dsoundLibrary, dsoundLibraryName);
22534 dsoundApi->dsoundLibrary = dsoundLibrary;
22535 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_DIRECTSOUND, dsoundLibrary, dsoundLibraryName, dsoundApi, func_DirectSoundCreate, DirectSoundCreate);
22536 FPL__WIN32_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_DIRECTSOUND, dsoundLibrary, dsoundLibraryName, dsoundApi, func_DirectSoundEnumerateW, DirectSoundEnumerateW);
22540 fpl__UnloadDirectSoundApi(dsoundApi);
22546 fpl__DirectSoundApi api;
22547 LPDIRECTSOUND directSound;
22548 LPDIRECTSOUNDBUFFER primaryBuffer;
22549 LPDIRECTSOUNDBUFFER secondaryBuffer;
22550 LPDIRECTSOUNDNOTIFY notify;
22551 HANDLE notifyEvents[FPL__DIRECTSOUND_MAX_PERIODS];
22553 uint32_t lastProcessedFrame;
22554 bool breakMainLoop;
22555} fpl__AudioBackendDirectSound;
22558 fpl__Win32Guid lookupID;
22560 uint32_t deviceInfoSize;
22561 uint32_t foundDeviceCount;
22562 uint32_t maxDeviceCount;
22563 uint32_t capacityOverflow;
22565} fpl__DirectSoundDeviceInfos;
22568 fpl__DirectSoundChannelsInfoResult_Success = 0,
22569 fpl__DirectSoundChannelsInfoResult_Failed,
22570 fpl__DirectSoundChannelsInfoResult_TargetFormat,
22571} fpl__DirectSoundChannelInfoResult;
22573fpl_internal uint16_t fpl__GetDirectSoundChannelsAndMapFromSpeakerConfig(
const DWORD speakerConfig, DWORD *outputChannelMask,
fplAudioChannelLayout *outputLayout) {
22574 uint16_t channels = 0;
22575 DWORD channelMask = 0;
22578 if (outputChannelMask !=
fpl_null) {
22579 channelMask = *outputChannelMask;
22583 layout = *outputLayout;
22586 switch (speakerConfig & 0xFF) {
22587 case DSSPEAKER_MONO:
22589 channelMask = SPEAKER_FRONT_CENTER;
22593 case DSSPEAKER_HEADPHONE:
22594 case DSSPEAKER_STEREO:
22596 channelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
22600 case DSSPEAKER_QUAD:
22602 channelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
22606 case DSSPEAKER_SURROUND:
22608 channelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER;
22612 case DSSPEAKER_5POINT1_SURROUND:
22614 channelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
22618 case DSSPEAKER_5POINT1_BACK:
22620 channelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
22624 case DSSPEAKER_7POINT1_SURROUND:
22626 channelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
22630 case DSSPEAKER_7POINT1_WIDE:
22632 channelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER;
22639 if (outputChannelMask !=
fpl_null) {
22640 *outputChannelMask = channelMask;
22644 *outputLayout = layout;
22650fpl_internal BOOL CALLBACK fpl__GetDeviceCallbackDirectSound(LPGUID lpGuid, LPCWSTR lpwstrDescription, LPCWSTR lpwstrModule, LPVOID lpContext) {
22651 fpl__DirectSoundDeviceInfos *infos = (fpl__DirectSoundDeviceInfos *)lpContext;
22653 if (infos->deviceInfos !=
fpl_null) {
22655 if (infos->isLookup) {
22657 isMatch = fpl__Win32IsEqualGuid(*lpGuid, infos->lookupID);
22659 isMatch = fpl__Win32IsEqualGuid(FPL__WIN32_GUID_ZERO, infos->lookupID);
22669 uint32_t index = infos->foundDeviceCount++;
22670 if (index < infos->maxDeviceCount) {
22675 fplMemoryCopy(lpGuid,
sizeof(outDeviceInfo->
id.dshow), &outDeviceInfo->
id.dshow);
22677 outDeviceInfo->
isDefault = fpl__Win32IsEqualGuid(outDeviceInfo->
id.dshow, FPL__WIN32_GUID_ZERO);
22679 infos->capacityOverflow++;
22682 infos->foundDeviceCount++;
22685 if (infos->isLookup && infos->foundDeviceCount > 0) {
22692fpl_internal FPL_AUDIO_BACKEND_GET_AUDIO_DEVICES_FUNC(fpl__AudiobackendDirectSoundGetAudioDevices) {
22693 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
22696 const fpl__DirectSoundApi *dsoundApi = &impl->api;
22697 if (dsoundApi->dsoundLibrary ==
fpl_null) {
22698 FPL__WARNING(FPL__MODULE_AUDIO_DIRECTSOUND,
"API is not loaded!");
22702 uint32_t result = 0;
22704 infos.maxDeviceCount = maxDeviceCount;
22705 infos.deviceInfos = deviceInfos;
22706 infos.capacityOverflow = 0;
22707 infos.deviceInfoSize = deviceInfoSize;
22708 dsoundApi->DirectSoundEnumerateW(fpl__GetDeviceCallbackDirectSound, &infos);
22709 result = infos.foundDeviceCount;
22710 if (infos.capacityOverflow > 0) {
22711 FPL__WARNING(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);
22716fpl_internal FPL_AUDIO_BACKEND_GET_AUDIO_DEVICE_INFO_FUNC(fpl__AudiobackendDirectSoundGetAudioDeviceInfo) {
22717 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
22721 fpl__PlatformAppState *appState = fpl__global__AppState;
22722 fpl__Win32AppState *win32AppState = &appState->win32;
22723 const fpl__Win32Api *apiFuncs = &win32AppState->winApi;
22725 const fpl__DirectSoundApi *dsoundApi = &impl->api;
22726 if (dsoundApi->dsoundLibrary ==
fpl_null) {
22727 FPL__WARNING(FPL__MODULE_AUDIO_DIRECTSOUND,
"API is not loaded!");
22731 LPDIRECTSOUND directSound =
fpl_null;
22734 const fpl__Win32Guid *deviceId =
fpl_null;
22736 fplAssert(
sizeof(GUID) ==
sizeof(targetDevice->dshow));
22737 deviceId = &targetDevice->dshow;
22743 infos.maxDeviceCount = 1;
22744 infos.deviceInfos = &deviceInfo;
22745 infos.capacityOverflow = 0;
22746 infos.deviceInfoSize =
sizeof(deviceInfo);
22747 infos.isLookup =
true;
22749 fpl__Win32CopyGuid(deviceId, &infos.lookupID);
22751 fpl__Win32CopyGuid(&FPL__WIN32_GUID_ZERO, &infos.lookupID);
22753 if (FAILED(dsoundApi->DirectSoundEnumerateW(fpl__GetDeviceCallbackDirectSound, &infos))) {
22758 if (!SUCCEEDED(dsoundApi->DirectSoundCreate((
const GUID *)deviceId, &directSound,
fpl_null))) {
22760 fpl__Win32FormatGuidString(idString,
fplArrayCount(idString), deviceId);
22766# if defined(FPL__ENABLE_WINDOW)
22768 windowHandle = appState->window.win32.windowHandle;
22772 windowHandle = apiFuncs->user.GetDesktopWindow();
22776 if (FAILED(IDirectSound_SetCooperativeLevel(directSound, windowHandle, DSSCL_PRIORITY))) {
22777 IDirectSound_Release(directSound);
22783 caps.dwSize =
sizeof(caps);
22784 if (FAILED(IDirectSound_GetCaps(directSound, &caps))) {
22785 IDirectSound_Release(directSound);
22791 if ((caps.dwFlags & DSCAPS_PRIMARYSTEREO) != 0) {
22792 DWORD speakerConfig;
22794 if (SUCCEEDED(IDirectSound_GetSpeakerConfig(directSound, &speakerConfig))) {
22795 channels = fpl__GetDirectSoundChannelsAndMapFromSpeakerConfig(speakerConfig,
fpl_null,
fpl_null);
22833 switch (audioChannelFlags) {
22859 if ((channels == 1) && ((channelMask == 0) || ((channelMask & SPEAKER_FRONT_CENTER) != 0))) {
22861 }
else if (channels == 2 && channelMask == 0) {
22865 uint32_t channelIndex = 0;
22866 for (uint32_t bit = 0; bit < 32; ++bit) {
22867 DWORD bitMask = (channelMask & (1UL << bit));
22868 if (bitMask != 0) {
22870 channelMap->
speakers[channelIndex++] = flags;
22880 for (uint16_t channelIndex = 0; channelIndex < channels; ++channelIndex) {
22881 DWORD channelValue = fpl__MapAudioSpeakerFlagsToWin32AudioChannelId(channelMap->
speakers[channelIndex]);
22882 result |= channelValue;
22890 waveFormat.Format.cbSize =
sizeof(waveFormat);
22891 waveFormat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
22892 waveFormat.Format.nChannels = (WORD)sourceFormat->
channels;
22893 waveFormat.Format.nSamplesPerSec = (DWORD)sourceFormat->sampleRate;
22895 waveFormat.Format.nBlockAlign = (waveFormat.Format.nChannels * waveFormat.Format.wBitsPerSample) / 8;
22896 waveFormat.Format.nAvgBytesPerSec = waveFormat.Format.nBlockAlign * waveFormat.Format.nSamplesPerSec;
22897 waveFormat.Samples.wValidBitsPerSample = waveFormat.Format.wBitsPerSample;
22899 fpl__Win32CopyGuid(&FPL__GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, &waveFormat.SubFormat);
22901 fpl__Win32CopyGuid(&FPL__GUID_KSDATAFORMAT_SUBTYPE_PCM, &waveFormat.SubFormat);
22903 waveFormat.dwChannelMask = fpl__GetWin32AudioChannelMaskFromMapping(channelMap, sourceFormat->channels);
22904 *outputWaveFormat = waveFormat;
22907fpl_internal FPL_AUDIO_BACKEND_RELEASE_DEVICE_FUNC(fpl__AudiobackendDirectSoundReleaseDevice) {
22908 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
22911 if (impl->stopEvent !=
fpl_null) {
22912 CloseHandle(impl->stopEvent);
22916 for (uint32_t i = 0; i < backend->internalFormat.periods; ++i) {
22917 if (impl->notifyEvents[i] !=
fpl_null) {
22918 CloseHandle(impl->notifyEvents[i]);
22924 IDirectSoundNotify_Release(impl->notify);
22928 if (impl->secondaryBuffer !=
fpl_null) {
22929 IDirectSoundBuffer_Release(impl->secondaryBuffer);
22933 if (impl->primaryBuffer !=
fpl_null) {
22934 IDirectSoundBuffer_Release(impl->primaryBuffer);
22938 if (impl->directSound !=
fpl_null) {
22939 IDirectSound_Release(impl->directSound);
22946fpl_internal FPL_AUDIO_BACKEND_RELEASE_FUNC(fpl__AudiobackendDirectSoundRelease) {
22947 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
22950 fpl__AudiobackendDirectSoundReleaseDevice(context, backend);
22952 fpl__UnloadDirectSoundApi(&impl->api);
22959fpl_internal FPL_AUDIO_BACKEND_INITIALIZE_FUNC(fpl__AudiobackendDirectSoundInitialize) {
22960 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
22963#define FPL__DSOUND_INIT_ERROR(ret, format, ...) do { \
22964 FPL__ERROR(FPL__MODULE_AUDIO_DIRECTSOUND, format, ## __VA_ARGS__); \
22965 fpl__AudiobackendDirectSoundRelease(context, backend); \
22970 fpl__DirectSoundApi *dsoundApi = &impl->api;
22971 if (!fpl__LoadDirectSoundApi(dsoundApi)) {
22977#undef FPL__DSOUND_INIT_ERROR
22980fpl_internal FPL_AUDIO_BACKEND_INITIALIZE_DEVICE_FUNC(fpl__AudiobackendDirectSoundInitializeDevice) {
22981 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
22984#define FPL__DSOUND_INIT_ERROR(ret, format, ...) do { \
22985 FPL__ERROR(FPL__MODULE_AUDIO_DIRECTSOUND, format, ## __VA_ARGS__); \
22986 fpl__AudiobackendDirectSoundReleaseDevice(context, backend); \
22991 fpl__PlatformAppState *appState = fpl__global__AppState;
22992 fpl__Win32AppState *win32AppState = &appState->win32;
22993 const fpl__Win32Api *apiFuncs = &win32AppState->winApi;
22995 fpl__DirectSoundApi *dsoundApi = &impl->api;
22996 if (dsoundApi->dsoundLibrary ==
fpl_null) {
23001 fpl__SetAudioDefaultChannelMapWin32(targetFormat->channels, targetFormat->channelLayout, outputChannelMap);
23006 fpl__SetupWaveFormatDirectSound(targetFormat, outputChannelMap, &waveFormat);
23011 infos.maxDeviceCount = 1;
23012 infos.deviceInfos = &internalDevice;
23013 infos.deviceInfoSize =
sizeof(internalDevice);
23014 infos.isLookup =
true;
23016 fpl__Win32CopyGuid(&targetDevice->id.dshow, &infos.lookupID);
23018 fpl__Win32CopyGuid(&FPL__WIN32_GUID_ZERO, &infos.lookupID);
23020 if (FAILED(dsoundApi->DirectSoundEnumerateW(fpl__GetDeviceCallbackDirectSound, &infos))) {
23024 const fpl__Win32Guid *deviceId = &internalDevice.
id.dshow;
23026 if (FAILED(dsoundApi->DirectSoundCreate((
const GUID *)deviceId, &impl->directSound,
fpl_null))) {
23028 fpl__Win32FormatGuidString(idString,
fplArrayCount(idString), deviceId);
23034# if defined(FPL__ENABLE_WINDOW)
23036 windowHandle = appState->window.win32.windowHandle;
23040 windowHandle = apiFuncs->user.GetDesktopWindow();
23046 if (FAILED(IDirectSound_SetCooperativeLevel(impl->directSound, windowHandle, isExclusive ? DSSCL_EXCLUSIVE : DSSCL_PRIORITY))) {
23047 FPL__DSOUND_INIT_ERROR(
fplAudioResultType_DeviceFailure,
"Failed setting DirectSound Cooperative Level to '%s' mode!", (isExclusive ?
"Exclusive" :
"Priority"));
23052 descDSPrimary.dwSize =
sizeof(DSBUFFERDESC);
23053 descDSPrimary.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
23054 if (FAILED(IDirectSound_CreateSoundBuffer(impl->directSound, &descDSPrimary, &impl->primaryBuffer,
fpl_null))) {
23058 LPDIRECTSOUNDBUFFER secondaryBuffer =
fpl_null;
23064 caps.dwSize =
sizeof(caps);
23065 if (FAILED(IDirectSound_GetCaps(impl->directSound, &caps))) {
23071 if ((caps.dwFlags & DSCAPS_PRIMARYSTEREO) != 0) {
23072 DWORD speakerConfig;
23073 if (SUCCEEDED(IDirectSound_GetSpeakerConfig(impl->directSound, &speakerConfig))) {
23074 DWORD channelMask = 0;
23075 waveFormat.Format.nChannels = fpl__GetDirectSoundChannelsAndMapFromSpeakerConfig(speakerConfig, &channelMask, &channelLayout);
23076 waveFormat.dwChannelMask = channelMask;
23078 waveFormat.Format.nChannels = 2;
23079 waveFormat.dwChannelMask = FPL__DirectSound_ChannelMask_Stereo;
23083 waveFormat.Format.nChannels = 1;
23084 waveFormat.dwChannelMask = FPL__DirectSound_ChannelMask_Mono;
23087 fpl__CreateChannelsMappingFromChannelMask(waveFormat.dwChannelMask, waveFormat.Format.nChannels, outputChannelMap);
23094 if (FAILED(IDirectSoundBuffer_SetFormat(impl->primaryBuffer, (WAVEFORMATEX *)&waveFormat))) {
23095 char subformatString[64];
23096 fpl__Win32FormatGuidString(subformatString,
fplArrayCount(subformatString), (
const fpl__Win32Guid *)&waveFormat.SubFormat);
23097 FPL__DSOUND_INIT_ERROR(
fplAudioResultType_UnsuportedDeviceFormat,
"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);
23101 DWORD requiredFormatSize;
23102 if (FAILED(IDirectSoundBuffer_GetFormat(impl->primaryBuffer,
fpl_null, 0, &requiredFormatSize))) {
23108 WAVEFORMATEXTENSIBLE *actualFormat = (WAVEFORMATEXTENSIBLE *)actualFormatData;
23109 if (FAILED(IDirectSoundBuffer_GetFormat(impl->primaryBuffer, (WAVEFORMATEX *)actualFormat, requiredFormatSize,
fpl_null))) {
23114 if (fpl__Win32IsEqualGuid(actualFormat->SubFormat, FPL__GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
23115 if (actualFormat->Format.wBitsPerSample == 64) {
23121 switch (actualFormat->Format.wBitsPerSample) {
23139 internalFormat.
channels = actualFormat->Format.nChannels;
23141 internalFormat.
sampleRate = actualFormat->Format.nSamplesPerSec;
23150 fplAssert(waveFormat.Format.nChannels > 0 && waveFormat.Format.nSamplesPerSec > 0 && waveFormat.Format.wBitsPerSample > 0);
23156 descDS.dwSize =
sizeof(DSBUFFERDESC);
23157 descDS.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
23158 descDS.dwBufferBytes = (DWORD)bufferSizeInBytes;
23159 descDS.lpwfxFormat = (WAVEFORMATEX *)&waveFormat;
23160 if (FAILED(IDirectSound_CreateSoundBuffer(impl->directSound, &descDS, &impl->secondaryBuffer,
fpl_null))) {
23166 "Using internal format (Channels: %u, Samplerate: %u, Type: %s, Periods: %u, Buffer size frames/bytes: %u/%u)",
23169 internalFormatTypeName,
23172 bufferSizeInBytes);
23175 if (FAILED(IDirectSoundBuffer_QueryInterface(impl->secondaryBuffer, FPL__IID_IDirectSoundNotify_Guid, (
void **)&impl->notify))) {
23180 DWORD periodSizeInBytes = bufferSizeInBytes / internalFormat.
periods;
23181 DSBPOSITIONNOTIFY notifyPoints[FPL__DIRECTSOUND_MAX_PERIODS];
23182 for (uint32_t i = 0; i < internalFormat.
periods; ++i) {
23184 if (impl->notifyEvents[i] ==
fpl_null) {
23189 notifyPoints[i].dwOffset = i * periodSizeInBytes;
23190 notifyPoints[i].hEventNotify = impl->notifyEvents[i];
23192 if (FAILED(IDirectSoundNotify_SetNotificationPositions(impl->notify, internalFormat.
periods, notifyPoints))) {
23198 if (impl->stopEvent ==
fpl_null) {
23202 *outputFormat = internalFormat;
23203 *outputDevice = internalDevice;
23207#undef FPL__DSOUND_INIT_ERROR
23210fpl_internal bool fpl__GetCurrentFrameDirectSound(
const fplAudioFormat *internalFormat, fpl__AudioBackendDirectSound *impl, uint32_t *pCurrentPos) {
23215 DWORD dwCurrentPosition;
23216 if (FAILED(IDirectSoundBuffer_GetCurrentPosition(impl->secondaryBuffer,
fpl_null, &dwCurrentPosition))) {
23225fpl_internal uint32_t fpl__GetAvailableFramesDirectSound(
const fplAudioFormat *internalFormat, fpl__AudioBackendDirectSound *impl) {
23227 uint32_t currentFrame;
23228 if (!fpl__GetCurrentFrameDirectSound(internalFormat, impl, ¤tFrame)) {
23236 uint32_t committedBeg = currentFrame;
23237 uint32_t committedEnd;
23238 committedEnd = impl->lastProcessedFrame;
23239 if (committedEnd <= committedBeg) {
23240 committedEnd += totalFrameCount;
23243 uint32_t committedSize = (committedEnd - committedBeg);
23244 fplAssert(committedSize <= totalFrameCount);
23246 return totalFrameCount - committedSize;
23249fpl_internal uint32_t fpl__WaitForFramesDirectSound(
const fplAudioFormat *internalFormat, fpl__AudioBackendDirectSound *impl) {
23255 if (timeoutInMilliseconds < 1) {
23256 timeoutInMilliseconds = 1;
23260 unsigned int eventCount = internalFormat->
periods + 1;
23261 HANDLE pEvents[FPL__DIRECTSOUND_MAX_PERIODS + 1];
23263 pEvents[eventCount - 1] = impl->stopEvent;
23265 while (!impl->breakMainLoop) {
23267 uint32_t framesAvailable = fpl__GetAvailableFramesDirectSound(internalFormat, impl);
23268 if (framesAvailable > 0) {
23269 return framesAvailable;
23273 WaitForMultipleObjects(eventCount, pEvents, FALSE, timeoutInMilliseconds);
23277 return fpl__GetAvailableFramesDirectSound(internalFormat, impl);
23280fpl_internal FPL_AUDIO_BACKEND_STOP_DEVICE_FUNC(fpl__AudioBackendDirectSoundStopDevice) {
23281 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
23285 if (FAILED(IDirectSoundBuffer_Stop(impl->secondaryBuffer))) {
23289 IDirectSoundBuffer_SetCurrentPosition(impl->secondaryBuffer, 0);
23294fpl_internal FPL_AUDIO_BACKEND_START_DEVICE_FUNC(fpl__AudioBackendDirectSoundStartDevice) {
23295 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
23298 fplAssert(backend->internalFormat.channels > 0);
23299 fplAssert(backend->internalFormat.periods > 0);
23304 uint32_t framesToRead = backend->internalFormat.bufferSizeInFrames / backend->internalFormat.periods;
23305 uint32_t desiredLockSize = framesToRead * backend->internalFormat.channels * audioSampleSizeBytes;
23308 DWORD actualLockSize;
23310 DWORD actualLockSize2;
23312 if (SUCCEEDED(IDirectSoundBuffer_Lock(impl->secondaryBuffer, 0, desiredLockSize, &pLockPtr, &actualLockSize, &pLockPtr2, &actualLockSize2, 0))) {
23313 framesToRead = actualLockSize / audioSampleSizeBytes / backend->internalFormat.channels;
23314 fpl__ReadAudioFramesFromClient(backend, framesToRead, pLockPtr);
23315 IDirectSoundBuffer_Unlock(impl->secondaryBuffer, pLockPtr, actualLockSize, pLockPtr2, actualLockSize2);
23316 impl->lastProcessedFrame = framesToRead;
23317 if (FAILED(IDirectSoundBuffer_Play(impl->secondaryBuffer, 0, 0, DSBPLAY_LOOPING))) {
23326fpl_internal FPL_AUDIO_BACKEND_STOP_MAIN_LOOP_FUNC(fpl__AudioBackendDirectSoundStopMainLoop) {
23327 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
23329 impl->breakMainLoop =
true;
23330 SetEvent(impl->stopEvent);
23333fpl_internal FPL_AUDIO_BACKEND_MAIN_LOOP_FUNC(fpl__AudioBackendDirectSoundMainLoop) {
23334 fpl__AudioBackendDirectSound *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AudioBackendDirectSound);
23337 fplAssert(backend->internalFormat.channels > 0);
23342 ResetEvent(impl->stopEvent);
23345 impl->breakMainLoop =
false;
23346 while (!impl->breakMainLoop) {
23348 uint32_t framesAvailable = fpl__WaitForFramesDirectSound(&backend->internalFormat, impl);
23349 if (framesAvailable == 0) {
23354 if (impl->breakMainLoop) {
23359 DWORD lockOffset = impl->lastProcessedFrame * backend->internalFormat.channels * audioSampleSizeBytes;
23360 DWORD lockSize = framesAvailable * backend->internalFormat.channels * audioSampleSizeBytes;
23363 DWORD actualLockSize;
23365 DWORD actualLockSize2;
23366 if (FAILED(IDirectSoundBuffer_Lock(impl->secondaryBuffer, lockOffset, lockSize, &pLockPtr, &actualLockSize, &pLockPtr2, &actualLockSize2, 0))) {
23367 FPL__ERROR(FPL__MODULE_AUDIO_DIRECTSOUND,
"Failed to lock directsound secondary buffer '%p' for offset/size (%lu / %lu)", impl->secondaryBuffer, lockOffset, lockSize);
23372 uint32_t frameCount = actualLockSize / audioSampleSizeBytes / backend->internalFormat.channels;
23373 fpl__ReadAudioFramesFromClient(backend, frameCount, pLockPtr);
23374 impl->lastProcessedFrame = (impl->lastProcessedFrame + frameCount) % backend->internalFormat.bufferSizeInFrames;
23377 IDirectSoundBuffer_Unlock(impl->secondaryBuffer, pLockPtr, actualLockSize, pLockPtr2, actualLockSize2);
23382fpl_globalvar fplAudioBackendDescriptor fpl__global_audioBackendDirectShowDescriptor = {
23385 fplStructField(fplAudioBackendDescriptorIDName,
id, { 0x618d4a47, 0x163c, 0x441d, { 0x85, 0xc6, 0x4d, 0x94, 0x33, 0x61, 0xc8, 0xb3 } }),
23386 fplStructField(fplAudioBackendDescriptorIDName, name,
"DirectSound"),
23389 fplStructField(fplAudioBackendDescriptorHeader, backendSize,
sizeof(fpl__AudioBackendDirectSound)),
23390 fplStructField(fplAudioBackendDescriptorHeader, isAsync,
false),
23394 fplStructField(fplAudioBackendFunctionTable, initialize, fpl__AudiobackendDirectSoundInitialize),
23395 fplStructField(fplAudioBackendFunctionTable, release, fpl__AudiobackendDirectSoundRelease),
23396 fplStructField(fplAudioBackendFunctionTable, getAudioDevices, fpl__AudiobackendDirectSoundGetAudioDevices),
23397 fplStructField(fplAudioBackendFunctionTable, getAudioDeviceInfo, fpl__AudiobackendDirectSoundGetAudioDeviceInfo),
23398 fplStructField(fplAudioBackendFunctionTable, initializeDevice, fpl__AudiobackendDirectSoundInitializeDevice),
23399 fplStructField(fplAudioBackendFunctionTable, releaseDevice, fpl__AudiobackendDirectSoundReleaseDevice),
23400 fplStructField(fplAudioBackendFunctionTable, startDevice, fpl__AudioBackendDirectSoundStartDevice),
23401 fplStructField(fplAudioBackendFunctionTable, stopDevice, fpl__AudioBackendDirectSoundStopDevice),
23402 fplStructField(fplAudioBackendFunctionTable, mainLoop, fpl__AudioBackendDirectSoundMainLoop),
23403 fplStructField(fplAudioBackendFunctionTable, stopMainLoop, fpl__AudioBackendDirectSoundStopMainLoop),
23414#if defined(FPL__ENABLE_AUDIO_ALSA)
23418 const char *deviceName;
23420} fpl__AlsaBufferScale;
23422fpl_globalvar fpl__AlsaBufferScale fpl__globalAlsaBufferScales[] = {
23426fpl_internal float fpl__AlsaGetBufferScale(
const char *deviceName) {
23428 for (
int i = 0; i <
fplArrayCount(fpl__globalAlsaBufferScales); ++i) {
23429 const char *testDeviceName = fpl__globalAlsaBufferScales[i].deviceName;
23431 float scale = fpl__globalAlsaBufferScales[i].scale;
23439fpl_internal uint32_t fpl__AlsaScaleBufferSize(
const uint32_t bufferSize,
const float scale) {
23440 uint32_t result =
fplMax(1, (uint32_t)(bufferSize * scale));
23457 }
else if (channels == 3) {
23467 }
else if (channels == 4) {
23472 }
else if (channels == 5) {
23486 }
else if (channels == 6) {
23493 }
else if (channels == 7) {
23514#if defined(FPL__ANONYMOUS_ALSA_HEADERS)
23515typedef void snd_pcm_t;
23516typedef void snd_pcm_format_mask_t;
23517typedef void snd_pcm_hw_params_t;
23518typedef void snd_pcm_sw_params_t;
23520typedef uint64_t snd_pcm_uframes_t;
23521typedef int64_t snd_pcm_sframes_t;
23523typedef struct snd_pcm_chmap_t {
23524 unsigned int channels;
23525 unsigned int pos[0];
23528typedef enum snd_pcm_stream_t {
23529 SND_PCM_STREAM_PLAYBACK = 0,
23530 SND_PCM_STREAM_CAPTURE,
23533typedef struct snd_pcm_channel_area_t {
23535 unsigned int first;
23537} snd_pcm_channel_area_t;
23539typedef enum snd_pcm_format_t {
23540 SND_PCM_FORMAT_UNKNOWN = -1,
23541 SND_PCM_FORMAT_S8 = 0,
23543 SND_PCM_FORMAT_S16_LE,
23544 SND_PCM_FORMAT_S16_BE,
23545 SND_PCM_FORMAT_U16_LE,
23546 SND_PCM_FORMAT_U16_BE,
23547 SND_PCM_FORMAT_S24_LE,
23548 SND_PCM_FORMAT_S24_BE,
23549 SND_PCM_FORMAT_U24_LE,
23550 SND_PCM_FORMAT_U24_BE,
23551 SND_PCM_FORMAT_S32_LE,
23552 SND_PCM_FORMAT_S32_BE,
23553 SND_PCM_FORMAT_U32_LE,
23554 SND_PCM_FORMAT_U32_BE,
23555 SND_PCM_FORMAT_FLOAT_LE,
23556 SND_PCM_FORMAT_FLOAT_BE,
23557 SND_PCM_FORMAT_FLOAT64_LE,
23558 SND_PCM_FORMAT_FLOAT64_BE,
23559 SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
23560 SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
23561 SND_PCM_FORMAT_MU_LAW,
23562 SND_PCM_FORMAT_A_LAW,
23563 SND_PCM_FORMAT_IMA_ADPCM,
23564 SND_PCM_FORMAT_MPEG,
23565 SND_PCM_FORMAT_GSM,
23566 SND_PCM_FORMAT_S20_LE,
23567 SND_PCM_FORMAT_S20_BE,
23568 SND_PCM_FORMAT_U20_LE,
23569 SND_PCM_FORMAT_U20_BE,
23570 SND_PCM_FORMAT_SPECIAL,
23571 SND_PCM_FORMAT_S24_3LE,
23572 SND_PCM_FORMAT_S24_3BE,
23573 SND_PCM_FORMAT_U24_3LE,
23574 SND_PCM_FORMAT_U24_3BE,
23575 SND_PCM_FORMAT_S20_3LE,
23576 SND_PCM_FORMAT_S20_3BE,
23577 SND_PCM_FORMAT_U20_3LE,
23578 SND_PCM_FORMAT_U20_3BE,
23579 SND_PCM_FORMAT_S18_3LE,
23580 SND_PCM_FORMAT_S18_3BE,
23581 SND_PCM_FORMAT_U18_3LE,
23582 SND_PCM_FORMAT_U18_3BE,
23583 SND_PCM_FORMAT_S16,
23584 SND_PCM_FORMAT_U16,
23585 SND_PCM_FORMAT_S24,
23586 SND_PCM_FORMAT_U24,
23587 SND_PCM_FORMAT_S32,
23588 SND_PCM_FORMAT_U32,
23589 SND_PCM_FORMAT_FLOAT,
23590 SND_PCM_FORMAT_FLOAT64,
23591 SND_PCM_FORMAT_IEC958_SUBFRAME,
23592 SND_PCM_FORMAT_S20,
23596typedef enum snd_pcm_access_t {
23597 SND_PCM_ACCESS_MMAP_INTERLEAVED = 0,
23598 SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
23599 SND_PCM_ACCESS_MMAP_COMPLEX,
23600 SND_PCM_ACCESS_RW_INTERLEAVED,
23601 SND_PCM_ACCESS_RW_NONINTERLEAVED
23604#define SND_PCM_NO_AUTO_RESAMPLE 0x00010000
23605#define SND_PCM_NO_AUTO_CHANNELS 0x00020000
23606#define SND_PCM_NO_AUTO_FORMAT 0x00040000
23609# include <alsa/asoundlib.h>
23612#define FPL__ALSA_FUNC_snd_pcm_open(name) int name(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
23613typedef FPL__ALSA_FUNC_snd_pcm_open(fpl__alsa_func_snd_pcm_open);
23614#define FPL__ALSA_FUNC_snd_pcm_close(name) int name(snd_pcm_t *pcm)
23615typedef FPL__ALSA_FUNC_snd_pcm_close(fpl__alsa_func_snd_pcm_close);
23616#define FPL__ALSA_FUNC_snd_pcm_hw_params_sizeof(name) size_t name(void)
23617typedef FPL__ALSA_FUNC_snd_pcm_hw_params_sizeof(fpl__alsa_func_snd_pcm_hw_params_sizeof);
23618#define FPL__ALSA_FUNC_snd_pcm_hw_params(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
23619typedef FPL__ALSA_FUNC_snd_pcm_hw_params(fpl__alsa_func_snd_pcm_hw_params);
23620#define FPL__ALSA_FUNC_snd_pcm_hw_params_any(name) int name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
23621typedef FPL__ALSA_FUNC_snd_pcm_hw_params_any(fpl__alsa_func_snd_pcm_hw_params_any);
23622#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)
23623typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_format(fpl__alsa_func_snd_pcm_hw_params_set_format);
23624#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)
23625typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_format_first(fpl__alsa_func_snd_pcm_hw_params_set_format_first);
23626#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)
23627typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_format_mask(fpl__alsa_func_snd_pcm_hw_params_get_format_mask);
23628#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)
23629typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_channels_near(fpl__alsa_func_snd_pcm_hw_params_set_channels_near);
23630#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)
23631typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_rate_resample(fpl__alsa_func_snd_pcm_hw_params_set_rate_resample);
23632#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)
23633typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_rate_near(fpl__alsa_func_snd_pcm_hw_params_set_rate_near);
23634#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)
23635typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_buffer_size_near(fpl__alsa_func_snd_pcm_hw_params_set_buffer_size_near);
23636#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)
23637typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_periods_near(fpl__alsa_func_snd_pcm_hw_params_set_periods_near);
23638#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)
23639typedef FPL__ALSA_FUNC_snd_pcm_hw_params_set_access(fpl__alsa_func_snd_pcm_hw_params_set_access);
23640#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)
23641typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_format(fpl__alsa_func_snd_pcm_hw_params_get_format);
23642#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_channels(name) int name(const snd_pcm_hw_params_t *params, unsigned int *val)
23643typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_channels(fpl__alsa_func_snd_pcm_hw_params_get_channels);
23644#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)
23645typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_rate(fpl__alsa_func_snd_pcm_hw_params_get_rate);
23646#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)
23647typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_buffer_size(fpl__alsa_func_snd_pcm_hw_params_get_buffer_size);
23648#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)
23649typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_periods(fpl__alsa_func_snd_pcm_hw_params_get_periods);
23650#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)
23651typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_access(fpl__alsa_func_snd_pcm_hw_params_get_access);
23652#define FPL__ALSA_FUNC_snd_pcm_hw_params_get_sbits(name) int name(const snd_pcm_hw_params_t *params)
23653typedef FPL__ALSA_FUNC_snd_pcm_hw_params_get_sbits(fpl__alsa_func_snd_pcm_hw_params_get_sbits);
23654#define FPL__ALSA_FUNC_snd_pcm_sw_params_sizeof(name) size_t name(void)
23655typedef FPL__ALSA_FUNC_snd_pcm_sw_params_sizeof(fpl__alsa_func_snd_pcm_sw_params_sizeof);
23656#define FPL__ALSA_FUNC_snd_pcm_sw_params_current(name) int name(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
23657typedef FPL__ALSA_FUNC_snd_pcm_sw_params_current(fpl__alsa_func_snd_pcm_sw_params_current);
23658#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)
23659typedef FPL__ALSA_FUNC_snd_pcm_sw_params_set_avail_min(fpl__alsa_func_snd_pcm_sw_params_set_avail_min);
23660#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)
23661typedef FPL__ALSA_FUNC_snd_pcm_sw_params_set_start_threshold(fpl__alsa_func_snd_pcm_sw_params_set_start_threshold);
23662#define FPL__ALSA_FUNC_snd_pcm_sw_params(name) int name(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
23663typedef FPL__ALSA_FUNC_snd_pcm_sw_params(fpl__alsa_func_snd_pcm_sw_params);
23664#define FPL__ALSA_FUNC_snd_pcm_format_mask_sizeof(name) size_t name(void)
23665typedef FPL__ALSA_FUNC_snd_pcm_format_mask_sizeof(fpl__alsa_func_snd_pcm_format_mask_sizeof);
23666#define FPL__ALSA_FUNC_snd_pcm_format_mask_test(name) int name(const snd_pcm_format_mask_t *mask, snd_pcm_format_t val)
23667typedef FPL__ALSA_FUNC_snd_pcm_format_mask_test(fpl__alsa_func_snd_pcm_format_mask_test);
23668#define FPL__ALSA_FUNC_snd_pcm_get_chmap(name) snd_pcm_chmap_t *name(snd_pcm_t *pcm)
23669typedef FPL__ALSA_FUNC_snd_pcm_get_chmap(fpl__alsa_func_snd_pcm_get_chmap);
23670#define FPL__ALSA_FUNC_snd_pcm_prepare(name) int name(snd_pcm_t *pcm)
23671typedef FPL__ALSA_FUNC_snd_pcm_prepare(fpl__alsa_func_snd_pcm_prepare);
23672#define FPL__ALSA_FUNC_snd_pcm_start(name) int name(snd_pcm_t *pcm)
23673typedef FPL__ALSA_FUNC_snd_pcm_start(fpl__alsa_func_snd_pcm_start);
23674#define FPL__ALSA_FUNC_snd_pcm_drop(name) int name(snd_pcm_t *pcm)
23675typedef FPL__ALSA_FUNC_snd_pcm_drop(fpl__alsa_func_snd_pcm_drop);
23676#define FPL__ALSA_FUNC_snd_device_name_hint(name) int name(int card, const char *iface, void ***hints)
23677typedef FPL__ALSA_FUNC_snd_device_name_hint(fpl__alsa_func_snd_device_name_hint);
23678#define FPL__ALSA_FUNC_snd_device_name_get_hint(name) char *name(const void *hint, const char *id)
23679typedef FPL__ALSA_FUNC_snd_device_name_get_hint(fpl__alsa_func_snd_device_name_get_hint);
23680#define FPL__ALSA_FUNC_snd_device_name_free_hint(name) int name(void **hints)
23681typedef FPL__ALSA_FUNC_snd_device_name_free_hint(fpl__alsa_func_snd_device_name_free_hint);
23682#define FPL__ALSA_FUNC_snd_card_get_index(name) int name(const char *name)
23683typedef FPL__ALSA_FUNC_snd_card_get_index(fpl__alsa_func_snd_card_get_index);
23684#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)
23685typedef FPL__ALSA_FUNC_snd_pcm_mmap_begin(fpl__alsa_func_snd_pcm_mmap_begin);
23686#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)
23687typedef FPL__ALSA_FUNC_snd_pcm_mmap_commit(fpl__alsa_func_snd_pcm_mmap_commit);
23688#define FPL__ALSA_FUNC_snd_pcm_recover(name) int name(snd_pcm_t *pcm, int err, int silent)
23689typedef FPL__ALSA_FUNC_snd_pcm_recover(fpl__alsa_func_snd_pcm_recover);
23690#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)
23691typedef FPL__ALSA_FUNC_snd_pcm_writei(fpl__alsa_func_snd_pcm_writei);
23692#define FPL__ALSA_FUNC_snd_pcm_avail(name) snd_pcm_sframes_t name(snd_pcm_t *pcm)
23693typedef FPL__ALSA_FUNC_snd_pcm_avail(fpl__alsa_func_snd_pcm_avail);
23694#define FPL__ALSA_FUNC_snd_pcm_avail_update(name) snd_pcm_sframes_t name(snd_pcm_t *pcm)
23695typedef FPL__ALSA_FUNC_snd_pcm_avail_update(fpl__alsa_func_snd_pcm_avail_update);
23696#define FPL__ALSA_FUNC_snd_pcm_wait(name) int name(snd_pcm_t *pcm, int timeout)
23697typedef FPL__ALSA_FUNC_snd_pcm_wait(fpl__alsa_func_snd_pcm_wait);
23698#define FPL__ALSA_FUNC_snd_pcm_info_sizeof(name) size_t name(void)
23699typedef FPL__ALSA_FUNC_snd_pcm_info_sizeof(fpl__alsa_func_snd_pcm_info_sizeof);
23700#define FPL__ALSA_FUNC_snd_pcm_info(name) int name(snd_pcm_t *handle, snd_pcm_info_t *info)
23701typedef FPL__ALSA_FUNC_snd_pcm_info(fpl__alsa_func_snd_pcm_info);
23702#define FPL__ALSA_FUNC_snd_pcm_info_get_name(name) const char* name(const snd_pcm_info_t *obj)
23703typedef FPL__ALSA_FUNC_snd_pcm_info_get_name(fpl__alsa_func_snd_pcm_info_get_name);
23707 fpl__alsa_func_snd_pcm_open *snd_pcm_open;
23708 fpl__alsa_func_snd_pcm_close *snd_pcm_close;
23709 fpl__alsa_func_snd_pcm_hw_params_sizeof *snd_pcm_hw_params_sizeof;
23710 fpl__alsa_func_snd_pcm_hw_params *snd_pcm_hw_params;
23711 fpl__alsa_func_snd_pcm_hw_params_any *snd_pcm_hw_params_any;
23712 fpl__alsa_func_snd_pcm_hw_params_set_format *snd_pcm_hw_params_set_format;
23713 fpl__alsa_func_snd_pcm_hw_params_set_format_first *snd_pcm_hw_params_set_format_first;
23714 fpl__alsa_func_snd_pcm_hw_params_get_format_mask *snd_pcm_hw_params_get_format_mask;
23715 fpl__alsa_func_snd_pcm_hw_params_set_channels_near *snd_pcm_hw_params_set_channels_near;
23716 fpl__alsa_func_snd_pcm_hw_params_set_rate_resample *snd_pcm_hw_params_set_rate_resample;
23717 fpl__alsa_func_snd_pcm_hw_params_set_rate_near *snd_pcm_hw_params_set_rate_near;
23718 fpl__alsa_func_snd_pcm_hw_params_set_buffer_size_near *snd_pcm_hw_params_set_buffer_size_near;
23719 fpl__alsa_func_snd_pcm_hw_params_set_periods_near *snd_pcm_hw_params_set_periods_near;
23720 fpl__alsa_func_snd_pcm_hw_params_set_access *snd_pcm_hw_params_set_access;
23721 fpl__alsa_func_snd_pcm_hw_params_get_format *snd_pcm_hw_params_get_format;
23722 fpl__alsa_func_snd_pcm_hw_params_get_channels *snd_pcm_hw_params_get_channels;
23723 fpl__alsa_func_snd_pcm_hw_params_get_rate *snd_pcm_hw_params_get_rate;
23724 fpl__alsa_func_snd_pcm_hw_params_get_buffer_size *snd_pcm_hw_params_get_buffer_size;
23725 fpl__alsa_func_snd_pcm_hw_params_get_periods *snd_pcm_hw_params_get_periods;
23726 fpl__alsa_func_snd_pcm_hw_params_get_access *snd_pcm_hw_params_get_access;
23727 fpl__alsa_func_snd_pcm_hw_params_get_sbits *snd_pcm_hw_params_get_sbits;
23728 fpl__alsa_func_snd_pcm_sw_params_sizeof *snd_pcm_sw_params_sizeof;
23729 fpl__alsa_func_snd_pcm_sw_params_current *snd_pcm_sw_params_current;
23730 fpl__alsa_func_snd_pcm_sw_params_set_avail_min *snd_pcm_sw_params_set_avail_min;
23731 fpl__alsa_func_snd_pcm_sw_params_set_start_threshold *snd_pcm_sw_params_set_start_threshold;
23732 fpl__alsa_func_snd_pcm_sw_params *snd_pcm_sw_params;
23733 fpl__alsa_func_snd_pcm_format_mask_sizeof *snd_pcm_format_mask_sizeof;
23734 fpl__alsa_func_snd_pcm_format_mask_test *snd_pcm_format_mask_test;
23735 fpl__alsa_func_snd_pcm_get_chmap *snd_pcm_get_chmap;
23736 fpl__alsa_func_snd_pcm_prepare *snd_pcm_prepare;
23737 fpl__alsa_func_snd_pcm_start *snd_pcm_start;
23738 fpl__alsa_func_snd_pcm_drop *snd_pcm_drop;
23739 fpl__alsa_func_snd_device_name_hint *snd_device_name_hint;
23740 fpl__alsa_func_snd_device_name_get_hint *snd_device_name_get_hint;
23741 fpl__alsa_func_snd_device_name_free_hint *snd_device_name_free_hint;
23742 fpl__alsa_func_snd_card_get_index *snd_card_get_index;
23743 fpl__alsa_func_snd_pcm_mmap_begin *snd_pcm_mmap_begin;
23744 fpl__alsa_func_snd_pcm_mmap_commit *snd_pcm_mmap_commit;
23745 fpl__alsa_func_snd_pcm_recover *snd_pcm_recover;
23746 fpl__alsa_func_snd_pcm_writei *snd_pcm_writei;
23747 fpl__alsa_func_snd_pcm_avail *snd_pcm_avail;
23748 fpl__alsa_func_snd_pcm_avail_update *snd_pcm_avail_update;
23749 fpl__alsa_func_snd_pcm_wait *snd_pcm_wait;
23750 fpl__alsa_func_snd_pcm_info_sizeof *snd_pcm_info_sizeof;
23751 fpl__alsa_func_snd_pcm_info *snd_pcm_info;
23752 fpl__alsa_func_snd_pcm_info_get_name *snd_pcm_info_get_name;
23753} fpl__AlsaAudioApi;
23756 fpl__AlsaAudioApi api;
23757 snd_pcm_t *pcmDevice;
23758 void *intermediaryBuffer;
23760 bool breakMainLoop;
23761} fpl__AlsaAudioBackend;
23763fpl_internal void fpl__UnloadAlsaApi(fpl__AlsaAudioApi *alsaApi) {
23765 if (alsaApi->libHandle !=
fpl_null) {
23766 dlclose(alsaApi->libHandle);
23771fpl_internal bool fpl__LoadAlsaApi(fpl__AlsaAudioApi *alsaApi) {
23773 const char *libraryNames[] = {
23776 bool result =
false;
23777 for (uint32_t index = 0; index <
fplArrayCount(libraryNames); ++index) {
23778 const char *libName = libraryNames[index];
23782 FPL__POSIX_LOAD_LIBRARY(FPL__MODULE_AUDIO_ALSA, libHandle, libName);
23783 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_open, snd_pcm_open);
23784 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_close, snd_pcm_close);
23785 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);
23786 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_hw_params, snd_pcm_hw_params);
23787 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);
23788 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);
23789 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);
23790 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);
23791 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);
23792 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);
23793 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);
23794 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);
23795 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);
23796 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);
23797 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);
23798 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);
23799 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);
23800 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);
23801 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);
23802 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);
23803 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);
23804 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);
23805 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);
23806 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);
23807 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);
23808 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_sw_params, snd_pcm_sw_params);
23809 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);
23810 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);
23811 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_get_chmap, snd_pcm_get_chmap);
23812 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_prepare, snd_pcm_prepare);
23813 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_start, snd_pcm_start);
23814 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_drop, snd_pcm_drop);
23815 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_device_name_hint, snd_device_name_hint);
23816 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);
23817 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);
23818 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_card_get_index, snd_card_get_index);
23819 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_mmap_begin, snd_pcm_mmap_begin);
23820 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_mmap_commit, snd_pcm_mmap_commit);
23821 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_recover, snd_pcm_recover);
23822 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_writei, snd_pcm_writei);
23823 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_avail, snd_pcm_avail);
23824 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_avail_update, snd_pcm_avail_update);
23825 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_wait, snd_pcm_wait);
23826 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_info_sizeof, snd_pcm_info_sizeof);
23827 FPL__POSIX_GET_FUNCTION_ADDRESS(FPL__MODULE_AUDIO_ALSA, libHandle, libName, alsaApi, fpl__alsa_func_snd_pcm_info, snd_pcm_info);
23828 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);
23829 alsaApi->libHandle = libHandle;
23835 fpl__UnloadAlsaApi(alsaApi);
23840fpl_internal uint32_t fpl__AudioWaitForFramesAlsa(
const fplAudioFormat *deviceFormat, fpl__AlsaAudioBackend *backend,
bool *requiresRestart) {
23842 if (requiresRestart !=
fpl_null) {
23843 *requiresRestart =
false;
23845 const fpl__AlsaAudioApi *alsaApi = &backend->api;
23847 while (!backend->breakMainLoop) {
23848 snd_pcm_sframes_t framesAvailable = alsaApi->snd_pcm_avail_update(backend->pcmDevice);
23849 if (framesAvailable < 0) {
23850 if (framesAvailable == -EPIPE) {
23851 if (alsaApi->snd_pcm_recover(backend->pcmDevice, framesAvailable, 1) < 0) {
23854 if (requiresRestart !=
fpl_null) {
23855 *requiresRestart =
true;
23857 framesAvailable = alsaApi->snd_pcm_avail_update(backend->pcmDevice);
23858 if (framesAvailable < 0) {
23865 if (framesAvailable >= periodSizeInFrames) {
23866 return periodSizeInFrames;
23869 if (framesAvailable < periodSizeInFrames) {
23871 int waitResult = alsaApi->snd_pcm_wait(backend->pcmDevice, -1);
23872 if (waitResult < 0) {
23873 if (waitResult == -EPIPE) {
23874 if (alsaApi->snd_pcm_recover(backend->pcmDevice, waitResult, 1) < 0) {
23877 if (requiresRestart !=
fpl_null) {
23878 *requiresRestart =
true;
23886 snd_pcm_sframes_t framesAvailable = alsaApi->snd_pcm_avail_update(backend->pcmDevice);
23887 if (framesAvailable < 0) {
23890 return framesAvailable;
23893fpl_internal bool fpl__GetAudioFramesFromClientAlsa(fplAudioContext *context, fplAudioBackend *backend) {
23894 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
23897 const fpl__AlsaAudioApi *alsaApi = &impl->api;
23899 if (!fpl__IsAudioDeviceStarted(context) && fpl__AudioGetDeviceState(context) != fpl__AudioDeviceState_Starting) {
23902 if (impl->breakMainLoop) {
23906 if (impl->isUsingMMap) {
23908 bool requiresRestart;
23909 uint32_t framesAvailable = fpl__AudioWaitForFramesAlsa(&backend->internalFormat, impl, &requiresRestart);
23910 if (framesAvailable == 0) {
23913 if (impl->breakMainLoop) {
23917 const snd_pcm_channel_area_t *channelAreas;
23918 snd_pcm_uframes_t mappedOffset;
23919 snd_pcm_uframes_t mappedFrames = framesAvailable;
23920 while (framesAvailable > 0) {
23921 int result = alsaApi->snd_pcm_mmap_begin(impl->pcmDevice, &channelAreas, &mappedOffset, &mappedFrames);
23925 if (mappedFrames > 0) {
23926 void *bufferPtr = (uint8_t *)channelAreas[0].addr + ((channelAreas[0].first + (mappedOffset * channelAreas[0].step)) / 8);
23927 fpl__ReadAudioFramesFromClient(backend, mappedFrames, bufferPtr);
23929 result = alsaApi->snd_pcm_mmap_commit(impl->pcmDevice, mappedOffset, mappedFrames);
23930 if (result < 0 || (snd_pcm_uframes_t)result != mappedFrames) {
23931 alsaApi->snd_pcm_recover(impl->pcmDevice, result, 1);
23934 if (requiresRestart) {
23935 if (alsaApi->snd_pcm_start(impl->pcmDevice) < 0) {
23939 if (framesAvailable >= mappedFrames) {
23940 framesAvailable -= mappedFrames;
23942 framesAvailable = 0;
23948 while (!impl->breakMainLoop) {
23949 uint32_t framesAvailable = fpl__AudioWaitForFramesAlsa(&backend->internalFormat, impl,
fpl_null);
23950 if (framesAvailable == 0) {
23953 if (impl->breakMainLoop) {
23956 fpl__ReadAudioFramesFromClient(backend, framesAvailable, impl->intermediaryBuffer);
23957 snd_pcm_sframes_t framesWritten = alsaApi->snd_pcm_writei(impl->pcmDevice, impl->intermediaryBuffer, framesAvailable);
23958 if (framesWritten < 0) {
23959 if (framesWritten == -EAGAIN) {
23962 }
else if (framesWritten == -EPIPE) {
23964 if (alsaApi->snd_pcm_recover(impl->pcmDevice, framesWritten, 1) < 0) {
23965 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to recover device after underrun!");
23968 framesWritten = alsaApi->snd_pcm_writei(impl->pcmDevice, impl->intermediaryBuffer, framesAvailable);
23969 if (framesWritten < 0) {
23970 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to write data to the PCM device!");
23976 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to write audio frames from client, error code: %d!", framesWritten);
23988fpl_internal FPL_AUDIO_BACKEND_STOP_MAIN_LOOP_FUNC(fpl__AudioBackendAlsaStopMainLoop) {
23989 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
23992 impl->breakMainLoop =
true;
23995fpl_internal FPL_AUDIO_BACKEND_RELEASE_DEVICE_FUNC(fpl__AudioBackendAlsaReleaseDevice) {
23996 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
23999 fpl__AlsaAudioApi *alsaApi = &impl->api;
24001 if (impl->pcmDevice !=
fpl_null) {
24002 alsaApi->snd_pcm_close(impl->pcmDevice);
24006 if (impl->intermediaryBuffer !=
fpl_null) {
24007 fpl__ReleaseDynamicMemory(impl->intermediaryBuffer);
24008 impl->intermediaryBuffer =
fpl_null;
24014fpl_internal FPL_AUDIO_BACKEND_RELEASE_FUNC(fpl__AudioBackendAlsaRelease) {
24015 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
24018 fpl__AudioBackendAlsaReleaseDevice(context, backend);
24025fpl_internal FPL_AUDIO_BACKEND_START_DEVICE_FUNC(fpl__AudioBackendAlsaStartDevice) {
24026 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
24029 const fpl__AlsaAudioApi *alsaApi = &impl->api;
24032 if (alsaApi->snd_pcm_prepare(impl->pcmDevice) < 0) {
24033 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to prepare PCM device '%p'!", impl->pcmDevice);
24038 if (!fpl__GetAudioFramesFromClientAlsa(context, backend)) {
24039 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to get initial audio frames from client!");
24043 if (impl->isUsingMMap) {
24044 if (alsaApi->snd_pcm_start(impl->pcmDevice) < 0) {
24045 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to start PCM device '%p'!", impl->pcmDevice);
24053fpl_internal FPL_AUDIO_BACKEND_STOP_DEVICE_FUNC(fpl__AudioBackendAlsaStopDevice) {
24054 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
24057 const fpl__AlsaAudioApi *alsaApi = &impl->api;
24059 if (alsaApi->snd_pcm_drop(impl->pcmDevice)) {
24060 FPL__ERROR(FPL__MODULE_AUDIO_ALSA,
"Failed to drop the PCM device '%p'!", impl->pcmDevice);
24072 return SND_PCM_FORMAT_U8;
24074 return SND_PCM_FORMAT_S16_BE;
24076 return SND_PCM_FORMAT_S24_3BE;
24078 return SND_PCM_FORMAT_S32_BE;
24080 return SND_PCM_FORMAT_FLOAT_BE;
24082 return SND_PCM_FORMAT_UNKNOWN;
24087 return SND_PCM_FORMAT_U8;
24089 return SND_PCM_FORMAT_S16_LE;
24091 return SND_PCM_FORMAT_S24_3LE;
24093 return SND_PCM_FORMAT_S32_LE;
24095 return SND_PCM_FORMAT_FLOAT_LE;
24097 return SND_PCM_FORMAT_UNKNOWN;
24102fpl_internal FPL_AUDIO_BACKEND_MAIN_LOOP_FUNC(fpl__AudioBackendAlsaMainLoop) {
24103 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
24106 impl->breakMainLoop =
false;
24107 while (!impl->breakMainLoop && fpl__GetAudioFramesFromClientAlsa(context, backend)) {
24114 case SND_PCM_FORMAT_U8:
24116 case SND_PCM_FORMAT_S16_BE:
24117 case SND_PCM_FORMAT_S16_LE:
24119 case SND_PCM_FORMAT_S24_3BE:
24120 case SND_PCM_FORMAT_S24_3LE:
24122 case SND_PCM_FORMAT_S32_BE:
24123 case SND_PCM_FORMAT_S32_LE:
24125 case SND_PCM_FORMAT_FLOAT_BE:
24126 case SND_PCM_FORMAT_FLOAT_LE:
24133fpl_internal FPL_AUDIO_BACKEND_INITIALIZE_FUNC(fpl__AudioBackendAlsaInitialize) {
24134 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
24137# define FPL__ALSA_INIT_ERROR(ret, format, ...) do { \
24138 FPL__ERROR(FPL__MODULE_AUDIO_ALSA, format, ## __VA_ARGS__); \
24139 fpl__AudioBackendAlsaRelease(context, backend); \
24144 fpl__AlsaAudioApi *alsaApi = &impl->api;
24145 if (!fpl__LoadAlsaApi(alsaApi)) {
24150#undef FPL__ALSA_INIT_ERROR
24153fpl_internal FPL_AUDIO_BACKEND_INITIALIZE_DEVICE_FUNC(fpl__AudioBackendAlsaInitializeDevice) {
24154 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
24157 snd_pcm_hw_params_t *hardwareParams =
fpl_null;
24158 snd_pcm_sw_params_t *softwareParams =
fpl_null;
24159 snd_pcm_info_t *pcmInfo =
fpl_null;
24161# define FPL__ALSA_INIT_ERROR(ret, format, ...) do { \
24162 if (pcmInfo != fpl_null) fpl__ReleaseTemporaryMemory(pcmInfo); \
24163 if (softwareParams != fpl_null) fpl__ReleaseTemporaryMemory(softwareParams); \
24164 if (hardwareParams != fpl_null) fpl__ReleaseTemporaryMemory(hardwareParams); \
24165 FPL__ERROR(FPL__MODULE_AUDIO_ALSA, format, ## __VA_ARGS__); \
24166 fpl__AudioBackendAlsaReleaseDevice(context, backend); \
24171 fpl__AlsaAudioApi *alsaApi = &impl->api;
24172 if (alsaApi->libHandle ==
fpl_null) {
24181 const char *alsaDeviceID =
fpl_null;
24183 alsaDeviceID = targetDevice->id.alsa;
24188 snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
24189 int openMode = SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT;
24191 const char *defaultDeviceNames[16] =
fplZeroInit;
24192 int defaultDeviceCount = 0;
24193 defaultDeviceNames[defaultDeviceCount++] =
"default";
24195 defaultDeviceNames[defaultDeviceCount++] =
"dmix";
24196 defaultDeviceNames[defaultDeviceCount++] =
"dmix:0";
24197 defaultDeviceNames[defaultDeviceCount++] =
"dmix:0,0";
24199 defaultDeviceNames[defaultDeviceCount++] =
"hw";
24200 defaultDeviceNames[defaultDeviceCount++] =
"hw:0";
24201 defaultDeviceNames[defaultDeviceCount++] =
"hw:0,0";
24203 bool isDeviceOpen =
false;
24204 for (
size_t defaultDeviceIndex = 0; defaultDeviceIndex < defaultDeviceCount; ++defaultDeviceIndex) {
24205 const char *defaultDeviceName = defaultDeviceNames[defaultDeviceIndex];
24206 FPL_LOG_DEBUG(
"ALSA",
"Opening PCM audio device '%s'", defaultDeviceName);
24207 if (alsaApi->snd_pcm_open(&impl->pcmDevice, defaultDeviceName, stream, openMode) == 0) {
24208 FPL_LOG_DEBUG(
"ALSA",
"Successfully opened PCM audio device '%s'", defaultDeviceName);
24209 isDeviceOpen =
true;
24215 FPL_LOG_WARN(
"ALSA",
"Failed opening default PCM audio device '%s'!", defaultDeviceName);
24218 if (!isDeviceOpen) {
24223 if (alsaApi->snd_pcm_open(&impl->pcmDevice, alsaDeviceID, stream, openMode) < 0) {
24231 const char *internalDeviceId = &internalDevice.
id.alsa[0];
24240 size_t pcmInfoSize = alsaApi->snd_pcm_info_sizeof();
24241 pcmInfo = (snd_pcm_info_t *)fpl__AllocateTemporaryMemory(pcmInfoSize, 8);
24246 if (alsaApi->snd_pcm_info(impl->pcmDevice, pcmInfo) == 0) {
24247 const char *pcmName = alsaApi->snd_pcm_info_get_name(pcmInfo);
24251 char **ppDeviceHints;
24252 if (alsaApi->snd_device_name_hint(-1,
"pcm", (
void ***)&ppDeviceHints) == 0) {
24253 char **ppNextDeviceHint = ppDeviceHints;
24254 while (*ppNextDeviceHint !=
fpl_null) {
24255 char *hintName = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"NAME");
24256 char *hintDesc = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"DESC");
24257 char *hintIOID = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"IOID");
24259 bool foundDevice =
false;
24263 foundDevice =
true;
24272 ++ppNextDeviceHint;
24279 alsaApi->snd_device_name_free_hint((
void **)ppDeviceHints);
24294 float bufferSizeScaleFactor = 1.0f;
24297 bufferSizeScaleFactor = fpl__AlsaGetBufferScale(internalDevice.
name);
24305 FPL_LOG_DEBUG(
"ALSA",
"Get hardware parameters from device '%s'", internalDeviceId);
24306 size_t hardwareParamsSize = alsaApi->snd_pcm_hw_params_sizeof();
24307 hardwareParams = (snd_pcm_hw_params_t *)fpl__AllocateTemporaryMemory(hardwareParamsSize, 8);
24309 if (alsaApi->snd_pcm_hw_params_any(impl->pcmDevice, hardwareParams) < 0) {
24312 FPL_LOG_DEBUG(
"ALSA",
"Successfullyy got hardware parameters from device '%s'", internalDeviceId);
24317 impl->isUsingMMap =
false;
24318 if (!audioSettings->alsa.noMMap) {
24319 if (alsaApi->snd_pcm_hw_params_set_access(impl->pcmDevice, hardwareParams, SND_PCM_ACCESS_MMAP_INTERLEAVED) == 0) {
24320 impl->isUsingMMap =
true;
24322 FPL_LOG_ERROR(
"ALSA",
"Failed setting MMap access mode for device '%s', trying fallback to standard mode!", internalDeviceId);
24325 if (!impl->isUsingMMap) {
24326 if (alsaApi->snd_pcm_hw_params_set_access(impl->pcmDevice, hardwareParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
24338 size_t formatMaskSize = alsaApi->snd_pcm_format_mask_sizeof();
24339 snd_pcm_format_mask_t *formatMask = (snd_pcm_format_mask_t *)fpl__AllocateTemporaryMemory(formatMaskSize, 8);
24341 alsaApi->snd_pcm_hw_params_get_format_mask(hardwareParams, formatMask);
24343 snd_pcm_format_t foundFormat;
24344 snd_pcm_format_t preferredFormat = fpl__MapAudioFormatToAlsaFormat(targetFormat->type);
24345 if (!alsaApi->snd_pcm_format_mask_test(formatMask, preferredFormat)) {
24348 snd_pcm_format_t defaultFormats[] = {
24349 isBigEndian ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE,
24350 isBigEndian ? SND_PCM_FORMAT_FLOAT_BE : SND_PCM_FORMAT_FLOAT_LE,
24351 isBigEndian ? SND_PCM_FORMAT_S32_BE : SND_PCM_FORMAT_S32_LE,
24352 isBigEndian ? SND_PCM_FORMAT_S24_3BE : SND_PCM_FORMAT_S24_3LE,
24355 foundFormat = SND_PCM_FORMAT_UNKNOWN;
24356 for (
size_t defaultFormatIndex = 0; defaultFormatIndex <
fplArrayCount(defaultFormats); ++defaultFormatIndex) {
24357 snd_pcm_format_t defaultFormat = defaultFormats[defaultFormatIndex];
24358 if (alsaApi->snd_pcm_format_mask_test(formatMask, defaultFormat)) {
24359 foundFormat = defaultFormat;
24364 foundFormat = preferredFormat;
24367 fpl__ReleaseTemporaryMemory(formatMask);
24369 if (foundFormat == SND_PCM_FORMAT_UNKNOWN) {
24373 if (alsaApi->snd_pcm_hw_params_set_format(impl->pcmDevice, hardwareParams, foundFormat) < 0) {
24376 internalFormat.
type = fpl__MapAlsaFormatToAudioFormat(foundFormat);
24381 unsigned int internalChannels = targetFormat->channels;
24382 if (alsaApi->snd_pcm_hw_params_set_channels_near(impl->pcmDevice, hardwareParams, &internalChannels) < 0) {
24385 internalFormat.
channels = internalChannels;
24389 fpl__SetAudioDefaultChannelMapALSA(internalFormat.
channels, internalFormat.
channelLayout, outputChannelMap);
24396 alsaApi->snd_pcm_hw_params_set_rate_resample(impl->pcmDevice, hardwareParams, 0);
24397 unsigned int actualSampleRate = targetFormat->sampleRate;
24399 if (alsaApi->snd_pcm_hw_params_set_rate_near(impl->pcmDevice, hardwareParams, &actualSampleRate, 0) < 0) {
24402 internalFormat.
sampleRate = actualSampleRate;
24407 snd_pcm_uframes_t actualBufferSize;
24409 actualBufferSize = fpl__AlsaScaleBufferSize(targetFormat->bufferSizeInFrames, bufferSizeScaleFactor);
24411 actualBufferSize = targetFormat->bufferSizeInFrames;
24414 if (alsaApi->snd_pcm_hw_params_set_buffer_size_near(impl->pcmDevice, hardwareParams, &actualBufferSize) < 0) {
24426 uint32_t internalPeriods = targetFormat->periods;
24427 int periodsDir = 0;
24428 if (alsaApi->snd_pcm_hw_params_set_periods_near(impl->pcmDevice, hardwareParams, &internalPeriods, &periodsDir) < 0) {
24429 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed setting PCM periods '%lu' for device '%s'!", internalPeriods, internalDeviceId);
24431 internalFormat.
periods = internalPeriods;
24436 if (alsaApi->snd_pcm_hw_params(impl->pcmDevice, hardwareParams) < 0) {
24437 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed to install PCM hardware parameters for device '%s'!", internalDeviceId);
24443 size_t softwareParamsSize = alsaApi->snd_pcm_sw_params_sizeof();
24444 softwareParams = (snd_pcm_sw_params_t *)fpl__AllocateTemporaryMemory(softwareParamsSize, 8);
24446 if (alsaApi->snd_pcm_sw_params_current(impl->pcmDevice, softwareParams) < 0) {
24447 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed to get software parameters for device '%s'!", internalDeviceId);
24449 snd_pcm_uframes_t minAvailableFrames = fpl__PrevPowerOfTwo(internalFormat.
bufferSizeInFrames / internalFormat.
periods);
24450 if (alsaApi->snd_pcm_sw_params_set_avail_min(impl->pcmDevice, softwareParams, minAvailableFrames) < 0) {
24451 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed to set software available min frames of '%lu' for device '%s'!", minAvailableFrames, internalDeviceId);
24453 if (!impl->isUsingMMap) {
24455 if (alsaApi->snd_pcm_sw_params_set_start_threshold(impl->pcmDevice, softwareParams, threshold) < 0) {
24456 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed to set start threshold of '%lu' for device '%s'!", threshold, internalDeviceId);
24459 if (alsaApi->snd_pcm_sw_params(impl->pcmDevice, softwareParams) < 0) {
24460 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed to install PCM software parameters for device '%s'!", internalDeviceId);
24463 if (!impl->isUsingMMap) {
24465 impl->intermediaryBuffer = fpl__AllocateDynamicMemory(bufferSizeInBytes, 16);
24466 if (impl->intermediaryBuffer ==
fpl_null) {
24467 FPL__ALSA_INIT_ERROR(
fplAudioResultType_Failed,
"Failed allocating intermediary buffer of size '%lu' for device '%s'!", bufferSizeInBytes, internalDeviceId);
24471 fpl__ReleaseTemporaryMemory(pcmInfo);
24472 fpl__ReleaseTemporaryMemory(softwareParams);
24473 fpl__ReleaseTemporaryMemory(hardwareParams);
24475 *outputFormat = internalFormat;
24476 *outputDevice = internalDevice;
24480#undef FPL__ALSA_INIT_ERROR
24483fpl_internal FPL_AUDIO_BACKEND_GET_AUDIO_DEVICE_INFO_FUNC(fpl__AudioBackendALSAGetAudioDeviceInfo) {
24484 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
24487 fpl__AlsaAudioApi *alsaApi = &impl->api;
24488 if (alsaApi->libHandle ==
fpl_null) {
24489 FPL__WARNING(FPL__MODULE_AUDIO_ALSA,
"API is not loaded!"); \
24498 deviceID = *targetDevice;
24506 snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
24507 int openMode = SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT;
24509 const char *defaultDeviceNames[16] =
fplZeroInit;
24510 int defaultDeviceCount = 0;
24511 defaultDeviceNames[defaultDeviceCount++] =
"default";
24513 defaultDeviceNames[defaultDeviceCount++] =
"dmix";
24514 defaultDeviceNames[defaultDeviceCount++] =
"dmix:0";
24515 defaultDeviceNames[defaultDeviceCount++] =
"dmix:0,0";
24517 defaultDeviceNames[defaultDeviceCount++] =
"hw";
24518 defaultDeviceNames[defaultDeviceCount++] =
"hw:0";
24519 defaultDeviceNames[defaultDeviceCount++] =
"hw:0,0";
24521 bool isDeviceOpen =
false;
24522 for (
size_t defaultDeviceIndex = 0; defaultDeviceIndex < defaultDeviceCount; ++defaultDeviceIndex) {
24523 const char *defaultDeviceName = defaultDeviceNames[defaultDeviceIndex];
24524 FPL_LOG_DEBUG(
"ALSA",
"Opening PCM audio device '%s'", defaultDeviceName);
24525 if (alsaApi->snd_pcm_open(&pcmDevice, defaultDeviceName, stream, openMode) == 0) {
24526 FPL_LOG_DEBUG(
"ALSA",
"Successfully opened PCM audio device '%s'", defaultDeviceName);
24527 isDeviceOpen =
true;
24531 FPL_LOG_ERROR(
"ALSA",
"Failed opening PCM audio device '%s'!", defaultDeviceName);
24534 if (!isDeviceOpen) {
24535 FPL__WARNING(FPL__MODULE_AUDIO_ALSA,
"No PCM audio device found!");
24539 const char *forcedDeviceId = deviceID.alsa;
24541 if (alsaApi->snd_pcm_open(&pcmDevice, forcedDeviceId, stream, openMode) < 0) {
24542 FPL__WARNING(FPL__MODULE_AUDIO_ALSA,
"PCM audio device by id '%s' not found!", forcedDeviceId);
24549 alsaApi->snd_pcm_close(pcmDevice);
24557fpl_internal FPL_AUDIO_BACKEND_GET_AUDIO_DEVICES_FUNC(fpl__AudioBackendAlsaGetAudioDevices) {
24558 fpl__AlsaAudioBackend *impl = FPL_GET_AUDIO_BACKEND_IMPL(backend, fpl__AlsaAudioBackend);
24561 const fpl__AlsaAudioApi *alsaApi = &impl->api;
24563 char **ppDeviceHints;
24564 if (alsaApi->snd_device_name_hint(-1,
"pcm", (
void ***)&ppDeviceHints) < 0) {
24568 uint32_t capacityOverflow = 0;
24569 uint32_t result = 0;
24570 char **ppNextDeviceHint = ppDeviceHints;
24571 while (*ppNextDeviceHint !=
fpl_null) {
24572 char *name = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"NAME");
24573 char *ioid = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"IOID");
24578 if (result >= maxDeviceCount) {
24579 ++capacityOverflow;
24585 char *desc = alsaApi->snd_device_name_get_hint(*ppNextDeviceHint,
"DESC");
24602 ++ppNextDeviceHint;
24604 alsaApi->snd_device_name_free_hint((
void **)ppDeviceHints);
24605 if (capacityOverflow > 0) {
24606 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);
24611fpl_globalvar fplAudioBackendDescriptor fpl__global_audioBackendALSADescriptor = {
24615 fplStructField(fplAudioBackendDescriptorIDName,
id, { 0x897c80d9, 0xc251, 0x4d48, { 0x80, 0x6e, 0x1a, 0x5b, 0x89, 0xb0, 0x97, 0x4 } }),
24619 fplStructField(fplAudioBackendDescriptorHeader, backendSize,
sizeof(fpl__AlsaAudioBackend)),
24620 fplStructField(fplAudioBackendDescriptorHeader, isAsync,
false),
24624 fplStructField(fplAudioBackendFunctionTable, initialize, fpl__AudioBackendAlsaInitialize),
24625 fplStructField(fplAudioBackendFunctionTable, release, fpl__AudioBackendAlsaRelease),
24626 fplStructField(fplAudioBackendFunctionTable, getAudioDevices, fpl__AudioBackendAlsaGetAudioDevices),
24627 fplStructField(fplAudioBackendFunctionTable, getAudioDeviceInfo, fpl__AudioBackendALSAGetAudioDeviceInfo),
24628 fplStructField(fplAudioBackendFunctionTable, initializeDevice, fpl__AudioBackendAlsaInitializeDevice),
24629 fplStructField(fplAudioBackendFunctionTable, releaseDevice, fpl__AudioBackendAlsaReleaseDevice),
24630 fplStructField(fplAudioBackendFunctionTable, startDevice, fpl__AudioBackendAlsaStartDevice),
24631 fplStructField(fplAudioBackendFunctionTable, stopDevice, fpl__AudioBackendAlsaStopDevice),
24632 fplStructField(fplAudioBackendFunctionTable, mainLoop, fpl__AudioBackendAlsaMainLoop),
24633 fplStructField(fplAudioBackendFunctionTable, stopMainLoop, fpl__AudioBackendAlsaStopMainLoop),
24648#if defined(FPL__ENABLE_AUDIO)
24651 FPL__CheckArgumentNullNoRet(inFormat);
24652 FPL__CheckArgumentNullNoRet(outFormat);
24659 uint16_t highestChannelCount =
fplMax(layoutChannelCount, inFormat->
channels);
24674 outFormat->
channels = layoutChannelCount;
24690 outFormat->
sampleRate = FPL__DEFAULT_AUDIO_SAMPLERATE;
24699 outFormat->
type = FPL__DEFAULT_AUDIO_FORMAT;
24708 outFormat->
periods = FPL__DEFAULT_AUDIO_PERIODS;
24732#define FPL__AUDIO_RESULT_TYPE_COUNT FPL__ENUM_COUNT(fplAudioResultType_First, fplAudioResultType_Last)
24735fpl_globalvar const char *fpl__global_audioResultTypeNameTable[] = {
24762#define FPL__AUDIO_BACKEND_TYPE_COUNT FPL__ENUM_COUNT(fplAudioBackendType_First, fplAudioResultType_Last)
24770fpl_internal uint32_t fpl__GetAudioBackendDescriptors(
const uint32_t maxDescriptorCount,
const fplAudioSettings *audioSettings, fplAudioBackendDescriptor *outputDescriptors) {
24773 uint32_t propeTypeCount = 0;
24777 userBackendType = audioSettings->
backend;
24781 probeTypes[propeTypeCount++] = userBackendType;
24783 for (uint32_t i = 0; i <
fplArrayCount(fpl__global_defaultAudioBackendTypes); ++i) {
24784 if (userBackendType == fpl__global_defaultAudioBackendTypes[i])
24786 probeTypes[propeTypeCount++] = fpl__global_defaultAudioBackendTypes[i];
24789 uint32_t descriptorCount = 0;
24791 uint32_t result = 0;
24793 for (uint32_t propeTypeIndex = 0; propeTypeIndex < propeTypeCount; ++propeTypeIndex) {
24795 const fplAudioBackendDescriptor *desc =
fpl_null;
24802#if defined(FPL__ENABLE_AUDIO_DIRECTSOUND)
24803 desc = &fpl__global_audioBackendDirectShowDescriptor;
24807#if defined(FPL__ENABLE_AUDIO_ALSA)
24808 desc = &fpl__global_audioBackendALSADescriptor;
24817 if (desc ==
fpl_null || !desc->header.isValid) {
24821 uint32_t outputDescriptorIndex = descriptorCount;
24822 if ((outputDescriptors !=
fpl_null) || (maxDescriptorCount > 0 && (descriptorCount < maxDescriptorCount))) {
24823 outputDescriptors[outputDescriptorIndex] = *desc;
24830 if (outputDescriptors ==
fpl_null) {
24831 return(descriptorCount);
24838 static fplAudioBackendDescriptor descriptors[8];
24840 uint32_t count = fpl__GetAudioBackendDescriptors(
fplArrayCount(descriptors), settings, descriptors);
24841 uint32_t result = 0;
24842 for (
size_t i = 0; i < count; ++i) {
24843 uint32_t size = descriptors[i].header.backendSize;
24844 result =
fplMax(result, size);
24851 const char *result = fpl__global_audioResultTypeNameTable[index];
24855typedef struct fpl__AudioEvent {
24856 fplMutexHandle mutex;
24857 fplConditionVariable cond;
24858 volatile int32_t signaled;
24861fpl_internal bool fpl__InitAudioEvent(fpl__AudioEvent *ev) {
24873fpl_internal void fpl__ReleaseAudioEvent(fpl__AudioEvent *ev) {
24878fpl_internal void fpl__WaitForAudioEvent(fpl__AudioEvent *ev) {
24880 while (!ev->signaled) {
24887fpl_internal void fpl__SetAudioEvent(fpl__AudioEvent *ev) {
24894typedef struct fpl__AudioState {
24895 fpl__CommonAudioState common;
24897 fplMutexHandle lock;
24899 fpl__AudioEvent startEvent;
24900 fpl__AudioEvent stopEvent;
24901 fpl__AudioEvent wakeupEvent;
24905 bool isAsyncBackend;
24908fpl_internal fpl__AudioState *fpl__GetAudioState(fpl__PlatformAppState *appState) {
24910 fpl__AudioState *result =
fpl_null;
24911 if (appState->audio.mem !=
fpl_null) {
24912 result = (fpl__AudioState *)appState->audio.mem;
24917fpl_internal fplAudioBackend *fpl__GetActiveAudioBackend(fpl__AudioState *audioState) {
24921 return audioState->common.backend;
24924fpl_internal void fpl__AudioSetDeviceState(fplAudioContext *context, fpl__AudioDeviceState newState) {
24928fpl_internal fpl__AudioDeviceState fpl__AudioGetDeviceState(fplAudioContext *context) {
24929 fpl__AudioDeviceState result = (fpl__AudioDeviceState)
fplAtomicLoadU32((
volatile uint32_t *)&context->state);
24933fpl_internal bool fpl__IsAudioDeviceInitialized(fplAudioContext *context) {
24937 fpl__AudioDeviceState state = fpl__AudioGetDeviceState(context);
24938 return(state != fpl__AudioDeviceState_Uninitialized);
24941fpl_internal bool fpl__IsAudioDeviceStarted(fplAudioContext *context) {
24945 fpl__AudioDeviceState state = fpl__AudioGetDeviceState(context);
24946 return(state == fpl__AudioDeviceState_Started);
24949fpl_internal void fpl__StopAudioDeviceMainLoop(fpl__AudioState *audioState) {
24952 audioState->common.funcTable.stopMainLoop(&audioState->common.context, audioState->common.backend);
24955fpl_internal bool fpl__ReleaseAudioDevice(fpl__AudioState *audioState) {
24960 fpl__CommonAudioState *commonAudioState = &audioState->common;
24962 fplAudioContext *context = &commonAudioState->context;
24964 fplAudioBackend *backend = commonAudioState->backend;
24967 if (fpl__IsAudioDeviceStarted(context)) {
24974 fpl__AudioSetDeviceState(context, fpl__AudioDeviceState_Uninitialized);
24977 fpl__SetAudioEvent(&audioState->wakeupEvent);
24983 fpl__ReleaseAudioEvent(&audioState->stopEvent);
24984 fpl__ReleaseAudioEvent(&audioState->startEvent);
24985 fpl__ReleaseAudioEvent(&audioState->wakeupEvent);
24989 if (backend !=
fpl_null && commonAudioState->funcTable.releaseDevice !=
fpl_null) {
24990 if (!commonAudioState->funcTable.releaseDevice(context, backend)) {
24998fpl_internal bool fpl__StopAudioDevice(fpl__AudioState *audioState) {
25001 bool result = audioState->common.funcTable.stopDevice(&audioState->common.context, audioState->common.backend);
25008 fplAudioResultType result = audioState->common.funcTable.startDevice(&audioState->common.context, audioState->common.backend);
25012fpl_internal void fpl__RunAudioDeviceMainLoop(fpl__AudioState *audioState) {
25015 audioState->common.funcTable.mainLoop(&audioState->common.context, audioState->common.backend);
25019#if defined(FPL_PLATFORM_WINDOWS)
25021 const fpl__Win32Api *wapi = &fpl__global__AppState->win32.winApi;
25024 fpl__AudioState *audioState = (fpl__AudioState *)data;
25028 fpl__CommonAudioState *commonAudioState = &audioState->common;
25030 fplAudioContext *context = &commonAudioState->context;
25032#if defined(FPL_PLATFORM_WINDOWS)
25033 wapi->ole.CoInitializeEx(
fpl_null, 0);
25038 fpl__StopAudioDevice(audioState);
25041 fpl__AudioSetDeviceState(context, fpl__AudioDeviceState_Stopped);
25042 fpl__SetAudioEvent(&audioState->stopEvent);
25045 fpl__WaitForAudioEvent(&audioState->wakeupEvent);
25051 if (fpl__AudioGetDeviceState(context) == fpl__AudioDeviceState_Uninitialized) {
25056 fplAssert(fpl__AudioGetDeviceState(context) == fpl__AudioDeviceState_Starting);
25059 audioState->workResult = fpl__StartAudioDevice(audioState);
25061 fpl__SetAudioEvent(&audioState->startEvent);
25066 fpl__AudioSetDeviceState(context, fpl__AudioDeviceState_Started);
25067 fpl__SetAudioEvent(&audioState->startEvent);
25070 fpl__RunAudioDeviceMainLoop(audioState);
25074 fpl__SetAudioEvent(&audioState->stopEvent);
25076#if defined(FPL_PLATFORM_WINDOWS)
25077 wapi->ole.CoUninitialize();
25081fpl_internal void fpl__ReleaseAudio(fpl__AudioState *audioState) {
25084#if defined(FPL_PLATFORM_WINDOWS)
25086 const fpl__Win32Api *wapi = &fpl__global__AppState->win32.winApi;
25089 fpl__CommonAudioState *commonAudioState = &audioState->common;
25091 fplAudioContext *context = &commonAudioState->context;
25093 fplAudioBackend *backend = commonAudioState->backend;
25095 if (fpl__IsAudioDeviceInitialized(context)) {
25096 fpl__ReleaseAudioDevice(audioState);
25099 if (backend !=
fpl_null && commonAudioState->funcTable.release !=
fpl_null) {
25100 commonAudioState->funcTable.release(context, backend);
25106#if defined(FPL_PLATFORM_WINDOWS)
25107 wapi->ole.CoUninitialize();
25134fpl_globalvar const uint32_t fpl__global_AudioFormat_FallbackSampleRates[] = {
25142fpl_globalvar const uint16_t fpl__global_AudioFormat_FallbackChannels[] = {
25152 const uint32_t channelCount =
fplArrayCount(fpl__global_AudioFormat_FallbackChannels);
25153 const uint32_t sampleRateCount =
fplArrayCount(fpl__global_AudioFormat_FallbackSampleRates);
25154 const uint32_t typeCount =
fplArrayCount(fpl__global_AudioFormat_FallbackTypes);
25160 size_t requiredCount = 0;
25161 if (isDefaultChannel) {
25162 if (requiredCount == 0)
25163 requiredCount = channelCount;
25165 requiredCount = requiredCount * channelCount;
25167 if (isDefaultType) {
25168 if (requiredCount == 0)
25169 requiredCount = typeCount;
25171 requiredCount = requiredCount * typeCount;
25173 if (isDefaultSampleRate) {
25174 if (requiredCount == 0)
25175 requiredCount = sampleRateCount;
25177 requiredCount = requiredCount * sampleRateCount;
25181 return requiredCount;
25184 uint32_t actualChannelCount = isDefaultChannel ? channelCount : 1;
25185 uint32_t actualTypeCount = isDefaultType ? typeCount : 1;
25186 uint32_t actualSampleRateCount = isDefaultSampleRate ? sampleRateCount : 1;
25188 size_t totalCount = 0;
25189 for (uint32_t channelIndex = 0; channelIndex < actualChannelCount; ++channelIndex) {
25190 uint16_t channel = isDefaultChannel ? fpl__global_AudioFormat_FallbackChannels[channelIndex] : 0;
25191 for (uint32_t typeIndex = 0; typeIndex < actualTypeCount; ++typeIndex) {
25193 for (uint32_t sampleRateIndex = 0; sampleRateIndex < actualSampleRateCount; ++sampleRateIndex) {
25194 uint32_t sampleRate = isDefaultSampleRate ? fpl__global_AudioFormat_FallbackSampleRates[sampleRateIndex] : 0;
25196 if (totalCount < maxOutputFormatCount) {
25197 outFormats[totalCount++] = format;
25211#if defined(FPL_PLATFORM_WINDOWS)
25213 const fpl__Win32Api *wapi = &fpl__global__AppState->win32.winApi;
25217 fpl__ReleaseAudio(audioState);
25221 fpl__PlatformAudioState *platformAudioState = &fpl__global__AppState->audio;
25222 fplAssert(platformAudioState->maxBackendSize > 0);
25223 fplAssert(platformAudioState->offsetToBackend > 0);
25226 fpl__CommonAudioState *common = &audioState->common;
25228 fplAudioContext *context = &common->context;
25230 fplAudioBackend *backend = (fplAudioBackend *)((uint8_t *)platformAudioState->mem + platformAudioState->offsetToBackend);
25231 common->backend = backend;
25241#if defined(FPL_PLATFORM_WINDOWS)
25242 wapi->ole.CoInitializeEx(
fpl_null, 0);
25245 static fplAudioBackendDescriptor descriptors[8];
25247 size_t audioBackendCount = fpl__GetAudioBackendDescriptors(
fplArrayCount(descriptors), audioSettings, descriptors);
25249 if (audioBackendCount == 0) {
25250 fpl__ReleaseAudio(audioState);
25258 const uint32_t defaultFallbackFieldCount =
fplArrayCount(fpl__global_AudioFormat_FallbackFields);
25266 for (
size_t backendIndex = 0; backendIndex < audioBackendCount; ++backendIndex) {
25267 const fplAudioBackendDescriptor *descriptor = &descriptors[backendIndex];
25270 fplAssert(descriptor->header.isValid && descriptor->table.initialize !=
fpl_null);
25271 resultType = descriptor->table.initialize(context, backend);
25273 descriptor->table.release(context, backend);
25278 fpl__SetupAudioDeviceFormat(&audioSettings->
targetFormat, &backend->desiredFormat);
25280 uint32_t fallbackFieldCount = 0;
25282 fallbackFields[fallbackFieldCount++] = backend->desiredFormat.defaultFields;
25283 for (uint32_t i = 0; i <
fplArrayCount(fpl__global_AudioFormat_FallbackFields); ++i) {
25284 fallbackFields[fallbackFieldCount++] = fpl__global_AudioFormat_FallbackFields[i];
25289 uint32_t fallbackFieldIndex = 0;
25291 fplAssert(descriptor->header.isValid && descriptor->table.initializeDevice !=
fpl_null);
25295 size_t testFormatCount = fpl__PopulateFallbackAudioFormats(fallbackFieldsMask,
fplArrayCount(testFormats) - 1, testFormats);
25298 uint32_t currentSampleRate;
25299 uint16_t currentChannels;
25302 bool formatFound =
false;
25303 for (uint32_t testFormatIndex = 0; testFormatIndex < testFormatCount; ++testFormatIndex) {
25311 currentTargetFormat.
channels = currentChannels;
25315 currentTargetFormat.
type = currentType;
25318 currentTargetFormat.
sampleRate = currentSampleRate;
25322 backend->internalDevice = audioSettings->
targetDevice;
25323 fpl__SetupAudioDeviceFormat(¤tTargetFormat, &backend->desiredFormat);
25327 FPL_LOG_DEBUG(FPL__MODULE_AUDIO,
"Initializing audio device with settings (SampleRate=%u, Channels=%u, Type='%s')", backend->desiredFormat.sampleRate, backend->desiredFormat.channels, formatTypeName);
25329 resultType = descriptor->table.initializeDevice(context, backend, &audioSettings->
specific, &backend->desiredFormat, &audioSettings->
targetDevice, &backend->internalFormat, &backend->internalDevice, &channelsMapping);
25331 const char *resultErrorStr = fplGetAudioResultName(resultType);
25332 FPL_LOG_WARN(FPL__MODULE_AUDIO,
"Failed initializing audio device with settings (SampleRate=%u, Channels=%u, Type='%s') -> %s", backend->desiredFormat.sampleRate, backend->desiredFormat.channels, formatTypeName, resultErrorStr);
25333 descriptor->table.releaseDevice(context, backend);
25335 FPL_LOG_DEBUG(FPL__MODULE_AUDIO,
"Successfully initialized audio device with settings (SampleRate=%u, Channels=%u, Type='%s')", backend->desiredFormat.sampleRate, backend->desiredFormat.channels, formatTypeName);
25336 audioState->common.funcTable = descriptor->table;
25337 audioState->common.channelsMapping = channelsMapping;
25338 audioState->backendType = descriptor->header.type;
25339 audioState->isAsyncBackend = descriptor->header.isAsync;
25345 ++fallbackFieldIndex;
25353 const char *resultErrorStr = fplGetAudioResultName(resultType);
25354 FPL_LOG_ERROR(FPL__MODULE_AUDIO,
"Either no backend was found or the specified audio format is not supported -> %s", resultErrorStr);
25355 fpl__ReleaseAudio(audioState);
25359 fpl__global__AppState->currentSettings.audio.backend = audioState->backendType;
25361 fpl__global__AppState->currentSettings.audio.clientReadCallback = audioState->common.backend->clientReadCallback;
25362 fpl__global__AppState->currentSettings.audio.clientUserData = audioState->common.backend->clientUserData;
25366 fpl__ReleaseAudio(audioState);
25369 if (!fpl__InitAudioEvent(&audioState->wakeupEvent)) {
25370 fpl__ReleaseAudio(audioState);
25373 if (!fpl__InitAudioEvent(&audioState->startEvent)) {
25374 fpl__ReleaseAudio(audioState);
25377 if (!fpl__InitAudioEvent(&audioState->stopEvent)) {
25378 fpl__ReleaseAudio(audioState);
25382 if (!audioState->isAsyncBackend) {
25386 audioThreadParams.
runFunc = fpl__AudioWorkerThread;
25387 audioThreadParams.
userData = audioState;
25389 if (audioState->workerThread ==
fpl_null) {
25390 fpl__ReleaseAudio(audioState);
25396 fpl__WaitForAudioEvent(&audioState->stopEvent);
25398 fpl__AudioSetDeviceState(context, fpl__AudioDeviceState_Stopped);
25401 fplAssert(fpl__AudioGetDeviceState(context) == fpl__AudioDeviceState_Stopped);
25415#if defined(FPL__ENABLE_VIDEO)
25417typedef union fpl__ActiveVideoBackend {
25418 fpl__VideoBackend base;
25420#if defined(FPL_PLATFORM_WINDOWS)
25421# if defined(FPL__ENABLE_VIDEO_OPENGL)
25422 fpl__VideoBackendWin32OpenGL win32_opengl;
25424# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
25425 fpl__VideoBackendWin32Software win32_software;
25429#if defined(FPL_SUBPLATFORM_X11)
25430# if defined(FPL__ENABLE_VIDEO_OPENGL)
25431 fpl__VideoBackendX11OpenGL x11_opengl;
25433# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
25434 fpl__VideoBackendX11Software x11_software;
25438#if defined(FPL__ENABLE_VIDEO_VULKAN)
25439 fpl__VideoBackendVulkan vulkan;
25442} fpl__ActiveVideoBackend;
25444typedef struct fpl__VideoState {
25445 fpl__VideoContext context;
25446 fpl__VideoData data;
25448 fpl__ActiveVideoBackend activeBackend;
25451fpl_internal fpl__VideoState *fpl__GetVideoState(fpl__PlatformAppState *appState) {
25453 fpl__VideoState *result =
fpl_null;
25454 if (appState->video.mem !=
fpl_null) {
25455 result = (fpl__VideoState *)appState->video.mem;
25460fpl_internal void fpl__DestroySurfaceBackend(fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
25461 const fpl__VideoContext *ctx = &videoState->context;
25463 ctx->destroyedWindowFunc(appState, &videoState->activeBackend.base);
25466fpl_internal void fpl__UnloadVideoBackend(fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
25467 const fpl__VideoContext *ctx = &videoState->context;
25469 ctx->unloadFunc(appState, &videoState->activeBackend.base);
25473fpl_internal bool fpl__LoadVideoBackend(fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
25474 const fpl__VideoContext *ctx = &videoState->context;
25476 bool result = ctx->loadFunc(appState, &videoState->activeBackend.base);
25480fpl_internal void fpl__ShutdownVideoBackend(fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
25483 const fpl__VideoContext *ctx = &videoState->context;
25485 ctx->shutdownFunc(appState, &appState->window, &videoState->activeBackend.base);
25487# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
25490 fpl__ReleaseDynamicMemory(backbuffer->
pixels);
25497fpl_internal bool fpl__InitializeVideoBackend(
const fplVideoBackendType backendType,
const fplVideoSettings *videoSettings,
const uint32_t windowWidth,
const uint32_t windowHeight, fpl__PlatformAppState *appState, fpl__VideoState *videoState) {
25502 const fpl__VideoContext *ctx = &videoState->context;
25505# if defined(FPL__ENABLE_VIDEO_SOFTWARE)
25508 backbuffer->
width = windowWidth;
25509 backbuffer->
height = windowHeight;
25513 backbuffer->
pixels = (uint32_t *)fpl__AllocateDynamicMemory(size, 4);
25515 FPL__ERROR(FPL__MODULE_VIDEO_SOFTWARE,
"Failed allocating video software backbuffer of size %xu bytes", size);
25516 fpl__ShutdownVideoBackend(appState, videoState);
25522 uint32_t *p = backbuffer->
pixels;
25523 uint32_t color = appState->initSettings.window.background.value == 0 ? 0xFF000000 : appState->initSettings.window.background.value;
25524 for (uint32_t y = 0; y < backbuffer->
height; ++y) {
25525 for (uint32_t x = 0; x < backbuffer->
width; ++x) {
25533 bool videoInitResult = ctx->initializeFunc(appState, &appState->window, videoSettings, &videoState->data, &videoState->activeBackend.base);
25534 if (!videoInitResult) {
25536 fpl__ShutdownVideoBackend(appState, videoState);
25544 switch (backendType) {
25545#if defined(FPL__ENABLE_VIDEO_OPENGL)
25548# if defined(FPL_PLATFORM_WINDOWS)
25549 return fpl__VideoBackend_Win32OpenGL_Construct();
25550# elif defined(FPL_SUBPLATFORM_X11)
25551 return fpl__VideoBackend_X11OpenGL_Construct();
25556#if defined(FPL__ENABLE_VIDEO_VULKAN)
25559 return fpl__VideoBackend_Vulkan_Construct();
25563#if defined(FPL__ENABLE_VIDEO_SOFTWARE)
25566# if defined(FPL_PLATFORM_WINDOWS)
25567 return fpl__VideoBackend_Win32Software_Construct();
25568# elif defined(FPL_SUBPLATFORM_X11)
25569 return fpl__VideoBackend_X11Software_Construct();
25577 FPL__ERROR(FPL__MODULE_VIDEO,
"The video backend '%s' is not supported for this platform",
fplGetVideoBackendName(backendType));
25578 return(fpl__StubVideoContext());
25592#if defined(FPL__ENABLE_WINDOW)
25593fpl_internal FPL__FUNC_PREPARE_VIDEO_WINDOW(fpl__PrepareVideoWindowDefault) {
25596# if defined(FPL__ENABLE_VIDEO)
25598 fpl__VideoState *videoState = fpl__GetVideoState(appState);
25599 if (videoState->context.prepareWindowFunc !=
fpl_null) {
25600 bool result = videoState->context.prepareWindowFunc(appState, &initSettings->
video, &appState->window, &videoState->activeBackend.base);
25609fpl_internal FPL__FUNC_FINALIZE_VIDEO_WINDOW(fpl__FinalizeVideoWindowDefault) {
25612#if defined(FPL__ENABLE_VIDEO)
25614 fpl__VideoState *videoState = fpl__GetVideoState(appState);
25615 if (videoState->context.finalizeWindowFunc !=
fpl_null) {
25616 bool result = videoState->context.finalizeWindowFunc(appState, &initSettings->
video, &appState->window, &videoState->activeBackend.base);
25625fpl_internal void fpl__ReleaseWindow(
const fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
25627# if defined(FPL_PLATFORM_WINDOWS)
25628 fpl__Win32ReleaseWindow(&initState->win32, &appState->win32, &appState->window.win32);
25629# elif defined(FPL_SUBPLATFORM_X11)
25630 fpl__X11ReleaseWindow(&appState->x11, &appState->window.x11);
25636 bool result =
false;
25638# if defined(FPL_PLATFORM_WINDOWS)
25639 result = fpl__Win32InitWindow(initSettings, currentWindowSettings, appState, &appState->win32, &appState->window.win32, setupCallbacks);
25640# elif defined(FPL_SUBPLATFORM_X11)
25641 result = fpl__X11InitWindow(initSettings, currentWindowSettings, appState, &appState->x11, &appState->window.x11, setupCallbacks);
25656#if defined(FPL__ENABLE_AUDIO)
25658#define FPL__AUDIOFORMATTYPE_COUNT FPL__ENUM_COUNT(fplAudioFormatType_First, fplAudioFormatType_Last)
25662fpl_globalvar uint32_t fpl__globalAudioFormatSampleSizeTable[] = {
25676 uint32_t result = fpl__globalAudioFormatSampleSizeTable[index];
25680fpl_globalvar const char *fpl__globalAudioFormatNameTable[] = {
25694 const char *result = fpl__globalAudioFormatNameTable[index];
25698#define FPL__AUDIOBACKENDTYPE_COUNT FPL__ENUM_COUNT(fplAudioBackendType_First, fplAudioBackendType_Last)
25701fpl_globalvar const char *fpl__globalAudioBackendNameTable[FPL__AUDIOBACKENDTYPE_COUNT] = {
25712 const fpl__PlatformAppState *appState = fpl__global__AppState;
25719 const char *result = fpl__globalAudioBackendNameTable[index];
25724 if (sampleRate == 0 || bufferSizeInMilliSeconds == 0)
return(0);
25725 uint32_t result = bufferSizeInMilliSeconds * sampleRate / 1000UL;
25730 if (sampleRate == 0 || frameCount == 0)
return(0);
25731 uint32_t result = frameCount * 1000UL / sampleRate;
25736 if (channelCount == 0)
return(0);
25742 if (channelCount == 0 || frameCount == 0)
return(0);
25744 uint32_t result = frameSize * frameCount;
25749 if (inputFrameCount == 0 || inputSampleRate == 0 || outputSampleRate == 0) {
25752 if (inputSampleRate == outputSampleRate) {
25753 return inputFrameCount;
25756 float inRatio = inputSampleRate / (float)outputSampleRate;
25757 float outRatio = 1.0f / inRatio;
25761 if (inputSampleRate > outputSampleRate) {
25764 fplAssert(outputSampleRate > inputSampleRate);
25768 float f = inputFrameCount * ratio;
25769 uint32_t full = (uint32_t)f;
25770 float fraction = full - f;
25773 uint32_t add = fraction != 0 ? (uint32_t)(fraction + 0.5f) : 0;
25775 uint32_t result = full + add;
25780#define FPL__AUDIO_CHANNEL_LAYOUT_COUNT FPL__ENUM_COUNT(fplAudioChannelLayout_First, fplAudioChannelLayout_Last)
25821fpl_globalvar uint16_t fpl__global_AudioChannelLayout_To_AudioChannelCount_Table[] = {
25840 if (channelCount <
fplArrayCount(fpl__global_AudioChannelCount_To_AudioChannelLayout_Table)) {
25841 fplAudioChannelLayout result = fpl__global_AudioChannelCount_To_AudioChannelLayout_Table[channelCount];
25849 uint16_t channels = fpl__global_AudioChannelLayout_To_AudioChannelCount_Table[index];
25877 switch (shareMode) {
25879 switch (latencyType) {
25888 switch (latencyType) {
25900 result |= ((uint64_t)sampleRate << 32);
25901 result |= ((uint64_t)channels << 16);
25902 result |= ((uint64_t)(type & 0xFF) << 8);
25910 *outSampleRate = (uint32_t)((format64 >> 32) & 0xFFFFFFFF);
25911 *outChannels = (uint16_t)((format64 >> 16) & 0xFFFF);
25918 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
25923 fpl__CommonAudioState *commonAudioState = &audioState->common;
25925 fplAudioContext *context = &commonAudioState->context;
25927 if (!fpl__IsAudioDeviceInitialized(context)) {
25931 fpl__AudioDeviceState firstDeviceState = fpl__AudioGetDeviceState(context);
25932 if (firstDeviceState == fpl__AudioDeviceState_Stopped) {
25940 if (fpl__AudioGetDeviceState(context) == fpl__AudioDeviceState_Stopping) {
25944 if (fpl__AudioGetDeviceState(context) == fpl__AudioDeviceState_Stopped) {
25950 if (fpl__AudioGetDeviceState(context) != fpl__AudioDeviceState_Started) {
25955 fpl__AudioSetDeviceState(context, fpl__AudioDeviceState_Stopping);
25957 if (audioState->isAsyncBackend) {
25959 fpl__StopAudioDevice(audioState);
25964 fpl__StopAudioDeviceMainLoop(audioState);
25968 fpl__WaitForAudioEvent(&audioState->stopEvent);
25979 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
25984 fpl__CommonAudioState *commonAudioState = &audioState->common;
25986 fplAudioContext *context = &commonAudioState->context;
25988 if (!fpl__IsAudioDeviceInitialized(context)) {
25992 if (fpl__AudioGetDeviceState(context) == fpl__AudioDeviceState_Started) {
26000 if (fpl__AudioGetDeviceState(context) == fpl__AudioDeviceState_Starting) {
26004 if (fpl__AudioGetDeviceState(context) == fpl__AudioDeviceState_Started) {
26010 if (fpl__AudioGetDeviceState(context) != fpl__AudioDeviceState_Stopped) {
26015 fpl__AudioSetDeviceState(context, fpl__AudioDeviceState_Starting);
26017 if (audioState->isAsyncBackend) {
26019 fpl__StartAudioDevice(audioState);
26020 fpl__AudioSetDeviceState(context, fpl__AudioDeviceState_Started);
26023 fpl__SetAudioEvent(&audioState->wakeupEvent);
26027 fpl__WaitForAudioEvent(&audioState->startEvent);
26028 result = audioState->workResult;
26039 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26044 fpl__ReleaseAudio(audioState);
26046 fplAudioContext *context = &audioState->common.context;
26048 fplAudioBackend *backend = (fplAudioBackend *)(((uint8_t *)fpl__global__AppState->audio.mem) + fpl__global__AppState->audio.offsetToBackend);
26051 const char *audioBackendName;
26052 const char *audioFormatName;
26053 const char *audioResultName;
26057 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Load Audio with Backend '%s' with Target-Format (Sample Rate=%u, Channels=%u, Format='%s')",
26065 audioResultName = fplGetAudioResultName(initAudioResult);
26067 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed loading Audio with Backend '%s' and Desired-Format (Sample Rate=%u, Channels=%u, Format='%s') -> %s",
26069 backend->desiredFormat.sampleRate,
26070 backend->desiredFormat.channels,
26073 fpl__ReleaseAudio(audioState);
26074 return(initAudioResult);
26079 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully loaded Audio with Backend '%s' and Internal-Format Sample Rate '%u', Channels '%u', Format '%s':", audioBackendName, backend->internalFormat.sampleRate, backend->internalFormat.channels, audioFormatName);
26083 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Play Audio (Auto)");
26085 audioResultName = fplGetAudioResultName(playResult);
26087 FPL__ERROR(FPL__MODULE_CORE,
"Failed playing Audio (Auto) -> %s", audioResultName);
26088 fpl__ReleaseAudio(audioState);
26089 return(playResult);
26091 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully playing Audio (Auto)");
26098 FPL__CheckPlatform(
false);
26099 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26103 fplAudioContext *context = &audioState->common.context;
26104 if (!fpl__IsAudioDeviceInitialized(context)) {
26107 fpl__ReleaseAudio(audioState);
26112 FPL__CheckArgumentNull(outFormat,
false);
26113 FPL__CheckPlatform(
false);
26114 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26118 fplAudioBackend *backend = audioState->common.backend;
26123 *outFormat = backend->internalFormat;
26128 FPL__CheckArgumentNull(outDevice,
false);
26129 FPL__CheckPlatform(
false);
26130 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26134 fplAudioBackend *backend = audioState->common.backend;
26139 *outDevice = backend->internalDevice;
26145 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26149 fplAudioBackend *backend = audioState->common.backend;
26153 return backend->internalDevice.name;
26157 FPL__CheckArgumentNull(outMapping,
false);
26158 FPL__CheckPlatform(
false);
26159 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26163 *outMapping = audioState->common.channelsMapping;
26168 FPL__CheckPlatform(
false);
26169 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26170 fplAudioBackend *backend = audioState !=
fpl_null ? audioState->common.backend :
fpl_null;
26174 fplAudioContext *context = &audioState->common.context;
26176 bool notStopped = fpl__AudioGetDeviceState(context) != fpl__AudioDeviceState_Stopped;
26177 if (invalidBackend || notStopped) {
26180 backend->clientReadCallback = newCallback;
26181 backend->clientUserData = userData;
26186 FPL__CheckPlatform(0);
26187 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26188 fplAudioContext *context = &audioState->common.context;
26189 fplAudioBackend *backend = fpl__GetActiveAudioBackend(audioState);
26194 if (invalidBackend) {
26199 uint32_t result = audioState->common.funcTable.getAudioDevices(context, backend, maxDeviceCount, stride, outDevices);
26204 FPL__CheckArgumentNull(outDeviceInfo,
false);
26205 FPL__CheckPlatform(
false);
26206 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26207 fplAudioContext *context = &audioState->common.context;
26208 fplAudioBackend *backend = fpl__GetActiveAudioBackend(audioState);
26213 if (invalidBackend) {
26217 bool result = audioState->common.funcTable.getAudioDeviceInfo(context, backend, deviceId, outDeviceInfo);
26231#if defined(FPL__ENABLE_VIDEO)
26232#define FPL__VIDEOBACKENDTYPE_COUNT FPL__ENUM_COUNT(fplVideoBackendType_First, fplVideoBackendType_Last)
26235fpl_globalvar const char *fpl__globalVideoBackendNameTable[FPL__VIDEOBACKENDTYPE_COUNT] = {
26244 const char *result = fpl__globalVideoBackendNameTable[index];
26250 fpl__PlatformAppState *appState = fpl__global__AppState;
26251 fpl__VideoState *videoState = fpl__GetVideoState(appState);
26253 return(videoState->backendType);
26260 fpl__PlatformAppState *appState = fpl__global__AppState;
26261 fpl__VideoState *videoState = fpl__GetVideoState(appState);
26264#if defined(FPL__ENABLE_VIDEO_SOFTWARE)
26266 result = &videoState->data.backbuffer;
26274 FPL__CheckPlatform(
false);
26275 fpl__PlatformAppState *appState = fpl__global__AppState;
26276 fpl__VideoState *videoState = fpl__GetVideoState(appState);
26277 bool result =
false;
26281 fpl__ShutdownVideoBackend(appState, videoState);
26282 result = fpl__InitializeVideoBackend(videoState->backendType, &appState->currentSettings.video, width, height, appState, videoState);
26289 FPL__CheckPlatformNoRet();
26290 fpl__PlatformAppState *appState = fpl__global__AppState;
26291 const fpl__VideoState *videoState = fpl__GetVideoState(appState);
26294 videoState->context.presentFunc(appState, &appState->window, &videoState->data, &videoState->activeBackend.base);
26300 fpl__PlatformAppState *appState = fpl__global__AppState;
26301 const fpl__VideoState *videoState = fpl__GetVideoState(appState);
26305 result = videoState->context.getProcedureFunc(&videoState->activeBackend.base, procName);
26312 fpl__PlatformAppState *appState = fpl__global__AppState;
26313 const fpl__VideoState *videoState = fpl__GetVideoState(appState);
26316 result = &videoState->activeBackend.base.surface;
26322 fpl__VideoContext context = fpl__ConstructVideoContext(backendType);
26323 bool result =
false;
26324 if (context.getRequirementsFunc !=
fpl_null) {
26325 result = context.getRequirementsFunc(requirements);
26331 fplVideoRect result = { left, top, (right - left) + 1, (bottom - top) + 1 };
26341#if !defined(FPL__SYSTEM_INIT_DEFINED)
26342#define FPL__SYSTEM_INIT_DEFINED
26344fpl_internal void fpl__ReleasePlatformStates(fpl__PlatformInitState *initState, fpl__PlatformAppState *appState) {
26348# if defined(FPL__ENABLE_AUDIO)
26351 if (appState->currentSettings.audio.stopAuto) {
26352 fpl__AudioState *audioState = fpl__GetAudioState(fpl__global__AppState);
26354 fpl__CommonAudioState *commonAudioState = &audioState->common;
26355 fplAudioContext *context = &commonAudioState->context;
26356 fpl__AudioDeviceState deviceState = fpl__AudioGetDeviceState(context);
26357 if (deviceState != fpl__AudioDeviceState_Stopped) {
26358 FPL_LOG_DEBUG(
"Core",
"Stop Audio (Auto)");
26364 FPL_LOG_DEBUG(
"Core",
"Release Audio");
26365 fpl__AudioState *audioState = fpl__GetAudioState(appState);
26367 fpl__ReleaseAudio(audioState);
26373# if defined(FPL__ENABLE_VIDEO)
26375 fpl__VideoState *videoState = fpl__GetVideoState(appState);
26377 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Shutdown Video Backend '%s'",
fplGetVideoBackendName(videoState->backendType));
26378 fpl__ShutdownVideoBackend(appState, videoState);
26384# if defined(FPL__ENABLE_WINDOW)
26386 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Window");
26387 fpl__ReleaseWindow(initState, appState);
26388 fpl__ClearInternalEvents();
26393# if defined(FPL__ENABLE_VIDEO)
26395 fpl__VideoState *videoState = fpl__GetVideoState(appState);
26397 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Destroy surface for Video Backend '%s'",
fplGetVideoBackendName(videoState->backendType));
26398 fpl__DestroySurfaceBackend(appState, videoState);
26400 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Video Backend '%s'",
fplGetVideoBackendName(videoState->backendType));
26401 fpl__UnloadVideoBackend(appState, videoState);
26409# if defined(FPL_PLATFORM_WINDOWS)
26410 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Win32 Platform");
26411 fpl__Win32ReleasePlatform(initState, appState);
26412# elif defined(FPL_PLATFORM_LINUX)
26413 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Linux Platform");
26414 fpl__LinuxReleasePlatform(initState, appState);
26415# elif defined(FPL_PLATFORM_UNIX)
26416 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Unix Platform");
26417 fpl__UnixReleasePlatform(initState, appState);
26423# if defined(FPL_SUBPLATFORM_X11)
26424 FPL_LOG_DEBUG(
"Core",
"Release X11 Subplatform");
26425 fpl__X11ReleaseSubplatform(&appState->x11);
26427# if defined(FPL_SUBPLATFORM_POSIX)
26428 FPL_LOG_DEBUG(
"Core",
"Release POSIX Subplatform");
26429 fpl__PosixReleaseSubplatform(&appState->posix);
26434 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release allocated Platform App State Memory");
26442#define FPL__PLATFORMTYPE_COUNT FPL__ENUM_COUNT(fplPlatformType_First, fplPlatformType_Last)
26445fpl_globalvar const char *fpl__globalPlatformTypeNameTable[] = {
26454 fpl__PlatformInitState *initState = &fpl__global__InitState;
26455 bool result = initState->isInitialized;
26461 const char *result = fpl__globalPlatformTypeNameTable[index];
26466 fpl__PlatformInitState *initState = &fpl__global__InitState;
26467 return(initState->initResult);
26471 fpl__PlatformInitState *initState = &fpl__global__InitState;
26472 initState->initResult = resultType;
26478 fpl__PlatformInitState *initState = &fpl__global__InitState;
26479 if (!initState->isInitialized) {
26480 FPL__CRITICAL(FPL__MODULE_CORE,
"Platform is not initialized");
26483 fpl__PlatformAppState *appState = fpl__global__AppState;
26484 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Release Platform");
26485 fpl__ReleasePlatformStates(initState, appState);
26486 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Platform released");
26492} fpl__PlatformMemoryBlock;
26494fpl_internal void fpl__PushPlatformMemory(fpl__PlatformMemoryBlock *block,
const size_t size,
const size_t alignment,
const size_t padding) {
26496 size_t offset = block->offset;
26497 size_t addonSize = padding + alignedSize;
26498 block->size += addonSize;
26499 block->offset += alignedSize + padding;
26504 if (fpl__global__InitState.isInitialized) {
26505 FPL__CRITICAL(FPL__MODULE_CORE,
"Platform is already initialized");
26509 fpl__PlatformInitState *initState = &fpl__global__InitState;
26517 fpl__PlatformMemoryBlock platformMemoryBlock =
fplZeroInit;
26518 fpl__PlatformMemoryBlock videoMemoryBlock =
fplZeroInit;
26519 fpl__PlatformMemoryBlock audioMemoryBlock =
fplZeroInit;
26522 fpl__PushPlatformMemory(&platformMemoryBlock,
sizeof(fpl__PlatformAppState), 16, 0);
26525# if defined(FPL__ENABLE_VIDEO)
26527 fpl__PushPlatformMemory(&videoMemoryBlock,
sizeof(fpl__VideoState), 16, 0);
26532# if defined(FPL__ENABLE_AUDIO)
26533 size_t maxAudioBackendSize = 0;
26534 size_t offsetToAudioBackend = 0;
26538 audioSettings = initSettings->
audio;
26542 maxAudioBackendSize = fpl__GetMaxAudioBackendSize(&audioSettings);
26543 fpl__PushPlatformMemory(&audioMemoryBlock,
sizeof(fpl__AudioState), 16, FPL__ARBITARY_PADDING);
26544 fpl__PushPlatformMemory(&audioMemoryBlock, maxAudioBackendSize, 16, 0);
26545 offsetToAudioBackend =
sizeof(fpl__AudioState) + FPL__ARBITARY_PADDING;
26549 fpl__PlatformMemoryBlock *memoryBlocks[3] =
fplZeroInit;
26550 uint8_t memoryBlockCount = 0;
26551 memoryBlocks[memoryBlockCount++] = &platformMemoryBlock;
26552 if (videoMemoryBlock.size > 0) {
26553 memoryBlocks[memoryBlockCount++] = &videoMemoryBlock;
26555 if (audioMemoryBlock.size > 0) {
26556 memoryBlocks[memoryBlockCount++] = &audioMemoryBlock;
26559 size_t totalMemorySize = 0;
26560 for (uint8_t i = 0; i < memoryBlockCount; ++i) {
26561 fpl__PlatformMemoryBlock *currentBlock = memoryBlocks[i];
26562 currentBlock->offset = totalMemorySize;
26563 size_t memoryBlockSize = currentBlock->size;
26564 totalMemorySize += memoryBlockSize;
26565 if (i < memoryBlockCount - 1) {
26566 totalMemorySize += FPL__ARBITARY_PADDING;
26570 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Allocate Platform Memory of size '%zu':", totalMemorySize);
26574 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed Allocating Platform Memory of size '%zu'", totalMemorySize);
26578 fplAssert(platformMemoryBlock.offset == 0);
26579 fpl__PlatformAppState *appState = fpl__global__AppState = (fpl__PlatformAppState *)platformMemory + platformMemoryBlock.offset;
26580 appState->initFlags = initFlags;
26582 appState->initSettings = *initSettings;
26586 appState->currentSettings = appState->initSettings;
26588 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully allocated Platform Memory of size '%zu'", totalMemorySize);
26591# if defined(FPL__ENABLE_VIDEO)
26600# if !defined(FPL__ENABLE_WINDOW)
26606# if defined(FPL_SUBPLATFORM_POSIX)
26608 FPL_LOG_DEBUG(
"Core",
"Initialize POSIX Subplatform:");
26609 if (!fpl__PosixInitSubplatform(initFlags, initSettings, &initState->posix, &appState->posix)) {
26610 FPL__CRITICAL(
"Core",
"Failed initializing POSIX Subplatform!");
26611 fpl__ReleasePlatformStates(initState, appState);
26614 FPL_LOG_DEBUG(
"Core",
"Successfully initialized POSIX Subplatform");
26618# if defined(FPL_SUBPLATFORM_X11)
26620 FPL_LOG_DEBUG(
"Core",
"Initialize X11 Subplatform:");
26621 if (!fpl__X11InitSubplatform(&appState->x11)) {
26622 FPL__CRITICAL(
"Core",
"Failed initializing X11 Subplatform!");
26623 fpl__ReleasePlatformStates(initState, appState);
26626 FPL_LOG_DEBUG(
"Core",
"Successfully initialized X11 Subplatform");
26631 bool isInitialized =
false;
26632 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Initialize %s Platform:", FPL_PLATFORM_NAME);
26633# if defined(FPL_PLATFORM_WINDOWS)
26634 isInitialized = fpl__Win32InitPlatform(appState->initFlags, &appState->initSettings, initState, appState);
26635# elif defined(FPL_PLATFORM_LINUX)
26636 isInitialized = fpl__LinuxInitPlatform(appState->initFlags, &appState->initSettings, initState, appState);
26637# elif defined(FPL_PLATFORM_UNIX)
26638 isInitialized = fpl__UnixInitPlatform(appState->initFlags, &appState->initSettings, initState, appState);
26641 if (!isInitialized) {
26642 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed initializing %s Platform!", FPL_PLATFORM_NAME);
26643 fpl__ReleasePlatformStates(initState, appState);
26646 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully initialized %s Platform", FPL_PLATFORM_NAME);
26649# if defined(FPL__ENABLE_VIDEO)
26651 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Init Video State with size '%zu'", videoMemoryBlock.size);
26652 fplAssert(videoMemoryBlock.offset > 0);
26653 appState->video.mem = platformMemory + videoMemoryBlock.offset;
26654 appState->video.memSize = videoMemoryBlock.size;
26655 fpl__VideoState *videoState = fpl__GetVideoState(appState);
26661 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Construct Video Context:");
26662 videoState->context = fpl__ConstructVideoContext(videoBackendType);
26663 videoState->backendType = videoBackendType;
26667 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Load Video API for Backend '%s':", videoBackendName);
26669 if (!fpl__LoadVideoBackend(appState, videoState)) {
26670 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed loading Video API for Backend '%s'!", videoBackendName);
26671 fpl__ReleasePlatformStates(initState, appState);
26675 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully loaded Video API for Backend '%s'", videoBackendName);
26680# if defined(FPL__ENABLE_WINDOW)
26682 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Init Window:");
26683 fpl__SetupWindowCallbacks winCallbacks =
fplZeroInit;
26684 winCallbacks.preSetup = fpl__PrepareVideoWindowDefault;
26685 winCallbacks.postSetup = fpl__FinalizeVideoWindowDefault;
26686 if (!fpl__InitWindow(&appState->initSettings, &appState->currentSettings.window, appState, &winCallbacks)) {
26687 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed initializing Window!");
26688 fpl__ReleasePlatformStates(initState, appState);
26691 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully initialized Window");
26696# if defined(FPL__ENABLE_VIDEO)
26698 fpl__VideoState *videoState = fpl__GetVideoState(appState);
26703 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Init Video with Backend '%s':", videoBackendName);
26704 if (!fpl__InitializeVideoBackend(appState->initSettings.video.backend, &appState->initSettings.video, windowSize.
width, windowSize.
height, appState, videoState)) {
26705 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed initialization Video with Backend '%s' with settings (Width=%d, Height=%d)", videoBackendName, windowSize.
width, windowSize.
height);
26706 fpl__ReleasePlatformStates(initState, appState);
26709 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully initialized Video with Backend '%s'", videoBackendName);
26714# if defined(FPL__ENABLE_AUDIO)
26716 fplAssert(audioMemoryBlock.offset > 0);
26717 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Init Audio State with size '%zu'", audioMemoryBlock.size);
26718 appState->audio.mem = platformMemory + audioMemoryBlock.offset;
26719 appState->audio.memSize = audioMemoryBlock.size;
26720 appState->audio.maxBackendSize = maxAudioBackendSize;
26721 appState->audio.offsetToBackend = offsetToAudioBackend;
26723 const char *audioBackendName;
26724 const char *audioDeviceName;
26725 const char *audioFormatName;
26726 const char *audioResultName;
26729 audioDeviceName = appState->initSettings.audio.targetDevice.name;
26731 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Init Audio with Backend '%s', Device '%s', Format (Sample Rate=%u, Channels=%u, Format='%s')",
26734 appState->initSettings.audio.targetFormat.sampleRate,
26735 appState->initSettings.audio.targetFormat.channels,
26738 fpl__AudioState *audioState = fpl__GetAudioState(appState);
26741 fplAudioBackend *backend = (fplAudioBackend *)((uint8_t *)appState->audio.mem + offsetToAudioBackend);
26744 if (!appState->initSettings.audio.manualLoad) {
26745 fplAudioResultType initAudioResult = fpl__InitAudio(&appState->initSettings.audio, audioState);
26747 audioResultName = fplGetAudioResultName(initAudioResult);
26749 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed initialization Audio with Backend '%s', Device '%s', Format (SampleRate=%u, Channels=%u, Format='%s') -> %s",
26752 backend->desiredFormat.sampleRate,
26753 backend->desiredFormat.channels,
26756 fpl__ReleasePlatformStates(initState, appState);
26761 audioDeviceName = backend->internalDevice.name;
26762 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully initialized Audio with Backend '%s', Device '%s', Format (Sample Rate=%u, Channels=%u, Format='%s')", audioBackendName, audioDeviceName, backend->internalFormat.sampleRate, backend->internalFormat.channels, audioFormatName);
26765 if (appState->initSettings.audio.startAuto && (appState->initSettings.audio.clientReadCallback !=
fpl_null)) {
26766 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Play Audio (Auto)");
26768 audioResultName = fplGetAudioResultName(playResult);
26770 FPL__CRITICAL(FPL__MODULE_CORE,
"Failed playing Audio (Auto) -> %s", audioResultName);
26771 fpl__ReleasePlatformStates(initState, appState);
26774 FPL_LOG_DEBUG(FPL__MODULE_CORE,
"Successfully playing Audio (Auto)");
26777 FPL_LOG_INFO(FPL__MODULE_CORE,
"Audio backend initialization is skipped due to user settings");
26782 initState->isInitialized =
true;
26788#if defined(FPL_PLATFORM_WINDOWS)
26790#elif defined(FPL_PLATFORM_LINUX)
26792#elif defined(FPL_PLATFORM_UNIX)
26802#if defined(FPL_COMPILER_MSVC)
26804# pragma warning( pop )
26805#elif defined(FPL_COMPILER_GCC)
26807# pragma GCC diagnostic pop
26808#elif defined(FPL_COMPILER_CLANG)
26810# pragma clang diagnostic pop
26820#if defined(FPL_ENTRYPOINT) && !defined(FPL__ENTRYPOINT_IMPLEMENTED)
26821# define FPL__ENTRYPOINT_IMPLEMENTED
26828#if !defined(FPL__HAS_PLATFORM_INCLUDES)
26829# define FPL__HAS_PLATFORM_INCLUDES
26831# if defined(FPL_PLATFORM_WINDOWS)
26833# if !defined(NOMINMAX)
26837# if !defined(WIN32_LEAN_AND_MEAN)
26838# define WIN32_LEAN_AND_MEAN 1
26842# include <windows.h>
26843# if _WIN32_WINNT < 0x0600
26844# error "Windows Vista or higher required!"
26855# if defined(FPL_PLATFORM_WINDOWS)
26857#define FPL__FUNC_WIN32_CommandLineToArgvW(name) LPWSTR* WINAPI name(LPCWSTR lpCmdLine, int *pNumArgs)
26858typedef FPL__FUNC_WIN32_CommandLineToArgvW(fpl__win32_func_CommandLineToArgvW);
26860typedef struct fpl__Win32CommandLineUTF8Arguments {
26864} fpl__Win32CommandLineUTF8Arguments;
26866fpl_internal fpl__Win32CommandLineUTF8Arguments fpl__Win32ParseWideArguments(LPWSTR cmdLine,
const bool appendExecutable) {
26867 fpl__Win32CommandLineUTF8Arguments args =
fplZeroInit;
26870 HMODULE shellapiLibrary = LoadLibraryA(
"shell32.dll");
26871 if (shellapiLibrary !=
fpl_null) {
26872 fpl__win32_func_CommandLineToArgvW *commandLineToArgvW = (fpl__win32_func_CommandLineToArgvW *)(
void *)GetProcAddress(shellapiLibrary,
"CommandLineToArgvW");
26873 if (commandLineToArgvW !=
fpl_null) {
26875 int cmdLineLen = lstrlenW(cmdLine);
26876 int executableFilePathArgumentCount = 0;
26877 wchar_t **executableFilePathArgs = NULL;
26878 size_t executableFilePathLen = 0;
26879 if (appendExecutable || (cmdLineLen == 0)) {
26880 executableFilePathArgumentCount = 0;
26881 executableFilePathArgs = commandLineToArgvW(L
"", &executableFilePathArgumentCount);
26882 executableFilePathLen = 0;
26883 for (
int i = 0; i < executableFilePathArgumentCount; ++i) {
26886 executableFilePathLen++;
26888 size_t sourceLen = lstrlenW(executableFilePathArgs[i]);
26889 int destLen = WideCharToMultiByte(CP_UTF8, 0, executableFilePathArgs[i], (
int)sourceLen,
fpl_null, 0,
fpl_null,
fpl_null);
26890 executableFilePathLen += destLen;
26895 int actualArgumentCount = 0;
26897 size_t actualArgumentsLen = 0;
26898 if (cmdLine !=
fpl_null && cmdLineLen > 0) {
26899 actualArgs = commandLineToArgvW(cmdLine, &actualArgumentCount);
26900 for (
int i = 0; i < actualArgumentCount; ++i) {
26901 size_t sourceLen = lstrlenW(actualArgs[i]);
26903 actualArgumentsLen += destLen;
26908 uint32_t totalArgumentCount = 0;
26909 if (executableFilePathArgumentCount > 0) {
26910 totalArgumentCount++;
26912 totalArgumentCount += actualArgumentCount;
26918 size_t totalStringLen = executableFilePathLen + actualArgumentsLen + totalArgumentCount;
26919 size_t singleArgStringSize =
sizeof(char) * (totalStringLen);
26920 size_t arbitaryPadding = 64;
26921 size_t argArraySize =
sizeof(
char **) * totalArgumentCount;
26922 size_t totalArgSize = singleArgStringSize + arbitaryPadding + argArraySize;
26925 args.count = totalArgumentCount;
26927 args.args = (
char **)((uint8_t *)args.mem + singleArgStringSize + arbitaryPadding);
26930 char *destArg = (
char *)args.mem;
26931 int startArgIndex = 0;
26932 if (executableFilePathArgumentCount > 0)
26934 args.args[startArgIndex++] = destArg;
26935 for (
int i = 0; i < executableFilePathArgumentCount; ++i) {
26939 wchar_t *sourceArg = executableFilePathArgs[i];
26940 size_t sourceArgLen = lstrlenW(sourceArg);
26942 WideCharToMultiByte(CP_UTF8, 0, sourceArg, (
int)sourceArgLen, destArg, destArgLen,
fpl_null,
fpl_null);
26943 destArg += destArgLen;
26946 LocalFree(executableFilePathArgs);
26950 if (actualArgumentCount > 0) {
26952 for (
int i = 0; i < actualArgumentCount; ++i) {
26953 args.args[startArgIndex++] = destArg;
26954 wchar_t *sourceArg = actualArgs[i];
26955 size_t sourceArgLen = lstrlenW(sourceArg);
26957 WideCharToMultiByte(CP_UTF8, 0, sourceArg, (
int)sourceArgLen, destArg, destArgLen,
fpl_null,
fpl_null);
26958 destArg += destArgLen;
26961 LocalFree(actualArgs);
26964 FreeLibrary(shellapiLibrary);
26970fpl_internal fpl__Win32CommandLineUTF8Arguments fpl__Win32ParseAnsiArguments(LPSTR cmdLine,
const bool appendExecutable) {
26971 fpl__Win32CommandLineUTF8Arguments result;
26974 int wideDestLen = MultiByteToWideChar(CP_ACP, 0, cmdLine, (
int)ansiSourceLen,
fpl_null, 0);
26976 wchar_t *wideCmdLine = (
wchar_t *)
fplMemoryAllocate(
sizeof(
wchar_t) * (wideDestLen + 1));
26977 MultiByteToWideChar(CP_ACP, 0, cmdLine, (
int)ansiSourceLen, wideCmdLine, wideDestLen);
26978 wideCmdLine[wideDestLen] = 0;
26979 result = fpl__Win32ParseWideArguments(wideCmdLine, appendExecutable);
26982 wchar_t tmp[1] = { 0 };
26983 result = fpl__Win32ParseWideArguments(tmp, appendExecutable);
26988#if !defined(FPL_NO_CRT)
26993 HWND consoleHandle = GetConsoleWindow();
27000 HWND consoleHandle = GetConsoleWindow();
27004 AttachConsole(GetCurrentProcessId());
27007 HANDLE hConOut = CreateFileW(L
"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
27008 HANDLE hConIn = CreateFileW(L
"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
27009 SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
27010 SetStdHandle(STD_ERROR_HANDLE, hConOut);
27011 SetStdHandle(STD_INPUT_HANDLE, hConIn);
27013#if !defined(FPL_NO_CRT)
27015 freopen_s(&dummy,
"CONIN$",
"r", stdin);
27016 freopen_s(&dummy,
"CONOUT$",
"w", stderr);
27017 freopen_s(&dummy,
"CONOUT$",
"w", stdout);
27022# if defined(FPL_NO_CRT)
27026# if defined(FPL_APPTYPE_WINDOW)
27027# if defined(UNICODE)
27028void __stdcall wWinMainCRTStartup(
void) {
27029 fpl__Win32InitConsole();
27030 LPWSTR argsW = GetCommandLineW();
27031 int result = wWinMain(GetModuleHandleW(
fpl_null),
fpl_null, argsW, SW_SHOW);
27032 fpl__Win32FreeConsole();
27033 ExitProcess(result);
27036void __stdcall WinMainCRTStartup(
void) {
27037 fpl__Win32InitConsole();
27038 LPSTR argsA = GetCommandLineA();
27039 int result = WinMain(GetModuleHandleA(
fpl_null),
fpl_null, argsA, SW_SHOW);
27040 fpl__Win32FreeConsole();
27041 ExitProcess(result);
27044# elif defined(FPL_APPTYPE_CONSOLE)
27045void __stdcall mainCRTStartup(
void) {
27046 fpl__Win32InitConsole();
27047 fpl__Win32CommandLineUTF8Arguments args;
27048# if defined(UNICODE)
27049 LPWSTR argsW = GetCommandLineW();
27050 args = fpl__Win32ParseWideArguments(argsW,
false);
27052 LPSTR argsA = GetCommandLineA();
27053 args = fpl__Win32ParseAnsiArguments(argsA,
false);
27055 int result = main(args.count, args.args);
27057 fpl__Win32FreeConsole();
27058 ExitProcess(result);
27061# error "Application type not set!"
27068# if defined(UNICODE)
27069int WINAPI wWinMain(HINSTANCE appInstance, HINSTANCE prevInstance, LPWSTR cmdLine,
int cmdShow) {
27070 fpl__Win32InitConsole();
27071 fpl__Win32CommandLineUTF8Arguments args = fpl__Win32ParseWideArguments(cmdLine,
true);
27072 int result = main(args.count, args.args);
27074 fpl__Win32FreeConsole();
27078int WINAPI WinMain(HINSTANCE appInstance, HINSTANCE prevInstance, LPSTR cmdLine,
int cmdShow) {
27079 fpl__Win32InitConsole();
27080 fpl__Win32CommandLineUTF8Arguments args = fpl__Win32ParseAnsiArguments(cmdLine,
true);
27081 int result = main(args.count, args.args);
27083 fpl__Win32FreeConsole();
27095#if !defined(FPL_NO_UNDEF)
27097# if defined(FPL_SUBPLATFORM_X11)
27111# 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 void fplAtomicWriteFence(void)
Inserts a memory write fence/barrier.
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 void fplAtomicReadWriteFence(void)
Inserts a memory read and write fence/barrier.
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 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_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 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 fplAtomicReadFence(void)
Inserts a memory read fence/barrier.
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 fplAudioChannelLayout fplGetDefaultAudioChannelLayoutFromChannels(const uint16_t channelCount)
Returns the default audio channel layout from the specified channel count.
fpl_common_api fplAudioResultType fplPlayAudio(void)
Start playing asynchronous audio.
fpl_common_api const char * fplGetAudioHardwareDeviceName(void)
Retrieves the audio device name for the current audio device.
fpl_common_api fplAudioResultType fplStopAudio(void)
Stop playing asynchronous audio.
fpl_common_api fplAudioResultType fplAudioInit(fplAudioSettings *audioSettings)
Re/Initializes the audio system with the specified audio settings.
fpl_common_api uint32_t fplGetAudioDevices(const uint32_t maxDeviceCount, const uint32_t deviceInfoSize, fplAudioDeviceInfo *outDevices)
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 fplAudioBackendType fplGetAudioBackendType(void)
Gets the current audio backend type.
fpl_common_api fplAudioFormatU64 fplEncodeAudioFormatU64(const uint32_t sampleRate, const uint16_t channels, const fplAudioFormatType type)
Creates an encoded audio format from the specified sample rate, channels, and type.
fpl_common_api uint32_t fplGetAudioFrameSizeInBytes(const fplAudioFormatType format, const uint16_t channelCount)
Computes the number of bytes required for one interleaved audio frame - containing all the channels.
fpl_common_api const char * fplGetAudioBackendName(const fplAudioBackendType backendType)
Gets the string that represents the given audio backend type.
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 fplAudioLatencyType fplGetAudioLatencyType(const fplAudioMode mode)
Gets the audio latency type from the specified audio mode.
fpl_common_api bool fplAudioRelease(void)
Unloads/Releases the audio system.
fpl_common_api uint32_t fplGetAudioBufferSizeInFrames(const uint32_t sampleRate, const uint32_t bufferSizeInMilliSeconds)
Computes the total number of frames for a given sample rate and buffer size.
fpl_common_api uint32_t fplGetAudioBufferSizeInMilliseconds(const uint32_t sampleRate, const uint32_t frameCount)
Computes the duration in milliseconds for the given sample rate and frame count.
fpl_common_api bool fplGetAudioHardwareDevice(fplAudioDeviceInfo *outDevice)
Retrieves the audio device info for the current audio device.
fpl_common_api bool fplGetAudioDeviceInfo(const fplAudioDeviceID *deviceId, fplAudioDeviceInfoExtended *outDeviceInfo)
Gets the full audio device info extended for the specified audio device ID.
fpl_common_api uint16_t fplGetAudioChannelsFromLayout(const fplAudioChannelLayout channelLayout)
Returns the number of channels from the specified audio channel layout.
fpl_common_api uint32_t fplGetTargetAudioFrameCount(const uint32_t inputFrameCount, const uint32_t inputSampleRate, const uint32_t outputSampleRate)
Computes the target number of audio frames from the specified input frame count and sample rate and t...
fpl_common_api fplAudioShareMode fplGetAudioShareMode(const fplAudioMode mode)
Gets the audio share mode from the specified audio mode.
fpl_common_api bool fplDecodeAudioFormatU64(const fplAudioFormatU64 format64, uint32_t *outSampleRate, uint16_t *outChannels, fplAudioFormatType *outType)
Decodes the specified encoded audio format to the specified sample rate, channels,...
fpl_common_api bool fplGetAudioHardwareFormat(fplAudioFormat *outFormat)
Retrieves the native audio format for the current audio device.
fpl_common_api bool fplGetAudioChannelMap(fplAudioChannelMap *outMapping)
Gets the audio channels mapping table.
fpl_common_api fplAudioMode fplCreateAudioMode(const fplAudioLatencyType latencyType, const fplAudioShareMode shareMode)
Creates an audio mode from the specified audio latency type and share mode.
fplAudioResultType
An enumeration of audio results.
fpl_common_api uint32_t fplGetAudioBufferSizeInBytes(const fplAudioFormatType format, const uint16_t channelCount, const uint32_t frameCount)
Computes the total number of bytes for the buffer and the given parameters.
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_NotImplemented
Feature or device is not implemented.
@ fplAudioResultType_NoBackendsFound
No audio backends found.
@ fplAudioResultType_DeviceByIdNotFound
Audio device by id was not found.
@ 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 audio result type.
@ fplAudioResultType_First
First audio result type.
@ fplAudioResultType_OutOfMemory
No memory available.
@ 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_InvalidArguments
Invalid arguments are passed to an audio function.
@ fplAudioResultType_UnsuportedDeviceFormat
The audio device format is unsupported.
@ fplAudioResultType_UnsetAudioBufferSize
The audio buffer size is not set.
@ fplAudioResultType_DeviceFailure
Error occurred while initializing an audio device.
@ fplAudioResultType_UnsetAudioFormat
The audio format type is not set.
@ fplAudioResultType_SystemNotInitialized
The audio system is not initialized.
@ 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(void)
Waits for a character to be typed in the console input and returns 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 a 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 void fplErrorsClear(void)
Clears all the current errors in the platform.
fpl_common_api const char * fplGetErrorByIndex(const size_t index)
Gets the last error string from the given index.
fpl_common_api const char * fplGetLastError(void)
Gets the last internal error string.
fpl_common_api size_t fplGetErrorCount(void)
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)
Moves 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)
Creates 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.
fplFileAttributeFlags
An enumeration 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_platform_api size_t fplCPUGetCoreCount(void)
Retrieves the total number of processor cores.
fpl_common_api uint64_t fplCPUXCR0(void)
Gets the x86 extended control register for index zero.
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_common_api uint64_t fplCPURDTSC(void)
Reads the current time stamp counter (RDTSC).
fplCPUArchType
An enumeration of architecture types.
fpl_platform_api fplCPUArchType fplCPUGetArchitecture(void)
Gets the processor architecture type.
fpl_common_api bool fplCPUGetCapabilities(fplCPUCapabilities *outCaps)
Gets the capabilities of the processor.
fplCPUCapabilitiesType
An enumeration of CPU types.
fpl_common_api const char * fplGetCPUCapabilitiesTypeName(const fplCPUCapabilitiesType type)
Gets the name of the specified fplCPUCapabilitiesType.
fpl_common_api bool fplCPUID(const uint32_t functionId, fplCPUIDLeaf *outLeaf)
Queries the x86 CPUID leaf register (EAX, EBX, ECX, EDX) for the given function id.
@ 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.
@ fplCPUCapabilitiesType_Last
Last fplCPUCapabilitiesType.
@ fplCPUCapabilitiesType_X86
x86 type.
@ fplCPUCapabilitiesType_First
First fplCPUCapabilitiesType.
@ fplCPUCapabilitiesType_ARM
ARM type.
@ fplCPUCapabilitiesType_Unknown
Unknown type.
fplLocaleFormat
An 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 void fplSetLogSettings(const fplLogSettings *params)
Overwrites the current log settings.
fpl_common_api const fplLogSettings * fplGetLogSettings(void)
Gets the current log settings.
void fpl_log_func_callback(const char *funcName, const int lineNumber, const fplLogLevel level, const char *message)
A function definition for a callback for printing a log message.
fplLogWriterFlags
An enumeration of log writer flags.
fpl_common_api fplLogLevel fplGetMaxLogLevel(void)
Gets the current maximum allowed log level.
@ 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 fplStackAllocate(size)
Manually allocate the number of specified bytes of memory on the stack.
#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()
Gets a value indicating whether the current platform is big-endian or not.
#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.
#define fplStructField
Defines a single field in a struct.
#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, that is aligned to the operating system...
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 platform's 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.
uint64_t fplAudioFormatU64
Encoded audio format in 64-bit ([63] Unused 8-bit, Type 8-bit, Channels 16-bit, Sample rate 32-bit [0...
fplAudioMode
An enumeration of audio modes that combines conservative/latency and exclusive/shared.
fplImageType
An enumeration of image types.
uint32_t fpl_audio_client_read_callback(const fplAudioFormat *deviceFormat, const uint32_t frameCount, void *outputSamples, void *userData)
A function definition for a callback that is called to read audio samples from the client.
fplInitFlags
An enumeration of initialization flags.
fpl_common_api fplSettings fplMakeDefaultSettings(void)
Creates a full settings structure containing default values.
fplPlatformResultType
An enumeration of platform result types.
fplVulkanValidationLayerMode
An enumeration of Vulkan validation layer modes.
fplAudioFormatType
An enumeration of audio format types.
void fpl_memory_release_callback(void *userData, void *ptr)
A function definition for a custom memory release callback.
fplMemoryAllocationMode
An enumeration of dynamic memory allocation modes.
fpl_common_api const char * fplGetAudioChannelTypeName(const fplAudioChannelType type)
Gets the name of the specified audio channel type.
fplOpenGLCompabilityFlags
An enumeration of OpenGL compatibility flags.
bool fpl_window_event_callback(const fplPlatformType platformType, void *windowState, void *rawEventData, void *userData)
A function definition for a callback executed for each raw window event.
fpl_window_event_callback fpl_window_exposed_callback
A function definition for a callback executed when the window needs to be exposed/repainted.
fplAudioShareMode
An enumeration of audio share modes.
void * fpl_memory_allocate_callback(void *userData, const size_t size, const size_t alignment)
A function definition for a custom memory allocation callback.
fpl_common_api fplColor32 fplCreateColorRGBA(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a)
Creates a 32-bit color structure from the specified R, G, B, A components.
fpl_common_api const fplSettings * fplGetCurrentSettings(void)
Gets the current settings.
#define FPL_MAX_AUDIO_CHANNEL_COUNT
Maximum number of audio channels.
void fplVulkanValidationLayerCallback(void *userData, const char *message, const uint32_t messageSeverity, const uint32_t messageType, const void *debugUtilsMessengerCallbackData)
A function definition for the debug callback that is called, when the validation layer writes somethi...
fpl_common_api void fplSetDefaultConsoleSettings(fplConsoleSettings *console)
Resets the given console settings container to default settings.
fplAudioDefaultFields
An enumeration of audio default fields.
fplAudioChannelType
An enumeration of audio channel types.
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.
fplAudioLatencyType
An enumeration of audio latency types.
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.
fplAudioChannelLayout
An enumeration of audio channel layouts.
fplVulkanValidationSeverity
An enumeration of Vulkan validation layer logging severity.
@ fplAudioMode_Exclusive_LowLatency
Exclusive Low Latency.
@ fplAudioMode_Exclusive_Conservative
Exclusive Conservative.
@ fplAudioMode_Shared_LowLatency
Shared Low Latency.
@ fplAudioMode_Shared_Conservative
Shared Conservative.
@ 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_OutOfMemory
Failed allocating required memory.
@ 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.
@ fplVulkanValidationLayerMode_Required
Enable validations and stop when it's not supported.
@ fplVulkanValidationLayerMode_Disabled
Do not use the validation.
@ fplVulkanValidationLayerMode_Optional
Enable validations when it's 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.
@ fplMemoryAllocationMode_Custom
Use custom memory allocation.
@ fplMemoryAllocationMode_Automatic
Use OS memory allocation.
@ fplOpenGLCompabilityFlags_Legacy
Use legacy context.
@ fplOpenGLCompabilityFlags_Compability
Use compatibility profile.
@ fplOpenGLCompabilityFlags_Core
Use core profile.
@ fplOpenGLCompabilityFlags_Forward
Remove features marked as deprecated.
@ fplAudioShareMode_Exclusive
Exclusive mode.
@ fplAudioShareMode_Shared
Shared mode.
@ fplAudioDefaultFields_Channels
Number of channels is default.
@ fplAudioDefaultFields_Periods
Number of periods is default.
@ fplAudioDefaultFields_ChannelLayout
Audio layout is default.
@ fplAudioDefaultFields_SampleRate
Samples per second is default.
@ fplAudioDefaultFields_Type
Audio format is default.
@ fplAudioDefaultFields_None
No default fields.
@ fplAudioDefaultFields_BufferSize
Buffer size is default.
@ fplAudioChannelType_AUX13
AUX 13.
@ fplAudioChannelType_AUX8
AUX 8.
@ fplAudioChannelType_FrontLeftOfCenter
Front left of center.
@ fplAudioChannelType_AUX6
AUX 6.
@ fplAudioChannelType_FrontLeft
Front left.
@ fplAudioChannelType_FrontRightOfCenter
Front right of center.
@ fplAudioChannelType_SideLeft
Side left.
@ fplAudioChannelType_TopBackCenter
Top back center.
@ fplAudioChannelType_TopBackRight
Top back right.
@ fplAudioChannelType_AUX12
AUX 12.
@ fplAudioChannelType_AUX9
AUX 9.
@ fplAudioChannelType_BackLeft
Back left.
@ fplAudioChannelType_TopCenter
Top center.
@ fplAudioChannelType_AUX5
AUX 5.
@ fplAudioChannelType_SideRight
Side right.
@ fplAudioChannelType_AUX1
AUX 1.
@ fplAudioChannelType_AUX10
AUX 10.
@ fplAudioChannelType_FrontRight
Front right.
@ fplAudioChannelType_AUX11
AUX 11.
@ fplAudioChannelType_First
First audio channel type.
@ fplAudioChannelType_LowFrequency
Low Frequency.
@ fplAudioChannelType_TopFrontLeft
Top front left.
@ fplAudioChannelType_AUX14
AUX 14.
@ fplAudioChannelType_TopFrontCenter
Top front center.
@ fplAudioChannelType_Last
Last audio channel type.
@ fplAudioChannelType_TopFrontRight
Top front right.
@ fplAudioChannelType_BackRight
Back right.
@ fplAudioChannelType_AUX3
AUX 3.
@ fplAudioChannelType_FrontCenter
Front center.
@ fplAudioChannelType_AUX15
AUX 15.
@ fplAudioChannelType_None
No or unknown audio channel.
@ fplAudioChannelType_AUX0
AUX 0.
@ fplAudioChannelType_AUX7
AUX 7.
@ fplAudioChannelType_BackCenter
Back center.
@ fplAudioChannelType_TopBackLeft
Top back left.
@ fplAudioChannelType_AUX2
AUX 2.
@ fplAudioChannelType_AUX4
AUX 4.
@ fplAudioBackendType_First
First fplAudioBackendType.
@ fplAudioBackendType_Last
Last fplAudioBackendType.
@ fplAudioBackendType_Alsa
ALSA audio backend.
@ fplAudioBackendType_Custom
Custom audio backend.
@ fplAudioBackendType_None
No audio backend.
@ fplAudioBackendType_Auto
Auto detect audio backend.
@ fplAudioBackendType_DirectSound
DirectSound audio backend.
@ fplVideoBackendType_Vulkan
Vulkan video backend.
@ fplVideoBackendType_None
No video backend.
@ fplVideoBackendType_Software
Software video backend.
@ fplVideoBackendType_First
First video backend.
@ fplVideoBackendType_OpenGL
OpenGL video backend.
@ fplVideoBackendType_Last
Last video backend.
@ fplPlatformType_Linux
Linux platform.
@ fplPlatformType_Unknown
Unknown platform.
@ fplPlatformType_Last
Last fplPlatformType.
@ fplPlatformType_Windows
Windows platform.
@ fplPlatformType_First
First fplPlatformType.
@ fplPlatformType_Unix
Unix platform.
@ fplAudioLatencyType_Low
Low latency.
@ fplAudioLatencyType_Conservative
Conservative latency.
@ fplAudioChannelLayout_4_1
4.1 Audio Channel Layout (4.1, 5 Channels: Front/LFE/Back).
@ fplAudioChannelLayout_4_0_Surround
4.0 Surround Audio Channel Layout (4.0 Surround, 4 Channels: Front/F-Center/B-Center).
@ fplAudioChannelLayout_Automatic
Automatic Audio Channel Layout (based on number of channels and/or sound device).
@ fplAudioChannelLayout_Last
Last Audio Channel Layout.
@ fplAudioChannelLayout_2_1
2.1 Audio Channel Layout (2.1, 3 Channels: Front, LFE).
@ fplAudioChannelLayout_4_0_Quad
4.0 Quad Audio Channel Layout (4.0 Quad, 4 Channels: Front/Back).
@ fplAudioChannelLayout_First
First Audio Channel Layout.
@ fplAudioChannelLayout_Stereo
Stereo Audio Channel Layout (2.0, 2 Channels: Front).
@ fplAudioChannelLayout_5_0_Surround
5.0 Audio Channel Layout (5.0, 5 Channels: Front/Center/Back).
@ fplAudioChannelLayout_6_1
6.1 Audio Channel Layout (6.1, 7 Channels: Front/F-Center/LFE/B-Center/Side).
@ fplAudioChannelLayout_7_1
7.1 Audio Channel Layout (7.1, 8 Channels: Front/Center/LFE/Back/Side).
@ fplAudioChannelLayout_5_1
5.1 Audio Channel Layout (5.1, 6 Channels: Front/Center/LFE/Side).
@ fplAudioChannelLayout_Unsupported
Unsupported Audio Channel Layout.
@ fplAudioChannelLayout_3_0_Surround
3.0 Surround Audio Channel Layout (3.0, 3 Channels: Front/F-Center).
@ fplAudioChannelLayout_Mono
Mono Audio Channel Layout (1.0, Single Channel: Front).
@ fplVulkanValidationSeverity_Verbose
Log warning, error, info, and verbose.
@ fplVulkanValidationSeverity_Off
Log nothing.
@ fplVulkanValidationSeverity_All
Log everything.
@ fplVulkanValidationSeverity_Info
Log warning, error, and info.
@ 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 into 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 into 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 parameters 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)
Lets 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 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 for the given thread handle.
fpl_platform_api bool fplSetThreadPriority(fplThreadHandle *thread, const fplThreadPriority newPriority)
Changes the thread priority to the given one, for the given thread handle.
struct fplThreadHandle fplThreadHandle
Forward declared thread handle.
fpl_common_api fplThreadState fplGetThreadState(fplThreadHandle *thread)
Gets the current thread state for the given thread.
fplThreadStates
An enumeration of thread states.
fplThreadPriority
Defines all possible thread priorities.
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 woken 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)
Waits 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.
void fpl_run_thread_callback(const fplThreadHandle *thread, void *data)
A function definition for a callback to execute user code inside another thread.
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)
Waits until the given thread is done running or the given timeout has been reached.
fpl_common_api size_t fplGetUsedThreadCount(void)
Gets the number of used/active threads.
fpl_platform_api bool fplSemaphoreTryWait(fplSemaphoreHandle *semaphore)
Tries to wait for the semaphore until it gets signaled or returns immediately.
fpl_platform_api bool fplSignalWaitForOne(fplSignalHandle *signal, const fplTimeoutValue timeout)
Waits until the given signal is woken 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)
Waits until one of the given threads is done running or the given timeout has been reached.
fpl_common_api size_t fplGetAvailableThreadCount(void)
Gets the number of available threads.
fpl_platform_api void fplSignalDestroy(fplSignalHandle *signal)
Releases the given signal and clears the structure to zero.
fpl_platform_api bool fplThreadYield(void)
Lets the current thread yield execution to another thread that is ready to run on this core.
fpl_platform_api bool fplSignalReset(fplSignalHandle *signal)
Resets the signal.
fpl_common_api const fplThreadHandle * fplGetMainThread(void)
Gets the thread handle for the main thread.
fpl_platform_api uint32_t fplGetCurrentThreadId(void)
Gets the thread id for the current thread.
fpl_platform_api bool fplThreadTerminate(fplThreadHandle *thread)
Forces the given thread to stop and release all underlying resources.
fpl_platform_api bool fplMutexTryLock(fplMutexHandle *mutex)
Tries to lock the given mutex without blocking other threads.
fpl_platform_api bool fplConditionInit(fplConditionVariable *condition)
Initializes 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 fplTimestamp fplTimestampQuery(void)
Gets the current fplTimestamp with most precision, used for time delta measurements only.
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.
uint32_t fplTimeoutValue
A type definition for a timeout value in milliseconds.
fpl_platform_api fplMilliseconds fplMillisecondsQuery(void)
Gets the current system clock in milliseconds, since some fixed starting point (OS start,...
#define FPL_TIMEOUT_INFINITE
Infinite timeout constant.
fpl_common_api fplVideoBackBuffer * fplGetVideoBackBuffer(void)
Retrieves the pointer to the current video backbuffer.
fpl_common_api void fplVideoFlip(void)
Forces the window to be redrawn or to swap the back/front buffer.
fpl_common_api const fplVideoSurface * fplGetVideoSurface(void)
Gets the current video surface 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_common_api fplVideoBackendType fplGetVideoBackendType(void)
Gets the current video backend.
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 const char * fplGetVideoBackendName(fplVideoBackendType backendType)
Gets a string that represents the given video backend.
fpl_common_api fplVideoRect fplCreateVideoRectFromLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom)
Makes a video rectangle from a LTRB rectangle.
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 fplWindowState fplGetWindowState(void)
Gets the current window state.
fpl_platform_api bool fplIsWindowDecorated(void)
Gets the window decorated state as boolean.
fpl_platform_api bool fplIsWindowFloating(void)
Gets the window floating state as boolean.
fpl_platform_api bool fplWindowUpdate(void)
Clears the internal event queue and updates input devices if needed.
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.
fplWindowState
An enumeration containing the states of a window.
fpl_platform_api bool fplIsWindowResizable(void)
Gets the window resizable state as boolean.
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 fplWindowShutdown(void)
Closes the window and stops the event loop.
fpl_platform_api void fplSetWindowTitle(const char *title)
Changes the window title to the given string.
fpl_platform_api bool fplIsWindowRunning(void)
Gets the window running state as a boolean.
fpl_platform_api bool fplGetWindowSize(fplWindowSize *outSize)
Retrieves the inner window size.
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 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_common_api void fplSetWindowInputEvents(const bool enabled)
Enables or disables the input events for the window entirely.
fpl_platform_api bool fplDisableWindowFullscreen(void)
Switches the window back to window mode.
fpl_platform_api bool fplEnableWindowFullscreen(void)
Enables fullscreen mode on the nearest display.
fplWindowVisibilityState
An enumeration containing the visibility state of a window.
fpl_platform_api bool fplIsWindowFullscreen(void)
Gets the window fullscreen state as boolean.
@ 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 information 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 bool fplGetWindowDisplay(fplDisplayInfo *outInfo)
Gets information about the display for the FPL window.
fpl_platform_api size_t fplGetDisplayCount(void)
Gets the number of active displays.
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 ...
fplButtonState
An enumeration of button states.
fplMouseEventType
An enumeration of mouse event types (Move, ButtonDown, etc.).
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, etc.).
fplGamepadEventType
An enumeration of gamepad event types (Connected, Disconnected, StateChanged, etc....
fplKeyboardEventType
An enumeration of keyboard event types.
fpl_platform_api void fplPollEvents(void)
Polls all the events from the OS and clears the internal event queue.
fplEventType
An enumeration of event types (Window, Keyboard, Mouse, etc.).
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 held 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_NumPad4
NumPad 4 key.
@ fplKey_Oem3
'‘~’ for US.
@ fplKey_RightAlt
Right Alt key.
@ fplKey_NumPad0
NumPad 0 key.
@ fplKey_Oem4
'[{' for US.
@ fplKey_Left
Left arrow key.
@ fplKey_NumPad6
NumPad 6 key.
@ fplKey_F1
Function key F1.
@ fplKey_LeftSuper
Left Super key.
@ fplKey_Decimal
Decimal key.
@ fplKey_LeftAlt
Left Alt key.
@ fplKey_F18
Function key F18.
@ fplKey_NumLock
Num Lock key.
@ fplKey_MediaPlayPause
Media Play/Pause key.
@ fplKey_F23
Function key F23.
@ fplKey_Multiply
Multiply key.
@ fplKey_RightSuper
Right Super key.
@ fplKey_F12
Function key F12.
@ fplKey_MediaStop
Media Stop key.
@ fplKey_F14
Function key F14.
@ fplKey_Oem7
''"' for US.
@ fplKey_MediaPrevTrack
Media Previous Track key.
@ fplKey_Substract
Subtract key.
@ fplKey_Select
Select key.
@ fplKey_F19
Function key F19.
@ fplKey_F6
Function key F6.
@ fplKey_NumPad7
NumPad 7 key.
@ fplKey_F7
Function key F7.
@ fplKey_NumPad2
NumPad 2 key.
@ fplKey_Divide
Divide key.
@ fplKey_F8
Function key F8.
@ fplKey_OemPlus
'+' for any country.
@ fplKey_PageDown
Page Down key.
@ fplKey_VolumeUp
Volume Up key.
@ fplKey_F10
Function key F10.
@ fplKey_Insert
Insert key.
@ fplKey_Return
Return key.
@ fplKey_Oem8
OEM specific key.
@ fplKey_F9
Function key F9.
@ fplKey_Backspace
Backspace key.
@ fplKey_OemMinus
'-' for any country.
@ fplKey_Right
Right arrow key.
@ fplKey_MediaNextTrack
Media Next Track key.
@ fplKey_LeftControl
Left Control key.
@ fplKey_Oem1
'/?' for US.
@ fplKey_OemPeriod
'.' for any country.
@ fplKey_NumPad5
NumPad 5 key.
@ fplKey_F21
Function key F21.
@ fplKey_F20
Function key F20.
@ fplKey_F16
Function key F16.
@ fplKey_NumPad8
NumPad 8 key.
@ fplKey_NumPad3
NumPad 3 key.
@ fplKey_F11
Function key F11.
@ fplKey_RightControl
Right Control key.
@ fplKey_F2
Function key F2.
@ fplKey_F24
Function key F24.
@ fplKey_F13
Function key F13.
@ fplKey_VolumeDown
Volume Down key.
@ fplKey_Escape
Escape key.
@ fplKey_F15
Function key F15.
@ fplKey_F22
Function key F22.
@ fplKey_F5
Function key F5.
@ fplKey_Snapshot
Snapshot key.
@ fplKey_F17
Function key F17.
@ fplKey_Delete
Delete key.
@ fplKey_Control
Control key.
@ fplKey_NumPad1
NumPad 1 key.
@ fplKey_LeftShift
Left Shift key.
@ fplKey_Scroll
Scroll Lock key.
@ fplKey_Execute
Execute key.
@ fplKey_NumPad9
NumPad 9 key.
@ fplKey_Separator
Separator key.
@ fplKey_Down
Down arrow key.
@ fplKey_Oem6
']}' for US.
@ fplKey_CapsLock
Caps Lock key.
@ fplKey_F4
Function key F4.
@ fplKey_F3
Function key F3.
@ fplKey_OemComma
',' for any country.
@ fplKey_RightShift
Right Shift key.
@ fplKey_PageUp
Page Up key.
@ fplKey_Oem2
'/?' for US.
@ fplKey_VolumeMute
Volume Mute key.
@ 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.
Container storing the capabilities of an ARM CPU.
bool hasSHA2
Has SHA2 support.
bool hasAES
Has AES support.
bool hasPMULL
Has PMULL support.
bool hasNEON
Has NEON support.
bool hasSHA1
Has SHA1 support.
bool hasCRC32
Has CRC32 support.
Stores the mapping of all audio channels to an audio speaker.
fplAudioChannelType speakers[FPL_MAX_AUDIO_CHANNEL_COUNT]
The mapping from channel 0-31 to an audio speaker.
Stores the fplAudioDeviceInfo and the supported formats.
fplAudioDeviceInfo info
The base fplAudioDeviceInfo.
fplAudioFormatU64 supportedFormats[63]
Supported audio formats.
size_t supportedFormatCount
Number of supported formats.
Stores the name and the ID of the audio device.
bool isDefault
A value indicating whether this is a default device or not.
fplAudioDeviceID id
Device ID.
char name[FPL_MAX_NAME_LENGTH - 1]
Device name.
Stores audio settings, such as format, device info, callbacks, backend, etc.
fplAudioDeviceInfo targetDevice
The target device.
void * clientUserData
User data pointer for client read callback.
fpl_b32 startAuto
Start playing of audio samples after platform initialization automatically.
fplAudioFormat targetFormat
The target format.
fpl_audio_client_read_callback * clientReadCallback
The callback for retrieving audio data from the client.
fpl_b32 manualLoad
Manual loading the audio system by fplAudioInit() and unload using fplAudioRelease().
fpl_b32 stopAuto
Stop playing of audio samples before platform release automatically.
fplAudioBackendType backend
The targeted backend.
fplSpecificAudioSettings specific
Specific settings.
Container storing the capabilities of a CPU.
fplCPUCapabilitiesType type
The capabilities type.
fplX86CPUCapabilities x86
x86 CPU capabilities.
uint8_t unused[28]
Unused.
fplARMCPUCapabilities arm
ARM CPU capabilities.
Stores the condition variable structure.
fpl_b32 isValid
Is it valid.
fplInternalConditionVariable internalHandle
The internal condition handle.
Stores the title and options for the console.
char title[FPL_MAX_NAME_LENGTH]
Console title.
A struct containing information 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.
Stores 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 physically 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.
Stores graphics API settings.
fplOpenGLSettings opengl
OpenGL settings.
fplVulkanSettings vulkan
Vulkan settings.
int dummy
Field for preventing union to be empty.
Stores data for working with an image source.
uint32_t width
Width in pixels.
fplImageType type
Image type.
const uint8_t * data
Reference 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.
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).
Stores console logging properties.
int dummy
Field for preventing struct to be empty.
Stores custom logging properties.
fpl_log_func_callback * callback
User callback.
Stores log writer settings.
fplLogWriterFlags flags
Flags.
fplLogWriterConsole console
Console.
fplLogWriterCustom custom
Custom.
Stores settings for 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.
Stores properties that represents any block of memory.
size_t size
The size of the allocated memory.
void * base
The base reference.
Stores information about the 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.
Stores 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.
Stores the mutex handle structure.
fplInternalMutexHandle internalHandle
The internal mutex handle.
fpl_b32 isValid
Is it valid.
Stores 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).
Stores 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
Compatibility flags.
uint8_t multiSamplingCount
Multisampling count.
uint32_t majorVersion
Desired major version.
Stores the semaphore handle structure.
fplInternalSemaphoreHandle internalHandle
The internal semaphore handle.
fpl_b32 isValid
Is it valid.
Stores 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.
Stores the signal handle structure.
fplInternalSignalHandle internalHandle
The internal signal handle.
fpl_b32 isValid
Is it valid.
Stores 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.
Stores 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.
Stores version information.
fplVersionNumberPart fix
Fix version.
union fplVersionInfo::@365135000334316031133255004035011055373020307002 version
Full version.
fplVersionNumberPart build
Build version.
fplVersionNumberPart values[4]
Version number parts.
fplVersionNumberPart major
Major version.
struct fplVersionInfo::@365135000334316031133255004035011055373020307002::@063163116360264167063231010243176073330000023206 parts
The version parts.
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 rectangle's 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.
Stores 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).
Stores Vulkan video settings.
fplVersionInfo engineVersion
The engine version (only required if fplVulkanSettings::instanceHandle is null).
fplVersionInfo apiVersion
The preferred Vulkan API version (only required if fplVulkanSettings::instanceHandle is null).
fplVulkanValidationLayerMode validationLayerMode
The validation layer mode fplVulkanValidationLayerMode.
const char * appName
The application name (only required if fplVulkanSettings::instanceHandle is null).
void * userData
User opaque user data that is passed to any validation layer 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 null).
const char * engineName
The engine name (only required if fplVulkanSettings::instanceHandle is null).
const char * libraryFile
Custom Vulkan driver library file name/path (null = Default Vulkan library).
fplVulkanValidationSeverity validationSeverity
The validation severity fplVulkanValidationSeverity.
const void * allocator
The Vulkan allocator (VkAllocationCallbacks).
fplVulkanValidationLayerCallback * validationLayerCallback
The validation layer callback fplVulkanValidationLayerCallback.
Stores the window callbacks.
void * eventUserData
User data pointer for the event callback.
fpl_window_event_callback * eventCallback
Event 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, do not touch.
size_t fileCount
Number of dropped in files.
const char ** files
File paths (Do not release this memory, it's 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.
Stores the position of a window.
int32_t left
Left position in screen coordinates.
int32_t top
Top position in screen coordinates.
Stores 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 from 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.
Stores the size of a window.
uint32_t width
Width in screen coordinates.
uint32_t height
Height in screen coordinates.
Container storing the capabilities of an x86 CPU.
bool hasSSE4_2
Has SSE4.2 support.
bool hasSSE
Has SSE support.
bool hasSSSE3
Has SSSE3 support.
bool hasAVX
Has AVX support.
bool hasAVX2
Has AVX2 support.
bool hasEM64T
Has EM64T support.
bool hasSSE4_1
Has SSE4.1 support.
bool hasAVX512
Has AVX512 support.
bool hasSSE3
Has SSE3 support.
bool hasBMI1
Has BMI1 support.
bool hasADX
Has ADX support.
bool hasAES_NI
Has AES-NI support.
bool hasSSE2
Has SSE2 support.
bool hasBMI2
Has BMI2 support.
bool hasSHA
Has SHA support.
bool hasF16C
Has F16C support.
bool hasFMA3
Has FMA3 support.
Stores the ID of the underlying backend.
uint8_t dummy[256]
Field for preventing union to be empty.
Container representing the 4-registers for a CPU-Leaf (EAX, EBX, ECX, EDX).
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.
struct fplColor32::@326013044226003007030237204232371201217365374302 components
The BGRA components.
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.
Stores the internal condition variable for any platform.
int dummy
Field for preventing union to be empty.
Stores the library handle for any platform.
A union containing the internal filehandle for any platform.
A union containing the internal filehandle for any platform.
Stores the internal mutex handle for any platform.
Stores the internal semaphore handle for any platform.
Stores the internal signal handle for any platform.
Stores the thread handle for any platform.
Stores backend-specific audio settings.
int dummy
Field for preventing union to be empty.
Stores 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.